การวิเคราะห์รูปหลายเหลี่ยม PostGIS (การวางแนวความยาวขอบ)


9

ฉันค่อนข้างใหม่ในโลกของ GIS และโดยเฉพาะอย่างยิ่ง PostGIS ดังนั้นโปรดขอโทษด้วยถ้าคำตอบดูเหมือนชัดเจน ...

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

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

ตารางผลลัพธ์อาจมีลักษณะเช่นนี้:

building_id | edge_id | orientation | edge_length
-------------------------------------------------
      1     |    1    |     315     |    10.0
      1     |    2    |      45     |     7.0
      1     |   ...   |     ...     |     ...

อย่างไรก็ตามฉันไม่แน่ใจว่ามันเป็นวิธีที่ฉลาดในการจัดเก็บผลลัพธ์เพื่อการประมวลผลเพิ่มเติม (เช่นคำนวณระยะทางจากขอบไปยังอาคารถัดไป ฯลฯ ) ดังนั้นคำถามของฉันคือสองเท่า:

  1. มีฟังก์ชัน PostGIS ที่มีประสิทธิภาพที่สามารถวิเคราะห์ขอบของรูปหลายเหลี่ยมได้หรือไม่ ในกรณีที่ไม่มีฟังก์ชั่นดั้งเดิมของ PostGIS ฉันอาจจะสนใจวิธีการแบบ Python
  2. อะไรจะเป็นวิธีที่ชาญฉลาดในการจัดเก็บผลลัพธ์ในตาราง PostGIS เนื่องจากรูปหลายเหลี่ยมอาจมีจำนวนขอบที่แตกต่างกัน

2
ขั้นแรกให้สร้างกลุ่มของรูปหลายเหลี่ยม: stackoverflow.com/questions/7595635/…จากนั้นจุดเริ่มต้นและจุดสิ้นสุดพิกัดควรไปที่คอลัมน์เช่น x1, y1 และ x2, y2 และกว่า ST_Azimuth (ST_Startpoint (รูปทรงเรขาคณิต), ST_Endpoint (รูปทรงเรขาคณิต)) . ( postgis.org/docs/ST_Azimuth.html )
Tamas Kosa

1
@ TamasKosa: คุณมีคำตอบที่ดี ทำไมไม่ขยายมันเป็นที่เดียว? นอกจากนี้สำหรับค่าเฉลี่ยอะซิมุ ธ ต้องใช้ +/- pi / 2
Martin F

1
@ TamasKosa นี่เป็นวิธีที่ฉันคิดเช่นกัน ใช้ST_ExteriorRingแล้วรับ azimuths ตามที่คุณพูด ฉันจะเก็บผลลัพธ์อย่างดีเลิศได้อย่างไรเนื่องจากอาคารสามารถมีจำนวนขอบที่แตกต่างกันได้ ในตารางเช่นฉันอธิบายไว้ข้างต้น? ฉันเห็นด้วยกับ MartinF นี่เป็นคำตอบเกือบ)
n1000

แค่อยากรู้ว่าทำไมคุณถึงต้องการ normals ... การสัมผัสกับแสงแดด?
Martin F

1
ส่วนแรกของคำถามของคุณได้รับคำตอบแล้วคุณสามารถใช้ ST_Dumppoints และ ST_Azimuth สำหรับส่วนที่สองเนื่องจากไม่มีองค์ประกอบเชิงพื้นที่ไปยังเอาต์พุตฉันจะคิดว่าลิงก์ไปยังรูปหลายเหลี่ยมและ edge_id ตามที่คุณจะได้พบ
John Powell

คำตอบ:


10

เมื่อวานนี้ฉันไม่มีเวลาสร้างรายละเอียด ... ดูโซลูชันของฉันใน 4 ขั้นตอน:

CREATE OR REPLACE VIEW bd_segment AS
SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) AS sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) AS ep
    FROM
       -- extract the individual linestrings
       (SELECT (ST_Dump(ST_Boundary(the_geom))).geom
       FROM bd) AS linestrings;

CREATE OR REPLACE VIEW bd_segment_geom AS
SELECT sp, ep, st_makeline(sp, ep) 
FROM bd_segment;

CREATE OR REPLACE view bd_segment_id AS 
SELECT bd.gid, row_number() 
    OVER (order by bd.gid), degrees(st_azimuth(ff.sp, ff.ep)-1.57079633) AS az_deg,
    ST_LENGTH(ff.st_makeline) , ff.st_makeline FROM bd_segment_geom ff
JOIN bd ON st_touches(ff.st_makeline, bd.the_geom)
GROUP BY bd.gid, ff.sp, ff.ep, ff.st_makeline;

UPDATE bd_segment_id
SET az_deg = az_deg + 360
WHERE az_deg < 0;

ข้อความค้นหาสุดท้ายให้รหัสอาคารกับการเข้าร่วมเชิงพื้นที่โดยใช้ st_touches หวังว่ามันจะช่วย อัปเดต - ใน qgis โซลูชันจะมีลักษณะดังนี้: ป้อนคำอธิบายรูปภาพที่นี่


1
ที่น่าประทับใจ! ฉันได้มันไปทำงาน ขอบคุณมาก! มันจะช้าไปหน่อยด้วยอาคารจำนวนมาก azimuths ไม่ใช่บรรทัดฐานตอนนี้ คุณยังมีความคิดว่าจะจัดการกับมันอย่างไร? ฉันไม่แน่ใจว่าจะหาด้าน "ภายนอก" ของรูปหลายเหลี่ยมได้อย่างไร
n1000

1
เพิ่ม 90 deggrees ไปยัง azimuth เป็นเรเดียนเช่นนี้องศา (st_azimuth (ff.sp, ff.ep) +1.57079633) มันจะสร้างบางครั้งค่าที่มากกว่า 360 แต่ด้วยคิวรีอัปเดตคุณสามารถแทนที่ค่าเหล่านั้นได้ หากคุณต้องการใช้เป็นมุมมองแบบคงที่ให้สร้าง "CREAT MATERIALIZED VIEW" และจะไม่ช้าในครั้งแรก
Tamas Kosa

2
ไม่มาก สมมติว่าทิศเหนือคือ 0 °สิ่งนี้จะให้ค่าปกติไปทางด้านในของรูปหลายเหลี่ยม / สิ่งปลูกสร้าง (ดังที่เห็นในภาพหน้าจอของคุณ) แต่คุณถูกต้อง - ง่ายUPDATEควรทำเคล็ดลับ ขอบคุณอีกครั้งสำหรับวิธีแก้ปัญหาที่ยอดเยี่ยมนี้ ฉันจะรออีกหลายวันถ้ามีคำตอบอื่นปรากฏขึ้นก่อนที่จะยอมรับ
n1000

1
เกี่ยวกับST_ForceRHRอะไร คำตอบนี้ดูเหมือนจะไม่เป็นไร
Jakub Kania

@JakubKania ฉันพยายามหาST_ForceRHRวิธีแก้ปัญหา แต่ก็ไม่ประสบความสำเร็จ จะขอบคุณสำหรับคำแนะนำ ... ฉันลองST_Dump(ST_Boundary(ST_ForceRHR(the_geom)))
n1000
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.