㈠ 高次Bezier曲線的繪制問題
將程序中
long Factor(int nS) //求nS!
{long Temp=1;for(int i=1;i<=nS;i++)Temp*=i;return Temp;};
改成
double Factor(int nS) //求nS!
{double Temp=1;for(int i=1;i<=nS;i++)Temp*=i;return Temp;};
即可
㈡ 三次Bezier曲線繪制編程
順便練一下貝塞爾函數,寫了一個applet,每秒鍾隨機生成4個點展示效果。
滿足題目要求的介面。
importjava.applet.Applet;
importjava.awt.Color;
importjava.awt.Graphics;
importjava.util.Random;
importjava.util.Timer;
importjava.util.TimerTask;
publicclassTestextendsApplet{
=-1570645570118871214L;
privateintpx[],py[];
privateRandomrnd;
@Override
publicvoidinit(){
rnd=newRandom(System.currentTimeMillis());
px=newint[4];
py=newint[4];
Timert=newTimer();
t.scheleAtFixedRate(newTimerTask(){
@Override
publicvoidrun(){
repaint();
}
},0,1000);
}
privatevoidgenerate(){
for(inti=0;i<4;i++){
px[i]=rnd.nextInt(150);
py[i]=rnd.nextInt(150);
}
}
staticpublicvoiddrawBezier(
Graphicsg,
intx0,inty0,
intx1,inty1,
intx2,inty2,
intx3,inty3){
int
px[]={x0,x1,x2,x3},
py[]={y0,y1,y2,y3};
g.setColor(Color.RED);
for(inti=0;i<px.length;i++){
g.fillOval(px[i],py[i],5,5);
}
g.setColor(Color.GREEN);
doublex=0,y=0;
intc=0;
for(doublet=0;t<=1;t+=0.01){
doubledx=cubicBezier(t,px),
dy=cubicBezier(t,py);
System.out.println("dx:"+dx+",dy:"+dy);
if(c++>0)g.drawLine((int)x,(int)y,(int)dx,(int)dy);
x=dx;y=dy;
}
}
(doublet,intp[]){
returnMath.pow(1-t,3)*p[0]+
3*t*Math.pow(1-t,2)*p[1]+
3*Math.pow(t,2)*(1-t)*p[2]+
Math.pow(t,3)*p[3];
}
@Override
publicvoidpaint(Graphicsg){
generate();
drawBezier(g,
px[0],py[0],
px[1],py[1],
px[2],py[2],
px[3],py[3]
);
}
}
㈢ 求二次貝塞爾曲線 演算法實現
typedefstruct
{
floatx;
floaty;
}Point2D;
/*cp在此是四個元素的數組:
cp[0]為起點,或上圖中的P0
cp[1]為第一控制點,或上圖中的P1
cp[2]為第二控制點,或上圖中的P2
cp[3]為結束點,或上圖中的P3
t為參數值,0<=t<=1*/
Point2DPointOnCubicBezier(Point2D*cp,floatt)
{
floatax,bx,cx;floatay,by,cy;
floattSquared,tCubed;Point2Dresult;
/*計算多項式系數*/
cx=3.0*(cp[1].x-cp[0].x);
bx=3.0*(cp[2].x-cp[1].x)-cx;
ax=cp[3].x-cp[0].x-cx-bx;
cy=3.0*(cp[1].y-cp[0].y);
by=3.0*(cp[2].y-cp[1].y)-cy;
ay=cp[3].y-cp[0].y-cy-by;
/*計算t位置的點值*/
tSquared=t*t;
tCubed=tSquared*t;
result.x=(ax*tCubed)+(bx*tSquared)+(cx*t)+cp[0].x;
result.y=(ay*tCubed)+(by*tSquared)+(cy*t)+cp[0].y;
returnresult;
}
/*ComputeBezier以控制點cp所產生的曲線點,填入Point2D結構數組。
調用方必須分配足夠的空間以供輸出,<sizeof(Point2D)numberOfPoints>*/
voidComputeBezier(Point2D*cp,intnumberOfPoints,Point2D*curve)
{
floatdt;inti;
dt=1.0/(numberOfPoints-1);
for(i=0;i<numberOfPoints;i++)
curve[i]=PointOnCubicBezier(cp,i*dt);
}
㈣ Bezier曲線 演算法 程序
看一下下面的Bezier曲線繪製程序,沒有錯誤提示,但是繪制不出Bezier曲線#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#include "math.h"//包含數學頭文件#define N_MAX_POINT 10//控制多邊形的最大頂點數#define ROUND(a) int(a+0.5)//四捨五入#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView) ON_COMMAND(ID_MENUBezierCurve, OnMENUBezierCurve) ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){ // TODO: add construction code here Flag=false;}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){ // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){ CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){ // default preparation return DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{ CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{ CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc))); return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::OnMENUBezierCurve()//菜單函數{ // TODO: Add your command handler code here RedrawWindow(); AfxGetMainWnd()->SetWindowText("曲線和曲面:Bezier曲線");//顯示標題 MessageBox("單擊左鍵繪制控制多邊形,單擊右鍵繪制曲線","提示",MB_OK); pt=new CPoint[N_MAX_POINT]; Flag=true;CtrlPoint=0;}void CTestView::DrawBezier()//繪制Bezier曲線{ CClientDC dc(this); double x,y; int rate=800,n; n=CtrlPoint-1; for(double t=0;t<=1;t+=1.0/rate) { x=0;y=0; for(int i=0;i<=n;i++) { x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i); y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i); } dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255));//曲線顏色 }}double CTestView::Cnk(const int &n, const int &i)//計算Bernstein第一項函數{ return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));}int CTestView::Factorial(int m)//階乘函數{ int f=1; for(int i=1;i<=m;i++) f*=i; return f;}void CTestView::DrawCharPolygon()//繪制控制多邊形函數{ CClientDC dc(this); CPen MyPen,*pOldPen; MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0));//控制多邊形 pOldPen=dc.SelectObject(&MyPen); for(int i=0;i<CtrlPoint;i++) { if(i==0) { dc.MoveTo(pt[i]); dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2); } else { dc.LineTo(pt[i]); dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2); } } dc.SelectObject(pOldPen); MyPen.DeleteObject();}void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//獲得屏幕控制點坐標函數{ // TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point); if(Flag) { pt[CtrlPoint].x=point.x; pt[CtrlPoint].y=point.y; if(CtrlPoint<N_MAX_POINT) CtrlPoint++; else Flag=false; DrawCharPolygon(); }}void CTestView::OnRButtonDown(UINT nFlags, CPoint point)//調用繪制Bezier曲線函數{ // TODO: Add your message handler code here and/or call default Flag=false; DrawBezier(); CView::OnRButtonDown(nFlags, point);}
㈤ 請問用MATLAB怎麼繪制bezier曲線
function
[x,y]=bezier(x,y)
%用法:
%bezier(x,y)
%
生成n-1次貝塞爾曲線,其中x和y是n個點的坐標
%h=bezier(x,y)
%
生成n-1次貝塞爾曲線並返回曲線句柄
%[x,y]=bezier(x,y)
%
返回n-1次貝塞爾曲線的坐標
%例子:
%bezier([5,6,10,12],[0
5
-5
-2])
n=length(x);
t=linspace(0,1);
xx=0;yy=0;
for
k=0:n-1
tmp=nchoosek(n-1,k)*t.^k.*(1-t).^(n-1-k);
xx=xx+tmp*x(k+1);
yy=yy+tmp*y(k+1);
end
if
nargout==2
x=xx;y=yy;
end
h=plot(xx,yy);
if
nargout==1
x=h;
end
㈥ 貝塞爾曲線演算法的詳細內容
//從1開始,是因為第一個是控制點,如果曲線不封閉,那麼第一個控制點是沒有用的。
//每一段貝賽爾曲線由相鄰的兩個頂點和之間的兩個控制點決定,所以頻率為3(後一個頂點在下一組中還要使用)
for(i=1;i<count-2;i+=3){
BezierToPoly(&bezierPts,apt,precision); //拆分每一段
polyPt.Append(apt);//拆分完成,加入數組
}
//如果是封閉曲線,那麼需要將最後一個頂點和第一個頂點以及最後一個控制點以及第一個控制點組成一組進行拆分
if(bClose){
CPoint ptBuffer[4];
ptBuffer[0] = bezierPts[count-2];
ptBuffer[1] = bezierPts[count-1];
ptBuffer[2] = bezierPts[0];
ptBuffer[3] = bezierPts[1];
BezierToPoly(&ptBuffer[0], apt,precision);
polyPt.Append(apt);
}
count = polyPt.GetSize();
i=0;
//過濾相鄰的值相等的點(由於精度和誤差,可能會有一些坐標值相同的相鄰拆分點)
while(i<count-1){
if(polyPt ==polyPt[i+1]){
polyPt.RemoveAt(i+1);
count--;
continue;
}
i++;
}
return true;
}
//拆分貝賽爾曲線
bool InciseBezier(CPoint *pSrcPt, CPoint *pDstPt)
{
CPoint buffer[3][3];
int i;
for(i=0;i<3;i++){
buffer[0] = pSrcPt + pSrcPt[i+1];
buffer[0].x /=2;
buffer[0].y /=2;
}
for(i=0;i<2;i++){
buffer[1] = buffer[0] + buffer[0][i+1];
buffer[1].x /=2;
buffer[1].y /=2;
}
buffer[2][0] = buffer[1][0] + buffer[1][1];
buffer[2][0].x /=2;
buffer[2][0].y /=2;
pDstPt[0]=pSrcPt[0];
pDstPt[1]=buffer[0][0];
pDstPt[2]=buffer[1][0];
pDstPt[3]=buffer[2][0];
pDstPt[4]=buffer[1][1];
pDstPt[5]=buffer[0][2];
pDstPt[6]=pSrcPt[3];
return true;
}
//拆分一組貝賽爾曲線段
bool BezierToPoly(CPoint *pSrcPts,CPtArray &polyPt,int precision)
{
polyPt.RemoveAll();
polyPt.SetSize(4);
polyPt[0] = pSrcPts[0];
polyPt[1] = pSrcPts[1];
polyPt[2] = pSrcPts[2];
polyPt[3] = pSrcPts[3];
CPoint ptBuffer[7];
int i,j,count =4;
bool bExit;
while(true){
bExit = true;
for(i=0;i<count-1;i+=3){
// if(GetBezierGap(&polyPt)>precision){
if(!EndBezierCut(&polyPt, precision)){
bExit = false;
InciseBezier(&polyPt, ptBuffer);
polyPt.RemoveAt(i+1,2);
polyPt.InsertAt(i+1,ptBuffer[1],5);
for(j=0;j<4;j++)
polyPt[i+2+j] = ptBuffer[2+j];
i += 3;
count += 3;
}
}
if(bExit)
break;
}
count = polyPt.GetSize();
i=0;
while(i<count-1){
if(polyPt ==polyPt[i+1]){
polyPt.RemoveAt(i+1);
count--;
continue;
}
i++;
}
return true;
}
/計算貝賽爾曲線兩個頂點的縱向和橫向的最大距離
int GetBezierGap(CPoint *p)
{
int gap = 0;
for(int i=1;i<4;i++){
if(abs(p.x-p[i-1].x)>gap)
gap=abs(p.x-p[i-1].x);
if(abs(p.y-p[i-1].y)>gap)
gap=abs(p.y-p[i-1].y);
}
return gap;
}
//判斷是否可以終止更精細得拆分
bool EndBezierCut(CPoint *ptBezier, int nExtent)
{
double C,dx,dy,delt,delt1,delt2;
if (nExtent<2)
nExtent = 2;
dx = (double)(ptBezier[3].x - ptBezier[0].x);
dy = (double)(ptBezier[3].y - ptBezier[0].y);
C = dx * ptBezier[0].y - dy * ptBezier[0].x;
delt = (double)nExtent*nExtent*(dy*dy+dx*dx);
delt1 = dy * ptBezier[1].x - dx * ptBezier[1].y + C;
delt2 = dy * ptBezier[2].x - dx * ptBezier[2].y + C;
delt1 = delt1 * delt1;
delt2 = delt2 * delt2;
if (delt1 > delt || delt2 > delt)
return FALSE;
else
return TRUE;
}
㈦ 對於2N+2個離散點,如何來構造Bezier曲線
如何利用VC + + 編程技術在圖形系統中動態繪制任意階Bezier 工程曲線方 法,並且使繪制的曲線具有捕捉、修改、動態增加型值點等功能。利用同樣的方法,可以實現 B 樣條、三次參數等其它工程曲線的繪制,從而擴大了Bezier 等曲線的工程應用。 關鍵詞:Bezier 曲線; 動態繪制; 高階; VC + + 中圖分類號: TP391 文獻標識碼:A 文章編號:1671 - 5322(2004) 04 - 0029 - 05 UG、CATIA 等圖形系統可以實現B 樣條曲線 的動態繪制方法,但沒有Bezier 、三次參數樣條等 曲線的繪制方法。雖然B 樣條曲線使用最廣泛, 但Bezier 、三次參數樣條在工程上也有較多的運 用。為拓寬工程曲線的應用范圍, 在結合現行 Bezier 等曲線的演算法的基礎上,利用VC + + 開發 工具實現了高階Bezier 等曲線的繪制方法,較方 便地動態實現了曲線的修改。本設計模塊可以單 獨使用,也可作為一個模塊嵌入其它圖形系統中 使用。從繪制Bezier 曲線的方法中可了解用現行 繪圖軟體實現曲線的動態繪制、曲線的識別、拖動 型值點修改曲線等編程方法,該方法對於開發其 它專業圖形系統有極大的幫助。
㈧ 如何實現任意階次bezier曲線的生成
如何利用VC + + 編程技術在圖形系統中動態繪制任意階Bezier 工程曲線方 法,並且使繪制的曲線具有捕捉、修改、動態增加型值點等功能。利用同樣的方法,可以實現 B 樣條、三次參數等其它工程曲線的繪制,從而擴大了Bezier 等曲線的工程應用。 關鍵詞:Bezier 曲線; 動態繪制; 高階; VC + + 中圖分類號: TP391 文獻標識碼:A 文章編號:1671 - 5322(2004) 04 - 0029 - 05 UG、CATIA 等圖形系統可以實現B 樣條曲線 的動態繪制方法,但沒有Bezier 、三次參數樣條等 曲線的繪制方法。雖然B 樣條曲線使用最廣泛, 但Bezier 、三次參數樣條在工程上也有較多的運 用。為拓寬工程曲線的應用范圍, 在結合現行 Bezier 等曲線的演算法的基礎上,利用VC + + 開發 工具實現了高階Bezier 等曲線的繪制方法,較方 便地動態實現了曲線的修改。本設計模塊可以單 獨使用,也可作為一個模塊嵌入其它圖形系統中 使用。從繪制Bezier 曲線的方法中可了解用現行 繪圖軟體實現曲線的動態繪制、曲線的識別、拖動 型值點修改曲線等編程方法,該方法對於開發其 它專業圖形系統有極大的幫助。 1 Bezier 曲線的演算法 1. 1 Bezier 曲線的描述 設 P 0 , P 1 , P 2 , …, P n , 為 n 階Bezier 曲線的特 征多邊形控制點,則Bezier 曲線一般表達式為 P( t) = ∑ n i =0 B i , n ( t) P i , 0 ≤t ≤1 (1) 其中: B i , n ( t) = C n i (1 - t) n - i t i ( i = 0 , 1 , …n) 1. 2 繪制Bezier 曲線的條件 繪制Bezier 曲線的條件有兩種,一是給出型 值點坐標,另一是給出控制點坐標。在計算中,一 般最終是利用控制點坐標計算來繪制曲線的。當 給出的數據是型值點時,要利用型值點的坐標值 反求出控制點坐標,再利用控制點坐標進行插補 運算求出曲線的坐標,反求控制點的演算法為: 設給出的型值點為 Q 0 , Q 1 , Q 2 …Q n , 要反求 的控制點為 P 0 , P 1 , P 2 …P n , 設參數 t = 0 , 1/ n , 2/ n …1 時分別經過 Q 0 , Q 1 , Q 2 …Q n , 根據Bezier 定義有 Q 0 = P(0) = P 0 Q 1 = P(1/ n) = B 0 , n (1/ n) P 0 + B 1 , n (1/ n) P 1 + … + B n , n (1/ n) P n …… (2) Q n- 1 = P( ( n - 1) / n) = B 0 , n ( ( n - 1) / n) P 0 + B 1 , n ( ( n - 1) / n) P 1 + …+ B n , n P n Q n = P n 把上式寫成矩陣形式,利用矩陣的求逆運算, 求出控制點為式(3) 。
2 繪制曲線類的方法 2. 1 構造Bezier 曲線類 在VC + + 中繪制Bezier 曲線,首先建立Bezi2 er 曲線類,利用Bezier 類的指針來對Bezier 曲線進 行控制。在VC + + 中所構造Bezier 的曲線類為 CBezier : : CBezier ( short ColorPen , short Color2 Brush , float LineWide , short LineType , float x- Scale , short Layer , int id-only , bool Delete , BpointStruct 3 BpointList) : CDraw ( ColorPen , ColorBrush ,LineWide , LineType ,x- Scale ,Layer ,id-only ,Delete) 各參數的控制對象分別為線型、顏色、線寬、 比例、圖層、曲線 ID 號、刪除狀態、型值點數目、存 放型值點的結構指針,其中BpointStruct 結構有 x 和y 兩個成員, 存放型值點坐標, CDraw 類為 CBezie 的基類,該類的各個參數在構造成時完成 初始化。CBezier 類成員有: int m-Numble ;/ / 存放結點的數目 BPointStruct 3 m-BpointList ;/ / 存放型值點的坐 標 BPointStruct 3 m- CpointList ;/ / 存放反求的控制 點的坐標 void Draw ( CDC 3 pDC , int m-DrawMode , int m- DrawMode1 ,short BackColor) ;/ / 繪制曲線函數 BOOL IsPoint (float x ,float y ,float jl ,float blc ,int 3 No) ; / / 判斷曲線是否選中函數 virtual void MDpoint ( int num , float x , float y) ;/ / 修改控制點函數 void GetRect (float 3 minX,float 3 minY,float 3 maxX, float 3 maxY) ;獲得曲線區域函數 virtual~CBezier () ;/ / CBezier 的析函數 CBezier 類成員在類構造時完成參數數值的 傳遞,繪制曲線時構造一個CBezier 類對象。為了 存儲構造的對象指針,在文檔類中建立一個存放 曲線指針的指針m-BezierArray。 CTypedPtrArray < CObArray , CBezier 3 > m- BezierArray。 2. 2 動態繪制Bezier 曲線 Bezier 曲線類由Draw 函數完成曲線的繪制, 在Draw中完成曲線的反求控制點、插補運算、區 域的計算, 設置線型、顏色、線寬等功能。Bezier 曲線的繪制方法是當用戶選擇繪制 Bezier 曲線的 功能時,用戶在屏幕上拾取型值點時或輸入型值 點坐標,在屏幕上動態繪制曲線,繪制中每增加一 個型值點時,則Bezier 曲線的階次增加一階,此方 法可以實現任意階的Bezier 曲線的繪制, 這和B 樣條的曲線繪制方法不同,B 樣條曲線可用多個 三次B 樣條曲線繪制N 個型值點樣條曲線,得到 的曲線是光滑連續的,而Bezier 曲線隨著型值點 個數的增加,若用升階的方法計算,則繪製程序要 根據型值點的個數重新計算曲線的坐標。Draw 函數繪制的程序流程如圖1 所示。 圖1 Draw函數的流程圖 Fig. 1 Process flowfor drawfunction 在程序中構造成計算矩陣時,把與坐標值對 應的參數 t 的值代入伯恩斯坦基函數計算出與各 型值點對應的各個基函數值,其中調用了求階乘、 求冪等函數,然後組合成一個基函數矩陣,再調用 矩陣的求逆運算,本模塊中採用全選主元高斯消 �9�9 0 3 �9�9 鹽城工學院學報(自然科學版) 第17 卷 去法進行求逆,得到計算的系數矩陣,求出控制點 坐標,根據Bezier 曲線的計算公式計算出曲線的 坐標。繪制Bezier 曲線調用了CDC類的繪制直線 方法,用直線段來近似代替曲線,圖形系統中繪制 曲線大多採用這種方法,曲線的近似程度和所采 用的插值間距有關。為了得到好的顯示效果,要 把間距控制視覺能接受的范圍內。由於無論曲線 多長, t 的值都是在0~1 之間, 當 t 的分隔間距恆 定時, 在動態繪制過中, 隨著曲線長度的增加, 直 線的逼近效果越差。t 的劃分方法很多, 可以利 用等間距、等弦長方法來解決這一問題, 一般來 說, t 的插值間距為非均勻, 而讓每一段代替曲線 的直線段的距離為定值, 獲得好的視覺效果。 2. 3 增加Bezier 曲線 在動態繪制過程中,當滑鼠移動過程中,曲線 也隨著滑鼠的位置不同實現重畫。這時的圖形指 針並沒有存儲到Bezier 曲線類的m-BezierArray 數 組中。只有當完成曲線繪制時,發出命令後才進 行曲線的最後繪制,對象指針才加入到 m-Bezier2 Array 中存儲。當用滑鼠的右鍵結束繪制時,在鼠 標的消息函數中增加以下語句 pDoc > AddCBezier ( m-pColor , m- brColor , m- LineWide ,m-LineType ,m-xScale ,m-Layer ,id-only ,0 , PushNumb ,BPointXyz) - > Draw( &ddd ,0 ,1 ,m- bCol2 or) ; AddCBezier 函數在文檔類中定義, 它完成對 象的增加,存儲指針。得到指針後,調用Draw 函 數繪制直線。 3 實現曲線類動態修改 3. 1 曲線的捕捉 曲線的捕捉功能是圖形系統的基本功能,要 實現曲線的捕捉前提是獲得曲線類的對象指針, 建立Bezier 曲線類的目的就是為了實現曲線的捕 捉、移動、修改、刪除、恢復, 移動和縮放功能。 Bezier 類中 IsPoint 函數就是為了實現滑鼠移動過 程中滑鼠位置與曲線之間距離的計算,距離判別 最簡單的方法是計算滑鼠點位置和對象中的存儲 的型值點距離,若距離在設定的范圍內,則把選中 的圖形突出顯示。IsPoint 函數不但返回曲線是否 選中的邏輯值,而且利用參數返回選中曲線的型 值點的序號。更為復雜的方法是把滑鼠點和曲線 的坐標進行判別,這種判別方法可用的判別點多, 曲線易選中,但計算復雜,系統採用第一種方法實 現捕捉功能。 3. 2 曲線的修改 在繪圖過程中,有時需要修改圖形,一般是通 過修改型值或控制點的位置來達到所要求的曲線 形狀。為了修改型值或控制點,在Bezier 類中增 加了Mdpoint 函數, 在函數中根據 IsPoint 返回的 型值點或控制點的序號替換它們的坐標,然後重 畫曲線,這樣就實現了動態修改的功能。 3. 3 曲線的刪除、恢復 曲線刪除有兩種情況,一種是可以恢復的,另 一種是不可恢復的。不可恢復的的刪除,只要在 存放對象指針的m-BezierArray 數組中刪除所要刪 除的曲線指針。如果是可恢復的刪除,只是在對 象的成員中增加了刪除標志,在重畫曲線時,做了 刪除標志的曲線不繪制,而對象指針並沒有從指 針數組中刪除。 3. 4 曲線的移動和縮放 曲線移動是讓曲線做平移。平移時,根據平 移的 X, Y方向的距離在曲線的型值或控制點上 加上一個平移值,該值的正負號表示移動方向。 曲線的縮放是根據圖形的縮放比例對圖形放 大或縮小。在程序中,增加了縮放的比例因子和 從邏輯坐標到實際坐標轉換函數VPtoDP 以及從 實際坐標到邏輯坐標的轉換函數DPtoVP ,在坐標 轉換函數中,通過縮放的比例因子改變坐標值達 到縮放目的。VPtoDP 函數定義如下 void CVDrawView: : DPtoVP (float x ,float y , int 3 X,int 3 Y) { 3 X= (int) ( (x - m-xStart) / blc) ; if (m-MapMode = = 1) 3 Y= m- hScreen - (int) ( (y - m-yStart) / blc) ; else 3 Y= (int) ( (y - m-yStart) / blc) - m- hScreen ; } 其中,blc 就是坐標變換中的縮放因子,m-xS2 tart 、m-yStart 是調節整個圖形的平行移動坐標。 4 實現曲線動態繪制的過程 在實現Bezier 曲線的繪制過程中,繪制過程 會調用了許多函數,利用了滑鼠的消息函數來實 現繪圖操作。具體實現的過程是先用滑鼠單擊左 鍵在屏幕上拾取曲線的型值點,當拖動滑鼠時,曲 線隨著滑鼠的移動在不斷的變化。