- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图找出使用哪个GEO实现来根据long/lat找到某个点的最近点。我将有数百万甚至数十亿个不同的经纬度点需要进行比较。我一直在寻找许多不同的实现来完成我需要完成的工作。我研究过Postgis(看起来很流行,性能也很好)、Neo4J(图形数据库对我来说是一个新概念,我不确定它们的性能如何)、AWS dynamodb geohash(可伸缩性很好,但只有library是用Java编写的,我希望在node.js中编写一个库)等,但无法找出哪个性能最好。我只关注性能而不是功能的数量。我所需要做的就是将一个点与所有点进行比较,找到最接近的点(读操作),并且能够快速更改数据库中的一个点(写操作)。有人能根据这些要求建议一个好的实现吗
最佳答案
PostGIS具有多种地理哈希功能。如果使字符串足够长,搜索会变得更快(每个框+它的8个邻居的冲突更少),但是geohash生成在插入新点时会更慢。
问题还在于你想要多精确。随着纬度的增加,纬度/长“距离”变差,因为经度从赤道的约110公里缩小到两极的0公里,而纬度总是约110公里。在45度的中纬度,经度接近79km,距离误差为2(sqr(110/79))。球面距离为你提供真实的纬度/长对数之间的距离是非常昂贵的计算(很多三角法正在进行),然后你的地理哈希将不会工作(除非你转换所有的点到平面坐标)。
一个可行的解决方案是:CREATE INDEX hash8 ON tablename(substring(hash_column FROM 1 FOR 8))
。这为您提供了一个比您的分辨率大一倍的框上的索引,这有助于查找点并减少搜索相邻哈希框的需要。
在点的INSERT
上,使用PostGIS将其长度为9(大约10米分辨率)的geohash计算成hash_列。你可以在这里使用BEFORE INSERT TRIGGER
。
在函数中:
给定一个点,通过查找geohash值缩短为8个字符的所有点来查找最近的点,该值等于给定点8个字符的geohash(因此是上面的索引)。
使用球坐标计算到每个遇到的点的距离,保持最近的点。但是,由于您只寻找最近的点(至少最初是这样),所以不要使用球坐标搜索距离,而是使用下面的优化,这将使搜索速度更快。
如果给定点比最近的计算点更接近由8个字符的geohash确定的框的边缘,则进行计算。如果是,则对其8个邻居中的所有点使用7个字符的geohash重复该过程。这可以通过计算到各个框边和角的距离并只计算相关的邻居哈希框来进行高度优化;我把这个留给您去修改。
无论如何,这不会特别快。如果你确实要接近几十亿个点,你可能会想一想集群,它有一个相当“自然”的地理哈希解决方案(例如,在substring(hash_column FROM 1 FOR 2)
上分解表,给你四个象限)。只需确保您考虑到跨边界搜索。
可以相当快地进行两个优化:
首先,“规范化”你的球面坐标(意思是:随着纬度的增加,补偿经度减少的长度),这样你就可以使用“伪笛卡尔”方法搜索最近的点。这只在点很接近的情况下才有效,但是由于您使用的是很多点,所以这不应该是一个问题。更具体地说,这应该适用于长度为6或更多的geohash框中的所有点。
假设椭球体(用于所有GPS设备),地球的长轴(A)为6378137米,椭圆度(E2)为。经度的一秒长度为
longSec := Pi * a * cos(lat) / sqrt(1 - e2 * sqr(sin(lat))) / 180 / 3600
longSec := 30.92208078 * cos(lat) / sqrt(1 - 0.00669438 * sqr(sin(lat)))
latSec := 30.870265 - 155.506 * cos(2 * lat) + 0.0003264 + cos(4 * lat)
longSec/latSec
。
CREATE FUNCTION nearest_point(pt geometry, ptHash8 char(8)) RETURNS integer AS $$
DECLARE
corrFactor double precision;
ptLat double precision;
ptLong double precision;
currPt record;
minDist double precision;
diffLat double precision;
diffLong double precision;
minId integer;
BEGIN
minDist := 100000000.; -- a large value, 10km (squared)
ptLat := ST_Y(pt);
ptLong := ST_X(pt);
corrFactor := 30.92208078 * cos(radians(ptLat)) / (sqrt(1 - 0.00669438 * power(sin(radians(ptLat)), 2)) *
(30.870265 - 155.506 * cos(2 * radians(ptLat)) + 0.0003264 + cos(4 * radians(ptLat))));
FOR currPt IN SELECT * FROM all_points WHERE hash8 = ptHash8
LOOP
diffLat := ST_Y(currPt.pt) - ptLat;
diffLong := (ST_X(currPt.pt) - ptLong) * corrFactor; -- "square" things out
IF (diffLat * diffLat) < (minDist * diffLong * diffLong) THEN -- no divisions here to speed thing up a little further
minDist := (diffLat * diffLat) / (diffLong * diffLong); -- this does not happen so often
minId := currPt.id;
END IF;
END LOOP;
IF minDist < 100000000. THEN
RETURN minId;
ELSE
RETURN NULL;
END IF;
END; $$ LANGUAGE PLPGSQL STRICT;
关于postgresql - 数百万个点可使用的GEO实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22602722/
我正在尝试按照以下方式根据教程使用 Bio.Geo 解析 GEO 文件: from Bio import Geo handle = open('GSE40603_combined_L1_L2.txt'
我在 Geo::Coder::US 工作和 Geo::Coder::US::Import .他们说我需要导入数据库,他们的示例没有显示如何执行此操作,至少对于现在可行的方式。 Geo::Coder::
我目前正在使用 C++ GEOS API 迭代 typedef Points(x 和 y 成员变量)的 vector。 我通过创建一个 geos::geom::Geometry 对象,在 0 处缓冲以
我正在使用 feedparser 来解析 XML 文件。但我无法解析 , 使用该文件中的 feedparser 进行标记!你们知道我如何在 python 中使用 feedparser 解析这些标签吗
我有一个 geojson 文档,我想对其执行一些 GEOS 转换,例如:计算交点、从另一个多边形中减去多边形等。 我已经能够创建 geo_types::Polygon来自文档,但无法将其转换为 GEO
我在 Ubuntu 14.04 LTS 上运行 Django 1.8 和 Python 3.4。就在最近,我的 Django 应用一直在报告 GEOS 不存在。 GEOS 已安装并且 libgeos_
Android 是否支持地理围栏,如果是,那么最早支持地理围栏功能的平台是什么。 最佳答案 在您提出问题时没有支持,但 Google 刚刚发布了该功能作为 Google IO 2013 的一部分: h
我创建了一个应用程序,可以向您发送某个位置的纬度/经度,我想知道是否有一种统一的方式通过文本消息发送它,这样 Android 或 iPhone 可能允许用户单击它并打开它 map 中的位置。 是的,A
我正在运行此查询 SELECT country, countries.code, countries.lat, countries.lng, countries.zoom, worldip.start
以下是我用于在距给定纬度/经度坐标的给定距离内定位教区的 SQL: SELECT record_id as parish_id, parish, church, ( 3959 * acos( cos(
我正在考虑使用 GEO 提醒的应用程序(在 iOS5 中添加的应用程序,当我离开/到达时在某个位置提醒我)。但我需要使用此功能(实际上,仅使用位置)来获取当前位置并将其与我的应用程序定义的位置进行比较
我想弄清楚如何在 geo.lua 中实际调用 GEOMETRYFILTER 函数,因为文档对我来说不是很清楚: https://github.com/RedisLabs/geo.lua#GEOMETR
我收到这个错误: ImportError: Could not find the GEOS library (tried ""geos_c"", ""libgeos_c-1""). Try sett
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我遵循了几个关于 Redis 中地理空间支持的示例。我尝试毫无问题地向我的 Redis 数据集添加 POINT 特征,随后我可以查询某个坐标(或 POINT 的某个成员)的某个半径(以米、公里、英里为
Flutter geolocator 总是分别给我这个纬度和经度 37.4219983, -122.084,这不是我的真实地址,所以我该如何改进它。 最佳答案 似乎您正在使用模拟器。这是给模拟器的默认
我一直在深入研究将NEST用于将使用ElasticSearch的基于.Net的项目,但是让我感到困惑的是,GeoDistance查询从未返回任何结果。 当调试简单的“*”查询的响应并查看搜索结果的.D
嘿,我正在开发一个应用程序,我需要根据距离过滤器显示所提供的纬度和经度的地点。我正在提供来自 elastic search 的数据。我可以使用 geo_distance 查询轻松地提供数据,以查找具有
当您使用 GEOADD 命令在 Redis 中添加键时,该条目将保存为排序集(类型:zset)。 我的问题是,有没有办法(也许使用Lua?)来确定排序集中的数据是否是“GEO”数据? 最佳答案 由于
映射地址属性:id name type和location。搜索映射: { "address": { "properties": { "id": { "type"
我是一名优秀的程序员,十分优秀!