การค้นหาจุดสามเหลี่ยมที่อยู่ใน


16

สมมติว่าผมมี 2D ตาข่ายประกอบด้วยสามเหลี่ยม nonoverlapping {Tk}k=1Nและชุดของจุด{pi}i=1Mk=1NTK K วิธีที่ดีที่สุดในการกำหนดสามเหลี่ยมแต่ละจุดนั้นคืออะไร

ตัวอย่างเช่นในภาพต่อไปนี้เรามี , ,ดังนั้นฉันต้องการฟังก์ชันที่ส่งคืนรายการ .p1T2p2T4p3T2ff(p1,p2,p3)=[2,4,2]

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

Matlab มีฟังก์ชั่นชี้ตำแหน่งซึ่งทำสิ่งที่ฉันต้องการสำหรับ Delaunay meshes แต่มันล้มเหลวสำหรับ mesh ทั่วไป

ความคิดแรก (โง่) ของฉันคือสำหรับโหนดวนรอบสามเหลี่ยมทั้งหมดเพื่อหาสามเหลี่ยมp i ที่อยู่ในอย่างไรก็ตามนี่ไม่มีประสิทธิภาพมาก - คุณอาจต้องวนซ้ำทุกสามเหลี่ยมทุกจุดดังนั้นจึง สามารถทำงานO ( N M )ได้pipiO(NM)

ความคิดต่อไปของฉันคือสำหรับทุกจุดค้นหาโหนดโหนดที่ใกล้ที่สุดผ่านการค้นหาเพื่อนบ้านที่ใกล้ที่สุดจากนั้นมองผ่านรูปสามเหลี่ยมที่แนบกับโหนดที่ใกล้ที่สุด ในกรณีนี้งานจะเป็นO ( a M l o g ( N)piโดยที่ aคือจำนวนสามเหลี่ยมสูงสุดที่ยึดติดกับโหนดใด ๆ ในตาข่าย มีสองประเด็นที่แก้ไขได้ แต่น่ารำคาญด้วยวิธีนี้O(aMlog(N))a

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

ดูเหมือนว่าไม่เหมาะสมทั้งหมดและฉันคิดว่าควรจะมีวิธีที่ดีกว่า นี่เป็นปัญหาที่เกิดขึ้นมากมายดังนั้นฉันจึงสงสัยว่าใครจะแนะนำวิธีที่ดีที่สุดในการค้นหาว่าโหนดใดมีสามเหลี่ยมอยู่ในนั้นไม่ว่าในทางทฤษฎีหรือในแง่ของห้องสมุดที่มีอยู่

ขอบคุณ!

คำตอบ:


16

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

O(logN)O(MlogN)M

แก้ไข 2 : พบPDF นี้ที่อธิบายรูปแบบ "การเดิน" ที่รับประกันว่าจะยุติและทบทวนวิธีการที่ไร้เดียงสามากขึ้น

อีกทางเลือกหนึ่งในการใช้ควอดทรีคือการใช้ลำดับชั้นของสมการ ดู Olivier Devillers ปรับปรุง Delaunay triangulation ที่สุ่มเพิ่มขึ้น ในพรอ. 14 Annu ACM Sympos คอมพิวเต Geom., หน้า 106-115, 1998 มันทำงานได้ดีที่สุดสำหรับการหาสามเหลี่ยม Delaunay แต่ยังสามารถใช้ได้กับ Delaunay ที่ไม่ใช่

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


Victor - คุณรู้เกี่ยวกับโค้ดโอเพนซอร์สใด ๆ ดูเหมือนว่ามันจะเป็นทางออกที่ดีมากสำหรับเคสของฉัน (แบบจำลองการติดตามอนุภาคที่ขับเคลื่อนโดยสนามปัจจุบันในโครงข่ายตะแกรง traingualr) ขอบคุณ
Chris Barker

ฉันมีรหัสสำหรับสิ่งนี้และฉันสามารถส่งให้คุณได้ มันอยู่ใน C / C ++ ยังไม่มีเวลาทำความสะอาดและโพสต์ลงบน Github ฉันต้องเขียนสิ่งนี้อย่างน้อยสองครั้งในชีวิตของฉันครั้งหนึ่งกับโครงสร้างข้อมูลฮาล์ฟเมจอีกครั้งด้วยการ quadedge แต่มันสามารถใช้ได้อย่างง่ายดายเมื่อสิ่งเหล่านั้นไม่พร้อมใช้งานและคุณจำเป็นต้องสร้างโครงสร้างทอพอโลยีด้วยตัวเอง ดูหน้าโปรไฟล์ของฉันสำหรับเว็บไซต์ของฉันซึ่งคุณสามารถค้นหาข้อมูลติดต่อได้ เราสามารถพูดคุยเรื่องนี้เพิ่มเติมออฟไลน์
Victor Liu

ฉันใกล้จะดำเนินการนี้ใน MATLAB โดยใช้การสั่งซื้อโค้ง Hilbert และการเดินแบบสุ่ม มันเป็นรหัสการวิจัย: ไม่ได้รับการปรับปรุง, ไม่ได้ทำเป็นเอกสาร, ฯลฯ แต่ก็ยังค่อนข้างเร็ว - ฉันสามารถให้รหัสแก่คุณได้ถ้าคุณสนใจ
Nick Alger

2
เกี่ยวกับ: "" "การกระโดดบนขอบควรเป็น O (logN)" "" ฉันไม่เห็นสิ่งนั้น ตัวอย่างเช่นในกรณีทางพยาธิวิทยาของแถบสามเหลี่ยมยาวขนาดใหญ่ (เช่นช่องทางแคบ ๆ เฉพาะในรูปสามเหลี่ยมกว้าง) ในกรณีที่เลวร้ายที่สุดคุณจะต้องกระโดดจากสามเหลี่ยมหนึ่งไปยังอีกจุดหนึ่งจนถึงจุดสิ้นสุด ในกรณีเฉลี่ยครึ่งทาง ดังนั้นถ้าคุณเพิ่มจำนวนสามเหลี่ยมเป็นสองเท่ามันจะเป็น O (N) ในกรณีที่ปกติมากขึ้นของการจัดเรียงรูปสามเหลี่ยมสี่เหลี่ยมจัตุรัสผมจะคาดหวัง O (sqrt (N)) หรือฉันกำลังพลาดอะไรอยู่? -Chris
Chris Barker

@Chris - ยินดีต้อนรับสู่ scicomp! ในฐานะที่เป็นส่วนหนึ่งของการทำความสะอาดของ Scicomp ฉันได้ย้ายคำตอบของคุณและบทสนทนาที่ตามมามาเป็นความคิดเห็นในคำตอบของ Victor เรารอคอยที่จะมีส่วนร่วมของคุณในเว็บไซต์
Aron Ahmadia

8

ฉันไม่มั่นใจว่าทางออกของคุณถูกต้องจริง พิจารณาสถานการณ์ที่คุณมีโหนดเหล่านี้:

  • A: (-3, 1)
  • B: (0, 2)
  • C: (3, 1)
  • D: (0, -5)

มีรูปสามเหลี่ยม ABC และ ACD ตอนนี้ B คือจุดที่ใกล้จุดกำเนิดมากที่สุด แต่ต้นกำเนิดอยู่ในรูปสามเหลี่ยม ACD ซึ่งไม่มี B

O(NM)แต่โดยทั่วไปจะเร็วกว่า - โดยเฉพาะอย่างยิ่งสำหรับ Delaunay triangulations และ triangulations ใกล้เคียงกับบางแง่มุม

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

  • พิกัดที่กล่องถูกแบ่งหรืออีกทางหนึ่งคือกล่องที่มีขอบเขตของ subtrees ย่อยทั้งสี่
  • ตัวชี้ไปยังทรีย่อย
  • ชุดของสามเหลี่ยมที่ตกลงไปในกล่องขอบของสี่เหลี่ยมนี้อย่างสมบูรณ์ แต่ไม่ได้อยู่ในตำแหน่งย่อยทั้งสี่ กล่าวอีกนัยหนึ่งสามเหลี่ยมที่ตัดกับส่วนของเส้นแบ่งย่อยสองส่วนใด ๆ ของควอดทรี

nnlognO(NM)


อืมคุณพูดถูก ในทางกลับกันถ้าการหารูปสามเหลี่ยมเป็น Delaunay ฉันคิดว่าเพื่อนบ้านที่ใกล้ที่สุดจะได้ผล มัน จำกัด มากเกินไปสำหรับสิ่งที่ฉันพยายามทำ แต่ในกรณี Delaunay พิจารณาไดอะแกรม Voronoi dual - เซลล์ Voronoi เป็นชุดของจุดที่อยู่ใกล้กับโหนดมากที่สุดและขอบสามเหลี่ยม delaunay ทั้งหมดตรงกับขอบของ Voronoi เซลล์ที่มุมฉากดังนั้นจุดใดก็ตามจะต้องอยู่ในรูปสามเหลี่ยมที่เชื่อมต่อกับโหนดที่อยู่ใกล้ที่สุด ฉันสงสัยว่านี่เป็นวิธีที่ฟังก์ชั่น pointLocation ของ matlab ทำงานภายใต้ประทุนหรือไม่?
Nick Alger

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