Show the calculated speed of the route on the map
This commit is contained in:
parent
8f0759fc63
commit
f0b4479664
@ -279,7 +279,7 @@ float calculate_speed(float starting_speed, float horizontal_distance, float hei
|
|||||||
if (final_speed < minimum_speed) {
|
if (final_speed < minimum_speed) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return std::min(final_speed, maximum_speed);
|
return std::fmin(final_speed, maximum_speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,6 +759,8 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
|||||||
.property("nodeId", &JSNodeInfo::nodeId)
|
.property("nodeId", &JSNodeInfo::nodeId)
|
||||||
.property("positionX", &JSNodeInfo::positionX)
|
.property("positionX", &JSNodeInfo::positionX)
|
||||||
.property("positionY", &JSNodeInfo::positionY)
|
.property("positionY", &JSNodeInfo::positionY)
|
||||||
|
.property("positionZ", &JSNodeInfo::positionZ)
|
||||||
|
.property("currentSpeed", &JSNodeInfo::currentSpeed)
|
||||||
.property("distanceFromStart", &JSNodeInfo::distanceFromStart);
|
.property("distanceFromStart", &JSNodeInfo::distanceFromStart);
|
||||||
|
|
||||||
emscripten::class_<JSSearchResult>("SearchResult")
|
emscripten::class_<JSSearchResult>("SearchResult")
|
||||||
|
|||||||
7
package-lock.json
generated
7
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@geoman-io/leaflet-geoman-free": "^2.18.3",
|
"@geoman-io/leaflet-geoman-free": "^2.18.3",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"@types/leaflet": "^1.9.19",
|
"@types/leaflet": "^1.9.19",
|
||||||
|
"hue-map": "^1.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"proj4": "^2.19.4"
|
"proj4": "^2.19.4"
|
||||||
},
|
},
|
||||||
@ -1096,6 +1097,12 @@
|
|||||||
"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
|
"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/hue-map": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hue-map/-/hue-map-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-L7n6cfthm9ZTdYbqJF1yBflHvI4MaWRg+XMJ4Ifc35jWcOfQlCRBETZ4ntnHLPUyDOse7KeelcsbWxx14Aaa+w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/leaflet": {
|
"node_modules/leaflet": {
|
||||||
"version": "1.9.4",
|
"version": "1.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"@geoman-io/leaflet-geoman-free": "^2.18.3",
|
"@geoman-io/leaflet-geoman-free": "^2.18.3",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"@types/leaflet": "^1.9.19",
|
"@types/leaflet": "^1.9.19",
|
||||||
|
"hue-map": "^1.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"proj4": "^2.19.4"
|
"proj4": "^2.19.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,8 +69,14 @@ export interface Coordinate {
|
|||||||
longitude: number
|
longitude: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PathSegment {
|
||||||
|
start: Coordinate,
|
||||||
|
end: Coordinate,
|
||||||
|
speed: number
|
||||||
|
}
|
||||||
|
|
||||||
interface ReturnFullPath {
|
interface ReturnFullPath {
|
||||||
coordinates: Coordinate[]
|
pathSegments: PathSegment[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Ring {
|
export interface Ring {
|
||||||
|
|||||||
@ -82,7 +82,8 @@ routeWorker.onmessage = e => {
|
|||||||
} else if (message.foundPathsFromNode != null) {
|
} else if (message.foundPathsFromNode != null) {
|
||||||
mapHandler?.drawEndPoints(message.foundPathsFromNode.endpoints);
|
mapHandler?.drawEndPoints(message.foundPathsFromNode.endpoints);
|
||||||
} else if (message.returnFullPath != null) {
|
} else if (message.returnFullPath != null) {
|
||||||
mapHandler?.drawPath(message.returnFullPath.coordinates);
|
let settings = getSettings();
|
||||||
|
mapHandler?.drawPath(message.returnFullPath.pathSegments, settings.minimumSpeed, settings.maximumSpeed);
|
||||||
} else if (message.searchAreaResult != null) {
|
} else if (message.searchAreaResult != null) {
|
||||||
searchStatusParagraph?.setHTMLUnsafe('Searching. ' + message.searchAreaResult.remainingNodes + ' possible starting points remain.');
|
searchStatusParagraph?.setHTMLUnsafe('Searching. ' + message.searchAreaResult.remainingNodes + ' possible starting points remain.');
|
||||||
let currentTime = Date.now();
|
let currentTime = Date.now();
|
||||||
|
|||||||
@ -1,13 +1,20 @@
|
|||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
import L, { FeatureGroup, Marker, Polygon, Polyline, type LatLngTuple } from 'leaflet';
|
import L, { FeatureGroup, Marker, Polygon, type LatLngTuple } from 'leaflet';
|
||||||
import '@geoman-io/leaflet-geoman-free'
|
import '@geoman-io/leaflet-geoman-free'
|
||||||
import '@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css'
|
import '@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css'
|
||||||
|
|
||||||
import './maphandler.css'
|
import './maphandler.css'
|
||||||
import { greenIcon, redIcon, violetIcon } from './icons.ts'
|
import { greenIcon, redIcon, violetIcon } from './icons.ts'
|
||||||
import type { Endpoint, Coordinate, Polygon as InterfacePolygon } from '../../interfaces.ts'
|
import type { Endpoint, Polygon as InterfacePolygon, PathSegment } from '../../interfaces.ts'
|
||||||
import type { Position } from 'geojson';
|
import type { Position } from 'geojson';
|
||||||
|
|
||||||
|
import { createPalette } from 'hue-map';
|
||||||
|
|
||||||
|
const viridisPalette = createPalette({
|
||||||
|
map: 'inferno',
|
||||||
|
steps: 100
|
||||||
|
});
|
||||||
|
|
||||||
interface ClickedMapListener {
|
interface ClickedMapListener {
|
||||||
(latitude: number, longitude: number): void;
|
(latitude: number, longitude: number): void;
|
||||||
}
|
}
|
||||||
@ -44,7 +51,7 @@ class MapHandler {
|
|||||||
|
|
||||||
startMarker?: Marker;
|
startMarker?: Marker;
|
||||||
endMarkers: FeatureGroup;
|
endMarkers: FeatureGroup;
|
||||||
path?: Polyline;
|
path: FeatureGroup;
|
||||||
|
|
||||||
editingPolygons: boolean = false;
|
editingPolygons: boolean = false;
|
||||||
|
|
||||||
@ -150,6 +157,7 @@ class MapHandler {
|
|||||||
this.searchAreaFeatureGroup = new L.FeatureGroup().addTo(this.map);
|
this.searchAreaFeatureGroup = new L.FeatureGroup().addTo(this.map);
|
||||||
this.exclusionAreaFeatureGroup = new L.FeatureGroup().addTo(this.map);
|
this.exclusionAreaFeatureGroup = new L.FeatureGroup().addTo(this.map);
|
||||||
this.endMarkers = new L.FeatureGroup().addTo(this.map);
|
this.endMarkers = new L.FeatureGroup().addTo(this.map);
|
||||||
|
this.path = new L.FeatureGroup().addTo(this.map);
|
||||||
|
|
||||||
this.map.addEventListener('click', e => {
|
this.map.addEventListener('click', e => {
|
||||||
if (!this.editingPolygons) {
|
if (!this.editingPolygons) {
|
||||||
@ -252,10 +260,7 @@ class MapHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public drawStartNode(nodeId: number, latitude: number, longitude: number): void {
|
public drawStartNode(nodeId: number, latitude: number, longitude: number): void {
|
||||||
if (this.path != null) {
|
this.path.clearLayers();
|
||||||
this.map.removeLayer(this.path);
|
|
||||||
this.path = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.startMarker != null) {
|
if (this.startMarker != null) {
|
||||||
this.map.removeLayer(this.startMarker);
|
this.map.removeLayer(this.startMarker);
|
||||||
@ -268,10 +273,7 @@ class MapHandler {
|
|||||||
|
|
||||||
public drawEndPoints(endpoints: Endpoint[]): void {
|
public drawEndPoints(endpoints: Endpoint[]): void {
|
||||||
this.endMarkers.clearLayers();
|
this.endMarkers.clearLayers();
|
||||||
if (this.path != null) {
|
this.path.clearLayers();
|
||||||
this.map.removeLayer(this.path);
|
|
||||||
this.path = undefined;
|
|
||||||
}
|
|
||||||
var firstMarker = true;
|
var firstMarker = true;
|
||||||
endpoints.forEach(endpoint => {
|
endpoints.forEach(endpoint => {
|
||||||
var settings;
|
var settings;
|
||||||
@ -303,17 +305,21 @@ class MapHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawPath(coordinates: Coordinate[]): void {
|
public drawPath(pathSegments: PathSegment[], minimumSpeed: number, maximumSpeed: number): void {
|
||||||
if (this.path != null) {
|
this.path.clearLayers();
|
||||||
this.map.removeLayer(this.path);
|
pathSegments.forEach(pathSegment => {
|
||||||
}
|
let startLeafletCoordinate: LatLngTuple = [pathSegment.start.latitude, pathSegment.start.longitude];
|
||||||
|
let endLeafletCoordinate: LatLngTuple = [pathSegment.end.latitude, pathSegment.end.longitude];
|
||||||
|
let leafletCoordinates = [startLeafletCoordinate, endLeafletCoordinate];
|
||||||
|
|
||||||
var leafletCoordinates = coordinates.map(coordinate => {
|
let intensity = Math.round((pathSegment.speed - minimumSpeed) * 99.0 / (maximumSpeed - minimumSpeed));
|
||||||
let latLngTuple: LatLngTuple = [coordinate.latitude, coordinate.longitude];
|
intensity = Math.min(Math.max(intensity, 0), 99);
|
||||||
return latLngTuple;
|
let color = viridisPalette.format('cssHex')[99-intensity];
|
||||||
|
|
||||||
|
let polyLine = L.polyline(leafletCoordinates, {color: color}).addTo(this.path);
|
||||||
|
let speedKmh = pathSegment.speed * 3.6;
|
||||||
|
polyLine.bindTooltip(Math.round(speedKmh) + '.' + (Math.round(speedKmh * 10.0) % 10) + ' km/h');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.path = L.polyline(leafletCoordinates).addTo(this.map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enableEditing() {
|
public enableEditing() {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Module, { type AreaSearchEntries, type MainModule, type MultiPolygon } from '../../../native/route_search.js';
|
import Module, { type AreaSearchEntries, type MainModule, type MultiPolygon } from '../../../native/route_search.js';
|
||||||
import proj4 from 'proj4';
|
import proj4 from 'proj4';
|
||||||
|
|
||||||
import type { Endpoint, Message, Polygon, SearchAreaResultEntry } from '../../interfaces';
|
import type { Endpoint, Message, PathSegment, Polygon, SearchAreaResultEntry } from '../../interfaces';
|
||||||
|
|
||||||
var dataLoaded = false;
|
var dataLoaded = false;
|
||||||
var module: MainModule | undefined = undefined;
|
var module: MainModule | undefined = undefined;
|
||||||
@ -133,22 +133,40 @@ onmessage = async (e) => {
|
|||||||
sendErrorMessage('Could not get path');
|
sendErrorMessage('Could not get path');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var coordinates = [];
|
let pathSegments: PathSegment[] = []
|
||||||
for (var i = 0; i < path.size(); i++) {
|
for (var i = 1; i < path.size(); i++) {
|
||||||
let currentPoint = path.get(i);
|
let currentPoint = path.get(i);
|
||||||
if (!currentPoint) {
|
if (!currentPoint) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
coordinates.push([currentPoint.positionX, currentPoint.positionY]);
|
let previousPoint = path.get(i-1);
|
||||||
|
if (!previousPoint) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let previousUtm = [previousPoint.positionX, previousPoint.positionY];
|
||||||
|
let currentUtm = [currentPoint.positionX, currentPoint.positionY];
|
||||||
|
|
||||||
|
let previousLngLat = proj4('EPSG:32633', 'EPSG:4326', previousUtm);
|
||||||
|
let currentLngLat = proj4('EPSG:32633', 'EPSG:4326', currentUtm);
|
||||||
|
|
||||||
|
let speed = Math.max(previousPoint.currentSpeed, currentPoint.currentSpeed);
|
||||||
|
let segment: PathSegment = {
|
||||||
|
start: {
|
||||||
|
latitude: previousLngLat[1],
|
||||||
|
longitude: previousLngLat[0]
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
latitude: currentLngLat[1],
|
||||||
|
longitude: currentLngLat[0]
|
||||||
|
},
|
||||||
|
speed: speed
|
||||||
|
}
|
||||||
|
|
||||||
|
pathSegments.push(segment);
|
||||||
}
|
}
|
||||||
path.delete();
|
path.delete();
|
||||||
|
|
||||||
coordinates = coordinates.map(utmCoordinate => {
|
let returnMessage: Message = {returnFullPath: {pathSegments: pathSegments}};
|
||||||
let lngLat = proj4('EPSG:32633', 'EPSG:4326', utmCoordinate);
|
|
||||||
return {latitude: lngLat[1], longitude: lngLat[0]};
|
|
||||||
});
|
|
||||||
|
|
||||||
let returnMessage: Message = {returnFullPath: {coordinates: coordinates}};
|
|
||||||
postMessage(returnMessage);
|
postMessage(returnMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user