@mytec: iter3.7.0 start, gpu calc int

This commit is contained in:
2026-02-03 22:41:08 +02:00
parent a61753c642
commit 6cd9d869cc
29 changed files with 2288 additions and 28 deletions

View File

@@ -1,8 +1,8 @@
/**
* Renders a dashed polyline around the coverage zone boundary.
*
* Uses @turf/concave to compute a concave hull (alpha shape) per site,
* which correctly follows sector/wedge shapes — not just convex circles.
* Prefers server-computed boundary if available (shapely concave_hull).
* Falls back to client-side @turf/concave computation.
*
* Performance: ~20-50ms for 10k points (runs once per coverage change).
*/
@@ -12,7 +12,7 @@ import { useMap } from 'react-leaflet';
import L from 'leaflet';
import concave from '@turf/concave';
import { featureCollection, point } from '@turf/helpers';
import type { CoveragePoint } from '@/types/index.ts';
import type { CoveragePoint, BoundaryPoint } from '@/types/index.ts';
import { logger } from '@/utils/logger.ts';
interface CoverageBoundaryProps {
@@ -21,6 +21,7 @@ interface CoverageBoundaryProps {
resolution: number; // meters — controls concave hull detail
color?: string;
weight?: number;
boundary?: BoundaryPoint[]; // server-provided boundary (preferred)
}
export default function CoverageBoundary({
@@ -29,13 +30,25 @@ export default function CoverageBoundary({
resolution,
color = '#ffffff', // white — visible against red-to-blue gradient
weight = 2,
boundary,
}: CoverageBoundaryProps) {
const map = useMap();
const layerRef = useRef<L.LayerGroup | null>(null);
// Compute boundary paths grouped by site
// Compute boundary paths - prefer server boundary, fallback to client-side
const boundaryPaths = useMemo(() => {
if (!visible || points.length === 0) return [];
if (!visible) return [];
// Use server-provided boundary if available
if (boundary && boundary.length >= 3) {
const serverPath: L.LatLngExpression[] = boundary.map(
(p) => [p.lat, p.lon] as L.LatLngExpression
);
return [serverPath];
}
// Fallback to client-side computation
if (points.length === 0) return [];
// Group points by siteId (fallback to 'all' when siteId not available from API)
const bySite = new Map<string, CoveragePoint[]>();
@@ -61,7 +74,7 @@ export default function CoverageBoundary({
}
return paths;
}, [points, visible, resolution]);
}, [points, visible, resolution, boundary]);
// Render / cleanup polylines
useEffect(() => {