检查用户是否在GPS附近的路线检查点

时间:2011-12-19 16:36:25

标签: geolocation gps routes

情况如下:

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

黑线表示预定路径,蓝色球表示检查点,蓝色多边形表示所需区域。绿线是一个更精确的用户,红线是一个不太准确的用户(一个醉酒的家伙可能会驾驶?)。两条线都应该在多边形内部,但是完全不跳过路线的用户不应该。

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

有什么建议吗?

修改

我正在考虑使用简单的distanceTo()函数来绘制一个假想的圆圈并检查用户是否在那里。这很好,因为实现和理解非常简单,而且很糟糕,因为为了确保最敏感的用户在检查点通过,我需要一个很大的半径,使正确的用户比预期更快地进入检查点区域。

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

3 个答案:

答案 0 :(得分:2)

假设你知道检查点的GeoLocation,你可以检查两者之间的距离。

使用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转换为像素,在您需要的区域周围创建“边界”。

将这些点存储到List&lt;&gt;点数,你应该全部设定。

答案 1 :(得分:1)

在下面的链接中查看一些algos来执行此操作

http://geospatialpython.com/2011/01/point-in-polygon.html

答案 2 :(得分: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精度的误差移动与用户的实际速度相当,那么这会产生多个通过标记,但这几乎可以达到任何算法。