feat(shortcut): area

This commit is contained in:
2026-04-20 09:36:34 +08:00
parent cad763d2a3
commit 04d530d692
8 changed files with 815 additions and 94 deletions

View File

@@ -0,0 +1,69 @@
import {
normalizeMultiPolygon,
type NormalizedMultiPolygon,
type NormalizedRing,
} from "./booleanAdapter"
export interface AreaFilterResult {
geometry: NormalizedMultiPolygon
removedOuterCount: number
removedHoleCount: number
}
const getRingArea = (ring: NormalizedRing) => {
let area = 0
for (let index = 0; index < ring.length - 1; index += 1) {
const [x1, y1] = ring[index]
const [x2, y2] = ring[index + 1]
area += x1 * y2 - x2 * y1
}
return Math.abs(area / 2)
}
export const filterMultiPolygonByAreaThreshold = ({
geometry,
minArea,
}: {
geometry: NormalizedMultiPolygon | null | undefined
minArea: number
}): AreaFilterResult => {
const normalizedGeometry = normalizeMultiPolygon(geometry)
const normalizedMinArea = Math.max(0, Number(minArea) || 0)
if (!normalizedMinArea) {
return {
geometry: normalizedGeometry,
removedOuterCount: 0,
removedHoleCount: 0,
}
}
let removedOuterCount = 0
let removedHoleCount = 0
const nextGeometry = normalizedGeometry.flatMap((polygon) => {
const [outerRing, ...holeRings] = polygon
if (!outerRing) return []
if (getRingArea(outerRing) < normalizedMinArea) {
removedOuterCount += 1
return []
}
const nextHoleRings = holeRings.filter((ring) => {
const keep = getRingArea(ring) >= normalizedMinArea
if (!keep) {
removedHoleCount += 1
}
return keep
})
return [[outerRing, ...nextHoleRings]]
})
return {
geometry: nextGeometry,
removedOuterCount,
removedHoleCount,
}
}