最近项目用到在Google map上判断事发地点,是否在管辖区域内。典型的判断一个点是否在不规则多边形内的例子。
但是Google map没有提供相应的api,找资料发现百度地图提供了,肿么办,为了一个工具类,加入百度地图吗,操蛋,这是不可能的!
百度地图api链接:
com.baidu.mapapi.utils类 SpatialRelationUtil
- java.lang.Object
- com.baidu.mapapi.utils.SpatialRelationUtil
Point Inclusion
• given a polygon and a point, is the point inside oroutside the polygon?
• orientation helps solving this problem in linear time
Point Inclusion — Part II
• Draw a horizontal line to the right of each point andextend it to infinity
• Count the number of times a line intersects thepolygon. We have:
- even number ⇒ point is outside
- odd number ⇒ point is inside
• Why?
• What about points d and g ?? Degeneracy!
那么下面自己搞一个吧,实测有效:
- public class SpatialRelationUtil {
- private SpatialRelationUtil() {
- }
- public class Point {
- double x;
- double y;
- }
- /**
- * 返回一个点是否在一个多边形区域内
- *
- * @param mPoints 多边形坐标点列表
- * @param point 待判断点
- * @return true 多边形包含这个点,false 多边形未包含这个点。
- */
- public static boolean isPolygonContainsPoint(List<Point> mPoints, Point point) {
- int nCross = 0;
- for (int i = 0; i < mPoints.size(); i++) {
- Point p1 = mPoints.get(i);
- Point p2 = mPoints.get((i + 1) % mPoints.size());
- // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
- // p1p2是水平线段,要么没有交点,要么有无限个交点
- if (p1.y == p2.y)
- continue;
- // point 在p1p2 底部 --> 无交点
- if (point.y < Math.min(p1.y, p2.y))
- continue;
- // point 在p1p2 顶部 --> 无交点
- if (point.y >= Math.max(p1.y, p2.y))
- continue;
- // 求解 point点水平线与当前p1p2边的交点的 X 坐标
- double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
- if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
- nCross++; // 只统计单边交点
- }
- // 单边交点为偶数,点在多边形之外 ---
- return (nCross % 2 == 1);
- }
- /**
- * 返回一个点是否在一个多边形边界上
- *
- * @param mPoints 多边形坐标点列表
- * @param point 待判断点
- * @return true 点在多边形边上,false 点不在多边形边上。
- */
- public static boolean isPointInPolygonBoundary(List<Point> mPoints, Point point) {
- for (int i = 0; i < mPoints.size(); i++) {
- Point p1 = mPoints.get(i);
- Point p2 = mPoints.get((i + 1) % mPoints.size());
- // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
- // point 在p1p2 底部 --> 无交点
- if (point.y < Math.min(p1.y, p2.y))
- continue;
- // point 在p1p2 顶部 --> 无交点
- if (point.y > Math.max(p1.y, p2.y))
- continue;
- // p1p2是水平线段,要么没有交点,要么有无限个交点
- if (p1.y == p2.y) {
- double minX = Math.min(p1.x, p2.x);
- double maxX = Math.max(p1.x, p2.x);
- // point在水平线段p1p2上,直接return true
- if ((point.y == p1.y) && (point.x >= minX && point.x <= maxX)) {
- return true;
- }
- } else { // 求解交点
- double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
- if (x == point.x) // 当x=point.x时,说明point在p1p2线段上
- return true;
- }
- }
- return false;
- }
- }
使用说明:只需要将SpatialRelationUtil这个工具类,复制到你的项目就可以直接使用,不用添加任何jar包。
效果展示:这个Demo展示判断事发地点是否在管辖区域内,也就是判断圆心是否在某一个基础区域内,如果在基础区域内,显示圆的半径(单位英里),如果不在基础区域给予提示:Point not in jurisdiction(事发点不在管辖范围内)。
[几何]判断点是否在不规则多边形内
最新推荐文章于 2021-09-03 11:42:53 发布