Я просто хочу дать вам несколько советов, для случая Q.B.Curve // сегмент:
чтобы получить достаточно быстрое вычисление, я думаю, что вы должны сначала подумать об использовании своего рода «ограничивающей рамки» для вашего алгоритма.
Скажем, P0 - первая точка Q. B. Кривая, P2 - вторая точка, P1 - контрольная точка, а P3P4 - сегмент:
- Вычислить расстояние от P0, P1, P2 до P3P4
- , если P0 ИЛИ P2 - ближайшая точка -> это ближайшая точка кривой от P3P4. конец: =).
- если P1 является ближайшей точкой, а Pi (i = 0 или 1) второй ближайшей точкой, расстояние между PiPC и P3P4 является оценкой искомого расстояния, которое может быть достаточно точным, в зависимости от на ваши нужды.
- если вам нужно быть более точным: вычислите P1 ', которая является точкой на Q.B.Curve, ближайшей к P1: вы обнаружите, что она применяет формулу BQC с t = 0,5. -> расстояние от PiP1 'до P3P4 является еще более точной оценкой, но более дорогостоящим.
- Обратите внимание, что если линия, определенная P1P1 ', пересекает P3P4, P1' является ближайшей точкой QBC от P3P4.
- если P1P1 'не пересекает P3P4, значит, вам не повезло, вы должны идти нелегким путем ...
Теперь, если (и когда) вам нужна точность:
Подумайте об использовании алгоритма «разделяй и властвуй» для параметра кривой:
который ближайший от P3P4 ?? P0P1 'или P1'P2 ??? если это P0P1 '-> t находится между 0 и 0,5, то вычислите Pm для t = 0,25.
Теперь, что является ближайшим от P3P4 ?? P0Pm или PmP1 '?? если это PmP1 '-> вычислить Pm2 для t = 0,25 + 0,125 = 0,375, то какой из них ближайший? PmPm2 или Pm2P1 '??? так далее
Вы сразу же получите точное решение, например, 6 итераций, а ваша точность на t равна 0,004 !! Вы можете остановить поиск, когда расстояние между двумя точками станет ниже заданного значения. (а не разница между двумя параметрами, так как для небольшого изменения параметра точки могут быть далеко)
на самом деле принцип этого алгоритма состоит в том, чтобы каждый раз аппроксимировать кривую с сегментами все более и более точно.
Для случая кривой / кривой я бы сначала «поставил» их в квадрат, чтобы избежать ненужных вычислений, поэтому сначала используйте вычисление сегмента / сегмента, а затем (возможно) вычисление сегмента / кривой и только при необходимости вычисление кривой / кривой.
Для кривых / кривых, разделяй и властвуй также труднее объяснить, но вы можете понять это. : =)
надеюсь, вы сможете найти хороший баланс для скорости / точности с этим: =)
Edit: думаю, я нашел для общего случая хорошее решение :-)
Вы должны перебрать (внутренние) ограничивающие треугольники каждого B.Q.C.
Таким образом, у нас есть треугольник T1, точки A, B, C, имеющие параметр «t» tA, tB, tC.
и треугольник T2, точки D, E, F, имеющие t-параметр tD, tE, tF.
Первоначально имеем tA = 0 tB = 0,5 tC = 1,0 и то же самое для T2 tD = 0, tE = 0,5, tF = 1,0
Идея состоит в том, чтобы рекурсивно вызывать процедуру, которая разделит T1 и / или T2 на более мелкие прямоугольники, пока мы не будем в порядке с достигнутой точностью.
Первым шагом является вычисление расстояния от T1 до T2, отслеживая, чтобы сегменты были ближайшими в каждом треугольнике. Первый «трюк»: если на T1 сегмент AC, то остановите рекурсивность на T1, ближайшая точка на кривой 1 - это A или C. Если на T2 ближайший сегмент - DF, то остановите рекурсивность на T2, ближайшая точка на Кривая 2 - это либо D, либо F. Если мы остановили рекурсивность для обоих -> расстояние возврата = min (AD, AF, CD, CF). тогда, если у нас есть рекурсивность на T1, и сегмент AB ближайший, новый T1 становится: A '= AB = точка кривой с tB = (tA + tC) / 2 = 0,25, C = старая B. То же самое относится и к T2: применить рекурсивность, если необходимо, и вызвать тот же алгоритм на новом T1 и новом T2 Остановите алгоритм, когда найденное расстояние между T1 и T2 минус расстояние, найденное между предыдущими T1 и T2, ниже порогового значения.
функция может выглядеть как ComputeDistance (curveParam1, A, C, shouldSplitCurve1, curveParam2, D, F, shouldSplitCurve2, previousDistance), где точки хранят также свои t-параметры.
обратите внимание, что расстояние (кривая, сегмент) является лишь частным случаем этого алгоритма, и что вы должны реализовать расстояние (треугольник, треугольник) и расстояние (сегмент, треугольник), чтобы он работал. Веселитесь.