กลับไปหน้าบทความ

อ่าน 5 นาที

ไม่มีชื่อบทความ

อัลกอริทึมของ Fortune เป็น อัลกอริทึมแบบกวาดเส้น สำหรับการสร้าง แผนภาพ Voronoi จากชุดจุดในระนาบโดยใช้ เวลา O ( n log n ) และ พื้นที่O( n ) [ 1 ] [ 2 ] เดิมทีได้รับการตีพิมพ์โดย...

อัลกอริทึมของ Fortune

ภาพเคลื่อนไหวอัลกอริทึมของ Fortune
ภาพเคลื่อนไหวอัลกอริทึมของ Fortune

อัลกอริทึมของ Fortuneเป็นอัลกอริทึมแบบกวาดเส้นสำหรับการสร้างแผนภาพ Voronoiจากชุดจุดในระนาบโดยใช้ เวลา O ( n  log n ) และ พื้นที่O( n ) [ 1 ] [ 2 ]เดิมทีได้รับการตีพิมพ์โดยSteven Fortuneในปี 1986 ในบทความของเขาเรื่อง "A sweepline algorithm for Voronoi diagrams" [ 3 ] 

คำอธิบายอัลกอริธึม

อัลกอริทึมนี้รักษาทั้งเส้นกวาด (sweep line)และเส้นชายหาด (beach line)ซึ่งทั้งสองเส้นจะเคลื่อนที่ผ่านระนาบขณะที่อัลกอริทึมดำเนินไป เส้นกวาดเป็นเส้นตรง ซึ่งเราอาจสมมติโดยทั่วไปว่าเป็นเส้นแนวตั้งและเคลื่อนที่จากซ้ายไปขวาบนระนาบ ในช่วงเวลาใด ๆ ระหว่างการทำงานของอัลกอริทึม จุดข้อมูลที่อยู่ทางซ้ายของเส้นกวาดจะถูกรวมเข้าในแผนภาพโวโรนอยแล้ว ในขณะที่จุดที่อยู่ทางขวาของเส้นกวาดจะยังไม่ถูกพิจารณา เส้นชายหาดไม่ใช่เส้นตรง แต่เป็นเส้นโค้งที่ซับซ้อนและเป็นชิ้นส่วนอยู่ทางซ้ายของเส้นกวาด ประกอบด้วยชิ้นส่วนของพาราโบลามันแบ่งส่วนของระนาบที่สามารถทราบแผนภาพโวโรนอยได้ โดยไม่คำนึงถึงจุดอื่น ๆ ที่อาจอยู่ทางขวาของเส้นกวาด ออกจากส่วนที่เหลือของระนาบ สำหรับแต่ละจุดทางซ้ายของเส้นกวาด เราสามารถกำหนดพาราโบลาของจุดที่อยู่ห่างจากจุดนั้นและจากเส้นกวาดเท่ากันได้ เส้นชายหาดเป็นขอบเขตของการรวมกันของพาราโบลาเหล่านี้ เมื่อเส้นกวาดเคลื่อนที่ไปเรื่อยๆ จุดยอดของเส้นขอบที่พาราโบลาสองเส้นตัดกัน จะลากเส้นขอบของแผนภาพโวโรนอย เส้นขอบจะเคลื่อนที่ไปโดยรักษาระยะฐานของพาราโบลาแต่ละอันให้อยู่กึ่งกลางระหว่างจุดที่เส้นกวาดผ่านในตอนแรกกับตำแหน่งใหม่ของเส้นกวาด ในทางคณิตศาสตร์ หมายความว่าพาราโบลาแต่ละอันถูกสร้างขึ้นโดยใช้เส้นกวาดเป็นเส้นไดเรกทริกซ์และจุดเริ่มต้นเป็นจุดโฟกัส

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

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

รหัสเทียม

คำอธิบาย รหัสเทียมของอัลกอริทึม[ 4 ]

อนุญาต*(z){\displaystyle \scriptstyle *(z)}เป็นการเปลี่ยนแปลง*(z)=(zx,zy+(z)){\displaystyle \scriptstyle *(z)=(z_{x},z_{y}+d(z))}, ที่ไหน(z){\displaystyle \scriptstyle d(z)}คือระยะทางแบบยุคลิดระหว่างzกับไซต์ที่ใกล้ที่สุด ให้T เป็น "แนวชายหาด" อาร์พี{\displaystyle \scriptstyle R_{p}}ให้ เป็นบริเวณที่ครอบคลุมโดยไซต์pซีพีq{\displaystyle \scriptstyle C_{pq}}ให้เป็นรังสีขอบเขตระหว่างไซต์pและqให้ เอส{\displaystyle \scriptstyle S}ให้ เป็นชุดของไซต์ที่จะนำอัลกอริธึมนี้ไปใช้ ให้พี1,พี2,...,พี{\displaystyle \scriptstyle p_{1},p_{2},...,p_{m}}ให้ X เป็นไซต์ที่สกัดจากS ที่มีพิกัด yน้อยที่สุดเรียงลำดับตามพิกัด x ให้ DeleteMin( X ) เป็นการกระทำในการลบไซต์ที่ต่ำที่สุดและซ้ายสุดของX (เรียงลำดับตาม y เว้นแต่ว่าไซต์ทั้งสองจะเหมือนกัน ในกรณีนั้นให้เรียงลำดับตาม x) ให้Vเป็นแผนที่โวโรนอยของSที่จะสร้างขึ้นโดยอัลกอริทึมนี้ คิวพี1,พี2,,พี,เอส{\displaystyle Q\gets {p_{1},p_{2},\dots ,p_{m},S}}สร้างรังสีขอบเขตแนวตั้งเริ่มต้นซีพี1,พี20,ซีพี2,พี30,,ซีพี1,พี0{\displaystyle \scriptstyle C_{p_{1},p_{2}}^{0},C_{p_{2},p_{3}}^{0},\dots ,C_{p_{m-1},p_{m}}^{0}}ที*(อาร์พี1),ซีพี1,พี20,*(อาร์พี2),ซีพี2,พี30,,*(อาร์พี1),ซีพี1,พี0,*(อาร์พี){\displaystyle T\gets *(R_{p_{1}}),C_{p_{1},p_{2}}^{0},*(R_{p_{2}}),C_{p_{2},p_{3}}^{0},\dots ,*(R_{p_{m-1}}),C_{p_{m-1},p_{m}}^{0},*(R_{p_{m}})}ในขณะที่ Q ไม่ว่างเปล่าให้ ลบ ค่าต่ำสุดของQ ออกหากp ของpเป็นไซต์ใน*(วี){\displaystyle \scriptstyle *(V)}: ค้นหาการปรากฏของภูมิภาค*(อาร์q){\displaystyle \scriptstyle *(R_{q})}ในTที่มีp อยู่ ถูกล้อมกรอบโดยซีq{\displaystyle \scriptstyle C_{rq}}ทางด้านซ้ายและซีq{\displaystyle \scriptstyle C_{qs}}ทางด้านขวา สร้างรังสีขอบเขตใหม่ซีพีq{\displaystyle \scriptstyle C_{pq}^{-}}และซีพีq+{\displaystyle \scriptstyle C_{pq}^{+}}โดยใช้ฐานp แทนที่*(อาร์q){\displaystyle \scriptstyle *(R_{q})}กับ*(อาร์q),ซีพีq,*(อาร์พี),ซีพีq+,*(อาร์q){\displaystyle \scriptstyle *(R_{q}),C_{pq}^{-},*(R_{p}),C_{pq}^{+},*(R_{q})}ในT ให้ลบ ส่วนที่ทับซ้อนกันทั้งหมดออกจากQซีq{\displaystyle \scriptstyle C_{rq}}และซีq{\displaystyle \scriptstyle C_{qs}}แทรก จุดตัดใดๆ ระหว่าง ลงใน Qซีq{\displaystyle \scriptstyle C_{rq}}และซีพีq{\displaystyle \scriptstyle C_{pq}^{-}}แทรก จุดตัดใดๆ ระหว่าง ลงใน Qซีพีq+{\displaystyle \scriptstyle C_{pq}^{+}}และซีq{\displaystyle \scriptstyle C_{qs}}pเป็นจุดยอดโวโรนอยใน*(วี){\displaystyle \scriptstyle *(V)}ให้ p เป็นจุดตัดของซีq{\displaystyle \scriptstyle C_{qr}}ทางด้านซ้ายและซี{\displaystyle \scriptstyle C_{rs}}ทางด้านขวา ให้ซีคุณq{\displaystyle \scriptstyle C_{uq}}เป็นเพื่อนบ้านทางซ้ายของซีq{\displaystyle \scriptstyle C_{qr}}และ ปล่อยให้ซีวี{\displaystyle \scriptstyle C_{sv}}เป็นเพื่อนบ้านที่ดีของซี{\displaystyle \scriptstyle C_{rs}}ในT ถ้าqy=y{\displaystyle \scriptstyle q_{y}=s_{y}}สร้าง รังสีขอบเขตใหม่ซีq0{\displaystyle \scriptstyle C_{qs}^{0}}มิฉะนั้น ถ้าpอยู่ทางขวาของค่าที่สูงกว่าระหว่างqและsให้ สร้างซีq+{\displaystyle \scriptstyle C_{qs}^{+}}มิฉะนั้นสร้างซีq{\displaystyle \scriptstyle C_{qs}^{-}} แทนที่endifซีq,*(อาร์),ซี{\displaystyle \scriptstyle C_{qr},*(R_{r}),C_{rs}}ด้วยการสร้างใหม่ซีq{\displaystyle \scriptstyle C_{qs}}ในT ให้ลบ ส่วนที่ทับซ้อนกันทั้งหมดออกจากQซีคุณq{\displaystyle \scriptstyle C_{uq}}และซีq{\displaystyle \scriptstyle C_{qr}} ลบ จุดตัดใดๆ ระหว่าง Q ออกจากQซี{\displaystyle \scriptstyle C_{rs}}และซีวี{\displaystyle \scriptstyle C_{sv}}แทรก จุดตัดใดๆ ระหว่าง ลงใน Qซีคุณq{\displaystyle \scriptstyle C_{uq}}และซีq{\displaystyle \scriptstyle C_{qs}}แทรก จุดตัดใดๆ ระหว่าง ลงใน Qซีq{\displaystyle \scriptstyle C_{qs}}และซีวี{\displaystyle \scriptstyle C_{sv}} บันทึกpเป็นจุดสูงสุดของซีq{\displaystyle \scriptstyle C_{qr}}และซี{\displaystyle \scriptstyle C_{rs}}และฐานของซีq{\displaystyle \scriptstyle C_{qs}} ส่งออกส่วนขอบเขตซีq{\displaystyle \scriptstyle C_{qr}}และซี{\displaystyle \scriptstyle C_{rs}}endcase endwhile ส่งออกรังสีขอบเขตที่เหลือในT

ไซต์และดิสก์ที่มีน้ำหนัก

ไซต์ที่มีน้ำหนักแบบบวก

ตามที่ Fortune อธิบายไว้ในเอกสารอ้างอิง[ 1 ]เวอร์ชันที่แก้ไขของอัลกอริทึมเส้นกวาดสามารถใช้สร้างแผนภาพ Voronoi ที่ถ่วงน้ำหนัก แบบบวกได้ โดยที่ระยะทางไปยังแต่ละไซต์จะถูกชดเชยด้วยน้ำหนักของไซต์ ซึ่งอาจมองได้ว่าเป็นแผนภาพ Voronoi ของชุดดิสก์ที่มีจุดศูนย์กลางอยู่ที่ไซต์และมีรัศมีเท่ากับน้ำหนักของไซต์ พบว่าอัลกอริทึมมีโอ(nบันทึก(n)){\displaystyle O(n\log(n))}ความซับซ้อนของเวลาโดยที่ n คือจำนวนไซต์ตามอ้างอิง[ 1 ]

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

  • การใช้งาน C ของ Steven Fortune
  • อัลกอริทึม Voronoi ของ Fortune ที่เขียนด้วยภาษา C++
  • อัลกอริทึมของ Fortune ที่เขียนด้วย JavaScriptถูกเก็บไว้ใน GitHub ตั้งแต่เดือนสิงหาคม 2558
  • การเข้าถึง การแสดงภาพอัลกอริทึมของ Fortuneณ ปี 2025 ถูกบล็อกแล้ว

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ไม่มีชื่อบทความ

อัลกอริทึมของ Fortune เป็น อัลกอริทึมแบบกวาดเส้น สำหรับการสร้าง แผนภาพ Voronoi จากชุดจุดในระนาบโดยใช้ เวลา O ( n log n ) และ พื้นที่O( n ) [ 1 ] [ 2 ] เดิมทีได้รับการตีพิมพ์โดย...

คำอธิบายอัลกอริธึม

อัลกอริทึมนี้รักษาทั้ง เส้นกวาด (sweep line) และ เส้นชายหาด (beach line) ซึ่งทั้งสองเส้นจะเคลื่อนที่ผ่านระนาบขณะที่อัลกอริทึมดำเนินไป เส้นกวาดเป็นเส้นตรง ซึ่งเราอาจสมมติโดยทั่วไปว่าเป็นเส้นแนวตั้งและเคลื่อนที่จากซ้ายไปขวาบนระนาบ ในช่วงเวลาใด ๆ...

ไซต์ที่มีน้ำหนักแบบบวก

ตามที่ Fortune อธิบายไว้ในเอกสารอ้างอิง [ 1 ] เวอร์ชันที่แก้ไขของอัลกอริทึมเส้นกวาดสามารถใช้สร้าง แผนภาพ Voronoi ที่ถ่วงน้ำหนัก แบบบวกได้ โดยที่ระยะทางไปยังแต่ละไซต์จะถูกชดเชยด้วยน้ำหนักของไซต์ ซึ่งอาจมองได้ว่าเป็นแผนภาพ Voronoi...

ลิงก์ภายนอก

การใช้งาน C ของ Steven Fortune อัลกอริทึม Voronoi ของ Fortune ที่เขียนด้วยภาษา C++ อัลกอริทึมของ Fortune ที่เขียนด้วย JavaScriptถูกเก็บไว้ใน GitHub ตั้งแต่เดือนสิงหาคม 2558 การเข้าถึง การแสดงภาพอัลกอริทึมของ Fortuneณ ปี 2025 ถูกบล็อกแล้ว