mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-25 15:05:32 +00:00
iD.geo.euclideanDistance should only be used for calculations of projected coordinates or display (pixel) coordinates. iD.geo.sphericalDistance calculates approximate geographical distances, accounting for distortions at higher latitudes. This can be used for determining the nearest node (operations.Delete, actions.Circularize) or relative length comparisons (actions.Split).
206 lines
7.5 KiB
JavaScript
206 lines
7.5 KiB
JavaScript
describe('iD.geo', function() {
|
|
describe('.roundCoords', function() {
|
|
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.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.geo.interp(a, b, 0)).to.eql([0, 0]);
|
|
});
|
|
});
|
|
|
|
describe('.euclideanDistance', function() {
|
|
it('distance between two same points is zero', function() {
|
|
var a = [0, 0],
|
|
b = [0, 0];
|
|
expect(iD.geo.euclideanDistance(a, b)).to.eql(0);
|
|
});
|
|
it('a straight 10 unit line is 10', function() {
|
|
var a = [0, 0],
|
|
b = [10, 0];
|
|
expect(iD.geo.euclideanDistance(a, b)).to.eql(10);
|
|
});
|
|
it('a pythagorean triangle is right', function() {
|
|
var a = [0, 0],
|
|
b = [4, 3];
|
|
expect(iD.geo.euclideanDistance(a, b)).to.eql(5);
|
|
});
|
|
});
|
|
|
|
describe('.sphericalDistance', function() {
|
|
it('distance between two same points is zero', function() {
|
|
var a = [0, 0],
|
|
b = [0, 0];
|
|
expect(iD.geo.sphericalDistance(a, b)).to.eql(0);
|
|
});
|
|
it('a straight 1 degree line at the equator is aproximately 111 km', function() {
|
|
var a = [0, 0],
|
|
b = [1, 0];
|
|
expect(iD.geo.sphericalDistance(a, b)).to.be.within(100E3,120E3);
|
|
});
|
|
it('a pythagorean triangle is right', function() {
|
|
var a = [0, 0],
|
|
b = [4, 3];
|
|
expect(iD.geo.sphericalDistance(a, b)).to.be.within(500E3,600E3);
|
|
});
|
|
it('east-west distances at high latitude are shorter', function() {
|
|
var a = [0, 60],
|
|
b = [1, 60];
|
|
expect(iD.geo.sphericalDistance(a, b)).to.be.within(50E3,60E3);
|
|
});
|
|
it('north-south distances at high latitude are not shorter', function() {
|
|
var a = [0, 60],
|
|
b = [0, 61];
|
|
expect(iD.geo.sphericalDistance(a, b)).to.be.within(100E3,120E3);
|
|
});
|
|
});
|
|
|
|
describe('.chooseEdge', function() {
|
|
var projection = function (l) { return l; };
|
|
projection.invert = projection;
|
|
|
|
it('returns undefined properties for a degenerate way (no nodes)', function() {
|
|
expect(iD.geo.chooseEdge([], [0, 0], projection)).to.eql({
|
|
index: undefined,
|
|
distance: Infinity,
|
|
loc: undefined
|
|
})
|
|
});
|
|
|
|
it('returns undefined properties for a degenerate way (single node)', function() {
|
|
expect(iD.geo.chooseEdge([iD.Node({loc: [0, 0]})], [0, 0], projection)).to.eql({
|
|
index: undefined,
|
|
distance: Infinity,
|
|
loc: undefined
|
|
})
|
|
});
|
|
|
|
it('calculates the orthogonal projection of a point onto a segment', function() {
|
|
// a --*--- b
|
|
// |
|
|
// c
|
|
//
|
|
// * = [2, 0]
|
|
var a = [0, 0],
|
|
b = [5, 0],
|
|
c = [2, 1],
|
|
nodes = [
|
|
iD.Node({loc: a}),
|
|
iD.Node({loc: b})
|
|
];
|
|
|
|
var choice = iD.geo.chooseEdge(nodes, c, projection);
|
|
expect(choice.index).to.eql(1);
|
|
expect(choice.distance).to.eql(1);
|
|
expect(choice.loc).to.eql([2, 0]);
|
|
});
|
|
|
|
it('returns the starting vertex when the orthogonal projection is < 0', function() {
|
|
var a = [0, 0],
|
|
b = [5, 0],
|
|
c = [-3, 4],
|
|
nodes = [
|
|
iD.Node({loc: a}),
|
|
iD.Node({loc: b})
|
|
];
|
|
|
|
var choice = iD.geo.chooseEdge(nodes, c, projection);
|
|
expect(choice.index).to.eql(1);
|
|
expect(choice.distance).to.eql(5);
|
|
expect(choice.loc).to.eql([0, 0]);
|
|
});
|
|
|
|
it('returns the ending vertex when the orthogonal projection is > 1', function() {
|
|
var a = [0, 0],
|
|
b = [5, 0],
|
|
c = [8, 4],
|
|
nodes = [
|
|
iD.Node({loc: a}),
|
|
iD.Node({loc: b})
|
|
];
|
|
|
|
var choice = iD.geo.chooseEdge(nodes, c, projection);
|
|
expect(choice.index).to.eql(1);
|
|
expect(choice.distance).to.eql(5);
|
|
expect(choice.loc).to.eql([5, 0]);
|
|
});
|
|
});
|
|
|
|
describe('.pointInPolygon', 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.geo.pointInPolygon(point, poly)).to.be.true;
|
|
});
|
|
it('says a point outside of a polygon is outside', function() {
|
|
var poly = [
|
|
[0, 0],
|
|
[0, 1],
|
|
[1, 1],
|
|
[1, 0],
|
|
[0, 0]];
|
|
var point = [0.5, 1.5];
|
|
expect(iD.geo.pointInPolygon(point, poly)).to.be.false;
|
|
});
|
|
});
|
|
|
|
describe('.polygonContainsPolygon', 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.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.geo.polygonContainsPolygon(outer, inner)).to.be.false;
|
|
});
|
|
});
|
|
|
|
describe('.polygonIntersectsPolygon', 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.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.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.geo.polygonIntersectsPolygon(outer, inner)).to.be.false;
|
|
});
|
|
});
|
|
|
|
describe('.pathLength', function() {
|
|
it('calculates a simple path length', function() {
|
|
var path = [[0, 0], [0, 1], [3, 5]];
|
|
expect(iD.geo.pathLength(path)).to.eql(6);
|
|
});
|
|
|
|
it('does not fail on single-point path', function() {
|
|
var path = [[0, 0]];
|
|
expect(iD.geo.pathLength(path)).to.eql(0);
|
|
});
|
|
|
|
it('estimates zero-length edges', function() {
|
|
var path = [[0, 0], [0, 0]];
|
|
expect(iD.geo.pathLength(path)).to.eql(0);
|
|
});
|
|
});
|
|
});
|