geo算法了解学习以及选择

2023-11-14

需求:通过坐标了解到距离最近的桩号/建筑/景点

Mysql:

Sql语句:

SELECT id,

      ST_Distance_Sphere(

           POINT(${item.longitude}, ${item.latitude}),

           POINT(longitude, latitude)

      ) AS distance

      FROM carport

      where carParkId = 66

      ORDER BY distance

LIMIT 1 ;

原理:

  1. 创建空间索引:为了支持地理空间计算,需要在存储地理数据的表上创建合适的空间索引。索引可以使用R-Tree或者其他适合地理空间数据的索引结构。

  2. 转换为球面坐标:将经度和纬度转换为球面坐标系中的点。经度取值范围为-180到180,纬度取值范围为-90到90。

  3. 计算球面距离:使用球面三角学的公式来计算两个球面坐标点之间的物理距离。MySQL中的ST_Distance_Sphere函数采用Haversine公式来计算大圆距离。

  4. 返回结果:ST_Distance_Sphere函数将计算得到的距离作为结果返回,单位通常是米或千米,具体取决于输入的地理坐标单位。

Redis:

const result = await redis.georadius('locations', item.longitude, item.latitude, 200, 'km', 'ASC', 'COUNT', 1);

原理:

  1. 对于每个地理位置,通过经纬度信息将其编码为一个唯一的Geohash值。Geohash是一种将经纬度转换为字符串的编码方式,它能够将相邻的地理位置映射到相似的编码中。
  2. Redis使用有序集合的数据结构来存储地理位置,其中集合的成员是地理位置的名称或标识符,分数是对应的Geohash值。
  3. 当需要查询附近的地理位置时,通过指定经纬度和半径信息,在存储的有序集合中进行范围查询。Redis会根据Geohash值的顺序和距离计算,在给定半径范围内检索出符合条件的地理位置。
  4. 结果返回时,可以获取地理位置的经纬度、距离等详细信息,以满足具体业务需求。

手写geo算法:

// 转换经纬度为弧度
function toRadians(degrees) {
    return degrees * (Math.PI / 180);
}

// 计算两个经纬度坐标之间的距离长度(单位:千米)
function calculateDistance(eventLoc, K) {
    const R = 6371; // 地球的半径(单位:千米)

    // 将经纬度转换为弧度
    const radLat1 = toRadians(eventLoc.latitude);
    const radLon1 = toRadians(eventLoc.longtitude);
    const radLat2 = toRadians(K.latitude);
    const radLon2 = toRadians(K.longtitude);

    // 差值
    const dLat = radLat2 - radLat1;
    const dLon = radLon2 - radLon1;

    // 应用Haversine公式计算距离
    const a = Math.sin(dLat/2)**2 + Math.cos(radLat1) * Math.cos(radLat2) * Math.sin(dLon/2)**2;
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    const distance = R * c;

    return distance;
}

function executeQuery(location, K_Nos) {
    let disMap = new Map()
    for (Kitem of K_Nos) {
        disMap.set(Kitem.id, calculateDistance(location, Kitem))
    }
    const keys = Array.from(disMap.keys());
    const minKey = Math.min(...keys);

    return minKey
}

原理:

  1. 将经纬度坐标转换为弧度制。将经度乘以π/180,将纬度乘以π/180,即可得到对应的弧度值。

  2. 使用Haversine公式计算两个点之间的球面距离。Haversine公式如下:

    a = sin²((lat₂ - lat₁) / 2) + cos(lat₁) * cos(lat₂) * sin²((lon₂ - lon₁) / 2) c = 2 * atan2(√a, √(1 - a)).
    distance = R * c.
  3. 其中,lat₁lon₁是第一个点的纬度和经度,lat₂lon₂是第二个点的纬度和经度,R是地球的半径(通常取平均半径约为6,371千米)。

  4. 重复计算步骤2,得到每对经纬度之间的距离。

  5. 取出最小距离。遍历所有计算得到的距离,找到最小值即可。

总结:

手写的geo算法在时间效率上要远高于另外两种方法,空间占用略少于前两种;

时间上的区别主要是因为手写的geo算法不需要通过网络,直接从内存中获取,而redis虽然也是从内存中获取数据,但是要经过网络传输进行计算,mysql无论计算还是获取数据都是通过网络,时间上最慢。

空间上来说,前两种方法几乎一致,都是把事件读取到内存,别的都不消耗内存空间;而手写的geo需要把桩号也录入内存,比前两种空间占用略大,这个大小差是桩号个数×12字节(桩号id,经纬度各四个字节)

持久化角度来说,数据库的持久化肯定是最好的;redis比手写geo要好一点,在不过期,不关机的情况下一般不会丢失数据;手写geo只能放在内存中,一旦程序关闭,数据就会丢失,持久化较差。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

geo算法了解学习以及选择 的相关文章

  • vs+qt程序添加cmd窗口

    概述 在项目开发过程中为方便查看一些调试信息 可以在运行时把命令行窗口同时显示出来 操作说明 项目右键选择属性 项目 属性 配置属性 链接器 系统 子系统 下拉选项中选择控制台 当不需要打 cmd 的时候设置子系统为窗口 SUBSYSTEM
  • EasyAR4.0稀疏空间地图室内导航

    现有的AR室内导航 一种方案是利用运动跟踪实现 但是偏移较大 比较靠谱或者说能满足商业使用的还是稀疏空间地图 ARCore管叫云锚点 实现效果如下 EasyAR稀疏云地图室内导航 制作思路其实很简单 先建立空间地图 然后利用平面图像追踪在空
  • PPTP 理解以及报文的分析

    首先 先来理解下什么是 PPTP PPTP将PPP Point to Point Protocol 帧封装进IP数据报中 通过IP网络如Internet或其他企业专用Intranet等发送 PPTP通过PPTP控制连接来创建 维护 终止一条
  • Dialog显示报错:Unable to add window -- token null is not valid; is your activity running?

    很平常的显示一个dialog 出现了如上报错 网上很多都说解决方案 但是没有说原理过程 简单的说下 在显示dialog时出现 是应用没有token所导致 而应用的token一般只有Activity拥有 所以需要用Activity作为cont
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • C语言,使用函数封装,实现单词的逆置 “hello my student” 最终结果是”student my hello”

    实现单词的逆置 hello my student 最终结果是 student my hello 在该函数 void StrFun char str 循环字符串的 在该函数 void StrRev char str 主要是实现逆置的 incl

随机推荐

  • 超详细的Linux基础命令

    文章目录 前言 Linux目录结构 Linux命令通用格式 ls 命令 什么是工作目录 什么是 HOME 目录 目录切换相关命令 cd 命令 pwd 命令 特殊的路径符 创建目录 文件操作相关命令 touch 命令 cat 命令 more
  • java 日历_java的日历类(Calendar)详解

    老实说对于时间的处理我大部分都在用Calendar日历类解决 现在整理一下 方便以后开发查阅 java util 类 Calendar java lang Object 继承者 java util Calendar 所有已实现的接口 Ser
  • 火线 地线 零线 漫谈

    交流电不分正负 那为什么又要分火线和零线呢 零线的对地电位不一定为零 接近0 零线的最近接地点是在变电所或者供电的变压器处 交流电正半周火线电压为220v 零线接近0v 正 负半周时火线电压为负220v 零线电压接近0V 负 所以二相插座不
  • 此URL不支持Http方法GET 详情 请求行中接收的方法由源服务器知道,但目标资源不支持 解决方法之一

    因为response和request位置反了 这里位置反了所以doGet是灰的 换了个位置就好了 具体原因https www it1352 com 982509 html
  • 深入理解 Spring Boot Starters 原理(手写Spring boot Start)

    版权声明 本文为博主原创文章 遵循 CC 4 0 by sa 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csdn net zhaohong bo article details 89924053 一 Spri
  • 英特尔的集显和Nvidia的独显切换(切换之后永久有效)

    参考网址 https blog csdn net a850565178 article details 107979314 前提介绍 安装了nvidia驱动之后 有些电脑会发现setting的devices的Graphics显示的还是llv
  • SmartAndroid之SmartJump,告别onActivityResult

    SmartJump 需求 应用场景 实现思路 代码 调用示例 后记 需求 在跳转到另一个Activity后 通过回调直接获取到数据 应用场景 普通的activity跳转 回调获取数据可以使逻辑更清晰 第三方库中activity数据回调可以让
  • 实战案列:AntiDebug

    往期推荐 self debugging反调试 轮循检测技术 进程名称检测 Java层反调试 Anti Debug主要是通过各种函数去确定当前进程是否处于被调试的状态 一 IDA里面静态分析so文件 1 将文件拖入jdax gui中 进行静态
  • PLSQL字体设置常见问题

    PLSQL字体设置常见问题 从网络资源下载的PLSQL 字体默认的大小不太适合大屏幕的电脑 因为看起来字体很小 我们可打开PLSQL来设置字体的大小以及其他常规设置 一 字体太小 操作流程 菜单栏的Tools gt Preferences
  • 静态多态和动态多态

    多态 静态多态和动态多态 多态的实现主要分为静态多态和动态多态 静态多态主要是重载和模板 在编译的时候就已经确定 动态多态是用虚函数机制实现的 在运行期间动态绑定 举个例子 一个父类类型的指针指向一个子类对象时候 使用父类的指针去调用子类中
  • vue学习 十二 vue文件目录知晓 or 组件嵌套

    说明 我使用的是HBuilder 软件能用就可以了 查看顺序是 index html 入口文件 gt main js gt App vue 模板文件 可以看出能显示出欢迎页面 还有那个大V都在这里可以看到 gt components 自定义
  • Redis DEL删除命令是否会导致阻塞

    DEL命令是存在阻塞的可能性的 1 使用DEL命令删除key DEL keya keyb keyc 2 根据删除的key的数量和类型 操作的时间复杂度不同 删除N个key key中的数量为M则时间复杂度是O N M 删除一个字符串的key则
  • 类中有引用需要注意——非静态的引用成员错误提示,不能使用默认的赋值运算符

    我们知道 当我们我们没有定义赋值操作符时 编译器会生成一个默认的赋值操作符执行浅拷贝 就像默认构造函数一样是编译器默认生成的 而如果勒种有引用就需要注意一个大大的误区 我们知道引用在定义的时候就需要初始化 指定这个引用变量是哪个变量的别名
  • C常用标准库及函数

    常用头文件 stdio h stdlib h ctype h string h math h system h 1 stdio库 主要功能是输入输出操作 包括文件输入输出 标准输入输出 输出函数 int puts const char st
  • Method的invoke方法初步了解

    Java调试过程中 我们有时候会需要对JVM运行过程中哪出了问题进行调试 先从最基础的了解 我们都知道Java框架中方法的调用基本上都是通过反射机制来实施的 具体流程如下 1 方法的调用先检查AccessibleObject的overrid
  • IT项目管理-HW6

    1 a b c 最后一条为该项目的关键路径 长度为15天 d 完成该项目所需的最短时间可能是10天 3 根据 1 中介绍 看板在项目流程中载体的分类为两种 一种是实体看板 一种是互联网看板 实体看板是敏捷开发团队中使用的最多 最直接的一种看
  • 脉冲的三种形式

    脉冲信号可以分为AB相脉冲 脉冲 方向 CW CCW脉冲 这三种信号格式 在十几年前或者还有明显的相对优缺点和适用场合 现在就已经无所谓了 即使在使用上还是有所区分 也基本上是由于历史习惯 1 A B信号 位置传感器最喜欢的格式 因为 早期
  • 修改远程桌面端口bat批处理(windows)

    新建批处理 将以下内容复制进去即可 修改成功后会自动重启 echo off color f0 echo 修改远程桌面3389端口 支持Windows 2003 2008 2008R2 2012 2012R2 7 8 10 echo 自动添加
  • springboot 集成 elasticsearch(maven项目)

    1 搭建springboot项目 能跑起来 具体百度 我的springboot版本 1 5 9 RELEASE 2 本机或者服务器安装elasticsearch并启动服务成功 我本地Windows安装的elasticsearch版本6 1
  • geo算法了解学习以及选择

    需求 通过坐标了解到距离最近的桩号 建筑 景点 Mysql Sql语句 SELECT id ST Distance Sphere POINT item longitude item latitude POINT longitude lati