mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-18 14:45:12 +02:00
Add geoHasLineIntersections, better for testing multipolygon rings
(closes #4741)
This commit is contained in:
+47
-1
@@ -80,12 +80,57 @@ export function geoChooseEdge(nodes, point, projection, activeID) {
|
||||
}
|
||||
|
||||
|
||||
// check active (dragged or drawing) segments against inactive segments
|
||||
// Test active (dragged or drawing) segments against inactive segments
|
||||
// This is used to test e.g. multipolygon rings that cross
|
||||
// `activeNodes` is the ring containing the activeID being dragged.
|
||||
// `inactiveNodes` is the other ring to test against
|
||||
export function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
|
||||
var actives = [];
|
||||
var inactives = [];
|
||||
var j, k, n1, n2, segment;
|
||||
|
||||
// gather active segments (only segments in activeNodes that contain the activeID)
|
||||
for (j = 0; j < activeNodes.length - 1; j++) {
|
||||
n1 = activeNodes[j];
|
||||
n2 = activeNodes[j+1];
|
||||
segment = [n1.loc, n2.loc];
|
||||
if (n1.id === activeID || n2.id === activeID) {
|
||||
actives.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
// gather inactive segments
|
||||
for (j = 0; j < inactiveNodes.length - 1; j++) {
|
||||
n1 = inactiveNodes[j];
|
||||
n2 = inactiveNodes[j+1];
|
||||
segment = [n1.loc, n2.loc];
|
||||
inactives.push(segment);
|
||||
}
|
||||
|
||||
// test
|
||||
for (j = 0; j < actives.length; j++) {
|
||||
for (k = 0; k < inactives.length; k++) {
|
||||
var p = actives[j];
|
||||
var q = inactives[k];
|
||||
var hit = geoLineIntersection(p, q);
|
||||
if (hit) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Test active (dragged or drawing) segments against inactive segments
|
||||
// This is used to test whether a way intersects with itself.
|
||||
export function geoHasSelfIntersections(nodes, activeID) {
|
||||
var actives = [];
|
||||
var inactives = [];
|
||||
var j, k;
|
||||
|
||||
// group active and passive segments along the nodes
|
||||
for (j = 0; j < nodes.length - 1; j++) {
|
||||
var n1 = nodes[j];
|
||||
var n2 = nodes[j+1];
|
||||
@@ -97,6 +142,7 @@ export function geoHasSelfIntersections(nodes, activeID) {
|
||||
}
|
||||
}
|
||||
|
||||
// test
|
||||
for (j = 0; j < actives.length; j++) {
|
||||
for (k = 0; k < inactives.length; k++) {
|
||||
var p = actives[j];
|
||||
|
||||
@@ -13,6 +13,7 @@ export { geoZoomToScale } from './geo.js';
|
||||
export { geoAngle } from './geom.js';
|
||||
export { geoChooseEdge } from './geom.js';
|
||||
export { geoEdgeEqual } from './geom.js';
|
||||
export { geoHasLineIntersections } from './geom.js';
|
||||
export { geoHasSelfIntersections } from './geom.js';
|
||||
export { geoRotate } from './geom.js';
|
||||
export { geoLineIntersection } from './geom.js';
|
||||
|
||||
@@ -24,8 +24,8 @@ import {
|
||||
|
||||
import {
|
||||
geoChooseEdge,
|
||||
geoHasLineIntersections,
|
||||
geoHasSelfIntersections,
|
||||
geoPathHasIntersections,
|
||||
geoVecSubtract,
|
||||
geoViewportEdge
|
||||
} from '../geo';
|
||||
@@ -245,7 +245,7 @@ export function modeDragNode(context) {
|
||||
if (k === activeIndex) continue;
|
||||
|
||||
// make sure active ring doesnt cross passive rings
|
||||
if (geoPathHasIntersections(rings[activeIndex].coords, rings[k].coords)) {
|
||||
if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +160,79 @@ describe('iD.geo - geometry', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoHasLineIntersections', function() {
|
||||
it('returns false for a degenerate way (no nodes)', function() {
|
||||
expect(iD.geoHasLineIntersections([], '')).to.be.false;
|
||||
});
|
||||
|
||||
it('returns false if no activeID', function() {
|
||||
var a = iD.osmNode({id: 'a', loc: [2, 2]});
|
||||
var b = iD.osmNode({id: 'b', loc: [4, 2]});
|
||||
var c = iD.osmNode({id: 'c', loc: [4, 4]});
|
||||
var d = iD.osmNode({id: 'd', loc: [2, 4]});
|
||||
var nodes = [a, b, c, d, a];
|
||||
expect(iD.geoHasLineIntersections(nodes, '')).to.be.false;
|
||||
});
|
||||
|
||||
it('returns false if there are no intersections', function() {
|
||||
// e --------- f
|
||||
// | |
|
||||
// | a --- b |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | d --- c |
|
||||
// | |
|
||||
// h --------- g
|
||||
var a = iD.osmNode({id: 'a', loc: [2, 2]});
|
||||
var b = iD.osmNode({id: 'b', loc: [4, 2]});
|
||||
var c = iD.osmNode({id: 'c', loc: [4, 4]});
|
||||
var d = iD.osmNode({id: 'd', loc: [2, 4]});
|
||||
var e = iD.osmNode({id: 'e', loc: [0, 0]});
|
||||
var f = iD.osmNode({id: 'f', loc: [8, 0]});
|
||||
var g = iD.osmNode({id: 'g', loc: [8, 8]});
|
||||
var h = iD.osmNode({id: 'h', loc: [0, 8]});
|
||||
var inner = [a, b, c, d, a];
|
||||
var outer = [e, f, g, h, e];
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'a')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'b')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'c')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'd')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'e')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'f')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'g')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'h')).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true if the activeID is causing intersections', function() {
|
||||
// e --------- f
|
||||
// | |
|
||||
// | a --------- b
|
||||
// | | |/
|
||||
// | | /|
|
||||
// | d --- c |
|
||||
// | |
|
||||
// h --------- g
|
||||
var a = iD.osmNode({id: 'a', loc: [2, 2]});
|
||||
var b = iD.osmNode({id: 'b', loc: [10, 2]});
|
||||
var c = iD.osmNode({id: 'c', loc: [4, 4]});
|
||||
var d = iD.osmNode({id: 'd', loc: [2, 4]});
|
||||
var e = iD.osmNode({id: 'e', loc: [0, 0]});
|
||||
var f = iD.osmNode({id: 'f', loc: [8, 0]});
|
||||
var g = iD.osmNode({id: 'g', loc: [8, 8]});
|
||||
var h = iD.osmNode({id: 'h', loc: [0, 8]});
|
||||
var inner = [a, b, c, d, a];
|
||||
var outer = [e, f, g, h, e];
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'a')).to.be.true;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'b')).to.be.true;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'c')).to.be.true;
|
||||
expect(iD.geoHasLineIntersections(inner, outer, 'd')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'e')).to.be.false;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'f')).to.be.true;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'g')).to.be.true;
|
||||
expect(iD.geoHasLineIntersections(outer, inner, 'h')).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoHasSelfIntersections', function() {
|
||||
it('returns false for a degenerate way (no nodes)', function() {
|
||||
expect(iD.geoHasSelfIntersections([], '')).to.be.false;
|
||||
|
||||
Reference in New Issue
Block a user