パス ジオメトリの概要
このトピックでは、Direct2D パス ジオメトリを使用して複雑な図面を作成する方法について説明します。 以下のセクションが含まれます。
前提条件
この概要では、「単純な Direct2D アプリケーションを作成する」の説明に従って、基本的 な Direct2D アプリケーションの作成に精通していることを前提としています。 また、「 ジオメトリの概要」で説明されているように、Direct2D ジオメトリの基本的な機能についても理解していることを前提としています。
Direct2D のパス ジオメトリ
パス ジオメトリは 、ID2D1PathGeometry インターフェイスで表されます。 パス ジオメトリをインスタンス化するには、 ID2D1Factory::CreatePathGeometry メソッドを 呼び出します。 これらのオブジェクトを使用すると、円弧、曲線、線などのセグメントで構成される複雑な幾何学的図形を記述できます。 パス ジオメトリに図形とセグメントを設定するには、 Open メソッドを呼び出して ID2D1GeometrySink を 取得し、geometry シンクのメソッドを使用して図形とセグメントをパス ジオメトリに追加します。
ID2D1GeometrySink を使用してパス ジオメトリを設定する
ID2D1GeometrySink は、直線、円弧、3 次ベジエ曲線、2 次ベジエ曲線を含むことができる幾何学的パスを記述します。
ジオメトリ シンクは、1 つ以上の図形で構成されます。 各図形は、1 つ以上の線分、曲線、または円弧セグメントで構成されます。 図形を作成するには、 BeginFigure メソッドを呼び出して図形の開始点を渡し、Add メソッド ( AddLine や AddBezier など) を使用してセグメントを追加します。 セグメントの追加が完了したら、 EndFigure メソッドを呼び出します。 この順序を繰り返して、追加の数値を作成できます。 図形の作成が完了したら、 Close メソッドを呼び出します。
例: 複雑な図面を作成する
次の図は、線、円弧、ベジエ曲線を含む複雑な描画を示しています。 次のコード例は、4 つのパス ジオメトリ オブジェクトを使用して図面を作成する方法を示しています。1 つは左山用、1 つは右山用、1 つは川用、1 つはフレアのある太陽用です。
左山のパス ジオメトリを作成する
次の図に示すように、最初に左山のパス ジオメトリを作成します。
左側の山を作成するには、 ID2D1Factory::CreatePathGeometry メソッドを呼び出して ID2D1PathGeometry を作成します。
hr = m_pD2DFactory->CreatePathGeometry(&m_pLeftMountainGeometry);
次に、 Open メソッドを使用して ID2D1PathGeometry からジオメトリ シンクを取得し、 pSink 変数に格納します。
ID2D1GeometrySink *pSink = NULL;
hr = m_pLeftMountainGeometry->Open(&pSink);
次に、 BeginFigure を呼び出し、この図が塗りつぶされていることを示す D2D1_FIGURE_BEGIN_FILLED を渡し、 AddLines を呼び出し、 D2D1_POINT_2F ポイントの配列 (267、177)、(236、192)、(212、160)、(156、255)、(346、255) の配列を渡します。
この方法を次のコードに示します。
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);
右山のパス ジオメトリを作成する
次に、ポイント (481、146)、(449、181)、(433、159)、(401、214)、(381、199)、(323、263)、および (575、263) を使用して、適切な山の別のパス ジオメトリを作成します。 次の図は、適切な山の表示方法を示しています。
この方法を次のコードに示します。
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);
}
太陽のパス ジオメトリを作成する
次の例では、次の図に示すように、太陽の別のパス ジオメトリを設定します。
これを行うには、パス ジオメトリによってシンクが作成され、円弧の図形と、各フレアの図形がシンクに追加されます。 BeginFigure、その Add (AddBezier など) メソッド、EndFigure のシーケンスを繰り返すことで、複数の図形がシンクに追加されます。
この方法を次のコードに示します。
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);
}
河川のパス ジオメトリを作成する
次に、ベジエ曲線を含む川の別のジオメトリ パスを作成します。 次の図は、川の表示方法を示しています。
この方法を次のコードに示します。
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);
}
パス ジオメトリをディスプレイにレンダリングする
次のコードは、設定されたパス ジオメトリをディスプレイにレンダリングする方法を示しています。 最初に太陽ジオメトリを描画して塗りつぶし、次に左の山ジオメトリ、次に川のジオメトリ、最後に右の山ジオメトリを描画します。
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();
完全な例では、次の図を出力します。
関連トピック