[几何]判断点是否在不规则多边形内

最近项目用到在Google map上判断事发地点,是否在管辖区域内。典型的判断一个点是否在不规则多边形内的例子。

但是Google map没有提供相应的api,找资料发现百度地图提供了,肿么办,为了一个工具类,加入百度地图吗,操蛋,这是不可能的!

百度地图api链接:

http://wiki.lbsyun.baidu.com/cms/androidsdk/doc/v3_7_0/com/baidu/mapapi/utils/SpatialRelationUtil.html

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!



那么下面自己搞一个吧,实测有效:

[java] view plain copy
  1. public class SpatialRelationUtil {  
  2.   
  3.     private SpatialRelationUtil() {  
  4.     }  
  5.   
  6.     public class Point {  
  7.         double x;  
  8.         double y;  
  9.     }  
  10.   
  11.     /** 
  12.      * 返回一个点是否在一个多边形区域内 
  13.      * 
  14.      * @param mPoints 多边形坐标点列表 
  15.      * @param point   待判断点 
  16.      * @return true 多边形包含这个点,false 多边形未包含这个点。 
  17.      */  
  18.     public static boolean isPolygonContainsPoint(List<Point> mPoints, Point point) {  
  19.         int nCross = 0;  
  20.         for (int i = 0; i < mPoints.size(); i++) {  
  21.             Point p1 = mPoints.get(i);  
  22.             Point p2 = mPoints.get((i + 1) % mPoints.size());  
  23.             // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数  
  24.             // p1p2是水平线段,要么没有交点,要么有无限个交点  
  25.             if (p1.y == p2.y)  
  26.                 continue;  
  27.             // point 在p1p2 底部 --> 无交点  
  28.             if (point.y < Math.min(p1.y, p2.y))  
  29.                 continue;  
  30.             // point 在p1p2 顶部 --> 无交点  
  31.             if (point.y >= Math.max(p1.y, p2.y))  
  32.                 continue;  
  33.             // 求解 point点水平线与当前p1p2边的交点的 X 坐标  
  34.             double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;  
  35.             if (x > point.x) // 当x=point.x时,说明point在p1p2线段上  
  36.                 nCross++; // 只统计单边交点  
  37.         }  
  38.         // 单边交点为偶数,点在多边形之外 ---  
  39.         return (nCross % 2 == 1);  
  40.     }  
  41.   
  42.     /** 
  43.      * 返回一个点是否在一个多边形边界上 
  44.      * 
  45.      * @param mPoints 多边形坐标点列表 
  46.      * @param point   待判断点 
  47.      * @return true 点在多边形边上,false 点不在多边形边上。 
  48.      */  
  49.     public static boolean isPointInPolygonBoundary(List<Point> mPoints, Point point) {  
  50.         for (int i = 0; i < mPoints.size(); i++) {  
  51.             Point p1 = mPoints.get(i);  
  52.             Point p2 = mPoints.get((i + 1) % mPoints.size());  
  53.             // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数  
  54.   
  55.             // point 在p1p2 底部 --> 无交点  
  56.             if (point.y < Math.min(p1.y, p2.y))  
  57.                 continue;  
  58.             // point 在p1p2 顶部 --> 无交点  
  59.             if (point.y > Math.max(p1.y, p2.y))  
  60.                 continue;  
  61.   
  62.             // p1p2是水平线段,要么没有交点,要么有无限个交点  
  63.             if (p1.y == p2.y) {  
  64.                 double minX = Math.min(p1.x, p2.x);  
  65.                 double maxX = Math.max(p1.x, p2.x);  
  66.                 // point在水平线段p1p2上,直接return true  
  67.                 if ((point.y == p1.y) && (point.x >= minX && point.x <= maxX)) {  
  68.                     return true;  
  69.                 }  
  70.             } else { // 求解交点  
  71.                 double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;  
  72.                 if (x == point.x) // 当x=point.x时,说明point在p1p2线段上  
  73.                     return true;  
  74.             }  
  75.         }  
  76.         return false;  
  77.     }  
  78.   
  79. }  


使用说明:只需要将SpatialRelationUtil这个工具类,复制到你的项目就可以直接使用,不用添加任何jar包。

效果展示:这个Demo展示判断事发地点是否在管辖区域内,也就是判断圆心是否在某一个基础区域内,如果在基础区域内,显示圆的半径(单位英里),如果不在基础区域给予提示:Point not in jurisdiction(事发点不在管辖范围内)。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值