คุณคำนวณจุดที่ใกล้ที่สุดบนเส้นโค้ง 2 เส้นได้อย่างไร


15

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

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


2
ฉันเชื่อว่าคำถามนี้เป็นการเริ่มต้นที่ดี
sam hocevar

คำตอบ:


3

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

แนวคิดมีดังต่อไปนี้:

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

อัลกอริทึมสำหรับระยะทางจากเบซิเยร์โค้งไปยังเส้น

เส้นโค้งเบซิเยร์เป็น parametrised โดยฟังก์ชั่นใช้ชุดของจุดควบคุมและพารามิเตอร์ที่แตกต่างกันF(t) tจำนวนจุดที่สร้างไม่สำคัญ

สาย parametrised สองจุดและAB

  1. ขอSAMPLES = 10ยกตัวอย่างเช่น

  2. เริ่มต้นด้วยt0 = 0และt1 = 1

  3. ปล่อย dt = (t1 - t0) / SAMPLES

  4. ถ้าdt < 1e-10(หรือสภาพความถูกต้องอื่น ๆ ที่คุณเห็นพอดี) ขั้นตอนวิธีการเสร็จสิ้นแล้วและคำตอบคือF(t0)

  5. คำนวณรายการSAMPLES + 1คะแนนบนเส้นโค้งเบซิเยร์:

    • L[0] = F(t0)
    • L[1] = F(t0 + dt)
    • L[2] = F(t0 + 2 * dt)
    • ...
    • L[SAMPLES] = F(t0 + SAMPLES * dt)
  6. ค้นหาจุดที่Lมีดัชนีiอยู่ใกล้กับเส้นมากที่สุด ใช้วิธีจุด / เส้นระยะห่างใด ๆ ที่คุณรู้ตัวอย่างเช่นระยะห่างของสแควร์||AB^L[i]A||² / ||AB||²ที่^หมายถึงผลิตภัณฑ์ครอสและ||…||เป็นระยะทาง

  7. ถ้าi == 0ตั้งค่าi = 1; ถ้าi == SAMPLESตั้งi = SAMPLES - 1

  8. อนุญาตt1 = t0 + (i + 1) * dtและt0 = t0 + (i - 1) * dt

  9. กลับไปที่ขั้นตอนที่ 3

อัลกอริทึมสำหรับระยะทางจากเส้นโค้งเบซิเยร์ถึงโค้งเบซิเยร์

เวลานี้เรามีสองเส้นโค้งเบซิเยร์, parametrised โดยและF(t)G(t)

  1. ขอSAMPLES = 10ยกตัวอย่างเช่น

  2. เริ่มต้นด้วยt0 = 0, t1 = 1, s0 = 0และs1 = 1

  3. ปล่อย dt = (t1 - t0) / SAMPLES

  4. ปล่อย ds = (s1 - s0) / SAMPLES

  5. ถ้าdt < 1e-10(หรือสภาพความถูกต้องอื่น ๆ ที่คุณเห็นพอดี) ขั้นตอนวิธีการเสร็จสิ้นแล้วและคำตอบคือF(t0)

  6. หากนี่เป็นการเรียกใช้ครั้งแรกของลูป:

    6.1 คำนวณรายการSAMPLES + 1คะแนนบนF( ดูด้านบน )

    6.2 คำนวณรายชื่อของจุดบนSAMPLES + 1G

    6.3 ค้นหาจุดคู่ที่ใกล้เคียงที่สุด

    6.4 ปรับปรุงt0, t1, s0, s1เท่าที่เห็นข้างต้น

  7. ELSE : ผลัดคำนวณรายการของจุดบนF หรือรายการของจุดบนGแล้วหาที่จุดบนFเป็นที่อยู่ใกล้G(s0)และอัปเดตt0และt1, หรือที่จุดGใกล้เคียงกับF(t0)และการปรับปรุงและs0s1

  8. กลับไปที่ขั้นตอนที่ 3

ประเด็น

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

แต่อย่างที่ฉันพูดก่อนที่คุณจะเริ่มคิดเกี่ยวกับการแก้ปัญหาที่มีประสิทธิภาพมากขึ้นคุณควรทดลองกับวิธีง่าย ๆ เหล่านั้นก่อน


0

1) แปลทุกอย่างเป็นหนึ่งแกนดังนั้นแทนที่จะต้องคำนวณความยาวของจุดหนึ่งไปที่ 'เส้น', 'เส้น' คือพูดแกน Y

จากนั้นเอ่อให้เส้นโค้งเบซิเยร์มากขึ้นฉันจะบอกว่ามันขึ้นอยู่กับจำนวนของจุดควบคุม

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

คะแนนเพิ่มเติมฉันลองคู่ที่ใกล้เคียงที่สุด (แปลแกน Y)

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


PS 2 เส้นโค้งอย่าคิดแม้แต่น้อย (คุณอาจได้รับสิ่งใด (อย่างน้อยที่สุดเท่าที่จะทำได้ .. ) ตามจำนวนจุดควบคุม)
Valmond

0

คำตอบบางส่วนจากหน้าบล็อกของอัลกอริทึมซึ่งพบจุดที่ใกล้ที่สุดบนเส้นโค้งเบซิเยร์กำลังสองที่ให้มาอย่างถูกต้อง

การสาธิต

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


ใช่เป็นตัวอย่างที่ดี คำตอบอยู่ที่ไหน
Anko

1
ฉันเดาว่าเขาต้องการให้เราดูแหล่งที่มาของตัวอย่าง: algorithmist.net/DegrafaClosestToQuad/srcview/index.html
Mutoh

0

สำหรับเส้นโค้ง Bezier - เส้นตรงวิธีที่แม่นยำที่สุดในการค้นหาคำตอบคือทำดังต่อไปนี้:

  1. แปลงปัญหาเพื่อให้เส้นตรงอยู่ในแนวนอนเสมอที่ Y = 0 ทำได้โดยการคูณจุดควบคุมทั้งหมดด้วยเมทริกซ์เลียนแบบที่เหมาะสม (ฉันถือว่าคุณคุ้นเคยกับการเป็นตัวแทนการแปลงเลียนแบบของเครื่องบินด้วยเมทริกซ์ 3x3 กับ 3 รายการคงที่)
  2. ตรวจสอบพิกัด Y ของจุดควบคุม หากพวกเขาไม่ได้มีสัญญาณเดียวกันทั้งหมดอาจมีจุดตัดกับเส้น คำนวณรากของส่วน Y ของเส้นโค้ง Bezier คุณสามารถใช้วิธีการค้นหารากใด ๆ สำหรับพหุนามมีหลายวิธีในวรรณคดี ตัวอย่างเช่น google "convex hull marching" - นี่เป็นวิธีที่ดีพอสมควรสำหรับชื่อพหุนามที่ใช้ในเส้นโค้ง Bezier ทุกรูทที่คุณพบคือค่าเวลาของจุดตัดกับเส้นตรงซึ่งระยะทางเป็นศูนย์ - งานของคุณเสร็จสิ้นแล้ว
  3. ถ้า coords Y ทั้งหมดมีเครื่องหมายเหมือนกันให้คำนวณอนุพันธ์ของส่วน Y ของเส้นโค้ง Bezier คุณสามารถละเว้นพิกัด X ของคะแนนเนื่องจากพวกเขาไม่ได้สร้างความแตกต่าง - เส้นเป้าหมายเป็นแนวนอน ค้นหารากของอนุพันธ์นั้น นี่คือค่าเวลาที่เส้นโค้งอยู่ใกล้กับเส้นมากที่สุด
  4. ประเมินเส้นโค้ง Bezier อย่างชัดเจนสำหรับทุกรูตที่คุณพบในขั้นตอนก่อนหน้าและรายงานรูตซึ่งให้ระยะห่างที่น้อยที่สุดจากบรรทัด คุณต้องตรวจสอบจุดปลาย - พวกมันอาจให้ระยะทางที่สั้นกว่ารูทใด ๆ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.