坐标经纬度的基本运算(2个坐标经纬度的距离、中心点坐标经纬度范围内的坐标计算)

现在的应用大都居于LBS服务,用户地理位置的获取(经纬度坐标、所属行政区域),提供服务场所的地理位置也有行政区域信息和坐标信息。

用户与服务场所的联系,就近服务原则的设计,服务场所相对于用户的排序。

一个简单的案例的设计:

根据用户定位获取服务场所,按距离排序。

用户端提供信息:居于经纬度的坐标信息(例如:纬度23.03057,经度113.75213),区域信息(省市区)

服务场所信息:经纬度,区域信息

相关概念:

目前国内主要有以下三种坐标系:

WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。

GCJ02:又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。

BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。

非中国地区地图,服务坐标统一使用WGS84坐标。

*这里我们先不考虑个坐标系的差异,按统一的公式计算。

地理知识和相关三角函数计算:

地球是一个近似于圆形的球体,半径6378137米。在地球经线上,1纬度为111km左右,在地球纬线上,1经度为111cosα(α表示该纬线的纬度.在不同纬线上,经度每差1度的实际距离是不相等的))。

计算2个经纬度的距离:

坐标点:A点:23.03057,113.75213  B点:23.03102,113.75212

计算2点的距离(米)

1、sql

SELECT  CAST(6378137.0 * ACOS(SIN(23.03057 / 180 * PI())* SIN(CAST(23.03102000 AS DECIMAL(18, 8)) / 180* PI()) + COS(23.03057 / 180 * PI())* COS(CAST(23.03102000 AS DECIMAL(18, 8)) / 180* PI()) * COS(( 113.75213- CAST(113.75212000 AS DECIMAL(18,8)) ) / 180* PI())) AS INT) AS Distance

2、C# 

public static double EARTH_RADIUS = 6378137d;/// <summary>/// 计算两点位置的距离,返回两点的距离,单位:公里或千米/// 该公式为GOOGLE提供,误差小于0.2米/// var dis = Utils.PointUtil.GetDistance(23.03057, 113.75213, 23.03102000, 113.75212000);/// </summary>/// <param name="lat1">第一点纬度</param>/// <param name="lng1">第一点经度</param>/// <param name="lat2">第二点纬度</param>/// <param name="lng2">第二点经度</param>/// <returns>返回两点的距离,单位:公里或千米</returns>public static double GetDistance(double lat1, double lng1, double lat2, double lng2){//地球半径,单位米double radLat1 = Rad(lat1);double radLng1 = Rad(lng1);double radLat2 = Rad(lat2);double radLng2 = Rad(lng2);double a = radLat1 - radLat2;double b = radLng1 - radLng2;double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;return result / 1000;}/// <summary>/// 经纬度转化成弧度/// </summary>/// <param name="d"></param>/// <returns></returns>private static double Rad(double d){return (double)d * Math.PI / 180d;}

3、JavaScript

//计算2个坐标点的距离,返回千米function GetDistance(lat1, lng1, lat2, lng2){var radLat1 = lat1 * Math.PI / 180.0;var radLat2 = lat2 * Math.PI / 180.0;var a = radLat1 - radLat2;var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));s = s * 6378.137;// EARTH_RADIUS;s = Math.round(s * 10000) / 10000;return s;}// 调用 return的距离单位为km//GetDistance(23.03057,113.75213,23.03102000,113.75212000)

扩展

大量频繁的计算消耗过多的服务器资源。特别在数据库比如计算10W条数据再按距离排序,这性能可想而知。那问题来了,如何优化呢?

技术上:加服务器,加缓存,前端分摊计算

业务上:添加条件嘛,缩写范围,比如添加地区条件

有一种情况:获取距离用户10公里范围内的服务场所。

sql 可能这样写:

 SELECT *FROM   ( SELECT    ID ,Store ,CAST(6378137.0 * ACOS(SIN(@lat / 180 * PI())* SIN(CAST([Latitude] AS DECIMAL(18,8)) / 180 * PI())+ COS(@lat / 180 * PI())* COS(CAST([Latitude] AS DECIMAL(18,8)) / 180 * PI())* COS(( @lng- CAST([Longitude] AS DECIMAL(18,8)) ) / 180* PI())) AS INT) AS DistanceFROM      Store WITH ( NOLOCK )) TWHERE  T.Distance <= 10 * 1000ORDER BY Distance ASC 

这样不就计算了全部记录行后再排序嘛,既然已经限定了10公里范围,想想如果可以得到中心点(用户坐标)10公里范围的最大、最小坐标不就能作为筛选条件了吗。

在平面中,以用户坐标位原点,根据距离取得四个顶点的坐标。

获取最大、最小经纬度坐标值

1、JavaScript

//经度、纬度、多少米 内的最大最小坐标点function FindMaxMinPoint(longitude, latitude, distance){var r = 6378137; //地球半径米var dis = distance; //米 var dlng = 2 * Math.asin(Math.sin(dis / (2 * r)) / Math.cos(latitude * Math.PI / 180));dlng = dlng * 180 / Math.PI;//角度转为弧度var dlat = dis / r;dlat = dlat * 180 / Math.PI;//角度转为弧度var minlat = latitude - dlat;var maxlat = latitude + dlat;var minlng = longitude - dlng;var maxlng = longitude + dlng;console.log(minlat);console.log(maxlat);console.log(minlng);console.log(maxlng);}FindMaxMinPoint(113.75213, 23.03057, 10*1000);

2、C#

/// <summary>/// 获取坐标点多少米内最大、最小坐标值/// </summary>/// <param name="longitude"></param>/// <param name="latitude"></param>/// <param name="distance">多少米</param>/// <returns></returns>public static dynamic FindMaxMinPoint(double longitude, double latitude, double distance){//先计算查询点的经纬度范围  double r = 6378137;//地球半径米  double dis = distance;//米距离    double dlng = 2 * Math.Asin(Math.Sin(dis / (2 * r)) / Math.Cos(latitude * Math.PI / 180));dlng = dlng * 180 / Math.PI;//角度转为弧度  double dlat = dis / r;dlat = dlat * 180 / Math.PI;//角度转为弧度  double minlat = latitude - dlat;double maxlat = latitude + dlat;double minlng = longitude - dlng;double maxlng = longitude + dlng;return new{MinLat = minlat,MaxLat = maxlat,MinLng = minlng,MaxLng = maxlng};}

得到这四个值后就可以在sql中添加条件了

WHERE [Latitude] BETWEEN @minLatitude AND @maxLatitude
AND [Longitude] BETWEEN @minLongitude AND @maxLongitude

配合索引将大大提升效率。

LBS的服务场景随处可见,对应小型的应用基于有限的资源,这种优化设计很大作用。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux磁盘管理实验1

1.在安装好的linux系统中新加一块硬盘&#xff0c;将硬盘分成2个主分区&#xff0c;和2个逻辑分区&#xff0c;将其中一个逻辑分区设置成vfat&#xff08;FAT32&#xff09;分区&#xff0c;并实现开机自动挂载所有分区。 答&#xff1a;添加一个硬盘为sdb 分成2个主分区&#…

华焰天下隆重推出华火智能电燃灶产品,引领绿色科技新潮流!

近日&#xff0c;以“慧聚英雄南昌&#xff0c;论道策划科技——畅展华焰未来&#xff0c;迈向财富新时代”为主题的华火新能源产品发布会于江西南昌盛大举办。 各级领导、全国各地的企业家、家电行业优秀从业者、新能源应用领域专家、策划行业名人大咖及广大媒体朋友莅临活动…

OAI openair3代码结构整理

openair3代码框架结构 OAI&#xff08;OpenAirInterface&#xff09;是一个开源的5G网络软件平台&#xff0c;用于研究和开发5G网络技术。OpenAir3是OAI项目中的一个子项目&#xff0c;专注于5G核心网络的功能实现。 一、OpenAir3的代码主要包括以下几个部分&#xff1a; NAS…

Halcon根据特征值选择区域select_shape

Halcon根据特征值选择区域 关于提取图像的特征&#xff0c;比较常用的一个算子是select_shape算子&#xff0c;它能高效地根据特征提取出符合条件的区域。该算子的原型如下&#xff1a; select_shape (Regions : SelectedRegions : Features, Operation, Min, Max :)参数1和参…

Python+Appium自动化测试的使用步骤

这篇文章主要介绍了PythonAppium实现自动化测试的使用步骤&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧 一、环境准备 1.脚本语言&#xff1a;Python3.x IDE&am…

【开源项目】超经典数字孪生智慧物流园

数字孪生物流园管理系统&#xff0c;具有仓储管理智能化、运输管理自动化、物流管理系统化、共享服务平台化等特点。飞渡科技基于数字孪生、物联网IOT、人工智能等新一代信息技术&#xff0c;以智能设备为基底&#xff0c;通过人、物、资源、系统等多方数据的传递和交互&#x…

任务调度实现

一、定时任务概述 在项目中开发定时任务应该一种比较常见的需求&#xff0c;在 Java 中开发定时任务主要有三种解决方案&#xff1a;一是使用JDK 自带的 Timer&#xff0c;二是使用 Spring Task&#xff0c;三是使用第三方组件 Quartz Timer 是 JDK 自带的定时任务工具,其简单易…

python 3.6 + robotFramework自动化框架 环境搭建、学习笔记

一、环境搭建 概览&#xff1a;win 7 python 3.6 pycharm robotframework IntelliBot fireFox 1.安装相关的库 推荐使用pip安装&#xff0c;如 pip install robotframework(以及selenium2library) 研发环境没外网&#xff0c;采用离线安装&#xff0c;down包后解压--进入…

buildroot 编译错误【001】

在GitHub 查找错误,也挺好用 解决办法 fakeroot 错误

通过聚道云软件连接器实现金蝶软件与客如云软件的无缝对接

客户介绍 某知名冷饮连锁品牌是国内一家拥有数千家门店的知名品牌&#xff0c;作为一家专注于冷饮和甜品的企业&#xff0c;我们致力于提供高品质、健康美味的食品&#xff0c;为消费者带来冰凉的甜蜜与畅快的口感。 我们始终坚持选用优质原料&#xff0c;严格把控生产流程&a…

二叉搜索树与双向链表

解题思路一&#xff1a; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;} } */ // 一定要用自己的理解真正弄出来才行&#xff0c;否则没有用&#xff01; // 再次提醒&#xff0c;计算机这种工科…