中国石凳联盟 登录注册

贝塞尔曲线德卡斯特里奥(de Casteljau)算法及程序

rockage··2 回复·291 浏览

发表回复


1) 描述




de Casteljau算法最基本的概念就是在线段AB中找到C点,使得C点将AB线段划分成u:(1-u)比例(AC:AB=u),怎么找这个C点呢?





A 到 B 的向量是 B – A ,因为u在0到1之间,所以C点就在u(B – A)处,考虑到A点的位置,C点的位置是A + u(B – A) = (1 – u)A + uB,因此,对于一个给定的u,(1–u)A + uB就是在A 和 B之间的C点,C点将AB线段划分成u:(1–u)比例。




de Casteljau算法的思想如下面所述:假设我们要求C(u),其中u 在 之间,从第一个多边开始,00-01-02-03...-0n,用上面的公式求得一个在0i 到0(i+1)的线段上的点1i,1i点将0i 到0(i+1)的线段划分成u:(1–u)比例;这样我们可以得到n 个点10, 11, 12, ...., 1(n-1),它们形成了新的n–1条线段。





上图中,u = 0.4,10 是00 到01线段上的点,11是01到02线段上的点,…,14是04到05线段上的点,所有的新点是兰色显示的。




新点按1i方式命名,对这些新点执行相同的操作,我们将可以得到第二个由(20, 21,…,2(n-2))n–1个点组成的多边和n–2条边;再次进行该操作,我们将可以得到第三个由(30, 31,…,3(n-3))n–2个点组成的多边和n–3条边;如此循环进行n次后,将产生一个单点n0;de Casteljau证明这个点就是我们要求的C(u)。




让我们继续看上面的图形,得到10 到11的线段上的点20将10 到11的线段划分成u:(1–u)比例,同样可以得到11 到12的线段上的点21,12 到13的线段上的点22,13 到14的线段上的点23,这第三个多边有四个点和三条边;如此继续,我们可以得到由30, 31 和 32三个点组成的新多边;再从这第四个多边,我们可以得到由40 和41 两个点组成的第五个多边;如此再进行一次,我们可以得到50, 这就是曲线上我们要求的C(u)。




这就是de Casteljau算法的几何解释,非常美妙的曲线设计。









注:以上原文出自





http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html










2) 程序




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




// pDC 设备




// flArrayx 组成点x坐标序列




// flArrayy 组成点y坐标序列




//created by: handwolf




//create time: 2004-10-1




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




int deCasteljau(CDC *pDC,CArrayfloat,float flArrayx,CArrayfloat,float flArrayy)




{




if(flArrayx.GetSize()!=flArrayy.GetSize())




return 0




float *pflX,*pflY




float flTempx,flTempy,flU//flu-------u参数




int i,n,j




n=flArrayx.GetSize()




if(n2) return 0




pflX=new float




pflY=new float




flTempx=flArrayx.GetAt(0)




flTempy=flArrayy.GetAt(0)




for(i=0ini++){




pflX=flArrayx.GetAt(i)




pflY=flArrayy.GetAt(i)




}




for(flU=0flU=1flU+=0.05/n){




for(i=1ini++){




for(j=0jn-ij++){




pflX=(1-flU)*pflX+flU*pflX




pflY=(1-flU)*pflY+flU*pflY




}




}




pDC-MoveTo(flTempx,flTempy)




pDC-LineTo(pflX,pflY)




flTempx=pflX




flTempy=pflY




}




delete pflX




delete pflY




return 1




}




////////////////////////////////////////////////////


点赞0 收藏
  航迹的3D向量点与点的连接使用贝塞尔曲线算法。这套曲线算法大致是这样的。
  如果已知一条曲线的参数方程,系数都已知,并且两个方程里都含有一个参数t,它的值介于0、1之间,表现形式如下所示:
  x(t) = ax * t ^ 3 + bx * t ^ 2 + cx * t + x0
  y(t) = ay * t ^ 3 + by * t ^ 2 + cy * t + y0
  
  由于这条曲线的起点(x0,y0)是已知的,我们可以用以下的公式来求得剩余三个点的坐标:
  x1 = x0 + cx / 3
  x2 = x1 + ( cx + bx ) / 3
  x3 = x0 + cx + bx + ax
  
  y1 = y0 + cy / 3
  y2 = y1 + ( cy + by ) / 3
  y3 = y0 + cy + by + ay
  
  你细细观察一下就知道了,无论方程的已知和所求是什么,总是有六个未知数,并且我们总能找到六个等式(记住(x0,y0)总是已知的),也就是说,上面的方法是完全可逆的,因此我们可以根据四个已知点坐标来反求曲线参数公式的系数。稍微一变换就得到了下面这组公式:
  cx = 3 * ( x1 - x0 )
  bx = 3 * ( x2 - x1 ) - cx
  ax = x3 - x0 - cx - bx
  
  cy = 3 * ( y1 - y0 )
  by = 3 * ( y2 - y1 ) - cy
  ay = y3 - y0 - cy - by
  
  而做航迹的根据时间和速度来解算当前物体位于贝塞尔曲线中的位置,当然,因为飞机在转弯,倾斜的时候,飞行速度都会受到影响,等等,等等,可能有很多现在我还没有想到的地方。我推荐做法是,在解算完贝塞尔曲线以后,顺带一起解算那条航迹的长度,然后根据时间来解算飞机所处的航迹的具体位置这样就方便很多了。
点赞0 收藏

Finding a Point on a Bézier Curve: De Casteljaus Algorithm



Following the construction of a Bézier curve, the next important task is to find the point
C
(
u
) on the curve for a particular
u
. A simple way is to plug
u
into every basis function, compute the product of each basis function and its corresponding control point, and finally add them together. While this works fine, it is not numerically stable (
i.e.
, could introduce numerical errors during the course of evaluating the Bernstein polynomials).

In what follows, we shall only write down the control point numbers. That is, the control points are
00
for
P

0
,
01
for
P

1
, ...,
0
i

for
P


i

, ...,
0
n

for
P


n

. The
0
s in these numbers indicate the initial or the 0-
th
iteration. Later on, it will be replaced with
1
,
2
,
3
and so on.

The fundamental concept of de Casteljaus algorithm is to choose a point
C
in line segment
AB
such that
C
divides the line segment
AB
in a ratio of
u
:1-
u
(
i.e.
, the ratio of the distance between
A
and
C
and the distance between
A
and
B
is
u
). Let us find a way to determine the point
C
.







The vector from
A
to
B
is
B - A
. Since
u
is a ratio in the range of 0 and 1, point
C
is located at
u
(
B - A
). Taking the position of
A
into consideration, point
C
is
A
+
u
(
B - A
) = (1 -
u
)
A
+
u

B
. Therefore, given a
u
, (1 -
u
)
A
+
u

B
is the point
C
between
A
and
B
that divides
AB
in a ratio of
u
:1-
u
.

The idea of de Casteljaus algorithm goes as follows. Suppose we want to find
C
(
u
), where
u
is in . Starting with the first polyline,
00-01-02-03...-0
n

, use the above formula to find a point
1
i

on the leg (
i.e.
line segment) from
0
i

to
0(
i
+1)
that divides the line segment
0
i

and
0(
i
+1)
in a ratio of
u
:1-
u
. In this way, we will obtain
n
points
10
,
11
,
12
, ....,
1(
n
-1)
. They define a new polyline of
n
- 1 legs.







In the figure above,
u
is 0.4.
10
is in the leg of
00
and
01
,
11
is in the leg of
01
and
02
, ..., and
14
is in the leg of
04
and
05
. All of these new points are in blue.

The new points are numbered as
1
i

s. Apply the procedure to this new polyline and we shall get a second polyline of
n
- 1 points
20
,
21
, ...,
2(
n
-2)
and
n
- 2 legs. Starting with this polyline, we can construct a third one of
n
- 2 points
30
,
31
, ...,
3(
n
-3)
and
n
- 3 legs. Repeating this process
n
times yields a single point

n
0
. De Casteljau proved that this is the point
C
(
u
) on the curve that corresponds to
u
.

Let us continue with the above figure. Let
20
be the point in the leg of
10
and
11
that divides the line segment
10
and
11
in a ratio of
u
:1-
u
. Similarly, choose
21
on the leg of
11
and
12
,
22
on the leg of
12
and
13
, and
23
on the leg of
13
and
14
. This gives a third polyline defined by
20
,
21
,
22
and
23
. This third polyline has 4 points and 3 legs. Keep doing this and we shall obtain a new polyline of three points
30
,
31
and
32
. From this fourth polyline, we have the fifth one of two points
40
and
41
. Do it once more, and we have
50
, the point
C
(0.4) on the curve.

This is the geometric interpretation of de Casteljaus algorithm, one of the most elegant result in curve design.








Actual Computation
Given the above geometric interpretation of de Casteljaus algorithm, we shall present a computation method, which is shown in the following figure.







First, all given control points are arranged into a column, which is the left-most one in the figure. For each pair of adjacent control points, draw a south-east bound arrow and a north-east bound arrow, and write down a new point at the intersection of the two adjacent arrows. For example, if the two adjacent points are
ij
and
i(j+1)
, the new point is
(i+1)j
. The south-east (
resp.
, north-east) bound arrow means multiplying 1 -
u
(
resp.
,
u
) to the point at its tail,
ij
(
resp.
,
i(j+1)
), and the new point is the sum.

Thus, from the initial column, column
0
, we compute column
1
from column
1
we obtain column
2
and so on. Eventually, after
n
applications we shall arrive at a single point

n
0
and this is the point on the curve. The following algorithm summarizes what we have discussed. It takes an array
P
of
n
+1 points and a
u
in the range of 0 and 1, and returns a point on the Bézier curve
C
(
u
).






Input:
array
P

n
of
n
+1 points and real number
u
in

Output:
point on curve,
C
(
u
)

Working:
point array
Q

n



for

i
:= 0
to

n

do




Q

i
:=
P

i
// save input


for

k
:= 1
to

n

do




for

i
:= 0
to

n - k

do




Q

i
:= (1 -
u
)
Q

i
+
u

Q

i
+ 1


return

Q










A Recurrence Relation
The above computation can be expressed recursively. Initially, let
P

0,
j

be
P


j

for
j
= 0, 1, ...,
n
. That is,
P

0,
j

is the
j
-th entry on column 0. The computation of entry
j
on column
i
is the following:







More precisely, entry
P


i
,
j

is the sum of (1-
u
)
P


i
-1,
j

(upper-left corner) and
u

P


i
-1,
j
+1
(lower-left corner). The final result (
i.e.
, the point on the curve) is
P


n
,0
. Based on this idea, one may immediately come up with the following recursive procedure:






function


deCasteljau

(
i
,
j
)

begin




if

i
= 0
then




return

P

0,
j




else




return
(1-
u
)*

deCasteljau

(
i
-1,
j
) +
u
*

deCasteljau

(
i
-1,
j
+1)


end




This procedure looks simple and short however, it is extremely inefficient. Here is why. We start with a call to

deCasteljau

(
n
,0) for computing
P


n
,0
. The
else
part splits this call into two more calls,

deCasteljau

(
n
-1,0) for computing
P


n
-1,0
and

deCasteljau

(
n
-1,1) for computing
P


n
-1,1
.







Consider the call to

deCasteljau

(
n
-1,0). It splits into two more calls,

deCasteljau

(
n
-2,0) for computing
P


n
-2,0
and

deCasteljau

(
n
-2,1) for computing
P


n
-2,1
. The call to

deCasteljau

(
n
-1,1) splits into two calls,

deCasteljau

(
n
-2,1) for computing
P


n
-2,1
and

deCasteljau

(
n
-2,2) for computing
P


n
-2,2
. Thus,

deCasteljau

(
n
-2,1) is called twice. If we keep expanding these function calls, we should discover that almost all function calls for computing
P


i
,
j

are repeated, not once but many times. How bad is this? In fact, the above computation scheme is identical to the following way of computing the
n
-th Fibonacci number:




function


Fibonacci

(
n
)

begin



if

n
= 0
or

n
= 1
then




return
1


else



return


Fibonacci

(
n
-1) +

Fibonacci

(
n
-2)


end


This program takes an exponential number of function calls (an exercise) to compute

Fibonacci

(
n
). Therefore, the above recursive version of de Casteljaus algorithm is


not


suitable for direct implementation, although it looks simple and elegant!









An Interesting Observation



The triangular computation scheme of de Casteljaus algorithm offers an interesting observation. Take a look at the following computation on a Bézier curve of degree 7 defined by 8 control points
00
,
01
, ...,
07
. Let us consider a set of consecutive points on the same column as the control points of a Bézier curve. Then, given a
u
in , how do we compute the corresponding point on this Bézier curve? If de Casteljaus algorithm is applied to these control points, the point on the curve is the opposite vertex of the equilaterals base formed by the selected points!







For example, if the selected points are
02
,
03
,
04
and
05
, the point on the curve defined by these four control points that corresponds to
u
is
32
. See the blue triangle. If the selected points are
11
,
12
and
13
, the point on the curve is
31
. See the yellow triangle. If the selected points are
30
,
31
,
32
,
33
and
34
, the point on the curve is
70
.

By the same reason,
70
is the point on the Bézier curve defined by control points
60
and
61
. It is also the point on the curve defined by
50
,
51
and
52
, and on the curve defined by
40
,
41
,
42
and
43
. In general, if we select a point and draw an equilateral as shown above, the base of this equilateral consists of the control points from which the selected point is computed.
点赞0 收藏
发表回复
发表回复