【问题标题】:PostGIS: Query z and m dimensions (linestringzm)PostGIS:查询 z 和 m 维度(linestringzm)
【发布时间】:2021-05-14 07:27:05
【问题描述】:

问题

我有一个包含多个linestringzm 的系统,其中数据的结构如下:[x, y, speed:int, time:int]。数据的结构是这样的,以便能够在x、y 和z 维度上使用ST_SimplifyVW,但我仍然希望能够基于m 维度查询线串,例如获取时间间隔之间的所有线串。

这是否可以通过 PostGIS 实现,或者我是否为我的用例错误地构建了数据?

示例

  • z = 速度,例如公里/小时
  • m = Unix 纪元时间
CREATE TABLE t (id int NOT NULL, geom geometry(LineStringZM,4326), CONSTRAINT t_pkey PRIMARY KEY (id));
INSERT INTO t VALUES (1, 'SRID=4326;LINESTRING ZM(30 10 5 1620980688, 30 15 10 1618388688, 30 20 15 1615710288, 30 25 20 1620980688)'::geometry);
INSERT INTO t VALUES (2, 'SRID=4326;LINESTRING ZM(50 10 5 1620980688, 50 15 10 1618388688, 50 20 15 1615710288, 50 25 20 1620980688)'::geometry);
INSERT INTO t VALUES (3, 'SRID=4326;LINESTRING ZM(20 10 5 1620980688, 20 15 10 1618388688, 20 20 15 1615710288, 20 25 20 1620980688)'::geometry);
  • 用例 A:基于 x、y 和 z 简化几何图形

    这可以通过例如ST_SimplifyVW 简化后保持m 维度。

  • 用例 B:根据m 维度查询几何

    我有一组 linestringzm,我想根据我的时间维度 (m) 进行查询。如果所有m 在例如1618388000 和1618388700 之间,则结果要么是完整的几何,要么是满足谓词的几何部分。查询数据最有效的方法是什么?

【问题讨论】:

  • 您能否出示CREATE TABLE 声明和INSERT 以便我们知道您的意思?
  • 您的意思是您要编写一个查询来检查您的线串的每个点是否具有与给定范围匹配的维度m?
  • @SOK: 这是你要找的WITH j AS ( SELECT id,geom, (ST_M((ST_DumpPoints(geom)).geom)) AS mdim FROM t ) SELECT DISTINCT id,geom FROM j WHERE mdim BETWEEN 1430 AND 1530 吗?
  • @JimJones:我添加了一个示例,希望可以更清楚地说明我想要实现的目标:)
  • 我还假设线串没有 id,对吗?

标签: postgresql postgis


【解决方案1】:

如果您想检查 LineString 的每个点,您可以ST_DumpPoints 他们并使用ST_M 获得M 维度。之后,将子集提取为包含重叠 M 值的 LineString,并使用 GROUP BY 应用 ST_MakeLine:

WITH j AS (
  SELECT id,geom,(ST_DumpPoints(geom)).geom AS p 
  FROM t 
) 
SELECT id,ST_AsText(ST_MakeLine(p))
FROM j
WHERE ST_M(p) BETWEEN 1618388000 AND 1618388700
GROUP BY id;

演示:db<>fiddle

注意:根据您的表和 LineString 大小,此查询可能会变得非常慢,因为值在查询时被解析,因此不会被索引。恕我直言,一个更优雅的选择是..

.. 1) 创建tstzrange 列

ALTER TABLE t ADD COLUMN line_interval tstzrange;

.. 2) 正确索引它

CREATE INDEX idx_t_line_interval ON t USING gist (line_interval);

.. 和 3) 用 geom 的 first 和 last 点的时间填充它:

UPDATE t SET line_interval = 
  tstzrange(
    to_timestamp(ST_M(ST_PointN(geom,1))),
    to_timestamp(ST_M(ST_PointN(geom,ST_NPoints(geom)))));

之后,您可以通过检查索引列是否与给定间隔重叠来加快速度。这将显着缩短查询时间:

SELECT * FROM t
WHERE line_interval && tstzrange(
                        to_timestamp(1618138148), 
                        to_timestamp(1618388700));

演示:db<>fiddle

进一步阅读:

【讨论】:

  • 我用主键更新了示例。使用ST_DumpPoints 是否有效,还是为了性能而以另一种方式构造数据更有意义?
猜你喜欢
  • 2021-08-19
  • 1970-01-01
  • 2020-09-30
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多