28.02.2013, 13:37. Просмотров 2125. Ответов 2
Нужны советы (скорее алгоритмические) по одной задаче.
Даны опорные точки кривой Безье, начальный и конечный параметры t0 и t1(0<t<1), а также значение ширины. Требуется "залить полосу" данной ширины вдоль кривой Безье, начиная с (x(t0),y(t0)) до (x(t1),y(t1)) причем желательно быстро.
Важно то, что ширину нужно откладывать вдоль перпендикуляра к кривой в данной точке.
Пробовал два подхода. Первый - это строить перпендикуляры в каждой точке, считать точку конца отрезка, прорисовывать линию. Второй - это строить круги в каждой точке с диаметром равным ширине.
Первый способ быстрее, но остаются пробелы между линиями. Недостаток второго способа это то, что почти каждая точка закрашивается несколько раз. К тому же почему-то идет расхождения между решениями(рисунок во вложении).
Красное - результат решения с кругами, черное-с перпендикулярами, зеленое - кривая Безье, построенная стандартными средствами C++(GDI+).
Вот содержательная часть кода.
C |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| for (double t = start; t < finish+STEP; t += STEP) {
if (t > 1) {
t = 1;
}
for (int i = 0; i < 4; i++) {
double b = getBezierBasis(i, 3, t);
double k=getDBasis(i,3,t);
res[ind].X += (int)floor(p[i].X * b);
res[ind].Y += (int)floor(p[i].Y * b);
res2[ind].X += (int)floor(p[i].X * k);
res2[ind].Y += (int)floor(p[i].Y * k);
}
double tg=1/res2[ind].Y;
double dy=l*sqrt(tg*tg+1);
double dx=(dy*tg);
pen.SetColor(Color(0,0,0));
graphics.DrawLine(&pen,res[ind].X,res[ind].Y,res[ind].X+dx,res[ind].Y+dy);
stat = graphics.FillEllipse(&solidBrush,res[ind].X,res[ind].Y,l*5,l*5);
ind++;
pen.SetColor(Color(0,255,0));
graphics.DrawBezier(&pen,p[0],p[1],p[2],p[3]);
} |
|
Может кто-нибудь делал что-нибудь подобное? Есть ли еще какие-либо решения этой задачи? Подозреваю, что как-то можно использовать афинную инвариантность кривой Безье.