mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-12 16:52:50 +00:00
Move graph out of connection, move more logic to Util, update tests.
This commit is contained in:
39
index.html
39
index.html
@@ -64,6 +64,7 @@
|
||||
</div>
|
||||
<script>
|
||||
var connection = new iD.Connection("http://www.overpass-api.de/api/xapi?");
|
||||
connection.graph(new iD.Graph());
|
||||
|
||||
var m = d3.select('#map');
|
||||
// Initialise map
|
||||
@@ -83,26 +84,13 @@
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Mode button handlers
|
||||
d3.select('#add-place').on('click', function() {
|
||||
map.controller.setState(new iD.controller.shape.NoSelection('node'));
|
||||
});
|
||||
|
||||
d3.select('#add-road').on('click', function() {
|
||||
// map.controller.setState(new iD.controller.shape.DrawWay('way'));
|
||||
console.log(iD.DrawWay.enter());
|
||||
console.log(iD.DrawWay.enter(map));
|
||||
});
|
||||
|
||||
d3.select('#add-area').on('click', function() {
|
||||
map.controller.setState(new iD.controller.shape.NoSelection());
|
||||
});
|
||||
|
||||
function grid(resp) {
|
||||
map.setCentre({
|
||||
lon: resp.results[0][0].lon,
|
||||
lat: resp.results[0][0].lat
|
||||
});
|
||||
}
|
||||
|
||||
d3.select('#geocode-form').on('submit', function() {
|
||||
d3.event.preventDefault();
|
||||
var val = d3.select('#geocode-location').node().value;
|
||||
@@ -110,29 +98,6 @@
|
||||
scr.src = 'http://api.tiles.mapbox.com/v3/mapbox/geocode/' +
|
||||
encodeURIComponent(val) + '.jsonp?callback=grid';
|
||||
});
|
||||
|
||||
/*
|
||||
$('#undo').click(function() {
|
||||
map.controller.undoStack.undo();
|
||||
map.updateUIs(true, true);
|
||||
});
|
||||
|
||||
$('#redo').click(function() {
|
||||
controller.undoStack.redo();
|
||||
map.updateUIs(true, true);
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Map control handlers
|
||||
|
||||
$('#zoomIn').click(function() {
|
||||
map.zoomIn();
|
||||
});
|
||||
|
||||
$('#zoomOut').click(function() {
|
||||
map.zoomOut();
|
||||
});
|
||||
*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,67 +4,19 @@ iD.Connection = function() {
|
||||
var nextNode = -1,
|
||||
nextWay = -1,
|
||||
nextRelation = -1,
|
||||
entities = {},
|
||||
relations = {},
|
||||
apiURL = 'http://www.openstreetmap.org/api/0.6/',
|
||||
modified = false;
|
||||
graph = {},
|
||||
apiURL = 'http://www.openstreetmap.org/api/0.6/';
|
||||
|
||||
var connection = {};
|
||||
|
||||
function all() {
|
||||
return d3.values(entities);
|
||||
}
|
||||
|
||||
function assign(obj) {
|
||||
// summary: Save an entity to the data store.
|
||||
if (obj.type === 'relation') {
|
||||
if (!relations[obj.id]) relations[obj.id] = obj;
|
||||
} else if (!entities[obj.id] || !entities[obj.id].loaded) {
|
||||
entities[obj.id] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
function getOrCreate(id, type) {
|
||||
// summary: Return an entity if it exists: if not, create an empty one with the given id, and return that.
|
||||
if (type === 'node') {
|
||||
if (!entities[id]) assign(new iD.Node(id, NaN, NaN, {}, false));
|
||||
return entities[id];
|
||||
} else if (type === 'way') {
|
||||
if (!entities[id]) {
|
||||
assign(new iD.Way(id, [], {}, false));
|
||||
}
|
||||
return entities[id];
|
||||
} else if (type === 'relation') {
|
||||
if (!relations[id]) assign(new iD.Relation(id, [], {}, false));
|
||||
return relations[id];
|
||||
}
|
||||
}
|
||||
|
||||
function doCreateNode(tags, lat, lon, perform) {
|
||||
// summary: Create a new node and save it in the data store, using an undo stack.
|
||||
var node = new iD.Node(nextNode--, lat, lon, tags, true);
|
||||
perform(new iD.actions.CreateEntityAction(node, assign));
|
||||
return node; // iD.Node
|
||||
}
|
||||
|
||||
function doCreateWay(tags, nodes, perform) {
|
||||
// summary: Create a new way and save it in the data store, using an undo stack.
|
||||
var way = new iD.Way(nextWay--, nodes.concat(), tags, true);
|
||||
perform(new iD.actions.CreateEntityAction(way, assign));
|
||||
return way;
|
||||
}
|
||||
|
||||
function doCreateRelation(tags, members, perform) {
|
||||
// summary: Create a new relation and save it in the data store, using an undo stack.
|
||||
var relation = new iD.Relation(nextRelation--, members.concat(), tags, true);
|
||||
perform(new iD.actions.CreateEntityAction(relation, assign));
|
||||
return relation;
|
||||
return d3.values(graph.index);
|
||||
}
|
||||
|
||||
function intersects(extent) {
|
||||
// summary: Find all drawable entities that are within a given bounding box.
|
||||
// Each one is an array of entities.
|
||||
return d3.values(entities).filter(function(e, id) {
|
||||
return d3.values(graph.index).filter(function(e, id) {
|
||||
return e.intersects(extent);
|
||||
});
|
||||
}
|
||||
@@ -79,87 +31,29 @@ iD.Connection = function() {
|
||||
d3.xml(url, parse(callback));
|
||||
}
|
||||
|
||||
function getTags(obj) {
|
||||
var tags = {};
|
||||
var tagelems = obj.getElementsByTagName('tag');
|
||||
// Doesn't use underscore for performance reasons
|
||||
for (var i = 0; i < tagelems.length; i++) {
|
||||
var item = tagelems[i];
|
||||
tags[item.attributes.k.nodeValue] = item.attributes.v.nodeValue;
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
function getNodes(obj) {
|
||||
var nodes = [];
|
||||
var nelems = obj.getElementsByTagName('nd');
|
||||
// Doesn't use underscore for performance reasons
|
||||
for (var i = 0; i < nelems.length; i++) {
|
||||
var item = nelems[i];
|
||||
nodes.push(entities[item.attributes.ref.nodeValue]);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function getMembers(obj) {
|
||||
var members = [];
|
||||
var elems = obj.getElementsByTagName('member');
|
||||
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
var item = elems[i];
|
||||
var id = item.attributes.ref.nodeValue,
|
||||
type = item.attributes.type.nodeValue,
|
||||
role = item.attributes.role.nodeValue;
|
||||
|
||||
var o = getOrCreate(id, type);
|
||||
members.push(new iD.RelationMember(o, role));
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
function parse(callback) {
|
||||
return function(dom) {
|
||||
if (!dom.childNodes) {
|
||||
return callback(new Error('Bad request'));
|
||||
}
|
||||
for (var i = 0; i < dom.childNodes[0].childNodes.length; i++) {
|
||||
var obj = dom.childNodes[0].childNodes[i], attrib;
|
||||
if (obj.nodeName === 'node') {
|
||||
var node = new iD.Node(
|
||||
obj.attributes.id.nodeValue,
|
||||
+obj.attributes.lat.nodeValue,
|
||||
+obj.attributes.lon.nodeValue,
|
||||
getTags(obj));
|
||||
assign(node);
|
||||
} else if (obj.nodeName === 'way') {
|
||||
var way = new iD.Way(
|
||||
obj.attributes.id.nodeValue,
|
||||
getNodes(obj),
|
||||
getTags(obj));
|
||||
assign(way);
|
||||
} else if (obj.nodeName === 'relation') {
|
||||
var relation = new iD.Relation(
|
||||
obj.attributes.id.nodeValue,
|
||||
getMembers(obj, connection),
|
||||
getTags(obj));
|
||||
assign(relation);
|
||||
}
|
||||
var obj = dom.childNodes[0].childNodes[i];
|
||||
graph.process(obj);
|
||||
}
|
||||
callback(null);
|
||||
};
|
||||
}
|
||||
|
||||
connection.entities = entities;
|
||||
connection.graph = function(x) {
|
||||
graph = x;
|
||||
return connection;
|
||||
};
|
||||
|
||||
connection.all = all;
|
||||
connection.relations = relations;
|
||||
connection.loadFromAPI = loadFromAPI;
|
||||
connection.loadFromURL = loadFromURL;
|
||||
connection.apiURL = apiURL;
|
||||
connection.intersects = intersects;
|
||||
connection.doCreateNode = doCreateNode;
|
||||
connection.doCreateWay = doCreateWay;
|
||||
connection.doCreateRelation = doCreateRelation;
|
||||
|
||||
return connection;
|
||||
};
|
||||
|
||||
@@ -1,2 +1,90 @@
|
||||
iD.Graph = function() {
|
||||
this.index = {};
|
||||
this.nodes = [];
|
||||
};
|
||||
|
||||
iD.Graph.prototype = {
|
||||
|
||||
getTags: function(obj) {
|
||||
var tags = {}, tagelems = obj.getElementsByTagName('tag');
|
||||
for (var i = 0; i < tagelems.length; i++) {
|
||||
var item = tagelems[i];
|
||||
tags[item.attributes.k.nodeValue] = item.attributes.v.nodeValue;
|
||||
}
|
||||
return tags;
|
||||
},
|
||||
|
||||
getNodes: function(obj) {
|
||||
var nodes = [], nelems = obj.getElementsByTagName('nd');
|
||||
for (var i = 0; i < nelems.length; i++) {
|
||||
var item = nelems[i];
|
||||
nodes.push(this.index[item.attributes.ref.nodeValue]);
|
||||
}
|
||||
return nodes;
|
||||
},
|
||||
|
||||
getMembers: function(obj) {
|
||||
var members = [];
|
||||
var elems = obj.getElementsByTagName('member');
|
||||
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
var item = elems[i];
|
||||
var id = item.attributes.ref.nodeValue,
|
||||
type = item.attributes.type.nodeValue,
|
||||
role = item.attributes.role.nodeValue;
|
||||
|
||||
var o = this.getOrCreate(id, type);
|
||||
members.push(new iD.RelationMember(o, role));
|
||||
}
|
||||
|
||||
return members;
|
||||
},
|
||||
|
||||
assign: function(obj) {
|
||||
// summary: Save an entity to the data store.
|
||||
if (obj.type === 'relation') {
|
||||
if (!this.index[obj.id]) this.index[obj.id] = obj;
|
||||
} else if (!this.index[obj.id] || !this.index[obj.id].loaded) {
|
||||
this.index[obj.id] = obj;
|
||||
}
|
||||
},
|
||||
|
||||
getOrCreate: function(id, type) {
|
||||
// summary: Return an entity if it exists: if not, create an empty one with the given id, and return that.
|
||||
if (type === 'node') {
|
||||
if (!this.index[id]) this.assign(new iD.Node(id));
|
||||
return this.index[id];
|
||||
} else if (type === 'way') {
|
||||
if (!this.index[id]) {
|
||||
this.assign(new iD.Way(id));
|
||||
}
|
||||
return this.index[id];
|
||||
} else if (type === 'relation') {
|
||||
if (!this.index[id]) this.assign(new iD.Relation(id));
|
||||
return this.index[id];
|
||||
}
|
||||
},
|
||||
|
||||
process: function(obj) {
|
||||
if (obj.nodeName === 'node') {
|
||||
var node = new iD.Node(
|
||||
obj.attributes.id.nodeValue,
|
||||
+obj.attributes.lat.nodeValue,
|
||||
+obj.attributes.lon.nodeValue,
|
||||
this.getTags(obj));
|
||||
this.assign(node);
|
||||
} else if (obj.nodeName === 'way') {
|
||||
var way = new iD.Way(
|
||||
obj.attributes.id.nodeValue,
|
||||
this.getNodes(obj),
|
||||
this.getTags(obj));
|
||||
this.assign(way);
|
||||
} else if (obj.nodeName === 'relation') {
|
||||
var relation = new iD.Relation(
|
||||
obj.attributes.id.nodeValue,
|
||||
this.getMembers(obj, connection),
|
||||
this.getTags(obj));
|
||||
this.assign(relation);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
iD.Relation = function(id, members, tags, loaded) {
|
||||
members = members || [];
|
||||
tags = tags || {};
|
||||
this.type = 'relation';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
@@ -12,6 +14,10 @@ iD.Relation = function(id, members, tags, loaded) {
|
||||
}
|
||||
};
|
||||
|
||||
iD.Relation.prototype = {
|
||||
intersects: function() { return true; }
|
||||
};
|
||||
|
||||
iD.RelationMember = function(entity, role) {
|
||||
this.entity = entity;
|
||||
this.role = role;
|
||||
|
||||
@@ -30,23 +30,28 @@ iD.Util.friendlyName = function(entity) {
|
||||
return n.length === 0 ? 'unknown' : n.join('; ');
|
||||
};
|
||||
|
||||
// TODO: don't use a cache here?
|
||||
iD.Util._presets = {};
|
||||
iD.Util.presets = function(type, callback) {
|
||||
if (iD.Util._presets[type]) return callback(iD.Util._presets[type]);
|
||||
$.ajax({
|
||||
url: 'presets/' + type + '.json',
|
||||
dataType: "json",
|
||||
error: function() {
|
||||
if (typeof console !== 'undefined') console.error(arguments);
|
||||
},
|
||||
success: function(resp) {
|
||||
iD.Util._presets[type] = resp;
|
||||
return callback(resp);
|
||||
}
|
||||
});
|
||||
iD.Util.TAG_CLASSES = {
|
||||
'highway': true,
|
||||
'railway': true,
|
||||
'motorway': true,
|
||||
'amenity': true,
|
||||
'landuse': true,
|
||||
'building': true,
|
||||
'bridge': true
|
||||
};
|
||||
|
||||
iD.Util.tileKey = function(coord) {
|
||||
return coord.z + ',' + coord.x + ',' + coord.y;
|
||||
iD.Util.styleClasses = function(pre) {
|
||||
return function(d) {
|
||||
var tags = d.tags;
|
||||
var c = [pre];
|
||||
function clean(x) {
|
||||
return iD.Util.TAG_CLASSES[x];
|
||||
}
|
||||
for (var k in tags) {
|
||||
if (!clean(k)) continue;
|
||||
c.push(k + '-' + tags[k]);
|
||||
c.push(k);
|
||||
}
|
||||
return c.join(' ');
|
||||
};
|
||||
};
|
||||
|
||||
@@ -17,9 +17,6 @@ iD.Map = function(obj) {
|
||||
|
||||
var inspector = iD.Inspector();
|
||||
|
||||
var tagclasses = [
|
||||
'highway', 'railway', 'motorway', 'amenity', 'landuse', 'building', 'bridge'];
|
||||
|
||||
var linegen = d3.svg.line()
|
||||
.x(function(d) { return projection(d)[0]; })
|
||||
.y(function(d) { return projection(d)[1]; });
|
||||
@@ -100,25 +97,6 @@ iD.Map = function(obj) {
|
||||
|
||||
function key(d) { return d._id; }
|
||||
|
||||
function classes(pre) {
|
||||
return function(d) {
|
||||
var tags = d.tags;
|
||||
var c = [pre];
|
||||
function clean(x) {
|
||||
return tagclasses.indexOf(x) !== -1;
|
||||
}
|
||||
for (var k in tags) {
|
||||
if (!clean(k)) continue;
|
||||
c.push(k + '-' + tags[k]);
|
||||
c.push(k);
|
||||
}
|
||||
if (selection.indexOf(d._id) !== -1) {
|
||||
c.push('active');
|
||||
}
|
||||
return c.join(' ');
|
||||
};
|
||||
}
|
||||
|
||||
function deselectClick() {
|
||||
selection = [];
|
||||
drawVector();
|
||||
@@ -169,11 +147,22 @@ iD.Map = function(obj) {
|
||||
return as - bs;
|
||||
}
|
||||
|
||||
var class_stroke = classes('stroke'),
|
||||
class_fill = classes('stroke'),
|
||||
class_area = classes('area'),
|
||||
class_marker = classes('marker'),
|
||||
class_casing = classes('casing');
|
||||
// This is an unfortunate hack that should be improved.
|
||||
function augmentSelect(fn) {
|
||||
return function(d) {
|
||||
var c = fn(d);
|
||||
if (selection.indexOf(d._id) !== -1) {
|
||||
c += ' active';
|
||||
}
|
||||
return c;
|
||||
};
|
||||
}
|
||||
|
||||
var class_stroke = augmentSelect(iD.Util.styleClasses('stroke')),
|
||||
class_fill = augmentSelect(iD.Util.styleClasses('stroke')),
|
||||
class_area = augmentSelect(iD.Util.styleClasses('area')),
|
||||
class_marker = augmentSelect(iD.Util.styleClasses('marker')),
|
||||
class_casing = augmentSelect(iD.Util.styleClasses('casing'));
|
||||
|
||||
function drawVector() {
|
||||
var all = connection.intersects(extent());
|
||||
|
||||
@@ -6,22 +6,22 @@ describe('Entity', function () {
|
||||
});
|
||||
|
||||
it('has no entity type', function () {
|
||||
expect(entity.entityType).toEqual('');
|
||||
expect(entity.type).toEqual('');
|
||||
});
|
||||
|
||||
describe('#parentWays', function () {
|
||||
it('returns an array of parents with entityType way', function () {
|
||||
entity.addParent({_id: 1, entityType: 'way'});
|
||||
entity.addParent({_id: 2, entityType: 'node'});
|
||||
expect(entity.parentWays()).toEqual([{_id: 1, entityType: 'way'}]);
|
||||
entity.addParent({_id: 1, type: 'way'});
|
||||
entity.addParent({_id: 2, type: 'node'});
|
||||
expect(entity.parentWays()).toEqual([{_id: 1, type: 'way'}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#parentRelations', function () {
|
||||
it('returns an array of parents with entityType relation', function () {
|
||||
entity.addParent({_id: 1, entityType: 'way'});
|
||||
entity.addParent({_id: 2, entityType: 'relation'});
|
||||
expect(entity.parentRelations()).toEqual([{_id: 2, entityType: 'relation'}]);
|
||||
entity.addParent({_id: 1, type: 'way'});
|
||||
entity.addParent({_id: 2, type: 'relation'});
|
||||
expect(entity.parentRelations()).toEqual([{_id: 2, type: 'relation'}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user