使用 Google Maps API in Android 检查点是否在多边形中

Check if point is in polygon with Google Maps API in Android

我正在 Android 上使用 Google 地图 API 创建一个谜题。这个link包含我用来画非洲国家的数据:World countries coordinates.

当用户点击地图时,会进行测试以检查它是否位于正确的国家/地区。

下面的代码遍历非洲国家列表(一个国家可能包含多个多边形)以找到包含点击点的国家并将其与正确的国家进行比较。

mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    @Override
    public void onMapClick(LatLng latLng) {

        if(isPointInPolygon(latLng,answerPolygon)) {
            // right answer
            Toast.makeText(MapsActivity.this, "point inside the right polygon", Toast.LENGTH_SHORT).show();
            Polygon p = mMap.addPolygon(new PolygonOptions().addAll(answerPolygon));
            p.setStrokeWidth(p.getStrokeWidth()/5);
            p.setFillColor(0x7F00FF00);
        }
        else {
            // wrong answer
            // search current polygon
            // color current polygon in red
            if (colorPolygonInRed(latLng)){
                Polygon p = mMap.addPolygon(new PolygonOptions().addAll(answerPolygon));
                p.setStrokeWidth(p.getStrokeWidth()/5);
                p.setFillColor(0x7F00FF00);
                Toast.makeText(MapsActivity.this, "point in known polygons", Toast.LENGTH_SHORT).show();
            }
            else {
                Toast.makeText(MapsActivity.this, "point in unknown polygons", Toast.LENGTH_SHORT).show();
            }
        }
    }
});

函数 isPointInPolygon() 仅适用于地图上的一个多边形,因为它基于几何(射线相交)。它在我的情况下不起作用。 例如,当我在乍得国内单击时(this picture 中的蓝点),埃及会变成红色(我的列表是按字母顺序排序的,所以埃及是点击点右侧的第一个验证点光线相交条件)。

public 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>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;
}
public boolean colorPolygonInRed(LatLng point){
    for (Country country:countryList){
        for (ArrayList<LatLng> polygon : country.getCoordinates()){
            if(isPointInPolygon(point,polygon)) {
                Polygon p = mMap.addPolygon(new PolygonOptions().addAll(polygon));
                p.setStrokeWidth(p.getStrokeWidth()/5);
                p.setFillColor(0x7FE00808);
                return true;
            }
        }
    }
    return false;
}

获取从我的列表中单击的多边形的正确方法是什么?

您可以使用 Google Maps Android API Utility Library. From the documentation 中的 PolyUtil.containsLocation 方法:

public static boolean containsLocation(LatLng point, java.util.List polygon, boolean geodesic)

Computes whether the given point lies inside the specified polygon. The polygon is always considered closed, regardless of whether the last point equals the first or not. Inside is defined as not containing the South Pole -- the South Pole is always outside. The polygon is formed of great circle segments if geodesic is true, and of rhumb (loxodromic) segments otherwise.

稍后回复,但为了以后的搜索,您还可以使用以下方法检查某个位置是否在当前可见地图区域内:

// Kotlin code
var location = LatLng(-27.6016488, -48.5137219)    
val isInside = mGoogleMap.projection.visibleRegion.latLngBounds.contains(location)

文档 link:contains (LatLng point)