Implement snap to corner
This commit is contained in:
parent
bfd08978a1
commit
6576da2660
1 changed files with 74 additions and 19 deletions
|
@ -1870,20 +1870,16 @@ editor = {
|
||||||
// check if layer is within the area limit for infinite extension
|
// check if layer is within the area limit for infinite extension
|
||||||
var allowInfiniteExtension = editor._is_layer_in_extension_area(layer, latlng, mapPoint);
|
var allowInfiniteExtension = editor._is_layer_in_extension_area(layer, latlng, mapPoint);
|
||||||
|
|
||||||
var snapPoint = editor._find_closest_point_on_geometry(layer, latlng, mapPoint, allowInfiniteExtension);
|
var snapPoints = editor._find_closest_point_on_geometry(layer, latlng, mapPoint, allowInfiniteExtension);
|
||||||
if (snapPoint && snapPoint.distance < editor._snap_distance) {
|
candidates.push(...snapPoints);
|
||||||
candidates.push(snapPoint);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// check current editing shape with infinite extension enabled
|
// check current editing shape with infinite extension enabled
|
||||||
if (editor._current_editing_shape) {
|
if (editor._current_editing_shape) {
|
||||||
var currentShapeSnap = editor._find_closest_point_on_geometry(
|
var currentShapeSnapPoints = editor._find_closest_point_on_geometry(
|
||||||
editor._current_editing_shape, latlng, mapPoint, true // Always enable infinite extension for current shape
|
editor._current_editing_shape, latlng, mapPoint, true // Always enable infinite extension for current shape
|
||||||
);
|
);
|
||||||
if (currentShapeSnap && currentShapeSnap.distance < editor._snap_distance) {
|
candidates.push(...currentShapeSnapPoints);
|
||||||
candidates.push(currentShapeSnap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// find closest candidate
|
// find closest candidate
|
||||||
|
@ -1891,6 +1887,30 @@ editor = {
|
||||||
candidates.sort(function(a, b) { return a.distance - b.distance; });
|
candidates.sort(function(a, b) { return a.distance - b.distance; });
|
||||||
var best = candidates[0];
|
var best = candidates[0];
|
||||||
|
|
||||||
|
// see if we can snap to a corner, i.e. an edge intersection
|
||||||
|
if (candidates.length >= 2 && candidates[0].isLine && candidates[1].isLine) {
|
||||||
|
console.log(candidates.slice(0,2))
|
||||||
|
var inters = editor._intersect_infinite(
|
||||||
|
[candidates[0].edgeStart, candidates[0].edgeEnd],
|
||||||
|
[candidates[1].edgeStart, candidates[1].edgeEnd]
|
||||||
|
)
|
||||||
|
if (inters) {
|
||||||
|
intersMap = editor.map.latLngToContainerPoint(inters)
|
||||||
|
var distance = Math.sqrt(
|
||||||
|
Math.pow(intersMap.x - mapPoint.x, 2) +
|
||||||
|
Math.pow(intersMap.y - mapPoint.y, 2)
|
||||||
|
)
|
||||||
|
if (distance < editor._snap_distance) {
|
||||||
|
best = {
|
||||||
|
latlng: inters,
|
||||||
|
distance: distance,
|
||||||
|
referenceVertex: inters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// show snap indicator with edge highlighting
|
// show snap indicator with edge highlighting
|
||||||
editor._show_snap_indicator(best.latlng, best);
|
editor._show_snap_indicator(best.latlng, best);
|
||||||
|
|
||||||
|
@ -1901,6 +1921,24 @@ editor = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_intersect_infinite: function(line1, line2) {
|
||||||
|
const [p1, p2] = line1;
|
||||||
|
const [p3, p4] = line2;
|
||||||
|
|
||||||
|
const x1 = p1.lng, y1 = p1.lat;
|
||||||
|
const x2 = p2.lng, y2 = p2.lat;
|
||||||
|
const x3 = p3.lng, y3 = p3.lat;
|
||||||
|
const x4 = p4.lng, y4 = p4.lat;
|
||||||
|
|
||||||
|
const denom = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4);
|
||||||
|
if (denom === 0) return null; // parallel
|
||||||
|
|
||||||
|
const px = ((x1*y2 - y1*x2)*(x3-x4) - (x1-x2)*(x3*y4 - y3*x4)) / denom;
|
||||||
|
const py = ((x1*y2 - y1*x2)*(y3-y4) - (y1-y2)*(x3*y4 - y3*x4)) / denom;
|
||||||
|
|
||||||
|
return {lng: px, lat: py};
|
||||||
|
},
|
||||||
|
|
||||||
_is_layer_in_extension_area: function(layer, targetLatLng, targetMapPoint) {
|
_is_layer_in_extension_area: function(layer, targetLatLng, targetMapPoint) {
|
||||||
if (!layer.getLatLngs) return false;
|
if (!layer.getLatLngs) return false;
|
||||||
|
|
||||||
|
@ -2064,10 +2102,9 @@ editor = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_find_closest_point_on_geometry: function(layer, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
_find_closest_point_on_geometry: function(layer, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
||||||
if (!layer.getLatLngs) return null;
|
if (!layer.getLatLngs) return [];
|
||||||
|
|
||||||
var closestPoint = null;
|
var closestPoints = [];
|
||||||
var closestDistance = Infinity;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var coordinates = [];
|
var coordinates = [];
|
||||||
|
@ -2083,16 +2120,16 @@ editor = {
|
||||||
var centerMapPoint = editor.map.latLngToContainerPoint(center);
|
var centerMapPoint = editor.map.latLngToContainerPoint(center);
|
||||||
var distance = centerMapPoint.distanceTo(targetMapPoint);
|
var distance = centerMapPoint.distanceTo(targetMapPoint);
|
||||||
if (distance < editor._snap_distance) {
|
if (distance < editor._snap_distance) {
|
||||||
return {
|
return [{
|
||||||
latlng: center,
|
latlng: center,
|
||||||
distance: distance,
|
distance: distance,
|
||||||
edgeStart: center,
|
edgeStart: center,
|
||||||
edgeEnd: center,
|
edgeEnd: center,
|
||||||
isInfiniteExtension: false,
|
isInfiniteExtension: false,
|
||||||
isRightAngle: false
|
isRightAngle: false
|
||||||
};
|
}];
|
||||||
}
|
}
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// check each edge of the geometry
|
// check each edge of the geometry
|
||||||
|
@ -2102,17 +2139,16 @@ editor = {
|
||||||
var p2 = coordinates[(i + 1) % coordinates.length];
|
var p2 = coordinates[(i + 1) % coordinates.length];
|
||||||
|
|
||||||
var snapPoint = editor._find_closest_point_on_edge(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension);
|
var snapPoint = editor._find_closest_point_on_edge(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension);
|
||||||
if (snapPoint && snapPoint.distance < closestDistance) {
|
if (snapPoint && snapPoint.distance < editor._snap_distance) {
|
||||||
closestDistance = snapPoint.distance;
|
closestPoints.push(snapPoint);
|
||||||
closestPoint = snapPoint;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return closestPoint;
|
return closestPoints;
|
||||||
},
|
},
|
||||||
|
|
||||||
_find_closest_point_on_edge: function(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
_find_closest_point_on_edge: function(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
||||||
|
@ -2132,6 +2168,7 @@ editor = {
|
||||||
distance: distance,
|
distance: distance,
|
||||||
edgeStart: p1,
|
edgeStart: p1,
|
||||||
edgeEnd: p2,
|
edgeEnd: p2,
|
||||||
|
isLine: true,
|
||||||
isInfiniteExtension: false,
|
isInfiniteExtension: false,
|
||||||
isRightAngle: false
|
isRightAngle: false
|
||||||
};
|
};
|
||||||
|
@ -2167,6 +2204,7 @@ editor = {
|
||||||
distance: distance,
|
distance: distance,
|
||||||
edgeStart: p1,
|
edgeStart: p1,
|
||||||
edgeEnd: p2,
|
edgeEnd: p2,
|
||||||
|
isLine: true,
|
||||||
isInfiniteExtension: isInfiniteExtension,
|
isInfiniteExtension: isInfiniteExtension,
|
||||||
isRightAngle: false,
|
isRightAngle: false,
|
||||||
t: originalT
|
t: originalT
|
||||||
|
@ -2195,9 +2233,26 @@ editor = {
|
||||||
editor._show_90_degree_highlight(snapInfo);
|
editor._show_90_degree_highlight(snapInfo);
|
||||||
} else if (snapInfo && snapInfo.edgeStart && snapInfo.edgeEnd) {
|
} else if (snapInfo && snapInfo.edgeStart && snapInfo.edgeEnd) {
|
||||||
editor._show_edge_highlight(snapInfo);
|
editor._show_edge_highlight(snapInfo);
|
||||||
|
} else if (snapInfo && snapInfo.referenceVertex) {
|
||||||
|
editor._show_intersect_highlight(snapInfo);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_show_intersect_highlight: function(snapInfo) {
|
||||||
|
var referenceVertex = snapInfo.referenceVertex;
|
||||||
|
var snapPoint = snapInfo.latlng;
|
||||||
|
|
||||||
|
// Draw line from reference vertex to snap point
|
||||||
|
var guideLine = L.polyline([referenceVertex, snapPoint], {
|
||||||
|
color: '#00aaff',
|
||||||
|
weight: 2,
|
||||||
|
opacity: 0.8,
|
||||||
|
dashArray: '4, 4',
|
||||||
|
className: '90-degree-guide'
|
||||||
|
});
|
||||||
|
editor._snap_indicator.addLayer(guideLine);
|
||||||
|
},
|
||||||
|
|
||||||
_show_90_degree_highlight: function(snapInfo) {
|
_show_90_degree_highlight: function(snapInfo) {
|
||||||
var referenceVertex = snapInfo.referenceVertex;
|
var referenceVertex = snapInfo.referenceVertex;
|
||||||
var snapPoint = snapInfo.latlng;
|
var snapPoint = snapInfo.latlng;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue