Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addition of new backend Emscripten pathfinding algorithm and new datastore generation #41

Open
wants to merge 58 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f09a9f3
Updated README with build instructions
Apr 21, 2016
25aab8e
Finally figured out how to generate docs. Missing dependency
Apr 22, 2016
aed56f1
Build instructions were missing some steps
Apr 27, 2016
dbbef13
Update README.md
Apr 27, 2016
62688b0
Added an annotated source file with my comments on what everything does
Apr 27, 2016
1ec3cc9
Ported datastore building from ecs-193a project. Untested
mazarf Apr 28, 2016
6694527
Fixed undefined dataStore problem and bad path to priority queue JS
Apr 28, 2016
15876c2
Add comments detailing next steps.
mazarf Apr 28, 2016
c551f75
Updated pathfinding to use Emscripten compiled C++ code
May 2, 2016
331e7fe
Got path animation working. Still needs to be tested for bugs
May 4, 2016
a2b72ad
Modified datastore-test.js beforeEach to use callback
May 5, 2016
440098b
Recompiled datastore.js to not generate .mem file as it was causing p…
May 5, 2016
d872d48
Updated karma config file to work with new js sources for testing
May 5, 2016
144d1d8
Update unit tests to work with new implementation.
mazarf May 11, 2016
e93188a
Update README.md
May 11, 2016
a167aaa
Integrate new unit tests.
mazarf May 11, 2016
5fb9b71
Updated documentation for datastore object.
May 11, 2016
7c46f74
Added partially linted versions of jquery.wayfinding & datastore-test
May 11, 2016
a4aa554
Fixed linter errors in jquery.wayfinding.js & datastore-test.js
May 12, 2016
b7cf53f
Renamed datastore.js to pathfinding.js
May 12, 2016
f7c4dd3
Passing all linter checks now
May 12, 2016
c55c939
Ignoring priority-queue.min.js & pathfinding.js from uglify grunt plugin
May 12, 2016
5fe3e0f
Updated datastore-test.js to use callback instead of setTimeout
May 12, 2016
e703460
In process of updating unit test files
May 12, 2016
c64465a
Updated unit tests to include our pathfinding tests
May 12, 2016
deab344
Grunt is missing from the devDependencies...
May 12, 2016
0530104
Updated Gruntfile to include C++ build instructions
May 12, 2016
3684d43
Removed rapidjson from repo. Updated Makefile to download it if needed
May 12, 2016
e488a52
Forgot a comma
May 12, 2016
23ee9ac
Revert "Removed rapidjson from repo. Updated Makefile to download it …
May 12, 2016
6aec6ef
Added ability to switch between new backend and old.
May 12, 2016
f567fef
Updated the documentation again to have both datastore definitions
May 12, 2016
fc1c1eb
Changed pathfinding file names to emscripten.pathfinding
May 12, 2016
1e1fe4d
Changed option newBackend to emscriptenBackend.
May 12, 2016
999032a
Updated README to include issues we have encountered with node_modules
May 12, 2016
84fcca0
Forgot to update datastores.html to work with old backend
May 12, 2016
8204d79
Update README.md
May 12, 2016
51ae06d
Merge pull request #1 from psalessi/master
cthielen May 19, 2016
af04b89
Refactored CPP code. Still needs more comments
May 25, 2016
dcf4299
Updated function names to now use old & new but recursive & emscripten
May 27, 2016
8fdcc78
Removed trailing space to pass linter
May 27, 2016
eee49f6
Removed trailing space to pass linter
May 27, 2016
d523764
Updated dist files
May 27, 2016
35af7d2
Can't let this fall behind
May 28, 2016
275f8fd
Changed some function names
May 28, 2016
8c12c3d
Add SVG linter.
jlperona May 31, 2016
f405fe9
Update included test files.
jlperona May 31, 2016
086df8c
Merge branch 'master' of github.com:dssit/wayfinding
jlperona Jun 1, 2016
4e47ff0
Merge pull request #2 from jlperona/master
cthielen Jun 1, 2016
10b9fa9
Added some final comments to C++ code
Jun 2, 2016
1187d0c
Refactored CPP code. Still needs more comments
May 25, 2016
1df370c
Updated function names to now use old & new but recursive & emscripten
May 27, 2016
9e41e3b
Removed trailing space to pass linter
May 27, 2016
7e31ce3
Updated dist files
May 27, 2016
42b8ade
Changed some function names
May 28, 2016
e5e72dd
Added some final comments to C++ code
Jun 2, 2016
4730a5c
Added emscriptenBackend option to wayfinding init in index.html
Jun 2, 2016
3ab3db0
Merge branch 'master' of https://github.com/psalessi/wayfinding
Jun 2, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added some final comments to C++ code
Paul Salessi committed Jun 2, 2016
commit e5e72dd6dfb9d2a2d83af6dacc6b53954894233b
2 changes: 1 addition & 1 deletion dist/emscripten.pathfinding.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/jquery.wayfinding.min.js

Large diffs are not rendered by default.

57 changes: 51 additions & 6 deletions src/emscripten.pathfinding.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// This file is used by jquery.wayfinding.js plugin to run Dijkstra's between to SVG rooms.
// It is compiled to JavaScript using the Emscripten compiler
// The binding of the C++ functions to JavaScript is done using Emscripten's Embind feature
// RapidJSON is used to parse the stringified JSON passed when called by JavaScript code.

#include <string>
#include <set>
#include <vector>
@@ -10,6 +15,8 @@
using namespace rapidjson;
using namespace std;

// There are three types of nodes in our datastore.
// The stop type is used to indicated the end of the path generated by Dijkstra's
enum nodeType {path, door, portal, stop};
string stringTypes[] = {"path", "door", "portal", "stop"};

@@ -35,18 +42,26 @@ class Node
int pathID;

// Door stuff
// The door's name
// The door's name. typically looks like "R123"
string doorID;
// These bools are used to indicate if the node is the starting or ending node for Dijkstras
bool start;
bool end;

// Portal stuff
string portalID;
// Portals pair with other portals located on different floors
// toFloor indicates what floor at portal's pair is on
// matchID is the ID of the portal's pair
// both are -1 if a portal does not have a pair
int toFloor;
int matchID;
// Usually, there are two types of portals: stairs or elevators
// This is to indicate if a portal is wheelchair accessible (elevators) for the Dijkstras code
bool accessible;

// Orders nodes by ID, floor, and type, in that order.
// Need to use priority queue for pathfinding
bool operator<(const Node other) const
{
if (id == other.id) {
@@ -71,6 +86,8 @@ class Graph
// number of floors in the graph
int floors;

// This is set to true in Dijkstra's if a path is found between the start and end
// This is used to indicated if a no path found error has occurred
bool foundPath = false;

vector< vector<Node> > paths;
@@ -79,6 +96,8 @@ class Graph

// Finds the shortest path from (startFloor, startID) to (endFloor, endID)
// Returns a map containing the route in reverse.
// Accessible indicates whether to find a wheelchair accesible path
// Called only by the pathfinding function
map<Node, Node> dijkstra(int startID, int startFloor, int endID,
int endFloor, bool accessible)
{
@@ -88,6 +107,7 @@ class Graph
map<Node, Node> path;
map<Node, int> minDist;

// Set all node distances to infinity
for (int floor = 0; floor < floors; floor++)
{
for (auto node : doors[floor])
@@ -106,10 +126,12 @@ class Graph
}
}

// Mark the start node
minDist[start] = 0;
path[start] = Node();
path[start].type = stop;

// Set up our priority queue
set< pair<int, Node> > activeNodes;
activeNodes.insert({0, start});

@@ -118,6 +140,7 @@ class Graph
// extract the next node to be processed
Node currentNode = activeNodes.begin()->second;
if (currentNode.type == door) {
// Stop if we've reached our destination
if (currentNode.id == end.id && currentNode.floor == end.floor)
{
foundPath = true;
@@ -147,6 +170,7 @@ class Graph
for (auto neighborID : currentNode.portals)
{
Node neighbor = portals[currentNode.floor][neighborID];
// If we're looking for an accessible route and the current portal is not, skip it
if (accessible && !neighbor.accessible)
{
continue;
@@ -158,7 +182,7 @@ class Graph
path[neighbor] = currentNode;
}
}
// Look at match
// Need to add the portal's pair to the set of nodes to be visited
if (currentNode.type == portal && currentNode.matchID != -1 && currentNode.toFloor != -1)
{
Node neighbor = portals[currentNode.toFloor][currentNode.matchID];
@@ -170,6 +194,8 @@ class Graph
}
}

foundPath = false;
// If the destination was never reached, return this empty route
map<Node, Node> error{{Node(), Node()}};
return error;
}
@@ -183,7 +209,11 @@ class Graph
}
};

// change name
// This function is called by JavaScript code by writing Module.pathfinding()
// dataStore should be stringified JSON of the map datastore
// startString & endString are the room names of the start and end point
// accessible is to indicated whether the user wants a wheelchair accessible route
// Returns a vector<string> that is JavaScript is able to work with
vector<string> pathfinding(string dataStore, string startString,
string endString, bool accessible)
{
@@ -206,9 +236,10 @@ vector<string> pathfinding(string dataStore, string startString,
graph.paths.resize(graph.floors);
graph.portals.resize(graph.floors);

// Go through each floor in datastore and make the graph object
for (int floor = 0; floor < graph.floors; floor++)
{
// Get doors
// Turn doors into nodes
Value& doorElements = document["doors"][floor];

for (int index = 0; index < doorElements.Size(); index++)
@@ -220,6 +251,7 @@ vector<string> pathfinding(string dataStore, string startString,
doorNode.doorID = doorElements[index]["doorId"].GetString();
doorNode.weight = 0;

// Check for start and end nodes
if (doorNode.doorID == startString)
{
doorNode.start = true;
@@ -259,7 +291,7 @@ vector<string> pathfinding(string dataStore, string startString,
graph.doors[floor].push_back(doorNode);
} // end of doors

// Get paths
// Turn paths into nodes
Value& pathElements = document["paths"][floor];

for (int index = 0; index < pathElements.Size(); index++)
@@ -290,7 +322,7 @@ vector<string> pathfinding(string dataStore, string startString,
graph.paths[floor].push_back(pathNode);
} // end of paths

// Get portals
// Turn portals into nodes
Value& portalElements = document["portals"][floor];

for (int index = 0; index < portalElements.Size(); index++)
@@ -328,8 +360,13 @@ vector<string> pathfinding(string dataStore, string startString,
} // end of floors

// Run dijkstra's
// elements will hold the returned path from Dijkstra's
// This will also hold an error if one occurs
// Possible errors are invalid rooms or no path between rooms
vector<string> elements;

// Check if the start and/or end room were not found
// If so, return an error
if (startID == -1 && startFloor == -1 && endID == -1 && endFloor == -1)
{
string error;
@@ -362,6 +399,9 @@ vector<string> pathfinding(string dataStore, string startString,
int pathCount = 0;
Node target = graph.doors[endFloor][endID];

// Add the nodes from the route to the element vector
// Strings are pushed into
// The strings have the format nodetype-nodefloor-nodeid. Ex: path-0-1
while (route[target].type != stop)
{
el = stringTypes[target.type] + "-" + to_string(target.floor) + "-" +
@@ -371,12 +411,14 @@ vector<string> pathfinding(string dataStore, string startString,
pathCount++;
}

// Make sure to the get last node
el = stringTypes[target.type] + "-" + to_string(target.floor) + "-" +
to_string(target.id);
elements.push_back(el);
}
else
{
// No route was found, so return error
string error;
error = "Path not found between start: " + startString + " & end: ";
error += endString;
@@ -387,6 +429,9 @@ vector<string> pathfinding(string dataStore, string startString,
return elements;
}

// Emscripten bindings
// JavaScript needs to know how to handle a vector<string>
// pathfinding is the function we want JavaScript to call
EMSCRIPTEN_BINDINGS(my_module) {
emscripten::register_vector<string>("VectorString");
emscripten::function("pathfinding", &pathfinding);
2 changes: 1 addition & 1 deletion src/emscripten.pathfinding.js

Large diffs are not rendered by default.