如何在PostgreSQL中获得多边形的具体点?

时间:2017-01-05 11:32:07

标签: postgresql geometry

我有简单的表格:

create table boxes2(id serial, rect polygon);
insert into boxes2(rect) values(polygon'((0,0),(10,0),(10,10),(0,10))');

我想得到这个多边形的具体点,我做了这个

select rect[0] from boxes2 where id = 1;

但是有错误:“类型多边形不是数组,不可能指定元素索引”

我该怎么做?

版本 - “PostgreSQL 9.5.4,由Visual C ++ build 1800,32位编译”

2 个答案:

答案 0 :(得分:2)

PostGIS扩展中有一个函数ST_DumpPoints(geometry geom),用于从几何对象中提取点。

如果rect值只是方框,则可以将多边形转换为方框:

select (box(rect))[0] right_top, (box(rect))[1] left_bottom
from boxes2 
where id = 1;

 right_top | left_bottom 
-----------+-------------
 (10,10)   | (0,0)
(1 row)

在这种情况下,您只需将值存储为box类型。

答案 1 :(得分:1)

这是一种相当复杂的方式来获得第一个'多边形的点,基于假设PostgreSQL以与输入相同的顺序保持顶点,将多边形转换为文本,然后使用正则表达式解析文本,取出您感兴趣的部分,并将其重新投射回来到点类型。它相当复杂:

WITH boxes2(id, rect) AS
(
VALUES
    (1, polygon'((0,0),(10,0),(10,10),(0,10))')
)
SELECT 
    p 
FROM 
    (
    SELECT
        row_number() over () AS rn, p
    FROM
        (
        SELECT
            (
             (regexp_matches(rect::text, 
              '\([^()]+\)', 'g')
             )[1]
            )::point AS p
        FROM
            boxes2
        WHERE
            id = 1
        ) AS pol_to_table_of_points
    ) AS numbered_table_of_points
WHERE
    rn = 2 /* This is if you want to get then 2nd point */ ;

我必须承认这看起来很糟糕,但是,AFAIK,没有公开的方式来获得第一个'多边形的点(也不是路径)。我很确定你可以使用PostGIS做到这一点,但没有它就找不到办法。

有一个函数可以获得点数(npoints(polygon '((1,1),(0,0))')),但不是特定点。将多边形转换为点数组(cast a_polygon :: point [])也不起作用。

警告:

从几何角度来看,如果A,B,C和D是点(顶点或角点),那么(A,B,C,D)所描述的polygons,(B,C, D,A),(C,D,A,B),(D,A,B,C)和相同的(有序的)四联体但反转:(D,C,B,A),...绝对等效。

所以,你不能真正说出第二个"第二个"多边形的顶点。此时,只是检查了几个点数非常少的样本,似乎表明PostgreSQL将多边形表示为有序的顶点列表,保持原始顺序。但是,如果这个新的表示以某种方式帮助它,它实际上可以改变它。

例如,以下查询中的所有多边形都是等效的:

WITH some_polygons (p1, p2, p3, p4, p5, p6, p7, p8) AS
(
VALUES
    ('(0,0), (1,0), (2,2), (0,3)' :: polygon,
     '(1,0), (2,2), (0,3), (0,0)' :: polygon,
     '(2,2), (0,3), (0,0), (1,0)' :: polygon,
     '(0,3), (0,0), (1,0), (2,2)' :: polygon,

     '(0,3), (2,2), (1,0), (0,0)' :: polygon,
     '(0,0), (0,3), (2,2), (1,0)' :: polygon,
     '(1,0), (0,0), (0,3), (2,2)' :: polygon,
     '(2,2), (1,0), (0,0), (0,3)' :: polygon
    )
)
SELECT
    p1 ~= p2 AS eq2,  -- ~= stands for "same as"
    p1 ~= p3 AS eq3,
    p1 ~= p4 AS eq4,
    p1 ~= p5 AS eq5,
    p1 ~= p6 AS eq6,
    p1 ~= p7 AS eq7,
    p1 ~= p8 AS eq8 
FROM
    some_polygons ;

我认为这就是为什么PostgreSQL决定不让你接受多边形的"nth" vertex的原因:它是理论上没有定义的东西。

因此,如果您想保持安全,并且不担心以后的实施更改会破坏您的代码,那么您可以存储一系列点(point[])。数组保证以保持值与提供的顺序相同。如果你需要一个多边形和原始的顶点列表,我想我会得到两个数据(即使这是一个非规范化的形式)。如果您只使用矩形,我会使用box类型;它更能代表您的需求。