diff --git a/NOTES.md b/NOTES.md
index 08306ab32..90142960d 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -1,3 +1,16 @@
+## The Graph
+
+iD implements a [persistent data structure](http://en.wikipedia.org/wiki/Persistent_data_structure)
+over the OSM data model.
+
+To be clear, this data model is something like
+
+
+ root -> relations (-> relations) -> ways -> nodes
+ \ \> nodes
+ \- ways -> nodes
+ \- nodes
+
## Actions
Actions are operations on OSM data like adding nodes, moving ways,
diff --git a/index.html b/index.html
index b92025444..82463d893 100755
--- a/index.html
+++ b/index.html
@@ -31,10 +31,10 @@
+
-
diff --git a/js/iD/Entity.js b/js/iD/Entity.js
index 091be884d..27ddd284c 100755
--- a/js/iD/Entity.js
+++ b/js/iD/Entity.js
@@ -1,14 +1,7 @@
-iD.Entity = function () {
- this.parents = {};
- this._id = iD.Util.id();
- this.id = NaN;
- this.loaded = false;
- this.type = '';
- this.modified = false;
- this.deleted = false;
-};
+iD.Entity = function () { };
iD.Entity.prototype = {
+ parents: {},
// a relation or way which contains this entity
addParent: function (x) {
this.parents[x._id] = x;
diff --git a/js/iD/Node.js b/js/iD/Node.js
index ebca16fdf..e6e963c1f 100644
--- a/js/iD/Node.js
+++ b/js/iD/Node.js
@@ -2,7 +2,6 @@ iD.Node = function(id, lat, lon, tags, loaded) {
this.type = 'node';
this.id = id;
this._id = iD.Util.id();
- this.entity = new iD.Entity();
this.lat = lat;
this.lon = lon;
this[0] = lon;
@@ -19,3 +18,5 @@ iD.Node.prototype = {
(this.lat >= extent[1][1]);
}
};
+
+iD.Util.extend(iD.Node, iD.Entity);
diff --git a/js/iD/Relation.js b/js/iD/Relation.js
index 2e3db1709..fb90e8c3f 100644
--- a/js/iD/Relation.js
+++ b/js/iD/Relation.js
@@ -1,11 +1,11 @@
-iD.Relation = function(id, members, tags, loaded) {
+iD.Relation = function(id, children, tags, loaded) {
members = members || [];
tags = tags || {};
this.type = 'relation';
this.id = id;
this._id = iD.Util.id();
this.entity = new iD.Entity();
- this.members = members;
+ this.children = children;
this.tags = tags;
this.modified = this.id < 0;
this.loaded = (loaded === undefined) ? true : loaded;
@@ -15,6 +15,8 @@ iD.Relation.prototype = {
intersects: function() { return true; }
};
+iD.Util.extend(iD.Relation, iD.Entity);
+
iD.RelationMember = function(entity, role) {
this.entity = entity;
this.role = role;
diff --git a/js/iD/Util.js b/js/iD/Util.js
index 802b88e0f..f61ee5dab 100644
--- a/js/iD/Util.js
+++ b/js/iD/Util.js
@@ -30,3 +30,11 @@ iD.Util.friendlyName = function(entity) {
return n.length === 0 ? 'unknown' : n.join('; ');
};
+iD.Util.extend = function(child, parent) {
+ for (var property in parent.prototype) {
+ if (typeof child.prototype[property] == "undefined") {
+ child.prototype[property] = parent.prototype[property];
+ }
+ }
+ return child;
+};
diff --git a/js/iD/Way.js b/js/iD/Way.js
index 9333ba7ba..491dc9761 100644
--- a/js/iD/Way.js
+++ b/js/iD/Way.js
@@ -12,27 +12,19 @@ iD.Way = function(id, nodes, tags, loaded) {
this.type = 'way';
this.id = id;
this._id = iD.Util.id();
- this.deleted = false;
- this.entity = new iD.Entity();
this.tags = tags;
- this.nodes = nodes;
+ this.children = nodes;
this.loaded = (loaded === undefined) ? true : loaded;
this.extent = {};
};
iD.Way.prototype = {
- addNode: function(node) {
- this.nodes.push(node);
- this._bounds = null;
- return this;
- },
-
// 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)?
- if (!this.nodes.length) return true;
- return this.nodes[this.nodes.length - 1] === this.nodes[0];
+ if (!this.children.length) return true;
+ return this.children[this.children.length - 1] === this.children[0];
},
isType: function(type) {
@@ -56,9 +48,10 @@ iD.Way.prototype = {
// ---------------------
// Bounding-box handling
intersects: function(extent) {
+ // TODO: rewrite with new id-mapping
return true;
// No-node ways are inside of nothing.
- if (!this.nodes.length) return false;
+ if (!this.children.length) return false;
var bounds = this.bounds();
// left
return !(
@@ -72,3 +65,5 @@ iD.Way.prototype = {
bounds[0][1] > extent[1][1]);
}
};
+
+iD.Util.extend(iD.Way, iD.Entity);
diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js
index b0debdff1..370fe91ce 100755
--- a/js/iD/renderer/Map.js
+++ b/js/iD/renderer/Map.js
@@ -113,7 +113,7 @@ iD.Map = function(obj) {
}
function nodeline(d) {
- return linegen(d.nodes.map(function(n) {
+ return linegen(d.children.map(function(n) {
return connection.graph().index[n];
}));
}
@@ -163,7 +163,7 @@ iD.Map = function(obj) {
});
var handles = layers[0].hit.selectAll('circle.handle')
- .data(active_entity.length ? active_entity[0].nodes : [], key);
+ .data(active_entity.length ? active_entity[0].children : [], key);
handles.exit().remove();
fills.exit().remove();
diff --git a/test/index.html b/test/index.html
index e233bc6bb..24c10d7d3 100644
--- a/test/index.html
+++ b/test/index.html
@@ -13,16 +13,15 @@
+
-
-
diff --git a/test/spec/Entity.js b/test/spec/Entity.js
index 7632c760b..784109279 100644
--- a/test/spec/Entity.js
+++ b/test/spec/Entity.js
@@ -5,10 +5,6 @@ describe('Entity', function () {
entity = new iD.Entity();
});
- it('has no entity type', function () {
- expect(entity.type).toEqual('');
- });
-
describe('#parentWays', function () {
it('returns an array of parents with entityType way', function () {
entity.addParent({_id: 1, type: 'way'});
diff --git a/test/spec/Way.js b/test/spec/Way.js
index f2686c85d..40662ab49 100644
--- a/test/spec/Way.js
+++ b/test/spec/Way.js
@@ -11,7 +11,7 @@ describe('Way', function() {
});
it('has zero nodes by default', function() {
- expect(way.nodes.length).toEqual(0);
+ expect(way.children.length).toEqual(0);
});
describe('#isClosed', function() {