张坤的个人博客

  • 首页
  • 分类
  • 标签
  • 日志

  • 搜索
Jenkins RabbitMQ Zookeeper IDEA Logstash Kibana ELK NIO Netty Spring Cloud Golang DataX Elasticsearch React Native Mysql H2 Socket Spring Boot Kafka Mybatis Sqlmap Vue Postgresql Docker Vert.x Flutter Flink Redis

求圆半径范围内所有的点

发表于 2020-06-03 | 分类于 默认分类 | 0 | 阅读次数 47

在做和地图有关的项目的时候,有时候会遇到这样的需求,比如:
已知圆中心的经纬度(lng, lat),手动输入它的半径radius,得到这个圆范围内所有的随机点。

我用的是百度地图js-sdk。
理论部分,喜欢看代码可以直接跳过:

image.png

从上图可以看出,圆1的经纬度是(114.132384, 22.539816)用(x1, y1)表示,圆2的经纬度是(114.131888, 22.533516)用(x2, y2)表示
我不可能用abs(x1 - x2) + abs(y1 - y2) <= radius这样的逻辑去判断圆1是否在以圆2为中心点,radius为半径的圆范围内,因为这样不是两点之间的最佳路径。(abs为取绝对值函数)

我需要用到初中数学学到过的勾股定理知识,用(abs(x1-x2))^2 + (abs(y1-y2))^2 <= radius^2来获得两点之间最短路径,也就是把这个想象成一个直角三角形,求它的斜边。

我通过js将原点的经纬度和半径传到后台,后台用java,用的是mybatis框架,数据库用的Oracle。
js和java就是简单的数据传输,可以省略,业务逻辑主要在sql部分:

表结构:车牌号,纬度,经度,时间。
先根据相同车牌号用GROUP BY去重,取最大时间的一条数据。

image.png

求圆半径内点的sql代码:

SELECT G1.*
FROM ${tableName} G1, (
    SELECT MIN(UUID) AS UUID, MAX(LOCATIONTIME)
    FROM ${tableName}
    GROUP BY VEHICLENO
) G2
WHERE G1.UUID = G2.UUID
    AND POWER(ABS((G1.LAT / 0.00000899 - #{lat} / 0.00000899)), 2) + POWER(ABS((G1.LON / 0.00001141 - #{lon} / 0.00001141)), 2) <![CDATA[<=]]> POWER(#{radius}, 2)
    AND VEHICLENO LIKE CONCAT(#{chepaihao}, '%')

主要的业务是这句:

POWER(ABS((G1.LAT / 0.00000899 - #{lat} / 0.00000899)), 2) + POWER(ABS((G1.LON / 0.00001141 - #{lon} / 0.00001141)), 2) <![CDATA[<=]]> POWER(#{radius}, 2)

0.00000899是纬度和米的比例关系: 1m = 0.00000899°
0.00001141是经度和米的比例关系: 1m = 0.00001141°

最后根据车牌号模块查询。

# Jenkins # RabbitMQ # Zookeeper # IDEA # Logstash # Kibana # ELK # NIO # Netty # Spring Cloud # Golang # DataX # Elasticsearch # React Native # Mysql # H2 # Socket # Spring Boot # Kafka # Mybatis # Sqlmap # Vue # Postgresql # Docker # Vert.x # Flutter # Flink # Redis
Redis跳跃表
Redis扩展类型
  • 文章目录
  • 站点概览
会Coding的猴子

会Coding的猴子

57 日志
19 分类
28 标签
RSS
Github
Creative Commons
© 2021 会Coding的猴子
由 Halo 强力驱动
|
主题 - NexT.Gemini v5.1.4

湘ICP备18011740号