fix: eraser tool works on polygon areas and line edges, not just vertices
This commit is contained in:
@@ -983,7 +983,7 @@ export function MapView({
|
||||
// Eraser mode: click on/near a feature to delete it
|
||||
if (mode === 'eraser') {
|
||||
const pixel = e.point
|
||||
const tolerance = 10 // px
|
||||
const tolerance = 20 // px
|
||||
const currentFeatures = featuresRef.current
|
||||
let closestIdx = -1
|
||||
let closestDist = Infinity
|
||||
@@ -992,29 +992,44 @@ export function MapView({
|
||||
const f = currentFeatures[i]
|
||||
const geom = f.geometry
|
||||
|
||||
// Get all coordinates to check proximity
|
||||
let allCoords: number[][] = []
|
||||
if (geom.type === 'Point') {
|
||||
allCoords = [geom.coordinates as number[]]
|
||||
} else if (geom.type === 'LineString') {
|
||||
allCoords = geom.coordinates as number[][]
|
||||
} else if (geom.type === 'Polygon') {
|
||||
allCoords = (geom.coordinates as number[][][])[0] || []
|
||||
}
|
||||
|
||||
for (const c of allCoords) {
|
||||
const projected = m.project([c[0], c[1]])
|
||||
const projected = m.project(geom.coordinates as [number, number])
|
||||
const dx = projected.x - pixel.x
|
||||
const dy = projected.y - pixel.y
|
||||
const dist = Math.sqrt(dx * dx + dy * dy)
|
||||
if (dist < closestDist) {
|
||||
closestDist = dist
|
||||
closestIdx = i
|
||||
if (dist < closestDist) { closestDist = dist; closestIdx = i }
|
||||
} else if (geom.type === 'LineString') {
|
||||
const lineCoords = geom.coordinates as number[][]
|
||||
for (let j = 0; j < lineCoords.length - 1; j++) {
|
||||
const p1 = m.project(lineCoords[j] as [number, number])
|
||||
const p2 = m.project(lineCoords[j + 1] as [number, number])
|
||||
const dist = pointToSegmentDist(pixel.x, pixel.y, p1.x, p1.y, p2.x, p2.y)
|
||||
if (dist < closestDist) { closestDist = dist; closestIdx = i }
|
||||
}
|
||||
} else if (geom.type === 'Polygon') {
|
||||
const ring = (geom.coordinates as number[][][])[0] || []
|
||||
// Check edges
|
||||
for (let j = 0; j < ring.length - 1; j++) {
|
||||
const p1 = m.project(ring[j] as [number, number])
|
||||
const p2 = m.project(ring[j + 1] as [number, number])
|
||||
const dist = pointToSegmentDist(pixel.x, pixel.y, p1.x, p1.y, p2.x, p2.y)
|
||||
if (dist < closestDist) { closestDist = dist; closestIdx = i }
|
||||
}
|
||||
// Point-in-polygon test (screen space)
|
||||
const projected = ring.map(c => m.project(c as [number, number]))
|
||||
let inside = false
|
||||
for (let j = 0, k = projected.length - 1; j < projected.length; k = j++) {
|
||||
const xi = projected[j].x, yi = projected[j].y
|
||||
const xk = projected[k].x, yk = projected[k].y
|
||||
if (((yi > pixel.y) !== (yk > pixel.y)) && (pixel.x < (xk - xi) * (pixel.y - yi) / (yk - yi) + xi)) {
|
||||
inside = !inside
|
||||
}
|
||||
}
|
||||
if (inside) { closestDist = 0; closestIdx = i }
|
||||
}
|
||||
}
|
||||
|
||||
if (closestIdx >= 0 && closestDist < tolerance * 3) {
|
||||
if (closestIdx >= 0 && closestDist < tolerance) {
|
||||
const deleted = currentFeatures[closestIdx]
|
||||
const newFeatures = currentFeatures.filter((_, i) => i !== closestIdx)
|
||||
onFeaturesChangeRef.current(newFeatures)
|
||||
|
||||
Reference in New Issue
Block a user