【问题标题】:How do I get the next point in a PostGIS linestring given the prior point as input给定先前点作为输入,如何获取 PostGIS 线串中的下一个点
【发布时间】:2012-10-15 10:35:05
【问题描述】:

我有 PostgreSQL8.4+PostGIS。

我有一列中包含线串几何图形的表格。我有这个线串的一个点,我想得到下一个点。为此,我想使用函数ST_NPointsST_PointN。为了使用它,我必须对所有点进行排序找到我的点,然后我会知道下一点是我需要的。

这是我的桌子:

-- Table: filedata

-- DROP TABLE filedata;

CREATE TABLE filedata
(
  num serial NOT NULL,
 id integer,
 mydata character(25),
 the_geom geometry,
 CONSTRAINT filedata_pkey PRIMARY KEY (num)
)
WITH (
OIDS=FALSE
);
ALTER TABLE filedata OWNER TO postgres;

以及示例线串:

"LINESTRING(60.7014631515719 56.8441322356241,60.7023117507097 56.8445673405349,60.702948200063 56.8447993944193,60.703902874093 56.8448574076656,60.706236521722 56.8447993944193,60.7094187684889 56.8449444273664,60.7121236782406 56.8450894597515,60.715571112238 56.8452925041466,60.718382096882 56.8454085290207,60.7204505572805 56.8453505166286,60.7222538304482 56.8450314468649,60.7246405155233 56.8444513130533,60.7260194891224 56.8440742212539,60.7260194891224 56.8440742212539,60.7260194891224 56.8440742212539,60.7260194891224 56.844045214035)"

【问题讨论】:

  • 示例数据和架构?如果您显示一些示例CREATE TABLEINSERTs,以及最好的预期结果表,它确实有助于回答问题。另外,提出您的 PostgreSQL 版本问题。
  • 实际上,您希望将线串视为一个点数组,并找到索引比输入点大一的点。是对的吗?或者你想对点列表进行排序然后得到下一个最大的点?如果您指的是下一个最大点,而不是列表中的下一个位置,您如何定义“最大”点?
  • @Clodoaldo 请不要使用特定于版本的标签重新标记,除非它是与特定版本密切相关的问题,例如“这适用于 Pg 8.4 但不适用于 9.1”。这不是。见meta.stackexchange.com/a/85744/193985
  • 你如何对积分进行排序?它们是二维的。你想先按 x 再按 y 排序吗?还是您的意思是“将它们排序为与它们在原始线串中出现的顺序相同”?
  • @CraigRinger 我不确定你的意思。我确实向现有的主标签添加了一个特定于版本的标签。我没有删除主标签。这就是你所说的retag吗?在这个问题中,我不知道版本是否重要,但我添加了版本标签,因为您要求提供版本,所以我认为这是相关的。

标签: postgresql postgis


【解决方案1】:

假设您指的是线串顺序中的下一个,您可以执行以下操作:

WITH 
  -- The input data; this would be from the `filedata` table normally
  geom(line) AS (VALUES ('LINESTRING(60.7014631515719 56.8441322356241,60.7023117507097 56.8445673405349,60.702948200063 56.8447993944193,60.703902874093 56.8448574076656,60.706236521722 56.8447993944193,60.7094187684889 56.8449444273664,60.7121236782406 56.8450894597515,60.715571112238 56.8452925041466,60.718382096882 56.8454085290207,60.7204505572805 56.8453505166286,60.7222538304482 56.8450314468649,60.7246405155233 56.8444513130533,60.7260194891224 56.8440742212539,60.7260194891224 56.8440742212539,60.7260194891224 56.8440742212539,60.7260194891224 56.844045214035)'::geometry)),
  -- Create a set of (index,point) rows
  --
  point_series(line,n) AS (
      SELECT line, generate_series(1, ST_NPoints(line)) FROM geom
  ),
  -- Annotate that row set to include the prior point in each row,
  -- ie (n, point_n, point_n_minus_one)
  --
  lagged_points(pointidx, point, lagpoint) AS (
    SELECT n, ST_PointN(line,n) AS pointn,
           lag(ST_PointN(line,n)) OVER () AS point_n1
    FROM point_series
  )
-- Now SELECT the point we want, the point after
-- the one specified in the WHERE clause
SELECT astext(point)
FROM lagged_points
WHERE lagpoint = 'POINT(60.7014631515719 56.8441322356241)'::geometry;

如果 PostGIS 提供一种将geometry 转换为点数组的方法,这将变得更加简单。如果它有一个等效于 intarray 的 idx 函数,它也会更简单。

【讨论】:

  • 这是我想要的。但我没有点的坐标,我有一个序列号,例如 4 或 5 或 6。
  • @KliverMax Argh。你为什么说现在,而不是首先写一个明确的问题,或者回复澄清请求?以上内容提供了您自己解决问题所需的所有线索;只需省略lag() 步骤并改用WHERE n = input_index+1
  • Postgis 有 st_dumppoints() 可用于获取点数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多