Übersicht über Pfadgeometrien
In diesem Thema wird beschrieben, wie Sie Direct2D-Pfadgeometrien verwenden, um komplexe Zeichnungen zu erstellen. Der Abschnitt ist wie folgt gegliedert.
- Voraussetzungen
- Pfadgeometrien in Direct2D
- Verwenden eines ID2D1GeometrySink zum Auffüllen einer Pfadgeometrie
- Beispiel: Erstellen einer komplexen Zeichnung
- Zugehörige Themen
Voraussetzungen
In dieser Übersicht wird davon ausgegangen, dass Sie mit dem Erstellen grundlegender Direct2D-Anwendungen vertraut sind, wie unter Erstellen einer einfachen Direct2D-Anwendung beschrieben. Außerdem wird davon ausgegangen, dass Sie mit den grundlegenden Features von Direct2D-Geometrien vertraut sind, wie in der Übersicht über Geometrien beschrieben.
Pfadgeometrien in Direct2D
Pfadgeometrien werden durch die ID2D1PathGeometry-Schnittstelle dargestellt. Um eine Pfadgeometrie zu instanziieren, rufen Sie die ID2D1Factory::CreatePathGeometry-Methode auf . Diese Objekte können verwendet werden, um komplexe geometrische Figuren zu beschreiben, die aus Segmenten wie Bögen, Kurven und Linien bestehen. Um eine Pfadgeometrie mit Abbildungen und Segmenten aufzufüllen, rufen Sie die Open-Methode auf, um einen ID2D1GeometrySink abzurufen, und verwenden Sie die Methoden der Geometriesenke, um der Pfadgeometrie Zahlen und Segmente hinzuzufügen.
Verwenden eines ID2D1GeometrySink zum Auffüllen einer Pfadgeometrie
ID2D1GeometrySink beschreibt einen geometrischen Pfad, der Linien, Bögen, kubische Bézierkurven und quadratische Bézierkurven enthalten kann.
Eine Geometriesenke besteht aus einer oder mehreren Abbildungen. Jede Abbildung besteht aus einem oder mehreren Linien-, Kurven- oder Bogensegmenten. Rufen Sie zum Erstellen einer Abbildung die BeginFigure-Methode auf, übergeben Sie den Ausgangspunkt der Abbildung, und verwenden Sie dann die Add-Methoden (z. B. AddLine und AddBezier), um Segmente hinzuzufügen. Wenn Sie das Hinzufügen von Segmenten abgeschlossen haben, rufen Sie die EndFigure-Methode auf. Sie können diese Sequenz wiederholen, um zusätzliche Abbildungen zu erstellen. Wenn Sie mit dem Erstellen von Abbildungen fertig sind, rufen Sie die Close-Methode auf.
Beispiel: Erstellen einer komplexen Zeichnung
Die folgende Abbildung zeigt eine komplexe Zeichnung mit Linien, Bögen und Bézierkurven. Im folgenden Codebeispiel wird gezeigt, wie die Zeichnung mithilfe von vier Pfadgeometrieobjekten erstellt wird: eines für den linken Berg, eines für den rechten Berg, eines für den Fluss und eines für die Sonne mit Eruptionen.
Erstellen einer Pfadgeometrie für den linken Berg
Im Beispiel wird zunächst eine Pfadgeometrie für den linken Berg erstellt, wie in der folgenden Abbildung dargestellt.
Um den linken Berg zu erstellen, ruft das Beispiel die ID2D1Factory::CreatePathGeometry-Methode auf, um eine ID2D1PathGeometry-Methode zu erstellen.
hr = m_pD2DFactory->CreatePathGeometry(&m_pLeftMountainGeometry);
Im Beispiel wird dann die Open-Methode verwendet, um eine Geometriesenke aus einer ID2D1PathGeometry abzurufen und in der pSink-Variablen zu speichern.
ID2D1GeometrySink *pSink = NULL;
hr = m_pLeftMountainGeometry->Open(&pSink);
Im Beispiel wird dann BeginFigure aufgerufen, wobei D2D1_FIGURE_BEGIN_FILLED übergeben wird, der angibt, dass diese Abbildung ausgefüllt ist. Anschließend wird AddLines aufgerufen, wobei ein Array von D2D1_POINT_2F Punkten (267, 177), (236, 192), (212, 160), (156, 255) und (346, 255) übergeben wird.
Dies wird im folgenden Code veranschaulicht.
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);
Erstellen einer Pfadgeometrie für den rechten Berg
Das Beispiel erstellt dann eine weitere Pfadgeometrie für den rechten Berg mit Punkten (481, 146), (449, 181), (433, 159), (401, 214), (381, 199), (323, 263) und (575, 263). Die folgende Abbildung zeigt, wie der rechte Berg angezeigt wird.
Dies wird im folgenden Code veranschaulicht.
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);
}
Erstellen einer Pfadgeometrie für die Sonne
Im Beispiel wird dann eine weitere Pfadgeometrie für die Sonne aufgefüllt, wie in der folgenden Abbildung gezeigt.
Dazu erstellt die Pfadgeometrie eine Senke und fügt der Senke eine Abbildung für den Bogen und eine Abbildung für jede Flare hinzu. Durch Wiederholen der Sequenz von BeginFigure, den Add-Methoden (z. B . AddBezier) und EndFigure werden der Senke mehrere Abbildungen hinzugefügt.
Dies wird im folgenden Code veranschaulicht.
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);
}
Erstellen einer Pfadgeometrie für den Fluss
Im Beispiel wird dann ein weiterer Geometriepfad für den Fluss erstellt, der Bézierkurven enthält. Die folgende Abbildung zeigt, wie der Fluss angezeigt wird.
Dies wird im folgenden Code veranschaulicht.
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);
}
Rendern der Pfadgeometrien auf dem Display
Der folgende Code zeigt, wie die aufgefüllten Pfadgeometrien auf der Anzeige gerendert werden. Es zeichnet und zeichnet zuerst die Sonnengeometrie, neben der linken Berggeometrie, dann die Flussgeometrie und schließlich die rechte Berggeometrie.
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();
Im vollständigen Beispiel wird die folgende Abbildung ausgegeben.
Zugehörige Themen