Files
iD/js/id/geo.js
John Firebaugh 5ea855e18d Replace Graph#fetch with Graph#childNodes
Having two kinds of Ways (fetched and non-fetched)
introduced some accidental complexity. This brings things
more in line with how parentWays/parentRelations work.

Fixes #73.
2013-01-25 15:10:44 -05:00

87 lines
2.4 KiB
JavaScript

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,
graph = map.history().graph(),
nodes = graph.childNodes(way),
projNodes = 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(nodes[idx].loc, 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);
});
};
iD.geo.pathLength = function(path) {
var length = 0,
dx, dy;
for (var i = 0; i < path.length - 1; i++) {
dx = path[i][0] - path[i + 1][0];
dy = path[i][1] - path[i + 1][1];
length += Math.sqrt(dx * dx + dy * dy);
}
return length;
};