java实现经纬度坐标是否在范围内的算法
需求是:一个点(经纬度)是否在一个多边形内部,多边形有多个点构成,每个点是一个实际的经纬度坐标,有多个点构成一个多边形,
算法数学上实现思路: 判断一个点是在一个多边形内部的集中情况
第一:目标点在多边形的某一个顶点上,我们认为目标点在多边形内部
第二:目标点在多边形的任意一天边上,我们认为目标点在多边形内部
第三:这种情况就比较复杂了,不在某天边上,也不和任何一个顶点重合.这时候就需要我们自己去算了,解决方案是将目标点的Y坐标与多边形的每一个点进行比较,我们会得到一个目标点所在的行与多边形边的交点的列表。如果目标点的两边点的个数都是奇数个则该目标点在多边形内,否则在多边形外。
这种算法适合凸多边形也适合凹多边形,所以是一种通用的算法,同时也解决了多边形的点的顺序不同导致的形状不同,比如一个五边形,可以是凸五边形,也可以是一个凹五边形,这个根据点的位置和顺序决定的。
有了数学上的实现思路,辣么我们就可以用java 或者去他语言去实现一个点(经纬度)是否在一个多边形内部了(多个点构成)。
我们先写一个 对点和线的一些公用方法,
package cn.liuzw.point;
import java.util.ArrayList;/*** <span style="font-family: Arial; font-size: 14px; line-height: 26px;">点和线的一些公用方法</span><br/>* * @author liuZhiwei* 2016年8月6日 下午3:48:38*/
public class Point {/*** 是否有 横断<br/>* 参数为四个点的坐标* @param px1* @param py1* @param px2* @param py2* @param px3* @param py3* @param px4* @param py4* @return */public boolean isIntersect ( double px1 , double py1 , double px2 , double py2 , double px3 , double py3 , double px4 , double py4 ) { boolean flag = false; double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3); if ( d != 0 ) { double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d; double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d; if ( (r >= 0) && (r <= 1) && (s >= 0) && (s <= 1) ) { flag = true; } } return flag; } /*** 目标点是否在目标边上边上<br/>* * @param px0 目标点的经度坐标* @param py0 目标点的纬度坐标* @param px1 目标线的起点(终点)经度坐标* @param py1 目标线的起点(终点)纬度坐标* @param px2 目标线的终点(起点)经度坐标* @param py2 目标线的终点(起点)纬度坐标* @return*/public boolean isPointOnLine ( double px0 , double py0 , double px1 , double py1 , double px2 , double py2 ) { boolean flag = false; double ESP = 1e-9;//无限小的正数if ( (Math.abs(Multiply(px0, py0, px1, py1, px2, py2)) < ESP) && ((px0 - px1) * (px0 - px2) <= 0) && ((py0 - py1) * (py0 - py2) <= 0) ) { flag = true; } return flag; } public double Multiply ( double px0 , double py0 , double px1 , double py1 , double px2 , double py2 ) { return ((px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0)); }/*** 判断目标点是否在多边形内(由多个点组成)<br/>* * @param px 目标点的经度坐标* @param py 目标点的纬度坐标* @param polygonXA 多边形的经度坐标集合* @param polygonYA 多边形的纬度坐标集合* @return*/public boolean isPointInPolygon ( double px , double py , ArrayList<Double> polygonXA , ArrayList<Double> polygonYA ) { boolean isInside = false; double ESP = 1e-9; int count = 0; double linePoint1x; double linePoint1y; double linePoint2x = 180; double linePoint2y; linePoint1x = px; linePoint1y = py; linePoint2y = py; for (int i = 0; i < polygonXA.size() - 1; i++) { double cx1 = polygonXA.get(i); double cy1 = polygonYA.get(i); double cx2 = polygonXA.get(i + 1); double cy2 = polygonYA.get(i + 1); //如果目标点在任何一条线上if ( isPointOnLine(px, py, cx1, cy1, cx2, cy2) ) { return true; }//如果线段的长度无限小(趋于零)那么这两点实际是重合的,不足以构成一条线段if ( Math.abs(cy2 - cy1) < ESP ) { continue; } //第一个点是否在以目标点为基础衍生的平行纬度线if ( isPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x, linePoint2y) ) { //第二个点在第一个的下方,靠近赤道纬度为零(最小纬度)if ( cy1 > cy2 ) count++; }//第二个点是否在以目标点为基础衍生的平行纬度线else if ( isPointOnLine(cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y) ) { //第二个点在第一个的上方,靠近极点(南极或北极)纬度为90(最大纬度)if ( cy2 > cy1 ) count++; }//由两点组成的线段是否和以目标点为基础衍生的平行纬度线相交else if ( isIntersect(cx1, cy1, cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y) ) { count++; } } if ( count % 2 == 1 ) { isInside = true; } return isInside; }
}
里面有三个方法,两个原子方法,一个主方法
第一个判断是否与横断 目标端和y轴 也就是东经0也叫西经180的一条经度线构成的一天平行于纬度(赤道)的一天线段和多边形的任意一天线段是否有横断。参数是四个点的坐标分别是目标点和目标点组成线段的一个点(在西经180度上) 多边形的任意连续的两个点(可以构成一条线段)
第二个是目标点是否在目标边上边上,
点三个是主方法,外接只需要调用这个方法,这个而方法的逻辑就是,第一步先判断目标点的坐标是否和多边形的任意一个顶点的坐标重合,如果重合直接放回true,说明目标点在该多边形内,如果都不重合,在判断是否在多边形的任意一条边上,如果在 返回true,如果以上两种情况都不成立在理由低三种算法,计算目标点平行于赤道的线和多边形的焦点,在判断焦点的个数。如果l两边的焦点是基数个返回true。
我可以写main方法去测试该程序。
package cn.liuzw.bean;import java.util.Random;/*** 点实体类<br/>* * @author liuZhiwei* 2016年8月15日 下午7:16:14*/
public class Area {public static Random rd=new Random();public Double createDouble(){return (double) rd.nextInt(1000);}public Area() {this.px = createDouble();this.py = createDouble();}public Area(Double px, Double py) {super();this.px = px;this.py = py;}public Area(Double px, Double py, String name) {super();this.px = px;this.py = py;this.name = name;}private Double px;private Double py;private String name;public Double getPx() {return px;}public void setPx(Double px) {this.px = px;}public Double getPy() {return py;}public void setPy(Double py) {this.py = py;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Area [px=" + px + ", py=" + py + ", name=" + name + "]";}public String getPoint() {StringBuffer buffer=new StringBuffer();buffer.append("(").append(px).append(",").append(py).append(")");return buffer.toString();}
}
main方法测试类
package cn.liuzw.test;import java.util.ArrayList;
import java.util.List;import cn.liuzw.bean.Area;
import cn.liuzw.point.Point;public class GraphicalMain {public static void main(String[] args) {//(113.944421,22.528841) (113.94629,22.529208)//isPointInPolygon(area.createDouble(),area.createDouble()); (114.082402,22.550271) 114.075323,22.543528)isPointInPolygon(113.947871,22.52804);}private static Boolean isPointInPolygon( double px , double py ){Area a1=new Area(113.941853,22.530777);Area a3=new Area(113.94788,22.527597);Area a2=new Area(113.940487,22.527789);Area a4=new Area(113.947925,22.530618);Area a5=new Area(113.941772,22.530727);List<Area> areas=new ArrayList<Area>();areas.add(a1);areas.add(a2);areas.add(a3);areas.add(a4);ArrayList<Double> polygonXA = new ArrayList<Double>(); ArrayList<Double> polygonYA = new ArrayList<Double>(); for(int i=0;i<areas.size();i++){Area area=areas.get(i);polygonXA.add(area.getPx());polygonYA.add(area.getPy());}Point point=new Point();Boolean flag= point.isPointInPolygon(px, py, polygonXA, polygonYA);StringBuffer buffer=new StringBuffer();buffer.append("目标点").append("(").append(px).append(",").append(py).append(")").append("\n");buffer.append(flag?"在":"不在").append("\t").append("由\n");for(int i=0;i<areas.size();i++){Area area=areas.get(i);buffer.append(area.getPoint()).append("; ");//buffer.append("第"+i+"个点"+area.getPoint()).append("\n");System.out.println("第"+(i+1)+"个点"+area.getPoint());}StringBuffer sb=new StringBuffer();sb.append("目标点:").append("(").append(px).append(",").append(py).append(")").append("\n");System.out.println(sb);buffer.append(areas.size()).append("个点组成的").append(areas.size()).append("边行内");System.out.println(buffer.toString());return flag;}
}
算法数学上实现思路: 判断一个点是在一个多边形内部的集中情况
第一:目标点在多边形的某一个顶点上,我们认为目标点在多边形内部
第二:目标点在多边形的任意一天边上,我们认为目标点在多边形内部
第三:这种情况就比较复杂了,不在某天边上,也不和任何一个顶点重合.这时候就需要我们自己去算了,解决方案是将目标点的Y坐标与多边形的每一个点进行比较,我们会得到一个目标点所在的行与多边形边的交点的列表。如果目标点的两边点的个数都是奇数个则该目标点在多边形内,否则在多边形外。
java实现经纬度坐标是否在范围内的算法相关推荐
- java 根据经纬度坐标查询出来附近店铺
@Override public CommonResult selectshopnear(double dis, double longitude,double latitude) {//先计算查询点 ...
- java gps经纬度坐标转高德坐标_高德经纬度转普通GPS经纬度
# 官方API: http://lbs.amap.com/api/webservice/guide/api/convert # 坐标体系说明:http://lbs.amap.com/faq/top/c ...
- java根据经纬度坐标计算两点的距离算法
2019独角兽企业重金招聘Python工程师标准>>> /** * Created by yuliang on 2015/3/20. */ public class Location ...
- java gps经纬度坐标转高德坐标_RN中Geolocation的经纬度坐标转换为高德地图坐标
Geolocation经纬度转换为高德地图经纬度方法 直接调用如下GPS. gcj_encrypt(lat, lon)就行了 var GPS = { PI : 3.14159265358979324, ...
- java根据经纬度坐标计算两点的距离算法,与百度地图测距工具相符
public IdDTO getDistance(List<double[]> latLngs) { double distance = 0.0; if (latLngs.size() & ...
- Java中如何通过经纬度坐标获取两个点之间的直线距离
前言 现在很多App都需要附带着附近人列表功能,所以我在这里实现2个点之间的距离计算 经纬度的获取需要第三方来支持,高德地图.百度地图.... 附近人功能具体的实现逻辑: 1.获取每个人的经纬度坐标, ...
- 根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用
文章目录 步骤一.下载省市区边界数据 步骤二.解析CSV文件导入数据库 步骤三.在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机 ...
- Java 百度地图 根据经纬度(坐标) 获取乡镇
申请百度开放平台KEY(ak) 没申请,随便找了一个 参数说明: extensions_town:行政区划返回乡镇级数据(town),仅国内召回乡镇数据 coordtype:坐标的类型 bd09ll( ...
- Java 根据高德地图获取经纬度坐标
1: 申请高德服务key /*** @param addressName* @param cityName* @Description 根据高德地图, 通过地址获取经纬度坐标* @Throws* @R ...
最新文章
- 尽快卸载这两款恶意浏览器插件!已有近 50 万用户安装
- php程序里的configini_php中配置文件操作 如config.php文件的读取修改等操作
- mysql mof_mof提权
- 程序直接控制I/O方式
- JavaScript中创建对象的方法
- 微型计算机控制技术黄勤期末,微型计算机控制技术作者黄勤第4章__工控机的抗干扰课案.ppt...
- python编写姓名年龄_python小工具 - alert弹框输出姓名年龄、求和
- 统计单词数(信息学奥赛一本通-T1400)
- 浅谈Hybrid技术的设计与实现【转】
- 替罪羊树—BZOJ3224: Tyvj 1728 普通平衡树
- 参考文献如何居中_一线教师如何写教育教学论文?
- Oracle PL/SQL游标的学习
- 1. 测度论-概率空间的基本概念
- 数据安全“考题”怎么破解?11月2日厦门站算力私享会开启
- RAW图片转换JPEG图片工具(免费)
- C++多线程传参详解
- On teaching mathematics--Arnold
- 移动硬盘制作随身系统
- 我们真的需要会议耳机吗?
- 计算机专业朋友圈文案,发朋友圈会收获一大波好评的句子,逼格超高(专业文案的收藏)...
热门文章
- 远离敏捷状态的 Scrum 框架
- Edge浏览器系列:win10如何关闭Alt+tab只切换Edge浏览器的网页
- 犀牛软件(rhinoceros)5.0中文破解版(转)
- drozer之玩转sieve
- 德勤《全球AI发展白皮书》出炉!八大新趋势,三个关键技术一文扫尽【附下载】...
- 马蜂窝支付中心架构演进
- 小伙伴们,一个身份证可注册五个微信公众号了!
- CVE-2020-1938漏洞复现(文末附EXP代码)
- php扫描目录入库,yii框架,扫描目录下文件入数据库
- linux计算生日时间,生日计算