多边形触摸检测谷歌地图API V2

我试图弄清楚如何最好地做到这一点,我有一张地图,上面画了一张。因为Google Maps API V2似乎没有在多边形上进行触摸检测。我想知道是否有可能检测触摸点是否在多边形内?如果是这样,那么我的主要目标是在地图上勾勒出一个状态,当用户点击该状态时,它将在自定义视图中显示更多详细信息。截至目前,我能够捕获地图,但是当用户点击内部时,我希望在.我是一个新手,所以如果我不够清楚,我很抱歉。PolygonMapOnClickPolygonpolygon.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);
     }    

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

    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;
}

}

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


答案 1

您尝试解决的问题是多边形中的点检验。

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

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


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

您的多边形由一系列顶点组成:。你需要单独查看每个,看看你是否与它相交ArrayList<Geopoint> verticesLine SegmentRay

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;
}

答案 2

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

PolyUtil.containsLocation(LatLng point, List<LatLng>polygon, boolean geodesic);

尽管文档在指南中没有明确提及它,但该方法就在那里

地图支持库文档


推荐