終于完成了相當(dāng)于GDI中Arc函數(shù)的功能了。這次仍然跟API有點(diǎn)誤差,不多這里的誤差是GDI的問(wèn)題。這里貼出截圖和代碼。觀看圖2和圖3,我們知道橢圓是對(duì)稱的,但是GDI并沒(méi)有做到這一點(diǎn)。我的算法也不能精確對(duì)稱,但是左右兩邊僅相差1個(gè)像素。Arc是橢圓的子集,所以Arc在這個(gè)局部(橢圓的最上方)中也應(yīng)該左右對(duì)稱。圖1中我先用GDI繪制黑色Arc,然后使用我的算法繪制紅色Arc。這里的自適應(yīng)步長(zhǎng)算法跟上一篇的Bezier曲線的算法是一樣的。
圖1:運(yùn)行結(jié)果
圖2:GDI局部放大
圖3: 我的結(jié)果圖放大
代碼:
1 #include "..\..\..\..\Library\Windows\VL_WinMain.h"
2 #include "..\..\..\..\Library\Windows\VL_WinGDI.h"
3
4 using namespace vl;
5 using namespace vl::windows;
6
7 class Evaluator : public VL_Base
8 {
9 protected:
10 VL_WinDIB* FBuffer;
11 VDouble FX1,FY1,FX2,FY2,FStart,FEnd;
12 VDouble FCenX,FCenY,FA,FB;
13 public:
14 Evaluator(VL_WinDIB* Buffer)
15 {
16 FBuffer=Buffer;
17 }
18
19 void SetEllipse(VDouble X1 , VDouble Y1 , VDouble X2 , VDouble Y2 , VDouble Start , VDouble End)
20 {
21 FX1=X1;
22 FY1=Y1;
23 FX2=X2;
24 FY2=Y2;
25 FStart=Start;
26 FEnd=End;
27
28 FCenX=(FX1+FX2)/2;
29 FCenY=(FY1+FY2)/2;
30 FA=(FX2-FX1)/2;
31 FB=(FY2-FY1)/2;
32 }
33
34 void GetP(VDouble T , VDouble& X , VDouble& Y)
35 {
36 VDouble Angle=FStart+T*(FEnd-FStart);
37 VDouble Sin=-sin(Angle);
38 VDouble Cos=cos(Angle);
39 if(abs(Sin)<0.5)
40 {
41 VDouble X2=1/(1/(FA*FA)+(Sin*Sin)/(FB*FB*Cos*Cos));
42 if(Pi_f/2<=Angle && Angle<=Pi_f*3/2)
43 {
44 X=-sqrt(X2);
45 }
46 else
47 {
48 X=sqrt(X2);
49 }
50 Y=X*Sin/Cos;
51 }
52 else
53 {
54 VDouble Y2=1/(1/(FB*FB)+(Cos*Cos)/(FA*FA*Sin*Sin));
55 if(0<=Angle && Angle<=Pi_f)
56 {
57 Y=-sqrt(Y2);
58 }
59 else
60 {
61 Y=sqrt(Y2);
62 }
63 X=Y*Cos/Sin;
64 }
65 X+=FCenX;
66 Y+=FCenY;
67 }
68
69 void SetColor(VInt X , VInt Y , VInt Color)
70 {
71 VByte R=Color%256;
72 VByte G=(Color>>8)%256;
73 VByte B=(Color>>16)%256;
74 if(X>=0 && X<FBuffer->GetWidth() && Y>=0 && Y<FBuffer->GetHeight())
75 {
76 ((VInt32u*)(FBuffer->ScanLines[Y]))[X]=(R<<16)+(G<<8)+B;
77 }
78 }
79
80 POINT GetStartPoint()
81 {
82 VDouble X,Y;
83 GetP(0,X,Y);
84 POINT P;
85 P.x=Round(X);
86 P.y=Round(Y);
87 return P;
88 }
89
90 POINT GetEndPoint()
91 {
92 VDouble X,Y;
93 GetP(1,X,Y);
94 POINT P;
95 P.x=Round(X);
96 P.y=Round(Y);
97 return P;
98 }
99
100 void DrawCurve()
101 {
102 POINT StartPoint=GetStartPoint();
103 POINT EndPoint=GetEndPoint();
104
105 VDouble T=0.0001;
106 VBool Finished=false;
107 VDouble OldX=StartPoint.x;
108 VDouble OldY=StartPoint.y;
109 VDouble X1,Y1;
110 VDouble X2=EndPoint.x;
111 VDouble Y2=EndPoint.y;
112
113 VInt OldX1=StartPoint.x;
114 VInt OldY1=StartPoint.y;
115 VInt OldX2=0;
116 VInt OldY2=0;
117 VBool Old2Available=false;
118 SetColor(OldX1,OldY1,RGB(255,0,0));
119 while(!Finished)
120 {
121 /*初始步長(zhǎng)為當(dāng)前t到結(jié)束點(diǎn)*/
122 VDouble dT=(1-T);
123 GetP(T+dT,X1,Y1);
124 VBool AtTail=true;
125 while(true)
126 {
127 /*取半步,檢查目標(biāo)點(diǎn)與當(dāng)前點(diǎn)的長(zhǎng)度*/
128 VDouble dTHalf=dT/2;
129 GetP(T+dTHalf,X2,Y2);
130 VDouble Length=sqrt((X1-OldX)*(X1-OldX)+(Y1-OldY)*(Y1-OldY));
131 VDouble LengthHalf=sqrt((X2-OldX)*(X2-OldX)+(Y2-OldY)*(Y2-OldY));
132 /*如果半步長(zhǎng)大于一步則取半步,繼續(xù)迭代*/
133 if(LengthHalf>Length)
134 {
135 dT=dTHalf;
136 X1=X2;
137 Y1=Y2;
138 }
139 else
140 {
141 /*否則,如果全步長(zhǎng)產(chǎn)生的距離<=1則繪制*/
142 if(Length<=1.001)
143 {
144 if(AtTail)
145 {
146 Finished=true;
147 }
148 break;
149 }
150 /*否則進(jìn)行近似測(cè)量*/
151 else
152 {
153 dT*=1/Length;
154 GetP(T+dT,X1,Y1);
155 }
156 }
157 AtTail=false;
158 }
159 /*計(jì)算像素位置*/
160 VInt X=Round(X1);
161 VInt Y=Round(Y1);
162 VInt dX_I=(OldX1-X)*(OldX1-X);
163 VInt dY_I=(OldY1-Y)*(OldY1-Y);
164 /*讓線條長(zhǎng)度保持1*/
165 if(Old2Available)
166 {
167 if(dX_I==1 && dY_I==1)
168 {
169 OldX1=X;
170 OldY1=Y;
171 SetColor(OldX1,OldY1,RGB(255,0,0));
172 }
173 else
174 {
175 OldX1=X;
176 OldY1=Y;
177 SetColor(OldX1,OldY1,RGB(255,0,0));
178 SetColor(OldX2,OldY2,RGB(255,0,0));
179 }
180 Old2Available=false;
181 }
182 else
183 {
184 if(dX_I==1 && dY_I==1)
185 {
186 OldX1=X;
187 OldY1=Y;
188 SetColor(OldX1,OldY1,RGB(255,0,0));
189 }
190 else if(dX_I==1 || dY_I==1)
191 {
192 OldX2=X;
193 OldY2=Y;
194 Old2Available=true;
195 }
196 }
197 OldX=X1;
198 OldY=Y1;
199 T+=dT;
200 }
201 if(Old2Available)
202 {
203 SetColor(OldX2,OldY2,RGB(255,0,0));
204 }
205 }
206 };
207
208 class MyForm : public VL_WinForm
209 {
210 protected:
211 VL_WinDIB* FBuffer;
212 VL_WinDC* FBufferDC;
213 VL_WinDC* FFormDC;
214 Evaluator* FEvaluator;
215
216 public:
217 MyForm():VL_WinForm(true)
218 {
219 FBuffer=new VL_WinDIB(800,600);
220 FBufferDC=&FBuffer->DC;
221 FFormDC=new VL_WinControlDC(GetHandle());
222 FBufferDC->FillRect(0,0,800,600);
223 FEvaluator=new Evaluator(FBuffer);
224
225 VDouble Start=Pi_f*3/18;
226 VDouble End=Pi_f*27/18;
227 FBufferDC->Arc(200,200,600,400,Round(100*cos(Start))+400,Round(100*-sin(Start))+300,Round(100*cos(End))+400,Round(100*-sin(End))+300);
228 FEvaluator->SetEllipse(200,200,600,400,Start,End);
229 FEvaluator->DrawCurve();
230
231 SetMaximizeBox(false);
232 SetMinimizeBox(false);
233 SetBorder(vwfbSingle);
234 SetClientWidth(800);
235 SetClientHeight(600);
236 SetText(L"Vczh Ellipse");
237 MoveCenter();
238
239 OnPaint.Bind(this,&MyForm::Form_OnPaint);
240
241 Show();
242 }
243
244 ~MyForm()
245 {
246 delete FEvaluator;
247 delete FFormDC;
248 delete FBuffer;
249 }
250
251 void Form_OnPaint(VL_Base* Sender)
252 {
253 FFormDC->Draw(0,0,FBuffer);
254 }
255 };
256
257 void main()
258 {
259 new MyForm();
260 GetApplication()->Run();
261 }
posted on 2008-06-12 06:02
陳梓瀚(vczh) 閱讀(2348)
評(píng)論(5) 編輯 收藏 引用 所屬分類:
2D