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

[long, lat, altitude] ? #25

Open SyJuly opened 6 years ago

SyJuly commented 6 years ago

Hi @perliedman!

I've been using your library for one-level pathfinding but would like to add a third dimension. Generally GeoJSON supports values of x,y,z and your Pathfinder is taking a FeatureCollection of lineStrings with xyz-coordinates just fine. The resulting path consists of one point only, although I gave a featureCollection of connected lineStrings. Same issue whatever path I want to take or whatever weight I manually assign. It seems like the Pathfinder cannot handle 3 dimensions.

Or maybe I am doing something wrong? Or is it possible to easily extend your Pathfinder for 3 dimensions?

Thank you for your help!

perliedman commented 6 years ago

Hi @SyJuly, would it be possible for you to supply some data I can test this on?

Depending on how you want 3D routing to work, GeoJSON Path Finder could probably support it, or already supports it, but there might be some minor bug. I've never tried it with elevation data myself.

SyJuly commented 6 years ago
const start = [13.526974, 52.45718, 2]
const finish = [13.526974, 52.45718, 4]
const features = [ 
 {
    type: "Feature",
    properties: {},
    geometry: {
      coordinates: [
        [13.526974, 52.45718, 2],
        [13.526974, 52.45718, 3],
      ],
      type: "LineString",
    },
  },
  {
    type: "Feature",
    properties: {},
    geometry: {
      coordinates: [
        [13.526974, 52.45718, 3],
        [13.526974, 52.45718, 4],
      ],
      type: "LineString",
    },
  },
  {
    type: "Feature",
    properties: {
      r_floor: "3",
    },
    geometry: {
      coordinates: [
        [13.52696, 52.457185, 3],
        [13.526974, 52.45718, 3],
      ],
      type: "LineString",
    },
  },
]

export function getPath(features, start, finish) {
  const pathFinder = new PathFinder(features, {
    weightFn: function(a, b, props) {
      if (!props.r_floor) {        // applies to all transition linestrings
        return 2;
      }
      var dx = a[0] - b[0];
      var dy = a[1] - b[1];
      return Math.sqrt(dx * dx + dy * dy);
    }
  });
  const path = pathFinder.findPath(point(start), point(finish));
  return path.path;
}

So, this is the example I am currently working on. The resulting path will give me on point only.

Thanks for your quick reply!

perliedman commented 6 years ago

Ok, so your linestrings differ only in z, and since the coordinate snapping algorithm only takes lat/lng into account, they are snapped to one point.

This logic is in the roundCoord function: https://github.com/perliedman/geojson-path-finder/blob/master/round-coord.js

I think it would be enough to just round the third component in a similar fashion to make this work.

IPWright83 commented 3 years ago

@perliedman unfortunately it's a little bit more tricky than that. @turf/distance is being used to calculate the weight by default, but this disregards the altitude. I've logged a bug about it https://github.com/Turfjs/turf/issues/2143.

I can confirm though, if you fix that (I've just hacked the height difference on the end for now, but I'm not sure that's correct) then it does work :)

perliedman commented 3 years ago

@IPWright83 yes, you will have to use a custom weight function. Can't say for certain, but would consider it unlikely for Turf to consider altitude.

DLamine202 commented 2 years ago

@IPWright83 Hello Sir, I have encountered the same problem with the levels. Indeed, I add to each point the level as its "z" coordinate. But I changed the weight function and still nothing happens. So I would like to know how you changed the function to make it work. Any ideas/suggestions from you are welcome.

IPWright83 commented 2 years ago

@DLamine202 I can't help as I don't have access to the code anymore. Maybe @ssar504 can help?

DLamine202 commented 2 years ago

@IPWright83 thank you for all