Add skipID to geoChooseEdge, to ignore dragging node

This commit is contained in:
Bryan Housel
2017-12-21 14:54:15 -05:00
parent fcacdb4400
commit d82d5dc3d0
2 changed files with 74 additions and 18 deletions
+9 -6
View File
@@ -157,14 +157,17 @@ export function geoRotate(points, angle, around) {
// projection onto that edge, if such a projection exists, or the distance to
// 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) {
export function geoChooseEdge(nodes, point, projection, skipID) {
var dist = geoEuclideanDistance;
var points = nodes.map(function(n) { return projection(n.loc); });
var ids = nodes.map(function(n) { return n.id; });
var min = Infinity;
var idx;
var loc;
for (var i = 0; i < points.length - 1; i++) {
if (ids[i] === skipID || ids[i + 1] === skipID) continue;
var o = points[i];
var s = geoVecSubtract(points[i + 1], o);
var v = geoVecSubtract(point, o);
@@ -187,11 +190,11 @@ export function geoChooseEdge(nodes, point, projection) {
}
}
return {
index: idx,
distance: min,
loc: loc
};
if (idx !== undefined) {
return { index: idx, distance: min, loc: loc };
} else {
return null;
}
}
+65 -12
View File
@@ -291,20 +291,12 @@ describe('iD.geo', function() {
var projection = function (l) { return l; };
projection.invert = projection;
it('returns undefined properties for a degenerate way (no nodes)', function() {
expect(iD.geoChooseEdge([], [0, 0], projection)).to.eql({
index: undefined,
distance: Infinity,
loc: undefined
});
it('returns null for a degenerate way (no nodes)', function() {
expect(iD.geoChooseEdge([], [0, 0], projection)).to.be.null;
});
it('returns undefined properties for a degenerate way (single node)', function() {
expect(iD.geoChooseEdge([iD.osmNode({loc: [0, 0]})], [0, 0], projection)).to.eql({
index: undefined,
distance: Infinity,
loc: undefined
});
it('returns null for a degenerate way (single node)', function() {
expect(iD.geoChooseEdge([iD.osmNode({loc: [0, 0]})], [0, 0], projection)).to.be.null;
});
it('calculates the orthogonal projection of a point onto a segment', function() {
@@ -344,6 +336,67 @@ describe('iD.geo', function() {
expect(choice.distance).to.eql(5);
expect(choice.loc).to.eql([5, 0]);
});
it('skips the given nodeID at end of way', function() {
//
// a --*-- b
// e |
// | |
// d - c
//
// * = [2, 0]
var a = [0, 0];
var b = [5, 0];
var c = [5, 5];
var d = [2, 5];
var e = [2, 0.1]; // e.g. user is dragging e onto ab
var nodes = [
iD.osmNode({id: 'a', loc: a}),
iD.osmNode({id: 'b', loc: b}),
iD.osmNode({id: 'c', loc: c}),
iD.osmNode({id: 'd', loc: d}),
iD.osmNode({id: 'e', loc: e})
];
var choice = iD.geoChooseEdge(nodes, e, projection, 'e');
expect(choice.index).to.eql(1);
expect(choice.distance).to.eql(0.1);
expect(choice.loc).to.eql([2, 0]);
});
it('skips the given nodeID in middle of way', function() {
//
// a --*-- b
// d |
// / \ |
// e c
//
// * = [2, 0]
var a = [0, 0];
var b = [5, 0];
var c = [5, 5];
var d = [2, 0.1]; // e.g. user is dragging d onto ab
var e = [0, 5];
var nodes = [
iD.osmNode({id: 'a', loc: a}),
iD.osmNode({id: 'b', loc: b}),
iD.osmNode({id: 'c', loc: c}),
iD.osmNode({id: 'd', loc: d}),
iD.osmNode({id: 'e', loc: e})
];
var choice = iD.geoChooseEdge(nodes, d, projection, 'd');
expect(choice.index).to.eql(1);
expect(choice.distance).to.eql(0.1);
expect(choice.loc).to.eql([2, 0]);
});
it('returns null if all nodes are skipped', function() {
var nodes = [
iD.osmNode({id: 'a', loc: [0, 0]}),
iD.osmNode({id: 'b', loc: [5, 0]}),
];
var choice = iD.geoChooseEdge(nodes, [2, 2], projection, 'a');
expect(choice).to.be.null;
});
});
describe('geoLineIntersection', function() {