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

New module @turf/shortest-path #956

Merged
merged 18 commits into from
Oct 25, 2017
Merged

New module @turf/shortest-path #956

merged 18 commits into from
Oct 25, 2017

Conversation

stebogit
Copy link
Collaborator

Ref. #788

/**
 * Returns the shortest {@link LineString|path} from {@link Point|start} to {@link Point|end} without colliding with
 * any {@link Feature} in {@link FeatureCollection<Polygon>| obstacles}
 *
 * @name shortestPath
 * @param {Geometry|Feature<Point>} start point
 * @param {Geometry|Feature<Point>} end point
 * @param {GeometryCollection|FeatureCollection<Polygon>} obstacles polygons
 * @param {Object} [options={}] optional parameters
 * @param {string} [options.units="kilometers"] can be degrees, radians, miles, kilometers, ...
 * @param {number} [options.resolution=100] distance between matrix points on which the path will be calculated
 * @returns {Feature<LineString>} shortest path between start and end
 * @example
 * var start = turf.point([-5, -6]);
 * var end = turf.point([9, -6]);
 * var obstacles = turf.featureCollection([turf.polygon([[0,-7],[5,-7],[5,-3],[0,-3],[0,-7]]));
 *
 * var path = shortestPath(start, end, obstacles);
 *
 * //addToMap
 * var addToMap = [start, end, obstacles, path];
 */
module.exports = function (start, end, obstacles, options) {

There is a lot of room for improvements, but what do you think of this first draft @DenisCarriere @rowanwins ? Any suggestion to improve speed and/or final result is more than welcome.

screen shot 2017-09-21 at 1 14 46 am

@rowanwins
Copy link
Member

Hey @stebogit

There a bunch of known algorithms for this sort of thing. For example try googling "dijkstra's algorithm", I think this is a semi-famous one that might help. Might be easier and more robust to follow a known pattern.

@DenisCarriere
Copy link
Member

👍 Love it! @stebogit 🎩 off to you for trying to implement this directly with only TurfJS modules.

@rowanwins There a bunch of known algorithms for this sort of thing.

Agreed, would be neat to have a comparable to see if @stebogit's implementation is faster & accurate to those other algorithms. I'm 👍 for any direction we decide to go to, as long as it's fast and accurate.

if (getType(start) !== 'Point') throw new Error('start must be Point');
if (!end) throw new Error('end point is required');
if (getType(end) !== 'Point') throw new Error('end must be Point');
if (!obstacles) throw new Error('obstacles collection is required');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we possibly have obstacles as an optional parameter? In case you want to use this module over an iterative process and maybe in some scenarios you would have 2 points with or without an obstacle, we could simply just return a lineString from both points (same as an empty featureCollection).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Great idea 👍

collection.features.push(start);
collection.features.push(end);

var box = bbox(scale(bboxPolygon(bbox(collection)), 1.15)); // extend 15%
Copy link
Member

@DenisCarriere DenisCarriere Sep 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't extend also be an optional parameter instead of hardcoded as 15%?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This in my mind was just to allow some space to allow the path around any object, like to avoid this (just a silly example):
screen shot 2017-09-21 at 8 20 57 pm
I don't see any other use for this parameter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough... that is a pretty silly scenario 😝

@@ -0,0 +1,1981 @@
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've recently just been removing/excluding the package-lock.json files, I'm not too sure if we should be having two lock files (yarn + npm).

I've added package-lock.json to the .gitignore, we could always add it back, but it seems like two lock files is a bit overkill (we only need to stick with one).

593cb91

"grid-to-matrix": "1.3.0",
"javascript-astar": "0.4.1",
"pathfinding": "0.4.18"
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's definitely missing some dependencies in the package.json, this is one of the reasons why the TravisCI tests will fail.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this is absolutely "work-in-progress", I added the whole @turf/turf for convenience while developing.
Sorry, I should have titled this more clearly as "proposal" (like the label); I was just interested at this point in you suggestions and check with you if my approach was reasonably sound so far.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Looks great to me so far! Was just trying to get the tests to pass

Copy link
Member

@DenisCarriere DenisCarriere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really awesome! Looking forward to add more tests to this, overall this looks like a great library.

A few concerns I mentioned in the comments, but looks great to me! 👍

@DenisCarriere
Copy link
Member

@stebogit Do you have an ESLint plugin installed in your current text editor?

TravisCI Error

/home/travis/build/Turfjs/turf/packages/turf-shortest-path/index.js
  116:37  error  'i' is defined but never used  no-unused-vars
✖ 1 problem (1 error, 0 warnings)

@stebogit stebogit changed the title New module @turf/shortest-path New module @turf/shortest-path (work-in-progress) Sep 22, 2017
@stebogit
Copy link
Collaborator Author

@rowanwins thanks for the tip.
I did some quick research and it turns out A* is the best choice here, since it's faster and (as Dijkstra) is guaranteed to return the shortest path:
http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html
Now, I'll try to compare the few implementations I found on npm to pick the best/fastest one.

Thanks guys!

@rowanwins
Copy link
Member

good luck with it @stebogit ! I find it really hard reading some of those maths/computer science papers and interpreting what they're saying, but if we can follow them they should lead us to decent performant implementations, and I think they teach us some good skills in queues and sweeplines etc that we should be able to apply elsewhere.

@DenisCarriere
Copy link
Member

A * looks like a great approach, @stebogit good luck in your npm quest to find one!

I like this image:

image

@DenisCarriere
Copy link
Member

DenisCarriere commented Sep 23, 2017

@stebogit Other possible module name would be @turf/least-cost-path, however I still prefer your original proposed name @turf/shortest-path.

@DenisCarriere DenisCarriere changed the title New module @turf/shortest-path (work-in-progress) New module @turf/shortest-path (⚠️ Work in progress %80) Sep 25, 2017
@bulutkartal
Copy link

bulutkartal commented Sep 26, 2017

I don't know if you guys would consider but shortest sea routes may be killer, either with reverse altitude or based on depth colors on maps. here is an example based on color.

@rowanwins
Copy link
Member

Hi @bulutkartal

Are you able to elaborate on your idea, are you saying that altitude or depth have a bearing on the path calculation? This module is for the actual calculation of the shortest path, it doesn't take into account how to visualise the result.

@bulutkartal
Copy link

bulutkartal commented Sep 27, 2017

I was trying to mean the reserve altitude can be used to calculate shortest sea routes(only water based), but using elevation services may be quite expensive and I don't think it is very suitable for turf. But instead of elevation services , map background colors can be used to calculate shortest sea routes. Lines will not pass through the land, only will stay in water colors. The link I sent above as an example works that way. It calculates the shortest distance between two ports and the line script creates stays in water. I saw the approach when I opened their bundled js. It was kinda cool what they did. This wouldn't be beneficial for land routes. I just saw the example was created at sea and idea just came out and found that link :)

@rowanwins
Copy link
Member

Hi @bulutkartal

Using the proposed module you will be able to pass in your start and end point (presumably ports), as well as a bunch of polygons (which represent land borders), the output line will show you the route between the points avoiding the land. So it wont have anything to do with elevation. I hope that helps clear things up.

@stebogit
Copy link
Collaborator Author

stebogit commented Sep 27, 2017

Just a quick note, I'm not really sure this implementation is the best one, 'cause the path should not move only on a grid...
I believe the right output should look more like this (compared to the one above):

screen shot 2017-09-27 at 12 01 07 am

I'll keep looking for an alternative though, probably after we are done with v5.0.

@bulutkartal
Copy link

bulutkartal commented Sep 27, 2017

using elevation was just an another idea to prevent line going through land since elevation will be negative in water. Was just an idea, nothing more :) But using colors are easier and faster approach.

@DenisCarriere
Copy link
Member

I believe the right output should look more like this

@stebogit Agreed, the 2nd map looks like it would be a better solution.

👍 to push this at the next minor release v5.1, big push for now would be to implement the ES Modules (we can add more modules afterwards).

@DenisCarriere DenisCarriere added this to the 5.1.0 milestone Sep 27, 2017
@DenisCarriere DenisCarriere changed the title New module @turf/shortest-path (⚠️ Work in progress %80) New module @turf/shortest-path Oct 25, 2017
@DenisCarriere
Copy link
Member

🎉 Merged & Published @turf/shortest-path

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants