วิธีการคำนวณมุมที่สองบรรทัดตัดกันใน PostGIS


19

ฉันต้องการคำนวณมุมระหว่างสองบรรทัดที่พวกเขาตัดกันใน PostGIS

จุดเริ่มต้นสำหรับการคำนวณมุมใน PostGIS นั้นน่าจะเป็นST_Azimuth - แต่นั่นก็เป็นจุดที่ป้อนเข้า ความคิดแรกของฉันคือการหาจุดสิ้นสุดของเส้นตัดกันและทำการคำนวณแบบอะซิมุ ธ นั่นไม่ดีพอเพราะคุณสมบัติส่วนใหญ่ของเส้นไม่ตรงและฉันสนใจในมุมที่จุดตัด ดังนั้นสิ่งที่ฉันเกิดขึ้นคือการดำเนินการซ้อนกันที่ทำตามขั้นตอนต่อไปนี้:

  1. ระบุจุดแยกทั้งหมดระหว่างตารางคุณลักษณะสองบรรทัด
  2. สร้างบัฟเฟอร์ขนาดเล็กมากรอบ ๆ จุดตัด
  3. ระบุจุดที่คุณสมบัติของเส้นตัดกันด้านนอกของบัฟเฟอร์ (ใช้จุดแรกถ้ามีมากกว่าหนึ่ง - ฉันสนใจเฉพาะจริงๆว่ามุมนั้นใกล้กับ 0, 90 หรือ 180 องศา)
  4. คำนวณ ST_Azimuth สำหรับสองจุดนั้น

SQL แบบเต็มมีความยาวในการโพสต์ที่นี่ แต่ฉัน gisted ที่นี่ถ้าคุณสนใจ (โดยวิธีการมีวิธีที่ดีกว่าที่จะดำเนินการมากกว่าเขตข้อมูลทั้งหมดจะลงงบกับ?)

ผลลัพธ์ไม่ถูกต้องดังนั้นฉันจึงทำสิ่งที่ผิดอย่างชัดเจน:

ตัวอย่างผลลัพธ์ 1 ตัวอย่างผลลัพธ์ 2

แก้ไขฉันเพิ่มการคำนวณใน EPSG ใหม่: 3785 และผลลัพธ์จะแตกต่างกันเล็กน้อย แต่ก็ไม่ถูกต้อง:

เอาต์พุตใน 3785 # 1 เอาต์พุตใน 3785 # 2

คำถามของฉันอยู่ที่ข้อบกพร่องในกระบวนการนี้ ฉันเข้าใจผิดว่า ST_Azimuth ทำอะไรได้บ้าง มีปัญหา CRS หรือไม่ มีอะไรอีกบ้างไหม? หรืออาจจะมีวิธีที่ง่ายกว่านี้มากในการทำเช่นนี้?


1
CRS ดั้งเดิมคืออะไร ควรทำการคำนวณมุมด้วยการฉายตามมาตรฐานไม่ใช่ด้วย lat / unprojected (SRID = 4326)
Mike T

เดิมทีมันคือ EPSG: 4326 พิกัดฉันรวม ST_Translate เพื่อให้แน่ใจว่า 100% การประมวลผลทั้งหมดจะต้องทำใน CRS เดียวกัน ฉันจะลองฉายตามลำดับขอบคุณ
mvexel

ฉันลดการคำนวณเป็น EPSG: 3785 และสร้างความแตกต่าง - ฉันจะแก้ไขคำถามเพื่อแสดงผลลัพธ์ใหม่ - แต่ผลลัพธ์ยังไม่สะท้อนมุมที่แท้จริง
mvexel

คำตอบ:


12

ฉันมีความศักดิ์สิทธิ์ มันค่อนข้างธรรมดา ฉันกำลังปล่อยข้อมูลสำคัญหนึ่งชิ้นสำหรับ PostGIS เพื่อคำนวณมุมที่ถูกต้อง

สิ่งที่ฉันคำนวณคือมุมระหว่างจุดสองจุดที่ตัดกันด้านนอกของบัฟเฟอร์เล็ก ๆ ในการคำนวณมุมของจุดตัดฉันต้องคำนวณมุมทั้งสองระหว่างจุดทั้งสองที่ด้านนอกของบัฟเฟอร์และจุดตัดของคุณลักษณะสองบรรทัดแล้วลบออก

ฉันอัปเดตSQLเต็มรูปแบบแต่นี่คือบิตเด่น

SELECT
    ...
    abs
    (
        round
        (
            degrees
            (
            ST_Azimuth
            (
                points.point2,
                points.intersection
            )
            -
            ST_Azimuth
            (
                points.point1,
                points.intersection
            )
        )::decimal % 180.0
        ,2
    )
)
AS angle
...
FROM
points 

1
ฉันกำลังคิดเกี่ยวกับมุมของจุดบัฟเฟอร์ที่แทรกตัว แต่ฉันไม่มีเวลาพูดถึงรายละเอียด อีกมุมหนึ่งคือหน่วยเชิงมุม คุณต้องคูณผลลัพธ์เป็นเรเดียนจาก ST_Azimuth ด้วย 180.0 / pi () เพื่อให้ได้ผลลัพธ์เป็นองศา
Mike T

ขอบคุณมากฉันใช้ PostgreSQL degrees () ฟังก์ชั่นสำหรับสิ่งนั้น
mvexel

ปังตอ (ผมไม่ได้รู้ว่ามีการทำงานองศาจนถึงขณะนี้.) มันจะดีที่จะห่อทั้งหมดตรรกะนี้ขึ้นมาในการเรียกใช้ฟังก์ชัน แต่ฉันมีปัญหาในการสร้างกรอบความคิดว่ามันจะทำงานเช่นST_IntersectionAngle(...?
Mike T

ฉันแปลกใจจริง ๆ ที่ไม่ใช่ฟังก์ชัน PostGIS ขอบคุณสำหรับความคิดเห็นของคุณเกี่ยวกับเรื่องนี้
mvexel

2

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

เพื่อหาคะแนนพิเศษสำหรับการคำนวณแบบราบฉันเพียงตรวจสอบความยาวด้านหลังสี่แยก (หรือหลังจากนั้นในกรณีที่เกิดขึ้นได้ยากในจุดเริ่มต้นของบรรทัด) โดยใช้ST_Line_Locate_PointและST_Line_Interpolate_Point :

abs(degrees( 
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line1, 
      abs(ST_Line_Locate_Point(line1, intersection) - 0.0001)
    )
  )
  -
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line2, 
      abs(ST_Line_Locate_Point(line2, intersection) - 0.0001)
    )
  )
))

permyriad นั้นเป็นกฎเกณฑ์และเพื่อผลลัพธ์ที่สอดคล้องกันมากขึ้นมันจะดีกว่าถ้าใช้ offset แบบสัมบูรณ์ สำหรับตัวอย่างเช่นตรวจสอบ 20m ล่วงหน้าคุณจะเปลี่ยน 0.0001 เป็น20/ST_Length(line1)และ20/ST_Length(line2)ตามลำดับ

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