fix(tgu-ops-ui): fix track antimeridian wrap and polygon culling on 2D map

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 <noreply@anthropic.com>
This commit is contained in:
Дмитрий Соловьев
2026-05-31 16:08:20 +03:00
parent 4ab765b0ee
commit 6d1b8e7cde
3 changed files with 14 additions and 13 deletions
@@ -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)
});