PostGIS - 路线匹配解决方案
Posted
技术标签:
【中文标题】PostGIS - 路线匹配解决方案【英文标题】:PostGIS - Route matching solution 【发布时间】:2018-02-23 11:12:02 【问题描述】:我们正在构建一个应用程序,我是一名司机,我从 A 点到 B 点旅行。在途中我可以找到沿同一路线旅行的乘客。
我们正在使用带有 PostGIS 扩展的 PostgreSQL。
在谷歌上搜索了很多之后,我发现我们可以使用线串来实现这一点。我不完全确定这种方法是否可行。
假设我有我的来源和目的地的坐标。
var RouteCoordinates = [
lat: 37.772, lng: -122.214,
lat: 21.291, lng: -157.821,
lat: -18.142, lng: 178.431,
lat: -27.467, lng: 153.027
];
我需要将它作为线串存储在我的数据库中。
在确定乘客是否也在这条路线上之后,但我们知道他的来源和目的地不会完全在我的线路字符串中,但它们会在附近。 例如半径 1 公里左右
如您所见,我的来源和目的地就是那条线。当我旅行时,我想挑选所有(来源和目的地)靠近我的路线(在特定半径内)的人
如果我想在特定半径内的数据库中找到特定位置,我将像这样查询
SELECT id, name, address, geom
FROM Seattle_Starbucks
WHERE ST_DWithin(geom, ST_MakePoint(-122.325959,47.625138)::geography, 1000);
现在我可以实现我的解决方案,因为我是 postGIS 新手,有点混乱
-
如何将我所有的源点和目标点存储在 DB 中
答:我需要使用ST_MakeLine这个函数转换成线串然后存储,对吧?
-
如上所述,如何根据我的要求进行查询
您能否告诉我如何实现这一目标。非常感谢您的帮助。谢谢
【问题讨论】:
这与 Elixir 和 Ecto 有何关系?您是否有原始 SQL 查询可以转换为 Ecto?您可能应该将此问题分为两个:1:原始 SQL 查询和 2:将其转换为 Ecto 格式。 您研究过 pgrouting 吗?如果我正确理解了您的问题,那么您不仅需要创建一条线路,而且一旦您选择了另一个效率非常低的客户,这条线路就必须更新。我很好奇,你为什么一开始就使用点而不是道路网络? 如果您不介意分享,您后来是如何解决这个问题的? 【参考方案1】:关于您的问题的一些想法:
我需要使用这个函数 ST_MakeLine 转换成线串和 然后存储,对吗?
是的,要将多个点合并为LINESTRING
,您可以使用ST_MakeLine
:
SELECT ST_AsText(
ST_MakeLine(ARRAY[ST_MakePoint(-122.21,37.77),
ST_MakePoint(-157.82,21.29),
ST_MakePoint(178.43,-18.14),
ST_MakePoint(153.02,-27.46)]));
st_astext
---------------------------------------------------------------------
LINESTRING(-122.21 37.77,-157.82 21.29,178.43 -18.14,153.02 -27.46)
(1 Zeile)
如上所述,如何根据我的要求进行查询
在LINESTRING
的每个点上创建一个缓冲区,并检查其中是否有其他几何图形。
首先,您必须使用 ST_DumpPoints
将您的溃败 LINESTRING
拆分为 POINT
s ...
db=# SELECT ST_AsText((ST_DumpPoints('LINESTRING(-122.21 37.77,-157.82 21.29,178.43 -18.14,153.02 -27.46)'::GEOMETRY)).geom);
st_astext
----------------------
POINT(-122.21 37.77)
POINT(-157.82 21.29)
POINT(178.43 -18.14)
POINT(153.02 -27.46)
(4 Zeilen)
.. 然后使用ST_Buffer
在每个点周围创建一个缓冲区。 ST_Buffer 返回一个几何图形,其中包含您的点周围的区域(或任何其他几何图形类型)。例如,取你路线的第一个点(如果我没有切换 x 和 y,它在旧金山的某个地方)POINT(-122.21 37.76)
:
db=# SELECT ST_AsText(
ST_Buffer('POINT(-122.21 37.76)'::GEOMETRY,0.0001, 'quad_segs=16'));
返回此几何:
POLYGON((-122.2099 37.76,-122.209900481527 37.759990198286,-122.209901921472 37.7599804909678,-122.209904305966 37.7599709715323,-122.209907612047 37.7599617316568,-122.209911807874 37.7599528603263,-122.209916853039 37.7599444429767,-122.209922698955 37.7599365606716,-122.209929289322 37.7599292893219,-122.209936560672 37.7599226989547,-122.209944442977 37.7599168530388,-122.209952860326 37.7599118078736,-122.209961731657 37.7599076120467,-122.209970971532 37.7599043059664,-122.209980490968 37.759901921472,-122.209990198286 37.7599004815273,-122.21 37.7599,-122.210009801714 37.7599004815273,-122.210019509032 37.759901921472,-122.210029028468 37.7599043059664,-122.210038268343 37.7599076120467,-122.210047139674 37.7599118078736,-122.210055557023 37.7599168530388,-122.210063439328 37.7599226989547,-122.210070710678 37.7599292893219,-122.210077301045 37.7599365606716,-122.210083146961 37.7599444429767,-122.210088192126 37.7599528603263,-122.210092387953 37.7599617316568,-122.210095694034 37.7599709715323,-122.210098078528 37.7599804909678,-122.210099518473 37.759990198286,-122.2101 37.76,-122.210099518473 37.760009801714,-122.210098078528 37.7600195090322,-122.210095694034 37.7600290284677,-122.210092387953 37.7600382683432,-122.210088192126 37.7600471396737,-122.210083146961 37.7600555570233,-122.210077301045 37.7600634393284,-122.210070710678 37.7600707106781,-122.210063439328 37.7600773010453,-122.210055557023 37.7600831469612,-122.210047139674 37.7600881921264,-122.210038268343 37.7600923879533,-122.210029028468 37.7600956940336,-122.210019509032 37.760098078528,-122.210009801714 37.7600995184727,-122.21 37.7601,-122.209990198286 37.7600995184727,-122.209980490968 37.760098078528,-122.209970971532 37.7600956940336,-122.209961731657 37.7600923879533,-122.209952860326 37.7600881921264,-122.209944442977 37.7600831469612,-122.209936560672 37.7600773010453,-122.209929289322 37.7600707106781,-122.209922698955 37.7600634393284,-122.209916853039 37.7600555570233,-122.209911807874 37.7600471396737,-122.209907612047 37.7600382683432,-122.209904305966 37.7600290284677,-122.209901921472 37.7600195090322,-122.209900481527 37.760009801714,-122.2099 37.76))
如果您想知道这个缓冲区的形状,请阅读answer。
使用此查询,您可以检查此缓冲区内是否有另一个几何图形 (ST_Within
):
db=# SELECT
ST_Within('POINT(-122.21 37.76)'::GEOMETRY,
ST_Buffer('POINT(-122.21 37.76)'::GEOMETRY,0.0001, 'quad_segs=16'));
st_within
-----------
t
(1 Zeile)
总而言之,您可以使用CTE
(又名 WITH 子句)并编写如下内容:
WITH j AS (
SELECT
(ST_DumpPoints('LINESTRING(-122.21 37.77,-157.82 21.29,178.43 -18.14,153.02 -27.46)'::GEOMETRY)).geom AS g)
SELECT id, name, address, geom
FROM Seattle_Starbucks
WHERE ST_Within(geom,ST_Buffer(j.g,0.0001, 'quad_segs=16'))
【讨论】:
以上是关于PostGIS - 路线匹配解决方案的主要内容,如果未能解决你的问题,请参考以下文章
错误:匹配 postgis 自定义模式时,函数 postgis_lib_version() 不存在
PostGIS 中的 ST_Buffer 对同一组行产生不同的结果