地理信息系统和算法,以找到在我附近经过的游乐设施

时间:2014-01-08 21:29:48

标签: algorithm gis

我正在尝试开发一款可以找到我的游戏的应用程序不仅基于像我一样从A到B的人,而且即使我在其他人的A到B的路上。

例如,如果有人搜索从泽西海岸到曼哈顿的车程,并且有许多车道在那附近行驶,我需要一种算法来计算谁最接近这个人。这很有挑战性,因为我不是在寻找到一个点的距离,而是距离路线的距离(例如,司机本来可以进入他从华盛顿特区到曼哈顿)

谷歌地图API很棒,但我需要一个能够解决节点到边缘距离的算法/程序,可能还需要一个先进的GIS系统。

有谁知道我可以在哪里找到关于这个主题的工作?

3 个答案:

答案 0 :(得分:0)

您可以尝试一些空间数据结构,例如四叉树,r树,delaunay三角剖分:Find nearest edge in graph

答案 1 :(得分:0)

由于您没有提及您正在使用的技术,我无法了解具体细节,但这里有一些东西/库可以帮助您入门:

  • 的API:

    • JTS(Java拓扑套件):包含用于查找点和线之间距离的函数以及用于加速搜索附近线(R树,四叉树......)的数据结构。
    • NetTopologySuite:JTS的.NET端口,对于.NET,还有DotSpatial API
    • geos:JTS的C ++端口
    • 对于Python,有ShapelyRTree,...
  • 各种数据库都有空间扩展,但有两个值得注意的是:

如果您在Windows上工作,请查看OSGeo4W,这是各种程序和库的便捷安装程序。

另请注意,有一个专门用于GIS的stackexchange站点。

答案 2 :(得分:0)

你可以从你的点到代表别人路径的线串的“距离”开始。您可以使用Samuel提到的技术来执行此操作,也可以编写自己的代码。对于LineString上的距离测试,您可以将其分解为两个问题。找到线段与点之间的最短距离。然后对行字符串中的每个段重复该测试。这里发布的代码是简单的强力测试,并没有尝试做任何优化,但除非你处理数百万条路径,否则你可能不必这样做,在这种情况下,一些简单的范围测试或R-树可以通过缩小测试路径来帮助优化。此外,这里的代码是用Java编写的,但应该很简单,你可以很容易地翻译成其他语言。

用于查找点到点的距离的段代码:

  /**
   * Gets the closest point that is on the segment to the specified point, which
   * can be anywhere.
   * @param point The point to get the closest point to.
   * @return The Coordinate closest to the specified point.
   */
  public Coord closestPointTo(Coord point)
  {
    EndPointInteraction endPointFlag = EndPointInteraction.OnLine;
    return closestPointTo(point, false, endPointFlag);
  }

  /**
   * Gets the closest point the the specified point, given information about
   * whether the line is allowed to be infinite or not.
   * @param point The point to find the closest point to.
   * @param isInfiniteLine boolean.  If this is true, the segment is treated as if
   * it defines an infinite line.
   * @param endPointFlag This contains extra information about whether the point
   * is past the start or end of the segment or whether the segment is degenerate.
   * @return The Coordinate that is the closest point on the line to the specified point.
   */
  public Coord closestPointTo(Coord point, boolean isInfiniteLine, 
          EndPointInteraction endPointFlag) {
    // If the points defining this segment are the same, we treat the segment as a point
    // special handling to avoid 0 in denominator later
    if (P2.X == P1.X && P2.Y == P1.Y) {
      endPointFlag = EndPointInteraction.P1equalsP2;
      return P1;
    }

    //http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm

    Vector v = toVector(); // vector from p1 to p2 in the segment
    v.Z = 0;
    Vector w = new Vector(P1, point); // vector from p1 to Point
    w.Z = 0;
    double c1 = w.dot(v); // the dot product represents the projection onto the line

    if (c1 < 0) {
      endPointFlag = EndPointInteraction.PastP1;
      if (!isInfiniteLine) // The closest point on the segment to Point is p1
      {
        return P1;
      }
    }

    double c2 = v.dot(v);

    if (c2 <= c1) {
      endPointFlag = EndPointInteraction.PastP2;
      if (!isInfiniteLine) // The closest point on the segment to Point is p2
      {
        return P2;
      }
    }

    // The closest point on the segment is perpendicular to the point, 
    // but somewhere on the segment between P1 and P2 
    endPointFlag = EndPointInteraction.OnLine;
    double b = c1 / c2;
    v = v.multiply(b);
    Coord pb = new Coord(P1.X + v.X, P1.Y + v.Y);
    return pb;
  }

  /**
   * Gets the minimum distance to the specified coordinate.
   * @param point The point to get the distance from this segment to.
   * @return The double distance.
   */
  public double distanceTo(Coord point)
  {
    return closestPointTo(point).distance(point);
  }

LineString(或带有坐标列表的任何部分)代码循环遍历段以获得距离:

  /**
   * Gets the minimum distance to an edge of the part.  This does not consider whether the point
   * is inside the part or not.
   * @param coordinate
   * @return 
   */
  public double distance(Coord coordinate)
  {
    List<Segment> segs = this.getSegments();
    double minDist = Double.MAX_VALUE;
    for(Segment seg : segs)
    {
      double dist = seg.distanceTo(coordinate);
      if(dist < minDist)
      {
        minDist = dist;
      }
    }
    return minDist;
  }

  /**
   * Generates a set of segments that represent this part.
   * @return 
   */
  public List<Segment> getSegments()
  {
    List<Segment> result = new ArrayList<Segment>();
    if(getCoordinates().size() < 2) {
      return result;
    }
    for(int i = 0; i < getCoordinates().size()-1; i++)
    {
      result.add(new Segment(getCoordinates().get(i), getCoordinates().get(i+1)));
    }
    if(closed)
    {
      result.add(new Segment(getCoordinates().get(getCoordinates().size()-1), getCoordinates().get(0)));
    }
    return result;
  }