perliedman / geojson-path-finder

Find shortest path through a network of GeoJSON
https://www.liedman.net/geojson-path-finder/
ISC License
301 stars 87 forks source link

How to assign one way road? #31

Open joptimus opened 6 years ago

joptimus commented 6 years ago

Hi,

We have implemented your API and all is working well so thank you! We have a question. We are showing a closed road network we mapped with real time GPS coordinates and are unclear on how to designate a certain path as a one way road so that in the calculation it does not pick this road if coming from the other direction? Is there a specific feature ID we need to add to the geojson to enable this?

Also we are trying to find the proper way to have the API disregard paths that require the moving object to turn around on the one way road they are on? We have read your weighted value explanation on the readme and tried to implement but I assume we are missing something in the geojson that causes this calculation to not work.

Any help would be appreciated!

perliedman commented 6 years ago

@joptimus the key is that your weight function has to return an object with different forward and backward components - setting one of them to zero prevents it from being used at all (one way). So, you need to have something in your GeoJSON that make it apparent what direction should be prevented.

If you haven't already, you can have a look at the weight function I use for the demo on the homepage: https://github.com/perliedman/geojson-path-finder/blob/gh-pages/router.js#L25

As you can see, I use one of the GeoJSON's properties to figure out if the road is one way or not.

Does this help?

joptimus commented 6 years ago

@perliedman thanks for the response! We are looking into this but wanted to clarify to make sure we are saying the right thing.

We have a network of single lane roads that can have a vehicle travel in either direction but if a vehicle is traveling in a certain direction it cannot turn around and go back the other way, it must continue on its path forward. Here is an example where I need to have 2 rules for one road:

I am on ROAD-A traveling NORTH, I cannot turn around on ROAD-A and travel SOUTH or I am on ROAD-A traveling SOUTH, I cannot turn around on ROAD-A and travel NORTH

NOTE: You cannot have two vehicles traveling on ROAD-A in opposite directions at the same time

Would this scenario be covered under your demo in the link? The issue I see is that we cannot designate that a road is "oneway" because it depends on the direction of travel. We are reviewing and will start to test but just thought I would ask in the meantime.

perliedman commented 6 years ago

Ok, it sounds like you have to take some care when modelling the GeoJSON. The way geojson-path-finder works, it can only make turns where two LineStrings meet - where the two geometries have a coordinate in common. So, without having seen your data, I don't think it will ever give you an instruction to make a U-turn in the middle of a road; however, it can make any turn as soon as it meets another road (two lines share the same coordinate).

There are no turn restrictions implemented in geojson-path-finder at the moment, so as long as a road is not one way, the router might use it.

joptimus commented 6 years ago

Here is an example with an airplane icon. The airplane is driving in one direction on a single geojson String and the router is saying go backwards on the same line rather than taking the direction in which its traveling.

image

Here is another example where its telling it to go back to the same path it came from and go in the direction its currently going.

image

Maybe we are doing something wrong with the road network? We thought maybe its because we have to much distance between points and need to add more? If so, is there a tool out there you know of that can help us add multiple points on a line at X distance?

perliedman commented 6 years ago

Ah, I see, I missed the obvious thing where the vehicle is already in a certain direction on a road, and can't make a U-turn initially.

The first example looks totally reasonable, given that the router doesn't know what direction the vehicle is travelling in, initially, and also doesn't know U-turns are forbidden.

The second example looks stranger, but it's hard to tell without seeing the actual network and coordinates - it might be that the start coordinate is so close to the crossing in the lower part of the picture, so it snaps them together. You could try specifying the precision option (see docs: https://github.com/perliedman/geojson-path-finder#pathfinder-options) to a lower value and see if it helps.

I think the basic problem is that geojson-path-finder has no concept of "initial direction" (or really direction, at all), so it doesn't know if you're going forward or backward when the routing starts.

The most obvious solution to this, that doesn't require changing geojson-path-finder, would be to reset the routing networks weights (calculate a new network) given the direction you're currently facing: that way, the current road would be made oneway, so that the route can't start with a u-turn.

Other than that, I think it would require some changes in geojson-path-finder, to implement at least basic support for turn restrictions (preventing u-turns). I would be interested in doing that, but it's out of reach for what I can do in free time, so it would either be if you're interested in doing it and submitting a pull request, or if it could be a feature you would be willing to sponsor development for.

maciejgoscinski commented 1 year ago

Hello! I'm currently experimenting with routing using this libary, and so far it seems quite wonderful with default settings. However, I'm having some serious trouble implementing one way routes.

For simplicity, let's assume our entire network FeatureCollection consists of one LineString feature - a simple route between points A and B. As long as I leave the default settings, I can successfully create routes between arbitrary points. The same works if I provide a custom weight function with separate forward and backwards parts (where the backward is a very high number).

It fails when I try to set backward = 0 (forward returning the actual distance). Regardless of which order I choose my A and B points to navigate between, the returned path is undefined. So it doesn't work in any direction now.

In addition, no errors are thrown when calling pathToGeoJSON(path), resulting with a Feature object with properties, but no geometry whatsoever. I guess it should throw the same message as it does in some other scenarios? "ERROR Error: coordinates must be an array of two or more positions".

Has anyone experienced the same problem, or am I misunderstanding something maybe?