أكثر

قم بإنشاء فسيفساء مثل مخطط فورونوي من المضلعات المنفصلة


يوضح الرسم التوضيحي أدناه المشكلة:

مثل (أ) لدي مجموعة من المضلعات المنفصلة ، مثل الأشكال الهندسية في PostGIS. أنا بحاجة إلى شيء مثل (ب)، فإن "فسيفساء" هذه المجموعة من المضلعات ، يتم بناؤها وفقًا لمعايير "منطقة التأثير" ... تشبه بناء Voronoi (موضحة بواسطة (ج)): في الواقع ، إذا كانت المضلعات عبارة عن نقاط ، فإن مناطق التأثير هي Voronoi.

التلخيص: أحتاج إلى ملف خوارزمية SQL (أو خوارزمية خاصة بـ PostGIS) تقوم بإنشاء "فسيفساء" لمجموعة من المضلعات المنفصلة. (ربما حلقة من عمليات ST_Buffer و ST_Difference الصغيرة)

ملاحظة: أحتاج ، مثل Voronoi's ، إلى تحديد المساحة (إطار مربع في (ب)) تم تجاهله.


هذه المشكلة مشابهة لتلك المتعلقة بالخطوط.

تحرير (بعد تعليقFelixIP)

أنا أفضل البقاء في المتجه الكون ، حتى لا تفقد الدقة (على سبيل المثال ، استخدام ST_DelaunayTriangles وإضافة وطرح التصميمات الداخلية بواسطة المضلعات الأصلية ، فهي تتكيف مع حل رسم بياني مزدوج) ... بعض الحزم البسيطة والآلية مثل pprepair (المساعدة مثل أدوات QGIS الطوبولوجية ليست تلقائية). لكن النقطية ربما يكون أبسط وأقل استهلاكًا لوحدة المعالجة المركزية.

هذا التوضيح "عملية GRID" صالح أيضًا كحل ، على افتراض أنه يمكن أن يسمح بنفس الدقة و "نمو منطقة التأثير الإقليدي".

يوجد في ARCGIS أداة تحليل مكاني تُعرف باسم Euclidean Allocation ، لذلك ، ربما يوجد حل مشابه لـ PostGIS ، بدءًا من مجموعة المضلعات (تصنيف المضلعات وتنقيطها وإعادة تكوينها).


لذلك ، سأقوم بإعداد كعكة لك - طبق فاكهة ، باستخدام أدوات PostGIS ، كما طلبت ، إذا فهمت السؤال بشكل صحيح ، وكما ذكرت ، يتحمل فريقها الإبداعي مسؤولية تشغيل فرن PostGIS.

سأطلب ألا يضايقني أي شخص بأسلوبي الفكاهي وأن أفهمه كلعبة!

الملف الأصلي عبارة عن فاكهة مقطعة وأشكال بسيطة (يشار إليها فيما يلي باسم الفاكهة) ، انظر الشكل 1 أدناه.

هذه هي الوصفة الخاصة بي ، وسوف يساعدني المبرمجون الأعزاء في ذلك ، والذين ستتعرف عليهم لاحقًا. لنبدأ ، ولهذا سننشئ عجينة نضع فيها ثمارنا ، والتي من أجلها يتم تشغيل النص:

إنشاء جدول poly_extent كـ SELECT ST_SetSRID (ST_Buffer (ST_Envelope (ST_Extent (geom)) ، 0.05) ، 4326) كـ geom FROM poly ؛

انظر النتيجة في الشكل 2 أدناه

الآن ، إذا كان هناك عدد قليل من الفواكه ، كما في صورتي ، فقم بإنشاء حدود المخزن المؤقت الخارجي على الفاكهة ، أو إذا كان هناك العديد من الفواكه ، فقم بإنشاء حدود المخزن المؤقت السلبي ، حيث يتم تشغيل البرنامج النصي:

قم بإنشاء جدول poly_buff_dump كـ SELECT ((ST_Dump (ST_Boundary (ST_Union (ST_Buffer ((geom) ، 0.01 ، 'Join = mitre mitre_limit = 5.0'))))). geom) geom FROM poly ؛

وقم بتقطيع الخطوط العازلة حول كل فاكهة

UPDATE poly_buff_dump SET geom = ST_RemovePoint (geom، ST_NPoints (geom) -1) WHERE ST_IsClosed (geom) = true ؛انظر النتيجة في الشكل 3 أدناه

(في الواقع ، اعتقدت أنه نتيجة لذلك سأحصل على خطوط متقطعة (مثل الدائرة) ، ولكن إذا كانت الأرقام صعبة ، في بعض الأحيان يتم الحصول على فواصل ، أو غير صحيحة ، على سبيل المثال ، سقط جانب واحد من المستطيل ، إلخ )

ثم تحتاج إلى تقسيم الخطوط التي تم الحصول عليها بطريقة مناسبة لك إلى مقاطع متساوية واستخراج النقاط منها

إنشاء جدول poly_buff_dump_pt كـ SELECT (ST_DumpPoints ((geom))). geom geom FROM poly_buff_segm ؛

النتيجة ، انظر الشكل 4 أدناه

الآن قم بتشغيل أداة Voronoi ، في هذا المكان استخدمت الأداة التي اقترحها الرابط MickyT: https: //gis.stackexchange.com/a/172246/120129 ، ونتيجة لذلك ستكون قد أنشأت جداول بالاسم "voronoi "لحقيقة أن" مساعدي الأول "منفصل عن الشيف ، شكرًا من الشيف! :-).

الطريقة الثانية في هذه الخطوة هي تشغيل وظيفة ST_VoronoiPolygons.

النتيجة ، انظر الشكل 5 أدناه

الآن ، قم بقطع الأجزاء الإضافية عن طريق تشغيل البرنامج النصي:

إنشاء جدول poly_voronoi_cut كـ SELECT ST_Intersection (a.geom، b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects (a.geom، b.geom) ؛النتيجة ، انظر الشكل 6 أدناه.

الآن قم بتشغيل البرنامج النصي لمحاذاة نوع البيانات الجغرافية في LineString:

إنشاء جدول poly_voronoi_dump كـ SELECT (ST_Dump (geom)). geom as geom FROM poly_voronoi_cut ؛والآن سأطلب من "رفيقي الثاني" أن يقوم بواجباتي ويخلط الكيك ويل (جيف - / أ / 785/120129) ، ويسويها في طبقة واحدة ، ولهذا ، شكراً لي على ذلك!

إنشاء جدول poly_overlay_cut AS حدد geom من ST_Dump ((حدد ST_Polygonize (geom) AS geom من (حدد ST_Union (geom) مثل geom من (حدد ST_ExternalRing (geom) AS geom من poly_voronoi_dump) AS خطوط) ؛حان الوقت الآن للذهاب إلى العمل ، حيث أقوم بتشغيل البرنامج النصي:

إنشاء جدول poly_voronoi_union كـ SELECT b.id ، (ST_ConvexHull (ST_Union (a.geom ، b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects (a.geom، b.geom) GROUP BY b.id، a .geom ، b.geom ؛ونص آخر:

إنشاء جدول poly_voronoi_union_area كـ SELECT ST_Union (ST_ConvexHull (ST_BuildArea (geom))) كـ geom FROM poly_voronoi_union GROUP BY id ؛انظر الشكل 7 أدناه

كما ترى في الصورة ، فإن التخفيضات لدينا لها طبقات صغيرة يمكن إزالتها كخيار باستخدام ST_SnapToGrid (أو بطريقة أخرى):

وأخيرًا ، سنقطع فاكهتنا المخبوزة من فطيرتنا ، حتى أنني تعبت قليلاً من الوقوف بجانب الفرن ، :-)

إنشاء جدول polygon_voronoi_result كـ SELECT (ST_Dump (ST_Difference (a.geom، b.geom))).النتيجة انظر الشكل 8

كل شيء منذ هذا اليوم ، الآن سيتعلم الجميع خبز فطائر لذيذة - طبق من الفاكهة. ساعد نفسك جميعًا ، واختر القطع التي تناسب الجميع.

(إنه لأمر مؤسف أنني لا أستطيع إطعام جميع الناس ، ليس بالكعك الإلكتروني ، ولكن بالكعك الحقيقي ، ربما ينتهي الجوع على الأرض ...)

يحرر: يمكن أن يبدو الكرز الموجود على الفطيرة كما يلي :-):

مع tbla AS (SELECT (ST_DumpPoints (geom)). geom geom FROM poly) ، tblb AS (SELECT ((ST_Dump (ST_VoronoiPolygons (ST_Collect (geom)))). geom) geom FROM tbla) ، tblc AS (SELECT ST_Intersection (a .geom، b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects (a.geom، b.geom))، tbld AS (SELECT id، ((ST_Dump (geom)). geom) geom FROM poly GROUP BY id، geom) SELECT id، ST_Union (a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects (a.geom، b.geom) GROUP BY id؛

أو

مع tbla AS (SELECT (ST_DumpPoints (geom)). geom geom FROM polygons) ، tblb AS (SELECT ((ST_Dump (ST_VoronoiPolygons (ST_Collect (geom)))). geom) geom FROM tbla) ، tblc AS (SELECT id ، ( (ST_Dump (geom)). geom) geom من المضلعات GROUP BY id ، geom) معرف التحديد ، ST_Union (a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects (a.geom ، b.geom) GROUP BY id ؛

مراجعة البرنامج النصي 01.04.2020:

مع tbla AS (مع atbl AS (معرف التحديد ، (ST_ExternalRing (((ST_Dump (geom)). geom))) geom FROM polygons) ، الفواصل الزمنية AS (SELECT create_series (0 ، 501) كخطوات) حدد الخطوات AS stp ، ST_LineInterpolatePoint (geom، steps / (SELECT count (steps) :: float-1 من الفواصل الزمنية)) geom FROM atbl ، والفترات GROUP BY id ، والفواصل الزمنية ، والخطوات ، و geom) ، و tblb AS (SELECT ((ST_Dump (ST_VoronoiPolygons (ST_Collect (geom) ))). geom) geom FROM tbla)، tblc AS (SELECT id، ((ST_Dump (geom)). geom) geom FROM polygons GROUP BY id، geom) SELECT id، ST_Union (a.geom) geom from tblb a JOIN tblc b ON ST_Intersects (a.geom، b.geom) GROUP BY id؛

معكم حسن وعادلا سيد بيكر شكرا لكم جميعا ونتمنى لك التوفيق :-) ...

الحلول الأصلية.

يسمى هذا البرنامج النصي: ST_VoronoiDiagramsFromPolygons.

يحرر:

قد تبدو وظيفة SQL على هذا النحو في الوقت الحالي وفقط لجدول واحد ومجموعة بيانات صغيرة !!!

إنشاء أو استبدال FUNCTION ST_VoronoiDiagramsFromPolygons (geom GEOMETRY ، n عدد صحيح) RETURNS TABLE (id bigint ، geom geomETRY) AS $ BODY $ WITH tbla AS (SELECT row_number () over () AS id ، ((geom geom)). من المضلعات) ، tblb AS (مع btbl AS (معرف التحديد ، ST_ExternalRing ((ST_Dump (geom)). geom) geom من tbla GROUP BY id ، geom) ، والفواصل الزمنية AS (SELECT create_series (0، n) كخطوات) حدد الخطوات AS stp، ST_LineInterpolatePoint (geom، steps / (SELECT count (steps) :: float-1 FROM الفواصل الزمنية)) geom FROM btbl ، الفترات GROUP BY id ، stp ، الفترات الزمنية ، الخطوات ، geom) ، tblc AS (SELECT (ST_Dump (ST_VoronoiPolygons (ST_Collect (geom)))). geom geom FROM tblb) حدد b.id، ST_Union (a.geom) geom FROM tblc a JOIN tbla b ON ST_Intersects (a.geom، b.geom) GROUP BY id؛ $ BODY $ LANGUAGE SQL

يركض

حدد DISTINCT (ST_VoronoiDiagramsFromPolygons (geom ، 300)). * geom من المضلعات ORDER BY id ؛

ربما يومًا ما سيقوم مطورو PostgreSQL و PostGIS بتحديث سلوكهم behavior ...


لا تحتوي Postgis على وظيفة مخصصة لـ voronoi ، ولكن Qgis تحتوي على وظيفة vornoi التي يمكن أن تجعل مضلعات voronoi من النقاط ، لذلك باستخدام qgis ، اتبعت الخطوات التالية للحصول على هذه النتيجة:

-جعل النقاط من استخدام المضلعاتاستخراج العقدالمهام.

-جعل مضلعات vornoi باستخدام دوال voroi في Qgis.

-قم بعمل صلة مكانية في Qgis.

- حل النتائج.


حسنًا - فكرت في هذا قليلاً ووجدت أنه شيء كنت أبحث عنه مؤخرًا.

خذ أعمدة الانطلاق الخاصة بك:

قم بإنشاء سمة جديدة برقم (100 في حالتي) استخدم Vector-> أدوات البحث -> نقاط عشوائية داخل أداة المضلعات التي ستولد (100) نقطة داخل كل مضلع:

ثم Vector-> Geometry tools -> Voronoi لتوليد polys بناءً على تلك الطبقة النقطية.

الآن ، يمكنك استخدام Vector -> Spatial Query tool: حدد النقاط التي تنتمي إلى مضلع واحد (أو أحد المضلعات) استخدم أداة الاستعلام المكاني لإنشاء مجموعة مختارة من مضلعات voronoi التي تنطبق على هذا المضلع. أضف سمة إلى voroni polygon تتوافق مع مضلع الاهتمام. (لقد استخدمت للتو 1،2،3،4)

يمكنك الآن Vector-> أدوات المعالجة الجغرافية-> الذوبان بناءً على السمة الجديدة الخاصة بك.


تعتبر النقاط العشوائية فكرة جيدة لإنشاء مضلع فورونوي من المضلعات ، وهي تعمل بشكل جيد ، لكنها سيئة جدًا للمضلعات القريبة من بعضها البعض:

ST_ApproximateMedialAxis هو بديل جيد آخر في حالة استخدام PostGIS: حساب مخططات Voronoi للمضلعات


لقد قمت بنشر حزمة mini python لعملها - voronoi-diagram-for-polygons. وتجدر الإشارة مقدمًا إلى أن هذه الحزمة تعتمد على الإصدار 1.8.dev0 الذي لا يزال قيد التطوير. بمعنى آخر ، لا يمكن تثبيت تبعية voronoi-diagram-for-polygons بواسطةنقطةتلقائيا. عليك تثبيت أحدث إصدار من Shapely أولاً عن طريق ما يلي:

نقطة تثبيت git + https: //github.com/Toblerity/Shapely.


شاهد الفيديو: احدث انواع الموزاييك للمطابخ والحمامات روعععععة (شهر اكتوبر 2021).