diff --git a/src/ExclusionCircle.ts b/src/ExclusionCircle.ts index cacb6a4..3d321e2 100644 --- a/src/ExclusionCircle.ts +++ b/src/ExclusionCircle.ts @@ -8,11 +8,14 @@ import { tagsToHTML } from './overpass.ts'; import { Circle, FeatureGroup, Polygon } from 'leaflet'; +// @ts-ignore +import { buffer, truncate } from '@turf/turf'; export class ExclusionCircle extends FeatureGroup { readonly id: string; readonly element: NWRElement; readonly reason: BannedArea; + readonly buffer: ReturnType | null = null; constructor(e: NWRElement) { super(); @@ -36,7 +39,9 @@ export class ExclusionCircle extends FeatureGroup { if (isWay(m)) { m.geometry.length > 3 ? this.addLayer(this.getPolygon(m.geometry, color)) - : this.addLayer(this.getCircle(m.geometry[0], color)); + : m.geometry.forEach((g) => + this.addLayer(this.getCircle(g, color)) + ); } else if (isNode(m)) { this.addLayer(this.getCircle(m, color)); } @@ -47,7 +52,17 @@ export class ExclusionCircle extends FeatureGroup { this.id = e.id; this.element = e; this.reason = reason; - + try { + this.buffer = truncate( + buffer(this.toGeoJSON(), 100, { units: 'meters' }) + ); + } catch (err) { + console.error( + `Buffer calc for id=${e.id}, type=${e.type} failed`, + e, + err + ); + } this.bindPopup( `
${tagsToHTML({ reason, ...e.tags })}↗ Auf OpenStreetMap öffnen
`, { maxWidth: 500 } diff --git a/src/buffer.ts b/src/buffer.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.ts b/src/main.ts index 5122f57..38d01e9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,21 +6,20 @@ import { FeatureGroup, GeoJSON, Map as LMap, + Polygon, Popup, TileLayer } from 'leaflet'; import 'leaflet-easybutton'; import { BannedArea, BannedAreas, NWRElement } from './overpass.ts'; import { colorMap, ExclusionCircle } from './ExclusionCircle.ts'; -import { - buffer, - dissolve, - featureCollection, - FeatureCollection, - truncate -} from '@turf/turf'; +// @ts-ignore +import { FeatureCollection, truncate } from '@turf/turf'; // @ts-ignore import type { Feature } from '@turf/helpers'; +import workerUrl from './worker/worker.ts?worker&url'; + +const worker = new Worker(workerUrl, { type: 'module' }); const m_mono = new TileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', @@ -70,8 +69,18 @@ map.on('moveend', async () => { }); let loading = false; +worker.addEventListener( + 'message', + (b: MessageEvent>) => { + exclusionZone.clearLayers(); + const zone = new GeoJSON(b.data, { + style: { color: 'red', fillOpacity: 0.1, weight: 1 } + }); + exclusionZone.addLayer(zone); + exclusionZone.bringToBack(); + } +); function showBuffer() { - console.time('prepare'); map.attributionControl.setPrefix('Berechne Zone'); const fs = Object.entries(buffers) .filter(([k]) => map.hasLayer(features[k as keyof typeof features])) @@ -83,22 +92,7 @@ function showBuffer() { }); if (fs.length > 0) { - exclusionZone.clearLayers(); - console.timeEnd('prepare'); - try { - console.time('dissolve'); - const b = dissolve(featureCollection(fs)); - const zone = new GeoJSON(b, { - style: { color: 'red', fillOpacity: 0.1, weight: 1 } - }); - console.timeEnd('dissolve'); - console.time('render'); - exclusionZone.addLayer(zone); - console.timeEnd('render'); - exclusionZone.bringToBack(); - } catch (err) { - console.error('dissolve', err); - } + worker.postMessage(fs); } map.attributionControl.setPrefix(''); } @@ -145,7 +139,6 @@ out geom;`; .then((r) => r.elements as NWRElement[]); loading = false; - console.time('parse'); map.attributionControl.setPrefix('Berechne Orte...'); const ids = elements.map((e) => e.id); const exclude: ExclusionCircle[] = []; @@ -168,20 +161,10 @@ out geom;`; } features[marker.reason].addLayer(marker); - try { - const b = buffer(marker.toGeoJSON(), 100, { units: 'meters' }); - - // new GeoJSON(b).addTo(map); - buffers[marker.reason].push(truncate(b)); - } catch (err) { - console.error( - `Buffer calc for id=${e.id}, type=${e.type} failed`, - e, - err - ); + if (marker.buffer) { + buffers[marker.reason].push(marker.buffer); } }); - console.timeEnd('parse'); queueMicrotask(showBuffer); map.attributionControl.setPrefix(''); diff --git a/src/worker/worker.ts b/src/worker/worker.ts new file mode 100644 index 0000000..ff6400a --- /dev/null +++ b/src/worker/worker.ts @@ -0,0 +1,13 @@ +// @ts-ignore +import { Feature } from '@turf/helpers'; +// @ts-ignore +import { dissolve, featureCollection } from '@turf/turf'; + +self.onmessage = function (e: MessageEvent) { + try { + const b = dissolve(featureCollection(e.data)); + self.postMessage(b); + } catch (err) { + console.error('dissolve', err); + } +};