perliedman/geojson-path-finder

[long, lat, altitude] ?

Opened this issue · 8 comments

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!

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.

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!

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.

@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 Turfjs/turf#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 :)

@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.

@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.

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

@IPWright83 thank you for all