নিম্নলিখিত ক্যোয়ারী ডেলাউন ট্রায়াঙ্গলস থেকে শুরু করে ভোরোনাই বহুভুজগুলির একটি যুক্তিসঙ্গত সেট করে বলে মনে হচ্ছে।
আমি কোনও বড় পোস্টগ্রিজ ব্যবহারকারী নই, তাই সম্ভবত এটি বেশ কিছুটা উন্নত হতে পারে।
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))))))