zoukankan      html  css  js  c++  java
  • Direct2D 几何图形

    通过ID2D1HwndRenderTarget,可以轻松地画作各种样式的长方形和椭圆形:

    View Code
    #include "Precompiled.h"
    #include "DesktopWindow.h"
    
    D2D1_COLOR_F const COLOR_BLUE    = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE     = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK     = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1StrokeStyle> m_style;
    
        void CreateDeviceIndependentResources()
        {
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLUE);
            auto size = m_target->GetSize();
            auto offset = 50.0f;
            auto rect = RectF( offset, offset, size.width - offset, size.height - offset );
            D2D1_ROUNDED_RECT rounded = { rect, 200.0f, 200.0f };
            D2D1_POINT_2F center = { size.width / 2.0f, size.height / 2.0 };
            D2D1_ELLIPSE ellipse = { center, center.x - offset, center.y - offset };
            
            m_brush->SetColor(COLOR_WHITE);
            m_brush->SetOpacity(1.0f);
            m_target->FillRectangle(rect, m_brush.Get());
    
            m_brush->SetColor(COLOR_BLACK);
            m_brush->SetOpacity(0.5f);
            m_target->DrawRectangle(rect, m_brush.Get(), 20.0f);
            
            m_target->DrawRoundedRectangle(rounded, m_brush.Get(), 40.0f);
    
            m_brush->SetColor(COLOR_YELLOW);
            m_target->DrawEllipse(ellipse, m_brush.Get(), 20.0f);
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

    通过运行在高中学过的一些数学知识,可以轻易绘制出一些其它有意思的图形:

    View Code
    #include "Precompiled.h"
    #include "DesktopWindow.h"
    #include <cmath>
    
    D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1StrokeStyle> m_style;
    
        void CreateDeviceIndependentResources()
        {
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        D2D1_POINT_2F EllipsePoint(D2D1_ELLIPSE const & ellipse, float angle)
        {
            const float pi = 3.1415926f;
    
            D2D1_POINT_2F point = 
            {
                ellipse.point.x + ellipse.radiusX * cos(angle * pi / 180.0f), 
                ellipse.point.y + ellipse.radiusY * sin(angle * pi / 180.0f), 
            };
            return point;
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLACK);
            auto size = m_target->GetSize();
            auto offset = 50.0f;
            auto rect = RectF( offset, offset, size.width - offset, size.height - offset );
            D2D1_ROUNDED_RECT rounded = { rect, 200.0f, 200.0f };
            D2D1_POINT_2F center = { size.width / 2.0f, size.height / 2.0f };
            D2D1_ELLIPSE ellipse = { center, center.x - offset, center.y - offset };
            
            m_brush->SetColor(COLOR_WHITE);
            m_target->FillEllipse(ellipse, m_brush.Get());
            m_brush->SetColor(COLOR_RED);
            m_target->DrawEllipse(ellipse, m_brush.Get(), 40.0f);
            m_target->DrawLine(
                EllipsePoint(ellipse, 135), 
                EllipsePoint(ellipse, 315), 
                m_brush.Get(), 40.0f);
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

    可以定义一些D2D1中的几何图形组件(ID2D1***Geometry),来简化绘制流程。注意,几何图形组件是独立于设备的资源(DeviceIndependentResources),因此只需要在CreateDeviceIndependentResources方法中定义即可。另外,几何图形组件是不可更改的(immutable),因此,一旦定义,将无法更改。以下是几何图形组件的一些基本应用:

    View Code
    #include "Precompiled.h"
    #include "DesktopWindow.h"
    
    D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1RectangleGeometry> m_rect;
        ComPtr<ID2D1RoundedRectangleGeometry> m_rounded;
        ComPtr<ID2D1EllipseGeometry> m_ellipse;
    
        void CreateDeviceIndependentResources()
        {
            D2D1_RECT_F rect = { 100.0f, 100.0f, 600.0f, 400.0f };
            D2D1_ROUNDED_RECT rounded = { rect, 40.0f, 40.0f };
            D2D1_ELLIPSE ellipse = 
            {
                { 350.0f, 250.0f }, 
                250.0f, 150.f,
            };
    
            m_factory->CreateRectangleGeometry(rect, m_rect.GetAddressOf());
            m_factory->CreateRoundedRectangleGeometry(rounded, m_rounded.GetAddressOf());
            m_factory->CreateEllipseGeometry(ellipse, m_ellipse.GetAddressOf());
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLUE);
            auto size = m_target->GetSize();
    
            m_brush->SetOpacity(0.5f);
    
            m_brush->SetColor(COLOR_WHITE);
            m_target->DrawGeometry(m_rect.Get(), m_brush.Get(), 40.0f);
    
            m_brush->SetColor(COLOR_RED);
            m_target->DrawGeometry(m_rounded.Get(), m_brush.Get(), 20.0f);
    
            m_brush->SetColor(COLOR_YELLOW);
            m_target->DrawGeometry(m_ellipse.Get(), m_brush.Get());
            m_target->FillGeometry(m_ellipse.Get(), m_brush.Get());
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

    可以使用路径几何图形(ID2D1PathGeometry),来定义更加复杂的图形,ID2D1PathGeometry是独立于设备的资源,因此只需在CreateDeviceIndependentResources方法中定义:

    View Code
    #include "Precompiled.h"
    #include "DesktopWindow.h"
    
    D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1PathGeometry> m_path;
    
        void CreateDeviceIndependentResources()
        {
            m_factory->CreatePathGeometry(m_path.GetAddressOf());
    
            ComPtr<ID2D1GeometrySink> sink;
            m_path->Open(sink.GetAddressOf());
    
            // 使用BEGIN_HOLLOW将不会填充多边形
            sink->BeginFigure(Point2F(50.0f, 50.0f), D2D1_FIGURE_BEGIN_HOLLOW);
            sink->AddLine(Point2F(250.0f, 50.0f));
            D2D1_POINT_2F points[] = 
            {
                { 250.0f, 250.0f }, 
                { 50.0f, 250.0f }
            };
            sink->AddLines(points, _countof(points));
            // 如果使用END_OPEN,则不会绘制最后一条边
            sink->EndFigure(D2D1_FIGURE_END_OPEN);
    
            // 可以绘制多个图形
            sink->BeginFigure(Point2F(300.0f, 50.0f), D2D1_FIGURE_BEGIN_FILLED);
            D2D1_POINT_2F points2[] = 
            {
                { 500.0f, 50.0f }, 
                { 550.0f, 250.0f }, 
                { 350.0f, 250.0f }, 
            };
            sink->AddLines(points2, _countof(points2));
            sink->EndFigure(D2D1_FIGURE_END_CLOSED);
    
            sink->Close();
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLUE);
            
            m_brush->SetColor(COLOR_YELLOW);
            m_target->FillGeometry(m_path.Get(), m_brush.Get());
    
            m_brush->SetColor(COLOR_RED);
            m_target->DrawGeometry(m_path.Get(), m_brush.Get(), 10.0f);
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

    注意定义的不同可以让图形也不同。

    除了路径组成的多边形外,Geometry还可以使用圆弧:

    View Code
    #include "stdafx.h"
    #include "DesktopWindow.h"
    
    D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1PathGeometry> m_arc1;
        ComPtr<ID2D1PathGeometry> m_arc2;
        ComPtr<ID2D1PathGeometry> m_arc3;
        ComPtr<ID2D1PathGeometry> m_arc4;
        D2D1_POINT_2F m_begin;  
        D2D1_POINT_2F m_end; 
         
        void BuildPath(ComPtr<ID2D1PathGeometry>& path, 
            D2D1_SWEEP_DIRECTION direction, D2D1_ARC_SIZE size)
        { 
            D2D1_ARC_SEGMENT arc = 
            {
                m_end, 
                { 100.0f, 100.0f }, 
                0.0f, 
                direction, 
                size
            };
            m_factory->CreatePathGeometry(path.ReleaseAndGetAddressOf());
    
            ComPtr<ID2D1GeometrySink> sink;
            path->Open(sink.GetAddressOf());
            sink->BeginFigure(m_begin, D2D1_FIGURE_BEGIN_FILLED);
            sink->AddArc(arc);
            sink->EndFigure(D2D1_FIGURE_END_OPEN);
            sink->Close();
        }
    
        void BuildPaths()
        {
            BuildPath(m_arc1, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE, D2D1_ARC_SIZE_LARGE);
            BuildPath(m_arc2, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE, D2D1_ARC_SIZE_SMALL);
            BuildPath(m_arc3, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_LARGE);
            BuildPath(m_arc4, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL);
        }
    
        void CreateDeviceIndependentResources()
        {
            m_begin = Point2F(100.0f, 60.0f);
            m_end = Point2F(200.0f, 210.0f);
    
            BuildPaths();
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLUE);
    
            m_brush->SetOpacity(1.0f);
            m_brush->SetColor(COLOR_RED);
            m_target->DrawGeometry(m_arc1.Get(), m_brush.Get(), 5.0f);
            m_target->DrawGeometry(m_arc2.Get(), m_brush.Get(), 5.0f);
            m_brush->SetColor(COLOR_WHITE);
            m_target->DrawGeometry(m_arc3.Get(), m_brush.Get(), 5.0f);
            m_target->DrawGeometry(m_arc4.Get(), m_brush.Get(), 5.0f);
    
            m_brush->SetColor(COLOR_BLACK);
            m_target->DrawLine(m_begin, m_end, m_brush.Get(), 3.0f);
    
            m_brush->SetOpacity(0.5f);
            m_brush->SetColor(COLOR_YELLOW);
            m_target->FillEllipse(Ellipse(m_begin, 8.0f, 8.0f), m_brush.Get());
            m_brush->SetColor(COLOR_YELLOW);
            m_target->FillEllipse(Ellipse(m_end, 8.0f, 8.0f), m_brush.Get());
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

    可以使用贝兹尔曲线(Bezier),来绘制出一些更加有意思的图形:

    View Code
    #include "stdafx.h"
    #include "DesktopWindow.h"
    
    D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
    D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
    D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
    D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };
    
    struct SampleWindow : DesktopWindow<SampleWindow>
    {
        ComPtr<ID2D1SolidColorBrush> m_brush;
        ComPtr<ID2D1PathGeometry> m_path;
        D2D1_POINT_2F m_c1;
        D2D1_POINT_2F m_c2;
        D2D1_POINT_2F start;
        D2D1_POINT_2F end;
    
        void CreateDeviceIndependentResources()
        {
            m_factory->CreatePathGeometry(m_path.GetAddressOf());
    
            ComPtr<ID2D1GeometrySink> sink;
            m_path->Open(sink.GetAddressOf());
            
            start = Point2F(100.0f, 600.0f);
            end = Point2F(900.0f, 600.0f);
            m_c1 = Point2F(50.0f, 50.0f);
            m_c2 = Point2F(600.0f, 50.0f);
            
            sink->BeginFigure(start, D2D1_FIGURE_BEGIN_FILLED);
            sink->AddBezier(BezierSegment(m_c1, m_c2, end));
            sink->EndFigure(D2D1_FIGURE_END_OPEN);
    
            sink->BeginFigure(start, D2D1_FIGURE_BEGIN_FILLED);
            D2D1_QUADRATIC_BEZIER_SEGMENT quad[] = 
            {
                { { 400.0f, 0.0f }, { 400.0f, 300.0f } }, 
                { { 400.0f, 600.0f}, end }
            };
            sink->AddQuadraticBeziers(quad, _countof(quad));
            sink->EndFigure(D2D1_FIGURE_END_OPEN);
    
            sink->Close();
        }
    
        void CreateDeviceResources()
        {
            m_target->CreateSolidColorBrush(COLOR_WHITE, 
                m_brush.ReleaseAndGetAddressOf());
        }
    
        void Draw()
        {
            m_target->Clear(COLOR_BLUE);
    
            m_brush->SetColor(COLOR_WHITE);
            m_target->FillEllipse(Ellipse(m_c1, 5.0f, 5.0f), m_brush.Get());
            m_target->FillEllipse(Ellipse(m_c2, 5.0f, 5.0f), m_brush.Get());
            m_target->FillEllipse(Ellipse(Point2F(400.0f, 0.0f), 5.0f, 5.0f), m_brush.Get());
            m_target->FillEllipse(Ellipse(Point2F(400.0f, 300.0f), 5.0f, 5.0f), m_brush.Get());
            m_target->FillEllipse(Ellipse(Point2F(400.0f, 600.0f), 5.0f, 5.0f), m_brush.Get());
    
            m_target->DrawGeometry(m_path.Get(), m_brush.Get(), 3.0f);
    
            m_brush->SetColor(COLOR_RED);
            m_target->DrawLine(start, m_c1, m_brush.Get(), 1.0f);
            m_target->DrawLine(end, m_c2, m_brush.Get(), 1.0f);
            m_target->DrawLine(start, Point2F(400.0f, 0.0f), m_brush.Get(), 1.0f);
            m_target->DrawLine(Point2F(400.0f, 0.0f), Point2F(400.0f, 300.0f), m_brush.Get(),  1.0f);
            m_target->DrawLine(Point2F(400.0f, 300.0f), Point2F(400.0f, 600.0f), m_brush.Get(), 1.0f);
            m_target->DrawLine(Point2F(400.0f, 600.0f), end, m_brush.Get(), 1.0f);
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        
        window.Run();
    }

  • 相关阅读:
    NX二次开发-UFUN获取系统相关信息UF_ask_system_info
    NX二次开发-UFUN设置环境变量UF_set_variable
    NX二次开发-UFUN获取环境变量路径,将环境变量转换为字符串,字符串拼接UF_translate_variable
    NX二次开发-UFUN终止UF_terminate
    NX二次开发-UFUN计时函数UF_begin_timer
    NX二次开发-获取WCS标识UF_CSYS_ask_wcs
    NX二次开发-UFUN将工程图转成CGM和PDF文件UF_CGM_export_cgm
    require.js简单入门
    【转】JS中的call()和apply()方法
    C# Enum枚举类型操作扩展类
  • 原文地址:https://www.cnblogs.com/sdflysha/p/3030043.html
Copyright © 2011-2022 走看看