Как достоверно определить, пересекаются ли две плоские кривые Безье? Под «надежно» я подразумеваю, что тест будет отвечать «да» только тогда, когда кривые пересекаются, и «нет» только тогда, когда они не пересекаются. Мне не нужно знать, по каким параметрам было найдено пересечение. Я также хотел бы использовать числа с плавающей точкой в реализации.
Я нашел несколько ответов по StackOverflow, в которых для теста используются ограничивающие рамки кривых: это не то, что мне нужно, поскольку такой тест может сообщать о пересечении, даже если кривые не пересекаются.
Самая близкая вещь, которую я нашел до сих пор, это « ограничивающий клин » Седерберга и Мейерса, но он «только» различает пересечение не более одного и не более двух, в то время как я хочу знать, есть ли самое большее ноль и одно или более пересечений.
источник
Ответы:
Альтернативный способ постановки задачи - определить функцию, которая дает расстояние между точками на двух кривых в зависимости от параметров кривых. Затем попытайтесь найти глобальный минимум этой функции. Если кривые пересекаются, минимум будет равен нулю; в противном случае минимальным будет некоторое положительное расстояние.
Чтобы быть явным, учитывая пару двумерных кривых, определенных с помощью , определите квадрат расстояния какc1,c2:[0,1]→R2
Для кубических кривых функция является полиномом шестой степени от двух переменных. Затем можно применить методы численной оптимизации, такие как симплекс-метод или сопряженный градиентный спуск . К сожалению, функция может иметь несколько локальных минимумов (это не выпукло), поэтому оптимизация не легка. Для полиномов могут быть более специализированные методы оптимизации, но для меня это не область знаний.f
источник
[Отказ от ответственности: я думаю, что следующее должно работать, но на самом деле не кодировал это сам]
Я не мог придумать «тривиальный» метод получения ответа «да / нет», но следующее было бы разумным подходом к практическому решению вопроса.
Предположим, что наши кривые A (s) и B (t) с контрольными точками { A0, A1..An } и { B0, .. Bm } соответственно.
Мне кажется, что, учитывая пару двумерных Безье, для которых мы хотим определить, пересекаются ли они, можно рассмотреть шесть случаев:
Случай, когда мы можем «тривиально» определить, что они не пересекаются.
Случай, когда они пересекаются конечное число раз, и мы можем «легко» определить, что они определенно пересекаются хотя бы один раз (но нам на самом деле все равно, где эти пересечения происходят)
Один из Безье является вырожденным, то есть точкой (которая возникнет, если все контрольные точки идентичны). Можно предположить, что мы уже обработали случай, когда оба являются точками.
Одна или несколько кривых закрыты, например, A0 == An. Чтобы упростить жизнь, мы поделим такие кривые и начнем снова.
Существует бесконечное количество точек пересечения, потому что каждая является подмножеством «родительского» Безье, и они перекрываются.
Мы не уверены в вышеуказанных случаях и нуждаемся в дальнейшем расследовании
На данный момент мы проигнорируем 3 и 4, но вернемся к ним позже.
Дело 1
Как вы намекаете в своем вопросе, если соответствующие ограничивающие рамки контрольных точек A и B ) не пересекаются, то кривые не могут пересекаться. Очевидно, это быстрый тест на отклонение, но он слишком консервативный. Как вы, вероятно, знаете, с кривой Безье выпуклая оболочка ее контрольных точек образует (более плотную) границу кривой. Таким образом, мы можем использовать технику разделительной оси, чтобы решить , не пересекаются ли оболочки A и B. (например, как показано в Википедии :)
Дело 2
Если проверка в случае 1 не пройдена, вы можете проверить наличие «тривиального» пересечения. Теперь, возможно, есть лучшие способы сделать это, но мне пришёл в голову следующий, относительно дешевый подход:
Рассмотрим только кривую А:
Мы знаем, что кривая начинается в , заканчивается в и будет лежать внутри выпуклой оболочки. Для простоты давайте вычислим направление отрезка линии и вычислим границы с обеих сторон (т.е. возьмем произведения точек оставшихся контрольных точек относительно перпендикуляра к ).A n ¯ A 0 A n ¯ A 0 A nA0 An A0An¯¯¯¯¯¯¯¯¯¯¯¯ A0An¯¯¯¯¯¯¯¯¯¯¯¯
Если мы сделаем то же самое с кривой B, мы получим следующий (возможный) случай:
Если мы находим и находятся вне противоположные границы B , и что и находятся на внешней стороне рамки А, то, в силу непрерывности Безье, должно быть по крайней мере , одно пересечение.A n B 0 B мA0 An B0 Bm
Дело 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 и наоборот. Это дало бы только доказательство пересечения, но не доказательство отсутствия пересечения.
источник