Allow reverse search, where you find the farthest start point from a given end point
This commit is contained in:
parent
2ca8a14d8f
commit
dc2e8170a4
@ -32,6 +32,9 @@
|
||||
<br />
|
||||
<button id="search-button">Start search</button>
|
||||
<button id="export-route-button">Export KML route</button>
|
||||
<br />
|
||||
<label for="reverse-search-input">Reverse search:</label><input type="checkbox" id="reverse-search-input" />
|
||||
<br />
|
||||
<p id="search-status-paragraph"></p>
|
||||
<table id="search-result-table" style="display: none;">
|
||||
<thead>
|
||||
@ -80,6 +83,10 @@
|
||||
end points are shown as purple circles. Click an endpoint to see the calculated route that leads from the start point
|
||||
to the end point.
|
||||
</p>
|
||||
<p>
|
||||
It is also possible to reverse the search, to find the farthest start point from a given end point. When this is done,
|
||||
farthest possible start point is shown in green, and other candidate start points are shown in orange.
|
||||
</p>
|
||||
<p>
|
||||
It is possible to mark areas on the map you would like to avoid. Click the "Draw areas that should not be
|
||||
entered" button at the top left of the map. It is marked with this icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20px"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. --> <path d="M367.2 412.5L99.5 144.8C77.1 176.1 64 214.5 64 256c0 106 86 192 192 192c41.5 0 79.9-13.1 111.2-35.5zm45.3-45.3C434.9 335.9 448 297.5 448 256c0-106-86-192-192-192c-41.5 0-79.9 13.1-111.2 35.5L412.5 367.2zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z"/></svg>.
|
||||
|
||||
@ -51,6 +51,7 @@ struct SearchResult {
|
||||
uint32_t startingNode;
|
||||
std::map<uint32_t, uint32_t> previous;
|
||||
std::map<uint32_t, SearchNodeInfo> reachableNodes;
|
||||
bool reverse;
|
||||
};
|
||||
|
||||
struct JSNodeInfo {
|
||||
@ -65,6 +66,7 @@ struct JSNodeInfo {
|
||||
|
||||
struct JSSearchResult {
|
||||
std::vector<JSNodeInfo> endPoints;
|
||||
bool reverse;
|
||||
};
|
||||
|
||||
struct ListNode {
|
||||
@ -240,57 +242,51 @@ JSNodeInfo findClosestNode(float positionX, float positionY) {
|
||||
return result;
|
||||
}
|
||||
|
||||
float calculateSpeed(float startingSpeed, float horizontalDistance, float heightDifference, float minimumSpeed, float maximumSpeed, float dragCoefficient) {
|
||||
float calculateSpeed(float startingSpeed, float horizontalDistance, float heightDifference, float dragCoefficient) {
|
||||
float slopeTan = heightDifference / horizontalDistance;
|
||||
float finalSpeed = -1;
|
||||
|
||||
// If the slope is flat, that is one calculation
|
||||
if (fabs(slopeTan) < 0.0001) {
|
||||
float timeToFinish = (exp(horizontalDistance * dragCoefficient) - 1) / (startingSpeed * dragCoefficient);
|
||||
finalSpeed = startingSpeed / (startingSpeed * dragCoefficient * timeToFinish + 1);
|
||||
} else {
|
||||
// Otherwise, we need to find some parameters
|
||||
float slope = atan(slopeTan);
|
||||
float slopeSin = sin(slope);
|
||||
float fullDistance = horizontalDistance * slopeTan / slopeSin;
|
||||
float acceleration = -GRAVITY_ACCELERATION * slopeSin;
|
||||
float terminalVelocity = sqrt(fabs(acceleration) / dragCoefficient);
|
||||
|
||||
// Uphill
|
||||
if (slope > 0) {
|
||||
float timeToPeak = atan(startingSpeed / terminalVelocity) / (dragCoefficient * terminalVelocity);
|
||||
// If the discriminant is greater than 1, the slope is so steep that we cannot reach the end with our starting speed
|
||||
float discriminant = cos(dragCoefficient * terminalVelocity * timeToPeak) * exp(fullDistance * dragCoefficient);
|
||||
if (discriminant > 1.f) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float timeToReachEnd = timeToPeak - acos(discriminant) / (dragCoefficient * terminalVelocity);
|
||||
finalSpeed = terminalVelocity * tan(dragCoefficient * terminalVelocity * (timeToPeak - timeToReachEnd));
|
||||
} else {
|
||||
// Downhill
|
||||
// If the starting speed is very close to the terminal velocity, we'll just stay at terminal velocity
|
||||
if (fabs(startingSpeed - terminalVelocity) < 0.001) {
|
||||
finalSpeed = terminalVelocity;
|
||||
} else if (startingSpeed < terminalVelocity) {
|
||||
float k1 = terminalVelocity * log((terminalVelocity + startingSpeed) / (terminalVelocity - startingSpeed)) * 0.5;
|
||||
float k2 = -log(cosh(k1 / terminalVelocity)) / dragCoefficient;
|
||||
float timeSpent = acosh(exp(dragCoefficient * (fullDistance - k2))) / (dragCoefficient * terminalVelocity) - k1 / (dragCoefficient * pow(terminalVelocity, 2));
|
||||
finalSpeed = terminalVelocity * tanh(dragCoefficient * terminalVelocity * timeSpent + k1 / terminalVelocity);
|
||||
} else if (startingSpeed > terminalVelocity) {
|
||||
float k1 = log((startingSpeed - terminalVelocity) / (startingSpeed + terminalVelocity)) * terminalVelocity / 2;
|
||||
float k2 = -log(-sinh(k1 / terminalVelocity)) / dragCoefficient;
|
||||
float timeSpent = k1 / (dragCoefficient * pow(terminalVelocity, 2)) - asinh(-exp(dragCoefficient * (fullDistance - k2))) / (dragCoefficient * terminalVelocity);
|
||||
finalSpeed = -terminalVelocity / tanh(k1 / terminalVelocity - dragCoefficient * terminalVelocity * timeSpent);
|
||||
}
|
||||
return startingSpeed * exp(-dragCoefficient * horizontalDistance);
|
||||
}
|
||||
|
||||
// If the slope is not flat, we should calculate some trig identities, and how long the slope is
|
||||
float slope = atan(slopeTan);
|
||||
float slopeSin = sin(slope);
|
||||
float fullDistance = horizontalDistance * slopeTan / slopeSin;
|
||||
|
||||
// We need to calculate the terminal velocity given the slope we're in
|
||||
float terminalVelocity = sqrt(fabs(GRAVITY_ACCELERATION * slopeSin) / dragCoefficient);
|
||||
|
||||
// First, calculate the final speed if we're going uphill
|
||||
if (slope > 0) {
|
||||
float timeToPeak = atan(startingSpeed / terminalVelocity) / (dragCoefficient * terminalVelocity);
|
||||
float discriminant = exp(fullDistance * dragCoefficient) * cos(dragCoefficient * terminalVelocity * timeToPeak);
|
||||
if (discriminant > 1.f) {
|
||||
// If this value is greater than 1, it means that the slope is too steep and we can never reach the top with our
|
||||
// starting speed
|
||||
return -1;
|
||||
}
|
||||
return terminalVelocity * tan(acos(discriminant));
|
||||
}
|
||||
|
||||
if (finalSpeed < minimumSpeed) {
|
||||
return -1;
|
||||
} else {
|
||||
return std::fmin(finalSpeed, maximumSpeed);
|
||||
|
||||
// Downhill must be split in three: starting slower than terminal velocity, starting at terminal velocity, and starting
|
||||
// above terminal velocity
|
||||
if (fabs(startingSpeed - terminalVelocity) < 0.0001) {
|
||||
return terminalVelocity;
|
||||
}
|
||||
|
||||
// If we're going faster than terminal velocity
|
||||
if (startingSpeed > terminalVelocity) {
|
||||
float k1 = log((startingSpeed - terminalVelocity) / (startingSpeed + terminalVelocity));
|
||||
float tanhInput = asinh(exp(dragCoefficient * fullDistance)*sinh(k1 * 0.5));
|
||||
return -terminalVelocity / tanh(tanhInput);
|
||||
}
|
||||
|
||||
// We only get here if we're going slower than terminal velocity
|
||||
float k1 = log((terminalVelocity + startingSpeed) / (terminalVelocity - startingSpeed));
|
||||
float tanhInput = acosh(exp(dragCoefficient * fullDistance) * cosh(k1 * 0.5));
|
||||
return terminalVelocity * tanh(tanhInput);
|
||||
}
|
||||
|
||||
float calculateRequiredSpeed(float endSpeed, float horizontalDistance, float heightDifference, float dragCoefficient) {
|
||||
@ -352,8 +348,9 @@ void getNeighbourConnections(RoadNode node, Connection* targetArray, int &number
|
||||
}
|
||||
}
|
||||
|
||||
SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float maximumSpeed, int maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed) {
|
||||
SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float maximumSpeed, int maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed, bool reverse) {
|
||||
SearchResult result;
|
||||
result.reverse = reverse;
|
||||
result.startingNode = startingNode;
|
||||
|
||||
RoadNode firstNode = set.roadNodes[startingNode];
|
||||
@ -363,11 +360,11 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float m
|
||||
result.reachableNodes[startingNode] = firstNodeInfo;
|
||||
|
||||
ListNode *nextNode = new ListNode;
|
||||
|
||||
|
||||
nextNode->id = startingNode;
|
||||
nextNode->currentSpeed = minimumSpeed;
|
||||
nextNode->currentCourse = 0;
|
||||
|
||||
|
||||
while (nextNode != NULL) {
|
||||
ListNode *currentNode = nextNode;
|
||||
nextNode = currentNode->next;
|
||||
@ -408,12 +405,22 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float m
|
||||
|
||||
RoadNode neighbourNode = set.roadNodes[neighbour.connectedPointNumber];
|
||||
float heightDifference = neighbourNode.positionZ - bestNode.positionZ;
|
||||
float resultingSpeed = calculateSpeed(currentSpeed, neighbour.distance, heightDifference, minimumSpeed, maximumSpeed, dragCoefficient);
|
||||
|
||||
if (resultingSpeed < 0) {
|
||||
continue;
|
||||
float resultingSpeed = -1;
|
||||
if (!reverse) {
|
||||
resultingSpeed = calculateSpeed(currentSpeed, neighbour.distance, heightDifference, dragCoefficient);
|
||||
if (resultingSpeed < minimumSpeed) {
|
||||
continue;
|
||||
}
|
||||
resultingSpeed = fmin(resultingSpeed, maximumSpeed);
|
||||
} else {
|
||||
resultingSpeed = calculateRequiredSpeed(currentSpeed, neighbour.distance, -heightDifference, dragCoefficient);
|
||||
if (resultingSpeed > maximumSpeed) {
|
||||
continue;
|
||||
}
|
||||
resultingSpeed = fmax(resultingSpeed, minimumSpeed);
|
||||
}
|
||||
|
||||
|
||||
// If we limit the speed on corners, do that here
|
||||
if (limitCornerSpeed) {
|
||||
float courseDifference = fabs(currentCourse - neighbour.course);
|
||||
@ -421,18 +428,34 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float m
|
||||
courseDifference = 360 - courseDifference;
|
||||
}
|
||||
|
||||
float maximumCornerSpeed;
|
||||
if (courseDifference > 95) {
|
||||
resultingSpeed = minimumSpeed;
|
||||
maximumCornerSpeed = minimumSpeed;
|
||||
} else if (courseDifference > 45.0) {
|
||||
float maximumCornerSpeed = (95 - courseDifference) / 50.0 * (maximumSpeed - minimumSpeed) + minimumSpeed;
|
||||
resultingSpeed = fmin(resultingSpeed, maximumCornerSpeed);
|
||||
maximumCornerSpeed = (95 - courseDifference) / 50.0 * (maximumSpeed - minimumSpeed) + minimumSpeed;
|
||||
} else {
|
||||
maximumCornerSpeed = maximumSpeed;
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
if (resultingSpeed > maximumCornerSpeed) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
resultingSpeed = fmin(maximumCornerSpeed, resultingSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this node is already in the reachable nodes map
|
||||
auto resultIterator = result.reachableNodes.find(neighbour.connectedPointNumber);
|
||||
if (resultIterator != result.reachableNodes.end() && resultingSpeed <= resultIterator->second.currentSpeed) {
|
||||
continue;
|
||||
if (reverse) {
|
||||
if (resultIterator != result.reachableNodes.end() && resultingSpeed >= resultIterator->second.currentSpeed) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (resultIterator != result.reachableNodes.end() && resultingSpeed <= resultIterator->second.currentSpeed) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
SearchNodeInfo reachableNodeInfo;
|
||||
@ -447,20 +470,38 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float m
|
||||
neighbourListNode->currentSpeed = reachableNodeInfo.currentSpeed;
|
||||
neighbourListNode->currentCourse = neighbour.course;
|
||||
|
||||
if (nextNode == NULL || resultingSpeed < nextNode->currentSpeed) {
|
||||
neighbourListNode->next = nextNode;
|
||||
nextNode = neighbourListNode;
|
||||
} else {
|
||||
ListNode* previousSearchNode = nextNode;
|
||||
ListNode* currentSearchNode = nextNode->next;
|
||||
|
||||
while(currentSearchNode != NULL && currentSearchNode->currentSpeed > resultingSpeed) {
|
||||
previousSearchNode = currentSearchNode;
|
||||
currentSearchNode = currentSearchNode->next;
|
||||
if (reverse) {
|
||||
if (nextNode == NULL || resultingSpeed > nextNode->currentSpeed) {
|
||||
neighbourListNode->next = nextNode;
|
||||
nextNode = neighbourListNode;
|
||||
} else {
|
||||
ListNode* previousSearchNode = nextNode;
|
||||
ListNode* currentSearchNode = nextNode->next;
|
||||
|
||||
while (currentSearchNode != NULL && currentSearchNode->currentSpeed < resultingSpeed) {
|
||||
previousSearchNode = currentSearchNode;
|
||||
currentSearchNode = currentSearchNode->next;
|
||||
}
|
||||
|
||||
previousSearchNode->next = neighbourListNode;
|
||||
neighbourListNode->next = currentSearchNode;
|
||||
}
|
||||
} else {
|
||||
if (nextNode == NULL || resultingSpeed < nextNode->currentSpeed) {
|
||||
neighbourListNode->next = nextNode;
|
||||
nextNode = neighbourListNode;
|
||||
} else {
|
||||
ListNode* previousSearchNode = nextNode;
|
||||
ListNode* currentSearchNode = nextNode->next;
|
||||
|
||||
while(currentSearchNode != NULL && currentSearchNode->currentSpeed > resultingSpeed) {
|
||||
previousSearchNode = currentSearchNode;
|
||||
currentSearchNode = currentSearchNode->next;
|
||||
}
|
||||
|
||||
previousSearchNode->next = neighbourListNode;
|
||||
neighbourListNode->next = currentSearchNode;
|
||||
}
|
||||
|
||||
previousSearchNode->next = neighbourListNode;
|
||||
neighbourListNode->next = currentSearchNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -468,8 +509,8 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimumSpeed, float m
|
||||
return result;
|
||||
}
|
||||
|
||||
JSSearchResult findAllPathsFromPointJS(int startingNode, float minimumSpeed, float maximumSpeed, int maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed) {
|
||||
lastSearchResult = findAllPathsFromPoint(startingNode, minimumSpeed, maximumSpeed, maximumSpeedLimit, dragCoefficient, allowMotorways, allowTunnels, allowAgainstOneway, limitCornerSpeed);
|
||||
JSSearchResult findAllPathsFromPointJS(int startingNode, float minimumSpeed, float maximumSpeed, int maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed, bool reverse) {
|
||||
lastSearchResult = findAllPathsFromPoint(startingNode, minimumSpeed, maximumSpeed, maximumSpeedLimit, dragCoefficient, allowMotorways, allowTunnels, allowAgainstOneway, limitCornerSpeed, reverse);
|
||||
|
||||
float startX = set.roadNodes[startingNode].positionX;
|
||||
float startY = set.roadNodes[startingNode].positionY;
|
||||
@ -520,6 +561,7 @@ JSSearchResult findAllPathsFromPointJS(int startingNode, float minimumSpeed, flo
|
||||
|
||||
JSSearchResult searchResult;
|
||||
searchResult.endPoints = filteredEndpoints;
|
||||
searchResult.reverse = lastSearchResult.reverse;
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
@ -560,6 +602,10 @@ std::vector<JSNodeInfo> getPathJS(uint32_t startingNode, uint32_t endNode, float
|
||||
path.push_back(nodeInfo);
|
||||
}
|
||||
|
||||
if (lastSearchResult.reverse) {
|
||||
std::reverse(path.begin(), path.end());
|
||||
}
|
||||
|
||||
float currentRequiredSpeed = -1.0;
|
||||
for (auto it = path.rbegin(); it != path.rend(); it++) {
|
||||
if (currentRequiredSpeed <= -1.0) {
|
||||
@ -771,7 +817,8 @@ AreaSearchResult continueAreaSearch() {
|
||||
currentAreaSearch.allowMotorways,
|
||||
currentAreaSearch.allowTunnels,
|
||||
currentAreaSearch.allowAgainstOneway,
|
||||
currentAreaSearch.limitCornerSpeed
|
||||
currentAreaSearch.limitCornerSpeed,
|
||||
false
|
||||
);
|
||||
|
||||
// Remove all nodes we have reached from here as possible future start nodes
|
||||
@ -919,7 +966,8 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
||||
|
||||
emscripten::class_<JSSearchResult>("SearchResult")
|
||||
.constructor<>()
|
||||
.property("endPoints", &JSSearchResult::endPoints);
|
||||
.property("endPoints", &JSSearchResult::endPoints)
|
||||
.property("reverse", &JSSearchResult::reverse);
|
||||
|
||||
emscripten::class_<PolygonCoordinate>("PolygonCoordinate")
|
||||
.constructor<>()
|
||||
|
||||
@ -45,7 +45,8 @@ interface FindPathsFromNode {
|
||||
allowMotorways: boolean,
|
||||
allowTunnels: boolean,
|
||||
allowAgainstOneway: boolean,
|
||||
limitCornerSpeed: boolean
|
||||
limitCornerSpeed: boolean,
|
||||
reverse: boolean
|
||||
}
|
||||
|
||||
export interface Endpoint {
|
||||
@ -57,7 +58,8 @@ export interface Endpoint {
|
||||
|
||||
interface FoundPathsFromNode {
|
||||
nodeId: number,
|
||||
endpoints: Endpoint[]
|
||||
endpoints: Endpoint[],
|
||||
reverse: boolean
|
||||
}
|
||||
|
||||
interface GetFullPath {
|
||||
|
||||
23
src/main.ts
23
src/main.ts
@ -17,7 +17,8 @@ interface Settings {
|
||||
allowTunnels: boolean,
|
||||
allowAgainstOneway: boolean,
|
||||
limitCornerSpeed: boolean,
|
||||
cutoffDistance: number
|
||||
cutoffDistance: number,
|
||||
reverse: boolean
|
||||
}
|
||||
|
||||
// Default settings values
|
||||
@ -47,6 +48,7 @@ let loadingContainer = document.getElementById('loadingcontainer');
|
||||
let mapContainer = document.getElementById('mapcontainer');
|
||||
let searchButton = document.getElementById('search-button');
|
||||
let exportButton = document.getElementById('export-route-button');
|
||||
let reverseCheckbox = document.getElementById('reverse-search-input');
|
||||
let searchStatusParagraph = document.getElementById('search-status-paragraph');
|
||||
let searchResultsTable = document.getElementById('search-result-table');
|
||||
let searchResultTableBody = document.getElementById('search-result-table-body');
|
||||
@ -72,8 +74,8 @@ routeWorker.onmessage = e => {
|
||||
}
|
||||
|
||||
else if (message.foundClosestNode != null) {
|
||||
mapHandler?.drawStartNode(message.foundClosestNode.foundNodeId, message.foundClosestNode.foundLatitude, message.foundClosestNode.foundLongitude);
|
||||
let settings = getSettings();
|
||||
mapHandler?.drawStartNode(message.foundClosestNode.foundNodeId, message.foundClosestNode.foundLatitude, message.foundClosestNode.foundLongitude, settings.reverse);
|
||||
let findPathsMessage: Message = {findPathsFromNode: {
|
||||
nodeId: message.foundClosestNode.foundNodeId,
|
||||
minimumSpeed: settings.minimumSpeed,
|
||||
@ -83,11 +85,12 @@ routeWorker.onmessage = e => {
|
||||
allowMotorways: settings.allowMotorways,
|
||||
allowTunnels: settings.allowTunnels,
|
||||
allowAgainstOneway: settings.allowAgainstOneway,
|
||||
limitCornerSpeed: settings.limitCornerSpeed
|
||||
limitCornerSpeed: settings.limitCornerSpeed,
|
||||
reverse: settings.reverse
|
||||
}};
|
||||
routeWorker.postMessage(findPathsMessage);
|
||||
} else if (message.foundPathsFromNode != null) {
|
||||
mapHandler?.drawEndPoints(message.foundPathsFromNode.endpoints);
|
||||
mapHandler?.drawEndPoints(message.foundPathsFromNode.endpoints, message.foundPathsFromNode.reverse);
|
||||
} else if (message.returnFullPath != null) {
|
||||
let settings = getSettings();
|
||||
mapHandler?.drawPath(message.returnFullPath.pathSegments, settings.minimumSpeed, settings.maximumSpeed);
|
||||
@ -130,8 +133,7 @@ routeWorker.onmessage = e => {
|
||||
|
||||
button.setHTMLUnsafe('Show in map');
|
||||
button.addEventListener('click', _ => {
|
||||
mapHandler?.drawStartNode(result.nodeId, result.latitude, result.longitude);
|
||||
let settings = getSettings();
|
||||
mapHandler?.drawStartNode(result.nodeId, result.latitude, result.longitude, false);
|
||||
let requestMessage: Message = {
|
||||
findPathsFromNode: {
|
||||
nodeId: result.nodeId,
|
||||
@ -142,7 +144,8 @@ routeWorker.onmessage = e => {
|
||||
allowMotorways: settings.allowMotorways,
|
||||
allowTunnels: settings.allowTunnels,
|
||||
allowAgainstOneway: settings.allowAgainstOneway,
|
||||
limitCornerSpeed: settings.limitCornerSpeed
|
||||
limitCornerSpeed: settings.limitCornerSpeed,
|
||||
reverse: false
|
||||
}
|
||||
};
|
||||
routeWorker.postMessage(requestMessage);
|
||||
@ -195,7 +198,8 @@ function setUpMapHandler() {
|
||||
allowMotorways: settings.allowMotorways,
|
||||
allowTunnels: settings.allowTunnels,
|
||||
allowAgainstOneway: settings.allowAgainstOneway,
|
||||
limitCornerSpeed: settings.limitCornerSpeed
|
||||
limitCornerSpeed: settings.limitCornerSpeed,
|
||||
reverse: settings.reverse
|
||||
}};
|
||||
routeWorker.postMessage(newRoutesMessage);
|
||||
}
|
||||
@ -325,7 +329,8 @@ function getSettings(): Settings {
|
||||
allowTunnels: getBooleanValue(allowTunnelsInput, DEFAULT_ALLOW_TUNNELS),
|
||||
allowAgainstOneway: getBooleanValue(allowAgainstOnewayInput, DEFAULT_ALLOW_AGAINST_ONE_WAY),
|
||||
limitCornerSpeed: getBooleanValue(limitCornerSpeedInput, DEFAULT_LIMIT_CORNER_SPEED),
|
||||
cutoffDistance: getNumberValue(cutoffDistanceInput, DEFAULT_CUTOFF_DISTANCE)
|
||||
cutoffDistance: getNumberValue(cutoffDistanceInput, DEFAULT_CUTOFF_DISTANCE),
|
||||
reverse: getBooleanValue(reverseCheckbox, false)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -250,28 +250,44 @@ class MapHandler {
|
||||
this.searchAreaPolygonListeners.push(searchAreaListener);
|
||||
}
|
||||
|
||||
public drawStartNode(nodeId: number, latitude: number, longitude: number): void {
|
||||
public drawStartNode(nodeId: number, latitude: number, longitude: number, reverse: boolean): void {
|
||||
this.path.clearLayers();
|
||||
|
||||
if (this.startMarker != null) {
|
||||
this.map.removeLayer(this.startMarker);
|
||||
}
|
||||
|
||||
var settings;
|
||||
if (reverse) {
|
||||
settings = {icon: redIcon};
|
||||
} else {
|
||||
settings = {icon: greenIcon};
|
||||
}
|
||||
|
||||
this.currentStartPoint = nodeId;
|
||||
this.endMarkers.clearLayers();
|
||||
this.startMarker = L.marker([latitude, longitude], {icon: greenIcon}).addTo(this.map);
|
||||
this.startMarker = L.marker([latitude, longitude], settings).addTo(this.map);
|
||||
}
|
||||
|
||||
public drawEndPoints(endpoints: Endpoint[]): void {
|
||||
public drawEndPoints(endpoints: Endpoint[], reverse: boolean): void {
|
||||
this.endMarkers.clearLayers();
|
||||
this.path.clearLayers();
|
||||
var firstMarker = true;
|
||||
|
||||
var color = reverse ? 'orange' : 'violet';
|
||||
var settings: L.MarkerOptions;
|
||||
if (reverse) {
|
||||
settings = {icon: greenIcon};
|
||||
} else {
|
||||
settings = {icon: redIcon};
|
||||
}
|
||||
|
||||
endpoints.forEach(endpoint => {
|
||||
var marker;
|
||||
if (firstMarker) {
|
||||
marker = L.marker([endpoint.latitude, endpoint.longitude], {icon: redIcon}).addTo(this.endMarkers);
|
||||
marker = L.marker([endpoint.latitude, endpoint.longitude], settings).addTo(this.endMarkers);
|
||||
} else {
|
||||
marker = L.circleMarker([endpoint.latitude, endpoint.longitude], {radius: 2, fillOpacity: 1.0, color: 'purple', bubblingMouseEvents: false}).addTo(this.endMarkers);
|
||||
marker = L.circleMarker([endpoint.latitude, endpoint.longitude], {radius: 2, fillOpacity: 1.0, color: color, bubblingMouseEvents: false}).addTo(this.endMarkers);
|
||||
}
|
||||
|
||||
marker.bindTooltip(Math.round(endpoint.distanceFromStart) + 'm');
|
||||
|
||||
@ -103,7 +103,8 @@ onmessage = async (e) => {
|
||||
message.findPathsFromNode.allowMotorways,
|
||||
message.findPathsFromNode.allowTunnels,
|
||||
message.findPathsFromNode.allowAgainstOneway,
|
||||
message.findPathsFromNode.limitCornerSpeed
|
||||
message.findPathsFromNode.limitCornerSpeed,
|
||||
message.findPathsFromNode.reverse
|
||||
);
|
||||
|
||||
let endpoints: Endpoint[] = [];
|
||||
@ -122,9 +123,10 @@ onmessage = async (e) => {
|
||||
distanceFromStart: nodeData.distanceFromStart
|
||||
});
|
||||
}
|
||||
let reverse: boolean = results.reverse;
|
||||
results.delete();
|
||||
|
||||
let returnMessage: Message = {foundPathsFromNode: {nodeId: message.findPathsFromNode.nodeId, endpoints: endpoints}};
|
||||
let returnMessage: Message = {foundPathsFromNode: {nodeId: message.findPathsFromNode.nodeId, endpoints: endpoints, reverse: reverse}};
|
||||
postMessage(returnMessage);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user