@mytec: iter1.5.1 ready for testing
This commit is contained in:
@@ -52,9 +52,11 @@ export default function CoverageBoundary({
|
||||
const paths: L.LatLngExpression[][] = [];
|
||||
|
||||
for (const sitePoints of bySite.values()) {
|
||||
const path = computeConcaveHull(sitePoints, resolution);
|
||||
if (path.length >= 3) {
|
||||
paths.push(path);
|
||||
const sitePaths = computeConcaveHulls(sitePoints, resolution);
|
||||
for (const path of sitePaths) {
|
||||
if (path.length >= 3) {
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,15 +105,16 @@ export default function CoverageBoundary({
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Compute a concave hull boundary for one site's coverage points.
|
||||
* Compute concave hull boundary path(s) for a set of coverage points.
|
||||
*
|
||||
* maxEdge = resolution * 3 (in km) gives good detail without over-fitting.
|
||||
* Returns multiple paths if hull is a MultiPolygon (disjoint coverage areas).
|
||||
* Falls back to empty if hull computation fails (e.g., collinear points).
|
||||
*/
|
||||
function computeConcaveHull(
|
||||
function computeConcaveHulls(
|
||||
pts: CoveragePoint[],
|
||||
resolutionM: number
|
||||
): L.LatLngExpression[] {
|
||||
): L.LatLngExpression[][] {
|
||||
if (pts.length < 3) return [];
|
||||
|
||||
// Convert to GeoJSON FeatureCollection of Points
|
||||
@@ -124,15 +127,28 @@ function computeConcaveHull(
|
||||
try {
|
||||
const hull = concave(fc, { maxEdge, units: 'kilometers' });
|
||||
|
||||
if (!hull || hull.geometry.type !== 'Polygon') {
|
||||
return [];
|
||||
if (!hull) return [];
|
||||
|
||||
// Handle both Polygon and MultiPolygon results
|
||||
if (hull.geometry.type === 'Polygon') {
|
||||
const coords = hull.geometry.coordinates[0];
|
||||
return [
|
||||
coords.map(
|
||||
([lon, lat]: number[]) => [lat, lon] as L.LatLngExpression
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
// GeoJSON coordinates are [lon, lat]; Leaflet needs [lat, lon]
|
||||
const coords = hull.geometry.coordinates[0];
|
||||
return coords.map(
|
||||
([lon, lat]: number[]) => [lat, lon] as L.LatLngExpression
|
||||
);
|
||||
if (hull.geometry.type === 'MultiPolygon') {
|
||||
// Return all polygons as separate boundary paths
|
||||
return hull.geometry.coordinates.map((poly) =>
|
||||
poly[0].map(
|
||||
([lon, lat]: number[]) => [lat, lon] as L.LatLngExpression
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
} catch (error) {
|
||||
logger.error('Coverage hull computation error:', error);
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user