简体   繁体   English

使用Android中的Google Maps API检查点是否为多边形

[英]Check if point is in polygon with Google Maps API in Android

I am using the Google Maps API on Android to create a puzzle. 我在Android上使用Google Maps API来制作拼图。 This link contains the data I used to draw African countries: World countries coordinates . 此链接包含我用于绘制非洲国家的数据: 世界国家坐标

When the user clicks on the map, a test is done to check whether it was in the right country or not. 当用户点击地图时,会进行测试以检查它是否在正确的国家/地区。

  • point inside right country: the right country is colored in green 指向正确的国家:正确的国家是绿色的

  • point inside another known country: the current country is colored in red 指向另一个已知国家:当前国家的颜色为红色

The code below iterates the list of African countries (a country may contain multiple polygons) to find the one that contains the clicked point and compare it with the right country. 下面的代码迭代非洲国家/地区列表(一个国家可能包含多个多边形),以找到包含点击点的那个,并将其与正确的国家进行比较。

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

The function isPointInPolygon() works with only one polygon on the map because it's based on geometry (ray intersect). 函数isPointInPolygon()仅在地图上使用一个多边形,因为它基于几何(光线相交)。 It doesn't work in my case. 它在我的情况下不起作用。 For example, when I click inside Chad the country (the blue spot in this picture ), Egypt is getting colored with red (my list is sorted alphabetically, so Egypt is the first one on the right of the clicked point that verifies the ray intersect condition). 例如,当我点击乍得国家( 这张照片中的蓝点)时,埃及变成红色(我的列表按字母顺序排序,因此埃及是点击点右侧的第一个验证光线相交的点条件)。

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

What's the right way to get the polygon which was clicked from my list? 获取从列表中单击的多边形的正确方法是什么?

You can use the PolyUtil.containsLocation method from the Google Maps Android API Utility Library . 您可以使用Google Maps Android API Utility Library中PolyUtil.containsLocation方法。 From the documentation : 文档

public static boolean containsLocation(LatLng point, java.util.List polygon, boolean geodesic) 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. 如果测地线为真,则多边形由大圆段形成,否则由多边形(loxodromic)段形成。

A bit later response, but for future searches, you can also check if a location is inside the current visible map area by using: 稍后响应,但对于将来的搜索,您还可以使用以下方法检查位置是否在当前可见地图区域内:

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

Documentation link: contains (LatLng point) 文档链接: 包含(LatLng点)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM