From 6d1b8e7cde97fd5b8f82f361ea11e9ced75df7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2=D1=8C=D0=B5=D0=B2?= Date: Sun, 31 May 2026 16:08:20 +0300 Subject: [PATCH] fix(tgu-ops-ui): fix track antimeridian wrap and polygon culling on 2D map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drawTracks: detect antimeridian crossing by comparing consecutive screen X positions against worldSize/2; use moveTo instead of lineTo on large jumps so tracks don't draw a horizontal line across the globe. Tgu2DMapView: replace the heuristic lon-range check (> 300°) with an exact condition — skip bbox culling when the canvas is wider than the world tile (entire globe visible) or when topLeft.lon >= bottomRight.lon (viewport straddles the antimeridian). Both cases previously produced a nonsensical bbox that hid polygons near ±180°. drawRequests: remove per-polygon screen-space culling; viewport filtering is already handled upstream by visiblePolygons, so the redundant check was incorrectly hiding requests at high zoom levels near canvas edges. Co-Authored-By: Claude Sonnet 4.6 --- .../src/features/tgu-map-2d/Tgu2DMapView.tsx | 13 +++++++------ .../src/features/tgu-map-2d/canvas/drawRequests.ts | 5 +---- .../src/features/tgu-map-2d/canvas/drawTracks.ts | 9 ++++++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/Tgu2DMapView.tsx b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/Tgu2DMapView.tsx index 6515960..37096a0 100644 --- a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/Tgu2DMapView.tsx +++ b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/Tgu2DMapView.tsx @@ -83,18 +83,19 @@ export function Tgu2DMapView({ const polygonIndex = useMemo(() => createPolygonSpatialIndex(activePolygons), [activePolygons]); const projection = useMemo(() => createMapProjection(view, size), [view, size]); const visiblePolygons = useMemo(() => { + // When the canvas is wider than the world tile, the entire globe is visible — + // bbox filtering would produce a nonsensical range, so skip it. + // When the viewport crosses the antimeridian, topLeft.lon ends up east of + // bottomRight.lon — same situation, show everything. const topLeft = projection.unproject({ x: 0, y: 0 }); const bottomRight = projection.unproject({ x: size.width, y: size.height }); - const minLon = Math.min(topLeft.lon, bottomRight.lon); - const maxLon = Math.max(topLeft.lon, bottomRight.lon); - - if (maxLon - minLon > 300) { + if (size.width >= projection.worldSize || topLeft.lon >= bottomRight.lon) { return activePolygons; } return queryPolygonsByBBox(polygonIndex, { - minLon, - maxLon, + minLon: topLeft.lon, + maxLon: bottomRight.lon, minLat: Math.min(topLeft.lat, bottomRight.lat), maxLat: Math.max(topLeft.lat, bottomRight.lat) }); diff --git a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawRequests.ts b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawRequests.ts index a38a047..1839716 100644 --- a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawRequests.ts +++ b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawRequests.ts @@ -12,15 +12,12 @@ export function drawRequests( ctx: CanvasRenderingContext2D, polygons: MapPolygon[], projection: MapProjection, - viewport: { width: number; height: number } + _viewport: { width: number; height: number } ) { ctx.save(); for (const polygon of polygons) { if (polygon.points.length < 3) continue; const screenPoints = polygon.points.map((point) => projection.project(point)); - if (!screenPoints.some((point) => point.x >= -32 && point.x <= viewport.width + 32 && point.y >= -32 && point.y <= viewport.height + 32)) { - continue; - } const color = SURVEY_COLORS[polygon.surveyType ?? ""] ?? DEFAULT_COLOR; ctx.beginPath(); diff --git a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawTracks.ts b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawTracks.ts index d922b10..c8084f4 100644 --- a/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawTracks.ts +++ b/services/pcp-tgu-ops-ui/src/features/tgu-map-2d/canvas/drawTracks.ts @@ -8,17 +8,20 @@ export function drawTracks(ctx: CanvasRenderingContext2D, lines: MapLine[], proj ctx.strokeStyle = "rgba(104, 195, 189, 0.76)"; ctx.lineWidth = 1.2; + const wrapThreshold = projection.worldSize / 2; for (const line of lines) { if (line.points.length < 2) continue; ctx.beginPath(); - line.points.forEach((point, index) => { + let prevX: number | undefined; + for (const point of line.points) { const screen = projection.project(point); - if (index === 0) { + if (prevX === undefined || Math.abs(screen.x - prevX) > wrapThreshold) { ctx.moveTo(screen.x, screen.y); } else { ctx.lineTo(screen.x, screen.y); } - }); + prevX = screen.x; + } ctx.stroke(); }