博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
地图,判断点与多边形位置关系
阅读量:5741 次
发布时间:2019-06-18

本文共 5709 字,大约阅读时间需要 19 分钟。

hot3.png

废话不多说,直接看代码

资料来源:http://paulbourke.net/geometry/polygonmesh/index.html#insidepoly

package com.xxx.utils.map;import java.util.Arrays;import com.xxx.bo.Point;/** * 用于点与多边形位置关系的判断 *  * @author liuwei * @date 2015年4月9日13:29:21 */public class GraphUtils {	/**	 * 判断点是否在圆形内 (俩点距离小于半径)	 */	public static boolean isPointInCircle(Point point, Point boundary, Double radius) {		if (boundary != null && point != null && radius != null && radius >= 0) {			double number = PointMath.distanceOfTwoPositionNew(point, boundary);			return radius >= number;		} else {			return false;		}	}	/**	 * 判断点是否在多边形内(基本思路是用交点法)	 * 	 * @param point	 * @param boundaryPoints	 * @return	 */	public static boolean isPointInPolygon(Point point, Point[] boundaryPoints) {		// 防止第一个点与最后一个点相同		if (boundaryPoints != null && boundaryPoints.length > 0				&& boundaryPoints[boundaryPoints.length - 1].equals(boundaryPoints[0])) {			boundaryPoints = Arrays.copyOf(boundaryPoints, boundaryPoints.length - 1);		}		int pointCount = boundaryPoints.length;		// 首先判断点是否在多边形的外包矩形内,如果在,则进一步判断,否则返回false		if (!isPointInRectangle(point, boundaryPoints)) {			return false;		}		// 如果点与多边形的其中一个顶点重合,那么直接返回true		for (int i = 0; i < pointCount; i++) {			if (point.equals(boundaryPoints[i])) {				return true;			}		}		/**		 * 基本思想是利用X轴射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则在多边形内。还会考虑一些特殊情况,如点在多边形顶点上		 * , 点在多边形边上等特殊情况。		 * http://paulbourke.net/geometry/polygonmesh/index.html#insidepoly		 */		// X轴射线与多边形的交点数		int intersectPointCount = 0;		// X轴射线与多边形的交点权值		float intersectPointWeights = 0;		// 浮点类型计算时候与0比较时候的容差		double precision = 2e-10;		// 边P1P2的两个端点		Point point1 = boundaryPoints[0], point2;		// 循环判断所有的边		for (int i = 1; i <= pointCount; i++) {			point2 = boundaryPoints[i % pointCount];			/**			 * 如果点的y坐标在边P1P2的y坐标开区间范围之外,那么不相交。			 */			if (point.getLat() < Math.min(point1.getLat(), point2.getLat())					|| point.getLat() > Math.max(point1.getLat(), point2.getLat())) {				point1 = point2;				continue;			}			/**			 * 此处判断射线与边相交			 */			if (point.getLat() > Math.min(point1.getLat(), point2.getLat())					&& point.getLat() < Math.max(point1.getLat(), point2.getLat())) {// 如果点的y坐标在边P1P2的y坐标开区间内				if (point1.getLng() == point2.getLng()) {// 若边P1P2是垂直的					if (point.getLng() == point1.getLng()) {						// 若点在垂直的边P1P2上,则点在多边形内						return true;					} else if (point.getLng() < point1.getLng()) {						// 若点在在垂直的边P1P2左边,则点与该边必然有交点						++intersectPointCount;					}				} else {// 若边P1P2是斜线					if (point.getLng() <= Math.min(point1.getLng(), point2.getLng())) {// 点point的x坐标在点P1和P2的左侧						++intersectPointCount;					} else if (point.getLng() > Math.min(point1.getLng(), point2.getLng())							&& point.getLng() < Math.max(point1.getLng(), point2.getLng())) {// 点point的x坐标在点P1和P2的x坐标中间						double slopeDiff = 0.0d;						if (point1.getLat() > point2.getLat()) {							slopeDiff = (point.getLat() - point2.getLat()) / (point.getLng() - point2.getLng())									- (point1.getLat() - point2.getLat()) / (point1.getLng() - point2.getLng());						} else {							slopeDiff = (point.getLat() - point1.getLat()) / (point.getLng() - point1.getLng())									- (point2.getLat() - point1.getLat()) / (point2.getLng() - point1.getLng());						}						if (slopeDiff > 0) {							if (slopeDiff < precision) {// 由于double精度在计算时会有损失,故匹配一定的容差。经试验,坐标经度可以达到0.0001								// 点在斜线P1P2上								return true;							} else {								// 点与斜线P1P2有交点								intersectPointCount++;							}						}					}				}			} else {				// 边P1P2水平				if (point1.getLat() == point2.getLat()) {					if (point.getLng() <= Math.max(point1.getLng(), point2.getLng())							&& point.getLng() >= Math.min(point1.getLng(), point2.getLng())) {						// 若点在水平的边P1P2上,则点在多边形内						return true;					}				}				/**				 * 判断点通过多边形顶点				 */				if (((point.getLat() == point1.getLat() && point.getLng() < point1.getLng()))						|| (point.getLat() == point2.getLat() && point.getLng() < point2.getLng())) {					if (point2.getLat() < point1.getLat()) {						intersectPointWeights += -0.5;					} else if (point2.getLat() > point1.getLat()) {						intersectPointWeights += 0.5;					}				}			}			point1 = point2;		}		if ((intersectPointCount + Math.abs(intersectPointWeights)) % 2 == 0) {// 偶数在多边形外			return false;		} else { // 奇数在多边形内			return true;		}	}	/**	 * 判断点是否在矩形内在矩形边界上,也算在矩形内(根据这些点,构造一个外包矩形)	 * 	 * @param point	 *            点对象	 * @param boundaryPoints	 *            矩形边界点	 * @return	 */	public static boolean isPointInRectangle(Point point, Point[] boundaryPoints) {		Point southWestPoint = getSouthWestPoint(boundaryPoints); // 西南角点		Point northEastPoint = getNorthEastPoint(boundaryPoints); // 东北角点		return (point.getLng() >= southWestPoint.getLng() && point.getLng() <= northEastPoint.getLng()				&& point.getLat() >= southWestPoint.getLat() && point.getLat() <= northEastPoint.getLat());	}	/**	 * 根据这组坐标,画一个矩形,然后得到这个矩形西南角的顶点坐标	 * 	 * @param vertexs	 * @return	 */	private static Point getSouthWestPoint(Point[] vertexs) {		double minLng = vertexs[0].getLng(), minLat = vertexs[0].getLat();		for (Point bmapPoint : vertexs) {			double lng = bmapPoint.getLng();			double lat = bmapPoint.getLat();			if (lng < minLng) {				minLng = lng;			}			if (lat < minLat) {				minLat = lat;			}		}		return new Point(minLng, minLat);	}	/**	 * 根据这组坐标,画一个矩形,然后得到这个矩形东北角的顶点坐标	 * 	 * @param vertexs	 * @return	 */	private static Point getNorthEastPoint(Point[] vertexs) {		double maxLng = 0.0d, maxLat = 0.0d;		for (Point bmapPoint : vertexs) {			double lng = bmapPoint.getLng();			double lat = bmapPoint.getLat();			if (lng > maxLng) {				maxLng = lng;			}			if (lat > maxLat) {				maxLat = lat;			}		}		return new Point(maxLng, maxLat);	}}

这是基本代码,大楷思路也都在这里面了。不太清楚的可以Q我851668663

转载于:https://my.oschina.net/Thinkeryjgfn/blog/875245

你可能感兴趣的文章
The Pilots Brothers' refrigerator(简单枚举)
查看>>
JavaScript 操作符
查看>>
《构建之法》读后感
查看>>
go语言接受者的选取
查看>>
php分页
查看>>
我们失去了,我们又没有失去什么
查看>>
ORACLE Index Lookup索引访问路径总结
查看>>
SpringMVC学习指南【笔记6】JSTL标签、函数
查看>>
GPS轨迹数据集免费下载资源整理
查看>>
考研?还是直接找工作?
查看>>
ue4 蓝图物体怎么不跟着蓝图动_UE4部分蓝图
查看>>
联通4g满格但是网速慢_为什么手机4G信号明明是满格,网络却很慢,背后的真实原因?...
查看>>
bable怎么使用 eclipse_Java Web轻松学46 - Maven集成到Eclipse中
查看>>
机器人 知乎碧桂园_碧桂园机器人首降淮阳,助力城市文化旅游
查看>>
ae2020不支持的视频驱动程序_音视频PaaS平台基于Windows的抓屏技术
查看>>
图纸打印什么时候用蓝图_工程图纸为什么是蓝图?
查看>>
网页中竖的目录怎么改成横的_骨架隔墙怎么做?
查看>>
查看历史操作记录_git操作方法
查看>>
5怎么选国外节点_房子装修,床垫怎么选?这5家床垫值得买
查看>>
变成一列_Excel一列数据转多行多列,这4条函数公式可以学起来
查看>>