PostGIS में वोरोनोई आरेख का निर्माण


12

मैं यहाँ से संशोधित कोड का उपयोग करके पॉइंट ऑफ ग्रिड से वोरोनोई आरेख बनाने की कोशिश कर रहा हूं । मेरे संशोधनों के बाद यह SQL क्वेरी है:

DROP TABLE IF EXISTS example.voronoi;
WITH 
    -- Sample set of points to work with
    Sample AS (SELECT ST_SetSRID(ST_Union(geom), 0) geom FROM example."MeshPoints2d"),
    -- 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_SetSRID((ST_Dump(ST_Polygonize(ST_Node(ST_LineMerge(ST_Union(v, ST_ExteriorRing(ST_ConvexHull(v)))))))).geom, 2180)
INTO example.voronoi
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

नीचे - मेरी क्वेरी का परिणाम। यहाँ छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं कि मैं "लगभग" सही वोरोनोई आरेख प्राप्त कर रहा हूं, हाइलाइट किए गए बिंदुओं को छोड़कर, जिनके पास अद्वितीय बहुभुज नहीं है। नीचे QGIS एल्गोरिथ्म क्या है और मैं क्वेरी से क्या प्राप्त करना चाहूंगा। कोई भी समस्या जहां मेरे कोड में समस्या है?

यहाँ छवि विवरण दर्ज करें


शायद आप SpatiaLite फ़ंक्शन "VoronojDiagram" gaia-gis.it/gaia-sins/spatialite-sql-latest.html के परिणाम की तुलना भी कर सकते हैं और gaia-gis.it/fossil/libspatialialite में स्रोत कोड पर एक नज़र डाल सकते हैं सूचकांक
user30184

अच्छा प्रश्न है, मैं उसी प्रश्न को देख रहा हूँ जिसे आप संदर्भ दे रहे हैं, इसे तेज करने की दृष्टि से, लेकिन समय के साथ चलते रहें। मुझे बाहरी मुद्दों के साथ इस मुद्दे की जानकारी नहीं थी।
जॉन पॉवेल

5
PostGIS 2.3 में आने वाले ST_Voronoi के लिए यह हमारे लायक है, इसके लिए Dan Baston जल्द ही कोड में जाँच करेगा - trac.osgeo.org/postgis/ticket/2259 बहुत अधिक लग रहा है बस खींचने की जरूरत है। लोग परीक्षण
LR1234567 21

क्या आप उन बिंदुओं के समूह को पोस्ट कर सकते हैं जिनका आप उपयोग कर रहे हैं? मैं इस पर अपने आप को थोड़ा सा परीक्षण करने का मन करूंगा
मिकटी

@MickyT यहां मेरे डेटा का लिंक है। डेटा SRID 2180 है।
डेमनबैक

जवाबों:


6

हालांकि यह प्रश्न में डेटा के लिए क्वेरी के साथ तत्काल समस्या को ठीक करता है, मैं सामान्य उपयोग के समाधान के रूप में इसके साथ खुश नहीं हूं और जब मैं कर सकता हूं तो मैं इस और पिछले उत्तर को फिर से लिखूंगा।

मुद्दा यह था कि मूल क्वेरी वोरोनोई बहुभुज के लिए बाहरी किनारे का निर्धारण करने के लिए वोरोनोई किनारों पर उत्तल पतवार का उपयोग कर रही थी। इसका मतलब यह था कि कुछ वोरोनोई किनारों बाहरी तक नहीं पहुंच रहे थे जब उन्हें होना चाहिए था। मैंने अवतल पतवार की कार्यक्षमता का उपयोग करते हुए देखा, लेकिन यह वास्तव में वैसा नहीं था जैसा मैं चाहता था।
एक त्वरित सुधार के रूप में मैंने उत्तल पतवार को बदल दिया है ताकि वोरोनोई किनारों के बंद सेट और मूल किनारों के चारों ओर एक बफर बनाया जा सके। वोरोनोई किनारों जो बंद नहीं होते हैं, वे कोशिश करने के लिए एक बड़ी दूरी तय करते हैं और सुनिश्चित करते हैं कि वे बाहरी को पार करते हैं और पॉलीगॉन बनाने के लिए उपयोग किए जाते हैं। आप बफ़र मापदंडों के साथ खेलना चाहते हैं।

WITH 
    -- Sample set of points to work with
    Sample AS (SELECT ST_SetSRID(ST_Union(geom), 0) geom FROM MeshPoints2d),
    -- 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_SetSRID((ST_Dump(ST_Polygonize(ST_Node(ST_LineMerge(ST_Union(v, (SELECT ST_ExteriorRing(ST_ConvexHull(ST_Union(ST_Union(ST_Buffer(edge,20),ct)))) FROM Edges))))))).geom, 2180) geom
INTO voronoi
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)) * 200),ST_Y(x.ct) + ((ST_Y(ST_Centroid(x.edge)) - ST_Y(x.ct)) * 200))
            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;

स्पष्टीकरण के लिए धन्यवाद और समस्या के लिए त्वरित समाधान! यह मेरे डेटा (थोड़ा धीमा होने के कारण ST_Union(ST_Buffer(geom))) के साथ काम करता है , लेकिन मैं अन्य बिंदुओं के साथ परीक्षण जारी रखूंगा । इस बीच मैं इंतजार करूंगा जैसा कि आपने कहा - अधिक सामान्य समाधान। :)
डेमनबैक

क्या आपके पास एक छवि है जिसे आप अपने अंतिम आउटपुट पर पोस्ट कर सकते हैं?
जेरिल कुक

10

@ LR1234567 द्वारा नई ST_Voronoi कार्यक्षमता को आज़माने के लिए एक सुझाव के बाद , जो @dbaston, @MickyT के मूल अद्भुत उत्तर (जैसा कि ओपी के प्रश्न में कहा गया है) द्वारा विकसित किया गया है और मूल डेटा का उपयोग करके अब इसे सरल बनाया जा सकता है:

WITH voronoi (vor) AS 
     (SELECT ST_Dump(ST_Voronoi(ST_Collect(geom))) FROM meshpoints)
SELECT (vor).path, (vor).geom FROM voronoi;

ओपी के सवाल के समान, इस आउटपुट में यह परिणाम है।

यहाँ छवि विवरण दर्ज करें

हालांकि, यह उसी मुद्दे से ग्रस्त है, जो अब मिकी के जवाब में तय किया गया है, कि अवतल पतवार पर अंक एक संलग्न बहुभुज नहीं मिलते हैं (जैसा कि एल्गोरिदम से उम्मीद की जाएगी)। मैंने चरणों की निम्नलिखित श्रृंखला के साथ एक प्रश्न के साथ इस मुद्दे को तय किया।

  1. इनपुट बिंदुओं के अवतल पतवार की गणना करें - अवतल पतवार पर बिंदु वे हैं जो आउटपुट वोरोनोई आरेख में अनबाउंड पॉलीगॉन हैं।
  2. अवतल पतवार पर मूल बिंदुओं का पता लगाएं (नीचे चित्र 2 में पीले बिंदु)।
  3. अवतल पतवार बफर (बफर दूरी मनमाना है और शायद इनपुट डेटा से अधिक बेहतर रूप से पाया जा सकता है?)।
  4. चरण 2 में निकटतम बिंदु के समीप पतवार के बफर पर निकटतम बिंदुओं का पता लगाएं। ये नीचे आरेख में हरे रंग के रूप में दिखाए जाते हैं।
  5. इन बिंदुओं को मूल डेटा सेट में जोड़ें
  6. इस संयुक्त डेटा सेट के वोरोनोई आरेख की गणना करें। जैसा कि तीसरे आरेख में देखा जा सकता है, पतवार के बिंदुओं में बहुभुज हैं।

चित्र 2 अवतल पतवार (पीला) पर अंक दिखा रहा है और पतवार (हरा) पर बफर के निकटतम अंक। आरेख 2।

क्वेरी को स्पष्ट रूप से सरल / संपीड़ित किया जा सकता है, लेकिन मैंने इसे छोड़ दिया यह CTE की एक श्रृंखला के रूप में है, क्योंकि इस तरह से चरणों का पालन करना आसान है। यह क्वेरी मिलीसेकंड में सेट किए गए मूल डेटा (एक देव सर्वर पर 11ms औसत) पर चलती है जबकि मिकीट का ST_Delauney का उपयोग करके एक ही सर्वर पर 4800ms में चलता है। DBaston का दावा है कि त्रिकोणीय दिनचर्या में वृद्धि के कारण, GEOS, 3.6देव के वर्तमान ट्रंक के खिलाफ भवन से गति बढ़ाने का एक और आदेश प्राप्त किया जा सकता है।

WITH 
  conv_hull(geom) AS 
        (SELECT ST_Concavehull(ST_Union(geom), 1) FROM meshpoints), 
  edge_points(points) AS 
        (SELECT mp.geom FROM meshpoints mp, conv_hull ch 
        WHERE ST_Touches(ch.geom, mp.geom)), 
  buffered_points(geom) AS
        (SELECT ST_Buffer(geom, 100) as geom FROM conv_hull),
  closest_points(points) AS
        (SELECT 
              ST_Closestpoint(
                   ST_Exteriorring(bp.geom), ep.points) as points,
             ep.points as epoints 
         FROM buffered_points bp, edge_points ep),
  combined_points(points) AS
        (SELECT points FROM closest_points 
        UNION SELECT geom FROM meshpoints),
  voronoi (vor) AS 
       (SELECT 
            ST_Dump(
                  ST_Voronoi(
                    ST_Collect(points))) as geom 
        FROM combined_points)
 SELECT 
     (vor).path[1] as id, 
     (vor).geom 
 FROM voronoi;

आरेख 3 जो अब एक बहुभुज में संलग्न सभी बिंदुओं को दिखा रहा है आरेख ३

नोट: वर्तमान में ST_Voronoi में स्रोत (संस्करण 2.3, या ट्रंक) से पोस्टगिस का निर्माण और GEOS 3.5 या इसके बाद के संस्करण के साथ लिंक करना शामिल है।

संपादित करें: मैंने अभी-अभी Postgis 2.3 को देखा है क्योंकि यह Amazon Web Services पर स्थापित है, और ऐसा लगता है कि फ़ंक्शन का नाम अब ST_VoronoiPolygons है।

कोई शक नहीं कि इस क्वेरी / एल्गोरिथ्म में सुधार नहीं किया जा सकता है। सुझावों का स्वागत करते हैं।


@dbaston। आश्चर्य है कि क्या आपके पास इस दृष्टिकोण पर कोई टिप्पणी है?
जॉन पॉवेल

1
ठीक है, सभी बिंदुओं को एक बहुभुज मिलता है, यह सिर्फ इतना है कि यह बहुत बड़ा है। यदि और इन्हें कैसे छोटा किया जाना चाहिए, तो यह बहुत ही व्यक्तिपरक है, और बाहरी पॉलीगनों के लिए वास्तव में क्या वांछित है, यह जानने के बिना यह जानना मुश्किल है कि "सबसे अच्छा" तरीका क्या है। तुम्हारा होना मेरे लिए एक अच्छा तरीका है। मैंने एक कम परिष्कृत विधि का उपयोग किया है जो आपके लिए आत्मा के समान है, एवीजी बिंदु घनत्व द्वारा निर्धारित एक निश्चित रिक्ति पर एक बफ़र उत्तल पतवार सीमा के साथ अतिरिक्त बिंदुओं को छोड़ देता है।
dbaston

@dbaston। धन्यवाद, बस यह सुनिश्चित कर रहा हूं कि मैं कुछ स्पष्ट याद नहीं कर रहा था। बाहरी बहुभुज को सिकोड़ने के लिए एक एल्गोरिथ्म आंतरिक लोगों के आकार के अनुरूप (मेरे मामले में पोस्टकोड क्षेत्रों में) कुछ ऐसा है जिसके बारे में मुझे कुछ और सोचना होगा।
जॉन पॉवेल

@ जॉन बरका एक और महान समाधान के लिए धन्यवाद। गणना की गति इस दृष्टिकोण से संतुष्ट होने से अधिक है। दुर्भाग्य से मैं अपने QGIS प्लगइन के अंदर इस एल्गोरिथ्म का उपयोग करना चाहूंगा, और इसे PostGIS 2.1+ बॉक्स से बाहर काम करना होगा। लेकिन निश्चित रूप से मैं इस समाधान का उपयोग PostGIS 2.3 आधिकारिक रिलीज के बाद करूंगा। वैसे भी इस तरह के व्यापक जवाब के लिए धन्यवाद। :)
दामनबैक

@DamnBack। तुम्हारा बहुत स्वागत है। मुझे काम के लिए इसकी आवश्यकता थी और आपके प्रश्न ने वास्तव में मेरी बहुत मदद की, क्योंकि मुझे ST_Voronoi के बारे में कोई पता नहीं था, और पुराने समाधान बहुत धीमे हैं (जैसा कि आपने देखा है)। यह मजेदार था यह भी पता लगाना :-)
जॉन पॉवेल

3

यदि आपके पास PostGIS 2.3 तक पहुँच है, तो नया ST_Voronoi फ़ंक्शन दें, हाल ही में प्रतिबद्ध:

http://postgis.net/docs/manual-dev/ST_Voronoi.html

खिड़कियों के लिए पूर्वनिर्मित बिल्ड हैं - http://postgis.net/windows_downloads/


इस जानकारी के लिए धन्यवाद कि इसमें अंतर्निहित ST_Voronoi फ़ंक्शन है - मैं इसे देखूंगा। दुर्भाग्य से मुझे समाधान की आवश्यकता है जो PostGIS 2.1+ संस्करणों पर काम करता है, इसलिए @MickyT क्वेरी फिलहाल मेरी जरूरतों के सबसे करीब है।
डेमनबैक

@ LR1234567। क्या इसके लिए GEOS के किसी विशेष संस्करण की आवश्यकता है। मेरे पास कल 2.3 और ST_Voronoi का परीक्षण करने का समय है।
जॉन पॉवेल

GEOS 3.5
LR1234567
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.