พื้นที่รวมของวงกลมที่ทับซ้อนกัน


107

ฉันเพิ่งเจอปัญหาที่ฉันมีวงกลมสี่วง (จุดกึ่งกลางและรัศมี) และต้องคำนวณพื้นที่ของการรวมกันของวงกลมเหล่านี้

ภาพตัวอย่าง:

สำหรับวงกลมสองวงมันค่อนข้างง่าย

ฉันสามารถคำนวณเศษส่วนของพื้นที่วงกลมแต่ละวงที่ไม่อยู่ในสามเหลี่ยมแล้วคำนวณพื้นที่ของสามเหลี่ยม

แต่มีอัลกอริทึมที่ชาญฉลาดที่ฉันสามารถใช้ได้เมื่อมีวงกลมมากกว่าสองวงหรือไม่?


15
นี่เป็นปัญหาที่น่าสนใจจริงๆฉันจำได้ว่าเคยเห็นสิ่งนี้ในชั้นเรียนเรขาคณิตของโรงเรียนมัธยม แต่ไม่พบวิธีแก้ปัญหา หากคุณไม่สามารถหาคำตอบได้ที่นี่ลองโพสต์ที่mathoverflow.netและปล่อยให้นักคณิตศาสตร์มีปัญหา: P
Charles Ma

25
บางครั้งโปรแกรมเมอร์ตัวจริงก็ต้องการคณิตศาสตร์จริง
ฟะ

1
วิธีการหาคำตอบสำหรับคำถามนี้ - "เรามีพนักงานขายที่อาศัยอยู่ในสถานที่ทั้ง 4 แห่งนี้ซึ่งแต่ละคนให้บริการในพื้นที่ 4 รัศมีนี้เราครอบคลุมพื้นที่เท่าไรในประเทศ" หากคุณมีการเปลี่ยนแปลงฐานข้อมูลของพนักงานขายสิ่งนี้จะกลายเป็นคำถามเกี่ยวกับการเขียนโปรแกรม!
Chris Roberts

5
อันที่จริงนี่เป็นปัญหาที่โปรแกรมเมอร์ชอบคิด
MAK

2
@zvolkov: แผงวงจรอธิบายด้วยภาษาที่วางสี่เหลี่ยมและวงกลมลงและเลือกลากได้ "คำนวณพื้นที่ทองแดง". (สิ่งนี้จำเป็นต้องใช้ในการคำนวณเวลาการจำหลักรู้ว่าจะต้องเพิ่มงานศิลปะการไล่สิ่งต่างๆหรือไม่)
DigitalRoss

คำตอบ:


97

ค้นหาจุดตัดวงกลมทั้งหมดในเส้นรอบนอก (เช่น B, D, F, H ในแผนภาพต่อไปนี้) เชื่อมต่อเข้าด้วยกันกับศูนย์กลางของวงกลมที่เกี่ยวข้องเพื่อสร้างรูปหลายเหลี่ยม พื้นที่ของการรวมกันของวงกลมคือพื้นที่ของรูปหลายเหลี่ยม + พื้นที่ของชิ้นส่วนวงกลมที่กำหนดโดยจุดตัดต่อเนื่องและจุดศูนย์กลางวงกลมที่อยู่ระหว่างพวกเขา คุณจะต้องพิจารณาหลุมต่างๆด้วย

วงกลมทับซ้อนกัน


17
จะเกิดอะไรขึ้นเมื่อมีรูตรงกลาง?
John Gietzen

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

3
ดี แต่ฉันเดาว่านี่จะต้องมีรายละเอียดการใช้งานจำนวนมากเพื่อจัดการกับกรณีพิเศษทั้งหมด (วงกลมในอีกอันหนึ่งไม่มีจุดตัดหลุมการติดต่อจุดเดียว ... )
ฟะ

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

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

32

ฉันแน่ใจว่ามีอัลกอริทึมที่ชาญฉลาด แต่นี่เป็นสิ่งที่น่าเบื่อที่ต้องค้นหา

  • ใส่กรอบล้อมรอบวงกลม
  • สร้างจุดสุ่มภายในกรอบขอบเขต
  • ดูว่าจุดสุ่มอยู่ในวงกลมวงใดวงหนึ่งหรือไม่
  • คำนวณพื้นที่โดยการเพิ่มและการหารอย่างง่าย (ratio_of_points_inside * area_of_bounding_box)

แน่นอนว่ามันโง่ แต่:

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

2
วิธีนี้จะได้ผล แต่วิธีการของมอนติคาร์โลเช่นวิธีนี้ขึ้นอยู่กับการสุ่มตัวอย่างแบบสม่ำเสมอโดยทั่วไปไม่มีอัตราการลู่เข้าที่ดีที่สุด
ShreevatsaR

2
ขออภัยแม้ว่าฉันจะชื่นชมในความพยายามของคุณและคิดว่าโซลูชันของคุณ "ใช้งานได้จริง" แต่ฉันถือว่าแนวทางของคุณผิดมาก นี่เป็นปัญหาเกินกว่าที่จะทำได้และควรแก้ไขโดยใช้คณิตศาสตร์ไม่ใช่กำลังดุร้าย การเสียพลังงานและแกนไปกับปัญหาเช่นนี้เป็นการสิ้นเปลืองและฟุ่มเฟือย
mafu

5
คุณพูดถูกฉันละอายใจตัวเอง แต่ฉันมีคลัสเตอร์ที่มี 12,000 คอร์ฉันสามารถจ่ายได้อย่างฟุ่มเฟือย และฉันคิดไม่ออกว่าจะสร้างโซลูชันทางคณิตศาสตร์ที่สวยงามสำหรับโปรเซสเซอร์จำนวนมากได้อย่างไร
High Performance Mark

8
ไม่มีอะไรผิดปกติกับวิธีมอนติคาร์โล (หรือแบบสุ่มใด ๆ ) หากให้ระดับความแม่นยำที่ต้องการและทำได้ในระยะเวลาที่เหมาะสม
MAK

@mafutrct คุณพูดถูกอย่างแน่นอน อย่างไรก็ตามการทำผิดพลาดเล็กน้อยในวิชาคณิตศาสตร์ทำได้ง่าย โซลูชันนี้ให้วิธีง่ายๆในการทดสอบความถูกต้อง
Richard

18

คำตอบของ Ants Aasma ให้แนวคิดพื้นฐาน แต่ฉันต้องการทำให้เป็นรูปธรรมมากขึ้นเล็กน้อย ดูวงกลมทั้งห้าด้านล่างและวิธีการย่อยสลาย

ตัวอย่าง

  • จุดสีน้ำเงินคือจุดศูนย์กลางวงกลม
  • จุดสีแดงคือจุดตัดขอบวงกลม
  • จุดสีแดงด้วยการตกแต่งภายในสีขาวเป็นวงกลมแยกเขตแดนที่ไม่ได้อยู่ในวงการอื่น

การระบุจุดทั้ง 3 ประเภทนี้เป็นเรื่องง่าย ตอนนี้สร้างโครงสร้างข้อมูลกราฟโดยที่โหนดเป็นจุดสีน้ำเงินและจุดสีแดงที่มีการตกแต่งภายในสีขาว สำหรับทุกวงกลมให้วางขอบระหว่างวงกลมตรงกลาง (จุดสีน้ำเงิน) และจุดตัดแต่ละจุด (จุดสีแดงที่มีภายในสีขาว) บนขอบเขต

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


ฉันคิดว่าฉันสามารถคำนวณชุดของจุดสีแดง / สีขาวได้ค่อนข้างง่าย แต่ทฤษฎีกราฟของฉันไม่ได้ดีเกินไป: อัลกอริทึมคุณจะได้รับจากรายการโหนด + ขอบไปยังพื้นที่คำนวณได้อย่างไร
user999305

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

16

สำหรับวิธีการแก้ปัญหาที่แตกต่างจากก่อนหน้านี้คุณสามารถสร้างการประมาณค่าด้วยความแม่นยำโดยพลการโดยใช้ควอดทรี

นอกจากนี้ยังใช้ได้กับการรวมกันของรูปร่างหากคุณสามารถบอกได้ว่าสี่เหลี่ยมอยู่ด้านในหรือด้านนอกหรือตัดกับรูปร่าง

แต่ละเซลล์มีสถานะอย่างใดอย่างหนึ่ง: ว่างเปล่าเต็มบางส่วน

อัลกอริทึมประกอบด้วย "การวาด" วงกลมในรูปสี่เหลี่ยมทรีที่เริ่มต้นด้วยความละเอียดต่ำ (เช่น 4 เซลล์ที่ทำเครื่องหมายว่าว่าง) แต่ละเซลล์มีดังนี้:

  • ภายในวงกลมอย่างน้อยหนึ่งวงกลมจากนั้นทำเครื่องหมายเซลล์ว่าเต็ม
  • นอกแวดวงทั้งหมดทำเครื่องหมายเซลล์ว่าว่าง
  • อื่นทำเครื่องหมายเซลล์เป็นบางส่วน

เมื่อเสร็จแล้วคุณสามารถคำนวณค่าประมาณของพื้นที่: เซลล์เต็มจะให้ขอบเขตล่างเซลล์ว่างจะให้ขอบเขตที่สูงขึ้นเซลล์บางส่วนให้ข้อผิดพลาดของพื้นที่สูงสุด

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

ฉันคิดว่าวิธีนี้จะง่ายกว่าวิธีทางเรขาคณิตซึ่งอาจต้องจัดการกรณีพิเศษจำนวนมาก


3
ฉันเดาว่าสิ่งนี้จะมาบรรจบกันอย่างรวดเร็วกว่าขั้นตอนวิธีจุดภายใน / ภายนอกมอนติคาร์โลด้วย
Frank Krueger

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

แรงเดรัจฉานที่นี่เรียกว่าทฤษฎีบทบีบ
ฟะ

นั่นคือประเภทของอัลกอริทึมที่คุณใช้ในการคำนวณช่วงเวลา en.wikipedia.org/wiki/Interval_arithmetic
rjmunro

13

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

อาจให้ข้อมูลเชิงลึกที่ดีกว่าในการสรุปอัลกอริทึมสำหรับวงกลมกึ่งซ้อนทับจำนวนมาก

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

(ในทางปฏิบัติบางทีวิธีมอนติคาร์โลก็คุ้มค่า)

ข้อความแสดงแทน
(ที่มา: secretGeek.net )


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

4

หากคุณต้องการคำตอบที่ไม่ต่อเนื่อง (ตรงข้ามกับคำตอบแบบต่อเนื่อง) คุณสามารถทำสิ่งที่คล้ายกับอัลกอริทึมการวาดภาพพิกเซล

วาดวงกลมบนเส้นตารางแล้วลงสีแต่ละเซลล์ของตารางถ้าส่วนใหญ่มีอยู่ภายในวงกลม (กล่าวคืออย่างน้อย 50% ของพื้นที่อยู่ในวงกลมวงใดวงหนึ่ง) ทำสิ่งนี้สำหรับทั้งเส้นตาราง (โดยที่เส้นตารางจะครอบคลุมพื้นที่ทั้งหมดที่วงกลมครอบคลุม) จากนั้นนับจำนวนเซลล์สีในเส้นตาราง


3

อืมปัญหาที่น่าสนใจมาก แนวทางของฉันอาจเป็นบางสิ่งตามบรรทัดต่อไปนี้:

  • หาวิธีหาว่าพื้นที่ของจุดตัดระหว่างวงกลมจำนวนเท่าใดก็ได้โดยพลการคือถ้าฉันมี 3 วงกลมฉันต้องสามารถหาว่าจุดตัดระหว่างวงกลมเหล่านั้นคืออะไร วิธี "มอนติคาร์โล" น่าจะเป็นวิธีที่ดีในการประมาณค่านี้ ( http://local.wasp.uwa.edu.au/~pbourke/geometry/circlearea/ )
  • กำจัดวงกลมใด ๆ ที่อยู่ในวงกลมที่ใหญ่กว่าทั้งหมด (ดูที่รัศมีและโมดูลัสของระยะห่างระหว่างจุดศูนย์กลางของวงกลมทั้งสอง) ฉันไม่คิดว่าเป็นข้อบังคับ
  • เลือกวงกลม 2 วง (เรียกว่า A และ B) แล้วหาพื้นที่ทั้งหมดโดยใช้สูตรนี้:

(เป็นจริงสำหรับรูปร่างใด ๆ ไม่ว่าจะเป็นวงกลมหรืออย่างอื่น)

area(A∪B) = area(A) + area(B) - area(A∩B)

โดยที่A ∪ BA ยูเนี่ยน B A ∩ Bหมายถึง A ตัดกัน B (คุณสามารถหาวิธีนี้ได้ตั้งแต่ขั้นตอนแรก

  • ตอนนี้ให้เพิ่มวงกลมและหาพื้นที่ที่เพิ่มเป็นผลรวม / ลบพื้นที่ของวงกลมและพื้นที่ของจุดตัดระหว่างวงกลม ตัวอย่างเช่นสำหรับวงกลม 3 วง (เรียกวงกลมพิเศษ C) เราหาพื้นที่โดยใช้สูตรนี้:

(ซึ่งเหมือนกับด้านบนที่Aถูกแทนที่ด้วยA∪B)

area((A∪B)∪C) = area(A∪B) + area(C) - area((A∪B)∩C)

ที่area(A∪B)เราเพิ่งออกกำลังกายและarea((A∪B)∩C)สามารถพบได้:

area((A∪B)nC) = area((A∩C)∪(B∩C)) = area(A∩C) + area(A∩B) - area((A∩C)∩(B∩C)) = area(A∩C) + area(A∩B) - area(A∩B∩C)

คุณสามารถหาพื้นที่ (A∩B∩C) จากด้านบนได้อีกที่ไหน

ขั้นตอนที่ยุ่งยากคือขั้นตอนสุดท้ายยิ่งเพิ่มวงกลมมากเท่าไหร่ก็ยิ่งซับซ้อนมากขึ้นเท่านั้น ฉันเชื่อว่ามีการขยายตัวสำหรับการหาพื้นที่ของทางแยกที่มีสหภาพที่ จำกัด หรือคุณอาจสามารถแก้ไขซ้ำได้

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

อาจมีวิธีที่ดีกว่าในการทำ btw นี้ - ความซับซ้อนจะเพิ่มขึ้นอย่างมาก (อาจจะเป็นแบบทวีคูณ แต่ฉันไม่แน่ใจ) สำหรับวงกลมพิเศษแต่ละวงที่เพิ่มเข้ามา


การจัดรูปแบบเป็นอย่างไร ขออภัยด้วยเกี่ยวกับการใช้ n และ u สำหรับจุดตัดและการรวมกันอาจมีวิธีที่ดีกว่านี้ ...
Justin

1
เพิ่มเครื่องหมายยูนิโคดยูนิโคด (∪) และจุดตัด (∩) หวังว่าพวกเขาจะทำงานได้
Spoike

3

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


2

นี่คืออัลกอริทึมที่ควรใช้งานง่ายในทางปฏิบัติและสามารถปรับเปลี่ยนเพื่อสร้างข้อผิดพลาดเล็ก ๆ น้อย ๆ โดยพลการ:

  1. ประมาณแต่ละวงกลมโดยรูปหลายเหลี่ยมปกติที่อยู่ตรงกลางจุดเดียวกัน
  2. คำนวณรูปหลายเหลี่ยมซึ่งเป็นจุดรวมของวงกลมโดยประมาณ
  3. คำนวณพื้นที่ของรูปหลายเหลี่ยมที่ผสาน

ขั้นตอนที่ 2 และ 3 สามารถทำได้โดยใช้อัลกอริทึมมาตรฐานที่หาได้ง่ายจากเรขาคณิตเชิงคำนวณ

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


2

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

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


1

ฉันพบลิงค์นี้ซึ่งอาจเป็นประโยชน์ ดูเหมือนจะไม่มีคำตอบที่ชัดเจน คำตอบของ Google อ้างอิงสำหรับสามวงกลมก็คือทฤษฎีบทของฮารูกิ มีกระดาษอยู่ที่นั่นเช่นกัน


1

ขึ้นอยู่กับปัญหาที่คุณพยายามแก้ปัญหาอาจเพียงพอที่จะได้ขอบเขตบนและล่าง ขอบเขตบนเป็นเรื่องง่ายเพียงแค่ผลรวมของวงกลมทั้งหมด สำหรับขอบเขตล่างคุณสามารถเลือกรัศมีเดียวโดยที่ไม่มีวงกลมซ้อนทับกัน เพื่อให้ดีกว่านั้นให้หารัศมีที่ใหญ่ที่สุด (ถึงรัศมีจริง) สำหรับแต่ละวงกลมเพื่อไม่ให้ทับซ้อนกัน มันควรจะเป็นเรื่องเล็กน้อยที่จะลบวงกลมที่ทับซ้อนกันทั้งหมด (วงกลมดังกล่าวทั้งหมดตอบสนอง | P_a - P_b | <= r_a) โดยที่ P_a เป็นศูนย์กลางของวงกลม A, P_b คือศูนย์กลางของวงกลม B และ r_a คือรัศมีของ A ) และเดิมพันทั้งบนและล่าง นอกจากนี้คุณยังสามารถได้ขอบเขตบนที่ดีกว่าหากคุณใช้สูตรคู่ของคุณกับคู่ที่กำหนดเองแทนที่จะใช้เพียงผลรวมของวงกลมทั้งหมด อาจมีวิธีที่ดีในการเลือก "สิ่งที่ดีที่สุด"

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


0

สิ่งนี้สามารถแก้ไขได้โดยใช้Green's Theoremซึ่งมีความซับซ้อนของ n ^ 2log (n) หากคุณไม่คุ้นเคยกับทฤษฎีของสีเขียวและต้องการทราบข้อมูลเพิ่มเติมนี่คือวิดีโอและบันทึกย่อจาก Khan Academy แต่เพื่อปัญหาของเราฉันคิดว่าคำอธิบายของฉันก็เพียงพอแล้ว

ขออภัยสำหรับลิงค์ไปยังรูปภาพเนื่องจากฉันไม่สามารถโพสต์ภาพได้ (คะแนนชื่อเสียงไม่เพียงพอ)

สมการทั่วไปของทฤษฎีบทสีเขียว

ถ้าฉันใส่LและM แบบนั้น

เงื่อนไข

จากนั้น RHS เป็นเพียงพื้นที่ของภูมิภาคRและสามารถหาได้จากการแก้อินทิกรัลปิดหรือ LHS และนี่คือสิ่งที่เรากำลังจะทำ

สหภาพแรงงานทั้งหมดสามารถแตกออกเป็นวงกลมที่ไม่ต่อเนื่องกันซึ่งตัดกัน

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

AreaOfUnion = (การรวมตามส่วนโค้งสีแดงในทิศทางทวนเข็มนาฬิกา + การรวมตามส่วนโค้งสีน้ำเงินในทิศทางตามเข็มนาฬิกา)

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

แม้แต่กรณีที่วงกลมไม่ตัดกับวงอื่นก็ยังได้รับการดูแล

นี่คือลิงก์ GitHub ไปยังรหัส C ++ของฉัน


-1

วิธีการวาดภาพพิกเซล (ตามที่แนะนำโดย @Loadmaster) ดีกว่าวิธีการแก้ปัญหาทางคณิตศาสตร์ในหลาย ๆ วิธี:

  1. การดำเนินการเป็นมากง่าย ปัญหาข้างต้นสามารถแก้ไขได้ในโค้ดน้อยกว่า 100 บรรทัดเนื่องจากโซลูชัน JSFiddle นี้แสดงให้เห็น (ส่วนใหญ่เป็นเพราะแนวคิดนั้นง่ายกว่ามากและไม่มีกรณีขอบหรือข้อยกเว้นในการจัดการ)
  2. มันปรับให้เข้ากับปัญหาทั่วไปได้ง่ายขึ้น มันใช้งานได้กับรูปร่างใด ๆ โดยไม่คำนึงถึงสัณฐานวิทยาตราบใดที่สามารถแสดงผลได้ด้วยไลบรารีการวาดภาพ 2 มิติ (กล่าวคือ“ ทั้งหมด!”) - วงกลมวงรีเส้นโค้งรูปหลายเหลี่ยมคุณตั้งชื่อมัน Heck แม้กระทั่งภาพบิตแมป
  3. ความซับซ้อนของวิธีการวาดภาพพิกเซลคือ ~ O [n] เมื่อเทียบกับ ~ O [n * n] สำหรับวิธีการแก้ปัญหาทางคณิตศาสตร์ ซึ่งหมายความว่าจะทำงานได้ดีขึ้นเมื่อจำนวนรูปร่างเพิ่มขึ้น
  4. และเมื่อพูดถึงประสิทธิภาพคุณมักจะได้รับการเร่งด้วยฮาร์ดแวร์ฟรีเนื่องจากไลบรารี 2D ที่ทันสมัยที่สุด (เช่นผืนผ้าใบของ HTML5 ฉันเชื่อว่า) จะกำจัดการแสดงผลงานไปยังตัวเร่งกราฟิก

ข้อเสียอย่างหนึ่งของการวาดภาพด้วยพิกเซลคือความแม่นยำที่ จำกัด ของโซลูชัน แต่สามารถปรับแต่งได้โดยการแสดงผลเป็นผืนผ้าใบที่ใหญ่ขึ้นหรือเล็กลงตามที่สถานการณ์ต้องการ โปรดทราบด้วยว่าการลบรอยหยักในโค้ดการแสดงผล 2 มิติ (มักจะเปิดใช้งานโดยค่าเริ่มต้น) จะให้ความแม่นยำที่ดีกว่าระดับพิกเซล ตัวอย่างเช่นฉันคิดว่าการเรนเดอร์ตัวเลข 100x100 ในผืนผ้าใบที่มีขนาดเท่ากันควรให้ความแม่นยำตามลำดับ 1 / (100 x 100 x 255) = .000039% ... ซึ่งน่าจะ "ดีพอ" สำหรับปัญหาที่เรียกร้องมากที่สุด

<p>Area computation of arbitrary figures as done thru pixel-painting, in which a complex shape is drawn into an HTML5 canvas and the area determined by comparing the number of white pixels found in the resulting bitmap.  See javascript source for details.</p>

<canvas id="canvas" width="80" height="100"></canvas>

<p>Area = <span id="result"></span></p>
// Get HTML canvas element (and context) to draw into
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Lil' circle drawing utility
function circle(x,y,r) {
  ctx.beginPath();
  ctx.arc(x, y, r, 0, Math.PI*2);
  ctx.fill();
}

// Clear canvas (to black)
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Fill shape (in white)
ctx.fillStyle = 'white';
circle(40, 50, 40);
circle(40, 10, 10);
circle(25, 15, 12);
circle(35, 90, 10);

// Get bitmap data
var id = ctx.getImageData(0, 0, canvas.width, canvas.height);
var pixels = id.data; // Flat array of RGBA bytes

// Determine area by counting the white pixels
for (var i = 0, area = 0; i < pixels.length; i += 4) {
  area += pixels[i]; // Red channel (same as green and blue channels)
}

// Normalize by the max white value of 255
area /= 255;

// Output result
document.getElementById('result').innerHTML = area.toFixed(2);

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