จะหาเซลล์กริด 2 มิติที่ถูกกวาดโดยวงกลมที่กำลังเคลื่อนที่ได้อย่างไร


9

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

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

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

อัปเดตวงกลมอาจใหญ่กว่าเซลล์กริดเดียว


mmh ทำไม 3 ชนกันก่อน 4
FxIII

@FxIII ที่จริงฉันย้ายวงกลมในภาพและมันตี 3 ก่อนหน้า 4 เพียง แต่แทบจะไม่ แต่ก่อนหน้านี้
ไม่เป็นไร

คำตอบ:


6

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

ให้Cเป็นศูนย์กลางของคุณและrรัศมีดังนั้นP' = C + ( R , 0) และP" = C + (0, R)

ถ้าDคือเวกเตอร์บอกทิศทางของคุณ (เวอร์ชั่นล่าสุด) คุณมีสองบรรทัด:

R '= D · t + P' ,

R "= D · t + P"

คุณต้องหาจุดตัดของเส้นเหล่านั้นด้วยเส้นของสมการง่ายๆ

y = iและ y = i ที่เป็นขอบของกริดของคุณ!

การแก้ปัญหาเป็นเรื่องง่ายเพราะคุณมีเพียงแค่พิจารณา x หรือ Component Y ของ R และ R". คุณจะได้พบกับเสื้อคุ้มค่าสำหรับแต่ละ insersection และจุดสำหรับ thoose เสื้อ s เพียงแค่การจัดเรียงจุดเหล่านั้นโดยTและคุณ เสร็จแล้ว.

ฉันเชื่อว่าคุณสามารถพูดได้อย่างง่ายดายว่าเซลล์ใดจะถูกตีถ้าคุณรู้จุดแยก

ใช้งานได้ถ้าr <1 (ความกว้างและความสูงของเซลล์)

มันใช้งานได้กับกรณีอื่น ๆ เพียงแค่ทำการพิจารณาบางอย่างเกี่ยวกับP 'และP "เราเลือก TOP และ LEFT เนื่องจากทิศทางทิศทางด้านล่างและด้านขวาควรได้รับการพิจารณาในทิศทางตรงกันข้ามคุณเข้าใจว่าทำไม

ตอนนี้ดูที่ภาพนี้: วงกลมใหญ่

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

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

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


ใช่ฉันคิดว่า P 'และ P "ชี้ตัวเอง แต่ไม่สามารถคิดได้ว่าจะทำอย่างไรเมื่อวงกลมมีขนาดใหญ่กว่าเซลล์เดียวจุดเพิ่มเติมนั้นสมเหตุสมผลจริงๆ (และเห็นได้ชัดว่าฉันต้องเพิ่มรังสีระหว่าง P' และเท่านั้น P ")
ไม่เป็นไร

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

ชัดเจนหรือไม่ว่าคุณต้องทดสอบเส้นกริดในแนวนอนและแนวตั้งแยกกัน?
FxIII

ฉันคิดว่าคุณต้องตรวจสอบเมื่อวงกลมครอบคลุมจุดสุดยอดของกริดเพราะวงกลมจะชนกับเซลล์ที่อยู่ติดกันตามแนวทแยงมุมตรงมุม แต่มันไม่จำเป็นว่าจะต้องเป็นจุดบน / ซ้าย / ล่าง / ขวาสุดของวงกลมที่แตะแรก (และคุณจะตรวจพบการชนกันเร็วเกินไป) ตัวอย่าง: สี่เหลี่ยม 3,4,5 ในแผนภาพตัวอย่างในคำถาม พวกเขาถูกตีตามลำดับ (3 จาก 4 และ 5 แล้ว) แต่อัลกอริทึมของคุณจะตรวจจับ 4 และ 5 พร้อมกัน
finnw

@finnw พวกเขาสัมผัสพร้อมกันเฉพาะในกรณีที่ cicle เดินทางไปในทิศทางของเส้นแบ่งครึ่ง
FxIII

1

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

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


8 รังสีอาจจะรับประกันการแยกทั้งหมด แต่พวกเขาจะไม่ให้พวกเขาในลำดับที่ถูกต้อง และสำหรับการชนฉันต้องการสั่งไม่ใช่แค่รายการของเซลล์
ไม่เป็นไร

เพิ่มอัลกอริธึมการชนกันของ ray เพื่อรักษาค่า t สำหรับแต่ละการชน เมื่อคุณได้รับการรวมกันของเซลล์คุณสามารถเรียงลำดับบนค่า t เพื่อรับลำดับที่ถูกต้อง
TreDubZedd

แต่ฉันจะเปรียบเทียบค่า t ของรังสีต่าง ๆ ได้อย่างไร
ไม่เป็นไร

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

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

1

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


ฉันคิดเกี่ยวกับเรื่องนี้เช่นกัน แต่ในความคิดของฉันนี่ไม่ใช่อัลกอริทึมที่ถูกต้อง Bresenham เลือกเพียงหนึ่งพิกเซลเขาต้องการทั้งหมด และมันจะผิดปรกติที่จะปรับ bresenham ให้เป็นวงกลมแค่หนึ่งพิกเซล
zacharmarz

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