feature/dual-rendering #12
@ -12,6 +12,33 @@ import type { BaseMapId, MapProjectionId } from '../types';
|
|||||||
import { kickRepaint, onMapStyleReady } from '../lib/mapCore';
|
import { kickRepaint, onMapStyleReady } from '../lib/mapCore';
|
||||||
import { guardedSetVisibility } from '../lib/layerHelpers';
|
import { guardedSetVisibility } from '../lib/layerHelpers';
|
||||||
|
|
||||||
|
/** Globe tessellation에서 vertex 65535 초과를 방지하기 위해 좌표 수를 줄임.
|
||||||
|
* 수역 폴리곤(해안선 디테일 2100+ vertex)이 globe에서 70,000+로 폭증하므로
|
||||||
|
* ring당 최대 maxPts개로 서브샘플링. 라벨 centroid에는 영향 없음. */
|
||||||
|
function simplifyZonesForGlobe(zones: ZonesGeoJson): ZonesGeoJson {
|
||||||
|
const MAX_PTS = 60;
|
||||||
|
const subsample = (ring: GeoJSON.Position[]): GeoJSON.Position[] => {
|
||||||
|
if (ring.length <= MAX_PTS) return ring;
|
||||||
|
const step = Math.ceil(ring.length / MAX_PTS);
|
||||||
|
const out: GeoJSON.Position[] = [ring[0]];
|
||||||
|
for (let i = step; i < ring.length - 1; i += step) out.push(ring[i]);
|
||||||
|
out.push(ring[0]); // close ring
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
...zones,
|
||||||
|
features: zones.features.map((f) => ({
|
||||||
|
...f,
|
||||||
|
geometry: {
|
||||||
|
...f.geometry,
|
||||||
|
coordinates: f.geometry.coordinates.map((polygon) =>
|
||||||
|
polygon.map((ring) => subsample(ring)),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function useZonesLayer(
|
export function useZonesLayer(
|
||||||
mapRef: MutableRefObject<maplibregl.Map | null>,
|
mapRef: MutableRefObject<maplibregl.Map | null>,
|
||||||
projectionBusyRef: MutableRefObject<boolean>,
|
projectionBusyRef: MutableRefObject<boolean>,
|
||||||
@ -61,11 +88,13 @@ export function useZonesLayer(
|
|||||||
if (!map.isStyleLoaded()) return;
|
if (!map.isStyleLoaded()) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// globe: 서브샘플링된 데이터로 vertex 폭증 방지, mercator: 원본 데이터
|
||||||
|
const sourceData = projection === 'globe' ? simplifyZonesForGlobe(zones) : zones;
|
||||||
const existing = map.getSource(srcId) as GeoJSONSource | undefined;
|
const existing = map.getSource(srcId) as GeoJSONSource | undefined;
|
||||||
if (existing) {
|
if (existing) {
|
||||||
existing.setData(zones);
|
existing.setData(sourceData);
|
||||||
} else {
|
} else {
|
||||||
map.addSource(srcId, { type: 'geojson', data: zones } as GeoJSONSourceSpecification);
|
map.addSource(srcId, { type: 'geojson', data: sourceData } as GeoJSONSourceSpecification);
|
||||||
}
|
}
|
||||||
|
|
||||||
const style = map.getStyle();
|
const style = map.getStyle();
|
||||||
|
|||||||
불러오는 중...
Reference in New Issue
Block a user