• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評(píng)論-2670  文章-0  trackbacks-0

                終于完成了相當(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

            評(píng)論:
            # re: 橢圓段掃描完成 2008-06-12 06:06 | 陳梓瀚(vczh)
            這個(gè)算法把里面的魔術(shù)數(shù)字“1”改成其他長(zhǎng)度的話,可以實(shí)現(xiàn)比較精確的等長(zhǎng)取樣。不過(guò)需要的迭代次數(shù)我還沒(méi)去研究,這個(gè)算法還是比較慢的。把橢圓當(dāng)成未知曲線來(lái)掃描事實(shí)上是為了偷懶,嘿嘿。

            經(jīng)過(guò)自己的不嚴(yán)密的論證,這個(gè)自適應(yīng)步長(zhǎng)算法可以正確掃描Bezier和橢圓,但是不能適應(yīng)一切曲線。  回復(fù)  更多評(píng)論
              
            # re: 橢圓段掃描完成 2008-06-30 21:07 | lll
            const REAL& C1 = 0.552285f;
            const REAL& rx = width / 2;
            const REAL& ry = height / 2;
            const REAL& cx = x + rx;
            const REAL& cy = y + ry;



            cx + rx, cy,
            cx + rx, cy + C1 * ry,
            cx + C1 * rx, cy + ry,
            cx, cy + ry

            cx - C1 * rx, cy + ry,
            cx - rx, cy + C1 * ry,
            cx - rx, cy,
            cx - rx, cy - C1 * ry,
            cx - C1 * rx, cy - ry,
            cx, cy - ry,
            cx + C1 * rx, cy - ry,
            cx + rx, cy - C1 * ry,
            cx + rx, cy,   回復(fù)  更多評(píng)論
              
            # re: 橢圓段掃描完成 2009-01-07 16:26 | baili35
            是不是GDI所繪制的圖形都向左上放縮小一個(gè)像素的原因才導(dǎo)致所繪制的橢圓不是對(duì)稱的。  回復(fù)  更多評(píng)論
              
            # re: 橢圓段掃描完成[未登錄](méi) 2009-08-08 09:00 | Jcily
            不對(duì)稱是因?yàn)槟J(rèn)情況GDI為了保證包圍矩形的寬高數(shù)字,而將右下角的實(shí)際繪制點(diǎn)使用bottomright-1.

            比如如下矩形
            ptTopLeft(1,1),ptBottomRight(2,2)
            實(shí)際畫(huà)出來(lái)只占一個(gè)像素,因?yàn)檫@個(gè)矩形寬高為1.與我們潛意識(shí)認(rèn)為效果的不一樣。

            而GDI+卻不是這樣。
              回復(fù)  更多評(píng)論
              
            # re: 橢圓段掃描完成 2009-08-09 01:57 | 陳梓瀚(vczh)
            @Jcily
            你這個(gè)論斷在他不對(duì)稱接近10個(gè)像素(看圖)的時(shí)候是不成立的,我不知道他用的是什么算法,不過(guò)根據(jù)小道消息,GDI里面的很多曲線都使用bezier去模擬的。  回復(fù)  更多評(píng)論
              
            精品综合久久久久久888蜜芽| 亚洲精品无码久久久久AV麻豆| 久久免费的精品国产V∧| 久久精品国产亚洲αv忘忧草| 99精品久久精品一区二区| 久久婷婷五月综合色奶水99啪 | 精品午夜久久福利大片| 国产成人99久久亚洲综合精品| 久久人妻少妇嫩草AV无码蜜桃| 精品久久亚洲中文无码| 国产精品99久久免费观看| 久久国产精品免费一区| 亚洲中文精品久久久久久不卡| 狠狠干狠狠久久| 国产亚洲精品久久久久秋霞| 久久96国产精品久久久| 无码国内精品久久综合88| A狠狠久久蜜臀婷色中文网| 久久精品成人免费观看97| 久久精品国产网红主播| 亚洲一级Av无码毛片久久精品| 国产成人久久精品激情 | 2021国产成人精品久久| 色悠久久久久久久综合网| 久久精品国产亚洲av日韩| 久久国产综合精品五月天| 久久人人爽爽爽人久久久| 日本精品久久久久久久久免费| 久久精品国产亚洲AV麻豆网站 | 久久综合精品国产一区二区三区| 亚洲精品国产字幕久久不卡| 精品久久人人爽天天玩人人妻 | 中文字幕亚洲综合久久菠萝蜜| 久久久久四虎国产精品| 中文字幕乱码久久午夜| 久久人人爽人人精品视频| 久久国产精品一区二区| 日韩人妻无码精品久久免费一| 久久人人爽人人澡人人高潮AV| 狠狠干狠狠久久| www.久久热|