mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
iD.util.geo => iD.geo
This commit is contained in:
74
js/id/geo.js
74
js/id/geo.js
@@ -1 +1,75 @@
|
||||
iD.geo = {};
|
||||
|
||||
iD.geo.roundCoords = function(c) {
|
||||
return [Math.floor(c[0]), Math.floor(c[1])];
|
||||
};
|
||||
|
||||
iD.geo.interp = function(p1, p2, t) {
|
||||
return [p1[0] + (p2[0] - p1[0]) * t,
|
||||
p1[1] + (p2[1] - p1[1]) * t];
|
||||
};
|
||||
|
||||
iD.geo.dist = function(a, b) {
|
||||
return Math.sqrt(Math.pow(a[0] - b[0], 2) +
|
||||
Math.pow(a[1] - b[1], 2));
|
||||
};
|
||||
|
||||
iD.geo.chooseIndex = function(way, point, map) {
|
||||
var dist = iD.geo.dist,
|
||||
projNodes = way.nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
});
|
||||
|
||||
for (var i = 0, changes = []; i < projNodes.length - 1; i++) {
|
||||
changes[i] =
|
||||
(dist(projNodes[i], point) + dist(point, projNodes[i + 1])) /
|
||||
dist(projNodes[i], projNodes[i + 1]);
|
||||
}
|
||||
|
||||
var idx = _.indexOf(changes, _.min(changes)),
|
||||
ratio = dist(projNodes[idx], point) / dist(projNodes[idx], projNodes[idx + 1]),
|
||||
loc = iD.geo.interp(way.nodes[idx].loc, way.nodes[idx + 1].loc, ratio);
|
||||
|
||||
return {
|
||||
index: idx + 1,
|
||||
loc: loc
|
||||
};
|
||||
};
|
||||
|
||||
// Return whether point is contained in polygon.
|
||||
//
|
||||
// `point` should be a 2-item array of coordinates.
|
||||
// `polygon` should be an array of 2-item arrays of coordinates.
|
||||
//
|
||||
// From https://github.com/substack/point-in-polygon.
|
||||
// ray-casting algorithm based on
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
//
|
||||
iD.geo.pointInPolygon = function(point, polygon) {
|
||||
var x = point[0],
|
||||
y = point[1],
|
||||
inside = false;
|
||||
|
||||
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
var xi = polygon[i][0], yi = polygon[i][1];
|
||||
var xj = polygon[j][0], yj = polygon[j][1];
|
||||
|
||||
var intersect = ((yi > y) != (yj > y)) &&
|
||||
(x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
|
||||
return inside;
|
||||
};
|
||||
|
||||
iD.geo.polygonContainsPolygon = function(outer, inner) {
|
||||
return _.every(inner, function (point) {
|
||||
return iD.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
iD.geo.polygonIntersectsPolygon = function(outer, inner) {
|
||||
return _.some(inner, function (point) {
|
||||
return iD.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -120,13 +120,13 @@ _.extend(iD.Relation.prototype, {
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = _.pluck(outers[o], 'loc');
|
||||
if (iD.util.geo.polygonContainsPolygon(outer, inner))
|
||||
if (iD.geo.polygonContainsPolygon(outer, inner))
|
||||
return o;
|
||||
}
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = _.pluck(outers[o], 'loc');
|
||||
if (iD.util.geo.polygonIntersectsPolygon(outer, inner))
|
||||
if (iD.geo.polygonIntersectsPolygon(outer, inner))
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ iD.modes.AddLine = function() {
|
||||
|
||||
} else if (datum.type === 'way') {
|
||||
// begin a new way starting from an existing way
|
||||
var choice = iD.util.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
|
||||
var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
history.perform(
|
||||
|
||||
@@ -80,7 +80,7 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
datum.id = datum.way;
|
||||
choice = datum;
|
||||
} else {
|
||||
choice = iD.util.geo.chooseIndex(datum, d3.mouse(surface.node()), map);
|
||||
choice = iD.geo.chooseIndex(datum, d3.mouse(surface.node()), map);
|
||||
}
|
||||
|
||||
history.replace(
|
||||
|
||||
@@ -116,7 +116,7 @@ iD.modes.Select = function(entity, initial) {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity &&
|
||||
(datum.geometry() === 'area' || datum.geometry() === 'line')) {
|
||||
var choice = iD.util.geo.chooseIndex(datum,
|
||||
var choice = iD.geo.chooseIndex(datum,
|
||||
d3.mouse(mode.map.surface.node()), mode.map),
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ iD.Map = function() {
|
||||
map.centerEase = function(loc) {
|
||||
var from = map.center().slice(), t = 0;
|
||||
d3.timer(function() {
|
||||
map.center(iD.util.geo.interp(from, loc, (t += 1) / 10));
|
||||
map.center(iD.geo.interp(from, loc, (t += 1) / 10));
|
||||
return t == 10;
|
||||
}, 20);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
iD.svg = {
|
||||
RoundProjection: function (projection) {
|
||||
return function (d) {
|
||||
return iD.util.geo.roundCoords(projection(d));
|
||||
return iD.geo.roundCoords(projection(d));
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ iD.svg.Midpoints = function(projection) {
|
||||
for (var j = 0; j < entity.nodes.length - 1; j++) {
|
||||
var a = projection(entity.nodes[j].loc);
|
||||
var b = projection(entity.nodes[j + 1].loc);
|
||||
if (iD.util.geo.dist(a, b) > 40) {
|
||||
if (iD.geo.dist(a, b) > 40) {
|
||||
midpoints.push({
|
||||
loc: iD.util.geo.interp(entity.nodes[j].loc, entity.nodes[j + 1].loc, 0.5),
|
||||
loc: iD.geo.interp(entity.nodes[j].loc, entity.nodes[j + 1].loc, 0.5),
|
||||
way: entity.id,
|
||||
index: j + 1,
|
||||
midpoint: true
|
||||
|
||||
@@ -70,79 +70,3 @@ iD.util.prefixCSSProperty = function(property) {
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
iD.util.geo = {};
|
||||
|
||||
iD.util.geo.roundCoords = function(c) {
|
||||
return [Math.floor(c[0]), Math.floor(c[1])];
|
||||
};
|
||||
|
||||
iD.util.geo.interp = function(p1, p2, t) {
|
||||
return [p1[0] + (p2[0] - p1[0]) * t,
|
||||
p1[1] + (p2[1] - p1[1]) * t];
|
||||
};
|
||||
|
||||
iD.util.geo.dist = function(a, b) {
|
||||
return Math.sqrt(Math.pow(a[0] - b[0], 2) +
|
||||
Math.pow(a[1] - b[1], 2));
|
||||
};
|
||||
|
||||
iD.util.geo.chooseIndex = function(way, point, map) {
|
||||
var dist = iD.util.geo.dist,
|
||||
projNodes = way.nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
});
|
||||
|
||||
for (var i = 0, changes = []; i < projNodes.length - 1; i++) {
|
||||
changes[i] =
|
||||
(dist(projNodes[i], point) + dist(point, projNodes[i + 1])) /
|
||||
dist(projNodes[i], projNodes[i + 1]);
|
||||
}
|
||||
|
||||
var idx = _.indexOf(changes, _.min(changes)),
|
||||
ratio = dist(projNodes[idx], point) / dist(projNodes[idx], projNodes[idx + 1]),
|
||||
loc = iD.util.geo.interp(way.nodes[idx].loc, way.nodes[idx + 1].loc, ratio);
|
||||
|
||||
return {
|
||||
index: idx + 1,
|
||||
loc: loc
|
||||
};
|
||||
};
|
||||
|
||||
// Return whether point is contained in polygon.
|
||||
//
|
||||
// `point` should be a 2-item array of coordinates.
|
||||
// `polygon` should be an array of 2-item arrays of coordinates.
|
||||
//
|
||||
// From https://github.com/substack/point-in-polygon.
|
||||
// ray-casting algorithm based on
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
//
|
||||
iD.util.geo.pointInPolygon = function(point, polygon) {
|
||||
var x = point[0],
|
||||
y = point[1],
|
||||
inside = false;
|
||||
|
||||
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
var xi = polygon[i][0], yi = polygon[i][1];
|
||||
var xj = polygon[j][0], yj = polygon[j][1];
|
||||
|
||||
var intersect = ((yi > y) != (yj > y)) &&
|
||||
(x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
|
||||
return inside;
|
||||
};
|
||||
|
||||
iD.util.geo.polygonContainsPolygon = function(outer, inner) {
|
||||
return _.every(inner, function (point) {
|
||||
return iD.util.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
iD.util.geo.polygonIntersectsPolygon = function(outer, inner) {
|
||||
return _.some(inner, function (point) {
|
||||
return iD.util.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -26,21 +26,21 @@ describe('Util', function() {
|
||||
|
||||
describe('geo', function() {
|
||||
describe('#roundCoords', function() {
|
||||
expect(iD.util.geo.roundCoords([0.1, 1])).to.eql([0, 1]);
|
||||
expect(iD.util.geo.roundCoords([0, 1])).to.eql([0, 1]);
|
||||
expect(iD.util.geo.roundCoords([0, 1.1])).to.eql([0, 1]);
|
||||
expect(iD.geo.roundCoords([0.1, 1])).to.eql([0, 1]);
|
||||
expect(iD.geo.roundCoords([0, 1])).to.eql([0, 1]);
|
||||
expect(iD.geo.roundCoords([0, 1.1])).to.eql([0, 1]);
|
||||
});
|
||||
|
||||
describe('#interp', function() {
|
||||
it('interpolates halfway', function() {
|
||||
var a = [0, 0],
|
||||
b = [10, 10];
|
||||
expect(iD.util.geo.interp(a, b, 0.5)).to.eql([5, 5]);
|
||||
expect(iD.geo.interp(a, b, 0.5)).to.eql([5, 5]);
|
||||
});
|
||||
it('interpolates to one side', function() {
|
||||
var a = [0, 0],
|
||||
b = [10, 10];
|
||||
expect(iD.util.geo.interp(a, b, 0)).to.eql([0, 0]);
|
||||
expect(iD.geo.interp(a, b, 0)).to.eql([0, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,17 +48,17 @@ describe('Util', function() {
|
||||
it('distance between two same points is zero', function() {
|
||||
var a = [0, 0],
|
||||
b = [0, 0];
|
||||
expect(iD.util.geo.dist(a, b)).to.eql(0);
|
||||
expect(iD.geo.dist(a, b)).to.eql(0);
|
||||
});
|
||||
it('a straight 10 unit line is 10', function() {
|
||||
var a = [0, 0],
|
||||
b = [10, 0];
|
||||
expect(iD.util.geo.dist(a, b)).to.eql(10);
|
||||
expect(iD.geo.dist(a, b)).to.eql(10);
|
||||
});
|
||||
it('a pythagorean triangle is right', function() {
|
||||
var a = [0, 0],
|
||||
b = [4, 3];
|
||||
expect(iD.util.geo.dist(a, b)).to.eql(5);
|
||||
expect(iD.geo.dist(a, b)).to.eql(5);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('Util', function() {
|
||||
it('says a point in a polygon is on a polygon', function() {
|
||||
var poly = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]];
|
||||
var point = [0.5, 0.5];
|
||||
expect(iD.util.geo.pointInPolygon(point, poly)).to.be.true;
|
||||
expect(iD.geo.pointInPolygon(point, poly)).to.be.true;
|
||||
});
|
||||
it('says a point outside of a polygon is outside', function() {
|
||||
var poly = [
|
||||
@@ -76,7 +76,7 @@ describe('Util', function() {
|
||||
[1, 0],
|
||||
[0, 0]];
|
||||
var point = [0.5, 1.5];
|
||||
expect(iD.util.geo.pointInPolygon(point, poly)).to.be.false;
|
||||
expect(iD.geo.pointInPolygon(point, poly)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -84,12 +84,12 @@ describe('Util', function() {
|
||||
it('says a polygon in a polygon is in', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonContainsPolygon(outer, inner)).to.be.true;
|
||||
expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.true;
|
||||
});
|
||||
it('says a polygon outside of a polygon is out', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[1, 1], [1, 9], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonContainsPolygon(outer, inner)).to.be.false;
|
||||
expect(iD.geo.polygonContainsPolygon(outer, inner)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,19 +97,19 @@ describe('Util', function() {
|
||||
it('says a polygon in a polygon intersects it', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonIntersectsPolygon(outer, inner)).to.be.true;
|
||||
expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true;
|
||||
});
|
||||
|
||||
it('says a polygon that partially intersects does', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[-1, -1], [1, 2], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonIntersectsPolygon(outer, inner)).to.be.true;
|
||||
expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.true;
|
||||
});
|
||||
|
||||
it('says totally disjoint polygons do not intersect', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[-1, -1], [-1, -2], [-2, -2], [-2, -1], [-1, -1]];
|
||||
expect(iD.util.geo.polygonIntersectsPolygon(outer, inner)).to.be.false;
|
||||
expect(iD.geo.polygonIntersectsPolygon(outer, inner)).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user