ভোরোনাই চিত্রটি নির্মাণ করতে কীভাবে ST_DelaunayTriangles ব্যবহার করবেন?


13

(2019 এডিট করুন) পোস্ট জিআইএস ভি 2.3-এর পর থেকে এসT_ ভারোনাইপলিগনগুলি উপলভ্য !


পোস্টজিআইএস ২.১+ এর সাহায্যে আমরা একটি ডেলাউন ট্রায়াঙ্গুলিটি তৈরি করতে ST_DelaunayTriangles () ব্যবহার করতে পারি , এটি তার ভোরোনাই চিত্রের দ্বৈত গ্রাফ এবং তাত্ত্বিকভাবে তাদের সঠিক এবং বিপরীতমুখী রূপান্তর রয়েছে।

এই পোস্টজিআইএস 2 ডেলাউন-টু-ভোরোনাই রূপান্তরটির জন্য কোনও অনুকূলিত অ্যালগরিদম সহ কোনও নিরাপদ এসকিউএল-স্ট্যান্ডার্ড স্ক্রিপ্ট কি বিদ্যমান ?


অন্যান্য রেফারেন্স: 1 , 2


কি gist.github.com/djq/4714788 জিনিস সাজানোর তোমার পরে কি?
মিকিটি

সে একটি বিশুদ্ধরূপে এসকিউএল ST_DelaunayTriangles ব্যবহার বাস্তবায়ন চায় ()
রাফায়েল

ST_DelaunayTrianglesলিনাক্স ডেবিয়ান স্টেবল ইনস্টল করতে এই উত্তরটি দেখুন
পিটার ক্রাউস

উত্তর:


23

নিম্নলিখিত ক্যোয়ারী ডেলাউন ট্রায়াঙ্গলস থেকে শুরু করে ভোরোনাই বহুভুজগুলির একটি যুক্তিসঙ্গত সেট করে বলে মনে হচ্ছে।

আমি কোনও বড় পোস্টগ্রিজ ব্যবহারকারী নই, তাই সম্ভবত এটি বেশ কিছুটা উন্নত হতে পারে।

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

ধাপ ২

ত্রিভুজ নোডগুলি পচন করুন এবং প্রান্তগুলি তৈরি করা যেতে পারে। আমি মনে করি প্রান্তগুলি পাওয়ার আরও ভাল উপায় হওয়া উচিত, তবে আমি একটিও পাইনি।

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

এখানে চিত্র বর্ণনা লিখুন

Edgesকোটে ত্রিভুজ এটা জন্যে প্রতিটি প্রান্ত এবং আইডি (পথ) আউটপুট।

পদক্ষেপ 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))))))

এখানে চিত্র বর্ণনা লিখুন


ভাল ক্লু, সম্ভবত একটি সমাধান (!)। আমার পরীক্ষা করা দরকার, তবে এখনই পারছি না ... বিশ্লেষণ করা: আপনি আমার রেফ 1 / কেনেথ স্লোয়ার প্রস্তাবিত সরাসরি অ্যালগরিদমের মতো "লম্ব দ্বিখণ্ডক" ব্যবহার করেন ST_ConvexHullএবং এর ST_Centroidপরিবর্তে কেন সরাসরি সমাধান করবেন না?
পিটার ক্রাউস

আমি বেশ কয়েকটি গণিত ছাড়াই বহির্মুখী প্রান্তের জন্য লম্ব দ্বিখণ্ডকগুলি করছি: :) আমি উত্তরে যে পদক্ষেপগুলি নিয়েছি তার একটি ব্যাখ্যা যুক্ত করব
মিকিটি

ভাল চিত্রণ এবং ব্যাখ্যা, খুব যুক্তিযুক্ত!   আপনি আমার যা প্রয়োজন তা সমস্ত পোস্ট করেছেন (!), কিন্তু আজকের দিনে আমার পরীক্ষার জন্য Postgis2.1 নেই ... আমি কি এখানে পরীক্ষার (উত্তর হিসাবে) কিছু প্রশ্নের উত্তর দিতে পারি?   1) এসT_ পোলিগনাইজ "সম্ভাব্য বহুভুজ সমন্বিত একটি জ্যামিতি সংগ্রহ তৈরি করে", সেগুলি কি সব ভোরোনাই কোষ, সঠিক?   ২) পারফরম্যান্স সম্পর্কে, আপনি কি ভাবেন যে আপনার সেন্ট্রয়েড-ভিত্তিক সমাধানের ক্ষেত্রে "লম্ব দ্বিখণ্ডক গণনার সমস্ত গণিত" এর চেয়ে একই সিপিইউ-টাইম রয়েছে?
পিটার ক্রাউস

@ পিটারক্রাস ১) এসT_ পলিগোনাইজ লাইনের কাজ থেকে ভোরোনাই কোষ তৈরি করে। এর সাথে কৌশলটি হ'ল নোডগুলিতে সমস্ত লাইন কাজ বিভক্ত হয়েছে তা নিশ্চিত করা। 2) আমি মনে করি না যে দ্বিখণ্ডার গণনা এবং লাইনে ST_Centroid ব্যবহারের মধ্যে অনেক পার্থক্য থাকবে। তবে এটি পরীক্ষা করা দরকার।
মিকিটি

ST_DelaunayTrianglesলিনাক্স ডেবিয়ান স্টেবলে ইনস্টল করার জন্য এই উত্তরটি দেখুন
পিটার ক্রাউস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.