2013-04-04 102 views
8

有一天我在Java中做了一個類來計算point(X,Y)是否在多邊形內。 (XYdouble,因爲將是地理座標)。Android中的點內多邊形測試

我知道Java有類Polygon,但我不得不使用Path2DPoint2D,因爲Polygon不允許double的,只是整數:(

我一旦多邊形在Path2D做的,我使用的方法containsPath2D了吧),我的問題解決了

但現在,我要導入到Android的,問題就在這裏,因爲Path2D需要進口。

import java.awt.geom.Path2D; 
import java.awt.geom.Point2D; 

在Android中不存在awt,所以我無法使用。

那麼,有沒有類似於Path2D那有contains方法?或者我必須自己計算?

這是我如何使用Path2D沒有在Java中:

private void ConstructPolygon(Vector<Point2D> coodinates) 
{  
    this.polygon.moveTo(coodinates.get(0).getX(), coodinates.get(0).getY());   

    //System.out.println(coodinates.get(0).getX() + " " + coodinates.get(0).getY()); 
    //System.out.println("asda"); 

    for(int i = 1; i < this.num_points; i++) 
    { 
     //System.out.println(coodinates.get(i).getX() + " " + coodinates.get(i).getY()); 
     this.polygon.lineTo(coodinates.get(i).getX(), coodinates.get(i).getY()); 
    } 
    this.polygon.closePath(); 
} 
public boolean InsideCity(Point2D punto) 
{ 
    return this.polygon.contains(punto);     
} 
+0

也許你可能只是10000乘以所有'double'值並使用它們與Java'Polygon'類? – 2016-04-20 07:51:46

回答

29

您可以準確地用我的簡單的庫這樣的:https://github.com/snatik/polygon-contains-point

準備多邊形:

Polygon polygon = Polygon.Builder() 
    .addVertex(new Point(1, 3)) 
    .addVertex(new Point(2, 8)) 
    .addVertex(new Point(5, 4)) 
    .addVertex(new Point(5, 9)) 
    .addVertex(new Point(7, 5)) 
    .addVertex(new Point(6, 1)) 
    .addVertex(new Point(3, 1)) 
    .build(); 

並檢查,而該點位於多邊形內:

Point point = new Point(4.5f, 7); 
boolean contains = polygon.contains(point); 

它與浮動的類型,幷包含孔:)

+1

Hi @sromku! 我得到了一個問題,我必須閱讀一個KML文件才能獲得座標,但是這可能會超過100分......所以我如何使用這些Builder的所有這些點? 因爲我的想法是讀取kml,獲得向量中的點(例如),然後構建多邊形... soo ..我不知道如何使用你的方式:(你可以嗎幫助我? 謝謝!!(代碼完美無缺!) – Shudy 2013-04-10 16:15:42

+0

請注意,此代碼無法通過它使用的奇怪傾斜光線直接碰到頂點的測試用例。 – Tatarize 2016-04-26 00:21:11

+0

即使使用最簡單的形狀,該庫也存在問題,請在考慮之前檢查問題列表。 https://github.com/sromku/polygon-contains-point/issues – 2016-07-09 07:37:20

4

對不起多邊形@ sromku我問自己(我從來沒有使用這種類型的東西)

這就是我如何解決如果任何人有相同的問題

Builder poly2 = new Polygon.Builder(); 
    for(int i = 0; i< xpoints.length;i++){ 
     poly2.addVertex(new Point(xpoints[i],ypoints[i])); 
    } 
    Polygon polygon2 = poly2.build(); 
5

這是我在Android中做到的。 正是基於這個java程序(光線投射算法): https://gis.stackexchange.com/questions/42879/check-if-lat-long-point-is-within-a-set-of-polygons-using-google-maps/46720#46720

public boolean pointInPolygon(LatLng point, Polygon polygon) { 
     // ray casting alogrithm http://rosettacode.org/wiki/Ray-casting_algorithm 
     int crossings = 0; 
     List<LatLng> path = polygon.getPoints(); 
     path.remove(path.size()-1); //remove the last point that is added automatically by getPoints() 

     // for each edge 
     for (int i=0; i < path.size(); i++) { 
      LatLng a = path.get(i); 
      int j = i + 1; 
      //to close the last edge, you have to take the first point of your polygon 
      if (j >= path.size()) { 
       j = 0; 
      } 
      LatLng b = path.get(j); 
      if (rayCrossesSegment(point, a, b)) { 
       crossings++; 
      } 
     } 

     // odd number of crossings? 
     return (crossings % 2 == 1); 
    } 

    public boolean rayCrossesSegment(LatLng point, LatLng a,LatLng b) { 
       // Ray Casting algorithm checks, for each segment, if the point is 1) to the left of the segment and 2) not above nor below the segment. If these two conditions are met, it returns true 
       double px = point.longitude, 
       py = point.latitude, 
       ax = a.longitude, 
       ay = a.latitude, 
       bx = b.longitude, 
       by = b.latitude; 
      if (ay > by) { 
       ax = b.longitude; 
       ay = b.latitude; 
       bx = a.longitude; 
       by = a.latitude; 
      } 
      // alter longitude to cater for 180 degree crossings 
      if (px < 0 || ax <0 || bx <0) { px += 360; ax+=360; bx+=360; } 
      // if the point has the same latitude as a or b, increase slightly py 
      if (py == ay || py == by) py += 0.00000001; 


      // if the point is above, below or to the right of the segment, it returns false 
      if ((py > by || py < ay) || (px > Math.max(ax, bx))){ 
       return false; 
      } 
      // if the point is not above, below or to the right and is to the left, return true 
      else if (px < Math.min(ax, bx)){ 
       return true; 
      } 
      // if the two above conditions are not met, you have to compare the slope of segment [a,b] (the red one here) and segment [a,p] (the blue one here) to see if your point is to the left of segment [a,b] or not 
      else { 
       double red = (ax != bx) ? ((by - ay)/(bx - ax)) : Double.POSITIVE_INFINITY; 
       double blue = (ax != px) ? ((py - ay)/(px - ax)) : Double.POSITIVE_INFINITY; 
       return (blue >= red); 
      } 

    } 
+0

請分享鏈接讓Polygon class – 2015-04-28 07:53:43

+0

能工作嗎? – 2017-01-05 13:37:46

9

您可以使用谷歌地圖PolyUtil:

import com.google.maps.android.PolyUtil; 

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true);