เพิ่มประสิทธิภาพการคำนวณเพื่อนบ้านที่ใกล้ที่สุดโดยใช้ PostGIS


13

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

จนถึงตอนนี้ฉันได้รับความช่วยเหลืออย่างมากจากคำตอบของ Mike Toews (ซึ่งฉันพูดด้วยการเปลี่ยนแปลงเล็กน้อย) ที่นี่:

SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM 
  public."TestArea" AS a, public."TestArea" AS b
WHERE
  a.hgt !=  b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400

จากนั้นฉันคำนวณขั้นต่ำ:

SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt

อย่างไรก็ตามความท้าทายของฉันคือการคำนวณสิ่งนี้สำหรับรูปหลายเหลี่ยมจำนวนมาก (1,000,000) เนื่องจากการคำนวณข้างต้นเปรียบเทียบแต่ละรูปหลายเหลี่ยมกับรูปหลายเหลี่ยมอื่น ๆ ฉันสงสัยว่าฉันจะปรับปรุงการคำนวณได้อย่างไรเพื่อที่ฉันจะได้ไม่ต้องทำการคำนวณ 10 ^ 12

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


แก้ไข: ใช้หนึ่งในคำแนะนำของ Nicklas ฉันกำลังทดลองกับST_Dwithin():

CREATE TABLE mytable_withinRange AS SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_DWithin(a.the_geom, b.the_geom, 400)
FROM 
  public."lon_TestArea" AS a, public."lon_TestArea" AS b

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

ส่งคืนตาราง ID ของแต่ละรูปหลายเหลี่ยมและไม่ว่าจะอยู่ในระยะที่กำหนดหรือไม่ เป็นไปได้หรือไม่ที่จะสร้างIF/ELSEคำสั่ง type โดยใช้ SQL? (ฉันอ่านเกี่ยวกับการใช้CASEเงื่อนไข) หรือฉันควรลองเข้าร่วมตารางที่ฉันผลิตไปยังตารางเดิมแล้วเรียกใช้แบบสอบถามอีกครั้งโดยใช้ ST_Distance?


ลองดูตัวอย่างที่สองในลิงค์ boston gis ในคำตอบของฉัน คุณควรใช้ st_dwithin ในส่วนของการสืบค้น
Nicklas Avén

คำตอบ:


7

มีขนาดใหญ่เป็นส่วน "เพื่อนบ้านที่ใกล้ที่สุด" บนหน้า


แก้ไข:

เกี่ยวกับ

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

เกี่ยวกับคำสั่ง CASE :

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

คุณรู้หรือไม่ว่าเส้นWHERE ST_DWithin(a.the_geom, b.the_geom, 400)จะป้องกันระยะทางที่มากกว่านั้น400เพื่อคำนวณหรือบันทึก? นอกจากนี้สามารถใช้คำสั่ง case สำหรับการคำนวณเชิงตัวเลขได้หรือไม่? ตัวอย่างเช่น:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
djq

1
@celenius หากระยะทางมากกว่า 400 ม. จะไม่มีการคำนวณอะไรในส่วนที่เลือก ฉันไม่เข้าใจว่าทำไมคุณถึงต้องการรวมเคส
Nicklas Avén

@Nicklas ตกลง - ฉันเข้าใจ ฉันคิดว่ามันอาจหมายถึงว่าเก็บระยะทางน้อยกว่า 400 เท่านั้น มันทำให้ง่ายกว่าที่ฉันคิดไว้มาก ขอบคุณ!
djq

3

สวัสดี

มีบางสิ่งที่ควรพิจารณาเพื่อทำให้สิ่งต่าง ๆ เคลื่อนที่เร็วขึ้นและบางสิ่งที่อาจเป็นไปได้ในอนาคต

ก่อนอื่นคุณกล่าวว่าคุณกำลังพิจารณาใช้บัฟเฟอร์เพื่อค้นหารูปหลายเหลี่ยมในช่วงต่ำสุดเพื่อหลีกเลี่ยงการคำนวณชุดค่าผสมทั้งหมด

ตามที่กล่าวไว้ในการเชื่อมโยงจากที่อื่นบอสตัน GISวิธีการที่เหมาะสมที่จะทำใน PostGIS ใช้ST_Dwithin ST_Dwithin ใช้ดัชนีเพื่อค้นหาเพื่อนบ้านในช่วงที่กำหนด

มันขึ้นอยู่กับชุดข้อมูลของหลักสูตรถ้ามันเพียงพอที่จะใช้ค่าคงที่สำหรับ st_DWithin สำหรับรูปหลายเหลี่ยมทั้งหมดหรือถ้าคุณต้องการทำอะไรบางอย่างเช่น underdark และ wildintellect กำลังคุยกันอยู่

สิ่งที่สองคือการใช้ PostGIS 1.5+ ที่นี่ นั่นเป็นเพราะการคำนวณรูปหลายเหลี่ยมกับรูปหลายเหลี่ยมนั้นเร็วกว่ามากตั้งแต่ 1.5 หากกล่องที่มีขอบเขตไม่ได้ตัดกัน คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ที่นี่ .

สิ่งที่สามที่พูดถึงคืออนาคต

ใน PostgreSQL 9.1 จะมีบางสิ่งที่เรียกว่า knn-gist นั่นคือดัชนีที่ไม่เพียง แต่ตอบใช่หรือไม่ใช่ แต่ยังส่งคืนผลลัพธ์ที่สั่งซื้อโดยตรงจากดัชนี คุณสามารถอ่านเกี่ยวกับที่นี่

แต่จะยังมีงานอีกมากที่ต้องทำในด้าน PostGIS ก่อนที่ผู้มีความรู้จะช่วยสิ่งนี้ มีตั๋วสำหรับที่นี่

ความนับถือ

Nicklas


ขอบคุณสำหรับคำแนะนำ Nicklas; เนื่องจากฉันพบว่ามันยากที่จะทำให้ pgAdmin / PostGIS เริ่มทำงานฉันคิดว่าฉันจะหลีกเลี่ยงการใช้ 1.5 ในขณะนี้ ดูเหมือนว่า ST_Dwithin () เป็นวิธีการแก้ปัญหานี้
djq

2
การติดตั้ง 1.5 จะไม่ส่งผลกระทบต่อความสัมพันธ์ระหว่าง postgresql และ pgadmin คุณสามารถมี postgis ได้มากกว่าหนึ่งรุ่นในเซิร์ฟเวอร์ฐานข้อมูลและจากนั้นคุณสามารถโหลดหนึ่งในฐานข้อมูล เพื่อให้คุณสามารถมีหนึ่งฐานข้อมูล 1.4 และหนึ่ง 1.5 ฐานข้อมูลหนึ่งเซิร์ฟเวอร์ฐานข้อมูลเดียวกัน
Nicklas Avén

1

หน้าต่อไปนี้เกี่ยวข้องกับงานของอาจารย์นาธานเคอร์ให้ข้อมูลเชิงลึกที่ดีเกี่ยวกับปัญหาโดยตรงนี้ เพื่อนร่วมงานของฉันลองใช้วิธี Bostongis ที่นี่และที่นี่แต่มีปัญหาบางอย่างทำให้ทำงานได้อย่างถูกต้อง

วิธีคิดอีกอย่างที่คล้ายกับบัฟเฟอร์คือทำสี่เหลี่ยมผืนผ้าขยาย / ทำสัญญา โดยทั่วไปผ่าน 1 ทำกล่อง bounding (เป็นหน่วย + x ตรงไปยัง bbox ของรูปหลายเหลี่ยมเดิม) ตัดกันที่คุณคิดว่าจะจับอย่างน้อยหนึ่งจุดตัด สำหรับข้อมูลที่มีจุดตัดทำแบบสอบถามย่อยที่ทดสอบตรงกับที่ใกล้เคียงที่สุด สำหรับข้อมูลล้มเหลวในการจับคู่ขยายกล่องขอบเขตและทำซ้ำ

เห็นได้ชัดว่าเป็นปัญหาการเขียนโปรแกรมแบบเรียกซ้ำและอาจทำได้ดีกว่าใน Python ที่มีรูปร่างสูงกว่า 100% ในโพสต์กิสโดยตรง

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