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
|
||||
var allowInfiniteExtension = editor._is_layer_in_extension_area(layer, latlng, mapPoint);
|
||||
|
||||
var snapPoint = editor._find_closest_point_on_geometry(layer, latlng, mapPoint, allowInfiniteExtension);
|
||||
if (snapPoint && snapPoint.distance < editor._snap_distance) {
|
||||
candidates.push(snapPoint);
|
||||
}
|
||||
var snapPoints = editor._find_closest_point_on_geometry(layer, latlng, mapPoint, allowInfiniteExtension);
|
||||
candidates.push(...snapPoints);
|
||||
});
|
||||
|
||||
// check current editing shape with infinite extension enabled
|
||||
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
|
||||
);
|
||||
if (currentShapeSnap && currentShapeSnap.distance < editor._snap_distance) {
|
||||
candidates.push(currentShapeSnap);
|
||||
}
|
||||
candidates.push(...currentShapeSnapPoints);
|
||||
}
|
||||
|
||||
// find closest candidate
|
||||
|
@ -1891,6 +1887,30 @@ editor = {
|
|||
candidates.sort(function(a, b) { return a.distance - b.distance; });
|
||||
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
|
||||
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) {
|
||||
if (!layer.getLatLngs) return false;
|
||||
|
||||
|
@ -2064,10 +2102,9 @@ editor = {
|
|||
},
|
||||
|
||||
_find_closest_point_on_geometry: function(layer, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
||||
if (!layer.getLatLngs) return null;
|
||||
if (!layer.getLatLngs) return [];
|
||||
|
||||
var closestPoint = null;
|
||||
var closestDistance = Infinity;
|
||||
var closestPoints = [];
|
||||
|
||||
try {
|
||||
var coordinates = [];
|
||||
|
@ -2083,16 +2120,16 @@ editor = {
|
|||
var centerMapPoint = editor.map.latLngToContainerPoint(center);
|
||||
var distance = centerMapPoint.distanceTo(targetMapPoint);
|
||||
if (distance < editor._snap_distance) {
|
||||
return {
|
||||
return [{
|
||||
latlng: center,
|
||||
distance: distance,
|
||||
edgeStart: center,
|
||||
edgeEnd: center,
|
||||
isInfiniteExtension: false,
|
||||
isRightAngle: false
|
||||
};
|
||||
}];
|
||||
}
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
// check each edge of the geometry
|
||||
|
@ -2102,17 +2139,16 @@ editor = {
|
|||
var p2 = coordinates[(i + 1) % coordinates.length];
|
||||
|
||||
var snapPoint = editor._find_closest_point_on_edge(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension);
|
||||
if (snapPoint && snapPoint.distance < closestDistance) {
|
||||
closestDistance = snapPoint.distance;
|
||||
closestPoint = snapPoint;
|
||||
if (snapPoint && snapPoint.distance < editor._snap_distance) {
|
||||
closestPoints.push(snapPoint);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
return closestPoint;
|
||||
return closestPoints;
|
||||
},
|
||||
|
||||
_find_closest_point_on_edge: function(p1, p2, targetLatLng, targetMapPoint, allowInfiniteExtension) {
|
||||
|
@ -2132,6 +2168,7 @@ editor = {
|
|||
distance: distance,
|
||||
edgeStart: p1,
|
||||
edgeEnd: p2,
|
||||
isLine: true,
|
||||
isInfiniteExtension: false,
|
||||
isRightAngle: false
|
||||
};
|
||||
|
@ -2167,6 +2204,7 @@ editor = {
|
|||
distance: distance,
|
||||
edgeStart: p1,
|
||||
edgeEnd: p2,
|
||||
isLine: true,
|
||||
isInfiniteExtension: isInfiniteExtension,
|
||||
isRightAngle: false,
|
||||
t: originalT
|
||||
|
@ -2195,9 +2233,26 @@ editor = {
|
|||
editor._show_90_degree_highlight(snapInfo);
|
||||
} else if (snapInfo && snapInfo.edgeStart && snapInfo.edgeEnd) {
|
||||
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) {
|
||||
var referenceVertex = snapInfo.referenceVertex;
|
||||
var snapPoint = snapInfo.latlng;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue