Dieser Artikel wurde maschinell übersetzt.

DirectX-Faktor

Direct2D-Geometrien und Bearbeitungsmöglichkeiten

Charles Petzold

Charles PetzoldGeometrie Sekundarstufe II kommt in zwei unterschiedlichen Varianten: Euklidischer Geometrie orientiert sich um Konstruktionen, Sätze und Beweise, während analytische Geometrie geometrische Figuren numerisch beschreibt mit Punkten in einem Koordinatensystem oft ein kartesischen Koordinatensystem zu Ehren des Pioniers der analytischen Geometrie, René Descartes genannt.

Es ist die analytische Geometrie, das bildet die Grundlage für den gesamten Vektor-Flügel der Computergrafik, so ist es Recht und billig, dass eine Schnittstelle namens ID2D1Geometry (und die sechs Schnittstellen, die daraus abgeleitet werden) ziemlich genau in der Mitte der Direct2D-Vektorgrafik sitzt.

In der letzten Ausgabe dieser Kolumne (msdn.microsoft.com/magazine/dn342879), ich wurde beschrieben, wie die ID2D1PathGeometry verwenden, um Zeilen in einer finger-painting Anwendung rendern, die unter Windows 8 ausgeführt wird.Nun möchte ich einen Schritt zurück und Geometrien im weiteren Detail zu erforschen und untersuchen, insbesondere einige faszinierenden Methoden zur Manipulation von Geometrien zu verschiedenen Geometrien durch ID2D1Geometry definiert.

Auch wenn Sie mit der Verwendung von Geometrien in der Windows-Runtime (WinRT) vertraut sind, bietet ID2D1Geometry, die in der WinRT Geometrie-Klasse verfügbar gemacht werden nicht.

Übersicht

Geometrien sind im wesentlichen Sammlungen von Koordinatenpunkte.Diese Koordinatenpunkte sind nicht an ein bestimmtes Gerät gebunden, daher Geometrien inhärent geräteunabhängige Objekte.Aus diesem Grund erstellen Sie Geometrien von verschiedenen Arten von Aufrufen von Methoden für das ID2D1Factory-Objekt, das die geräteunabhängige Direct2D Factory ist.Die sechs Geometrie-Erstellung-Methoden sind gezeigt Abbildung 1, zusammen mit dem Interface-Typ von Objekten, die sie erstellen.

Abbildung 1 die sechs Geometry-Methoden und Schnittstellen

ID2D1Factory-Methode Erstellte Objekt (abgeleitet von ID2D1Geometry)
CreateRectangleGeometry ID2D1RectangleGeometry
CreateRoundedRectangleGeometry ID2D1RoundedRectangleGeometry
CreateEllipseGeometry ID2D1EllipseGeometry
CreatePathGeometry ID2D1PathGeometry
CreateTransformedGeometry ID2D1TransformedGeometry
CreateGeometryGroup ID2D1GeometryGroup

Mit Ausnahme von CreatePathGeometry erstellen diese Methoden unveränderliche Objekte: Alle zum Erstellen des Objekts erforderlichen Informationen an die Methode übergeben wird, und Sie können etwas über die Geometrie nicht ändern, nachdem es erstellt wurde.

Der einzige Grund ist das ID2D1PathGeometry-Objekt anders ist da CreatePathGeometry ein Objekt zurückgibt, die im Wesentlichen leer ist.Ich werde beschreiben, wie Sie es in Kürze tanken.

CreateTransformedGeometry nimmt ein vorhandenes ID2D1Geometry-Objekt und eine affine Transformationsmatrix.Die resultierende Geometrie ist übersetzt, skaliert, gedreht oder verzerrt durch diese Matrix.Erstellen­GeometryGroup-Methode akzeptiert ein Array von ID2D1Geometry-Objekten und erstellt eine Geometrie, die die Zusammensetzung der einzelnen Geometrien ist.

Wenn Sie das Visual Studio Direct2D (XAML)-Projekt-Vorlage verwenden, um eine Windows-Speicher-Anwendung zu erstellen, DirectX zugreift, werden Sie im allgemeinen Geometry-Objekte erstellen, in der CreateDeviceIndependent­Ressourcenund Überschreiben der Rendering-Klasse verwenden sie während der gesamten Laufzeit des Programms, insbesondere während der Render-Überschreibung.

Die ID2D1RenderTarget-Schnittstelle (ableiten welche Schnittstellen wie z. B. ID2D1DeviceContext) definiert zwei Methoden für Rendering Geometrien auf einer Zeichenoberfläche: DrawGeometry und FillGeometry.

Die DrawGeometry-Methode zeichnet die Linien und Kurven der Geometrie mit einer angegebenen Brush, Strichstärke und Konturenstil, solide, punktierte, gestrichelte oder benutzerdefinierte Dash-Gemusterte Linien ermöglicht.Die FillGeometry-Methode füllt geschlossene Räumen einer Geometrie mit einem Pinsel und einer optionalen Deckkraftmaske.Sie können auch Geometrien zum Clipping, einhergehende Aufrufen von PushLayer für das Renderingziel mit einer D2D1_LAYER_PARAMETERS-Struktur, die die Geometrie enthält.

Manchmal braucht man eine Geometrie zu animieren.Am effizientesten ist eine Matrixtransformation auf das Renderingziel anwenden, vor dem Rendern der Geometrie.Wenn dies nicht ausreichend ist, müssen Sie die Geometrie, wahrscheinlich während der Update-Methode in der Renderingklasse neu zu erstellen.(Oder möchten Sie eine Reihe von Geometrien zu Beginn erstellen und speichern.) Obwohl neu erstellen von Geometrien den Rendering-Aufwand erhöht, ist es manchmal notwendig.Doch, zum größten Teil, wenn Sie nicht Geometrien neu erstellen müssen, nicht tun.

Die Geometrie-Senke

Das ID2D1PathGeometry-Objekt ist eine Sammlung von geraden Linien und Kurven, speziell kubisch und Quadratische Bézier-Kurven und Bögen, die Kurven auf den Umfang einer Ellipse sind.Sie können steuern, ob diese Linien und Kurven verbunden sind, und ob sie geschlossene Räumen definieren.

Füllen eine Pfadgeometrie mit Linien und Kurven, erfordert die Verwendung eines Objekts vom Typ ID2D1GeometrySink.Diese besondere Senke ist nicht für das Waschen von Geometrien!Stellen sie sich ein Gefäss — ein Ziel für Linien und Kurven, die dann von der Pfadgeometrie beibehalten werden.

Hier ist eine Pfadgeometrie zu erstellen:

  1. Erstellen Sie ein ID2D1PathGeometry-Objekt, indem Sie CreatePathGeometry für ein ID2D1Factory-Objekt aufrufen.
  2. Rufen Sie Open auf der ID2D1PathGeometry ein neues ID2D1GeometrySink-Objekt zu erhalten.
  3. Rufen Sie die Methoden für die ID2D1GeometrySink Linien und Kurven, die die Pfadgeometrie hinzu.
  4. Rufen Sie enge, auf die ID2D1GeometrySink.

Die ID2D1PathGeometry ist nicht nutzbar, bis Ende des ID2D1GeometrySink-Objekts aufgerufen wurde.Nachdem Close aufgerufen wird, ist die ID2D1PathGeometry unveränderlich: Dessen Inhalt nicht in irgendeiner Weise geändert werden, und Sie können öffnen wieder aufrufen.Die Geometrie-Senke hat nicht mehr einen Zweck, und Sie können es loswerden.

Das dritte Element in der Liste beinhaltet in der Regel den umfangreichsten Code.Eine Pfadgeometrie ist eine Sammlung von Figuren; Jede Figur ist eine Reihe von miteinander verbundenen Linien und Kurven, den so genannten Segmenten.Beim Aufrufen von Funktionen auf die ID2D1GeometrySink beginnen Sie mit einer optionalen Aufruf von SetFillMode Algorithmus Füllung eingeschlossen Bereiche an.Dann für jede Reihe verbundener Linien und Kurven in der Pfadgeometrie:

  1. Rufen Sie BeginFigure, Angabe der erste Punkt und ob geschlossene Räumen gefüllt werden.
  2. Rufen Sie Methoden, die mit dem Wort hinzufügen, verbundene Linien, Bézier-Kurven und Bögen um die Figur hinzuzufügen beginnen.
  3. Rufen Sie EndFigure, der angibt, ob der letzte Punkt automatisch auf den ersten Punkt mit einer geraden verbunden werden soll.

Wenn Sie die Dokumentation der ID2D1GeometrySink betrachten, nehmen Sie zur Kenntnis, die ID2D1SimplifiedGeometrySink, die eigentlich die wichtigsten Methoden definiert die Schnittstelle abgeleitet.Mehr über diese Differenzierung in Kürze.

Da der Inhalt einer ID2D1PathGeometry unveränderlich sind, sobald Sie ihren Pfad definiert haben benötigen Sie ein ID2D1Path alter­Geometrie müssen Sie neu erstellen und wieder durch den Pfad Definition Prozess.Jedoch, wenn Sie zusätzliche Zahlen nur am Anfang oder Ende einer vorhandenen Pfad Geometrie hinzufügen, ist eine Verknüpfung verfügbar: Eine neue Pfadgeometrie erstellen, fügen Sie einige Zahlen hinzu und übertragen Sie den Inhalt der vorhandenen Pfadgeometrie in der neuen Pfadgeometrie, durch Aufrufen der Stream-Funktion der vorhandenen Pfadgeometrie mit der neuen ID2D1GeometrySink.Sie können dann zusätzliche Zahlen vor Schließung hinzufügen.

Zeichnen und füllen

Jetzt bin ich bereit, einen Code zu zeigen.Die herunterladbare Geometrie­Experimente-Projekt entstand in Visual Studio 2012 mit der Windows Store Direct2D (XAML)-Vorlage.Ich benannte die SimpleTextRenderer-Klasse zu GeometryVarietiesRenderer, und ich entfernte alle Code und Markup Beispiel Textwiedergabe zugeordnet.

In der XAML-Datei definiert eine Reihe von Radio-Buttons für verschiedene Geometrie-Rendering-Techniken.Jedes Optionsfeld ist Mitglied einer RenderingOption-Enumeration definiert ich zugeordnet.Eine große Switch und Case-Anweisung in der Render überschreiben verwendet Member dieser Enumeration RenderingOption gesteuert, welcher Code ausgeführt wird.

Die Geometrie-Erstellung tritt während der CreateDevice­IndependentResources überschreiben.Eine Geometrie, die das Programm erstellt ist ein fünfzackiger Stern.Etwas verallgemeinert Methode, die dieser Geometrie baut erscheint Abbildung 2.Es besteht aus einer Figur mit vier Liniensegmenten, aber der letzte Punkt wird automatisch mit dem ersten Punkt verbunden.

Abbildung 2-Methode, um einen fünfzackigen Stern Geometrie bauen

HRESULT GeometryVarietiesRenderer::CreateFivePointedStar(
  float radius, ID2D1PathGeometry** ppPathGeometry)
{
  if (ppPathGeometry == nullptr)
    return E_POINTER;
  HRESULT hr = m_d2dFactory->CreatePathGeometry(ppPathGeometry);
  ComPtr<ID2D1GeometrySink> geometrySink;
  if (SUCCEEDED(hr))
  {
    hr = (*ppPathGeometry)->Open(&geometrySink);
  }
  if (SUCCEEDED(hr))
  {
    geometrySink->BeginFigure(Point2F(0, -radius), 
      D2D1_FIGURE_BEGIN_FILLED);
    for (float angle = 2 * XM_2PI / 5; 
        angle < 2 * XM_2PI; angle += 2 * XM_2PI / 5)
    {
      float sin, cos;
      D2D1SinCos(angle, &sin, &cos);
      geometrySink->AddLine(Point2F(radius * sin, -radius * cos));
    }
    geometrySink->EndFigure(D2D1_FIGURE_END_CLOSED);
    hr = geometrySink->Close();
  }
  return hr;
}

Abbildung 3 zeigt viel von der CreateDeviceIndependentResources-Methode. (Um die Liste einfach zu halten, nahm ich den Umgang mit fahrenden HRESULT-Werten.) Die Methode beginnt mit der Erstellung einer Geometrie, die eine Platz-Welle, ein Aufruf zum Erstellen des fünfzackigen Sterns und ein Aufruf an eine andere Methode zum Erstellen einer unendlich-Zeichen ähnelt. Zwei der diese Geometrien werden transformiert, und alle drei werden in der CreateGeometryGroup-Methode kombiniert (aufgerufen am unteren Rand Abbildung 3) in ein Element mit dem Namen M_geometryGroup.

Abbildung 3 ein Großteil der CreateDeviceIndependentResources überschreiben

void GeometryVarietiesRenderer::CreateDeviceIndependentResources()
{
  DirectXBase::CreateDeviceIndependentResources();
  // Create square-wave geometry
  HRESULT hr = m_d2dFactory->CreatePathGeometry(&m_squareWaveGeometry);
  ComPtr<ID2D1GeometrySink> geometrySink;
  hr = m_squareWaveGeometry->Open(&geometrySink);
  geometrySink->BeginFigure(Point2F(-250, 50), 
    D2D1_FIGURE_BEGIN_HOLLOW);
  geometrySink->AddLine(Point2F(-250, -50));
  geometrySink->AddLine(Point2F(-150, -50));
  geometrySink->AddLine(Point2F(-150,  50));
  geometrySink->AddLine(Point2F(-50,   50));
  geometrySink->AddLine(Point2F(-50,  -50));
  geometrySink->AddLine(Point2F( 50,  -50));
  geometrySink->AddLine(Point2F( 50,   50));
  geometrySink->AddLine(Point2F(150,   50));
  geometrySink->AddLine(Point2F(150,  -50));
  geometrySink->AddLine(Point2F(250,  -50));
  geometrySink->AddLine(Point2F(250,   50));
  geometrySink->EndFigure(D2D1_FIGURE_END_OPEN);
  hr = geometrySink->Close();
  // Create star geometry and translate it
  ComPtr<ID2D1PathGeometry> starGeometry;
  hr = CreateFivePointedStar(150, &starGeometry);
  hr = m_d2dFactory->CreateTransformedGeometry(starGeometry.Get(),
           Matrix3x2F::Translation(0, -200),
           &m_starGeometry);
  // Create infinity geometry and translate it
  ComPtr<ID2D1PathGeometry> infinityGeometry;
  hr = CreateInfinitySign(100, &infinityGeometry);
  hr = m_d2dFactory->CreateTransformedGeometry(infinityGeometry.Get(),
            Matrix3x2F::Translation(0, 200),
            &m_infinityGeometry);
  // Create geometry group
  CreateGeometryGroup();
  ...
}

Die CreateDeviceIndependentResources-Methode erstellt auch zwei Konturenstile mit abgerundeten enden und Verknüpfungen. Man ist solide und das andere ist übersät.

Die CreateDeviceDependentResources-Methode erstellt zwei Pinseln: schwarz für Zeichnung und rot für Füllung.

Wenn das Programm wird gestartet, das erste Optionsfeld aktiviert ist, und DrawGeometry heißt:

m_d2dContext->DrawGeometry(m_geometryGroup.Get(),
                           m_blackBrush.Get());

Das Ergebnis wird angezeigt, Abbildung 4, aussehende seltsam wie das Logo von einige seltsame Grafik-Kult.

The Startup Screen of GeometryExperimentation
Abbildung 4 der Startbildschirm von GeometryExperimentation

Da das Programm die drei separaten Geometrien zur Vereinfachung der Darstellung kombiniert, werden sie alle mit dem gleichen Pinsel gerendert werden. In ein richtiges Programm würde Sie wahrscheinlich pflegen eine Reihe von einzelnen Geometrien und Farbe sie alles anders.

Die ersten paar Optionen zeigen, wie die Geometrie mit ein dicker Strich und eine formatierte Zeile, einschließlich eine gepunktete Linie gezeichnet werden kann. (Während des Programms Strichdicken von 1, 10 und 20 Pixel dienen und sollte optisch leicht zu unterscheiden.)

Wenn Pfadgeometrien und Animation in XAML zu demonstrieren, möchte ich den Strich-Offset des einen Konturenstil eine XAML-basierte Animation zuweisen verursacht Punkte, um die Geometrie zu reisen. Sie können etwas ähnliches in DirectX (als die animierte Dot Offset Option veranschaulicht) tun, aber Sie explizit das ID2D1StrokeStyle-Objekt bei jedem Bildschirm-Aktualisierung wiederherstellen müssen. Dies geschieht in der Update-Methode.

Geschlossene Räumen der Geometrie können auch mit einem Pinsel ausgefüllt werden:

m_d2dContext->FillGeometry(m_geometryGroup.Get(),
                           m_redBrush.Get());

Das Ergebnis ist in Abbildung 5 dargestellt. Es gibt keine geschlossenen Räumen in der Rechteckwellenform. Das Interieur Pentagon des fünfzackigen Sterns ist nicht gefüllt, da den Füllmodus auf einen Algorithmus, bekannt als Alternative festgelegt ist. Sie können die beiden Radio-Buttons in der unteren linken Ecke Abbildung 5 gewundenen Füllmodus um das Pentagon zu füllen wählen. Im Füllmodus muss angegeben werden, wenn die ID2D1GeometryGroup zu erstellen, so dass das M_geometryGroup-Objekt neu erstellt werden, wenn entweder die beiden Radio-Buttons geklickt werden muss. Wenn die Geometrien in der Geometriegruppe überlappen, werden sich überschneidenden Bereiche gefüllt auch auf der Grundlage dieser Füllmodus.

Filling Geometries
Abbildung 5-Füllung-Geometrien

Oft möchten Sie sowohl zeichnen und füllen eine Geometrie. Sie wollen in der Regel FillGeometry zuerst anrufen und dann DrawGeometry, den Strich vollständig sichtbar zu halten.

Vereinfachte und Vereinfachung Geometrien

Angenommen Sie, die Anwendung erstellt ein ID2D1PathGeometry dynamisch, vielleicht aus Benutzereingaben, und Sie würden gerne "die Pfadgeometrie um die Figuren und die Segmente extrahieren verhören". Vielleicht möchten Sie diese Informationen als eine Reihe von standard-PathGeometry, PathFigure, LineSegment und BezierSegment-Tags in einem XAML-Format zu speichern.

Zunächst erscheint es nicht als ob dies möglich ist. Die ID2D1PathGeometry hat GetFigureCount und GetSegmentCount Methoden, aber keine Methoden um tatsächlich diese Abbildungen und Segmenten zu extrahieren.

Aber erinnern die Stream-Methode. Diese Methode akzeptiert eine ID2D1­GeometrySink und kopiert den Inhalt der Pfadgeometrie in das Spülbecken. Der Schlüssel hier ist, dass Sie Ihre eigene Klasse schreiben, die die ID2D1GeometrySink-Schnittstelle implementiert, und übergeben Sie eine Instanz dieser Klasse an die Stream-Methode. Innerhalb dieser benutzerdefinierten Klasse können Sie behandeln alle Aufrufe von BeginFigure, AddLine und So weiter und mach was du willst mit ihnen.

Natürlich ist eine solche Klasse nicht trivial. Müssten die Implementierungen aller Methoden in ID2D1GeometrySink, sowie ID2D1­SimplifiedGeometrySink und IUnknown.

Allerdings gibt es eine Möglichkeit, diese Arbeit etwas erleichtern: Die ID2D1Geometry-Schnittstelle definiert eine Methode namens Simplify, der eine Geometry-Objekt in eine "vereinfachte" Geometrie umwandelt, die nur gerade Linien und kubische Bezier-Splines enthält. Dieses Kunststück ist möglich, da Quadratische Bézier-Splines und Bögen durch kubische Bezier-Splines angenähert werden können. Dies bedeutet, dass die benutzerdefinierte Klasse nur die ID2D1SimplifiedGeometrySink und IUnknown-Methoden implementieren muss. Übergeben Sie einfach eine Instanz dieser benutzerdefinierten Klasse der Simplify-Methode alle Geometrie.

Simplify können Sie auch die vereinfachte Inhalt einer Geometrie in eine neue Pfadgeometrie kopieren. Hier ist der Code in der Geometrie­Experimente, die macht dieses (außer der HRESULT überprüfen):

m_d2dFactory->CreatePathGeometry(&m_simplifiedGeometry);
ComPtr<ID2D1GeometrySink> geometrySink;
m_simplifiedGeometry->Open(&geometrySink);
m_geometryGroup->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
                          IdentityMatrix(), geometrySink.Get());
geometrySink->Close();

Hinweis das erste Argument der Simplify-Methode bedeutet, dass Sie kubische Beziers und geraden Linien in der vereinfachte Pfad-Geometrie. Sie können einschränken, dass nur Zeilen, in diesem Fall die Bezier Kurven durch eine Reihe von geraden Linien angenähert werden. Dies ist ein so genanntes "Abflachung." Wenn Abplattung mit viel Präzision ausgeführt wird man nicht sagen, des Unterschied optisch, aber Sie können auch eine Abflachung Toleranz angeben, sodass die Bézier-Kurve nicht sehr gut angenähert ist. Hier ist ein Code in GeometryExperimentation, die eine "grob vereinfachte" Geometrie erstellt:

m_d2dFactory->CreatePathGeometry(&m_grosslySimplifiedGeometry);
m_grosslySimplifiedGeometry->Open(&geometrySink);
m_geometryGroup->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
                           IdentityMatrix(), 20, geometrySink.Get());
geometrySink->Close();

Die Sterne und quadratische Welle gleich aussehen, aber die unendlich-Zeichen ist nicht mehr ganz so glatt, wie im Abbildung 6. Standardmäßig ist die Abflachung Toleranz 0,25.

A Grossly Flattened Infinity Sign
Abbildung 6 abgeflacht grob Infinity Sign

Weitere Geometrie-Manipulationen

Die ID2D1Geometry-Schnittstelle definiert drei zusätzliche Methoden, die etwa so vereinfachen, dass sie eine neue Geometrie zu berechnen und schreiben Sie es in ein ID2D1SimplifiedGeometrySink. Gliederung und Widen erörtert hier, aber nicht CombineWithGeometry (weil es nur etwas interessantes mit mehrere überlappende Geometrien macht, und ich nichts in diesem Programm habe).

Wie Sie gesehen haben, können Pfadgeometrien sich überschneidenden Segmente haben. Die unendlich-Zeichen hat eine schneidende Segment rechts in der Mitte und der fünfzackigen Stern hat eine Reihe von sich überschneidenden Segmente. Vom ID2D1Geometry definierte Gliederung-Methode erstellt eine neue Pfadgeometrie basierend auf einem vorhandenen Pfadgeometrie, die eliminiert diese Kreuzungen, aber behält die gleichen geschlossenen Räumen.

Hier ist der Code in GeometryExperimentation, das die Geometriegruppe in eine Geometrie gegliederten Pfad konvertiert:

m_d2dFactory->CreatePathGeometry(&m_outlinedGeometry);
m_outlinedGeometry->Open(&geometrySink);
m_geometryGroup->Outline(IdentityMatrix(), geometrySink.Get());
geometrySink->Close();

Da dieses M_outlinedGeometry-Objekt die gleichen gefüllten Flächen als M_geometryGroup definiert wird, ist es anders, je nachdem, ob M_geometryGroup mit einer alternativen Füll-Modus oder kurvenreiche Füll-Modus erstellt wurde.

Die ursprüngliche Geometriegruppe verfügt über insgesamt drei Figuren: eine für den Stern, eine für die Rechteckwelle und eine für das unendlich-Zeichen. Wenn diese Geometriegruppe mit den alternativen Füll-Modus erstellt wird, enthält die Kontur der Geometrie acht Figuren: Fünf für die fünf Punkte des Sternes, eine für die Rechteckwelle und zwei für das unendlich-Zeichen. Aber optisch scheint es das gleiche. Wenn die Geometriegruppe mit den gewundenen Füll-Modus erstellt wird, jedoch hat die Kontur der Geometrie insgesamt vier Figuren: die unendlich-Zeichen hat zwei Zahlen genau wie bei den alternativen Füll-Modus, aber da das gesamte innere des Sterns ausgefüllt wird, der Stern besteht aus nur eine Figur, wie in Abbildung 7.

An Outlined Path Geometry
Abbildung 7 eine gegliederte Pfadgeometrie

Solch eine Geometrie von Grund auf neu zu definieren wäre mathematisch etwas schwierig, aber die Outline-Methode macht es ganz einfach. Da die Pfadgeometrie durch Umriss definiert keine sich überschneidenden Segmente enthält, ist im Füllmodus wirkungslos.

Ich finde die Widen-Methode, die interessanteste zu sein. Widen versteht, sollten eine Pfadgeometrie, die nur eine einzige gerade Linie zwischen zwei Punkten enthält. Wenn diese Geometrie gezeichnet wird, wird es mit einer bestimmten Dicke, gestrichelt, so dass es tatsächlich als ein ausgefülltes Rechteck dargestellt wird. Enthält die Linienart abgerundete enden, ist dieses Rechteck mit zwei gefüllten Halbkreisen verziert.

Die Widen-Methode berechnet eine Pfadgeometrie, die den Umriss des gerenderten Objekts beschreibt. Hierzu erfordert Widen Argumente angeben, die gewünschte Strichstärke und Konturenstil, genau wie DrawGeometry. Hier ist der Code in das GeometryExperimentation-Projekt:

m_d2dFactory->CreatePathGeometry(&m_widenedGeometry);
m_widenedGeometry->Open(&geometrySink);
m_geometryGroup->Widen(20, m_roundedStrokeStyle.Get(),
                        IdentityMatrix(), geometrySink.Get());
geometrySink->Close();

Beachten Sie die Strichstärke von 20 Pixel. Das Programm zeichnet dann diese erweiterten Geometrie mit einem ein-Pixel-Strichstärke:

m_d2dContext->DrawGeometry(m_widenedGeometry.Get(),
                           m_blackBrush.Get(), 1);

Das Ergebnis ist in Abbildung 8 dargestellt. Ich finde die Artefakte erstellt von dieser Prozeß sehr interessant. Es ist als ob ich irgendwie in die Innereien des Algorithmus Strichzeichnung peering bin.

A Widened Path Geometry
Abbildung 8 verbreitert Pfadgeometrie

Das GeometryExperimentation-Programm ermöglicht es auch, füllen die verbreiterte Pfadgeometrie:

m_d2dContext->FillGeometry(m_widenedGeometry.Get(),
                           m_redBrush.Get());

Füllen eine Pfadgeometrie, die verbreitert wurde, hat mit einem bestimmten Strichbreite und Konturenstil ist optisch identisch mit streicheln den Originalpfad mit dieser Breite und Stil. Der nur sichtbare Unterschied zwischen den gerundet Breite Strich zeichnen und füllen erweitert Optionen im GeometryExperimentation ist die Farbe, weil ich schwarz für Zeichnung und rot für die Füllung verwenden.

Vielleicht möchten füllen und eine ausgebaute Pfadgeometrie zu zeichnen, aber Sie würde wahrscheinlich lieber, dass die internen Artefakte entfernt werden. Dabei ist besonders einfach. Wenden Sie einfach die Outline-Methode auf die erweiterten Pfadgeometrie:

m_d2dFactory->CreatePathGeometry(&m_outlinedWidenedGeometry);
m_outlinedWidenedGeometry->Open(&geometrySink);
m_widenedGeometry->Outline(IdentityMatrix(), geometrySink.Get());
geometrySink->Close();

Wenn Sie ausfüllen und die Geometrie gegliederten verbreiterte Pfad zu zeichnen, Sie jetzt das Bild im Abbildung 9. Es ist frei von Artefakten und optisch ganz anders als alles, was sonst von diesem Programm gerendert, und anders als alles wäre ich mutig genug, um Code von Grund auf neu.

An Outlined Widened Path Geometry, Stroked and Filled
Abbildung 9 eine konturierte verbreitert Pfadgeometrie, streichelte und gefüllt

Alle anderen?

Es gibt eine andere Methode, die Geometriedaten in einer ID2D1SimplifiedGeometrySink schreibt, aber möglicherweise müssen Sie dafür die Jagd gehen. Es zählt nicht die Direct2D-Schnittstelle. Es ist in DirectWrite, und es ist die GetGlyphRunOutline Methode der IDWriteFontFace. Diese leistungsfähige Methode generiert Pfadgeometrien aus Textpfaden Charakter, und es ist einfach auch Spaß zu ignorieren. Bleiben Sie am Ball!

Charles Petzold schreibt seit langem redaktionelle Beiträge für das MSDN Magazin und ist Autor von „Programming Windows, 6th edition“ (O’Reilly Media, 2012), einem Buch über das Schreiben von Anwendungen für Windows 8. Die Adresse seiner Website lautet charlespetzold.com.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Wessam Bahnassi (In|Framez Technology), Worachai Chaoweeraprasit (Microsoft), Anthony Hodsdon (Microsoft) und Michael B. McLaughlin (Bob Taco Industries)

Anthony Hodsdon ist seit seiner Gründung in Windows 7 ein Entwickler in der Direct2D-Team. Seine Interessenschwerpunkte sind Geometrie (analytische und euklidischen) und numerische Algorithmen.

Worachai Chaoweeraprasit führend bei der Entwicklung von Direct2D und DirectWrite. Er liebt gute Typografie und mind-bendingly schnelle Grafik. Er lehrte seine dritte-Schüler in seiner Freizeit einfacher programmieren als Bewegung blockiert--er sagte ihm, es heißt einfach, C.

Michael B. McLaughlin ist ein Visual C++-MVP und der Inhaber von Bob Taco Industries, ein Mikro-ISV und Consultinggesellschaft. Er war früher ein XNA/DirectX MVP und ist ein ehemaliger Rechtsanwalt. Seine Website ist bobtacoindustries.com und seine Twitter-Griff ist @mikebmcl.

Wessam Bahnassi ist ein Software-Ingenieur mit großer Leidenschaft für Computergrafiken und Spiele. 7 Jahre lang arbeitete er als ein führen Rendering Engineering bei Electronic Arts. Jetzt ist er Lead Programmer bei In|Framez Technology Corp., ein Aufseher im arabisch Game Developer Network, ein DirectX MVP seit 2003 und jetzt Visual C++ MVP.