mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 23:14:47 +02:00
Refactor style, abstract id references
This is the first commit that really goes whole hog in terms of creating an object graph. It's quite close, though it could be faster in a lot of ways.
This commit is contained in:
+3
-3
@@ -15,6 +15,7 @@
|
||||
<script type="text/javascript" src="js/iD/id.js"></script>
|
||||
<script type="text/javascript" src="js/iD/actions/UndoStack.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Util.js"></script>
|
||||
<script type="text/javascript" src="js/iD/renderer/style.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Taginfo.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/iD/controller/controller.js"></script>
|
||||
@@ -36,8 +37,6 @@
|
||||
<script type="text/javascript" src="js/iD/Entity.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Way.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Connection.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Controller.js"></script>
|
||||
<script type="text/javascript" src="js/iD/controller/DrawWay.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Graph.js"></script>
|
||||
|
||||
<div id="map"></div>
|
||||
@@ -64,7 +63,8 @@
|
||||
</div>
|
||||
<script>
|
||||
var connection = new iD.Connection("http://www.overpass-api.de/api/xapi?");
|
||||
connection.graph(new iD.Graph());
|
||||
var graph = new iD.Graph();
|
||||
connection.graph(graph);
|
||||
|
||||
var m = d3.select('#map');
|
||||
// Initialise map
|
||||
|
||||
+60
-4
@@ -31,20 +31,76 @@ iD.Connection = function() {
|
||||
d3.xml(url, parse(callback));
|
||||
}
|
||||
|
||||
function getNodes(obj) {
|
||||
var nodes = [], nelems = obj.getElementsByTagName('nd');
|
||||
for (var i = 0; i < nelems.length; i++) {
|
||||
var item = nelems[i];
|
||||
nodes.push(item.attributes.ref.nodeValue);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function getTags(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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
id: id,
|
||||
type: type,
|
||||
role: role
|
||||
};
|
||||
|
||||
members.push(o);
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
function objectData(obj) {
|
||||
return {
|
||||
type: obj.nodeName,
|
||||
id: obj.attributes.id.nodeValue,
|
||||
tags: getTags(obj),
|
||||
lat: (obj.attributes.lat) ? obj.attributes.lat.nodeValue : null,
|
||||
lon: (obj.attributes.lon) ? obj.attributes.lon.nodeValue : null,
|
||||
members: getMembers(obj),
|
||||
nodes: getNodes(obj)
|
||||
};
|
||||
}
|
||||
|
||||
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];
|
||||
graph.process(obj);
|
||||
}
|
||||
var ways = dom.childNodes[0].getElementsByTagName('way'),
|
||||
relations = dom.childNodes[0].getElementsByTagName('relation'),
|
||||
nodes = dom.childNodes[0].getElementsByTagName('node');
|
||||
var i;
|
||||
for (i = 0; i < ways.length; i++) graph.insert(objectData(ways[i]));
|
||||
for (i = 0; i < relations.length; i++) graph.insert(objectData(relations[i]));
|
||||
for (i = 0; i < nodes.length; i++) graph.insert(objectData(nodes[i]));
|
||||
callback(null);
|
||||
};
|
||||
}
|
||||
|
||||
connection.graph = function(x) {
|
||||
if (!arguments.length) return graph;
|
||||
graph = x;
|
||||
return connection;
|
||||
};
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
iD.Controller = function() {
|
||||
var controller = {},
|
||||
state = null;
|
||||
|
||||
controller.undoStack = new iD.UndoStack();
|
||||
|
||||
controller.setState = function(newState) {
|
||||
// summary: Enter a new ControllerState, firing exitState on the old one, and enterState on the new one.
|
||||
if (newState === state) { return; }
|
||||
if (state) state.exitState();
|
||||
newState.controller = controller;
|
||||
state = newState;
|
||||
newState.enterState();
|
||||
};
|
||||
|
||||
return controller;
|
||||
};
|
||||
+2
-6
@@ -9,21 +9,18 @@ iD.Entity = function () {
|
||||
};
|
||||
|
||||
iD.Entity.prototype = {
|
||||
// Parent-handling
|
||||
// a relation or way which contains this entity
|
||||
addParent: function (x) {
|
||||
// summary: Record a parent (a relation or way which contains this entity).
|
||||
this.parents[x._id] = x;
|
||||
},
|
||||
removeParent: function (x) {
|
||||
// summary: Remove a parent (e.g. when node removed from a way).
|
||||
delete this.parents[x._id];
|
||||
},
|
||||
hasParent: function (x) {
|
||||
// summary: Does this entity have the specified parent (e.g. is it in a certain relation)?
|
||||
// summary: Does this entity have the specified parent (e.g. is it in a certain relation)?
|
||||
return !!this.parents[x._id];
|
||||
},
|
||||
parentObjects: function () {
|
||||
// summary: List of all parents of this entity.
|
||||
var objects = [];
|
||||
for (var i in this.parents) {
|
||||
objects.push(this.parents[i]);
|
||||
@@ -31,7 +28,6 @@ iD.Entity.prototype = {
|
||||
return objects;
|
||||
},
|
||||
hasParentWays: function () {
|
||||
// summary: Does this entity have any parents which are ways?
|
||||
var parentObjects = this.parentObjects();
|
||||
for (var i = 0; i < parentObjects.length; i++) {
|
||||
if (parentObjects[i].type === 'way') return true;
|
||||
|
||||
+19
-79
@@ -4,87 +4,27 @@ iD.Graph = function() {
|
||||
};
|
||||
|
||||
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;
|
||||
insert: function(o) {
|
||||
var obj;
|
||||
if (o.type === 'node') {
|
||||
obj = new iD.Node(
|
||||
o.id,
|
||||
o.lat,
|
||||
o.lon,
|
||||
o.tags);
|
||||
} else if (o.type === 'way') {
|
||||
obj = new iD.Way(
|
||||
o.id,
|
||||
o.nodes,
|
||||
o.tags);
|
||||
} else if (o.type === 'relation') {
|
||||
obj = new iD.Relation(
|
||||
o.id,
|
||||
o.members,
|
||||
o.tags);
|
||||
}
|
||||
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) {
|
||||
if (obj && (!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,18 +1,14 @@
|
||||
// [Node](http://wiki.openstreetmap.org/wiki/Node)
|
||||
iD.Node = function(id, lat, lon, tags, loaded) {
|
||||
// summary: An OSM node.
|
||||
this.type = 'node';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
this.entity = new iD.Entity();
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
// TODO: keep or trash this custom
|
||||
this[0] = lon;
|
||||
this[1] = lat;
|
||||
this.tags = tags;
|
||||
this.loaded = (loaded === undefined) ? true : loaded;
|
||||
this.modified = this.id < 0;
|
||||
};
|
||||
|
||||
iD.Node.prototype = {
|
||||
|
||||
@@ -9,9 +9,6 @@ iD.Relation = function(id, members, tags, loaded) {
|
||||
this.tags = tags;
|
||||
this.modified = this.id < 0;
|
||||
this.loaded = (loaded === undefined) ? true : loaded;
|
||||
for (var i = 0; i < members.length; i++) {
|
||||
members[i].entity.entity.addParent(this);
|
||||
}
|
||||
};
|
||||
|
||||
iD.Relation.prototype = {
|
||||
|
||||
@@ -30,28 +30,3 @@ iD.Util.friendlyName = function(entity) {
|
||||
return n.length === 0 ? 'unknown' : n.join('; ');
|
||||
};
|
||||
|
||||
iD.Util.TAG_CLASSES = {
|
||||
'highway': true,
|
||||
'railway': true,
|
||||
'motorway': true,
|
||||
'amenity': true,
|
||||
'landuse': true,
|
||||
'building': true,
|
||||
'bridge': true
|
||||
};
|
||||
|
||||
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(' ');
|
||||
};
|
||||
};
|
||||
|
||||
+5
-11
@@ -7,29 +7,22 @@
|
||||
// If a a way is _closed_, it is assumed to be an area unless it has a
|
||||
// `highway` or `barrier` tag and is not also tagged `area`.
|
||||
iD.Way = function(id, nodes, tags, loaded) {
|
||||
// summary: An OSM way.
|
||||
nodes = nodes || [];
|
||||
tags = tags || {};
|
||||
this.type = 'way';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
this.deleted = false;
|
||||
this.entity = new iD.Entity();
|
||||
this.tags = tags || {};
|
||||
this.tags = tags;
|
||||
this.nodes = nodes;
|
||||
this.loaded = (loaded === undefined) ? true : loaded;
|
||||
this.modified = this.id < 0;
|
||||
this.nodes = [];
|
||||
this.extent = {};
|
||||
|
||||
if (nodes) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
this.addNode(nodes[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
iD.Way.prototype = {
|
||||
|
||||
addNode: function(node) {
|
||||
node.entity.addParent(this);
|
||||
this.nodes.push(node);
|
||||
this._bounds = null;
|
||||
return this;
|
||||
@@ -63,6 +56,7 @@ iD.Way.prototype = {
|
||||
// ---------------------
|
||||
// Bounding-box handling
|
||||
intersects: function(extent) {
|
||||
return true;
|
||||
// No-node ways are inside of nothing.
|
||||
if (!this.nodes.length) return false;
|
||||
var bounds = this.bounds();
|
||||
|
||||
+9
-39
@@ -9,7 +9,6 @@ iD.Map = function(obj) {
|
||||
selection = [],
|
||||
width = obj.width || 800,
|
||||
height = obj.height || 400,
|
||||
controller = iD.Controller(),
|
||||
projection = d3.geo.mercator()
|
||||
.scale(512).translate([512, 512]),
|
||||
connection = obj.connection,
|
||||
@@ -114,37 +113,9 @@ iD.Map = function(obj) {
|
||||
}
|
||||
|
||||
function nodeline(d) {
|
||||
return linegen(d.nodes);
|
||||
}
|
||||
|
||||
var highway_stack = [
|
||||
'motorway',
|
||||
'motorway_link',
|
||||
'trunk',
|
||||
'trunk_link',
|
||||
'primary',
|
||||
'primary_link',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
'unclassified',
|
||||
'residential',
|
||||
'service',
|
||||
'footway'
|
||||
];
|
||||
|
||||
function waystack(a, b) {
|
||||
if (!a || !b) return 0;
|
||||
if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
|
||||
return a.tags.layer - b.tags.layer;
|
||||
}
|
||||
if (a.tags.bridge) return 1;
|
||||
if (b.tags.bridge) return -1;
|
||||
var as = 0, bs = 0;
|
||||
if (a.tags.highway && b.tags.highway) {
|
||||
as -= highway_stack.indexOf(a.tags.highway);
|
||||
bs -= highway_stack.indexOf(b.tags.highway);
|
||||
}
|
||||
return as - bs;
|
||||
return linegen(d.nodes.map(function(n) {
|
||||
return connection.graph().index[n];
|
||||
}));
|
||||
}
|
||||
|
||||
// This is an unfortunate hack that should be improved.
|
||||
@@ -158,18 +129,18 @@ iD.Map = function(obj) {
|
||||
};
|
||||
}
|
||||
|
||||
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'));
|
||||
var class_stroke = augmentSelect(iD.Style.styleClasses('stroke')),
|
||||
class_fill = augmentSelect(iD.Style.styleClasses('stroke')),
|
||||
class_area = augmentSelect(iD.Style.styleClasses('area')),
|
||||
class_marker = augmentSelect(iD.Style.styleClasses('marker')),
|
||||
class_casing = augmentSelect(iD.Style.styleClasses('casing'));
|
||||
|
||||
function drawVector() {
|
||||
var all = connection.intersects(extent());
|
||||
|
||||
var ways = all.filter(function(a) {
|
||||
return a.type === 'way' && !a.isClosed();
|
||||
}).sort(waystack),
|
||||
}).sort(iD.Style.waystack),
|
||||
areas = all.filter(function(a) {
|
||||
return a.type === 'way' && a.isClosed();
|
||||
}),
|
||||
@@ -295,7 +266,6 @@ iD.Map = function(obj) {
|
||||
map.zoomOut = zoomOut;
|
||||
|
||||
map.connection = connection;
|
||||
map.controller = controller;
|
||||
map.projection = projection;
|
||||
|
||||
redraw();
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
iD.Style = {};
|
||||
iD.Style.highway_stack = [
|
||||
'motorway',
|
||||
'motorway_link',
|
||||
'trunk',
|
||||
'trunk_link',
|
||||
'primary',
|
||||
'primary_link',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
'unclassified',
|
||||
'residential',
|
||||
'service',
|
||||
'footway'
|
||||
];
|
||||
|
||||
iD.Style.waystack = function(a, b) {
|
||||
if (!a || !b) return 0;
|
||||
if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
|
||||
return a.tags.layer - b.tags.layer;
|
||||
}
|
||||
if (a.tags.bridge) return 1;
|
||||
if (b.tags.bridge) return -1;
|
||||
var as = 0, bs = 0;
|
||||
if (a.tags.highway && b.tags.highway) {
|
||||
as -= iD.Style.highway_stack.indexOf(a.tags.highway);
|
||||
bs -= iD.Style.highway_stack.indexOf(b.tags.highway);
|
||||
}
|
||||
return as - bs;
|
||||
};
|
||||
|
||||
|
||||
iD.Style.TAG_CLASSES = {
|
||||
'highway': true,
|
||||
'railway': true,
|
||||
'motorway': true,
|
||||
'amenity': true,
|
||||
'landuse': true,
|
||||
'building': true,
|
||||
'bridge': true
|
||||
};
|
||||
|
||||
iD.Style.styleClasses = function(pre) {
|
||||
return function(d) {
|
||||
var tags = d.tags;
|
||||
var c = [pre];
|
||||
function clean(x) {
|
||||
return iD.Style.TAG_CLASSES[x];
|
||||
}
|
||||
for (var k in tags) {
|
||||
if (!clean(k)) continue;
|
||||
c.push(k + '-' + tags[k]);
|
||||
c.push(k);
|
||||
}
|
||||
return c.join(' ');
|
||||
};
|
||||
};
|
||||
@@ -25,6 +25,7 @@
|
||||
<script type="text/javascript" src="../js/iD/Controller.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/renderer/markers.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/renderer/Map.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/renderer/Style.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/renderer/tiles.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Graph.js"></script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user