Visão geral das geometrias de caminho
Este tópico descreve como usar Direct2D geometrias de caminho para criar desenhos complexos. Ele contém as seguintes seções:
- Pré-requisitos
- Geometrias de caminho em Direct2D
- Usando um ID2D1GeometrySink para popular uma geometria de caminho
- Exemplo: Criar um desenho complexo
- Tópicos relacionados
Pré-requisitos
Essa visão geral pressupõe que você esteja familiarizado com a criação de aplicativos básicos Direct2D, conforme descrito em Criar um aplicativo de Direct2D simples. Ele também pressupõe que você esteja familiarizado com os recursos básicos de geometrias Direct2D, conforme descrito na Visão geral de geometrias.
Geometrias de caminho em Direct2D
As geometrias de caminho são representadas pela interface ID2D1PathGeometry . Para instanciar uma geometria de caminho, chame o método ID2D1Factory::CreatePathGeometry . Esses objetos podem ser usados para descrever figuras geométricas complexas compostas por segmentos como arcos, curvas e linhas. Para preencher uma geometria de caminho com figuras e segmentos, chame o método Open para recuperar um ID2D1GeometrySink e use os métodos do coletor de geometria para adicionar figuras e segmentos à geometria do caminho.
Usando um ID2D1GeometrySink para popular uma geometria de caminho
ID2D1GeometrySink descreve um caminho geométrico que pode conter linhas, arcos, curvas de Bézier cúbicas e curvas quadráticas de Bézier.
Um coletor de geometria consiste em uma ou mais figuras. Cada figura é composta por um ou mais segmentos de linha, curva ou arco. Para criar uma figura, chame o método BeginFigure , passando o ponto de partida da figura e, em seguida, use seus métodos Add (como AddLine e AddBezier) para adicionar segmentos. Quando terminar de adicionar segmentos, chame o método EndFigure . Você pode repetir essa sequência para criar figuras adicionais. Quando terminar de criar números, chame o método Close .
Exemplo: Criar um desenho complexo
A ilustração a seguir mostra um desenho complexo com linhas, arcos e curvas de Bézier. O exemplo de código a seguir mostra como criar o desenho usando quatro objetos de geometria de caminho, um para a montanha esquerda, um para a montanha direita, um para o rio e outro para o sol com sinalizadores.
Criar uma geometria de caminho para a montanha esquerda
O exemplo primeiro cria uma geometria de caminho para a montanha esquerda, conforme mostrado na ilustração a seguir.
Para criar a montanha esquerda, o exemplo chama o método ID2D1Factory::CreatePathGeometry para criar um ID2D1PathGeometry.
hr = m_pD2DFactory->CreatePathGeometry(&m_pLeftMountainGeometry);
Em seguida, o exemplo usa o método Open para obter um coletor de geometria de um ID2D1PathGeometry e o armazena na variável pSink .
ID2D1GeometrySink *pSink = NULL;
hr = m_pLeftMountainGeometry->Open(&pSink);
Em seguida, o exemplo chama BeginFigure, passando D2D1_FIGURE_BEGIN_FILLED que indica que essa figura está preenchida e chama AddLines, passando uma matriz de D2D1_POINT_2F pontos (267, 177), (236, 192), (212, 160), (156, 255) e (346, 255).
O código a seguir mostra como fazer isso.
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);
Criar uma geometria de caminho para a montanha direita
Em seguida, o exemplo cria outra geometria de caminho para a montanha direita com pontos (481, 146), (449, 181), (433, 159), (401, 214), (381, 199), (323, 263) e (575, 263). A ilustração a seguir mostra como a montanha direita é exibida.
O código a seguir mostra como fazer isso.
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);
}
Criar uma geometria de caminho para o sol
Em seguida, o exemplo preenche outra geometria de caminho para o sol, conforme mostrado na ilustração a seguir.
Para fazer isso, a geometria do caminho cria um coletor e adiciona uma figura para o arco e uma figura para cada sinalizador ao coletor. Repetindo a sequência de BeginFigure, seus métodos Add (como AddBezier) e EndFigure, várias figuras são adicionadas ao coletor.
O código a seguir mostra como fazer isso.
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);
}
Criar uma geometria de caminho para o rio
Em seguida, o exemplo cria outro caminho de geometria para o rio que contém curvas de Bézier. A ilustração a seguir mostra como o rio é exibido.
O código a seguir mostra como fazer isso.
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);
}
Renderizar as Geometrias de Caminho na Tela
O código a seguir mostra como renderizar as geometrias de caminho populadas na exibição. Primeiro desenha e pinta a geometria do sol, ao lado da geometria da montanha esquerda, depois a geometria do rio, e finalmente a geometria da montanha direita.
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();
O exemplo completo gera a ilustração a seguir.
Tópicos relacionados