PostGIS:查询 z 和 m 维度 (linestringzm)

PostGIS: Query z and m dimensions (linestringzm)

问题

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

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

例子

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);

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

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

注意:根据您的 table 和 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) 用 geomfirstlast 点的时间填充它:

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

延伸阅读: