最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析在Direct2D中畫Bezier曲線的實現(xiàn)方法

 更新時間:2013年05月17日 16:09:15   作者:  
本篇文章是對在Direct2D中畫Bezier曲線的實現(xiàn)方法進行了詳細(xì)的分析介紹,需要的朋友參考下
Direct2D通過ID2D1RenderTarget接口支持基本圖元(直線,矩形,圓角矩形,橢圓等)的繪制,然而,此接口并未提供對曲線繪制的直接支持。因此,想要使用Direct2D繪制一段通過指定點的曲線,比如Bezier曲線,必須借助于DrawGeometry()方法間接實現(xiàn)。需要通過一定的算法,將指定點轉(zhuǎn)換為定義Path的控制點。幸運的是,codproject上已經(jīng)有人做了這項工作,給出了相應(yīng)的轉(zhuǎn)換算法,并給出了C#版的實現(xiàn):
Draw a Smooth Curve through a Set of 2D Points with Bezier Primitives
C#的代碼可以很容易的轉(zhuǎn)換成C++版本的,下面是我轉(zhuǎn)換的一個用于Direct2D的繪制Bezier曲線的C++函數(shù):
復(fù)制代碼 代碼如下:

 /// <summary>
 /// Refer to : http://www.codeproject.com/KB/graphics/BezierSpline.aspx
 /// Solves a tridiagonal system for one of coordinates (x or y) of first Bezier control points.
 /// </summary>
 /// <param name="rhs">Right hand side vector.</param>
 /// <param name="x">Solution vector.</param>
 void GetFirstControlPoints(
     __in const std::vector<FLOAT>& rhs,
     __out std::vector<FLOAT>& x )
 {
     ATLASSERT(rhs.size()==x.size());
     int n = rhs.size();
     std::vector<FLOAT> tmp(n);    // Temp workspace.

     FLOAT b = 2.0f;
     x[0] = rhs[0] / b;
     for (int i = 1; i < n; i++) // Decomposition and forward substitution.
     {
         tmp[i] = 1 / b;
         b = (i < n-1 ? 4.0f : 3.5f) - tmp[i];
         x[i] = (rhs[i] - x[i-1]) / b;
     }
     for (int i = 1; i < n; i++)
     {
         x[n-i-1] -= tmp[n-i] * x[n-i]; // Back substitution.
     }
 }

 /// <summary>
 /// Refer to : http://www.codeproject.com/KB/graphics/BezierSpline.aspx
 /// Get open-ended Bezier Spline Control Points.
 /// </summary>
 /// <param name="knots">Input Knot Bezier spline points.</param>
 /// <param name="firstCtrlPt">Output First Control points array of knots.size()-1 length.</param>
 /// <param name="secondCtrlPt">Output Second Control points array of knots.size()-1 length.</param>
 void GetCurveControlPoints(
     __in const std::vector<D2D1_POINT_2F>& knots,
     __out std::vector<D2D1_POINT_2F>& firstCtrlPt,
     __out std::vector<D2D1_POINT_2F>& secondCtrlPt )
 {
     ATLASSERT( (firstCtrlPt.size()==secondCtrlPt.size())
         && (knots.size()==firstCtrlPt.size()+1) );

     int n = knots.size()-1;
     ATLASSERT(n>=1);

     if (n == 1)
     {
         // Special case: Bezier curve should be a straight line.
         // 3P1 = 2P0 + P3
         firstCtrlPt[0].x = (2 * knots[0].x + knots[1].x) / 3.0f;
         firstCtrlPt[0].y = (2 * knots[0].y + knots[1].y) / 3.0f;

         // P2 = 2P1 – P0
         secondCtrlPt[0].x = 2 * firstCtrlPt[0].x - knots[0].x;
         secondCtrlPt[0].y = 2 * firstCtrlPt[0].y - knots[0].y;
         return;
     }

     // Calculate first Bezier control points
     // Right hand side vector
     std::vector<FLOAT> rhs(n);

     // Set right hand side X values
     for (int i = 1; i < (n-1); ++i)
     {
         rhs[i] = 4 * knots[i].x + 2 * knots[i+1].x;
     }
     rhs[0] = knots[0].x + 2 * knots[1].x;
     rhs[n-1] = (8 * knots[n-1].x + knots[n].x) / 2.0f;
     // Get first control points X-values
     std::vector<FLOAT> x(n);
     GetFirstControlPoints(rhs,x);

     // Set right hand side Y values
     for (int i = 1; i < (n-1); ++i)
     {
         rhs[i] = 4 * knots[i].y + 2 * knots[i+1].y;
     }
     rhs[0] = knots[0].y + 2 * knots[1].y;
     rhs[n-1] = (8 * knots[n-1].y + knots[n].y) / 2.0f;
     // Get first control points Y-values
     std::vector<FLOAT> y(n);
     GetFirstControlPoints(rhs,y);

     // Fill output arrays.
     for (int i = 0; i < n; ++i)
     {
         // First control point
         firstCtrlPt[i] = D2D1::Point2F(x[i],y[i]);
         // Second control point
         if (i < (n-1))
         {
             secondCtrlPt[i] = D2D1::Point2F(2 * knots[i+1].x - x[i+1], 2*knots[i+1].y-y[i+1]);
         }
         else
         {
             secondCtrlPt[i] = D2D1::Point2F((knots[n].x + x[n-1])/2, (knots[n].y+y[n-1])/2);
         }
     }
 }

 HRESULT CreateBezierSpline(
     __in ID2D1Factory* pD2dFactory,
     __in const std::vector<D2D1_POINT_2F>& points,
     __out ID2D1PathGeometry** ppPathGeometry )
 {
     CHECK_PTR(pD2dFactory);
     CHECK_OUTPUT_PTR(ppPathGeometry);
     ATLASSERT(points.size()>1);

     int n = points.size();
     std::vector<D2D1_POINT_2F> firstCtrlPt(n-1);
     std::vector<D2D1_POINT_2F> secondCtrlPt(n-1);
     GetCurveControlPoints(points,firstCtrlPt,secondCtrlPt);

     HRESULT hr = pD2dFactory->CreatePathGeometry(ppPathGeometry);
     CHECKHR(hr);
     if (FAILED(hr))
         return hr;

     CComPtr<ID2D1GeometrySink> spSink;
     hr = (*ppPathGeometry)->Open(&spSink);
     CHECKHR(hr);
     if (SUCCEEDED(hr))
     {
         spSink->SetFillMode(D2D1_FILL_MODE_WINDING);
         spSink->BeginFigure(points[0],D2D1_FIGURE_BEGIN_FILLED);
         for (int i=1;i<n;i++)
             spSink->AddBezier(D2D1::BezierSegment(firstCtrlPt[i-1],secondCtrlPt[i-1],points[i]));
         spSink->EndFigure(D2D1_FIGURE_END_OPEN);
         spSink->Close();
     }
     return hr;
 }

下面是一個使用此函數(shù)繪制正弦函數(shù)的Sample,曲線的紅點是曲線的控制點:
復(fù)制代碼 代碼如下:

 #pragma once
 #include "stdafx.h"
 #include <Direct2DHelper.h>
 using D2D1::Point2F;
 using D2D1::SizeU;
 using D2D1::ColorF;
 using D2D1::Matrix3x2F;
 using D2D1::BezierSegment;
 using D2D1::RectF;

 #include <vector>
 using std::vector;
 #include <algorithm>
 #include <boost/math/distributions/normal.hpp>

 class CMainWindow :
     public CWindowImpl<CMainWindow,CWindow,CSimpleWinTraits>
 {
 public:
     BEGIN_MSG_MAP(CMainWindow)
         MSG_WM_PAINT(OnPaint)
         MSG_WM_ERASEBKGND(OnEraseBkgnd)
         MSG_WM_SIZE(OnSize)
         MSG_WM_CREATE(OnCreate)
         MSG_WM_DESTROY(OnDestroy)
     END_MSG_MAP()

     int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/)
     {
         CreateDeviceIndependentResource();
         CreateDeviceResource();
         CreateCurve();
         return 0;
     }

     void OnDestroy()
     {
         PostQuitMessage(0);
     }

     void OnPaint(CDCHandle)
     {
         CPaintDC dc(m_hWnd);
         Render();
     }

     BOOL OnEraseBkgnd(CDCHandle dc)
     {
         return TRUE;    // we have erased the background
     }

     void OnSize(UINT /*nType*/, CSize size)
     {
         if (m_spHwndRT)
         {
             m_spHwndRT->Resize(SizeU(size.cx,size.cy));
             CreateCurve();
         }
     }

 private:
     void Render()
     {
         if (!m_spHwndRT)
             CreateDeviceResource();

         m_spHwndRT->BeginDraw();
         m_spHwndRT->Clear(ColorF(ColorF::CornflowerBlue));

         m_spHwndRT->SetTransform(Matrix3x2F::Identity());

         D2D1_SIZE_F size = m_spHwndRT->GetSize();
         FLOAT width = size.width-50, height = size.height-50;
         D2D1_MATRIX_3X2_F reflectY = Direct2DHelper::ReflectYMatrix();
         D2D1_MATRIX_3X2_F translate = Matrix3x2F::Translation(size.width/2.0f,size.height/2.0f);
         m_spHwndRT->SetTransform(reflectY*translate);

         // draw coordinate axis
         m_spSolidBrush->SetColor(ColorF(ColorF::Red));
         m_spHwndRT->DrawLine(Point2F(-width*0.5f,0),Point2F(width*0.5f,0),m_spSolidBrush,2.0f);
         m_spSolidBrush->SetColor(ColorF(ColorF::DarkGreen));
         m_spHwndRT->DrawLine(Point2F(0,-height*0.5f),Point2F(0,height*0.5f),m_spSolidBrush,2.0f);

         // draw curve
         m_spSolidBrush->SetColor(ColorF(ColorF::Blue));
         m_spHwndRT->DrawGeometry(m_spPathGeometry,m_spSolidBrush,1.0f);

         // draw point marks
         m_spSolidBrush->SetColor(ColorF(ColorF::Red));
         for (auto p=m_Points.cbegin();p!=m_Points.cend();p++)
         {
             Direct2DHelper::DrawRectPoint(m_spHwndRT,m_spSolidBrush,(*p),5.0f);
         }

         HRESULT hr = m_spHwndRT->EndDraw();
         if (hr == D2DERR_RECREATE_TARGET)
             DiscardDeviceResource();
     }

     void CreateDeviceIndependentResource()
     {
         Direct2DHelper::CreateD2D1Factory(&m_spD2dFactory);
     }

     void CreateDeviceResource()
     {
         CRect rc;
         GetClientRect(&rc);

         CHECK_PTR(m_spD2dFactory);
         IFR(m_spD2dFactory->CreateHwndRenderTarget(
             D2D1::RenderTargetProperties(),
             D2D1::HwndRenderTargetProperties(m_hWnd,SizeU(rc.Width(),rc.Height())),
             &m_spHwndRT));
         IFR(m_spHwndRT->CreateSolidColorBrush(ColorF(ColorF::Red),&m_spSolidBrush));
     }

     void DiscardDeviceResource()
     {
         m_spSolidBrush.Release();
         m_spHwndRT.Release();
     }

     void CreateCurve()
     {
         if (!m_spHwndRT)
             return;
         if (m_spPathGeometry)
         {
             m_spPathGeometry.Release();
             m_Points.clear();
         }

         const int ptCount = 100;
         D2D1_SIZE_F size = m_spHwndRT->GetSize();
         FLOAT width = size.width-50.0f, height = size.height*0.4f;

 #define SIN_CURVE   
 #ifdef SIN_CURVE    // create sin curve
         FLOAT factor = static_cast<FLOAT>(4.0f*M_PI/width);
         FLOAT x = -width*0.5f, y = 0, dx = width/ptCount;
         for (int i=0;i<ptCount+1;i++)
         {
             y = height*sin(factor*x);
             m_Points.push_back(Point2F(x,y));
             x += dx;
         }
 #else                // create normal distribute curve
         FLOAT factor = 10.0f/width;
         FLOAT x = -width*0.5f, y = 0, dx = width/ptCount;
         boost::math::normal nd;
         for (int i=0;i<ptCount+1;i++)
         {
             y = height*static_cast<FLOAT>(boost::math::pdf(nd,factor*x));
             m_Points.push_back(Point2F(x,y));
             x += dx;
         }
 #endif // SIN_CURVE

         // create Bezier spline
         Direct2DHelper::CreateBezierSpline(m_spD2dFactory,m_Points,&m_spPathGeometry);
         CHECK_PTR(m_spPathGeometry);
     }

 private:
     CComPtr<ID2D1Factory> m_spD2dFactory;
     CComPtr<ID2D1HwndRenderTarget> m_spHwndRT;
     CComPtr<ID2D1SolidColorBrush> m_spSolidBrush;
     CComPtr<ID2D1PathGeometry> m_spPathGeometry;

     vector<D2D1_POINT_2F> m_Points;
 };


相關(guān)文章

  • C++實現(xiàn)將長整型數(shù)轉(zhuǎn)換為字符串的示例代碼

    C++實現(xiàn)將長整型數(shù)轉(zhuǎn)換為字符串的示例代碼

    這篇文章主要介紹了C++實現(xiàn)將長整型數(shù)轉(zhuǎn)換為字符串的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C/C++實現(xiàn)crc碼計算和校驗

    C/C++實現(xiàn)crc碼計算和校驗

    循環(huán)冗余校驗(Cyclic Redundancy Check, CRC)是一種根據(jù)網(wǎng)絡(luò)數(shù)據(jù)包或計算機文件等數(shù)據(jù)產(chǎn)生簡短固定位數(shù)校驗碼的一種信道編碼技術(shù)。本文主要介紹了C++實現(xiàn)crc碼計算和校驗的方法,需要的可以參考一下
    2023-03-03
  • Microsoft Visual Studio 2022的安裝與使用詳細(xì)教程

    Microsoft Visual Studio 2022的安裝與使用詳細(xì)教程

    Microsoft Visual Studio 2022是Microsoft Visual Studio軟件的一個高版本,能夠編寫和執(zhí)行C/C++代碼,具有強大的功能,是開發(fā)C/C++程序的主流軟件,這篇文章主要介紹了Microsoft Visual Studio 2022的安裝與使用詳細(xì)教程
    2024-01-01
  • C++無法打開源文件bits/stdc++.h的問題

    C++無法打開源文件bits/stdc++.h的問題

    這篇文章主要介紹了C++無法打開源文件bits/stdc++.h的問題以及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++棧的數(shù)組實現(xiàn)代碼

    C++棧的數(shù)組實現(xiàn)代碼

    這篇文章主要介紹了C++棧的數(shù)組實現(xiàn)方式,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • C++中this指針的理解與作用詳解

    C++中this指針的理解與作用詳解

    這篇文章主要給大家介紹了關(guān)于C++中this指針的理解與作用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C++實現(xiàn)LeetCode(107.二叉樹層序遍歷之二)

    C++實現(xiàn)LeetCode(107.二叉樹層序遍歷之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(107.二叉樹層序遍歷之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++ DLL實現(xiàn)循環(huán)播放音樂的示例詳解

    C++ DLL實現(xiàn)循環(huán)播放音樂的示例詳解

    這篇文章主要為大家詳細(xì)介紹了C++ DLL實現(xiàn)循環(huán)播放音樂的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解下
    2024-03-03
  • C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷

    C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷的相關(guān)資料,為了加快查找節(jié)點的前驅(qū)和后繼。對二叉樹的線索化就是對二叉樹進行一次遍歷,在遍歷的過程中檢測節(jié)點的左右指針是否為空,如果是空,則將他們改為指向前驅(qū)和后繼節(jié)點的線索,需要的朋友可以參考下
    2017-08-08
  • C++ 空指針解引用的解決方法

    C++ 空指針解引用的解決方法

    空指針解引用是一種常見且嚴(yán)重的錯誤,它通常由于指針未初始化、被設(shè)置為nullptr或指向無效地址引起,本文主要介紹了C++ 空指針解引用的解決方法,感興趣的可以了解一下
    2024-08-08

最新評論

蒙自县| 昌宁县| 叶城县| 新野县| 通辽市| 大丰市| 安义县| 玉树县| 东安县| 枞阳县| 泉州市| 双流县| 敦煌市| 固原市| 迁西县| 大宁县| 宜阳县| 玛多县| 甘谷县| 吴忠市| 丘北县| 镇巴县| 红原县| 株洲县| 双柏县| 彭州市| 长沙市| 松溪县| 溧水县| 临城县| 墨竹工卡县| 讷河市| 大安市| 乌鲁木齐市| 新邵县| 安丘市| 博爱县| 佛学| 和静县| 饶平县| 重庆市|