2011-12-19 175 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