Функция для возврата списка точек на кривой Безье с одинаковой длиной дуги - PullRequest
5 голосов
/ 27 января 2010

Кто-то где-то должен был решить эту проблему. Я могу найти много отличных веб-сайтов, объясняющих эту проблему и способы ее решения. Хотя я уверен, что они хорошо написаны и имеют смысл для математических свистов, это не я. И хотя я могу понимать это нечетко, я не понимаю, как превратить эту математику в функцию, которую я могу использовать.

Поэтому я прошу вас, если у вас есть функция, которая может сделать это на любом языке (даже на ассемблере Fortran или Heck 6502) - пожалуйста, помогите мне.

  • предпочитаю аналитическое решение итеративному

РЕДАКТИРОВАТЬ: хочу указать, что это кубический Безье, с которым я пытаюсь работать.

1 Ответ

3 голосов
/ 19 ноября 2010

То, что вы просите, это обратная функция длины дуги. Итак, для кривой B вам нужна функция Linv (len), которая возвращает a t от 0 до 1, так что длина дуги кривой между 0 и t равна len.

Если бы у вас была эта функция, вашу проблему действительно легко решить. Пусть B (0) будет первой точкой. Чтобы найти следующую точку, вы просто вычислите B (Linv (w)), где w - это «равная длина дуги», на которую вы ссылаетесь. Чтобы получить следующий балл, просто оцените B (Linv (2 * w)) и т. Д., Пока Linv (n * w) не станет больше 1.

Мне недавно пришлось столкнуться с этой проблемой. Я придумала или наткнулась на несколько решений, ни одно из которых мне не подходит (но, возможно, они подойдут вам).

Теперь это немного сложно, поэтому позвольте мне сначала дать вам ссылку на исходный код: http://icedtea.classpath.org/~dlila/webrevs/perfWebrev/webrev/raw_files/new/src/share/classes/sun/java2d/pisces/Dasher.java. То, что вы хотите, находится в классе LengthIterator. Вам не нужно смотреть на любые другие части файла. Существует множество методов, которые определены в другом файле. Чтобы добраться до них, просто вырежьте все из / raw_files / до конца URL. Вот как вы это используете. Инициализируйте объект на кривой. Затем, чтобы получить параметр точки с длиной дуги L из начала кривой, просто вызовите next (L) (чтобы получить фактическую точку, просто оцените вашу кривую по этому параметру, используя алгоритм деКастельо или предложение Знека). Каждый последующий вызов next (x) перемещает вас на расстояние x вдоль кривой по сравнению с вашей последней позицией. next возвращает отрицательное число, когда вы выходите за пределы кривой.

Объяснение кода: так, мне нужно было значение t, чтобы длина от B (0) до B (t) имела длину LEN (где LEN известен). Я просто сплющил кривую. Итак, просто делите кривую рекурсивно, пока каждая кривая не окажется достаточно близко к линии (вы можете проверить это, сравнив длину контрольного многоугольника с длиной линии, соединяющей конечные точки). Вы можете вычислить длину этой подкривой как (controlPolyLength + endPointsSegmentLen) / 2. Добавьте все эти длины к аккумулятору и остановите рекурсию, когда значение аккумулятора> = LEN. Теперь назовем последнюю подкатегорию C и пусть [t0, t1] будет ее областью. Вы знаете, что t, которое вы хотите, это t0 <= t <t1, и вы знаете длину от B (0) до B (t0) - назовите это значение L0t0. Итак, теперь вам нужно найти t, для которого длина от C (0) до C (t) равна LEN-L0t0. Это именно та проблема, с которой мы начали, но в меньшем масштабе. Мы могли бы использовать рекурсию, но это было бы ужасно медленно, поэтому вместо этого мы просто использовали тот факт, что C - очень плоская кривая. Мы делаем вид, что C - это прямая, и вычисляем точку в точке t, используя P = C (0) + ((LEN-L0t0) / length (C)) * (C (1) -C (0)). Эта точка на самом деле не лежит на кривой, потому что она находится на линии C (0) -> C (1), но она очень близка к точке, которую мы хотим. Итак, мы просто решаем Bx (t) = Px и By (t) = Py. Это просто поиск кубических корней, который имеет решение с закрытым исходным кодом, но я просто использовал метод Ньютона. Теперь у нас есть t, которое мы хотим, и мы можем просто вычислить C (t), который является фактической точкой.

Я должен упомянуть, что несколько месяцев назад я пролистал бумагу, в которой было другое решение, которое нашло приближение к естественной параметризации кривой. Автор разместил ссылку на нее здесь: Эквидистантные точки на кривых Безье

...