请高手讲解贝塞尔曲线的算法,我想自己实现贝塞尔曲线算法?谢谢(100分)

  • 主题发起人 主题发起人 sztsg
  • 开始时间 开始时间
S

sztsg

Unregistered / Unconfirmed
GUEST, unregistred user!
自己如何实现贝塞尔曲线算法?请给出尽量详细的说明?谢谢
 
问题: delphi中有无贝塞尔曲线函数 ( 积分: 50 )
分类: 图形图象

来自: 雨幽公主, 时间: 2003-12-22 16:30:00, ID: 2369468
我是第一次提问,也是个初学者。最近在帮别人编写个曲线绘制程序,其中需要用到贝塞尔曲线,请问delphi中有这个函数吗?如果有,该怎么使用,如果没有,又该怎么解决呢?我现在已经计算出了贝塞尔函数需要用到的几个点的坐标(其实我并不知道贝塞尔曲线到底需要哪些值,只是听别人说需要我算出来的这几个,当然还有好多值,我只是算出了几个点想先试验一下。经过验证我的坐标值是正确的)

来自: andy263, 时间: 2003-12-22 16:37:00, ID: 2369489
没有

来自: 雨幽公主, 时间: 2003-12-22 17:02:00, ID: 2369563
如果没有,那delphi中怎么画贝塞尔曲线?

来自: 暮佳雨, 时间: 2003-12-22 17:04:00, ID: 2369567
canvas.PolyBezier

来自: app2001, 时间: 2003-12-22 17:14:00, ID: 2369600
我这里有一些资料,你瞧瞧吧
在Delph下调用PolyBezier();
procedure TForm1.Button1Click(Sender: TObject);
var point:array[0..6] of Tpoint;
h:HDC;
begin
h:=getdc(form1.handle);
point[0].x:=25; point[0].y:=25;
point[1].x:=35; point[1].y:=170;
point[2].x:=130;point[2].y:=120;
point[3].x:=150;point[3].y:=150;
point[4].x:=170;point[4].y:=280;
point[5].x:=250;point[5].y:=115;
point[6].x:=250;point[6].y:=225;
polybezier(h,point,7);
end;

PolyBezier 画一系列相连的曲线,每一段包含4个point,第一点是曲线起点,
第二点,第三点指定曲线形状的控制点,第四点是曲线终点。
本例中,1为起点,4为中点,7为终点,2,3,5,6为控制点。
OR 调用canvas.polybezier();

*** Drawing CURVES in Delphi? ***
Solution 1
From: dmitrys@phyast.la.asu.edu (Dmitry Streblechenko)

In article <4uijv6$kf7@newsbf02.news.aol.com,
gtabsoft2@aol.com (GTABSoft2) wrote:
Does anyone have source code or info on drawing Bezier curves? I must have
it for my component. Please respond to my email address.
I did this some time ago; I was too lazy to learn how to draw Bezier curves using Win API, so I did it using Polyline().

Note I used floating type values for points coordinates, (I used some kind of virtual screen), just change them to integer.



--------------------------------------------------------------------------------


PBezierPoint = ^TBezierPoint;
TBezierPoint = record
X,Y:double; //main node
Xl,Yl:double; //left control point
Xr,Yr:double; //right control point
end;

//P1 and P2 are two TBezierPoint's, t is between 0 and 1:
//when t=0 X=P1.X, Y=P1.Y; when t=1 X=P2.X, Y=P2.Y;

procedure BezierValue(P1,P2:TBezierPoint; t:double; var X,Y:double);
var t_sq,t_cb,r1,r2,r3,r4:double;
begin
t_sq := t * t;
t_cb := t * t_sq;
r1 := (1 - 3*t + 3*t_sq - t_cb)*P1.X;
r2 := ( 3*t - 6*t_sq + 3*t_cb)*P1.Xr;
r3 := ( 3*t_sq - 3*t_cb)*P2.Xl;
r4 := ( t_cb)*P2.X;
X := r1 + r2 + r3 + r4;
r1 := (1 - 3*t + 3*t_sq - t_cb)*P1.Y;
r2 := ( 3*t - 6*t_sq + 3*t_cb)*P1.Yr;
r3 := ( 3*t_sq - 3*t_cb)*P2.Yl;
r4 := ( t_cb)*P2.Y;
Y := r1 + r2 + r3 + r4;
end;


--------------------------------------------------------------------------------


To draw Bezier curve, split interval between P1 and P2 into several intervals based on how coarse you want your Bezier curve look (3 - 4 pixels looks Ok), then in a loop create an array of points using procedure above with t from 0 to 1 and draw that array of points using polyline().

Solution 2
From: saconn@iol.ie (Stephen Connolly)

gtabsoft2@aol.com (GTABSoft2) wrote:
Does anyone have source code or info on drawing Bezier curves? I must have
it for my component. Please respond to my email address.
I'm posting this here - 'cause: 1. I've seen people ask for this before, 2. The reference is so old I just had to. (BTW I have older references than this ;-P)

I'm sure that there is a standard Borland disclaimer to go with this:



--------------------------------------------------------------------------------


(********************************************************************)
(* GRAPHIX TOOLBOX 4.0 *)
(* Copyright (c) 1985, 87 by Borland International, Inc. *)
(********************************************************************)
unit GShell;

interface

{-------------------------------- snip ----------------------------}

procedure Bezier(A : PlotArray; MaxContrPoints : integer;
var B : PlotArray; MaxIntPoints : integer);

implementation

{-------------------------------- snip ---------------------------}

procedure Bezier{(A : PlotArray; MaxContrPoints : integer;
var B : PlotArray; MaxIntPoints : integer)};
const
MaxControlPoints = 25;
type
CombiArray = array[0..MaxControlPoints] of Float;
var
N : integer;
ContrPoint, IntPoint : integer;
T, SumX, SumY, Prod, DeltaT, Quot : Float;
Combi : CombiArray;

begin
MaxContrPoints := MaxContrPoints - 1;
DeltaT := 1.0 / (MaxIntPoints - 1);
Combi[0] := 1;
Combi[MaxContrPoints] := 1;
for N := 0 to MaxContrPoints - 2 do
Combi[N + 1] := Combi[N] * (MaxContrPoints - N) / (N + 1);
for IntPoint := 1 to MaxIntPoints do
begin
T := (IntPoint - 1) * DeltaT;
if T <= 0.5 then
begin
Prod := 1.0 - T;
Quot := Prod;
for N := 1 to MaxContrPoints - 1 do
Prod := Prod * Quot;
Quot := T / Quot;
SumX := A[MaxContrPoints + 1, 1];
SumY := A[MaxContrPoints + 1, 2];
for N := MaxContrPoints downto 1 do
begin
SumX := Combi[N - 1] * A[N, 1] + Quot * SumX;
SumY := Combi[N - 1] * A[N, 2] + Quot * SumY;
end;
end
else
begin
Prod := T;
Quot := Prod;
for N := 1 to MaxContrPoints - 1 do
Prod := Prod * Quot;
Quot := (1 - T) / Quot;
SumX := A[1, 1];
SumY := A[1, 2];
for N := 1 to MaxContrPoints do
begin
SumX := Combi[N] * A[N + 1, 1] + Quot * SumX;
SumY := Combi[N] * A[N + 1, 2] + Quot * SumY;
end;
end;
B[IntPoint, 1] := SumX * Prod;
B[IntPoint, 2] := SumY * Prod;
end;
end; { Bezier }

end. { GShell }



来自: 雨幽公主, 时间: 2003-12-24 9:14:00, ID: 2372890
app2001老兄,
在Delph下调用PolyBezier()的方法我试了一下,点的坐标只能是整型,而我需要实型。就是把我做出的点四舍五入进去,画出的曲线跑到了窗口的左上角,而且与我用绘图软件做出的差别很大。
请别见笑,Tpoint,hdc,h:=getdc(form1.handle),polybezier(h,point,7)这些是什么意思我不懂,能解释清楚吗?至于下面的两个方法,我在具体的编程中应该怎么引用呢?看的不是很明白,
如果你能帮助我成功实现我的软件功能,我将再给你50分。


来自: duhai_lee, 时间: 2003-12-24 9:47:00, ID: 2373006
Tpoint : 坐标类型吧, 有两个属性,X,Y 我这样想
hdc: 类似句柄 ,我觉得是一样的。 但是应该有差别,高手们出来重新解释
h:=getdc(form1.handle): 把FORM1的 句柄赋值给“句柄”变量H
polybezier(h,point,7) : 执行该方法, H,POINT,7均是方法参数。 呵呵:) 
 高手来再用标准的语法解释一下。 我就会这样了。

来自: app2001, 时间: 2003-12-24 10:29:00, ID: 2373167
我不笑,不过我也没有试过,你得自己试了

来自: 雨幽公主, 时间: 2003-12-24 16:34:00, ID: 2374275
哪位能解释清楚,我再给50分.

来自: yangying_2000, 时间: 2003-12-24 16:46:00, ID: 2374306
幸亏你叫公主,我记得原来也有人问过这个问题,硬是没人理,惨啊,
做女人真好哈哈

来自: 雨幽公主, 时间: 2003-12-24 17:01:00, ID: 2374352
大哥就别废话了,帮帮忙吧,很急的.

来自: yangying_2000, 时间: 2003-12-24 17:07:00, ID: 2374365
抱歉,我要过平安夜去了,要是明天还没有解决就帮你一把呵呵

来自: 雪中漫步, 时间: 2003-12-24 17:15:00, ID: 2374390
Tpoint--就是坐标了;
DC在GDI中是一个非常重要的概念。在MSDN上查看各个GDI函数的使用说明,我们会发现大部分GDI函数都有一个HDC类型的参数;HDC就是DC句柄。Windows应用程序进行图形、图像处理的一般操作步骤如下:
  1. 取得指定窗口的DC;
  2. 确定使用的坐标系及映射方式;
  3. 进行图形、图像或文字处理;
  4. 释放所使用的DC。
至于polybezier(),这是一个api函数,用户绘制Bezier曲线
具体得再试试了,我也没弄过这个东东:)

来自: 雨幽公主, 时间: 2003-12-26 9:55:00, ID: 2376362
如果我要指定曲线的起始点该怎么做?
polybezier(h,point,7)始终从窗口的左上角开始画,而且好象画反了(曲线到是正确的)

来自: hanpengshan_00, 时间: 2003-12-26 10:06:00, ID: 2376415
Tcanvas方法提供了两个绘制 bezier的曲线函数,polybezierto(const windows::Tpoint * points,const int points_size);
利用该函数可以使用points参数指定的端点和控制点绘制3次bezier曲线
还有一个是polybezier,定义同上

来自: 雨幽公主, 时间: 2003-12-26 10:10:00, ID: 2376436
有例子能给一个吗?

来自: Highpeak, 时间: 2003-12-26 10:48:00, ID: 2376569
procedure TForm1.Button1Click(Sender: TObject);
var
P:array[0..3] of Tpoint;
begin
p[0].x :=0;p[0].y :=0;
p[1].x :=300;p[1].y :=30;
p[2].x :=200;p[2].y :=400;
p[3].x :=550;p[3].y :=400;
Canvas.Pen.Color :=clred;
Canvas.PolyBezier(p);
end;

来自: 雨幽公主, 时间: 2003-12-26 10:57:00, ID: 2376603
如果我需要的点的坐标是小数点后精确几位的该怎么办?上面这个是整型的吧。

来自: yangying_2000, 时间: 2003-12-26 11:06:00, ID: 2376624
既然是点就没法再往下走了,因为这里的点对应于分辨率,如800*600的分辨率的意思就是屏幕以800*600个点来组成,绘图都是根据这个点阵来绘的

来自: 雨幽公主, 时间: 2003-12-26 11:15:00, ID: 2376659
那能再精确些吗?这样四舍五入不是不太精确了吗?

来自: 雨幽公主, 时间: 2003-12-26 14:57:00, ID: 2377313
用Canvas.PolyBezier(p)的结果与用polybezier(h,point,7)做出的结果是一样的.
我的意思是能不能指定曲线的起始点,并把它画在一个指定的区域里。

来自: 雨幽公主, 时间: 2003-12-26 16:41:00, ID: 2377668
具体讲就是把曲线画在像绘图软件中的绘图区域里那样。那容器里的坐标又该怎么规定呢?我试验了一下,发现它的坐标怎么与书本中讲的不太一样?就是说画出的图经X轴对称后才与我用绘图软件做出的一致。

来自: duhai_lee, 时间: 2003-12-27 11:25:00, ID: 2378580
累加, 进位然后标式。

来自: 雨幽公主, 时间: 2003-12-29 11:24:00, ID: 2381216
换个说法,如果用delphi编写绘图软件,它的坐标应该怎样定义?原点在哪里?1、2、3、4象限又到底是个什么样的情况?关于这方面我一无所知。回答上来的可以先告诉我,我单独提出问题给你分。

来自: JackKen, 时间: 2003-12-29 11:36:00, ID: 2381252
天啊,公主,你又吧问题问回去了。我不是高手也只能用些菜鸟的方法做。
用一个Image控件做画图的白板。Image有canvas那你就可以很容易画Bezier
曲线了。至于坐标,Image默认左上角为(0,0)向右x不断增大。向下,y不断
增大。关于用Image画图,你可以看看(.../Borland/Delphi6/Demos/Doc/Graphex
中的例子。

问题讨论没有结束 ...
 
http://www.delphibbs.com/keylife/iblog_show.asp?xid=207
 
weiliu兄,能不能详细解释一下贝塞尔曲线是如何定义的及下面一段程序。谢谢
procedure Bezier{(A : PlotArray; MaxContrPoints : integer;
var B : PlotArray; MaxIntPoints : integer)};
const
MaxControlPoints = 25;
type
CombiArray = array[0..MaxControlPoints] of Float;
var
N : integer;
ContrPoint, IntPoint : integer;
T, SumX, SumY, Prod, DeltaT, Quot : Float;
Combi : CombiArray;

begin
MaxContrPoints := MaxContrPoints - 1;
DeltaT := 1.0 / (MaxIntPoints - 1);
Combi[0] := 1;
Combi[MaxContrPoints] := 1;
for N := 0 to MaxContrPoints - 2 do
Combi[N + 1] := Combi[N] * (MaxContrPoints - N) / (N + 1);
for IntPoint := 1 to MaxIntPoints do
begin
T := (IntPoint - 1) * DeltaT;
if T <= 0.5 then
begin
Prod := 1.0 - T;
Quot := Prod;
for N := 1 to MaxContrPoints - 1 do
Prod := Prod * Quot;
Quot := T / Quot;
SumX := A[MaxContrPoints + 1, 1];
SumY := A[MaxContrPoints + 1, 2];
for N := MaxContrPoints downto 1 do
begin
SumX := Combi[N - 1] * A[N, 1] + Quot * SumX;
SumY := Combi[N - 1] * A[N, 2] + Quot * SumY;
end;
end
else
begin
Prod := T;
Quot := Prod;
for N := 1 to MaxContrPoints - 1 do
Prod := Prod * Quot;
Quot := (1 - T) / Quot;
SumX := A[1, 1];
SumY := A[1, 2];
for N := 1 to MaxContrPoints do
begin
SumX := Combi[N] * A[N + 1, 1] + Quot * SumX;
SumY := Combi[N] * A[N + 1, 2] + Quot * SumY;
end;
end;
B[IntPoint, 1] := SumX * Prod;
B[IntPoint, 2] := SumY * Prod;
end;
end; { Bezier }
 
http://faq.xunweb.org/itfaq/structure/2006-06-05/12473.html
 
接受答案了.
 
后退
顶部