经纬度坐标为中心点生成米距离长度半径的圆形面,含java js源码+在线绘制,代码简单零依赖

news2024/10/6 20:30:49

文章目录

  • java版源码
  • js版源码
  • 在线绘制预览效果
  • 关于计算的精确度

前些时间在更新我的坐标边界查询工具的时候,需要用到经纬度坐标点的距离计算,和以坐标点为中心生成一个指定距离为半径的圆,搜了一下没有找到现成简单又合适的代码,于是把自己压箱底的代码翻出来了,简化完善了一下,嘿,代码量也不大,还挺好用。

本方法是通过计算得到圆上的多个坐标点,来得到的一个近似的圆形面,只要坐标点够多,这个圆就能足够圆;有了这些坐标点就很容易表示成不同的格式,比如:GeoJSON文本WKT文本Geometry实例

源自 坐标边界查询工具 开源库:https://github.com/xiangyuecn/AreaCity-Query-Geometry (github可以换成gitee),高性能的坐标数据、边界数据查询工具,Java开源程序、带http查询接口,内存占用低(1秒可查1万个以上坐标对应的城市信息)。

java版源码

public static void main(String[] args) {
	//计算天坛到天安门的距离
	System.out.println(Distance(116.410622, 39.881773, 116.397476, 39.908647));
	//生成天坛1公里范围的圆形面
	System.out.println(CreateSimpleCircleWKT(116.410622, 39.881773, 1000, 24));
}

/** 计算两个坐标的距离,单位米 **/
static public double Distance(double lng1, double lat1, double lng2, double lat2) {
	//采用Haversine formula算法,高德地图的js计算代码,比较简洁 https://www.cnblogs.com/ggz19/p/7551088.html
	double d=Math.PI/180;
	double f=lat1*d, h=lat2*d;
	double i=lng2*d - lng1*d;
	double e=(1 - Math.cos(h - f) + (1 - Math.cos(i)) * Math.cos(f) * Math.cos(h)) / 2;
	return 2 * 6378137 * Math.asin(Math.sqrt(e));
}

/** 以坐标点为中心,简单粗略的创建一个指定半径的圆,半径单位米,pointCount为构建圆的坐标点数(比如24个点,点越多越圆,最少3个点),返回构成圆的坐标点数组 **/
static public double[][] CreateSimpleCircle(double lng, double lat, double radius, int pointCount) {
	//球面坐标不会算,转换成三角坐标简单点,经度代表值大约:0.01≈1km 0.1≈10km 1≈100km 10≈1000km
	double km=radius/1000;
	double a=km<5?0.01 :km<50?0.1 :km<500?1 :10;
	double b=Distance(lng, lat, lng+a, lat);
	double c=Distance(lng, lat, lng, lat+a);
	double rb=radius/b*a;
	double rc=radius/c*a;
	double[][] arr=new double[pointCount+1][];
	double n=0,step=360.0/pointCount,N=360-step/2; //注意浮点数±0.000000001的差异
	for(int i=0;n<N;i++,n+=step){
		double x=lng+rb*Math.cos(n*Math.PI/180);
		double y=lat+rc*Math.sin(n*Math.PI/180);
		arr[i]=new double[] { x, y };
	}
	arr[pointCount]=new double[] { arr[0][0], arr[0][1] }; //闭环
	return arr;
}

/**
以坐标点为中心,简单粗略的创建一个指定半径的圆,半径单位米,pointCount为构建圆的坐标点数(比如24个点,点越多越圆,最少3个点),返回圆的WKT(Well Known Text)文本
,WKT图形绘制预览工具:https://xiangyuecn.gitee.io/areacity-jsspider-statsgov/assets/geo-echarts.html
**/
static public String CreateSimpleCircleWKT(double lng, double lat, double radius, int pointCount) {
	double[][] points=CreateSimpleCircle(lng, lat, radius, pointCount);
	DecimalFormat df=new DecimalFormat("0.######");
	StringBuilder wkt=new StringBuilder("POLYGON((");
	for(int i=0;i<points.length;i++) {
		if(i>0)wkt.append(",");
		wkt.append(df.format(points[i][0])+" "+df.format(points[i][1]));
	}
	wkt.append("))");
	return wkt.toString();
}

js版源码

//测试:计算天坛到天安门的距离
console.log(Distance(116.410622, 39.881773, 116.397476, 39.908647));
//测试:生成天坛1公里范围的圆形面
console.log(CreateSimpleCircleWKT(116.410622, 39.881773, 1000, 24));

/** 计算两个坐标的距离,单位米 **/
function Distance(lng1, lat1, lng2, lat2) {
    //采用Haversine formula算法,高德地图的js计算代码,比较简洁 https://www.cnblogs.com/ggz19/p/7551088.html
    var d=Math.PI/180;
    var f=lat1*d, h=lat2*d;
    var i=lng2*d - lng1*d;
    var e=(1 - Math.cos(h - f) + (1 - Math.cos(i)) * Math.cos(f) * Math.cos(h)) / 2;
    return 2 * 6378137 * Math.asin(Math.sqrt(e));
}

/** 以坐标点为中心,简单粗略的创建一个指定半径的圆,半径单位米,pointCount为构建圆的坐标点数(比如24个点,点越多越圆,最少3个点),返回构成圆的坐标点数组 **/
function CreateSimpleCircle(lng, lat, radius, pointCount){
	//球面坐标不会算,转换成三角坐标简单点,经度代表值大约:0.01≈1km 0.1≈10km 1≈100km 10≈1000km
	var km=radius/1000;
	var a=km<5?0.01 :km<50?0.1 :km<500?1 :10;
	var b=Distance(lng, lat, lng+a, lat);
	var c=Distance(lng, lat, lng, lat+a);
	var rb=radius/b*a;
	var rc=radius/c*a;
	var arr=[];
	var n=0,step=360.0/pointCount,N=360-step/2; //注意浮点数±0.000000001的差异
	for(var i=0;n<N;i++,n+=step){
		var x=lng+rb*Math.cos(n*Math.PI/180);
		var y=lat+rc*Math.sin(n*Math.PI/180);
		arr[i]=[x, y];
	}
	arr.push([arr[0][0], arr[0][1]]); //闭环
	return arr;
};

/**
以坐标点为中心,简单粗略的创建一个指定半径的圆,半径单位米,pointCount为构建圆的坐标点数(比如24个点,点越多越圆,最少3个点),返回圆的WKT(Well Known Text)文本
,WKT图形绘制预览工具:https://xiangyuecn.gitee.io/areacity-jsspider-statsgov/assets/geo-echarts.html
**/
function CreateSimpleCircleWKT(lng, lat, radius, pointCount){
	var points=CreateSimpleCircle(lng, lat, radius, pointCount);
    var wkt=["POLYGON(("];
    for(var i=0;i<points.length;i++) {
		wkt.push((i>0?",":"")+(+points[i][0].toFixed(6))+" "+(+points[i][1].toFixed(6)));
    }
    wkt.push("))");
    return wkt.join("");
};

在线绘制预览效果

生成了圆形面的WKT文本后,可以粘贴进在线预览页面绘制显示:https://xiangyuecn.gitee.io/areacity-jsspider-statsgov/assets/geo-echarts.html ,方便代码调试,地图上有测距功能,可以测量圆面的准确度;页面上的画圆功能,采用的就是js版的代码。

24个坐标点的圆形面显示效果

关于计算的精确度

两个经纬度坐标的距离计算,采用的Haversine formula算法,下面的计算代码中高德地图的api同样是Haversine formula算法,和百度地图的计算结果误差在0.2%以内:

bMap=window.BMapGL&&BMapGL.Map.prototype||{getDistance:function(a,b){return BMap.Map.prototype.getDistance(new BMap.Point(a.lng,a.lat),new BMap.Point(b.lng,b.lat)) }};

//地图api计算【纬度】之间的距离,每一度之间的距离是相同的
bMap.getDistance({lng:111,lat:15},{lng:111,lat:16})        //百度111194.86米
new AMap.LngLat(111,15).distance(new AMap.LngLat(111,16)) //高德111319.49米

bMap.getDistance({lng:121,lat:55},{lng:121,lat:56})        //百度111194.78米
new AMap.LngLat(121,55).distance(new AMap.LngLat(121,56)) //高德111319.49米

//地图api计算【经度】之间的距离,会随着纬度的不同而不同
bMap.getDistance({lng:111,lat:15},{lng:112,lat:15})        //百度107405.91米
new AMap.LngLat(111,15).distance(new AMap.LngLat(112,15)) //高德107526.28米

bMap.getDistance({lng:111,lat:55},{lng:112,lat:55})        //百度63778.21米
new AMap.LngLat(111,55).distance(new AMap.LngLat(112,55)) //高德63849.69米
        //经度在相同纬度下每一度之间的距离是相同的
        bMap.getDistance({lng:121,lat:55},{lng:122,lat:55})        //百度63778.21米
        new AMap.LngLat(121,55).distance(new AMap.LngLat(122,55)) //高德63849.69米

对于构成圆的坐标点的计算,使用的以前压箱底的代码,计算比较简单,经度和纬度分别计算出一度的距离长度,在等比例的换算出半径对应的度数大小,比如算出来的经度1°是100km,那么20km半径对应的度数就是1° * 20 / 100 = 0.2°

  • 纬度每一度之间的距离都是固定的长度,等比例换算后的结果是没有误差的。
  • 经度每一度之间的距离长度会随着纬度变化,低纬度长高纬度短,圆面的上下纬度不同,半径小的时候误差小,半径越大误差越大。

所以按等比例换算在纬度上没有问题,但经度上会产生一定的误差,但只要圆的半径不超过10km,误差就能控制在0.5%以内,可通过下面代码直接计算观察到:

//经度之间的距离,不同纬度下的误差计算
d1=new AMap.LngLat(111,15.0).distance(new AMap.LngLat(111.2,15.0));
d2=new AMap.LngLat(111,15.2).distance(new AMap.LngLat(111.2,15.2));
console.log(d2, (d1-d2)/d2*100+"%") //低纬度下经度0.2°距离≈20km,纬度0.2°导致0.09%误差
d1=new AMap.LngLat(111,55.0).distance(new AMap.LngLat(111.2,55.0));
d2=new AMap.LngLat(111,55.2).distance(new AMap.LngLat(111.2,55.2));
console.log(d2, (d1-d2)/d2*100+"%") //高纬度下经度0.2°距离≈10km,纬度0.2°导致0.50%误差

d1=new AMap.LngLat(111,15).distance(new AMap.LngLat(112,15));
d2=new AMap.LngLat(111,16).distance(new AMap.LngLat(112,16));
console.log(d2, (d1-d2)/d2*100+"%") //低纬度下经度1°距离≈100km,纬度1°导致0.49%误差
d1=new AMap.LngLat(111,55).distance(new AMap.LngLat(112,55));
d2=new AMap.LngLat(111,56).distance(new AMap.LngLat(112,56));
console.log(d2, (d1-d2)/d2*100+"%") //高纬度下经度1°距离≈60km,纬度1°导致2.57%误差

由于是通过圆上的坐标点连起来得到的一个圆,本质上是一个近似圆的多边形,只要坐标点足够多就越接近圆,当坐标点少的情况下肉眼可见的不是那么圆(最少3个坐标点,三角形),误差也会很大。但考虑到点数越多,会导致使用上很多地方的计算量会变的很大,所以构成圆的坐标点数也是一个综合考虑的数量,我选择24个坐标点构成一个圆,每个象限6个点,点之间角度为15°。

【完】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/622372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于OpenCV 和 Dlib 进行头部姿态估计

写在前面 工作中遇到&#xff0c;简单整理博文内容涉及基于 OpenCV 和 Dlib头部姿态评估的简单Demo理解不足小伙伴帮忙指正 庐山烟雨浙江潮&#xff0c;未到千般恨不消。到得还来别无事&#xff0c;庐山烟雨浙江潮。 ----《庐山烟雨浙江潮》苏轼 https://github.com/LIRUILONGS…

2023智源大会议程公开 | 大模型新基建与智力运营论坛

6月9日&#xff0c;2023北京智源大会&#xff0c;将邀请这一领域的探索者、实践者、以及关心智能科学的每个人&#xff0c;共同拉开未来舞台的帷幕&#xff0c;你准备好了吗&#xff1f;与会知名嘉宾包括&#xff0c;图灵奖得主Yann LeCun、OpenAI创始人Sam Altman、图灵奖得主…

【模型评估】混淆矩阵(confusion_matrix)之 TP、FP、TN、FN;敏感度、特异度、准确率、精确率

你这蠢货&#xff0c;是不是又把酸葡萄和葡萄酸弄“混淆”啦&#xff01;&#xff01;&#xff01;这里的混淆&#xff0c;我们细品&#xff0c;帮助我们理解名词“混淆矩阵” 上面日常情况中的混淆就是&#xff1a;是否把某两件东西或者多件东西给弄混了&#xff0c;迷糊了。把…

数据隐私保护的最佳实践:全面了解数据脱敏方案

1、数据脱敏 数据脱敏是一种保护敏感信息的安全措施&#xff0c;通常会将真实数据替换成模拟数据或者经过处理后的数据。下面是常见的数据脱敏实现方案&#xff1a; 字符串替换&#xff1a;将需要脱敏的字符串中指定位置的字符替换为“****”或其他符号。例如&#xff0c;将银…

MySQL数据库误删恢复

前言 经常听说删库跑路这真的不只是一句玩笑话,若不小心删除了数据库,事情很严重。你一个不小心可能会给公司删没。建议研发不要直连生成环境,一般的话都会分配账号权限,生产环境的账号尽量是只读,以防你一个不经意给库或表删除。一定要备份,这很重要,这是一个血的教训。…

iTOP3568开发板-Buildroot 系统设置待机和锁屏

Weston 的超时待机时长可以在启动参数中配置,也可以在 weston.ini 的 core 段配置。 方法一&#xff1a; 修改文件系统中/etc/init.d/S50launcher 文件&#xff0c;如下图所示的红框&#xff0c;0 代表禁止待机&#xff0c;可自行设置待机时间&#xff0c;单位是秒。 方法二&a…

深浅拷贝各种实现方式性能

拷贝方式 拷贝方式类型原理备注Object.clone()默认 浅拷贝&#xff0c;可以自定义实现深拷贝对象内存复制constructor可以实现深拷贝自定义实现BeanUtil.copyProperties()浅拷贝利用 getter/setter 实现属性拷贝反射&#xff0c;spring utilCollectionUtils.clone()深拷贝本质…

强化学习驱动的低延迟视频传输

随着视频会议、视频直播的流行以及未来AR/VR业务的发展&#xff0c;低延迟视频传输服务被广泛使用&#xff0c;但视频质量&#xff08;QoE&#xff09;还不能满足用户要求。那么近年来新兴的AI神经网络是否能为视频传输带来智能化的优化&#xff1f;今天LiveVideoStack大会北京…

macos m1 pip install lightgbm error

MacOS M1电脑&#xff0c;执行 pip install lightgbm 错误如下&#xff1a; 尝试如下操作&#xff1a; 参考链接如下&#xff1a; https://github.com/Microsoft/LightGBM/issues/1324 brew install cmake brew install gcc git clone --recursive https://github.com/Micro…

Unity之OpenXR+XR Interaction Toolkit接入HTC Vive解决手柄无法使用的问题

前言 随着Unity版本的不断进化,VR的接口逐渐统一,现在大部分的VR项目都开始使用OpenXR开发了。基于OpenXR,我们可以快速适配HTC,Pico,Oculus,等等设备。 今天我们要说的问题就是,当我们按照官方的标准流程配置完OpenXR后(参考:Unity之OpenXR+XR Interaction Toolkit…

西门子S7-200 CPU输入/输出接线说明

总结来看&#xff0c;S7-200系列PLC提供4个不同的基本型号的8种CPU&#xff0c;其接线方式也可大致分为6种&#xff1a; 1.CPU SR20接线 2.CPU SR40接线 3.CPU CR40接线 4.CPU ST40接线 5. CPU SR60接线 6. CPU ST60接线 除了CPU外&#xff0c;我们还需要了解200smart PLC的数…

排序算法大总结(插入、希尔、选择、堆、冒泡、快速、归并、计数)

1. 排序概要2. 插入排序直接插入排序希尔排序&#xff08;缩小增量排序&#xff09; 3.选择排序直接选择排序堆排序 4. 交换排序冒泡排序快速排序霍尔版本&#xff08;hoare&#xff09;挖坑法双指针版本快排优化快速排序非递归 5. 归并排序归并递归版本归并非递归版本 6.计数排…

物联网开发项目中具备哪些特点?

物联网开发是一项由设备、传感器、系统和应用程序组成的复杂技术。许多公司已经制定了计划&#xff0c;准备将物联网技术整合到他们的系统中&#xff0c;以帮助提高效率和生产力。在许多方面&#xff0c;物联网都是一项技术投资&#xff0c;但与其他投资相比&#xff0c;它可以…

RFID如何提升工业物流管理效率?

RFID技术目前已经在工业物流行业中广泛应用&#xff0c;企业只要将附带产品信息的RFID标签贴在货物上&#xff0c;利用工业读写器&#xff0c;可以快速准确地读取货物信息&#xff0c;提高仓库管理效率。 RFID如何提升工业物流管理效率? 1、跟踪货物 RFID技术可帮助企业跟踪货…

声表面波滤波器圆片级互连封装技术研究

陈作桓&#xff0c;于大全&#xff0c;张名川 厦门大学&#xff0c;厦门云天半导体科技有限公司 摘要 射频前端模块是无线通信的核心&#xff0c;滤波器作为射频前端的关键器件&#xff0c;可将带外干扰和噪声滤除以保留特定频段内的信号&#xff0c;满足射频系统的通讯要求…

B站刚崩,唯品会又崩:亿级用户网站的架构硬伤与解决方案

说在前面 在40岁老架构师尼恩的数千读者的社区中&#xff0c;一直在指导大家简历和职业升级。前几天&#xff0c;指导了一个华为老伙伴的简历&#xff0c;小伙伴的优势在异地多活&#xff0c;但是在简历指导的过程中&#xff0c;尼恩发现&#xff1a; 异地多活的概念、异地多活…

Segment Anything模型用于地理空间数据

原文地址&#xff1a;https://samgeo.gishub.org/examples/satellite/ 此笔记本通过几行代码展示了如何使用 Segment Anything Model (SAM) 来使用分段卫星图像。确保为此jupyter notebook使用 GPU 运行时。 安装依赖 取消注释并运行以下单元格以安装所需的依赖项。 # %pip ins…

如何批量删除文件名称中的内容

网上有很多&#xff0c;这里自己要用就整理一下。 最好的还是知乎大佬张三丰的方式&#xff0c;放在参考内第一个链接。 首先打开命令行提示符 另一种方式按住WinR 输入powershell 弹出窗口&#xff1a; 我这里为了展示&#xff0c;在C盘新建了一个文件夹命名为1 里面新建了…

比起各式各样的AI应用,我们可能更需要AI for OS

刚刚过去的五月&#xff0c;是一个炙热的AI之夏。前有2023谷歌 I/O开发者大会“炸场”&#xff0c;开建AI全宇宙&#xff0c;后有2023微软Build大会&#xff0c;一切都与AI相关。 AI被谷歌和微软应用到各个产品&#xff0c;落地速度一路狂飙。不过&#xff0c;应用层面&#xf…

开启未来科技之门:选择IT相关专业,迈向成功的高考生小贴士!

毕业在即&#xff0c;许多即将高考的学生正面临选择未来专业的重要决策。在当今数字化时代&#xff0c;IT行业成为一个备受瞩目的领域&#xff0c;为学生们提供了广阔的就业前景和丰富的发展机会。本文将为高考生提供一些关于选择IT相关专业的小贴士&#xff0c;以帮助他们做出…