• <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>

            XY

            沒有任何借口
            posts - 9, comments - 31, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

              作者:路緣

            原文網(wǎng)址:http://www.cnblogs.com/xuyuan77/archive/2008/10/13/1310269.html

            德國(guó)數(shù)學(xué)家David Hilbert發(fā)現(xiàn)了一種曲線,首先把一個(gè)正方形等分成四個(gè)小正方形,依次從西南角的正方形中心出發(fā)往北到西北正方形中心,再往東到東北角的正方形中心,再往南到東南角正方形中心,這是一次迭代,如果對(duì)四個(gè)小正方形繼續(xù)上述過(guò)程,往下劃分,反復(fù)進(jìn)行,最終就得到一條可以填滿整個(gè)正方形的曲線,這就是Hibert曲線,其大致過(guò)程如下圖所示

             

                                            Hibert曲線生成過(guò)程

             

            下面我們來(lái)看如何寫程序生成這樣的曲線,其實(shí)不管迭代多少次,都是由如下的圖形

                        基本圖 

            構(gòu)成,唯一所不同的是開口方向不一樣。開口方向不一樣就涉及到圖像旋轉(zhuǎn),圖像旋轉(zhuǎn)的基本知識(shí)接下來(lái)會(huì)介紹。目前我們最關(guān)心的是這樣生成的曲線過(guò)程右什么規(guī)律,從上述描述生成的過(guò)程就已經(jīng)看出了規(guī)律,當(dāng)然人肯定一眼就看出來(lái)了,但計(jì)算機(jī)如何知道呢?這就是生成Hibert曲線算法的關(guān)鍵了:

            為了便于找出規(guī)律,我們來(lái)看下面一副圖

             

            上圖中應(yīng)該是把所有開口方向(共四種)都涵蓋了。我們約定四種類型:

            開口往南-0,開口往西-1,開口往北-2,開口往東-3。我們結(jié)合基本圖,就有這樣的規(guī)律,畫表如下:

            點(diǎn)

            點(diǎn)所在圖類型

            以該點(diǎn)為中心產(chǎn)生的圖類型

            dot1

            0

            1

            dot1

            1

            2

            dot1

            2

            3

            dot1

            3

            0

             

            其他的點(diǎn)類似也有類似的規(guī)律,這個(gè)規(guī)律才是我們編碼的基礎(chǔ)。是下次遞歸調(diào)用畫圖函數(shù)傳參數(shù)的前提。下面我們來(lái)看一下畫圖中涉及到的圖像旋轉(zhuǎn)的相關(guān)數(shù)學(xué)知識(shí)。

            圖像旋轉(zhuǎn)

            圖像旋轉(zhuǎn)是指把定義的圖像繞某一點(diǎn)以逆時(shí)針或順時(shí)針方向旋轉(zhuǎn)一定的角度,通常是指繞圖像的中心以逆時(shí)針方向旋轉(zhuǎn)。

            假設(shè)圖像的左上角為(left, top),右下角為(right, bottom),則圖像上任意點(diǎn)(x0, y0)繞其中心(xcenter, ycenter)逆時(shí)針旋轉(zhuǎn)angle角度后,新的坐標(biāo)位置(x, y′)的計(jì)算公式為:

            xcenter = (right left 1) 2 left;

            ycenter = (bottom top 1) 2 top;

            x =  (x0 xcenter) cosθ (y0 ycenter) sinθ xcenter;

            y =  (x0 xcenter) sinθ (y0 ycenter) cosθ ycenter;

            與圖像的鏡像變換相類似,也采用按行逐點(diǎn)變換的方式實(shí)現(xiàn)圖像的旋轉(zhuǎn)。

             

            現(xiàn)在一切都準(zhǔn)備就緒,我們來(lái)實(shí)現(xiàn)相關(guān)的算法如下:

             

            /**********************************************************************************************
            功能:實(shí)現(xiàn)繪制Hilbert曲線
            參數(shù):
                pDC:設(shè)備上下文
                n:維都
                len:邊長(zhǎng)
                x:中心橫坐標(biāo)
                y:中心縱坐標(biāo)
                iType:繪畫類型,開口:0-南,1-西,2-北,3-東
                unit_length:最小單元長(zhǎng)度
            /*********************************************************************************************
            */

            void CGraphicAppView::DrawHilbert(CDC* pDC, int n, int len, int x, int y, int iType, int unit_length)
            {
                
            //存儲(chǔ)以x,y為中心的西南、西北、東北、東南四角定點(diǎn)的坐標(biāo)
                int arr[4][2];
                arr[
            0][0= x -len/4; arr[0][1=y+len/4
                arr[
            1][0= x -len/4; arr[1][1=y-len/4;
                arr[
            2][0= x +len/4; arr[2][1=y-len/4;
                arr[
            3][0= x +len/4; arr[3][1=y+len/4
                
            //存儲(chǔ)以x,y為中心的(西南、西北、東北、東南四角定點(diǎn))經(jīng)過(guò)處理后的坐標(biāo)
                int a[4][2];
                memset(a, 
            0sizeof(a));

                
            int sin_v=0,cos_v=1;//默認(rèn)為0度的值
                switch(iType)//根據(jù)不同的開口方向,對(duì)旋轉(zhuǎn)三角函數(shù)賦值
                {
                
            case 1://開口向左
                    sin_v = 1; cos_v = 0;
                    
            break;
                
            case 2://開口向上
                    sin_v = 0; cos_v = -1;
                    
            break;
                
            case 3:    //開口向右
                    sin_v = -1; cos_v = 0;
                    
            break;
                }


                
            for(int i = 0; i<4; i++)//完成旋轉(zhuǎn)
                {
                    a[i][
            0= (arr[i][0- x)*cos_v - (arr[i][1- y)*sin_v + x;
                    a[i][
            1= (arr[i][0- x)*sin_v + (arr[i][1- y)*cos_v + y;
                }


                CPen newPen(PS_DASHDOTDOT, 
            2, RGB(y%255, x%255, (y+x)%255));
                pDC
            ->SelectObject(&newPen);        

                
            if(n > 1)
                
            {
                    
            int length = len/2;
                    DrawHilbert(pDC, n
            -1, length, a[0][0], a[0][1], (1+iType)%4,unit_length);
                    DrawHilbert(pDC, n
            -1, length, a[1][0], a[1][1], iType,unit_length);
                    DrawHilbert(pDC, n
            -1, length, a[2][0], a[2][1], iType,unit_length);
                    DrawHilbert(pDC, n
            -1, length, a[3][0], a[3][1], (3+iType)%4,unit_length);

                    
            switch(iType)
                    
            {
                    
            case 0:
                    
            case 2:
                        pDC
            ->MoveTo(x-length + 0.5*unit_length, y + 0.5*unit_length);
                        pDC
            ->LineTo(x-length + 0.5*unit_length, y - 0.5*unit_length);

                        pDC
            ->MoveTo(x-0.5*unit_length, y - (1-iType)*0.5*unit_length);
                        pDC
            ->LineTo(x+0.5*unit_length, y - (1-iType)*0.5*unit_length);

                        pDC
            ->MoveTo(x+length - 0.5*unit_length, y + 0.5*unit_length);
                        pDC
            ->LineTo(x+length - 0.5*unit_length, y - 0.5*unit_length);
                        
            break;
                    
            case 1:
                    
            case 3:
                        pDC
            ->MoveTo(x-0.5*unit_length, y -length + 0.5*unit_length);
                        pDC
            ->LineTo(x+0.5*unit_length, y -length + 0.5*unit_length);

                        pDC
            ->MoveTo(x+(2-iType)*0.5*unit_length, y - 0.5*unit_length);
                        pDC
            ->LineTo(x+(2-iType)*0.5*unit_length, y + 0.5*unit_length);

                        pDC
            ->MoveTo(x-0.5*unit_length, y +length - 0.5*unit_length);
                        pDC
            ->LineTo(x+0.5*unit_length, y +length - 0.5*unit_length);
                        
            break;
                    }

                }

                
            else
                
            {        
                    pDC
            ->MoveTo(a[0][0], a[0][1]);
                    pDC
            ->LineTo(a[1][0], a[1][1]);
                    pDC
            ->LineTo(a[2][0], a[2][1]);
                    pDC
            ->LineTo(a[3][0], a[3][1]);
                }

            }

            算法中還涉及到了,連接迭代產(chǎn)生的圖像的過(guò)程,由于算法不是很優(yōu)雅,在這兒就不細(xì)說(shuō)了,其次如果把二維映射到三維,將會(huì)得到更美妙的曲線,最近忙著找工作,有時(shí)間再想了,有興趣的朋友可以研究下三維的情況。

             

            其次希望有朋友能有更好的算法,希望不吝賜教,先謝過(guò)了。最后我們來(lái)看一下迭代6次的一個(gè)運(yùn)行結(jié)果圖:

            調(diào)用的代碼段如下:

            void CGraphicAppView::OnDraw(CDC* pDC)
            {
                CGraphicAppDoc
            * pDoc = GetDocument();
                ASSERT_VALID(pDoc);
                
            if (!pDoc)
                    
            return;
                
            // TODO: add draw code for native data here
                int n = 6;
                
            long t = ::pow(2.0, n);
                
            int length = 400;
                
            int unit_length = length/t;
                DrawHilbert(pDC, n, length, 
            2002000, unit_length);
            }

            Feedback

            # re: 分形的樂趣之_Hilbert曲線  回復(fù)  更多評(píng)論   

            2008-10-13 21:53 by 陳梓瀚(vczh)
            there is a bug, the colors of connection lines are wrong. It seems that the color is not decided when you draw the picture.

            # re: 分形的樂趣之_Hilbert曲線  回復(fù)  更多評(píng)論   

            2008-10-13 22:50 by 路緣
            @陳梓瀚(vczh)
            Thank you for your reply. But I can't find the bug ,
            and the program runs on my computer smoothly.

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久久无码一区二区三区 | 女同久久| 欧美精品九九99久久在观看| 久久久久久精品免费免费自慰| 欧美噜噜久久久XXX| 久久久久这里只有精品| 午夜精品久久久久久毛片| 精品久久久无码中文字幕| 久久久久波多野结衣高潮| 国产精品欧美亚洲韩国日本久久| 国产成人精品综合久久久久| 精品乱码久久久久久夜夜嗨| 色综合久久中文字幕无码| 久久精品无码免费不卡| 72种姿势欧美久久久久大黄蕉| 久久夜色精品国产噜噜亚洲a| 99久久精品毛片免费播放| 99久久国产宗和精品1上映| 久久精品国产精品亚洲| 久久国产乱子精品免费女| 久久综合狠狠综合久久综合88 | 国产激情久久久久影院小草| 日韩精品久久无码中文字幕| 久久久久久久91精品免费观看| 久久午夜福利电影| 国内精品久久久久久久涩爱| 久久精品一区二区三区不卡| 97r久久精品国产99国产精| 久久久久久国产精品无码超碰| 亚洲AV日韩精品久久久久| 亚洲精品无码成人片久久| 综合人妻久久一区二区精品| 97精品国产97久久久久久免费| 久久人人爽人人爽人人片AV不 | 久久99国产精品久久99小说| 国产精品久久久久免费a∨| 无码国内精品久久综合88| 亚洲成色www久久网站夜月| 日产精品99久久久久久| 东京热TOKYO综合久久精品| 色成年激情久久综合|