Move buffer dissolve to worker
This commit is contained in:
+17
-2
@@ -8,11 +8,14 @@ import {
|
|||||||
tagsToHTML
|
tagsToHTML
|
||||||
} from './overpass.ts';
|
} from './overpass.ts';
|
||||||
import { Circle, FeatureGroup, Polygon } from 'leaflet';
|
import { Circle, FeatureGroup, Polygon } from 'leaflet';
|
||||||
|
// @ts-ignore
|
||||||
|
import { buffer, truncate } from '@turf/turf';
|
||||||
|
|
||||||
export class ExclusionCircle extends FeatureGroup<Polygon | Circle> {
|
export class ExclusionCircle extends FeatureGroup<Polygon | Circle> {
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly element: NWRElement;
|
readonly element: NWRElement;
|
||||||
readonly reason: BannedArea;
|
readonly reason: BannedArea;
|
||||||
|
readonly buffer: ReturnType<buffer> | null = null;
|
||||||
|
|
||||||
constructor(e: NWRElement) {
|
constructor(e: NWRElement) {
|
||||||
super();
|
super();
|
||||||
@@ -36,7 +39,9 @@ export class ExclusionCircle extends FeatureGroup<Polygon | Circle> {
|
|||||||
if (isWay(m)) {
|
if (isWay(m)) {
|
||||||
m.geometry.length > 3
|
m.geometry.length > 3
|
||||||
? this.addLayer(this.getPolygon(m.geometry, color))
|
? 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)) {
|
} else if (isNode(m)) {
|
||||||
this.addLayer(this.getCircle(m, color));
|
this.addLayer(this.getCircle(m, color));
|
||||||
}
|
}
|
||||||
@@ -47,7 +52,17 @@ export class ExclusionCircle extends FeatureGroup<Polygon | Circle> {
|
|||||||
this.id = e.id;
|
this.id = e.id;
|
||||||
this.element = e;
|
this.element = e;
|
||||||
this.reason = reason;
|
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(
|
this.bindPopup(
|
||||||
`<div class="whitespace-pre-wrap flex flex-col gap-3">${tagsToHTML({ reason, ...e.tags })}<a href="https://www.openstreetmap.org/${e.type}/${e.id}" target="_blank">↗ Auf OpenStreetMap öffnen</a></div>`,
|
`<div class="whitespace-pre-wrap flex flex-col gap-3">${tagsToHTML({ reason, ...e.tags })}<a href="https://www.openstreetmap.org/${e.type}/${e.id}" target="_blank">↗ Auf OpenStreetMap öffnen</a></div>`,
|
||||||
{ maxWidth: 500 }
|
{ maxWidth: 500 }
|
||||||
|
|||||||
+20
-37
@@ -6,21 +6,20 @@ import {
|
|||||||
FeatureGroup,
|
FeatureGroup,
|
||||||
GeoJSON,
|
GeoJSON,
|
||||||
Map as LMap,
|
Map as LMap,
|
||||||
|
Polygon,
|
||||||
Popup,
|
Popup,
|
||||||
TileLayer
|
TileLayer
|
||||||
} from 'leaflet';
|
} from 'leaflet';
|
||||||
import 'leaflet-easybutton';
|
import 'leaflet-easybutton';
|
||||||
import { BannedArea, BannedAreas, NWRElement } from './overpass.ts';
|
import { BannedArea, BannedAreas, NWRElement } from './overpass.ts';
|
||||||
import { colorMap, ExclusionCircle } from './ExclusionCircle.ts';
|
import { colorMap, ExclusionCircle } from './ExclusionCircle.ts';
|
||||||
import {
|
// @ts-ignore
|
||||||
buffer,
|
import { FeatureCollection, truncate } from '@turf/turf';
|
||||||
dissolve,
|
|
||||||
featureCollection,
|
|
||||||
FeatureCollection,
|
|
||||||
truncate
|
|
||||||
} from '@turf/turf';
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import type { Feature } from '@turf/helpers';
|
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(
|
const m_mono = new TileLayer(
|
||||||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||||
@@ -70,8 +69,18 @@ map.on('moveend', async () => {
|
|||||||
});
|
});
|
||||||
let loading = false;
|
let loading = false;
|
||||||
|
|
||||||
|
worker.addEventListener(
|
||||||
|
'message',
|
||||||
|
(b: MessageEvent<FeatureCollection<Polygon>>) => {
|
||||||
|
exclusionZone.clearLayers();
|
||||||
|
const zone = new GeoJSON(b.data, {
|
||||||
|
style: { color: 'red', fillOpacity: 0.1, weight: 1 }
|
||||||
|
});
|
||||||
|
exclusionZone.addLayer(zone);
|
||||||
|
exclusionZone.bringToBack();
|
||||||
|
}
|
||||||
|
);
|
||||||
function showBuffer() {
|
function showBuffer() {
|
||||||
console.time('prepare');
|
|
||||||
map.attributionControl.setPrefix('Berechne Zone');
|
map.attributionControl.setPrefix('Berechne Zone');
|
||||||
const fs = Object.entries(buffers)
|
const fs = Object.entries(buffers)
|
||||||
.filter(([k]) => map.hasLayer(features[k as keyof typeof features]))
|
.filter(([k]) => map.hasLayer(features[k as keyof typeof features]))
|
||||||
@@ -83,22 +92,7 @@ function showBuffer() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (fs.length > 0) {
|
if (fs.length > 0) {
|
||||||
exclusionZone.clearLayers();
|
worker.postMessage(fs);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
map.attributionControl.setPrefix('');
|
map.attributionControl.setPrefix('');
|
||||||
}
|
}
|
||||||
@@ -145,7 +139,6 @@ out geom;`;
|
|||||||
.then((r) => r.elements as NWRElement[]);
|
.then((r) => r.elements as NWRElement[]);
|
||||||
|
|
||||||
loading = false;
|
loading = false;
|
||||||
console.time('parse');
|
|
||||||
map.attributionControl.setPrefix('Berechne Orte...');
|
map.attributionControl.setPrefix('Berechne Orte...');
|
||||||
const ids = elements.map((e) => e.id);
|
const ids = elements.map((e) => e.id);
|
||||||
const exclude: ExclusionCircle[] = [];
|
const exclude: ExclusionCircle[] = [];
|
||||||
@@ -168,20 +161,10 @@ out geom;`;
|
|||||||
}
|
}
|
||||||
|
|
||||||
features[marker.reason].addLayer(marker);
|
features[marker.reason].addLayer(marker);
|
||||||
try {
|
if (marker.buffer) {
|
||||||
const b = buffer(marker.toGeoJSON(), 100, { units: 'meters' });
|
buffers[marker.reason].push(marker.buffer);
|
||||||
|
|
||||||
// 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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.timeEnd('parse');
|
|
||||||
|
|
||||||
queueMicrotask(showBuffer);
|
queueMicrotask(showBuffer);
|
||||||
map.attributionControl.setPrefix('');
|
map.attributionControl.setPrefix('');
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
import { Feature } from '@turf/helpers';
|
||||||
|
// @ts-ignore
|
||||||
|
import { dissolve, featureCollection } from '@turf/turf';
|
||||||
|
|
||||||
|
self.onmessage = function (e: MessageEvent<Feature[]>) {
|
||||||
|
try {
|
||||||
|
const b = dissolve(featureCollection(e.data));
|
||||||
|
self.postMessage(b);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('dissolve', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user