mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-12 16:52:50 +00:00
Fix specs, add new GeoJSON class with mappings, rename entityType to
type
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<script type="text/javascript" src="js/lib/underscore-min.js"></script>
|
||||
<script type="text/javascript" src="js/lib/d3.v2.js"></script>
|
||||
|
||||
<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/Taginfo.js"></script>
|
||||
@@ -29,6 +30,7 @@
|
||||
<script type="text/javascript" src="js/iD/renderer/markers.js"></script>
|
||||
<script type="text/javascript" src="js/iD/ui/Inspector.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/iD/GeoJSON.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Node.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Relation.js"></script>
|
||||
<script type="text/javascript" src="js/iD/Entity.js"></script>
|
||||
@@ -36,6 +38,7 @@
|
||||
<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>
|
||||
<div id='modebuttons'>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
iD.Connection = function() {
|
||||
// summary: The data store, including methods to fetch data from (and, eventually, save data to)
|
||||
// summary: The data store, including methods to fetch data from (and, eventually, save data to)
|
||||
// an OSM API server.
|
||||
var nextNode = -1, // next negative ids
|
||||
nextWay = -1, // |
|
||||
nextRelation = -1, // |
|
||||
var nextNode = -1,
|
||||
nextWay = -1,
|
||||
nextRelation = -1,
|
||||
entities = {},
|
||||
relations = {},
|
||||
pois = {},
|
||||
apiURL = 'http://www.openstreetmap.org/api/0.6/map?bbox=',
|
||||
apiURL = 'http://www.openstreetmap.org/api/0.6/',
|
||||
modified = false;
|
||||
|
||||
var connection = {};
|
||||
@@ -20,7 +17,7 @@ iD.Connection = function() {
|
||||
|
||||
function assign(obj) {
|
||||
// summary: Save an entity to the data store.
|
||||
if (obj.entityType === 'relation') {
|
||||
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;
|
||||
@@ -74,7 +71,7 @@ iD.Connection = function() {
|
||||
|
||||
// Request data within the bbox from an external OSM server.
|
||||
function loadFromAPI(box, callback) {
|
||||
loadFromURL(apiURL +
|
||||
loadFromURL(apiURL + 'map?bbox=' +
|
||||
[box[0][0], box[1][1], box[1][0], box[0][1]], callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
iD.Controller = function() {
|
||||
var controller = {},
|
||||
state = null;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
iD.Entity = function () {
|
||||
this.parents = {};
|
||||
this._id = iD.Util.id();
|
||||
this.id = NaN;
|
||||
this.loaded = false;
|
||||
this.entityType = '';
|
||||
this.type = '';
|
||||
this.modified = false;
|
||||
this.deleted = false;
|
||||
};
|
||||
@@ -36,7 +34,7 @@ iD.Entity.prototype = {
|
||||
// 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].entityType === 'way') return true;
|
||||
if (parentObjects[i].type === 'way') return true;
|
||||
}
|
||||
},
|
||||
parentWays: function () {
|
||||
@@ -49,7 +47,7 @@ iD.Entity.prototype = {
|
||||
var poc = [];
|
||||
var parentObjects = this.parentObjects();
|
||||
for (var i = 0; i < parentObjects.length; i++) {
|
||||
if (parentObjects[i].entityType === _class) {
|
||||
if (parentObjects[i].type === _class) {
|
||||
poc.push(parentObjects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
31
js/iD/GeoJSON.js
Normal file
31
js/iD/GeoJSON.js
Normal file
@@ -0,0 +1,31 @@
|
||||
iD.GeoJSON = {
|
||||
mapping: function(entity) {
|
||||
if (this.mappings[entity.type]) {
|
||||
return this.mappings[entity.type](entity);
|
||||
}
|
||||
},
|
||||
mappings: {
|
||||
node: function(entity) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: entity.tags,
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [entity.lon, entity.lat]
|
||||
}
|
||||
};
|
||||
},
|
||||
way: function(entity) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: entity.tags,
|
||||
geometry: {
|
||||
'type': 'LineString',
|
||||
'coordinates': _.map(entity.nodes, function(node) {
|
||||
return [node.lon, node.lat];
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
2
js/iD/Graph.js
Normal file
2
js/iD/Graph.js
Normal file
@@ -0,0 +1,2 @@
|
||||
iD.Graph = function() {
|
||||
};
|
||||
@@ -1,9 +1,7 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
// [Node](http://wiki.openstreetmap.org/wiki/Node)
|
||||
iD.Node = function(id, lat, lon, tags, loaded) {
|
||||
// summary: An OSM node.
|
||||
this.entityType = 'node';
|
||||
this.type = 'node';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
this.entity = new iD.Entity();
|
||||
@@ -18,17 +16,6 @@ iD.Node = function(id, lat, lon, tags, loaded) {
|
||||
};
|
||||
|
||||
iD.Node.prototype = {
|
||||
toGeoJSON: function() {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [this.lon, this.lat]
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
intersects: function(extent) {
|
||||
return (this.lon >= extent[0][0]) &&
|
||||
(this.lon <= extent[1][0]) &&
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
iD.Relation = function(id, members, tags, loaded) {
|
||||
this.entityType = 'relation';
|
||||
this.type = 'relation';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
this.entity = new iD.Entity();
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
// Taginfo service singleton
|
||||
iD.Taginfo = (function() {
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
iD.Util = {};
|
||||
|
||||
iD.Util._id = 0;
|
||||
|
||||
83
js/iD/Way.js
83
js/iD/Way.js
@@ -1,5 +1,3 @@
|
||||
if (typeof iD === 'undefined') iD = {};
|
||||
|
||||
// Way
|
||||
// wiki: http://wiki.openstreetmap.org/wiki/Way
|
||||
//
|
||||
@@ -10,7 +8,7 @@ if (typeof iD === 'undefined') iD = {};
|
||||
// `highway` or `barrier` tag and is not also tagged `area`.
|
||||
iD.Way = function(id, nodes, tags, loaded) {
|
||||
// summary: An OSM way.
|
||||
this.entityType = 'way';
|
||||
this.type = 'way';
|
||||
this.id = id;
|
||||
this._id = iD.Util.id();
|
||||
this.deleted = false;
|
||||
@@ -52,21 +50,8 @@ iD.Way.prototype = {
|
||||
return false; // Boolean
|
||||
},
|
||||
|
||||
toGeoJSON: function() {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
'type': 'LineString',
|
||||
'coordinates': _.map(this.nodes, function(node) {
|
||||
return [node.lon, node.lat];
|
||||
})
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
updateBounds: function() {
|
||||
this._bounds = d3.geo.bounds(this.toGeoJSON());
|
||||
this._bounds = d3.geo.bounds(iD.GeoJSON.mapping(this));
|
||||
},
|
||||
|
||||
bounds: function() {
|
||||
@@ -91,69 +76,5 @@ iD.Way.prototype = {
|
||||
// of the top-left
|
||||
bounds[0][0] > extent[1][0] &&
|
||||
bounds[0][1] > extent[1][1]);
|
||||
},
|
||||
|
||||
// --------------
|
||||
// Action callers
|
||||
|
||||
doAppendNode: function(node, performAction) {
|
||||
// summary: Add a node to the end of the way, using an undo stack.
|
||||
// returns: New length of the way.
|
||||
if (node!=this.getLastNode()) performAction(new iD.actions.AddNodeToWayAction(this, node, this.nodes, -1, true));
|
||||
return this.nodes.length + 1; // int
|
||||
},
|
||||
|
||||
doPrependNode: function(node, performAction) {
|
||||
// summary: Add a node to the start of the way, using an undo stack.
|
||||
// returns: New length of the way.
|
||||
if (node!=this.nodes[0]) performAction(new iD.actions.AddNodeToWayAction(this, node, this.nodes, 0, true));
|
||||
return this.nodes.length + 1; // int
|
||||
},
|
||||
|
||||
doInsertNode:function(index, node, performAction) {
|
||||
// summary: Add a node at a given index within the way, using an undo stack.
|
||||
if (index > 0 && this.nodes[index - 1]==node) return;
|
||||
if (index < this.nodes.length - 1 && this.nodes[index]==node) return;
|
||||
performAction(new iD.actions.AddNodeToWayAction(this, node, this.nodes, index, false));
|
||||
},
|
||||
|
||||
doInsertNodeAtClosestPosition:function(newNode, isSnap, performAction) {
|
||||
// summary: Add a node into whichever segment of the way is nearest, using an undo stack.
|
||||
// isSnap: Boolean Should the node position be snapped to be exactly on the segment?
|
||||
// returns: The index at which the node was inserted.
|
||||
var closestProportion = 1,
|
||||
newIndex = 0,
|
||||
snapped;
|
||||
|
||||
for (var i = 0; i < this.nodes.length - 1; i++) {
|
||||
var node1 = this.nodes[i],
|
||||
node2 = this.nodes[i + 1],
|
||||
directDist = this._pythagoras(node1, node2),
|
||||
viaNewDist = this._pythagoras(node1, newNode) +
|
||||
this._pythagoras(node2, newNode),
|
||||
proportion = Math.abs(viaNewDist/directDist - 1);
|
||||
if (proportion < closestProportion) {
|
||||
newIndex = i+1;
|
||||
closestProportion = proportion;
|
||||
snapped = this._calculateSnappedPoint(node1, node2, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
// splice in new node
|
||||
if (isSnap) { newNode.doSetLonLatp(snapped.x, snapped.y, performAction); }
|
||||
this.doInsertNode(newIndex, newNode, performAction);
|
||||
return newIndex; // int
|
||||
},
|
||||
|
||||
_pythagoras:function(node1, node2) {
|
||||
return (Math.sqrt(Math.pow(node1.lon-node2.lon,2) +
|
||||
Math.pow(node1.latp-node2.latp,2)));
|
||||
},
|
||||
|
||||
_calculateSnappedPoint:function(node1, node2, newNode) {
|
||||
var w = node2.lon - node1.lon;
|
||||
var h = node2.latp - node1.latp;
|
||||
var u = ((newNode.lon-node1.lon) * w + (newNode.latp-node1.latp) * h) / (w*w + h*h);
|
||||
return { x: node1.lon + u*w, y: node1.latp + u*h };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ declare("iD.controller.shape.NoSelection", null, {
|
||||
|
||||
processMouseEvent: function(event, entityUI) {
|
||||
var entity = entityUI ? entityUI.entity : null;
|
||||
var entityType = entity ? entity.entityType : null;
|
||||
var entityType = entity ? entity.type : null;
|
||||
var map = this.controller.map;
|
||||
var connection = map.connection;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ define(['dojo/_base/declare',
|
||||
|
||||
processMouseEvent: function(event, entityUI) {
|
||||
var entity = entityUI ? entityUI.entity : null;
|
||||
var entityType = entity ? entity.entityType : null;
|
||||
var entityType = entity ? entity.type : null;
|
||||
var way;
|
||||
|
||||
if (event.type === 'click') {
|
||||
|
||||
1
js/iD/id.js
Normal file
1
js/iD/id.js
Normal file
@@ -0,0 +1 @@
|
||||
if (typeof iD === 'undefined') var iD = {};
|
||||
@@ -179,13 +179,13 @@ iD.Map = function(obj) {
|
||||
var all = connection.intersects(extent());
|
||||
|
||||
var ways = all.filter(function(a) {
|
||||
return a.entityType === 'way' && !a.isClosed();
|
||||
return a.type === 'way' && !a.isClosed();
|
||||
}).sort(waystack),
|
||||
areas = all.filter(function(a) {
|
||||
return a.entityType === 'way' && a.isClosed();
|
||||
return a.type === 'way' && a.isClosed();
|
||||
}),
|
||||
points = all.filter(function(a) {
|
||||
return a.entityType === 'node';
|
||||
return a.type === 'node';
|
||||
});
|
||||
|
||||
var fills = layers[0].fill.selectAll('path.area')
|
||||
|
||||
@@ -17,7 +17,7 @@ iD.Inspector = function(selection) {
|
||||
head.append('a')
|
||||
.attr('class', 'permalink')
|
||||
.attr('href', 'http://www.openstreetmap.org/browse/' +
|
||||
d.entityType + '/' + d.id)
|
||||
d.type + '/' + d.id)
|
||||
.text('#' + d.id);
|
||||
|
||||
var table = d3.select(this)
|
||||
|
||||
@@ -12,16 +12,21 @@
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="../js/lib/underscore-min.js"></script>
|
||||
<script type="text/javascript" src="../js/lib/d3.v2.min.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/id.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Util.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Node.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Relation.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Entity.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/GeoJSON.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/actions/UndoStack.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/ui/Inspector.js"></script>
|
||||
<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/tiles.js"></script>
|
||||
<script type="text/javascript" src="../js/iD/Graph.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/Util.js"></script>
|
||||
@@ -31,6 +36,8 @@
|
||||
<script type="text/javascript" src="spec/Way.js"></script>
|
||||
<script type="text/javascript" src="spec/Map.js"></script>
|
||||
<script type="text/javascript" src="spec/Connection.js"></script>
|
||||
<script type="text/javascript" src="spec/Graph.js"></script>
|
||||
<script type="text/javascript" src="spec/GeoJSON.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
|
||||
15
test/spec/GeoJSON.js
Normal file
15
test/spec/GeoJSON.js
Normal file
@@ -0,0 +1,15 @@
|
||||
describe('GeoJSON', function() {
|
||||
|
||||
describe('#mapping', function() {
|
||||
it('should be able to map a node to geojson', function() {
|
||||
var node = new iD.Node(10, 38, -77);
|
||||
expect(iD.GeoJSON.mapping(node).geometry.type).toEqual('Point');
|
||||
});
|
||||
it('should be able to map a way to geojson', function() {
|
||||
var way = new iD.Way();
|
||||
var gj = iD.GeoJSON.mapping(way);
|
||||
expect(gj.type).toEqual('Feature');
|
||||
expect(gj.geometry.type).toEqual('LineString');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -14,17 +14,21 @@ describe('Map', function() {
|
||||
foo.parentNode.removeChild(foo);
|
||||
});
|
||||
|
||||
it('can set and get its zoom level', function() {
|
||||
expect(map.setZoom(4)).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
describe('#getZoom', function() {
|
||||
it('accurate reports zoom level', function() {
|
||||
expect(map.setZoom(4)).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
it('can zoom out and in', function() {
|
||||
expect(map.setZoom(4)).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
expect(map.zoomOut()).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(3);
|
||||
expect(map.zoomIn()).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
describe('#zoomIn', function() {
|
||||
it('changes reported zoom level', function() {
|
||||
expect(map.setZoom(4)).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
expect(map.zoomOut()).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(3);
|
||||
expect(map.zoomIn()).toEqual(map);
|
||||
expect(map.getZoom()).toEqual(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,11 +2,11 @@ describe('Node', function() {
|
||||
var node;
|
||||
|
||||
beforeEach(function() {
|
||||
node = new iD.Node(null, 10, 38, -77);
|
||||
node = new iD.Node(10, 38, -77);
|
||||
});
|
||||
|
||||
it('is a node entity', function() {
|
||||
expect(node.entityType).toEqual('node');
|
||||
expect(node.type).toEqual('node');
|
||||
});
|
||||
|
||||
it('should be initialized with a proper ID, lat, and lon', function() {
|
||||
@@ -16,12 +16,6 @@ describe('Node', function() {
|
||||
});
|
||||
|
||||
it('knows if it is within a bounding box', function() {
|
||||
expect(node.within([[-90, 90], [90, -90]])).toBeTruthy();
|
||||
});
|
||||
|
||||
it('can provide geojson', function() {
|
||||
var gj = node.toGeoJSON();
|
||||
expect(gj.type).toEqual('Feature');
|
||||
expect(gj.geometry.type).toEqual('Point');
|
||||
expect(node.intersects([[-90, 90], [90, -90]])).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,15 +7,17 @@ describe('Way', function() {
|
||||
});
|
||||
|
||||
it('is a way', function() {
|
||||
expect(way.entityType).toEqual('way');
|
||||
expect(way.type).toEqual('way');
|
||||
});
|
||||
|
||||
it('has zero nodes by default', function() {
|
||||
expect(way.nodes.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('is closed by default', function() {
|
||||
expect(way.isClosed()).toEqual(true);
|
||||
describe('#isClosed', function() {
|
||||
it('is closed by default', function() {
|
||||
expect(way.isClosed()).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('is a way when it has no nodes', function() {
|
||||
@@ -25,10 +27,4 @@ describe('Way', function() {
|
||||
it('is also an area when it has no nodes', function() {
|
||||
expect(way.isType('area')).toEqual(true);
|
||||
});
|
||||
|
||||
it('can provide geojson', function() {
|
||||
var gj = way.toGeoJSON();
|
||||
expect(gj.type).toEqual('Feature');
|
||||
expect(gj.geometry.type).toEqual('LineString');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user