ฉันจะเพิ่มและลบรูปหลายเหลี่ยมนูนได้อย่างไร


12

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

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

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

ฉันจะทำสิ่งนี้ได้อย่างไร


เรากำลังพูดถึง 2D ที่นี่หรือไม่? เพราะในการรวมรูปหลายเหลี่ยม 3 มิตินั้นไม่ค่อยสมเหตุสมผลนัก
concept3d

ใช่แล้วฉันกำลังพูดถึง 2D! แม้ว่าฉันจะไม่เห็นว่าทำไมมันไม่สมเหตุสมผลใน 3D มากกว่าใน 2D
เซบาสเตียนบาร์ ธ

2
การเพิ่มรูปหลายเหลี่ยมสองรูปแบบในแบบ 3 มิติถ้าแบนแล้วมันไม่สมเหตุสมผลหากอยู่ในระนาบเดียวกันหากมีปริมาตร (ของแข็ง) ก็เป็นเรื่องที่แตกต่าง
concept3d

ตกลงฉันเข้าใจแล้ว ฉันไม่ได้คิดถึงกราฟิก แต่เป็นวัตถุที่ปะทะกัน ขอบคุณสำหรับการชี้แจง
Sebastian Barth

สำหรับค้นหาจุดทั้งหมดที่พวกเขาตัดกันและเพิ่มจุดยอดในชุด ชุดมีความสำคัญในการป้องกันการทับซ้อน จากนั้นเพิ่มจุดยอดอื่น ๆ จากรูปร่างสองรูปอื่น ๆ ลงในชุด ชุดนี้ประกอบด้วยจุดยอดทั้งหมดของรูปร่างเสริม
Vaughan Hilts

คำตอบ:


9

TL; DR คุณต้องใช้การดำเนินการบูลีนโดยใช้แผนผัง BSP

ดูเหมือนว่าเรากำลังพูดถึงConstructive Solid Geometryที่นี่ ฉันนำ CSG ไปใช้ในเชิงพาณิชย์เพื่อให้ฉันรู้เรื่องหนึ่งหรือสองอย่างเกี่ยวกับเรื่องนี้

กระดาษคลาสสิกเกี่ยวกับ CSG เรียกว่าMerging BSP Trees Yields Polyhedral Set Operationsโดยทั่วไปแล้วมันอธิบายได้มากเกินไป แต่พูดสั้น ๆ เกี่ยวกับอัลกอริทึมที่เกี่ยวข้องกับรูปหลายเหลี่ยมที่วางอยู่บนระนาบเดียวกับการแบ่งพื้นที่ไบนารีโดยทั่วไปแล้ว ต้นไม้ BSP จากตาข่ายเหลี่ยมหลายอัน ขั้นตอนที่สองคือการรวมต้นไม้ BSP เหล่านั้น คุณเพียงนำต้นไม้หนึ่งต้นมาใส่ไว้ในต้นอีกต้นหนึ่ง จากนั้นอัลกอริทึมดำเนินการเพื่ออธิบายวิธีจัดการกับแต่ละโหนดปมสำหรับการแบ่งและการแทนที่โหนดโหนดที่ไม่ต้องการในรูปร่างสุดท้ายจะถูกลบออกส่วนอื่นจะได้รับพาเรนต์ที่เหมาะสม

แต่เดี๋ยวก่อน! โดยทั่วไปแล้วกระดาษนั้นพูดเกี่ยวกับตาข่ายเหลี่ยมและระนาบ 3 มิติใช่ไหม

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

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

เกี่ยวกับความทนทานเชิงตัวเลข เป็นการดีที่จะทราบว่ามีการคำนวณทางเรขาคณิตสองประเภท

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

แนวคิดของการเป็นตัวแทนเครื่องบินโดยใช้ตาข่ายเหลี่ยมนั้นถูกอธิบายเป็นครั้งแรกโดย Sugihara และ Iri [SI89] การเป็นตัวแทนชนิดนี้ให้ประโยชน์ที่สำคัญอย่างหนึ่งเมื่อพูดถึงงานที่เกี่ยวข้องกับการเปลี่ยนโทโพโลยีของของแข็งที่เป็นตัวแทนของตาข่ายเช่นการประเมินผลของบูลีนนิพจน์: ไม่มีการสร้างข้อมูลเรขาคณิตเบื้องต้นใหม่เพื่อให้ได้รูปทรงหลายเหลี่ยม

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

และสุดท้ายผมอยากจะเพิ่มหากคุณต้องการที่จะเริ่มต้นการดำเนินงาน BSP CSG ของคุณผมจะแนะนำให้เริ่มต้นในBSP Faqs


เจ๋ง แต่ตอบโต้ได้ง่ายโดยพิจารณาว่า BSP ของรูปหลายเหลี่ยมนูนหรือรูปหลายเหลี่ยมเป็นรายการ กระดาษที่ดี
3Dave

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

อ่านั่นสมเหตุสมผลแล้ว เรียงจากไฮบริด BSP แล้ว
3Dave

@DavidLively และ BSP นั้นไม่ใช่เรื่องง่ายที่จะแสดงแม้ว่าคำถาม OP เป็นกรณีที่ง่ายในกรณีที่ซับซ้อนมากขึ้นด้วยรูปทรงเรขาคณิตของรูปหลายเหลี่ยมหลายล้านเมื่อคุณเสร็จสิ้นการสร้างต้นไม้ที่คุณไม่ได้ทำ
concept3d

@ concept3d ฉันหวังว่าสิ่งนี้จะไม่น่ารำคาญเกินไปเนื่องจากนี่เป็นคำตอบอายุ 5 ปี แต่มีสองสิ่งที่ฉันไม่เข้าใจจริง ๆ : เมื่อพยายามระบุว่ามีจุดหนึ่งอยู่ทางซ้ายหรือขวาของเครื่องบิน / เส้น มันจะไม่ง่ายกว่าที่จะหมุนทุกสิ่งเพื่อให้ระนาบ / เส้นตรงกับระนาบ / เส้นเล็ก ๆ แล้วลองพิจารณาพิกัดของจุดหมุน วิธีการเกี่ยวกับการใช้อัลกอริทึม Sutherland – Hodgman แทนต้นไม้ BSP เสียงค่อนข้างคล้ายกับวิธีนี้
John P

1

ไปตามตัวอย่างของคุณ:

เลือกจุดเริ่มต้นเริ่มต้นบนรูปหลายเหลี่ยม A จากนั้นเริ่มตรวจสอบการตัดขอบตามเข็มนาฬิกา (หรือทวนเข็มนาฬิกา) หากไม่มีจุดตัดให้เพิ่มจุดสุดยอดก่อนหน้าในรูปหลายเหลี่ยมที่เกิดขึ้น หากมีจุดตัดให้เพิ่มจุดที่จุดตัดเหล่านั้นไปยังรูปหลายเหลี่ยมที่เป็นผลลัพธ์ของคุณจากนั้นเริ่มการวนซ้ำรูปหลายเหลี่ยม B ตามลำดับการพัน ทำสิ่งเดียวกันสลับเป็นรูปหลายเหลี่ยม A อีกครั้งหากมีทางแยกเกิดขึ้น

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

สำคัญ: ตรวจสอบให้แน่ใจว่าจุดสุดยอดที่คุณเริ่มต้นไม่อยู่ในรูปหลายเหลี่ยมอื่น (ตรวจสอบบทความนี้เพื่อดูจุดในการทดสอบรูปหลายเหลี่ยม)

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


0

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

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

Convexมีความซับซ้อนมากกว่าเดิมเล็กน้อย:

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

วิธีการหนึ่งคือการทำซ้ำในการเพิ่มจุดยอดจากรูปหลายเหลี่ยมที่สองเป็นที่หนึ่งครั้งละหนึ่งการพัฒนารูปหลายเหลี่ยมแรกในภาชนะที่ครอบคลุมทุกอย่าง

โดยทั่วไป:

  • วนซ้ำตามจุดยอดของรูปหลายเหลี่ยมที่สอง
  • สำหรับแต่ละจุดยอด V วนซ้ำผ่านขอบรูปหลายเหลี่ยมแรก:
  • ค้นหา "ช่วง" ของขอบที่เผชิญหน้ากับจุดสุดยอด
  • ใช้คู่ด้านนอกของจุดยอดที่กำหนดช่วงนั้นและลบขอบทั้งหมดในช่วงที่เชื่อมต่อ
  • วาดสองส่วนใหม่จากจุดยอดด้านนอกเหล่านั้นไปยังจุดยอดใหม่ (จากรูปหลายเหลี่ยมที่สอง) ตรวจสอบให้แน่ใจว่าขอบใหม่หันหน้าไปทางทิศทางที่ถูกต้อง
  • ไปยังจุดสุดยอดถัดไปจากรูปหลายเหลี่ยมที่สอง

นี่คือไดอะแกรมที่แสดงกระบวนการสำหรับจุดสุดยอดแรก:

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

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

บางทีคนอื่นก็สามารถพูดสอดด้วยคำแนะนำการลบบางอย่าง


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

อัลกอริทึมจะละเว้นจุดยอดที่เป็น "ด้านใน" ของรูปหลายเหลี่ยมเป้าหมายซึ่งจะชดเชยปัญหาที่ขอบจากรูปหลายเหลี่ยมที่สองตัดกันแรก
3Dave

เกือบเท่ากับเฟสผสาน (จุดที่ 4 ของอัลกอริทึมฮัลล์การผสานในกรณีของฉันมันไม่ใช่วิธีการแก้ไขที่ถูกต้องในการเพิ่มพื้นที่เพิ่มเติมหลังจากรวมรูปหลายเหลี่ยมการแก้ปัญหาที่ถูกต้องคือการเก็บรูปหลายเหลี่ยมทั้งสอง ไม่ทับซ้อนกันหรือแตะต้อง
Sebastian Barth

@luftgewehrindianer Ah - ใช่นั่นสร้างความแตกต่างอย่างมาก บางทีฉันอาจเข้าใจผิดคำถาม คุณกำลังมองหาการเพิ่มรูปหลายเหลี่ยมเข้าด้วยกันโดยไม่ต้องกังวลว่าผลลัพธ์จะเป็นแบบนูนหรือเว้าหรือไม่ หรือสร้างชุดนูนตามสี่แยก (ไม่ต้องสนใจการลบในขณะนี้)
3Dave

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