Skip to content

Commit

Permalink
Prevent self intersecting lines without a junction node
Browse files Browse the repository at this point in the history
(closes #4646)
  • Loading branch information
bhousel committed Jan 9, 2018
1 parent 49eb46f commit e661281
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 10 deletions.
12 changes: 5 additions & 7 deletions modules/behavior/draw_way.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {

context.replace(actionMoveNode(end.id, loc));
end = context.entity(end.id);
checkGeometry(true); // skipLast = true
checkGeometry(origWay.isClosed()); // skipLast = true when drawing areas
}


Expand Down Expand Up @@ -125,11 +125,9 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
for (var i = 0; i < parents.length; i++) {
var parent = parents[i];
var nodes = parent.nodes.map(function(nodeID) { return graph.entity(nodeID); });
if (parent.isClosed()) {
if (skipLast) nodes.pop(); // disregard closing segment - #4655
if (geoHasSelfIntersections(nodes, entity.id)) {
return true;
}
if (skipLast) nodes.pop(); // disregard closing segment - #4655
if (geoHasSelfIntersections(nodes, entity.id)) {
return true;
}
}

Expand Down Expand Up @@ -296,7 +294,7 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
// If the way has enough nodes to be valid, it's selected.
// Otherwise, delete everything and return to browse mode.
drawWay.finish = function() {
checkGeometry(false); // skipLast = false
checkGeometry(true); // skipLast = true
if (context.surface().classed('nope')) {
return; // can't click here
}
Expand Down
14 changes: 12 additions & 2 deletions modules/geo/geom.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,18 @@ export function geoHasSelfIntersections(nodes, activeID) {
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;
}

var hit = geoLineIntersection(p, q);
if (hit) {
var epsilon = 1e-8;
// skip if the hit is at the segment's endpoint
if (geoVecEqual(p[1], hit, epsilon) || geoVecEqual(p[0], hit, epsilon) ||
geoVecEqual(q[1], hit, epsilon) || geoVecEqual(q[0], hit, epsilon) ) {
continue;
} else {
return true;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion modules/modes/drag_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export function modeDragNode(context) {

// If we still haven't tested this node's parent way for self-intersections.
// (because it's not a member of a multipolygon), test it now.
if (activeIndex === null && parent.isClosed()) {
if (activeIndex === null) {
nodes = parent.nodes.map(function(nodeID) { return graph.entity(nodeID); });
if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
return true;
Expand Down

0 comments on commit e661281

Please sign in to comment.