mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-17 22:24:49 +02:00
Refactor vector math functions from geo.js to vector.js
This commit is contained in:
@@ -10,11 +10,7 @@ import {
|
||||
polygonCentroid as d3_polygonCentroid
|
||||
} from 'd3-polygon';
|
||||
|
||||
import {
|
||||
geoEuclideanDistance,
|
||||
geoInterp
|
||||
} from '../geo';
|
||||
|
||||
import { geoVecInterp, geoVecLength } from '../geo';
|
||||
import { osmNode } from '../osm';
|
||||
|
||||
|
||||
@@ -41,8 +37,8 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
|
||||
centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points),
|
||||
radius = d3_median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
|
||||
centroid = (points.length === 2) ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points),
|
||||
radius = d3_median(points, function(p) { return geoVecLength(centroid, p); }),
|
||||
sign = d3_polygonArea(points) > 0 ? 1 : -1,
|
||||
ids;
|
||||
|
||||
@@ -82,7 +78,7 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
}
|
||||
|
||||
// position this key node
|
||||
var distance = geoEuclideanDistance(centroid, keyPoints[i]);
|
||||
var distance = geoVecLength(centroid, keyPoints[i]);
|
||||
if (distance === 0) { distance = 1e-4; }
|
||||
keyPoints[i] = [
|
||||
centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
|
||||
@@ -91,7 +87,7 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
loc = projection.invert(keyPoints[i]);
|
||||
node = keyNodes[i];
|
||||
origNode = origNodes[node.id];
|
||||
node = node.move(geoInterp(origNode.loc, loc, t));
|
||||
node = node.move(geoVecInterp(origNode.loc, loc, t));
|
||||
graph = graph.replace(node);
|
||||
|
||||
// figure out the between delta angle we want to match to
|
||||
@@ -122,7 +118,7 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
origNode = origNodes[node.id];
|
||||
nearNodes[node.id] = angle;
|
||||
|
||||
node = node.move(geoInterp(origNode.loc, loc, t));
|
||||
node = node.move(geoVecInterp(origNode.loc, loc, t));
|
||||
graph = graph.replace(node);
|
||||
}
|
||||
|
||||
@@ -145,7 +141,7 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
}
|
||||
}
|
||||
|
||||
node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
|
||||
node = osmNode({ loc: geoVecInterp(origNode.loc, loc, t) });
|
||||
graph = graph.replace(node);
|
||||
|
||||
nodes.splice(endNodeIndex + j, 0, node);
|
||||
@@ -220,7 +216,7 @@ export function actionCircularize(wayId, projection, maxAngle) {
|
||||
|
||||
// move interior nodes to the surface of the convex hull..
|
||||
for (var j = 1; j < indexRange; j++) {
|
||||
var point = geoInterp(hull[i], hull[i+1], j / indexRange),
|
||||
var point = geoVecInterp(hull[i], hull[i+1], j / indexRange),
|
||||
node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
|
||||
graph = graph.replace(node);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ import { osmNode } from '../osm';
|
||||
import {
|
||||
geoAngle,
|
||||
geoChooseEdge,
|
||||
geoInterp,
|
||||
geoPathIntersections,
|
||||
geoPathLength,
|
||||
geoSphericalDistance,
|
||||
geoVecAdd,
|
||||
geoVecInterp,
|
||||
geoVecSubtract
|
||||
} from '../geo';
|
||||
|
||||
@@ -206,7 +206,7 @@ export function actionMove(moveIds, tryDelta, projection, cache) {
|
||||
if (!isEP1 && !isEP2) {
|
||||
var epsilon = 1e-4, maxIter = 10;
|
||||
for (var i = 0; i < maxIter; i++) {
|
||||
loc = geoInterp(edge1.loc, edge2.loc, 0.5);
|
||||
loc = geoVecInterp(edge1.loc, edge2.loc, 0.5);
|
||||
edge1 = geoChooseEdge(nodes1, projection(loc), projection);
|
||||
edge2 = geoChooseEdge(nodes2, projection(loc), projection);
|
||||
if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { geoInterp } from '../geo';
|
||||
import { geoVecInterp } from '../geo';
|
||||
|
||||
export function actionMoveNode(nodeID, toLoc) {
|
||||
|
||||
@@ -8,7 +8,7 @@ export function actionMoveNode(nodeID, toLoc) {
|
||||
|
||||
var node = graph.entity(nodeID);
|
||||
return graph.replace(
|
||||
node.move(geoInterp(node.loc, toLoc, t))
|
||||
node.move(geoVecInterp(node.loc, toLoc, t))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,10 +2,7 @@ import _clone from 'lodash-es/clone';
|
||||
import _uniq from 'lodash-es/uniq';
|
||||
|
||||
import { actionDeleteNode } from './delete_node';
|
||||
import {
|
||||
geoEuclideanDistance,
|
||||
geoInterp
|
||||
} from '../geo';
|
||||
import { geoVecInterp, geoVecLength } from '../geo';
|
||||
|
||||
|
||||
/*
|
||||
@@ -40,7 +37,7 @@ export function actionOrthogonalize(wayId, projection) {
|
||||
|
||||
node = graph.entity(nodes[corner.i].id);
|
||||
loc = projection.invert(points[corner.i]);
|
||||
graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
|
||||
graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
|
||||
|
||||
} else {
|
||||
var best,
|
||||
@@ -69,7 +66,7 @@ export function actionOrthogonalize(wayId, projection) {
|
||||
if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
|
||||
loc = projection.invert(points[i]);
|
||||
node = graph.entity(nodes[i].id);
|
||||
graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
|
||||
graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +97,7 @@ export function actionOrthogonalize(wayId, projection) {
|
||||
q = subtractPoints(c, b),
|
||||
scale, dotp;
|
||||
|
||||
scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
|
||||
scale = 2 * Math.min(geoVecLength(p, [0, 0]), geoVecLength(q, [0, 0]));
|
||||
p = normalizePoint(p, 1.0);
|
||||
q = normalizePoint(q, 1.0);
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import {
|
||||
} from 'd3-polygon';
|
||||
|
||||
import {
|
||||
geoEuclideanDistance,
|
||||
geoExtent,
|
||||
geoInterp,
|
||||
geoRotate
|
||||
geoRotate,
|
||||
geoVecInterp,
|
||||
geoVecLength
|
||||
} from '../geo';
|
||||
|
||||
import { utilGetAllNodes } from '../util';
|
||||
@@ -69,7 +69,7 @@ export function actionReflect(reflectIds, projection) {
|
||||
q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
|
||||
p, q;
|
||||
|
||||
var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
|
||||
var isLong = (geoVecLength(p1, q1) > geoVecLength(p2, q2));
|
||||
if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
|
||||
p = p1;
|
||||
q = q1;
|
||||
@@ -92,7 +92,7 @@ export function actionReflect(reflectIds, projection) {
|
||||
b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
|
||||
];
|
||||
var loc2 = projection.invert(c2);
|
||||
node = node.move(geoInterp(node.loc, loc2, t));
|
||||
node = node.move(geoVecInterp(node.loc, loc2, t));
|
||||
graph = graph.replace(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { actionDeleteNode } from './delete_node';
|
||||
|
||||
import {
|
||||
geoEuclideanDistance,
|
||||
geoInterp
|
||||
geoVecInterp,
|
||||
geoVecLength
|
||||
} from '../geo';
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export function actionStraighten(wayId, projection) {
|
||||
],
|
||||
loc2 = projection.invert(p);
|
||||
|
||||
graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
|
||||
graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
|
||||
|
||||
} else {
|
||||
// safe to delete
|
||||
@@ -69,7 +69,7 @@ export function actionStraighten(wayId, projection) {
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
startPoint = points[0],
|
||||
endPoint = points[points.length-1],
|
||||
threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
|
||||
threshold = 0.2 * geoVecLength(startPoint, endPoint),
|
||||
i;
|
||||
|
||||
if (threshold === 0) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { behaviorTail } from './tail';
|
||||
|
||||
import {
|
||||
geoChooseEdge,
|
||||
geoEuclideanDistance,
|
||||
geoVecLength,
|
||||
geoViewportEdge
|
||||
} from '../geo';
|
||||
|
||||
@@ -81,7 +81,7 @@ export function behaviorDraw(context) {
|
||||
d3_select(window).on('mouseup.draw', function() {
|
||||
var t2 = +new Date();
|
||||
var p2 = point();
|
||||
var dist = geoEuclideanDistance(p1, p2);
|
||||
var dist = geoVecLength(p1, p2);
|
||||
|
||||
element.on('mousemove.draw', mousemove);
|
||||
d3_select(window).on('mouseup.draw', null);
|
||||
@@ -157,7 +157,7 @@ export function behaviorDraw(context) {
|
||||
|
||||
var currSpace = context.mouse();
|
||||
if (_disableSpace && _lastSpace) {
|
||||
var dist = geoEuclideanDistance(_lastSpace, currSpace);
|
||||
var dist = geoVecLength(_lastSpace, currSpace);
|
||||
if (dist > tolerance) {
|
||||
_disableSpace = false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
|
||||
import { geoEuclideanDistance } from '../geo';
|
||||
import { geoVecLength } from '../geo';
|
||||
|
||||
import {
|
||||
modeBrowse,
|
||||
@@ -103,7 +103,7 @@ export function behaviorSelect(context) {
|
||||
|
||||
if (!p1) return;
|
||||
var p2 = point();
|
||||
var dist = geoEuclideanDistance(p1, p2);
|
||||
var dist = geoVecLength(p1, p2);
|
||||
|
||||
p1 = null;
|
||||
if (dist > tolerance) {
|
||||
|
||||
+18
-71
@@ -1,6 +1,15 @@
|
||||
import _every from 'lodash-es/every';
|
||||
import _some from 'lodash-es/some';
|
||||
|
||||
import {
|
||||
geoVecAngle,
|
||||
geoVecCross,
|
||||
geoVecDot,
|
||||
geoVecInterp,
|
||||
geoVecLength,
|
||||
geoVecSubtract
|
||||
} from './vector.js';
|
||||
|
||||
|
||||
// constants
|
||||
var TAU = 2 * Math.PI;
|
||||
@@ -8,66 +17,6 @@ var EQUATORIAL_RADIUS = 6356752.314245179;
|
||||
var POLAR_RADIUS = 6378137.0;
|
||||
|
||||
|
||||
// vector addition
|
||||
export function geoVecEquals(a, b) {
|
||||
return (a[0] === b[0]) && (a[1] === b[1]);
|
||||
}
|
||||
|
||||
// vector addition
|
||||
export function geoVecAdd(a, b) {
|
||||
return [ a[0] + b[0], a[1] + b[1] ];
|
||||
}
|
||||
|
||||
// vector subtraction
|
||||
export function geoVecSubtract(a, b) {
|
||||
return [ a[0] - b[0], a[1] - b[1] ];
|
||||
}
|
||||
|
||||
// vector multiplication
|
||||
export function geoVecScale(a, b) {
|
||||
return [ a[0] * b, a[1] * b ];
|
||||
}
|
||||
|
||||
// vector rounding (was: geoRoundCoordinates)
|
||||
export function geoVecFloor(a) {
|
||||
return [ Math.floor(a[0]), Math.floor(a[1]) ];
|
||||
}
|
||||
|
||||
// linear interpolation
|
||||
export function geoInterp(p1, p2, t) {
|
||||
return [
|
||||
p1[0] + (p2[0] - p1[0]) * t,
|
||||
p1[1] + (p2[1] - p1[1]) * t
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// dot product
|
||||
export function geoDot(a, b, origin) {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[0] - origin[0]) +
|
||||
(a[1] - origin[1]) * (b[1] - origin[1]);
|
||||
}
|
||||
|
||||
|
||||
// 2D cross product of OA and OB vectors, returns magnitude of Z vector
|
||||
// Returns a positive value, if OAB makes a counter-clockwise turn,
|
||||
// negative for clockwise turn, and zero if the points are collinear.
|
||||
export function geoCross(a, b, origin) {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[1] - origin[1]) -
|
||||
(a[1] - origin[1]) * (b[0] - origin[0]);
|
||||
}
|
||||
|
||||
|
||||
// http://jsperf.com/id-dist-optimization
|
||||
export function geoEuclideanDistance(a, b) {
|
||||
var x = a[0] - b[0];
|
||||
var y = a[1] - b[1];
|
||||
return Math.sqrt((x * x) + (y * y));
|
||||
}
|
||||
|
||||
|
||||
export function geoLatToMeters(dLat) {
|
||||
return dLat * (TAU * POLAR_RADIUS / 360);
|
||||
}
|
||||
@@ -140,9 +89,7 @@ export function geoEdgeEqual(a, b) {
|
||||
// Return the counterclockwise angle in the range (-pi, pi)
|
||||
// between the positive X axis and the line intersecting a and b.
|
||||
export function geoAngle(a, b, projection) {
|
||||
a = projection(a.loc);
|
||||
b = projection(b.loc);
|
||||
return Math.atan2(b[1] - a[1], b[0] - a[0]);
|
||||
return geoVecAngle(projection(a.loc), projection(b.loc));
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +110,7 @@ export function geoRotate(points, angle, around) {
|
||||
// the closest vertex on that edge. Returns an object with the `index` of the
|
||||
// chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
|
||||
export function geoChooseEdge(nodes, point, projection, skipID) {
|
||||
var dist = geoEuclideanDistance;
|
||||
var dist = geoVecLength;
|
||||
var points = nodes.map(function(n) { return projection(n.loc); });
|
||||
var ids = nodes.map(function(n) { return n.id; });
|
||||
var min = Infinity;
|
||||
@@ -176,7 +123,7 @@ export function geoChooseEdge(nodes, point, projection, skipID) {
|
||||
var o = points[i];
|
||||
var s = geoVecSubtract(points[i + 1], o);
|
||||
var v = geoVecSubtract(point, o);
|
||||
var proj = geoDot(v, s) / geoDot(s, s);
|
||||
var proj = geoVecDot(v, s) / geoVecDot(s, s);
|
||||
var p;
|
||||
|
||||
if (proj < 0) {
|
||||
@@ -214,15 +161,15 @@ export function geoLineIntersection(a, b) {
|
||||
var q2 = [b[1][0], b[1][1]];
|
||||
var r = geoVecSubtract(p2, p);
|
||||
var s = geoVecSubtract(q2, q);
|
||||
var uNumerator = geoCross(geoVecSubtract(q, p), r);
|
||||
var denominator = geoCross(r, s);
|
||||
var uNumerator = geoVecCross(geoVecSubtract(q, p), r);
|
||||
var denominator = geoVecCross(r, s);
|
||||
|
||||
if (uNumerator && denominator) {
|
||||
var u = uNumerator / denominator;
|
||||
var t = geoCross(geoVecSubtract(q, p), s) / denominator;
|
||||
var t = geoVecCross(geoVecSubtract(q, p), s) / denominator;
|
||||
|
||||
if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
|
||||
return geoInterp(p, p2, t);
|
||||
return geoVecInterp(p, p2, t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +231,7 @@ export function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
|
||||
function testSegments(outer, inner) {
|
||||
for (var i = 0; i < outer.length - 1; i++) {
|
||||
for (var j = 0; j < inner.length - 1; j++) {
|
||||
var a = [ outer[i], outer[i +1 ] ];
|
||||
var a = [ outer[i], outer[i + 1] ];
|
||||
var b = [ inner[j], inner[j + 1] ];
|
||||
if (geoLineIntersection(a, b)) return true;
|
||||
}
|
||||
@@ -305,7 +252,7 @@ export function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
|
||||
export function geoPathLength(path) {
|
||||
var length = 0;
|
||||
for (var i = 0; i < path.length - 1; i++) {
|
||||
length += geoEuclideanDistance(path[i], path[i + 1]);
|
||||
length += geoVecLength(path[i], path[i + 1]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,11 +1,7 @@
|
||||
export { geoAngle } from './geo.js';
|
||||
export { geoChooseEdge } from './geo.js';
|
||||
export { geoCross } from './geo.js';
|
||||
export { geoDot } from './geo.js';
|
||||
export { geoEdgeEqual } from './geo.js';
|
||||
export { geoEuclideanDistance } from './geo.js';
|
||||
export { geoExtent } from './extent.js';
|
||||
export { geoInterp } from './geo.js';
|
||||
export { geoRawMercator } from './raw_mercator.js';
|
||||
export { geoRotate } from './geo.js';
|
||||
export { geoLatToMeters } from './geo.js';
|
||||
@@ -22,10 +18,15 @@ export { geoPolygonContainsPolygon } from './geo.js';
|
||||
export { geoPolygonIntersectsPolygon } from './geo.js';
|
||||
export { geoScaleToZoom } from './geo.js';
|
||||
export { geoSphericalDistance } from './geo.js';
|
||||
export { geoVecAdd } from './geo.js';
|
||||
export { geoVecEquals } from './geo.js';
|
||||
export { geoVecFloor } from './geo.js';
|
||||
export { geoVecSubtract } from './geo.js';
|
||||
export { geoVecScale } from './geo.js';
|
||||
export { geoVecAdd } from './vector.js';
|
||||
export { geoVecAngle } from './vector.js';
|
||||
export { geoVecCross } from './vector.js';
|
||||
export { geoVecDot } from './vector.js';
|
||||
export { geoVecEqual } from './vector.js';
|
||||
export { geoVecFloor } from './vector.js';
|
||||
export { geoVecInterp } from './vector.js';
|
||||
export { geoVecLength } from './vector.js';
|
||||
export { geoVecSubtract } from './vector.js';
|
||||
export { geoVecScale } from './vector.js';
|
||||
export { geoZoomToScale } from './geo.js';
|
||||
export { geoViewportEdge } from './geo.js';
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// vector equals
|
||||
export function geoVecEqual(a, b) {
|
||||
return (a[0] === b[0]) && (a[1] === b[1]);
|
||||
}
|
||||
|
||||
// vector addition
|
||||
export function geoVecAdd(a, b) {
|
||||
return [ a[0] + b[0], a[1] + b[1] ];
|
||||
}
|
||||
|
||||
// vector subtraction
|
||||
export function geoVecSubtract(a, b) {
|
||||
return [ a[0] - b[0], a[1] - b[1] ];
|
||||
}
|
||||
|
||||
// vector multiplication
|
||||
export function geoVecScale(a, b) {
|
||||
return [ a[0] * b, a[1] * b ];
|
||||
}
|
||||
|
||||
// vector rounding (was: geoRoundCoordinates)
|
||||
export function geoVecFloor(a) {
|
||||
return [ Math.floor(a[0]), Math.floor(a[1]) ];
|
||||
}
|
||||
|
||||
// linear interpolation
|
||||
export function geoVecInterp(a, b, t) {
|
||||
return [
|
||||
a[0] + (b[0] - a[0]) * t,
|
||||
a[1] + (b[1] - a[1]) * t
|
||||
];
|
||||
}
|
||||
|
||||
// http://jsperf.com/id-dist-optimization
|
||||
export function geoVecLength(a, b) {
|
||||
var x = a[0] - b[0];
|
||||
var y = a[1] - b[1];
|
||||
return Math.sqrt((x * x) + (y * y));
|
||||
}
|
||||
|
||||
// Return the counterclockwise angle in the range (-pi, pi)
|
||||
// between the positive X axis and the line intersecting a and b.
|
||||
export function geoVecAngle(a, b) {
|
||||
return Math.atan2(b[1] - a[1], b[0] - a[0]);
|
||||
}
|
||||
|
||||
// dot product
|
||||
export function geoVecDot(a, b, origin) {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[0] - origin[0]) +
|
||||
(a[1] - origin[1]) * (b[1] - origin[1]);
|
||||
}
|
||||
|
||||
// 2D cross product of OA and OB vectors, returns magnitude of Z vector
|
||||
// Returns a positive value, if OAB makes a counter-clockwise turn,
|
||||
// negative for clockwise turn, and zero if the points are collinear.
|
||||
export function geoVecCross(a, b, origin) {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[1] - origin[1]) -
|
||||
(a[1] - origin[1]) * (b[0] - origin[0]);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ export { coreDifference as Difference } from './core/difference';
|
||||
export { coreGraph as Graph } from './core/graph';
|
||||
export { coreHistory as History } from './core/history';
|
||||
export { coreTree as Tree } from './core/tree';
|
||||
export { geoVecCross as geoCross } from './geo/vector';
|
||||
export { geoVecInterp as geoInterp } from './geo/vector';
|
||||
export { geoVecFloor as geoRoundCoordinates } from './geo/vector';
|
||||
export { geoVecLength as geoEuclideanDistance } from './geo/vector';
|
||||
export { osmEntity as Entity } from './osm/entity';
|
||||
export { osmNode as Node } from './osm/node';
|
||||
export { osmRelation as Relation } from './osm/relation';
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import {
|
||||
geoChooseEdge,
|
||||
geoLineIntersection,
|
||||
geoVecEquals,
|
||||
geoVecEqual,
|
||||
geoVecSubtract,
|
||||
geoViewportEdge
|
||||
} from '../geo';
|
||||
@@ -203,8 +203,8 @@ export function modeDragNode(context) {
|
||||
var p = actives[j];
|
||||
var q = inactives[k];
|
||||
// skip if segments share an endpoint
|
||||
if (geoVecEquals(p[1], q[0]) || geoVecEquals(p[0], q[1]) ||
|
||||
geoVecEquals(p[0], q[0]) || geoVecEquals(p[1], q[1]) ) {
|
||||
if (geoVecEqual(p[1], q[0]) || geoVecEqual(p[0], q[1]) ||
|
||||
geoVecEqual(p[0], q[0]) || geoVecEqual(p[1], q[1]) ) {
|
||||
continue;
|
||||
} else if (geoLineIntersection(p, q)) {
|
||||
return true;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js';
|
||||
import { t } from '../util/locale';
|
||||
import { actionRotate } from '../actions';
|
||||
import { behaviorEdit } from '../behavior';
|
||||
import { geoInterp } from '../geo';
|
||||
import { geoVecInterp } from '../geo';
|
||||
|
||||
import {
|
||||
modeBrowse,
|
||||
@@ -80,7 +80,7 @@ export function modeRotate(context, entityIDs) {
|
||||
if (points.length === 1) { // degenerate case
|
||||
_pivot = points[0];
|
||||
} else if (points.length === 2) {
|
||||
_pivot = geoInterp(points[0], points[1], 0.5);
|
||||
_pivot = geoVecInterp(points[0], points[1], 0.5);
|
||||
} else {
|
||||
_pivot = d3_polygonCentroid(d3_polygonHull(points));
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import _uniq from 'lodash-es/uniq';
|
||||
|
||||
import { geoArea as d3_geoArea } from 'd3-geo';
|
||||
|
||||
import { geoExtent, geoCross } from '../geo';
|
||||
import { geoExtent, geoVecCross } from '../geo';
|
||||
import { osmEntity } from './entity';
|
||||
import { osmLanes } from './lanes';
|
||||
import { osmOneWayTags } from './tags';
|
||||
@@ -142,7 +142,7 @@ _extend(osmWay.prototype, {
|
||||
var o = coords[(i+1) % coords.length];
|
||||
var a = coords[i];
|
||||
var b = coords[(i+2) % coords.length];
|
||||
var res = geoCross(a, b, o);
|
||||
var res = geoVecCross(a, b, o);
|
||||
|
||||
curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
|
||||
if (curr === 0) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { select as d3_select } from 'd3-selection';
|
||||
import { t } from '../util/locale';
|
||||
|
||||
import { d3geoTile as d3_geoTile } from '../lib/d3.geo.tile';
|
||||
import { geoEuclideanDistance, geoScaleToZoom } from '../geo';
|
||||
import { geoScaleToZoom, geoVecLength } from '../geo';
|
||||
import { utilPrefixCSSProperty } from '../util';
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ export function rendererTileLayer(context) {
|
||||
|
||||
requests.forEach(function(d) {
|
||||
var c = tileCenter(d);
|
||||
var dist = geoEuclideanDistance(c, mapCenter);
|
||||
var dist = geoVecLength(c, mapCenter);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
nearCenter = d;
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
geoStream as d3_geoStream
|
||||
} from 'd3-geo';
|
||||
|
||||
import { geoEuclideanDistance } from '../geo';
|
||||
import { geoVecLength } from '../geo';
|
||||
|
||||
|
||||
// Touch targets control which other vertices we can drag a vertex onto.
|
||||
@@ -82,7 +82,7 @@ export function svgOneWaySegments(projection, graph, dt) {
|
||||
b = [x, y];
|
||||
|
||||
if (a) {
|
||||
var span = geoEuclideanDistance(a, b) - offset;
|
||||
var span = geoVecLength(a, b) - offset;
|
||||
|
||||
if (span >= 0) {
|
||||
var angle = Math.atan2(b[1] - a[1], b[0] - a[0]);
|
||||
|
||||
@@ -10,11 +10,11 @@ import { textDirection } from '../util/locale';
|
||||
|
||||
import {
|
||||
geoExtent,
|
||||
geoEuclideanDistance,
|
||||
geoInterp,
|
||||
geoPolygonIntersectsPolygon,
|
||||
geoPathLength,
|
||||
geoScaleToZoom
|
||||
geoScaleToZoom,
|
||||
geoVecInterp,
|
||||
geoVecLength
|
||||
} from '../geo';
|
||||
|
||||
import { osmEntity } from '../osm';
|
||||
@@ -489,10 +489,10 @@ export function svgLabels(projection, context) {
|
||||
var b = sub[j + 1];
|
||||
|
||||
// split up the text into small collision boxes
|
||||
var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
|
||||
var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2));
|
||||
|
||||
for (var box = 0; box < num; box++) {
|
||||
var p = geoInterp(a, b, box / num);
|
||||
var p = geoVecInterp(a, b, box / num);
|
||||
var x0 = p[0] - boxsize - padding;
|
||||
var y0 = p[1] - boxsize - padding;
|
||||
var x1 = p[0] + boxsize + padding;
|
||||
@@ -532,7 +532,7 @@ export function svgLabels(projection, context) {
|
||||
for (var i = 0; i < points.length - 1; i++) {
|
||||
var a = points[i];
|
||||
var b = points[i + 1];
|
||||
var current = geoEuclideanDistance(a, b);
|
||||
var current = geoVecLength(a, b);
|
||||
var portion;
|
||||
if (!start && sofar + current >= from) {
|
||||
portion = (from - sofar) / current;
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
|
||||
import {
|
||||
geoAngle,
|
||||
geoEuclideanDistance,
|
||||
geoInterp,
|
||||
geoLineIntersection
|
||||
geoLineIntersection,
|
||||
geoVecInterp,
|
||||
geoVecLength
|
||||
} from '../geo';
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ export function svgMidpoints(projection, context) {
|
||||
if (midpoints[id]) {
|
||||
midpoints[id].parents.push(entity);
|
||||
} else {
|
||||
if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
|
||||
var point = geoInterp(a.loc, b.loc, 0.5);
|
||||
if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) {
|
||||
var point = geoVecInterp(a.loc, b.loc, 0.5);
|
||||
var loc = null;
|
||||
|
||||
if (extent.intersects(point)) {
|
||||
@@ -83,8 +83,8 @@ export function svgMidpoints(projection, context) {
|
||||
for (var k = 0; k < 4; k++) {
|
||||
point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
|
||||
if (point &&
|
||||
geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
|
||||
geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
|
||||
geoVecLength(projection(a.loc), projection(point)) > 20 &&
|
||||
geoVecLength(projection(b.loc), projection(point)) > 20)
|
||||
{
|
||||
loc = point;
|
||||
break;
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
|
||||
<script src='spec/geo/extent.js'></script>
|
||||
<script src='spec/geo/geo.js'></script>
|
||||
<script src='spec/geo/vector.js'></script>
|
||||
|
||||
<script src='spec/lib/d3.combobox.js'></script>
|
||||
<script src='spec/lib/d3.keybinding.js'></script>
|
||||
|
||||
@@ -5,7 +5,7 @@ describe('iD.actionCircularize', function () {
|
||||
var points = graph.childNodes(graph.entity(id))
|
||||
.map(function (n) { return projection(n.loc); }),
|
||||
centroid = d3.polygonCentroid(points),
|
||||
radius = iD.geoEuclideanDistance(centroid, points[0]),
|
||||
radius = iD.geoVecLength(centroid, points[0]),
|
||||
estArea = Math.PI * radius * radius,
|
||||
trueArea = Math.abs(d3.polygonArea(points)),
|
||||
pctDiff = (estArea - trueArea) / estArea;
|
||||
@@ -31,10 +31,10 @@ describe('iD.actionCircularize', function () {
|
||||
vector2 = [point2[0] - center[0], point2[1] - center[1]],
|
||||
distance;
|
||||
|
||||
distance = iD.geoEuclideanDistance(vector1, [0, 0]);
|
||||
distance = iD.geoVecLength(vector1, [0, 0]);
|
||||
vector1 = [vector1[0] / distance, vector1[1] / distance];
|
||||
|
||||
distance = iD.geoEuclideanDistance(vector2, [0, 0]);
|
||||
distance = iD.geoVecLength(vector2, [0, 0]);
|
||||
vector2 = [vector2[0] / distance, vector2[1] / distance];
|
||||
|
||||
return 180 / Math.PI * Math.acos(vector1[0] * vector2[0] + vector1[1] * vector2[1]);
|
||||
@@ -106,7 +106,7 @@ describe('iD.actionCircularize', function () {
|
||||
graph = iD.actionCircularize('-', projection)(graph);
|
||||
|
||||
expect(isCircular('-', graph)).to.be.ok;
|
||||
expect(iD.geoEuclideanDistance(graph.entity('d').loc, [2, -2])).to.be.lt(0.5);
|
||||
expect(iD.geoVecLength(graph.entity('d').loc, [2, -2])).to.be.lt(0.5);
|
||||
});
|
||||
|
||||
it('creates circle respecting min-angle limit', function() {
|
||||
|
||||
@@ -1,108 +1,5 @@
|
||||
describe('iD.geo', function() {
|
||||
|
||||
describe('geoVecEquals', function() {
|
||||
it('tests vectors for equality', function() {
|
||||
expect(iD.geoVecEquals([1, 2], [1, 2])).to.be.true;
|
||||
expect(iD.geoVecEquals([1, 2], [1, 0])).to.be.false;
|
||||
expect(iD.geoVecEquals([1, 2], [2, 1])).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecAdd', function() {
|
||||
it('adds vectors', function() {
|
||||
expect(iD.geoVecAdd([1, 2], [3, 4])).to.eql([4, 6]);
|
||||
expect(iD.geoVecAdd([1, 2], [0, 0])).to.eql([1, 2]);
|
||||
expect(iD.geoVecAdd([1, 2], [-3, -4])).to.eql([-2, -2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecSubtract', function() {
|
||||
it('subtracts vectors', function() {
|
||||
expect(iD.geoVecSubtract([1, 2], [3, 4])).to.eql([-2, -2]);
|
||||
expect(iD.geoVecSubtract([1, 2], [0, 0])).to.eql([1, 2]);
|
||||
expect(iD.geoVecSubtract([1, 2], [-3, -4])).to.eql([4, 6]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecScale', function() {
|
||||
it('multiplies vectors', function() {
|
||||
expect(iD.geoVecScale([1, 2], 0)).to.eql([0, 0]);
|
||||
expect(iD.geoVecScale([1, 2], 1)).to.eql([1, 2]);
|
||||
expect(iD.geoVecScale([1, 2], 2)).to.eql([2, 4]);
|
||||
expect(iD.geoVecScale([1, 2], 0.5)).to.eql([0.5, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecFloor (was: geoRoundCoordinates)', function() {
|
||||
it('rounds vectors', function() {
|
||||
expect(iD.geoVecFloor([0.1, 1])).to.eql([0, 1]);
|
||||
expect(iD.geoVecFloor([0, 1])).to.eql([0, 1]);
|
||||
expect(iD.geoVecFloor([0, 1.1])).to.eql([0, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoInterp', function() {
|
||||
it('interpolates halfway', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 10];
|
||||
expect(iD.geoInterp(a, b, 0.5)).to.eql([5, 5]);
|
||||
});
|
||||
it('interpolates to one side', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 10];
|
||||
expect(iD.geoInterp(a, b, 0)).to.eql([0, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoDot', function() {
|
||||
it('dot product of right angle is zero', function() {
|
||||
var a = [1, 0];
|
||||
var b = [0, 1];
|
||||
expect(iD.geoDot(a, b)).to.eql(0);
|
||||
});
|
||||
it('dot product of same vector multiplies', function() {
|
||||
var a = [2, 0];
|
||||
var b = [2, 0];
|
||||
expect(iD.geoDot(a, b)).to.eql(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoCross', function() {
|
||||
it('2D cross product of right hand turn is positive', function() {
|
||||
var a = [2, 0];
|
||||
var b = [0, 2];
|
||||
expect(iD.geoCross(a, b)).to.eql(4);
|
||||
});
|
||||
it('2D cross product of left hand turn is negative', function() {
|
||||
var a = [2, 0];
|
||||
var b = [0, -2];
|
||||
expect(iD.geoCross(a, b)).to.eql(-4);
|
||||
});
|
||||
it('2D cross product of colinear points is zero', function() {
|
||||
var a = [-2, 0];
|
||||
var b = [2, 0];
|
||||
expect(iD.geoCross(a, b)).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoEuclideanDistance', function() {
|
||||
it('distance between two same points is zero', function() {
|
||||
var a = [0, 0];
|
||||
var b = [0, 0];
|
||||
expect(iD.geoEuclideanDistance(a, b)).to.eql(0);
|
||||
});
|
||||
it('a straight 10 unit line is 10', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 0];
|
||||
expect(iD.geoEuclideanDistance(a, b)).to.eql(10);
|
||||
});
|
||||
it('a pythagorean triangle is right', function() {
|
||||
var a = [0, 0];
|
||||
var b = [4, 3];
|
||||
expect(iD.geoEuclideanDistance(a, b)).to.eql(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoLatToMeters', function() {
|
||||
it('0 degrees latitude is 0 meters', function() {
|
||||
expect(iD.geoLatToMeters(0)).to.eql(0);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
describe('iD.geo vector', function() {
|
||||
|
||||
describe('geoVecEqual', function() {
|
||||
it('tests vectors for equality', function() {
|
||||
expect(iD.geoVecEqual([1, 2], [1, 2])).to.be.true;
|
||||
expect(iD.geoVecEqual([1, 2], [1, 0])).to.be.false;
|
||||
expect(iD.geoVecEqual([1, 2], [2, 1])).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecAdd', function() {
|
||||
it('adds vectors', function() {
|
||||
expect(iD.geoVecAdd([1, 2], [3, 4])).to.eql([4, 6]);
|
||||
expect(iD.geoVecAdd([1, 2], [0, 0])).to.eql([1, 2]);
|
||||
expect(iD.geoVecAdd([1, 2], [-3, -4])).to.eql([-2, -2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecSubtract', function() {
|
||||
it('subtracts vectors', function() {
|
||||
expect(iD.geoVecSubtract([1, 2], [3, 4])).to.eql([-2, -2]);
|
||||
expect(iD.geoVecSubtract([1, 2], [0, 0])).to.eql([1, 2]);
|
||||
expect(iD.geoVecSubtract([1, 2], [-3, -4])).to.eql([4, 6]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecScale', function() {
|
||||
it('multiplies vectors', function() {
|
||||
expect(iD.geoVecScale([1, 2], 0)).to.eql([0, 0]);
|
||||
expect(iD.geoVecScale([1, 2], 1)).to.eql([1, 2]);
|
||||
expect(iD.geoVecScale([1, 2], 2)).to.eql([2, 4]);
|
||||
expect(iD.geoVecScale([1, 2], 0.5)).to.eql([0.5, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecFloor (was: geoRoundCoordinates)', function() {
|
||||
it('rounds vectors', function() {
|
||||
expect(iD.geoVecFloor([0.1, 1])).to.eql([0, 1]);
|
||||
expect(iD.geoVecFloor([0, 1])).to.eql([0, 1]);
|
||||
expect(iD.geoVecFloor([0, 1.1])).to.eql([0, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecInterp', function() {
|
||||
it('interpolates halfway', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 10];
|
||||
expect(iD.geoVecInterp(a, b, 0.5)).to.eql([5, 5]);
|
||||
});
|
||||
it('interpolates to one side', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 10];
|
||||
expect(iD.geoVecInterp(a, b, 0)).to.eql([0, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecLength (was: geoEuclideanDistance)', function() {
|
||||
it('distance between two same points is zero', function() {
|
||||
var a = [0, 0];
|
||||
var b = [0, 0];
|
||||
expect(iD.geoVecLength(a, b)).to.eql(0);
|
||||
});
|
||||
it('a straight 10 unit line is 10', function() {
|
||||
var a = [0, 0];
|
||||
var b = [10, 0];
|
||||
expect(iD.geoVecLength(a, b)).to.eql(10);
|
||||
});
|
||||
it('a pythagorean triangle is right', function() {
|
||||
var a = [0, 0];
|
||||
var b = [4, 3];
|
||||
expect(iD.geoVecLength(a, b)).to.eql(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecAngle', function() {
|
||||
it('returns angle between a and b', function() {
|
||||
expect(iD.geoVecAngle([0, 0], [1, 0])).to.be.closeTo(0, 1e-6);
|
||||
expect(iD.geoVecAngle([0, 0], [0, 1])).to.be.closeTo(Math.PI / 2, 1e-6);
|
||||
expect(iD.geoVecAngle([0, 0], [-1, 0])).to.be.closeTo(Math.PI, 1e-6);
|
||||
expect(iD.geoVecAngle([0, 0], [0, -1])).to.be.closeTo(-Math.PI / 2, 1e-6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecDot', function() {
|
||||
it('dot product of right angle is zero', function() {
|
||||
var a = [1, 0];
|
||||
var b = [0, 1];
|
||||
expect(iD.geoVecDot(a, b)).to.eql(0);
|
||||
});
|
||||
it('dot product of same vector multiplies', function() {
|
||||
var a = [2, 0];
|
||||
var b = [2, 0];
|
||||
expect(iD.geoVecDot(a, b)).to.eql(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoVecCross', function() {
|
||||
it('2D cross product of right hand turn is positive', function() {
|
||||
var a = [2, 0];
|
||||
var b = [0, 2];
|
||||
expect(iD.geoVecCross(a, b)).to.eql(4);
|
||||
});
|
||||
it('2D cross product of left hand turn is negative', function() {
|
||||
var a = [2, 0];
|
||||
var b = [0, -2];
|
||||
expect(iD.geoVecCross(a, b)).to.eql(-4);
|
||||
});
|
||||
it('2D cross product of colinear points is zero', function() {
|
||||
var a = [-2, 0];
|
||||
var b = [2, 0];
|
||||
expect(iD.geoVecCross(a, b)).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user