Condividi tramite


Panoramica delle geometrie del percorso

Questo argomento descrive come usare geometrie del percorso Direct2D per creare disegni complessi. Include le sezioni seguenti:

Prerequisiti

Questa panoramica presuppone che si abbia familiarità con la creazione di applicazioni Direct2D di base, come descritto in Creare un'applicazione Direct2D semplice. Si presuppone inoltre che si abbia familiarità con le funzionalità di base delle geometrie Direct2D, come descritto nella panoramica delle geometrie.

Geometrie del percorso in Direct2D

Le geometrie del percorso sono rappresentate dall'interfaccia ID2D1PathGeometry . Per creare un'istanza di una geometria del percorso, chiamare il metodo ID2D1Factory::CreatePathGeometry . Questi oggetti possono essere usati per descrivere figure geometriche complesse composte da segmenti quali archi, curve e linee. Per popolare una geometria di percorso con figure e segmenti, chiamare il metodo Open per recuperare un ID2D1GeometrySink e usare i metodi del sink geometry per aggiungere figure e segmenti alla geometria del percorso.

Uso di un ID2D1GeometrySink per popolare una geometria del percorso

ID2D1GeometrySink descrive un percorso geometrico che può contenere linee, archi, curve bezier cubiche e curve quadratiche di Bezier.

Un sink geometry è costituito da una o più figure. Ogni figura è costituita da uno o più segmenti di linea, curva o arco. Per creare una figura, chiamare il metodo BeginFigure , passando il punto iniziale della figura e quindi usare i metodi Add (ad esempio AddLine e AddBezier) per aggiungere segmenti. Al termine dell'aggiunta di segmenti, chiamare il metodo EndFigure . È possibile ripetere questa sequenza per creare figure aggiuntive. Al termine della creazione di figure, chiamare il metodo Close .

Esempio: Creare un disegno complesso

La figura seguente mostra un disegno complesso con linee, archi e curve di Bezier. L'esempio di codice che segue illustra come creare il disegno usando quattro oggetti geometry del percorso, uno per la montagna sinistra, una per la montagna destra, una per il fiume e una per il sole con razzi.

illustrazione di un fiume, montagne e sole, usando geometrie del percorso

Creare una geometria di percorso per la montagna sinistra

L'esempio crea prima una geometria di percorso per la montagna sinistra, come illustrato nella figura seguente.

Mostra un disegno complesso di un poligono che mostra una montagna.

Per creare la montagna sinistra, nell'esempio viene chiamato il metodo ID2D1Factory::CreatePathGeometry per creare un ID2D1PathGeometry.

hr = m_pD2DFactory->CreatePathGeometry(&m_pLeftMountainGeometry);

L'esempio usa quindi il metodo Open per ottenere un sink geometry da un ID2D1PathGeometry e lo archivia nella variabile pSink .

ID2D1GeometrySink *pSink = NULL;
hr = m_pLeftMountainGeometry->Open(&pSink);

L'esempio chiama quindi BeginFigure, passando D2D1_FIGURE_BEGIN_FILLED che indica che questa figura viene riempita, quindi chiama AddLines, passando una matrice di D2D1_POINT_2F punti, (267, 177), (236, 192), (212, 160), (156, 255) e (346, 255).

A tal fine, osservare il codice indicato di seguito.

pSink->SetFillMode(D2D1_FILL_MODE_WINDING);

pSink->BeginFigure(
    D2D1::Point2F(346,255),
    D2D1_FIGURE_BEGIN_FILLED
    );
D2D1_POINT_2F points[5] = {
   D2D1::Point2F(267, 177),
   D2D1::Point2F(236, 192),
   D2D1::Point2F(212, 160),
   D2D1::Point2F(156, 255),
   D2D1::Point2F(346, 255), 
   };
pSink->AddLines(points, ARRAYSIZE(points));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);

Creare una geometria del percorso per la montagna destra

L'esempio crea quindi un'altra geometria di percorso per la montagna destra con punti (481, 146), (449, 181), (433, 159), (401, 214), (381, 199), (323, 263) e (575, 263). Nella figura seguente viene illustrato come viene visualizzata la montagna destra.

illustrazione di un poligono che mostra una montagna

A tal fine, osservare il codice indicato di seguito.

        hr = m_pD2DFactory->CreatePathGeometry(&m_pRightMountainGeometry);
        if(SUCCEEDED(hr))
        {
            ID2D1GeometrySink *pSink = NULL;

            hr = m_pRightMountainGeometry->Open(&pSink);
            if (SUCCEEDED(hr))
            {
                pSink->SetFillMode(D2D1_FILL_MODE_WINDING);

                pSink->BeginFigure(
                    D2D1::Point2F(575,263),
                    D2D1_FIGURE_BEGIN_FILLED
                    );
                D2D1_POINT_2F points[] = {
                   D2D1::Point2F(481, 146),
                   D2D1::Point2F(449, 181),
                   D2D1::Point2F(433, 159),
                   D2D1::Point2F(401, 214),
                   D2D1::Point2F(381, 199), 
                   D2D1::Point2F(323, 263), 
                   D2D1::Point2F(575, 263)
                   };
                pSink->AddLines(points, ARRAYSIZE(points));
                pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
            }
            hr = pSink->Close();

            SafeRelease(&pSink);
       }

Creare una geometria del percorso per il sole

Nell'esempio viene quindi popolata un'altra geometria del percorso per il sole, come illustrato nella figura seguente.

illustrazione di un arco e curve più bezier che mostrano il sole

A tale scopo, la geometria del percorso crea un sink e aggiunge una figura per l'arco e una figura per ogni flare al sink. Ripetendo la sequenza di BeginFigure, i relativi metodi Add (ad esempio AddBezier) e EndFigure, vengono aggiunte più figure al sink.

A tal fine, osservare il codice indicato di seguito.

        hr = m_pD2DFactory->CreatePathGeometry(&m_pSunGeometry);
        if(SUCCEEDED(hr))
        {
            ID2D1GeometrySink *pSink = NULL;

            hr = m_pSunGeometry->Open(&pSink);
            if (SUCCEEDED(hr))
            {
                pSink->SetFillMode(D2D1_FILL_MODE_WINDING);
            
                pSink->BeginFigure(
                    D2D1::Point2F(270, 255),
                    D2D1_FIGURE_BEGIN_FILLED
                    );
                pSink->AddArc(
                    D2D1::ArcSegment(
                        D2D1::Point2F(440, 255), // end point
                        D2D1::SizeF(85, 85),
                        0.0f, // rotation angle
                        D2D1_SWEEP_DIRECTION_CLOCKWISE,
                        D2D1_ARC_SIZE_SMALL
                        ));            
                pSink->EndFigure(D2D1_FIGURE_END_CLOSED);

                pSink->BeginFigure(
                    D2D1::Point2F(299, 182),
                    D2D1_FIGURE_BEGIN_HOLLOW
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(299, 182),
                       D2D1::Point2F(294, 176),
                       D2D1::Point2F(285, 178)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(276, 179),
                       D2D1::Point2F(272, 173),
                       D2D1::Point2F(272, 173)
                       ));
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);

                pSink->BeginFigure(
                    D2D1::Point2F(354, 156),
                    D2D1_FIGURE_BEGIN_HOLLOW
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(354, 156),
                       D2D1::Point2F(358, 149),
                       D2D1::Point2F(354, 142)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(349, 134),
                       D2D1::Point2F(354, 127),
                       D2D1::Point2F(354, 127)
                       ));
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);

                pSink->BeginFigure(
                    D2D1::Point2F(322,164),
                    D2D1_FIGURE_BEGIN_HOLLOW
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(322, 164),
                       D2D1::Point2F(322, 156),
                       D2D1::Point2F(314, 152)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(306, 149),
                       D2D1::Point2F(305, 141),
                       D2D1::Point2F(305, 141)
                       ));              
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);

                pSink->BeginFigure(
                    D2D1::Point2F(385, 164),
                    D2D1_FIGURE_BEGIN_HOLLOW
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(385,164),
                       D2D1::Point2F(392,161),
                       D2D1::Point2F(394,152)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(395,144),
                       D2D1::Point2F(402,141),
                       D2D1::Point2F(402,142)
                       ));                
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);

                pSink->BeginFigure(
                    D2D1::Point2F(408,182),
                    D2D1_FIGURE_BEGIN_HOLLOW
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(408,182),
                       D2D1::Point2F(416,184),
                       D2D1::Point2F(422,178)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(428,171),
                       D2D1::Point2F(435,173),
                       D2D1::Point2F(435,173)
                       ));
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);
            }
            hr = pSink->Close();

            SafeRelease(&pSink);
       }

Creare una geometria del percorso per il fiume

L'esempio crea quindi un altro percorso geometry per il fiume che contiene curve bezier. La figura seguente mostra come viene visualizzato il fiume.

illustrazione delle curve di bezier che mostrano un fiume

A tal fine, osservare il codice indicato di seguito.

        hr = m_pD2DFactory->CreatePathGeometry(&m_pRiverGeometry);
    
        if(SUCCEEDED(hr))
        {
            ID2D1GeometrySink *pSink = NULL;

            hr = m_pRiverGeometry->Open(&pSink);
            if (SUCCEEDED(hr))
            {
                pSink->SetFillMode(D2D1_FILL_MODE_WINDING);
                pSink->BeginFigure(
                    D2D1::Point2F(183, 392),
                    D2D1_FIGURE_BEGIN_FILLED
                    );
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(238, 284),
                       D2D1::Point2F(472, 345),
                       D2D1::Point2F(356, 303)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(237, 261),
                       D2D1::Point2F(333, 256),
                       D2D1::Point2F(333, 256)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(335, 257),
                       D2D1::Point2F(241, 261),
                       D2D1::Point2F(411, 306)
                       ));
                pSink->AddBezier(
                   D2D1::BezierSegment(
                       D2D1::Point2F(574, 350),
                       D2D1::Point2F(288, 324),
                       D2D1::Point2F(296, 392)
                       ));
                pSink->EndFigure(D2D1_FIGURE_END_OPEN);
            }

Eseguire il rendering delle geometrie del percorso nella visualizzazione

Il codice seguente illustra come eseguire il rendering delle geometrie del percorso popolate nella visualizzazione. Disegna prima e disegna la geometria del sole, accanto alla geometria della montagna sinistra, poi la geometria del fiume e infine la geometria della montagna destra.

 m_pRenderTarget->BeginDraw();

 m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

 m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

 D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();
 m_pRenderTarget->FillRectangle(
     D2D1::RectF(0, 0, rtSize.width, rtSize.height),
     m_pGridPatternBitmapBrush
     );

 m_pRenderTarget->FillGeometry(m_pSunGeometry, m_pRadialGradientBrush);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black, 1.f));
 m_pRenderTarget->DrawGeometry(m_pSunGeometry, m_pSceneBrush, 1.f);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::OliveDrab, 1.f));
 m_pRenderTarget->FillGeometry(m_pLeftMountainGeometry, m_pSceneBrush);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black, 1.f));
 m_pRenderTarget->DrawGeometry(m_pLeftMountainGeometry, m_pSceneBrush, 1.f);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::LightSkyBlue, 1.f));
 m_pRenderTarget->FillGeometry(m_pRiverGeometry, m_pSceneBrush);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black, 1.f));
 m_pRenderTarget->DrawGeometry(m_pRiverGeometry, m_pSceneBrush, 1.f);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::YellowGreen, 1.f));
 m_pRenderTarget->FillGeometry(m_pRightMountainGeometry, m_pSceneBrush);

 m_pSceneBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black, 1.f));
 m_pRenderTarget->DrawGeometry(m_pRightMountainGeometry, m_pSceneBrush, 1.f);


 hr = m_pRenderTarget->EndDraw();

L'esempio completo restituisce l'illustrazione seguente.

illustrazione di un fiume, montagne e sole, usando geometrie del percorso

Creare un'applicazione Direct2D semplice

Panoramica delle geometrie