根据我的需求,我正在谷歌地图上绘制多边形,如下所示的图片。(使用maps v2)
现在我需要在用户进入该特定多边形时显示一个警报。
如何确定我的当前位置是否在多边形内。 (需要优化方式,不会消耗电池)
提前感谢。
根据我的需求,我正在谷歌地图上绘制多边形,如下所示的图片。(使用maps v2)
现在我需要在用户进入该特定多边形时显示一个警报。
如何确定我的当前位置是否在多边形内。 (需要优化方式,不会消耗电池)
提前感谢。
我刚试过射线投射算法,这个算法可以准确地识别多边形中的点。
详细内容请参考http://en.wikipedia.org/wiki/Point_in_polygon上关于射线投射算法的论文。
private boolean isPointInPolygon(LatLng tap, ArrayList<LatLng> 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(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;
}
我发现射线投射方法不可靠,但最终我使用了来自谷歌地图的PolyUtil
。
你需要依赖compile 'com.google.maps.android:android-maps-utils:0.5'
然后这个方法看起来像这样
PolyUtil.containsLocation(userLocation, polyPointsList, false);
编辑
这是在源代码中找到的该方法的描述。
计算给定点是否位于指定多边形内部。无论最后一个点是否等于第一个点,该多边形始终被视为闭合。内部定义为不包含南极 -- 南极始终在外部。如果geodesic为true,则多边形由大圆段组成,否则由rhumb(loxodromic)段组成。
请查看以下链接:
Polygon Touch detection Google Map API V2
这是RayCasting算法,它可能对你有帮助 :)
该算法的简要描述如下:
从你的点向右绘制一条水平线,如果它与多边形的边相交的次数是奇数,则该点在多边形内部,否则在外部 :)
这些维基链接将为您提供完整的想法:
以下是使用Dart编写的代码,取自于: https://github.com/KohlsAdrian/google_maps_utils/blob/master/lib/poly_utils.dart
/// Checks if [point] is inside [polygon]
static bool containsLocationPoly(Point point, List<Point> polygon) {
num ax = 0;
num ay = 0;
num bx = polygon[polygon.length - 1].x - point.x;
num by = polygon[polygon.length - 1].y - point.y;
int depth = 0;
for (int i = 0; i < polygon.length; i++) {
ax = bx;
ay = by;
bx = polygon[i].x - point.x;
by = polygon[i].y - point.y;
if (ay < 0 && by < 0) continue; // both "up" or both "down"
if (ay > 0 && by > 0) continue; // both "up" or both "down"
if (ax < 0 && bx < 0) continue; // both points on left
num lx = ax - ay * (bx - ax) / (by - ay);
if (lx == 0) return true; // point on edge
if (lx > 0) depth++;
}
return (depth & 1) == 1;
}