Use a web worker to calculate, to avoid locking up the browser. Also, use semicolons between points, and fix bug where it is impossible to calculate route when receiving points in the URL

This commit is contained in:
Martin Asprusten
2026-08-29 13:43:19 +02:00
parent eac2a41f18
commit f3a1f058c0
4 changed files with 72 additions and 28 deletions
+29 -24
View File
@@ -1,5 +1,4 @@
import MapHandler from './map/maphandler';
import Module, { type MainModule } from '../native/salesman.js';
import haversine from 'haversine-distance';
import './style.css';
import { LatLng } from 'leaflet';
@@ -8,12 +7,11 @@ import { createUrl, parseUrl } from './url/UrlHandler.js';
import { wktToGeoJSON } from '@terraformer/wkt';
import PPENHandler from './files/ppenhandler.js';
import type { GeoJsonObject } from 'geojson';
import type { SearchStatusMessage, StartSearchMessage } from './worker/messages.js';
// Outside influences
let mapHandler = new MapHandler();
let module: MainModule = await Module();
let worker = new Worker(new URL('./worker/worker.ts', import.meta.url), {type: 'module'});
// HTTP elements to be edited
let clearMapButton = document.getElementById('clear-map');
@@ -57,7 +55,7 @@ mapHandler.addMarkerClickedListener((latLng) => {
awaiting(latLng);
});
awaitingResolutions = [];
})
});
@@ -65,6 +63,7 @@ mapHandler.addMarkerClickedListener((latLng) => {
interface State {
points: LatLng[] | null,
distances: [LatLng, LatLng, number][],
calculating: boolean,
foundPath: number[] | null,
complexPath: GeoJsonObject | null,
@@ -81,7 +80,8 @@ interface State {
let state: State = {
points: null,
distances: [],
foundPath: [],
calculating: false,
foundPath: null,
complexPath: null,
ppenHandler: null,
@@ -122,7 +122,8 @@ function updateState() {
// Always just allow the share link button, do nothing here
// Only allow the calculate route button when we have more than three points, and don't already have a route
if (state.points == null || state.points.length < 3 || state.foundPath != null) {
// Also, disallow the get route button when currently calculating
if (state.points == null || state.points.length < 3 || state.foundPath != null || state.calculating) {
allowCalculateRoute = false;
}
@@ -283,16 +284,24 @@ function updateState() {
}
}
function calculateRoute(): number[] {
// In case of messages from the web worker, do work
worker.onmessage = e => {
let message = e.data as SearchStatusMessage;
state.foundPath = message.path;
state.calculating = false;
updateState();
}
function calculateRoute(): void {
if (!state.points) {
return [];
return;
}
let points: LatLng[] = state.points;
let weights = new module.Weights();
let weights: number[][] = [];
for (var i = 0; i < points.length; i++) {
let weightsRow = new module.WeightsRow();
let weightsRow: number[] = [];
for (var j = 0; j < points.length; j++) {
var distance: number;
if (i == j) {
@@ -312,20 +321,16 @@ function calculateRoute(): number[] {
}
}
weightsRow.push_back(distance);
weightsRow.push(distance);
}
weights.push_back(weightsRow);
weights.push(weightsRow);
}
let path = module.findShortestPath(weights);
var foundPath = [];
for (var i = 0; i < path.size(); i++) {
let pointIndex = path.get(i);
if (typeof pointIndex != 'undefined') {
foundPath.push(pointIndex);
}
}
return foundPath;
let startSearchMessage: StartSearchMessage = {
weights: weights
};
worker.postMessage(startSearchMessage);
}
function populateDistancesTable() {
@@ -788,9 +793,9 @@ shareLinkButton?.addEventListener('click', async _ => {
calculateRouteButton?.addEventListener('click', _ => {
if (calculateRouteButton.classList.contains('clickable')) {
let path = calculateRoute();
state.foundPath = path;
state.calculating = true;
updateState();
calculateRoute();
}
});