เราจะกำหนดความยาวของเส้นทางได้อย่างไร?


11

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

UPDATE:

พา ธ ถูกแสดงในระนาบคาร์ทีเซียน (2D)


คำถามของคุณมีคำตอบใกล้ด้านล่างของคำตอบนี้
BlueRaja - Danny Pflughoeft

คำตอบ:


7

ดังคำตอบก่อนหน้านี้ที่กล่าวว่าการคำนวณความยาวของเส้นโค้ง Bezier นั้นยาก ( เป็นไปไม่ได้ใช่ไหม) ฉันจะบอกว่าเกม 100% ใช้ความยาวโดยประมาณซึ่งค่อนข้างแม่นยำเพียงพอเสมอ

ไม่กี่เดือนที่ผ่านมาฉันใช้งานโดยใช้วิธีการที่เสนอในการแบ่งส่วนโค้งออกเป็นส่วนย่อย ๆ และเพิ่มความยาว มีตัวอย่างของภาษา C ++ การดำเนินงานของที่นี่


11

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


ฉันอาจพิจารณาว่า แต่ฉันจะกำหนดได้อย่างไรว่าฉันควรมีเซ็กเมนต์จำนวนเท่าใดและฉันจะแมปเซกเมนต์เพื่อให้มีจุดเริ่มต้นและจุดสิ้นสุดบนเส้นทางของฉันได้อย่างไร เทคนิคนี้มีชื่อหรือไม่? (ดังนั้นฉันค้นหาบน Google)
Valentin Radu

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

ฉันขอขอบคุณคำอธิบายของการลงคะแนนเสียงเพียงแค่รู้ว่าสิ่งที่ฉันสามารถปรับปรุงในคำตอบของฉัน ...
bummzack

7

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

การใช้งานที่มีอยู่บางอย่าง (รหัสคัดลอกวาง):

การใช้การประมาณ Chebyshevตามผู้เขียนความแม่นยำเติบโตขึ้นตามขนาดเส้นโค้งที่เพิ่มขึ้น ดู pp. 7-8 pseudocode ส่วนที่เหลือเป็นคำอธิบายของอัลกอริธึมอื่น ๆ ที่พวกมันใช้วิธีการที่คุณสามารถเพิกเฉย หมายเลขอ้างอิงออนไลน์อ้างอิงถึงวิธีการนี้ว่าเป็นวิธีที่ดี

ดูวิธีรัดกุมเหล่านี้ด้วย


5

สิ่งนี้เริ่มต้นจากความคิดเห็นเกี่ยวกับความคิดเห็นในคำตอบของ @ bummzack แต่ยาวเกินไป

ฉันจะกำหนดได้อย่างไรว่าฉันควรมีเซ็กเมนต์กี่เซ็กเมนต์

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

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

ปกติจะมีการแบ่งย่อยที่ t = 0.5 แต่อัลกอริทึมของ de Casteljau อนุญาตให้แยกได้ทุกจุดดังนั้นหากคุณมีลูกบาศก์เบซิเยร์ที่มีจุดควบคุม C_0 ถึง C_3 และ C_2 นั้นใกล้กับส่วนของเส้นแบ่งระหว่างจุดปลายมากกว่า C_1 มาก หนึ่งใน 1/3 หรือ 2/3 ให้ขอบเขตที่แคบ ฉันไม่ได้ทำงานผ่านพีชคณิตเพื่อพิสูจน์ว่าสิ่งไหนดีกว่ากัน แต่คุณสามารถทดลองและรายงานกลับหากคุณต้องการ หากไม่มีอะไรอื่นฉันต้องการชี้ให้เห็นว่าตัวเลือกอยู่ที่นั่น


3

การคำนวณความยาวของเส้นโค้ง parametrized สามารถทำได้โดยนำอินทิกรัลของ sqrt ((dx / dt) ² + (dy / dt) ²) โดยที่ dx / dt เป็นอนุพันธ์ของ x-component ของส่วนโค้งและ dy / dt คืออนุพันธ์ขององค์ประกอบ y ของส่วนโค้ง ในกรณีของBézier-spline ทั้งสองนี้จะเหมือนกันเนื่องจากสามารถขยายสมการไปยังมิติใดก็ได้

สูตรสำหรับลูกบาศก์เบซิเยร์ - อิสระคือหนึ่งต่อไปนี้: B (t) = (1 - t³) * P0 + 3 (1 - t) ²t * P1 + 3 (1 - t) t² * P2 + t³ P3 โดยที่ P0 ผ่าน P3 เป็นจุดควบคุม

ตาม Wolfram | Alpha อนุพันธ์ของสูตรนี้คือ: d (B (t)) / dt = 3 (t (t (P3 - P0) P2) + P2 (2 - 3t) + P1 (3t² - 4t + 1))

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

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