ST_DelaunayTriangles를 사용하여 보로 노이 다이어그램을 구성하는 방법은 무엇입니까?


13

(2019 편집) PostGIS v2.3부터 ST_VoronoiPolygon을 사용할 수 있습니다 !


PostGIS 2.1 이상에서는 ST_DelaunayTriangles () 를 사용하여 Volauoi 다이어그램이중 그래프Delaunay 삼각 분할 을 생성 할 수 있으며 이론 상으로는 정확하고 가역적 인 변환이 가능합니다.

어떤 안전합니까 SQL 표준 스크립트최적화 된 알고리즘 이 존재 이 PostGIS2 들로네 - 투 - 보로 노이 변환 ?


다른 심판 : 1 , 2


gist.github.com/djq/4714788은 당신이 후에있는 물건의 종류?
MickyT

나는 그가 ST_DelaunayTriangles를 사용하여 순수 SQL 구현을 원하는 생각 ()
라파엘

ST_DelaunayTrianglesLinux Debian Stable 에 설치하려면 이 답변참조하십시오 .
Peter Krauss

! ST_VoronoiPolygons PostGIS 2.3 이후 이용 가능
Peter Krauss

답변:


23

다음 쿼리는 들로네 삼각형에서 시작하여 합리적인 보로 노이 다각형 세트를 수행하는 것으로 보입니다.

나는 Postgres 사용자가 아니기 때문에 아마 약간 향상 될 수 있습니다.

WITH 
    -- Sample set of points to work with
    Sample AS (SELECT ST_GeomFromText('MULTIPOINT (12 5, 5 7, 2 5, 19 6, 19 13, 15 18, 10 20, 4 18, 0 13, 0 6, 4 1, 10 0, 15 1, 19 6)') geom),
    -- Build edges and circumscribe points to generate a centroid
    Edges AS (
    SELECT id,
        UNNEST(ARRAY['e1','e2','e3']) EdgeName,
        UNNEST(ARRAY[
            ST_MakeLine(p1,p2) ,
            ST_MakeLine(p2,p3) ,
            ST_MakeLine(p3,p1)]) Edge,
        ST_Centroid(ST_ConvexHull(ST_Union(-- Done this way due to issues I had with LineToCurve
            ST_CurveToLine(REPLACE(ST_AsText(ST_LineMerge(ST_Union(ST_MakeLine(p1,p2),ST_MakeLine(p2,p3)))),'LINE','CIRCULAR'),15),
            ST_CurveToLine(REPLACE(ST_AsText(ST_LineMerge(ST_Union(ST_MakeLine(p2,p3),ST_MakeLine(p3,p1)))),'LINE','CIRCULAR'),15)
        ))) ct      
    FROM    (
        -- Decompose to points
        SELECT id,
            ST_PointN(g,1) p1,
            ST_PointN(g,2) p2,
            ST_PointN(g,3) p3
        FROM    (
            SELECT (gd).Path id, ST_ExteriorRing((gd).Geom) g -- ID andmake triangle a linestring
            FROM (SELECT (ST_Dump(ST_DelaunayTriangles(geom))) gd FROM Sample) a -- Get Delaunay Triangles
            )b
        ) c
    )
SELECT ST_Polygonize(ST_Node(ST_LineMerge(ST_Union(v, ST_ExteriorRing(ST_ConvexHull(v))))))
FROM (
    SELECT  -- Create voronoi edges and reduce to a multilinestring
        ST_LineMerge(ST_Union(ST_MakeLine(
        x.ct,
        CASE 
        WHEN y.id IS NULL THEN
            CASE WHEN ST_Within(
                x.ct,
                (SELECT ST_ConvexHull(geom) FROM sample)) THEN -- Don't draw lines back towards the original set
                -- Project line out twice the distance from convex hull
                ST_MakePoint(ST_X(x.ct) + ((ST_X(ST_Centroid(x.edge)) - ST_X(x.ct)) * 2),ST_Y(x.ct) + ((ST_Y(ST_Centroid(x.edge)) - ST_Y(x.ct)) * 2))
            END
        ELSE 
            y.ct
        END
        ))) v
    FROM    Edges x 
        LEFT OUTER JOIN -- Self Join based on edges
        Edges y ON x.id <> y.id AND ST_Equals(x.edge,y.edge)
    ) z;

쿼리에 포함 된 샘플 포인트에 대해 다음과 같은 다각형 세트를 생성합니다. 여기에 이미지 설명을 입력하십시오

쿼리 설명

1 단계

입력 지오메트리에서 들로네 삼각형 만들기

SELECT (gd).Path id, ST_ExteriorRing((gd).Geom) g -- ID and make triangle a linestring
FROM (SELECT (ST_Dump(ST_DelaunayTriangles(geom))) gd FROM Sample) a -- Get Delaunay Triangles

2 단계

삼각형 노드를 분해하고 가장자리를 만들 수 있습니다. 가장자리를 얻는 더 좋은 방법이 있어야한다고 생각하지만 찾지 못했습니다.

SELECT ...
        ST_MakeLine(p1,p2) ,
        ST_MakeLine(p2,p3) ,
        ST_MakeLine(p3,p1)
        ...
FROM    (
    -- Decompose to points
    SELECT id,
        ST_PointN(g,1) p1,
        ST_PointN(g,2) p2,
        ST_PointN(g,3) p3
    FROM    (
        ... Step 1...
        )b
    ) c

여기에 이미지 설명을 입력하십시오

3 단계

각 삼각형에 대해 외접원을 만들고 중심을 찾으십시오

SELECT ... Step 2 ...
    ST_Centroid(ST_ConvexHull(ST_Union(-- Done this way due to issues I had with LineToCurve
        ST_CurveToLine(REPLACE(ST_AsText(ST_LineMerge(ST_Union(ST_MakeLine(p1,p2),ST_MakeLine(p2,p3)))),'LINE','CIRCULAR'),15),
        ST_CurveToLine(REPLACE(ST_AsText(ST_LineMerge(ST_Union(ST_MakeLine(p2,p3),ST_MakeLine(p3,p1)))),'LINE','CIRCULAR'),15)
    ))) ct      
FROM    (
    -- Decompose to points
    SELECT id,
        ST_PointN(g,1) p1,
        ST_PointN(g,2) p2,
        ST_PointN(g,3) p3
    FROM    (
        ... Step 1...
        )b
    ) c

여기에 이미지 설명을 입력하십시오

EdgesCTE는 그것이 속한 각 삼각형의 에지와 ID (경로)를 출력한다.

4 단계

서로 다른 삼각형 (내부 모서리)에 대해 동일한 모서리가있는 '에지'테이블에 '외부 조인'.

SELECT  
    ...
    ST_MakeLine(
    x.ct, -- Circumscribed Circle centroid
    CASE 
    WHEN y.id IS NULL THEN
        CASE WHEN ST_Within( -- Don't draw lines back towards the original set
            x.ct,
            (SELECT ST_ConvexHull(geom) FROM sample)) THEN
            -- Project line out twice the distance from convex hull
            ST_MakePoint(
                ST_X(x.ct) + ((ST_X(ST_Centroid(x.edge)) - ST_X(x.ct)) * 2),
                T_Y(x.ct) + ((ST_Y(ST_Centroid(x.edge)) - ST_Y(x.ct)) * 2)
            )
        END
    ELSE 
        y.ct -- Centroid of triangle with common edge
    END
    ))) v
FROM    Edges x 
    LEFT OUTER JOIN -- Self Join based on edges
    Edges y ON x.id <> y.id AND ST_Equals(x.edge,y.edge)

공통 모서리가있는 경우 각 중심 사이에 선을 그립니다.

여기에 이미지 설명을 입력하십시오

모서리가 결합되지 않은 (외부) 중심에서 모서리 중심을 통과하는 선을 그립니다. 원의 중심이 삼각형 세트 안에있는 경우에만이 작업을 수행하십시오.

여기에 이미지 설명을 입력하십시오

5 단계

그려진 선의 볼록 껍질을 선으로 만듭니다. 모든 라인을 통합하고 병합하십시오. 다각형화할 수있는 토폴로지 세트를 갖도록 라인 세트를 노드 화하십시오.

SELECT ST_Polygonize(ST_Node(ST_LineMerge(ST_Union(v, ST_ExteriorRing(ST_ConvexHull(v))))))

여기에 이미지 설명을 입력하십시오


좋은 단서, 아마도 해결책 (!). 테스트 할 필요가 있지만 지금은 할 수 없습니다 ... 분석 : ref1 / Kenneth Sloa가 제안한 직접 알고리즘에서와 같이 "수직 이등분선"을 대신 사용 ST_ConvexHull하고 직접 솔루션이 아닌 이유는 무엇입니까? ST_Centroid
Peter Krauss

나는 거의 단지 모든 수학 않고, 외부 가장자리에 대한 수직 이등분선을하고있다 :) 내가 대답에 수행 한 단계에 대한 설명을 추가 할 것입니다
MickyT

좋은 일러스트와 설명, 매우 교훈적인!   내가 필요한 모든 것을 게시했지만 (요즘 테스트 할 Postgis2.1이 없습니다 ... 테스트로 답변 할 수있는 몇 가지 질문을 여기에서 (주석으로) 확인할 수 있습니까?   1) ST_Polygonize는 "가능한 다각형을 포함하는 GeometryCollection을 생성합니다", 그들은 모두 Voronoi 셀입니다. 맞습니까?   2) 성능에 대해, 중심 기반 솔루션이 "수직 이등분선 계산의 모든 수학"과 비슷한 CPU 시간을 가지고 있다고 생각하십니까?
Peter Krauss

@PeterKrauss 1) ST_polygonize는 라인 작업에서 보로 노이 셀을 생성합니다. 트릭은 모든 라인 작업이 노드에서 분할되도록하는 것입니다. 2) 나는 bisection을 계산하는 것과 ST_Centroid를 사용하는 것 사이에 많은 차이가 있다고 생각하지 않습니다. 그러나 테스트해야합니다.
MickyT

ST_DelaunayTrianglesLinux Debian Stable 에 설치하려면 이 답변참조하십시오 .
Peter Krauss
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.