2011-12-19 106 views
5

这里的情况:检查用户是否是附近路线检查站与GPS

我有一个预定的路径GPS用户将运行。该路线有一些检查站,用户应该通过所有检查站(将它们视为赛车游戏检查站,防止用户采取捷径)。我需要确保用户通过所有检查点。 我想确定一个将在检查点范围内考虑的区域,但我不希望它只是一个径向区域,它应该是考虑到路径形式的区域。 不明白吗?我也没有看到这张画得很差的图片,以便更好地理解它: Route example

黑色线代表预定路径,蓝色球是检查点,蓝色多边形是有用区域。绿线是一个更精确的用户,红线是一个不太准确的用户(一个喝醉酒的家伙驾驶也许是大声笑)。这两条线应位于多边形内,但完全跳过路线的用户不应该。

我已经在这里看到了一个函数来检查用户是否在这样一个多边形内,但我需要知道如何计算多边形。

有什么建议吗?

编辑:

我使用的是简单的distanceTo()函数只画一个假想的圆,并检查用户是否有考虑。这很好,因为实现和理解起来非常简单,而且很糟糕,因为要确保最有可能的用户在检查点通过时,我需要一个大的半径,使得正确的用户更快地进入检查点区域。

只是让你们更好地理解情况,这是为了应用程序应该用于交通(汽车或公共汽车),并且检查点应该是划分你的路线的地标或景点,例如,某处交通堵塞开始或停止的地方。

+0

为什么你需要一个多边形而不是使用内圈? – SERPRO 2011-12-19 16:51:21

回答

2

你可以只检查两个之间的距离,假设你知道检查点的地理位置。

使用distanceTo函数并设置用户需要从检查点继续运行的多个仪表的阈值。

编辑

既然你想避免distanceTo,这里是一个小功能,我写了一段时间后,检查点是否在一个多边形:

public boolean PIP(Point point, List<Point> polygon){ 
    boolean nodepolarity=false; 
    int sides = polygon.size(); 
    int j = sides -1; 
    for(int i=0;i<sides;i++){ 
     if((polygon.get(i).y<point.y && polygon.get(j).y>=point.y) ||(polygon.get(j).y<point.y && polygon.get(i).y>=point.y)){ 
      if (polygon.get(i).x+(point.y-polygon.get(i).y)/(polygon.get(j).y-polygon.get(i).y)*(polygon.get(j).x-polygon.get(i).x)<point.x) { 
       nodepolarity=!nodepolarity; 
      } 
     } 
    j=i; 
    } 
    return nodepolarity; //FALSE=OUTSIDE, TRUE=INSIDE 
} 

List<Point> polygon是名单构成多边形的点。

这使用Ray casting algorithm来确定光线通过多边形的交点。

您只需要使用toPixels方法将GeoPoints转换为像素,在需要的区域周围创建'边界'。

将这些点存储到点列表中,并且应该全部设置。

+0

这正是我想要避免的,如果我这样做,我会失去一些精确度,但如果我没有找到其他东西,我会研究它。 – 2011-12-19 19:47:37

+0

@RodrigoCastro查看编辑 – MrZander 2011-12-19 21:11:53

+0

Thaanks,我几乎完成了创建该区域的工作(实际上,我在思考更多关于它后改变了我想要的定义)。我编辑了一个新的(更好的)图像显示我想要的问题。 – 2011-12-20 03:22:08

1

我知道这是一个古老的问题,但也许它会对某人有用。

这是一个更简单的方法,所需的计算量更少。这不会在用户第一次进入阈值区域时触发,它只会得到用户在检查点附近通过的最近点,以及他已经接近的最近点。

这个想法是为每个检查点维护一个3个项目的距离列表,其中最后三个距离(所以它应该是[d(t),d(t-1),d(t-2) ])。这个列表应该在每个距离计算中旋转。如果在任何距离计算中先前的d(t-1)距离小于当前的d(t)并且大于先前的d(t-2),则移动点已经通过检查点。通过检查实际距离d(t-1)可以确定这是否是真正的通过,或者这只是一个小故障。

private long DISTANCE_THRESHOLD = 2000; 

private Checkpoint calculateCheckpoint(Map<Checkpoint, List<Double>> checkpointDistances) 
{ 
    Map<Checkpoint, Double> candidates = new LinkedHashMap<Checkpoint, Double>(); 
    for (Checkpoint checkpoint: checkpointDistances.keySet()) 
    { 
     List<Double> distances = checkpointDistances.get(checkpoint); 
     if (distances == null || distances.size() < 3) 
      continue; 
     if (distances.get(0) > distances.get(1) && distances.get(1) < distances.get(2) && distances.get(1) < (DISTANCE_THRESHOLD)) //TODO: make this depend on current speed 
      candidates.put(checkpoint, distances.get(1)); 
    } 

    List<Entry<Checkpoint, Double>> list = new LinkedList<Entry<Checkpoint,Double>>(candidates.entrySet()); 
    Collections.sort(list, comp); 

    if (list.size() > 0) 
     return list.get(0).getKey(); 
    else 
     return null; 
} 

Comparator<Entry<Checkpoint, Double>> comp = new Comparator<Entry<Checkpoint,Double>>() 
{ 
    @Override 
    public int compare(Entry<Checkpoint, Double> o1, Entry<Checkpoint, Double> o2) 
    { 
     return o1.getValue().compareTo(o2.getValue()); 
    } 
}; 

的函数获取一个参数 - 一个Map<Checkpoint, List<Double>>与检查站和最后三个距离的列表。它输出最近的Checkpoint通过或null(如果没有)。 应该明智地选择DISTANCE_THRESHOLDComparator只是为了能够根据检查点距离用户的距离来排序检查点以获取最近的检查点。

当然这有一些小缺陷,例如,如果移动点移动十字交叉,或者GPS精度的误差移动与用户的实际速度相称,则会产生多个合格标记,但这几乎会碰到任何算法。

+0

谢谢,我不再在原来的项目上工作,但这可能会帮助我即将开展的巴士跟踪项目! – 2013-05-16 02:58:34

+0

我认为在同一时间保持超过3点的内存可能是一个好主意,以检查可能暗示GPS故障的不一致性,而不是指示用户已经离开该区域的实际数据 – 2013-05-16 03:00:29

+1

@ rodrigo-卡特罗是,这3点是解决问题的绝对最低要求。更多的点会减少错误的可能性,但会使代码复杂化。也许这应该留给一些更智能的算法(也许是GPS芯片本身),它可以滤除测量的抖动并仅提供真实/有效的运动数据。所以这是另一个问题。 :) – Tylla 2013-05-17 14:13:52