文档章节

地图,判断点与多边形位置关系

北极心
 北极心
发布于 2017/04/08 12:19
字数 1104
阅读 61
收藏 1

废话不多说,直接看代码

资料来源: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

© 著作权归作者所有

共有 人打赏支持
北极心
粉丝 35
博文 39
码字总数 16464
作品 0
深圳
后端工程师
私信 提问
c#之多边形裁剪线(未考虑重合情况)------初级

在学习过程中,想找个东西写一下,就写了一个多边形裁剪线的C#的小程序并在这里和大家分享一下。 一、想法思路 首先设计页面,页面布局写的很简单,建议用自己做的。 由于当时写的时候没有指...

mmmmmmFC
2017/11/06
0
0
判断点是否在多边形内部(Ray-casting Algorithm)

判断一个点是否在多边形内部的典型方法: (1)面积和判别法:判断目标点与多边形的每条边组成的三角形面积和是否等于该多边形,相等则在多边形内部。 (2)夹角和判别法:判断目标点与所有边...

vocaloid01
04/19
0
0
原生Js从0开始实现一个链家网地图画圈找房功能

概述 最近做项目的时候遇到的一个需求:要实现一个链家网地图找房中的画圈找房功能。链家网是采用百度地图实现房源展示,先来看看链家网的画圈找房功能,有木有很炫酷~~,可以到链家上体验一下...

超级索尼子
05/26
0
0
判断点是否在多边形内

射线法(奇偶法) 只适用于简单多边形(没有自相交点)。从P点开始的射线穿过多边形边界次数,多边形的边界将多边形分为内部和外部。如果是偶数在多边形外部,否则奇数在多边形内部。如下图所...

乙知
2016/11/07
296
0
WebGIS中一种根据网格索引判断点面关系的方法

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/。 1.背景 判断点面关系的算法有很多,在我之前的博文中有一篇专门对其进行了描述:判断点...

李晓晖
2016/01/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

传播正能量——《海南英才》阅读的读后感2200字

传播正能量——《海南英才》阅读的读后感2200字: 新华社记者12月8日从公安部获悉,针对自媒体“网络水军”敲诈勒索等违法犯罪活动突出问题,今年以来,公安部组织各地公安机关依法深入开展侦...

原创小博客
16分钟前
1
0
Confluence 6 对一个空间进行归档后产生的影响

空间 如果一个空间被归档: 将不会在查找结果中显示,除非你选择 在归档空间中查找(Search archived spaces)。如果没有归档空间的话,这个功能是隐藏的。 页面和内容将不会在 Confluence 的...

honeymose
18分钟前
2
0
java框架学习日志-2

上篇文章(java框架学习日志-1)虽然跟着写了例子,也理解为什么这么写,但是有个疑问,为什么叫控制反转?控制的是什么?反转又是什么? 控制其实就是控制对象的创建。 反转与正转对应,正转...

白话
今天
4
0
Integer使用双等号比较会发生什么

话不多说,根据以下程序运行,打印的结果为什么不同? Integer a = 100;Integer b = 100;System.out.println(a == b);//print : trueInteger a = 200;Integer b = 200;System.out.pr...

兜兜毛毛
昨天
10
0
CockroachDB

百度云上的CockroachDB 云数据库 帮助文档 > 产品文档 > CockroachDB 云数据库 > 产品描述 开源NewSQL – CockroachDB在百度内部的应用与实践 嘉宾演讲视频及PPT回顾:http://suo.im/5bnORh ...

miaojiangmin
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部