สร้างภาพโมเสกเช่น Voronoi Diagram จากรูปหลายเหลี่ยมที่แยกออกจากกัน


12

ภาพประกอบด้านล่างแสดงปัญหา :

ป้อนคำอธิบายรูปภาพที่นี่

ใน(a)ฉันมีชุดของรูปหลายเหลี่ยมที่ไม่ปะติดปะต่อกันเช่นรูปทรงเรขาคณิตใน PostGIS ฉันต้องการสิ่งที่ต้องการ(ข)ที่ "โมเสค"ชุดของรูปหลายเหลี่ยมนี้สร้างมันด้วย "เขตอิทธิพล" เกณฑ์ที่ ... เป็นเหมือนก่อสร้าง Voronoi (แสดงโดย(c) ): ในความเป็นจริงถ้ารูปหลายเหลี่ยมที่ถูก จุดอิทธิพลของภูมิภาคคือ Voronoi

สรุป: ฉันต้องการอัลกอริทึม SQL (หรือบางอย่างเฉพาะสำหรับ PostGIS) ที่สร้าง "โมเสค" ของชุดของรูปหลายเหลี่ยมที่ไม่ปะติดปะต่อกัน (อาจเป็นการวนของการดำเนินการ ST_Buffer และ ST_Difference เล็กน้อย)

PS: ฉันต้องการเช่นเดียวกับของ Voronoi การเว้นวรรคนั้น (กรอบกำลังสองใน(b) ) จะถูกละเว้น


ปัญหานี้คล้ายกับที่เกี่ยวกับบรรทัดนี้

แก้ไข (หลังจากความคิดเห็น @FelixIP)

ฉันต้องการที่จะอยู่ในจักรวาลเวกเตอร์เพื่อไม่ให้สูญเสียความแม่นยำ (เช่นการใช้ST_DelaunayTrianglesและการเพิ่มและลบการตกแต่งภายในด้วยรูปหลายเหลี่ยมดั้งเดิมพวกเขาปรับใช้โซลูชันกราฟคู่ ) ... แพคเกจที่ง่ายและอัตโนมัติเช่นPprepair (ช่วยเหมือนเครื่องมือ QGISไม่อัตโนมัติ) แต่rasterนั้นอาจจะง่ายกว่าและใช้ CPU น้อยกว่า

ภาพประกอบ "กระบวนการ GRID" นี้ยังสามารถใช้เป็นวิธีแก้ปัญหาโดยสมมติว่าสามารถให้ความแม่นยำและ "อิทธิพลแบบยุคลิดที่มีอิทธิพลต่อการเติบโตในภูมิภาค"

ป้อนคำอธิบายรูปภาพที่นี่

ใน ARCGIS มีเครื่องมือการวิเคราะห์เชิงพื้นที่ที่รู้จักกันในชื่อEuclidean Allocationดังนั้นบางทีอาจมีวิธีแก้ปัญหาที่คล้ายกันของ PostGISโดยเริ่มจากกลุ่มรูปหลายเหลี่ยม


ขอบคุณ @Nir ขอโทษด้วยความสับสนกับคะแนนฉันไม่ได้ใช้คะแนนเพียงรูปหลายเหลี่ยมเป็นรายการ(a)และ(b)ของภาพประกอบ ... คุณมีลิงค์ของเบาะแสเกี่ยวกับการแก้ปัญหาหรือไม่?
Peter Krauss

ใน ArcGIS มีทางออกแรสเตอร์ที่เรียกว่าการจัดสรร eucledean หรือใกล้ชิด
FelixIP

ขอบคุณ @ FelixIP ฉันได้แก้ไข "well come raster solutions" ;-)
Peter Krauss

หากคุณลบรูปหลายเหลี่ยมออกจากขอบเขตรูปสามเหลี่ยมคุณจะเหลือรูปหลายเหลี่ยม โครงกระดูกของมันgis.stackexchange.com/questions/177/…เป็นสิ่งที่คุณต้องการฉันเดา การติดตั้งใช้งานเป็นเรื่องใหญ่
FelixIP

1
@Cyril ฉันสามารถตรวจสอบสคริปต์ของคุณ ... สัปดาห์หน้า การโพสต์สิ่งที่ดูเหมือนว่าเป็นทางออกของฟังก์ชั่น PostGIS ที่ทันสมัยจะเป็นก้าวแรกที่ดี
Peter Krauss

คำตอบ:


2

ดังนั้นฉันจะเตรียมเค้กให้กับคุณ - ผลไม้โดยใช้เครื่องมือ PostGIS ตามที่คุณร้องขอถ้าฉันเข้าใจคำถามอย่างถูกต้องและอย่างที่ฉันได้กล่าวถึงความรับผิดชอบในการทำงานของเตาอบ PostGIS นั้นเป็นความรับผิดชอบของทีมงานสร้างสรรค์ของเธอ

ฉันจะขอไม่ให้ใครขุ่นเคืองในสไตล์ที่มีอารมณ์ขันของฉันและเข้าใจว่ามันเป็นเกม!

ไฟล์ต้นฉบับเป็นผลไม้ที่ถูกหั่นและมีรูปทรงที่เรียบง่าย (ต่อไปนี้จะเรียกว่าผลไม้) ดูรูปที่ 1 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือสูตรของฉันและฉันจะได้รับการช่วยเหลือในเรื่องนี้โดยโปรแกรมเมอร์ที่รักซึ่งคุณจะได้เรียนรู้ในภายหลัง มาเริ่มกันเถอะและสำหรับสิ่งนี้เราจะสร้างแป้งสาลีซึ่งจะวางผลไม้ของเราซึ่งใช้สคริปต์:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

ดูผลลัพธ์ในรูปที่ 2 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้ถ้ามีผลไม้น้อยเช่นในรูปภาพของฉันสร้างเส้นขอบของบัฟเฟอร์ภายนอกบนผลไม้หรือถ้ามีผลไม้มากมายให้สร้างเส้นขอบของบัฟเฟอร์ลบซึ่งใช้สคริปต์:

create table poly_buff_dump as 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 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

(อันที่จริงฉันคิดว่าเป็นผลให้ฉันได้รับเส้นแตก (เช่นในวงกลม) แต่ถ้าตัวเลขเป็นเรื่องยากบางครั้งจะได้รับการแบ่งบางครั้งไม่ถูกต้องตัวอย่างเช่นด้านหนึ่งของสี่เหลี่ยมหลุดออกมา ฯลฯ )

จากนั้นคุณต้องแบ่งบรรทัดที่ได้รับในวิธีที่สะดวกสำหรับคุณในส่วนที่เท่ากันและแยกคะแนนจากพวกเขา

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

ผลลัพธ์ดูรูปที่ 4 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้เรียกใช้เครื่องมือ Voronoi ในที่นี้ฉันใช้เครื่องมือที่แนะนำโดยลิงค์ MickyT: /gis//a/172246/120129 เนื่องจากคุณจะสร้างตารางที่มีชื่อ“ voronoi” "สำหรับความจริงที่ว่า" ผู้ช่วยคนแรกของฉัน "แยกจากพ่อครัวขอบคุณจากพ่อครัว! :-)

วิธีที่สองในขั้นตอนนี้คือการเรียกใช้ฟังก์ชัน ST_VoronoiPolygons

ผลลัพธ์ดูรูปที่ 5 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้ให้ตัดส่วนเพิ่มเติมโดยเรียกใช้สคริปต์:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); ผลลัพธ์ดูรูปที่ 6 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้เรียกใช้สคริปต์เพื่อจัดตำแหน่งประเภท geodata ใน LineString:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; และตอนนี้ฉันจะขอให้ "เพื่อนที่สองของฉัน" ทำหน้าที่ของฉันและผสมเค้ก wel (Jeff - /gis//a/785/120129 ) ปรับระดับให้เป็นเลเยอร์เดียวและเพื่อ ขอบคุณฉันมัน!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); ตอนนี้ถึงเวลาที่ฉันจะต้องทำงานแล้วซึ่งฉันจะเรียกใช้สคริปต์:

create table poly_voronoi_union as 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; และสคริปต์อื่น:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; ดูรูปที่ 7 ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ดังที่คุณเห็นในภาพการตัดของเรามีเลเยอร์เล็ก ๆ ซึ่งสามารถลบออกได้เป็นตัวเลือกโดยใช้ ST_SnapToGrid (หรืออีกวิธีหนึ่ง):

และในที่สุดเราจะตัดผลไม้อบออกจากพายของฉันฉันยังรู้สึกเหนื่อยเล็กน้อยที่ยืนอยู่ข้างเตาอบ :-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); ผลลัพธ์ดูรูปที่ 8 ป้อนคำอธิบายรูปภาพที่นี่

ทุกอย่างตั้งแต่วันนี้ตอนนี้ทุกคนจะเรียนรู้ที่จะอบขนมพายแสนอร่อย - ผลไม้ ช่วยตัวเองทุกคนและเลือกชิ้นส่วนที่คุณชอบพอสำหรับทุกคน

(เป็นเรื่องน่าเสียดายที่ฉันไม่สามารถให้อาหารกับทุกคนได้จริง ๆ ไม่ใช่เค้กอิเล็กทรอนิกส์ แต่ด้วยเค้กจริงอาจจะหิวบนโลก ... )

แก้ไข:เชอร์รี่บนพายอาจมีลักษณะเช่นนี้ :-):

WITH
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;

หรือ

WITH
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 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;

แก้ไขสคริปต์ 01.04.2020:

WITH tbla AS (
WITH atbl AS (SELECT id, (ST_ExteriorRing(((ST_Dump(geom)).geom))) geom FROM polygons),
intervals AS (SELECT generate_series (0, 501) as steps)
SELECT steps AS stp, ST_LineInterpolatePoint(geom, steps/(SELECT count(steps)::float-1 FROM intervals)) geom FROM atbl, intervals GROUP BY id, intervals.steps, 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;

กับคุณเป็นคนดีและเป็นธรรม Mr.Baker ขอขอบคุณทุกท่านและขอให้โชคดี: -) ...

โซลูชั่นดั้งเดิม

สคริปต์นี้มีชื่อว่า: ST_VoronoiDiagramsFromPolygons


1
สวัสดีภาพประกอบที่ดีและดูเหมือนผลลัพธ์ที่ดี (!) คำแนะนำสำหรับการสนทนาสั้น ๆ ดู @geogeek solution ขั้นตอนใน QGis ดูเหมือนว่าเป็นขั้นตอนหลักของ PostGIS ที่นี่ ... ทำไมต้อง e ST_BufferและST_ConvexHull? มีอัลกอริธึมทางเลือกหรือไม่?
Peter Krauss

1) ดู ST_Buffer และรูปหลายเหลี่ยมถูกสร้างขึ้นเพื่อลดเส้นแบ่งระหว่างตัวเลขต้นฉบับในระหว่างการใช้งานฟังก์ชั่น Voronoi ดังนั้นขนาดบัฟเฟอร์ที่ใหญ่กว่าที่คุณสามารถระบุได้ยิ่งราบรื่นยิ่งขึ้นสายการแยกจะถูกสร้างขึ้นเป็น ฟังก์ชั่น Voronoi ... 2) ST_ConvexHull จากตัวเลขมากมายในแต่ละรูปหลายเหลี่ยมรูปหลายเหลี่ยมที่เราต้องการ ... 3) วันนี้นี่คือวิสัยทัศน์ของฉันในการแก้ไขคำถามของคุณฉันไม่รู้ว่าจะเกิดอะไรขึ้นกับเราทุกคน และการตัดสินใจของพวกเราในอนาคต ...
Cyril Mikhalchenko

ค่าที่สำคัญอีกอย่างของเส้นบัฟเฟอร์คือพวกมันจะช่วยให้เราเลือกชิ้นส่วนจากผลลัพธ์ของการทำงานของ Voronoi เพื่อสร้างรูปหลายเหลี่ยมรวมสำหรับแต่ละรูปร่าง ...
Cyril Mikhalchenko

โดยวิธีการที่ฉันยินดีต้อนรับการปรับปรุงรหัสและวิธีการเพื่อที่พวกเขาจะไม่เลวลงผลลัพธ์ ...
Cyril Mikhalchenko

1
สวัสดีไซริลฉันเห็นด้วยว่า ST_Buffer เป็นตัวเลือกที่ดีในการทำให้เส้นชั้นความสูงปกติ (!) สมบูรณ์แบบ เกี่ยวกับST_ConvexHullเป็นเพียงความอยากรู้ผลลัพธ์ที่เราจะได้รับหลังจากรูปที่ 6 poly_voronoi_unionโดยไม่มี ST_ConvexHull
Peter Krauss

8

Postgis ไม่มีฟังก์ชันเฉพาะสำหรับ voronoi แต่ Qgis มีฟังก์ชัน vornoi ซึ่งสามารถสร้างรูปหลายเหลี่ยม voronoi จากจุดดังนั้นใช้ qgis ฉันได้ทำตามขั้นตอนต่อไปนี้เพื่อให้ได้ผลลัพธ์เหล่านี้:

ทำให้คะแนนจากรูปหลายเหลี่ยมโดยใช้extract nodesฟังก์ชั่น

ทำให้ vornoi รูปหลายเหลี่ยมโดยใช้ฟังก์ชั่น voroi ใน Qgis

- ทำให้อวกาศเข้าร่วมใน Qgis

- ยุบผลลัพธ์

ป้อนคำอธิบายรูปภาพที่นี่


1
Nice solution (!) และขอบคุณภาพประกอบ คุณสามารถปรับปรุงมันได้หรือไม่ ดูสี่เหลี่ยมผืนผ้าด้านซ้ายด้านล่างมันคือ 4 คะแนนที่ Voronoi และศูนย์กลางของรูปสี่เหลี่ยมผืนผ้าไม่มีตัวแทนการบิดเบือนพื้นที่ของมัน (การสูญเสียเป็นรูปสามเหลี่ยม) ... บางทีการปรับปรุงอาจทำได้โดยการสุ่มตัวอย่างปกติของรูปหลายเหลี่ยมแต่ละรูป ... บางทีก็เป็นจุดภายใน
Peter Krauss

ฉันใช้เครื่องมือ densify ใน ArcGIS สิ่งนี้ช่วยปรับปรุงรูปหลายเหลี่ยมความใกล้เคียงอย่างมีนัยสำคัญ +1
FelixIP

3

ตกลง - คิดเกี่ยวกับเรื่องนี้เล็กน้อยและพบว่ามันเป็นสิ่งที่ฉันได้ดูเมื่อเร็ว ๆ นี้

ใช้ polys เริ่มต้นของคุณ:

ป้อนคำอธิบายรูปภาพที่นี่

สร้างแอตทริบิวต์ใหม่ด้วยตัวเลข (100 ในกรณีของฉัน) ใช้ Vector-> เครื่องมือวิจัย -> คะแนนสุ่มภายในเครื่องมือรูปหลายเหลี่ยมซึ่งจะสร้าง (100) คะแนนภายในแต่ละรูปหลายเหลี่ยม: ป้อนคำอธิบายรูปภาพที่นี่

จากนั้น Vector-> เครื่องมือเรขาคณิต -> Voronoi เพื่อสร้าง polys ตามเลเยอร์จุดนั้น

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้คุณสามารถใช้เครื่องมือ Vector -> Spatial Query: เลือกจุดที่เป็นของรูปหลายเหลี่ยมหนึ่งรูป (หรือรูปหลายเหลี่ยมหนึ่งรูป) ใช้เครื่องมือสอบถามเชิงพื้นที่เพื่อสร้างรูปหลายเหลี่ยม voronoi ซึ่งใช้กับรูปหลายเหลี่ยมนั้น เพิ่มแอตทริบิวต์ให้กับรูปหลายเหลี่ยม voroni ซึ่งสอดคล้องกับรูปหลายเหลี่ยมที่น่าสนใจ (ฉันเพิ่งใช้ 1,2,3,4)

ตอนนี้คุณสามารถ Vector-> Geoprocessing Tools-> ละลายตามคุณสมบัติใหม่ของคุณ

ป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณ @AAmes (!) ภาพประกอบเป็นสิ่งที่ดีและวิธีนี้เป็นทางเลือกที่ดี ... แต่คำถามเกี่ยวกับ "อัลกอริทึม SQL (หรือบางอย่างที่เฉพาะเจาะจงสำหรับ PostGIS)"และตอนนี้ความโปรดปรานเกี่ยวกับการใช้ฟังก์ชั่น ST_VoronoiPolygons ()ที่อาจจะแก้ปัญหาทั้งหมดในคลิกเดียว ;-)
ปีเตอร์อูส

@AAmes การค้นหาอย่างรวดเร็วแสดงให้เห็นว่าวิธีนี้สามารถนำมาใช้ใน PostGIS ได้เช่นกัน วิธีสร้างจุดสุ่มในรูปหลายเหลี่ยมใน postgisอธิบายการสร้างจุดจากรูปหลายเหลี่ยมและจากนั้นจะต้องตรงไปตรงมา
Phil G

เงินรางวัลของฉันคือให้คุณเป็นแรงจูงใจ (ยินดีต้อนรับที่นี่!) แต่คำตอบนี้เป็นคำตอบสำหรับคำถามและความต้องการเงินรางวัล
Peter Krauss

ขอบคุณปีเตอร์ฉันเห็นบันทึกของคุณ แต่น่าเสียดายที่ฉันไม่มีโอกาสกลับมาพูดอีก ฉันยังไม่มีประสบการณ์ใน PostGIS และจะใช้เวลามากกว่าที่ฉันพร้อมให้การตอบรับที่ดี ฉันหวังว่าการสำรวจพื้นที่นี้ของเราจะเป็นประโยชน์ต่อผู้คนในอนาคตบางทีถ้าฉันได้รับรอยแตกที่ PostGIS เร็ว ๆ นี้ฉันจะกลับมาอีกครั้งเพื่อรับการฝึกฝน!
AA

2

คะแนนสุ่มเป็นความคิดที่ดีในการสร้างรูปหลายเหลี่ยม voronoi จากรูปหลายเหลี่ยมมันทำงานได้ค่อนข้างดี แต่มันค่อนข้างดีสำหรับรูปหลายเหลี่ยมที่อยู่ใกล้กัน: ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

ST_ApproximateMedialAxis เป็นอีกทางเลือกที่ดีถ้าใช้ PostGIS: การคำนวณไดอะแกรม Voronoi สำหรับรูปหลายเหลี่ยม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.