mirror of
https://github.com/FoggedLens/iD.git
synced 2026-03-03 18:03:38 +00:00
Use simple objects for data, simplify graph
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
|
||||
<script type='text/javascript' src='js/iD/format/GeoJSON.js'></script>
|
||||
<script type='text/javascript' src='js/iD/format/XML.js'></script>
|
||||
<script type='text/javascript' src='js/iD/graph/pdata.js'></script>
|
||||
<script type='text/javascript' src='js/iD/graph/Node.js'></script>
|
||||
<script type='text/javascript' src='js/iD/graph/Relation.js'></script>
|
||||
<script type='text/javascript' src='js/iD/graph/Way.js'></script>
|
||||
|
||||
@@ -6,11 +6,6 @@ iD.Connection = function(graph) {
|
||||
|
||||
var connection = {};
|
||||
|
||||
function all() {
|
||||
return graph.nodes;
|
||||
}
|
||||
|
||||
|
||||
// Request data within the bbox from an external OSM server.
|
||||
function loadFromAPI(box, callback) {
|
||||
loadFromURL(apiURL + 'map?bbox=' +
|
||||
@@ -24,12 +19,12 @@ iD.Connection = function(graph) {
|
||||
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);
|
||||
nodes.push(+nelems[i].attributes.ref.nodeValue);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// <tag k="highway" v="unclassified"/>
|
||||
function getTags(obj) {
|
||||
var tags = {}, tagelems = obj.getElementsByTagName('tag');
|
||||
for (var i = 0; i < tagelems.length; i++) {
|
||||
@@ -39,6 +34,7 @@ iD.Connection = function(graph) {
|
||||
return tags;
|
||||
}
|
||||
|
||||
// <member type="node" ref="364933006" role=""/>
|
||||
function getMembers(obj) {
|
||||
var members = [],
|
||||
elems = obj.getElementsByTagName('member');
|
||||
@@ -54,38 +50,45 @@ iD.Connection = function(graph) {
|
||||
return members;
|
||||
}
|
||||
|
||||
// <node id="1831881213"
|
||||
// version="1"
|
||||
// changeset="12370172"
|
||||
// lat="54.0900666"
|
||||
// lon="12.2539381"
|
||||
// user="lafkor"
|
||||
// uid="75625"
|
||||
// visible="true"
|
||||
// timestamp="2012-07-20T09:43:19Z">
|
||||
function objectData(obj) {
|
||||
return {
|
||||
var o = {
|
||||
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)
|
||||
nodes: getNodes(obj),
|
||||
tags: getTags(obj)
|
||||
};
|
||||
var numbers = {id: true, lat: true, lon: true };
|
||||
for (var i = 0; i < obj.attributes.length; i++) {
|
||||
var n = obj.attributes[i].nodeName;
|
||||
var v = obj.attributes[i].nodeValue;
|
||||
o[n] = numbers[n] ? +v : v;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function parse(callback) {
|
||||
return function(dom) {
|
||||
if (!dom.childNodes) {
|
||||
return callback(new Error('Bad request'));
|
||||
}
|
||||
var root = dom.childNodes[0],
|
||||
ways = root.getElementsByTagName('way'),
|
||||
relations = root.getElementsByTagName('relation'),
|
||||
nodes = root.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]));
|
||||
if (!dom.childNodes) return callback(new Error('Bad request'));
|
||||
var root = dom.childNodes[0];
|
||||
connection.graph.insert(_.map(root.getElementsByTagName('way'), objectData));
|
||||
connection.graph.insert(_.map(root.getElementsByTagName('node'), objectData));
|
||||
connection.graph.insert(_.map(root.getElementsByTagName('relation'), objectData));
|
||||
callback(null);
|
||||
};
|
||||
}
|
||||
|
||||
connection.graph = graph;
|
||||
connection.all = all;
|
||||
connection.loadFromAPI = loadFromAPI;
|
||||
connection.objectData = objectData;
|
||||
connection.loadFromURL = loadFromURL;
|
||||
connection.apiURL = apiURL;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ iD.GeoJSON = {
|
||||
properties: entity.tags,
|
||||
geometry: {
|
||||
'type': 'LineString',
|
||||
'coordinates': _.map(entity.children, function(node) {
|
||||
'coordinates': entity.nodes.map(function(node) {
|
||||
return [node.lon, node.lat];
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ iD.XML = {
|
||||
JXON.unbuild({
|
||||
way: {
|
||||
'@id': entity.id,
|
||||
'nd': entity.children.map(function(e) {
|
||||
'nd': entity.nodes.map(function(e) {
|
||||
return {
|
||||
keyAttributes: {
|
||||
ref: e.id
|
||||
|
||||
@@ -1,57 +1,43 @@
|
||||
iD.Graph = function() {
|
||||
};
|
||||
iD.Graph = function() { };
|
||||
|
||||
iD.Graph.prototype = {
|
||||
|
||||
index: {},
|
||||
head: {},
|
||||
|
||||
insert: function(o) {
|
||||
var obj;
|
||||
// Do not reinsert OSM objects
|
||||
if (this.index[o.id]) return;
|
||||
if (o.type === 'node') {
|
||||
obj = {
|
||||
type: 'node',
|
||||
id: o.id,
|
||||
uid: uuid.v4(),
|
||||
lat: o.lat,
|
||||
lon: o.lon,
|
||||
tags: o.tags
|
||||
};
|
||||
} else if (o.type === 'way') {
|
||||
obj = new iD.Way(
|
||||
o.id,
|
||||
uuid.v4(),
|
||||
o.nodes,
|
||||
o.tags);
|
||||
} else if (o.type === 'relation') {
|
||||
obj = new iD.Relation(
|
||||
o.id,
|
||||
uuid.v4(),
|
||||
o.members,
|
||||
o.tags);
|
||||
// stack of previous versions of this datastructure
|
||||
prev: [],
|
||||
|
||||
insert: function(a) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (this.head[a[i].id]) return;
|
||||
this.head[a[i].id] = a[i];
|
||||
}
|
||||
if (!obj) return;
|
||||
this.index[obj.id] = [obj];
|
||||
},
|
||||
|
||||
modify: function(callback) {
|
||||
// Previous version pushed onto stack
|
||||
var o = pdata.object(this.head).get();
|
||||
prev.push(o);
|
||||
|
||||
// Make head a copy with no common history
|
||||
this.head = pdata.object(this.head).get();
|
||||
},
|
||||
|
||||
intersects: function(version, extent) {
|
||||
// summary: Find all drawable entities that are within a given bounding box.
|
||||
// Each one is an array of entities.
|
||||
var items = [];
|
||||
for (var i in this.index) {
|
||||
if (this.index[i][version]) {
|
||||
items.push(this.index[i][version]);
|
||||
}
|
||||
for (var i in this.head) {
|
||||
if (this.head[i]) items.push(this.head[i]);
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
fetch: function(object) {
|
||||
var o = this.index[object][0];
|
||||
fetch: function(id) {
|
||||
var o = this.head[id];
|
||||
var f = _.clone(o);
|
||||
if (!f.children || !f.children.length) return f;
|
||||
f.children = f.children.map(function(c) {
|
||||
if (!f.nodes || !f.nodes.length) return f;
|
||||
f.nodes = f.nodes.map(function(c) {
|
||||
return this.fetch(c);
|
||||
}.bind(this));
|
||||
return f;
|
||||
|
||||
@@ -6,19 +6,15 @@
|
||||
//
|
||||
// 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, uid, children, tags, loaded) {
|
||||
this.id = id;
|
||||
this.uid = uid;
|
||||
this.tags = tags || {};
|
||||
this.children = children || [];
|
||||
this.loaded = (loaded === undefined) ? true : loaded;
|
||||
this.extent = {};
|
||||
|
||||
iD.Way = {
|
||||
isClosed: function(w) {
|
||||
if (!w.nodes.length) return true;
|
||||
return w.nodes[w.nodes.length - 1] === w.nodes[0];
|
||||
}
|
||||
};
|
||||
|
||||
iD.Way.prototype = {
|
||||
|
||||
type: 'way',
|
||||
|
||||
/*
|
||||
// JOSM: http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/data/osm/Way.java#L466
|
||||
isClosed: function() {
|
||||
// summary: Is this a closed way (first and last nodes the same)?
|
||||
@@ -64,3 +60,4 @@ iD.Way.prototype = {
|
||||
bounds[0][1] > extent[1][1]);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
46
js/iD/graph/pdata.js
Normal file
46
js/iD/graph/pdata.js
Normal file
@@ -0,0 +1,46 @@
|
||||
var pdata = {};
|
||||
|
||||
pdata.object = function(input) {
|
||||
|
||||
var v = clone(input),
|
||||
proxy = {};
|
||||
|
||||
function clone(x) {
|
||||
var v = {};
|
||||
for (var k in x) v[k] = x[k];
|
||||
return v;
|
||||
}
|
||||
|
||||
// Remove a key from the object. This is like `delete`,
|
||||
// but does not delete the key in this closure's object
|
||||
proxy.remove = function(key) {
|
||||
var n = {}, k, i;
|
||||
if (typeof key === 'object') {
|
||||
var keys = {};
|
||||
for (i = 0; i < key.length; i++) keys[key[i]] = true;
|
||||
for (k in v) if (!keys[k]) n[k] = v[k];
|
||||
} else {
|
||||
for (k in v) if (k !== key) n[k] = v[k];
|
||||
}
|
||||
return pdata.object(n);
|
||||
};
|
||||
|
||||
// Set a value or values in the object. Overwrites
|
||||
// existing values.
|
||||
proxy.set = function(vals) {
|
||||
var n = clone(v);
|
||||
for (var j in vals) {
|
||||
n[j] = vals[j];
|
||||
}
|
||||
return pdata.object(n);
|
||||
};
|
||||
|
||||
// Get the contained object.
|
||||
proxy.get = function() {
|
||||
return clone(v);
|
||||
};
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = pdata;
|
||||
@@ -44,17 +44,17 @@ iD.Map = function(elem) {
|
||||
// geo
|
||||
linegen = d3.svg.line()
|
||||
.x(function(d) {
|
||||
var node = connection.graph.index[d][version];
|
||||
var node = graph.head[d];
|
||||
return projection([node.lon, node.lat])[0];
|
||||
})
|
||||
.y(function(d) {
|
||||
var node = connection.graph.index[d][version];
|
||||
var node = graph.head[d];
|
||||
return projection([node.lon, node.lat])[1];
|
||||
}),
|
||||
// Abstract linegen so that it pulls from `.children`. This
|
||||
// makes it possible to call simply `.attr('d', nodeline)`.
|
||||
nodeline = function(d) {
|
||||
return linegen(d.children);
|
||||
return linegen(d.nodes);
|
||||
},
|
||||
// Abstract a key function that looks for uids. This is given
|
||||
// as a second argument to `.data()`.
|
||||
@@ -99,10 +99,10 @@ iD.Map = function(elem) {
|
||||
var all = graph.intersects(version, getExtent());
|
||||
|
||||
var ways = all.filter(function(a) {
|
||||
return a.type === 'way' && !a.isClosed();
|
||||
return a.type === 'way' && !iD.Way.isClosed(a);
|
||||
}).sort(iD.Style.waystack),
|
||||
areas = all.filter(function(a) {
|
||||
return a.type === 'way' && a.isClosed();
|
||||
return a.type === 'way' && iD.Way.isClosed(a);
|
||||
}),
|
||||
points = all.filter(function(a) {
|
||||
return a.type === 'node';
|
||||
@@ -222,6 +222,7 @@ iD.Map = function(elem) {
|
||||
download();
|
||||
drawVector();
|
||||
} else {
|
||||
// TODO: hide vector features
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,5 +322,6 @@ iD.Map = function(elem) {
|
||||
parent.node().offsetWidth,
|
||||
parent.node().offsetHeight);
|
||||
redraw();
|
||||
|
||||
return d3.rebind(map, dispatch, 'on');
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user