<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創未來!
    隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
    數據加載中……

    坐標空間

    Win32應用程序設計接口(API)使用四種坐標空間:世界坐標系空間、頁面空間、設備空間、和物理設備空間。應用程序運用世界坐標系空間對圖形輸出進行旋轉、斜切或者反射(一般坐標系完不成這些特殊的功能)。
    Win32 API把世界坐標系空間和頁面空間稱為邏輯空間;最后一種坐標空間(即物理設備空間)通常指應用程序窗口的客戶區;但是它也包括整個桌面、完整的窗口(包括框架、標題欄和菜單欄)或打印機的一頁或繪圖儀的一頁紙。
    如果該應用程序調用了SetWorldTransform函數,那么映射就從應用程序的世界坐標系空間開始;否則,映射在頁面空間中進行。
    下面有一個從MSDN中拷貝出來的例子如下:
    enum TransformStyle { SCALE, TRANSLATE, ROTATE, SHEAR, REFLECT, NORMAL};

    void CXXXXView::TransformAndDraw(int iTransform, HWND hWnd)
    {
        HDC hDC;
        XFORM xForm;
        RECT rect;
     
        // Retrieve a DC handle for the application's window.
     
        hDC = ::GetDC(hWnd);
     
        // Set the mapping mode to LOENGLISH. This moves the
        // client area origin from the upper left corner of the
        // window to the lower left corner (this also reorients
        // the y-axis so that drawing operations occur in a true
        // Cartesian space). It guarantees portability so that
        // the object drawn retains its dimensions on any display.

        SetGraphicsMode(hDC, GM_ADVANCED);
        SetMapMode(hDC, MM_LOENGLISH);
     
        // Set the appropriate world transformation (based on the
        // user's menu selection).
     
        switch (iTransform)
        {
            case SCALE:        // Scale to 1/2 of the original size.
                xForm.eM11 = (FLOAT) 0.5;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 0.5;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case TRANSLATE:   // Translate right by 3/4 inch.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 75.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case ROTATE:      // Rotate 30 degrees counterclockwise.
                xForm.eM11 = (FLOAT) 0.8660;
                xForm.eM12 = (FLOAT) 0.5000;
                xForm.eM21 = (FLOAT) -0.5000;
                xForm.eM22 = (FLOAT) 0.8660;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case SHEAR:       // Shear along the x-axis with a
                              // proportionality constant of 1.0.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 1.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case REFLECT:     // Reflect about a horizontal axis.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) -1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case NORMAL:      // Set the unity transformation.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
      default:
       break;
        }
     
        // Find the midpoint of the client area.
     
        ::GetClientRect(hWnd, (LPRECT) &rect);
        DPtoLP(hDC, (LPPOINT) &rect, 2);
     
        // Select a hollow brush.
     
        SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
     
        // Draw the exterior circle.
     
        Ellipse(hDC, (rect.right / 2 - 100), (rect.bottom / 2 + 100),
            (rect.right / 2 + 100), (rect.bottom / 2 - 100));
     
        // Draw the interior circle.
     
        Ellipse(hDC, (rect.right / 2 -94), (rect.bottom / 2 + 94),
            (rect.right / 2 + 94), (rect.bottom / 2 - 94));
     
        // Draw the key.
     
        Rectangle(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 113),
            (rect.right / 2 + 13), (rect.bottom / 2 + 50));
        Rectangle(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 96),
            (rect.right / 2 + 13), (rect.bottom / 2 + 50));
     
        // Draw the horizontal lines.
     
        MoveToEx(hDC, (rect.right/2 - 150), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 - 16), (rect.bottom / 2 + 0));
     
        MoveToEx(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 + 13), (rect.bottom / 2 + 0));
     
        MoveToEx(hDC, (rect.right / 2 + 16), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 + 150), (rect.bottom / 2 + 0));
     
        // Draw the vertical lines.
     
        MoveToEx(hDC, (rect.right/2 + 0), (rect.bottom / 2 - 150), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 - 16));
     
        MoveToEx(hDC, (rect.right / 2 + 0), (rect.bottom / 2 - 13), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 13));
     
        MoveToEx(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 16), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 150));
     
        ::ReleaseDC(hWnd, hDC);
    }
    頁面空間到設備空間的轉換是原Windows接口的一部分,也是我們可以用代碼控制的一種轉換,頁面空間到設備空間的轉換所用的是兩個矩形的寬與高的比率,其中頁面空間中的矩形被稱為窗口,設備空間中的矩形被稱為視口,Windows把窗口原點映射到視口原點,把窗口范圍映射到視口范圍,就完成了這種轉換。

    設備空間到物理空間的轉換有幾個獨特之處:它只限于平移,并由Windows的窗口管理部分控制,這種轉換的唯一用途是確保設備空間的原點被映射到物理設備上的適當點上。沒有函數能設置這種轉換,也沒有函數可以獲取有關數據。因此我們不能人為干預。

    實際上我們需要完成的是從頁面空間到物理設備空間的映射,由于物理設備空間通常指應用程序窗口的客戶區,因此我們只用關注于從頁面空間到設備空間的映射就可以了。

    一旦應用程序建立了設備描述表(DC),并立即開始調用GDI繪圖或輸出函數,則運用默認頁面空間到設備空間的轉換和設備空間到客戶區的轉換(在應用程序調用SetWorldTransform函數之前,不會出現世界坐標空間到頁面空間的轉換)。

    默認頁面空間到設備空間的轉換結果是一對一的映射;即頁面空間上給出的一點映射到設備空間的一個點。正如前文講到的,這種轉換沒有以矩陣指定,而是通過把視口寬除以窗口寬,把視口高除以窗口高而得出的。在默認的情況下,視口尺寸為1x1個象素,窗口尺寸為1x1頁單位。

    幾乎在所有的GDI函數中使用的坐標值都是采用的邏輯單位。Windows必須將邏輯單位轉換為“設備單位”,即像素。Windows對所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函數和一些GDI函數(例如GetDeviceCaps函數),永遠使用設備坐標。“窗口”是基于邏輯坐標的,邏輯坐標可以是象素、毫米、英寸等單位;“視口”是基于設備坐標(象素)的。通常,視口和客戶區是相同的。

    窗口(邏輯)坐標轉換為視口(設備)坐標的兩個公式:
    xViewport=(xWindow-xWinOrg)*xViewExt/xWinExt+xViewOrg
    yViewport=(yWindow-yWinOrg)*yViewExt/yWinExt+yViewOrg

    視口(設備)坐標轉換為窗口(邏輯)坐標的兩個公式:
    xWindow=(xViewPort-xViewOrg)*xWinExt/xViewExt+xWinOrg
    yWindow=(yViewPort-yViewOrg)*yWinExt/yViewExt+yWinOrg

    在MM_TEXT映射方式下邏輯坐標和設備坐標的相互轉換
    窗口(邏輯)坐標轉換為視口(設備)坐標的兩個公式:
    xViewport = xWindow-xWinOrg+xViewOrg
    yViewport = yWindow-yWinOrg+yViewOrg
    視口(設備)坐標轉換為窗口(邏輯)坐標的兩個公式:
    xWindow = xViewport-xViewOrg+xWinOrg
    yWindow = yViewport-yViewOrg+yWinOrg

    CDC中提供了兩個成員函數函數SetViewportOrg和SetWindowOrg,用來改變視口和窗口的原點。
    如果將視口原點設置為(xViewOrg,yViewOrg),則邏輯點(0,0)就會被映射為設備點(xViewOrg,yViewOrg)。如果將窗口原點改變為(xWinOrg,yWinOrg),則邏輯點(xWinOrg,yWinOrg)將會被映射為設備點(0,0),即左上角。
    不管對窗口和視口原點作什么改變,設備點(0,0)始終是客戶區的左上角。

    說一點自己的感悟:
    坐標系有四種,上面介紹的很詳細了,就不多說了。
    對于很重要的從頁面坐標到設備坐標的轉換,頁面坐標用邏輯單位表示,可以采用長度度量單位如米或英尺來與邏輯單位相掛鉤,也可以用像素來和邏輯單位掛鉤,而且我們說窗口;設備坐標只用像素表示,而且我們說視口。因此從邏輯坐標到設備坐標有很多種映射方式:
    Mapping Mode Logical Unit Positive y-axis Extends...
    MM_TEXT 1 pixel Downward
    MM_HIMETRIC 0.01 mm Upward
    MM_TWIPS 1/1440 in Upward
    MM_HIENGLISH 0.001 in Upward
    MM_LOMETRIC 0.1 mm Upward
    MM_LOENGLISH 0.01 in Upward
    還有MM_ISOTROPIC(長度和寬度的比例因子一致)和MM_ANISOTROPIC(長寬比例因子可以不一致)。
    舉個例子來說,比如MM_HIMETRIC,每個邏輯單元代表0.01毫米,比如邏輯橫坐標100,代表1毫米的長度,而對于設備坐標(也可以說物理坐標)來說,如果分辨率是96dpi,那么也就是1英尺有96個像素,因此從1毫米先轉換為多少英尺,然后再轉換為多少個像素,就可以知道屏幕上在哪個位置顯示這個位置了。

    還需要注意的是,GDI函數都是用邏輯坐標來計算的,而非GDI函數以及少部分GDI函數都是用設備坐標也就是像素來表示的,設備坐標只能用像素來計算。

     

     

    posted on 2008-02-23 19:18 so true 閱讀(743) 評論(0)  編輯  收藏 所屬分類: C&C++

    主站蜘蛛池模板: 成人精品国产亚洲欧洲| 免费观看的毛片手机视频| 无码人妻一区二区三区免费看| 97在线免费视频| 99久久免费看国产精品| 成人免费无毒在线观看网站| 国产国产人免费视频成69大陆| 亚洲午夜国产片在线观看| 亚洲AV日韩AV天堂一区二区三区| 亚洲男人的天堂久久精品| 日本一区二区在线免费观看 | 性感美女视频免费网站午夜| 免费国产一级特黄久久| 亚洲欧洲日产国码久在线观看| 亚洲综合偷自成人网第页色| 在线视频网址免费播放| 一个人免费高清在线观看| 亚洲欧洲中文日韩久久AV乱码| 久久丫精品国产亚洲av| 一级女人18片毛片免费视频| xxxx日本免费| 亚洲va在线va天堂va四虎| 羞羞视频网站免费入口| 99久久这里只精品国产免费| 亚洲精品成人无限看| 亚洲sm另类一区二区三区| 久久久久成人片免费观看蜜芽| 国产v片免费播放| 亚洲欧美国产国产一区二区三区| 99精品视频免费| 亚洲日本乱码在线观看| 一级一级一级毛片免费毛片| 国产午夜影视大全免费观看| 色偷偷女男人的天堂亚洲网| 日韩精品极品视频在线观看免费 | 亚洲性色AV日韩在线观看| 在线观看AV片永久免费| 亚洲自国产拍揄拍| 日韩电影免费在线观看视频| 亚洲一区二区三区高清在线观看| 在线观看免费人成视频色9|