diff --git a/.gitignore b/.gitignore
index 5dc90e4..c3e3c1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.vscode/
dist/
native/*
node_modules/
diff --git a/index.html b/index.html
index 590a068..e5955ef 100644
--- a/index.html
+++ b/index.html
@@ -63,6 +63,9 @@
+
+
+
diff --git a/native/route_search.cpp b/native/route_search.cpp
index d37ac92..da12c20 100644
--- a/native/route_search.cpp
+++ b/native/route_search.cpp
@@ -15,6 +15,7 @@ const float GRAVITY_ACCELERATION = 9.81;
struct Connection {
int connected_point_number;
float distance;
+ float course;
uint8_t speed_limit;
bool motorway;
bool tunnel;
@@ -64,6 +65,7 @@ struct JSSearchResult {
struct ListNode {
int id;
float current_speed;
+ float current_course;
ListNode* next = NULL;
};
@@ -93,6 +95,7 @@ struct CurrentAreaSearch {
bool allowMotorways;
bool allowTunnels;
bool allowAgainstOneway;
+ bool limitCornerSpeed;
std::vector startNodes;
size_t startNodeCounter = 0;
@@ -121,10 +124,12 @@ void addLinkToRoadNode(RoadNode* roadNodes, int node_from, int node_to, uint8_t
float to_y = roadNodes[node_to].position_y;
float distance = sqrt(pow(to_x - from_x, 2) + pow(to_y - from_y, 2));
+ float course = atan2(to_x - from_x, to_y - from_y) * 180 / 3.14152965;
Connection connection;
connection.connected_point_number = node_to;
connection.distance = distance;
+ connection.course = course;
connection.speed_limit = speed_limit;
connection.motorway = motorway;
connection.tunnel = tunnel;
@@ -302,7 +307,7 @@ void getNeighbourConnections(RoadNode node, Connection* targetArray, int &number
}
}
-SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float maximum_speed, int maximumSpeedLimit, float drag_coefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway) {
+SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float maximum_speed, int maximumSpeedLimit, float drag_coefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed) {
SearchResult result;
result.startingNode = startingNode;
@@ -313,10 +318,10 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float
result.reachableNodes[startingNode] = firstNodeInfo;
ListNode *nextNode = new ListNode;
- ListNode *lastNode = nextNode;
nextNode->id = startingNode;
nextNode->current_speed = minimum_speed;
+ nextNode->current_course = 0;
while (nextNode != NULL) {
ListNode *currentNode = nextNode;
@@ -324,12 +329,9 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float
int currentId = currentNode->id;
float currentSpeed = currentNode->current_speed;
+ float currentCourse = currentNode->current_course;
RoadNode bestNode = set.roadNodes[currentId];
-
- if (lastNode == currentNode) {
- lastNode = NULL;
- }
delete currentNode;
Connection neighbours[10];
@@ -366,6 +368,21 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float
if (resultingSpeed < 0) {
continue;
}
+
+ // If we limit the speed on corners, do that here
+ if (limitCornerSpeed) {
+ float courseDifference = fabs(currentCourse - neighbour.course);
+ if (courseDifference > 180.0) {
+ courseDifference = 360 - courseDifference;
+ }
+
+ if (courseDifference > 95) {
+ resultingSpeed = minimum_speed;
+ } else if (courseDifference > 45.0) {
+ float maximumCornerSpeed = (95 - courseDifference) / 50.0 * (maximum_speed - minimum_speed) + minimum_speed;
+ resultingSpeed = fmin(resultingSpeed, maximumCornerSpeed);
+ }
+ }
// Check if this node is already in the reachable nodes map
auto resultIterator = result.reachableNodes.find(neighbour.connected_point_number);
@@ -383,6 +400,7 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float
ListNode *neighbourListNode = new ListNode;
neighbourListNode->id = neighbour.connected_point_number;
neighbourListNode->current_speed = reachableNodeInfo.currentSpeed;
+ neighbourListNode->current_course = neighbour.course;
if (nextNode == NULL || resultingSpeed < nextNode->current_speed) {
neighbourListNode->next = nextNode;
@@ -405,8 +423,8 @@ SearchResult findAllPathsFromPoint(int startingNode, float minimum_speed, float
return result;
}
-JSSearchResult findAllPathsFromPointJS(int startingNode, float minimumSpeed, float maximumSpeed, int maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway) {
- lastSearchResult = findAllPathsFromPoint(startingNode, minimumSpeed, maximumSpeed, maximumSpeedLimit, dragCoefficient, allowMotorways, allowTunnels, allowAgainstOneway);
+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);
float start_x = set.roadNodes[startingNode].position_x;
float start_y = set.roadNodes[startingNode].position_y;
@@ -721,7 +739,7 @@ std::vector findPossibleStartNodes(float minimumSpeed, float maximumSp
return possibleStartNodes;
}
-AreaSearchResult startAreaSearch(float minimumSpeed, float maximumSpeed, float maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, std::vector>> searchArea) {
+AreaSearchResult startAreaSearch(float minimumSpeed, float maximumSpeed, float maximumSpeedLimit, float dragCoefficient, bool allowMotorways, bool allowTunnels, bool allowAgainstOneway, bool limitCornerSpeed, std::vector>> searchArea) {
currentAreaSearch = CurrentAreaSearch();
currentAreaSearch.startNodes = findPossibleStartNodes(minimumSpeed, maximumSpeedLimit, dragCoefficient, allowMotorways, allowTunnels, allowAgainstOneway, searchArea);
currentAreaSearch.minimumSpeed = minimumSpeed;
@@ -731,6 +749,7 @@ AreaSearchResult startAreaSearch(float minimumSpeed, float maximumSpeed, float m
currentAreaSearch.allowMotorways = allowMotorways;
currentAreaSearch.allowTunnels = allowTunnels;
currentAreaSearch.allowAgainstOneway = allowAgainstOneway;
+ currentAreaSearch.limitCornerSpeed = limitCornerSpeed;
AreaSearchResult result;
result.remainingNodes = currentAreaSearch.startNodes.size();
@@ -747,7 +766,8 @@ AreaSearchResult continueAreaSearch() {
currentAreaSearch.dragCoefficient,
currentAreaSearch.allowMotorways,
currentAreaSearch.allowTunnels,
- currentAreaSearch.allowAgainstOneway
+ currentAreaSearch.allowAgainstOneway,
+ currentAreaSearch.limitCornerSpeed
);
// Remove all nodes we have reached from here as possible future start nodes
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 4c6f8eb..f1e5ca7 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -44,7 +44,8 @@ interface FindPathsFromNode {
dragCoefficient: number,
allowMotorways: boolean,
allowTunnels: boolean,
- allowAgainstOneway: boolean
+ allowAgainstOneway: boolean,
+ limitCornerSpeed: boolean
}
export interface Endpoint {
@@ -102,7 +103,8 @@ interface SearchArea {
dragCoefficient: number,
allowMotorways: boolean,
allowTunnels: boolean,
- allowAgainstOneway: boolean
+ allowAgainstOneway: boolean,
+ limitCornerSpeed: boolean
}
interface ContinueSearch {
diff --git a/src/main.ts b/src/main.ts
index 3fd9499..7ccc21c 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -16,6 +16,7 @@ interface Settings {
allowMotorways: boolean,
allowTunnels: boolean,
allowAgainstOneway: boolean,
+ limitCornerSpeed: boolean,
cutoffDistance: number
}
@@ -27,6 +28,7 @@ const DEFAULT_DRAG_COEFFICIENT = 0.005;
const DEFAULT_ALLOW_MOTORWAYS = false;
const DEFAULT_ALLOW_TUNNELS = false;
const DEFAULT_ALLOW_AGAINST_ONE_WAY = false;
+const DEFAULT_LIMIT_CORNER_SPEED = true;
const DEFAULT_CUTOFF_DISTANCE = 1000;
// Set up variables
@@ -58,6 +60,7 @@ let dragCoefficientInput = document.getElementById('drag-coefficient-input');
let allowMotorwaysInput = document.getElementById('allow-motorways-input');
let allowTunnelsInput = document.getElementById('allow-tunnels-input');
let allowAgainstOnewayInput = document.getElementById('allow-wrong-way-input');
+let limitCornerSpeedInput = document.getElementById('limit-corner-speed-input');
let cutoffDistanceInput = document.getElementById('cutoff-distance-input');
@@ -79,7 +82,8 @@ routeWorker.onmessage = e => {
dragCoefficient: settings.dragCoefficient,
allowMotorways: settings.allowMotorways,
allowTunnels: settings.allowTunnels,
- allowAgainstOneway: settings.allowAgainstOneway
+ allowAgainstOneway: settings.allowAgainstOneway,
+ limitCornerSpeed: settings.limitCornerSpeed
}};
routeWorker.postMessage(findPathsMessage);
} else if (message.foundPathsFromNode != null) {
@@ -137,7 +141,8 @@ routeWorker.onmessage = e => {
dragCoefficient: settings.dragCoefficient,
allowMotorways: settings.allowMotorways,
allowTunnels: settings.allowTunnels,
- allowAgainstOneway: settings.allowAgainstOneway
+ allowAgainstOneway: settings.allowAgainstOneway,
+ limitCornerSpeed: settings.limitCornerSpeed
}
};
routeWorker.postMessage(requestMessage);
@@ -189,7 +194,8 @@ function setUpMapHandler() {
dragCoefficient: settings.dragCoefficient,
allowMotorways: settings.allowMotorways,
allowTunnels: settings.allowTunnels,
- allowAgainstOneway: settings.allowAgainstOneway
+ allowAgainstOneway: settings.allowAgainstOneway,
+ limitCornerSpeed: settings.limitCornerSpeed
}};
routeWorker.postMessage(newRoutesMessage);
}
@@ -306,6 +312,7 @@ setUpNumberInput(dragCoefficientInput, 'drag-coefficient', DEFAULT_DRAG_COEFFICI
setUpBooleanInput(allowMotorwaysInput, 'allow-motorways', DEFAULT_ALLOW_MOTORWAYS);
setUpBooleanInput(allowTunnelsInput, 'allow-tunnels', DEFAULT_ALLOW_TUNNELS);
setUpBooleanInput(allowAgainstOnewayInput, 'allow-against-one-way', DEFAULT_ALLOW_AGAINST_ONE_WAY);
+setUpBooleanInput(limitCornerSpeedInput, 'limit-corner-speed', DEFAULT_LIMIT_CORNER_SPEED);
setUpNumberInput(cutoffDistanceInput, 'cutoff-distance', DEFAULT_CUTOFF_DISTANCE);
function getSettings(): Settings {
@@ -317,6 +324,7 @@ function getSettings(): Settings {
allowMotorways: getBooleanValue(allowMotorwaysInput, DEFAULT_ALLOW_MOTORWAYS),
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)
};
}
@@ -329,6 +337,7 @@ function enableSettings(): void {
enableInput(allowMotorwaysInput);
enableInput(allowTunnelsInput);
enableInput(allowAgainstOnewayInput);
+ enableInput(limitCornerSpeedInput);
}
function disableSettings(): void {
@@ -339,6 +348,7 @@ function disableSettings(): void {
disableInput(allowMotorwaysInput);
disableInput(allowTunnelsInput);
disableInput(allowAgainstOnewayInput);
+ disableInput(limitCornerSpeedInput);
}
@@ -356,7 +366,8 @@ searchButton?.addEventListener('click', _ => {
dragCoefficient: settings.dragCoefficient,
allowMotorways: settings.allowMotorways,
allowTunnels: settings.allowTunnels,
- allowAgainstOneway: settings.allowAgainstOneway
+ allowAgainstOneway: settings.allowAgainstOneway,
+ limitCornerSpeed: settings.limitCornerSpeed
}};
routeWorker.postMessage(message);
}
diff --git a/src/modules/worker/worker.ts b/src/modules/worker/worker.ts
index c2e9fdd..64416de 100644
--- a/src/modules/worker/worker.ts
+++ b/src/modules/worker/worker.ts
@@ -102,7 +102,8 @@ onmessage = async (e) => {
message.findPathsFromNode.dragCoefficient,
message.findPathsFromNode.allowMotorways,
message.findPathsFromNode.allowTunnels,
- message.findPathsFromNode.allowAgainstOneway
+ message.findPathsFromNode.allowAgainstOneway,
+ message.findPathsFromNode.limitCornerSpeed
);
let endpoints: Endpoint[] = [];
@@ -186,6 +187,7 @@ onmessage = async (e) => {
settings.allowMotorways,
settings.allowTunnels,
settings.allowAgainstOneway,
+ settings.limitCornerSpeed,
createCMultiPolygon(module, settings.polygons)
);