Como recuperar dados geometry estendendo ID2D1SimplifiedGeometrySink
Embora um objeto ID2D1Geometry seja imutável, há casos em que você precisa manipular os dados de geometria em um objeto geometry de caminho. Direct2D permite que você faça isso fornecendo uma interface extensível chamada ID2D1SimplifiedGeometrySink. Para ilustração de conceito, este tópico descreve como estender essa interface para recuperar os dados de geometria de um objeto geometry de caminho.
Para estender a interface ID2D1SimplifiedGeometrySink
- Implemente uma classe que herda de ID2D1SimplifiedGeometrySink.
- Crie uma instância dessa classe e passe-a para ID2D1Geometry::Simplify.
O exemplo de código a seguir mostra como implementar uma classe chamada SpecializedSink que herda da interface ID2D1SimplifiedGeometrySink . Para simplificar a ilustração de conceito, o método AddLines estendido recupera os dados de geometria e os exibe na janela do console; você pode personalizar esse método para atender às suas necessidades de dados específicas.
class SpecializedSink : public ID2D1SimplifiedGeometrySink
{
public:
SpecializedSink()
: m_cRef(1)
{
}
STDMETHOD_(ULONG, AddRef)(THIS)
{
return InterlockedIncrement(reinterpret_cast<LONG volatile *>(&m_cRef));
}
STDMETHOD_(ULONG, Release)(THIS)
{
ULONG cRef = static_cast<ULONG>(
InterlockedDecrement(reinterpret_cast<LONG volatile *>(&m_cRef)));
if(0 == cRef)
{
delete this;
}
return cRef;
}
STDMETHOD(QueryInterface)(THIS_ REFIID iid, void** ppvObject)
{
HRESULT hr = S_OK;
if (__uuidof(IUnknown) == iid)
{
*ppvObject = static_cast<IUnknown*>(this);
AddRef();
}
else if (__uuidof(ID2D1SimplifiedGeometrySink) == iid)
{
*ppvObject = static_cast<ID2D1SimplifiedGeometrySink*>(this);
AddRef();
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT * /*beziers*/,
UINT /*beziersCount*/)
{
// Customize this method to meet your specific data needs.
}
STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointsCount)
{
// Customize this method to meet your specific data needs.
printf("\n\nRetrieving geometry data from a derived ID2D1SimplifiedGeometrySink object:\n");
for (UINT i = 0; i < pointsCount; ++i)
{
printf("%.0f, %.0f\n", points[i].x, points[i].y);
}
}
STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint,
D2D1_FIGURE_BEGIN figureBegin)
{
}
STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd)
{
}
STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode)
{
}
STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags)
{
}
STDMETHOD(Close)()
{
return S_OK;
}
private:
UINT m_cRef;
};
Em seguida, o exemplo usa um conjunto de dados (182, 209), (211, 251), (251, 226), (392, 360) e (101, 360) para criar uma geometria de caminho populada (m_pGeometry) em que os dados podem ser recuperados.
hr = m_pD2DFactory->CreatePathGeometry(&m_pGeometry);
if(SUCCEEDED(hr))
{
ID2D1GeometrySink *pSink = NULL;
hr = m_pGeometry->Open(&pSink);
if (SUCCEEDED(hr))
{
pSink->SetFillMode(D2D1_FILL_MODE_WINDING);
pSink->BeginFigure(
D2D1::Point2F(101,360),
D2D1_FIGURE_BEGIN_FILLED
);
D2D1_POINT_2F points[5] = {
D2D1::Point2F(182,209),
D2D1::Point2F(211,251),
D2D1::Point2F(251,226),
D2D1::Point2F(392,360),
D2D1::Point2F(101,360),
};
printf("Adding the following geometry data to an ID2D1GeometrySink object:\n");
printf("182, 209\n");
printf("211, 251\n");
printf("251, 226\n");
printf("392, 360\n");
printf("101, 360\n");
pSink->AddLines(points, ARRAYSIZE(points));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
hr = pSink->Close();
pSink->Release();
Por fim, o exemplo cria um objeto SpecializedSink e, em seguida, chama o método ID2D1Geometry::Simplify , passando o objeto SpecializedSink e o parâmetro D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES , o que faz com que todas as curvas sejam mescladas em segmentos de linha.
SpecializedSink *pSpecializedSink = NULL;
if (SUCCEEDED(hr))
{
pSpecializedSink = new SpecializedSink();
if (!pSpecializedSink)
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = m_pGeometry->Simplify(
D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES, // This causes any curves to be flattened into line segments.
NULL, // world transform
pSpecializedSink
);
if (SUCCEEDED(hr))
{
hr = pSpecializedSink->Close();
}
pSpecializedSink->Release();
}
O programa cria saídas conforme mostrado na captura de tela a seguir.
Tópicos relacionados