Polygon Touch检测Google Map API V2

Dwi*_*ill 12 java android coordinates point-in-polygon google-maps-android-api-2

我想弄清楚如何最好地做到这一点,我有一张地图上Polygon画了一张.因为Google Maps API V2似乎没有在Polygon上进行触摸检测.我很想知道是否可以检测触点是否在Polygon内?如果是这样,我的主要目标是在地图上勾画状态,当用户点击该状态时,它将在自定义视图中显示更多细节.到目前为止,我能够捕获MapOnClick地图,但是当用户点击内部时,Polygon我想要polygon.getID()设置在地图上Toast.我是新手,所以如果我不够清楚,我会道歉.

googleMap.setOnMapClickListener(new OnMapClickListener() 
    {
        public void onMapClick(LatLng point) 
        {
        boolean checkPoly = true;

        Toast.makeText(MainActivity.this,"The Location is outside of the Area", Toast.LENGTH_LONG).show();
        }    
     });
     }
     }
   catch (Exception e) {
         Log.e("APP","Failed", e);
     }    
Run Code Online (Sandbox Code Playgroud)

好的,这就是我到目前为止所做的半工作

    private boolean rayCastIntersect(LatLng tap, LatLng vertA, LatLng vertB) {

    double aY = vertA.latitude;
    double bY = vertB.latitude;
    double aX = vertA.longitude;
    double bX = vertB.longitude;
    double pY = tap.latitude;
    double pX = tap.longitude;
     if (aY > bY) {
            aX = vertB.longitude;
            aY = vertB.latitude;
            bX = vertA.longitude;
            bX = vertA.latitude;
        }
    System.out.println("aY: "+aY+" aX : "+aX);
    System.out.println("bY: "+bY+" bX : "+bX);

     if (pX < 0) pX += 360;
        if (aX < 0) aX += 360;
        if (bX < 0) bX += 360;

        if (pY == aY || pY == bY) pY += 0.00000001;
        if ((pY > bY || pY < aY) || (pX > Math.max(aX, bX))) return false;
        if (pX < Math.min(aX, bX))

            return true;
//  }

    double m = (aX != bX) ? ((bY - aY) / (bX - aX)) : aX;
    double bee = (aX != pX) ? ((pY - aY) / (pX - aX)) : aX;
    double x = (pY - bee) / m;

    return x > pX;
}
Run Code Online (Sandbox Code Playgroud)

}

我遇到的问题是触摸在每个多边形的左边都是真的,直到到达另一个多边形.我的算法会导致这个问题出了什么问题?任何帮助,将不胜感激.

Mat*_*att 24

您要解决的问题是Point in Polygon测试.

为了帮助可视化光线投射的概念:

在一张纸上绘制多边形.然后,从任意随机点开始,在页面右侧画一条直线.如果您的线与多边形相交了奇数次,则表示您的起点位于多边形内.


那么,你如何在代码中做到这一点?

您的多边形由顶点列表组成: ArrayList<Geopoint> vertices.您需要Line Segment单独查看每个,并查看Ray它是否相交

private boolean isPointInPolygon(Geopoint tap, ArrayList<Geopoint> vertices) {
    int intersectCount = 0;
    for(int j=0; j<vertices.size()-1; j++) {
        if( rayCastIntersect(tap, vertices.get(j), vertices.get(j+1)) ) {
            intersectCount++;
        }
    }

    return (intersectCount%2) == 1); // odd = inside, even = outside;
}

private boolean rayCastIntersect(Geopoint tap, Geopoint vertA, Geopoint vertB) {

    double aY = vertA.getLatitude();
    double bY = vertB.getLatitude();
    double aX = vertA.getLongitude();
    double bX = vertB.getLongitude();
    double pY = tap.getLatitude();
    double pX = tap.getLongitude();

    if ( (aY>pY && bY>pY) || (aY<pY && bY<pY) || (aX<pX && bX<pX) ) {
        return false; // a and b can't both be above or below pt.y, and a or b must be east of pt.x
    }

    double m = (aY-bY) / (aX-bX);               // Rise over run
    double bee = (-aX) * m + aY;                // y = mx + b
    double x = (pY - bee) / m;                  // algebra is neat!

    return x > pX;
}
Run Code Online (Sandbox Code Playgroud)

  • @MuhammadBabar我想在一个单独的线程上问这个。有两种解决这个问题的方法。这很棘手,因为需要可点击的区域缓冲区(用户在线上精确点击的几率很小) (2认同)

use*_*495 15

Google地图支持库现在有一个静态方法可以为您检查:

PolyUtil.containsLocation(LatLng point, List<LatLng>polygon, boolean geodesic);
Run Code Online (Sandbox Code Playgroud)

尽管文档没有在指南中明确提及,但方法仍然存在

地图支持库文档


mat*_*ash 9

随着Google Play Services 8.4.0的发布,Maps API已经包含了对添加OnPolygonClickListener多边形的支持.这两个多边形,折线和覆盖支持类似的活动.

您只需要调用GoogleMap.setOnPolygonClickListener(OnPolygonClickListener listener)它来设置它,并相应地为其他侦听器(setOnPolylineClickListener,&c):

map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {  
    @Override  
    public void onPolygonClick(Polygon polygon) {  
        // Handle click ...  
    }  
});  
Run Code Online (Sandbox Code Playgroud)

虽然有点晚,但它很好地解决了这个用例.