Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Построение контура кривой Безье


kingdom ©   (2005-01-24 10:45:00) 

Привет всем!

Кто-нибудь занимался построение контура к кривой Безье?

Задача такая, дана кривая Безье 2 или 3 порядка, дано расстояние от кривой до контура.
Нужно построить контур из кривых Безье 2 и 3 порядка соответственно с заданной точностью.
Критерий точности можно выбра самому, главное чтобы он был разумным =)
Напомню, что контур это кривая расстояние между которой и исходной кривой константа.
Достаточно вычислить контур с одной стороны от исходной кривой.

Заранее всем спасибо!


kingdom   (2005-01-27 15:47:00) [1]

>Григорьев Антон
Спасибо за ответ

Как ты правильно сказал, этот способ медленный и это не совсем то, что мне надо. Мне не надо рисовать контур, мне надо построить контур.

У меня получился такой алгоритм для кривых Безье 2 степени, берем исходную кривую и строим к ней кривую Безье, которая в точках 0 и 1 находится на заданном расстоянии от исходной и имеет такае же производные как у исходной. Такая кривая определяется однозначно. Расстояние между кривыми в точке 0.5 будет больше заданного, поэтому нужно иметь оценочную функцию, которая скажет велико ли отклонение. Если велико, то делим исходную кривую на две части и повторяем действия, иначе для данного участка исходной кривой контур найден.

Вопрос в том, как выглядит эта оценочная функция?


Григорьев Антон   (2005-01-27 07:46:00) [2]

Можно подойти к этой проблеме с другого конца. Пусть для каждой точки кривой Безье мы постороили круг с центром в этой точке и радиусом, равным той самой константе, задающей расстояние от контура до кривой. Граница фигуры, которую составляют все эти круги, как раз и будет требуемым контуром.

Чтобы построить такую фигуру, нужно выполнить следующие действия:
1. Построить траекторию на основе кривой Безье (BeginPath/PolyBezier/EndPath).
2. Привести внутреннее представление траектории к ломаной, состоящей из отреков прямых (FlattenPath).
3. Получить координаты узлов этой ломаной (GetPath).
4. Пройтись по всем звеньям ломаной и с помощью LineDDA получить координаты всех промежуточных точек.
5. Для каждой из полученных точек создать регион в виде круга заданного радиуса (CreateEllipticRgn) и объединить все эти регионы в один (CombineRgn).
6. Построить контур полученного региона (FrameRgn). Всё, задача решена.

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

Пример действий п. 1-4 можно посмотреть на http://www.delphikingdom.com/asp/viewitem.asp?catalogid=881


kingdom   (2005-01-25 18:36:00) [3]

Вот я и пробую ))
Вопрос в том какую метрику выбрать?
Экспериментировал с k(0) - k(1), плохо работает.
Я думаю есть метрика геометрически обоснованная, буду искать.

MBo спасибо, ты мне очень помог!


MBo   (2005-01-25 18:28:00) [4]

Тут без проб трудно посоветовать. пробеги по кривой, скажем, в 5-10 точках, оценивай кривизну. участки с большой кривизной еще подели


kingdom   (2005-01-25 18:19:00) [5]

У меня осталася только один вопрос, как определить, что кривую надо разбить?
Пробую брать разницу кривизны в начале и в конце кривой. Если больше некоторого числа, то делить. Однако, на практике видно, что это не очень хороший вариант, появляется много делений на плавных участках.


MBo   (2005-01-25 18:15:00) [6]

Я попробовал - совпадает. Убедись, что правильно делишь(отрисовкой всех трех кривых) и  покажи код вычисления кривизны.


kingdom   (2005-01-25 17:37:00) [7]

Короче, я тормозить начал под вечер, все нармально =)))


kingdom   (2005-01-25 17:26:00) [8]

Подели кривую (q) на левую и правую половину (lq, rq)
q(0) = lq(0)
q(1) = rq(1)
кривизна q в точке 0 не равна кривизне lq в точке 0


MBo   (2005-01-25 17:10:00) [9]

1. Не понял, какая точка 0.0 имеется в виду
2. Уверен, что кривую правильно разбиваешь?


kingdom   (2005-01-25 16:57:00) [10]

Странная вещь получается...
Если разбить кривую пополам, то кривизна, например, в точке 0.0 для исходной и новой половинки не совпадает, она уменьшается =(

Как это можно объяснить?


kingdom   (2005-01-25 14:17:00) [11]

Я нашел ошибку, производную неправильно взял,
спасибо!

Буду дальше разбираться =)


MBo   (2005-01-25 13:42:00) [12]

вот как получается

k=dFi/dl=(ArcTan(Y'/X'))'/Sqrt(dX^2+dY^2)=(Y'/X')'*ArcTan()'/Sqrt(dX^2+dY^2)=(Y''X'-Y'X'')/(X')^2*(1/(1+(Y'/X')^2)/Sqrt( dX^2+dY^2)=(Y''X'-Y'X'')/(dX^2+dY^2)^3/2


MBo   (2005-01-25 13:08:00) [13]

>у тебя есть ссылка на вывод этой формулы
Нет.
Примерно отсюда нужно исходить: кривизна по определению есть предел отношения угла поворота касательной к длине дуги, и
для малых углов Fi~Tan(Fi)=dy/dx


kingdom   (2005-01-25 12:52:00) [14]

>MBo
Спасибо! Это мне очень поможет =)
Может у тебя есть ссылка на вывод этой формулы, а то у меня другая получалась.


MBo   (2005-01-25 08:05:00) [15]

>Не могу найти формулы кривизны для Кривой Безье

из дифф. геометрии - кривизна параметрической плоской кривой (величина, обратная радиусу кривизны):

k=1/R = (X'Y'' - Y' X'')/(X'^2+Y'^2)^3/2
(первые и вторые производные по параметру t)

P.S. встречал упоминание о методе аппроксимации Tiller-Hanson - там, кажется, делают примерно так, как я описал, только сплайны не строят, сразу Безье по неким критериям.
Кроме того, глянь www.truetex.com, описание MetaFog.


kingdom   (2005-01-24 18:02:00) [16]

>MBo
Спасибо за ответ!
Не могу найти формулы кривизны для Кривой Безье

>REA
Пишу графическую библиотеку, нужно что-то типа StrokePath сделать


REA   (2005-01-24 12:57:00) [17]

А какая если не секрет предметная область?


MBo   (2005-01-24 12:28:00) [18]

В дополнение: "плохими местами" будут те, где радиус кривизны кривой меньше офсета. По крайней мере, в точках, где эти величины совпадают, исходную кривую стоит порезать.


MBo   (2005-01-24 11:52:00) [19]

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

Приближение - строим перпендикуляры нужной длины к кривой (с постоянным шагом по t или меняем шаг в зависимости от кривизны кривой), через полученные точки проводим какие-либо кубические сплайны (в зависимости от требуемой гладкости), переводим сплайны в базис полиномов Бернштейна.


REA   (2005-01-24 10:51:00) [20]

Сплайны рисовал, Безье не рисовал...


Наверх

Титульная страница Поиск, карта сайта Написать письмо