Надежный тест на пересечение двух кривых Безье

9

Как достоверно определить, пересекаются ли две плоские кривые Безье? Под «надежно» я подразумеваю, что тест будет отвечать «да» только тогда, когда кривые пересекаются, и «нет» только тогда, когда они не пересекаются. Мне не нужно знать, по каким параметрам было найдено пересечение. Я также хотел бы использовать числа с плавающей точкой в ​​реализации.

Я нашел несколько ответов по StackOverflow, в которых для теста используются ограничивающие рамки кривых: это не то, что мне нужно, поскольку такой тест может сообщать о пересечении, даже если кривые не пересекаются.

Самая близкая вещь, которую я нашел до сих пор, это « ограничивающий клин » Седерберга и Мейерса, но он «только» различает пересечение не более одного и не более двух, в то время как я хочу знать, есть ли самое большее ноль и одно или более пересечений.

Ecir Hana
источник
Я не уверен, что он существует как таковой, определение wetehr или вероятности того, что 0-1 или 2 или более, является довольно тривиальным, но формулировка на самом деле не делает его простым, чтобы убедиться, что его 0 или 1 без фактической проверки.
joojaa
Каковы требования времени выполнения? Решение, которое должно быть в состоянии дать довольно точные результаты, состояло бы в том, чтобы аппроксимировать обе кривые большим количеством коротких прямых отрезков и затем пересекать их попарно. Но это стоит много времени и памяти.
Dragonseel
@Dragonseel Хорошо, я был бы рад любому решению, на самом деле, но так как вы спросили, O (1) было бы хорошо. Но приближение кривых с отрезками линий приводит к тем же проблемам, что и тест на перекрытие ограничивающего прямоугольника ...
Ecir Hana
Интересная проблема. Я не думаю, что есть простой ответ, но я бы хотел ошибиться. У вас есть ссылка на газету Седерберга и Мейерса?
Даниэль М Гессель
@DanielMGessel Да, см. Правку выше.
Ecir Hana

Ответы:

6

Альтернативный способ постановки задачи - определить функцию, которая дает расстояние между точками на двух кривых в зависимости от параметров кривых. Затем попытайтесь найти глобальный минимум этой функции. Если кривые пересекаются, минимум будет равен нулю; в противном случае минимальным будет некоторое положительное расстояние.

Чтобы быть явным, учитывая пару двумерных кривых, определенных с помощью , определите квадрат расстояния какc1,c2:[0,1]R2

f(u,v):[0,1]2R0|c2(v)c1(u)|2

Для кубических кривых функция является полиномом шестой степени от двух переменных. Затем можно применить методы численной оптимизации, такие как симплекс-метод или сопряженный градиентный спуск . К сожалению, функция может иметь несколько локальных минимумов (это не выпукло), поэтому оптимизация не легка. Для полиномов могут быть более специализированные методы оптимизации, но для меня это не область знаний.f

Натан Рид
источник
Почему это полином 6-й степени, а не 3-й степени, если мы говорим о кубических Безье? И два метода, с которыми вы связаны, способны ли они находить решения только в , в отличие от всего ? [0,1]2R2
Ecir Hana
1
@EcirHana Это 6-я степень, потому что это квадратное расстояние. (Вы можете получить квадратный корень, но тогда он больше не будет полиномом и будет не гладким в нуле.) Обратите внимание, что - это пространство параметров, а не пространство, в котором живут сплайны, т.е. сплайны с конечными точками. В любом случае, методы будут хорошо работать в , но они только «спускаются» из первоначального предположения и находят локальный минимум; требуется нечто большее, чтобы изучить всю область параметров и найти глобальный минимум. Ограничение пространства параметров, вероятно, полезно там. [0,1]R2
Натан Рид
1
Натан - хорошая формулировка! Я ржавый, но: я думаю, что вы можете разделить каждую кривую Безье на самое большее 5 сегментов, где или изменяют направление на кривой. , в зависимости от меняет направление максимум дважды (корни производной), разбивая кривую на 3 сегмента, 2 из которых могут быть снова разделены путем изменения направления . Теперь у вас есть не прямые сегменты, а сегменты, которые не слишком сильно изгибаются. Я думаю, что если вы начнете поиск в 25 точках, выбранных парами сегментов, вы всегда сможете найти глобальные минимумы, но я не совсем понимаю, как это доказать (или опровергнуть). xyxciy
Даниэль М Гессель
@Nathan: Я думал об этом, но, потратив много времени на написание кода для поиска минимумов в форматах сжатия текстур, все это казалось немного отвратительным.
Симон Ф
5

[Отказ от ответственности: я думаю, что следующее должно работать, но на самом деле не кодировал это сам]

Я не мог придумать «тривиальный» метод получения ответа «да / нет», но следующее было бы разумным подходом к практическому решению вопроса.

Предположим, что наши кривые A (s) и B (t) с контрольными точками { A0, A1..An } и { B0, .. Bm } соответственно.

Мне кажется, что, учитывая пару двумерных Безье, для которых мы хотим определить, пересекаются ли они, можно рассмотреть шесть случаев:

  1. Случай, когда мы можем «тривиально» определить, что они не пересекаются.

  2. Случай, когда они пересекаются конечное число раз, и мы можем «легко» определить, что они определенно пересекаются хотя бы один раз (но нам на самом деле все равно, где эти пересечения происходят)

  3. Один из Безье является вырожденным, то есть точкой (которая возникнет, если все контрольные точки идентичны). Можно предположить, что мы уже обработали случай, когда оба являются точками.

  4. Одна или несколько кривых закрыты, например, A0 == An. Чтобы упростить жизнь, мы поделим такие кривые и начнем снова.

  5. Существует бесконечное количество точек пересечения, потому что каждая является подмножеством «родительского» Безье, и они перекрываются.

  6. Мы не уверены в вышеуказанных случаях и нуждаемся в дальнейшем расследовании

На данный момент мы проигнорируем 3 и 4, но вернемся к ним позже.

Дело 1

Как вы намекаете в своем вопросе, если соответствующие ограничивающие рамки контрольных точек A и B ) не пересекаются, то кривые не могут пересекаться. Очевидно, это быстрый тест на отклонение, но он слишком консервативный. Как вы, вероятно, знаете, с кривой Безье выпуклая оболочка ее контрольных точек образует (более плотную) границу кривой. Таким образом, мы можем использовать технику разделительной оси, чтобы решить , не пересекаются ли оболочки A и B. (например, как показано в Википедии :)

введите описание изображения здесь

Дело 2

Если проверка в случае 1 не пройдена, вы можете проверить наличие «тривиального» пересечения. Теперь, возможно, есть лучшие способы сделать это, но мне пришёл в голову следующий, относительно дешевый подход:

Рассмотрим только кривую А:

"Толстая линия" границы Безье

Мы знаем, что кривая начинается в , заканчивается в и будет лежать внутри выпуклой оболочки. Для простоты давайте вычислим направление отрезка линии и вычислим границы с обеих сторон (т.е. возьмем произведения точек оставшихся контрольных точек относительно перпендикуляра к ).A n ¯ A 0 A n ¯ A 0 A nA0AnA0An¯A0An¯

Если мы сделаем то же самое с кривой B, мы получим следующий (возможный) случай: введите описание изображения здесь

Если мы находим и находятся вне противоположные границы B , и что и находятся на внешней стороне рамки А, то, в силу непрерывности Безье, должно быть по крайней мере , одно пересечение.A n B 0 B мA0AnB0Bm

Дело 6

Если мы не можем сразу показать ни один из вышеперечисленных случаев, то разделим каждый из Безье на две «половины», то есть . Это относительно просто (оставлено в качестве упражнения для читателя), но особенно тривиально для квадратичных Безье :A1,A2,B1,B2

Рекурсивно сравните 4 комбинации: . Ясно, что если все проходят случай 1, пересечения нет. Если произойдет сбой 1, продолжите остальные тесты с этим сокращенным подмножеством.(A1,B1),(A2,B1)...(A2,B2)

Случай 3 и 5

Это где это становится немного более утомительным.

Если «случай 3» проходит тест «случай 1», мне кажется, что вам нужно найти фактическое пересечение. Учитывая, что существует простой процесс сопоставления N контрольных точек Безье, A (s), с N-1 точками Безье, A '(s), представляющими его 1-ю производную (при условии, что для в относительно редких, так называемых «вырожденных» ситуациях, когда 1-я производная стремится к нулю), затем итерация Ньютона (в одном измерении) может использоваться для поиска потенциальных решений.
Отметим также, что, поскольку контрольные точки A '(s) являются границей производных значений, в некоторых случаях существует возможность досрочного устранения.

Случай 5 представляется относительно маловероятным, поэтому, возможно, только если после нескольких рекурсий нет убедительных доказательств, можно попробовать каждую конечную точку A с кривой B и наоборот. Это дало бы только доказательство пересечения, но не доказательство отсутствия пересечения.

Саймон Ф
источник
Да, но мне лично больше интересен случай, когда о случае, когда Bm и / или B0 находятся в пределах объема A max и min, но не пробивают его, тогда вам нужно подразделить и в худшем случае рассчитать пересечение точка. Лучше было бы использовать минимальную ограничивающую рамку, также известную как аппроксимация толстой линией.
joojaa
Учитывая, что с каждым бинарным делением разница между кривой и отрезком, соединяющим конечные точки, уменьшается на разумный коэффициент (и, на мой взгляд, это может быть 4х для квадратиков), конечно, границы идут довольно быстро сходиться к «тонкой» ленте.
Симон Ф
Да, но в худшем случае, другой Безье начинается с другого.
joojaa
Вы имеете в виду, например, An == B0 . Вы определяете это как пересечение или нет?
Симон Ф
Больше не похоже на то, что B0 находится где-то на кривой. Или даже просто минимальное пересечение
joojaa