Search code examples
directxsharpdx

Undesired End-Caps with StrokeStyle when using PathGeometry.Widen()


I'm using SharpDX in order to draw polylines on .NET WinForms. These polylines represent the profile of sheetmetal.

A PathGeometry object is composed, defining the polyline:

'reset m_pathGeometry (the core geometry of this sheetmetal profile)
m_pathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)

' pointsRef = collection of points showing the segments & bends in this sheetmetal profile
Dim pointsRef As List(Of Vector2) = calculateSegmentsPoints()

' Add lines to m_pathGeometry using our points collection
Using sink As SimplifiedGeometrySink = m_pathGeometry.Open()
    sink.BeginFigure(pointsRef.First(), FigureBegin.Filled)
    sink.AddLines(pointsRef.ToArray)
    sink.EndFigure(FigureEnd.Open)
    sink.Close()
End Using

Before being drawn to screen I apply a transform (to take into account transformation & scale):

' update m_fillTransformedGeometry based on m_pathGeometry & the current transform matrix3x2,
m_fillTransformedGeometry = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_pathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)

' to draw the polyline
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)

The polyline gets drawn with a strokestyle, rounded line-joins and flat end-caps

With m_strokeStyleProps
   .LineJoin = LineJoin.Round
   .EndCap = CapStyle.Flat
   .StartCap = CapStyle.Flat
End With

Result is a bit pale, could use a stroke:

JustAFill

First idea was to draw the same polyline in a darker color, with a slightly wider StrokeWidth:

' First draw a wider stroke
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_strokeBrush, (plaatdikte + 0.2) * _transformMatrix.ScaleVector(1), m_strokeStyle)

' Then draw the fill
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)

The result is nice, but the end-caps don't get a stroke this way: NoEndCapStroke

Second idea is to create a (slightly widened) PathGeometry for the stroke itself by calling the Widen() method on the original polyline-PathGeometry.

'define m_widenedPathGeometry (makes op the outline/stroke of this sheetmetal profile)
m_widenedPathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)
Using sink As SimplifiedGeometrySink = m_widenedPathGeometry.Open()
    m_pathGeometry.Widen(0.2, sink)
    sink.Close()
End Using

This widened geometry gets drawn (taking in account transformation) as a 'stroke' prior to drawing the 'fill' (both using the same StrokeStyle!):

' update m_transGeom based on m_widenedPathGeometry & the current transform matrix3x2,
m_transGeom = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_widenedPathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)
'   to draw the stroke of the Polyline
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_transGeom, m_strokeBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)

' update m_fillTransformedGeometry based on m_pathGeometry & the current transform matrix3x2,
m_fillTransformedGeometry = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_pathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)
' to draw the fill of the PolyLine
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)

This generates an undesired effect on the End-Caps: (Either rounded, wich isn't defined in the StrokeStyle or something in between)

enter image description here

This Stroke/Fill - method kindof works correctly when I redefine the used StrokeStyle to have 'rounded' endcaps:

enter image description here

But the 'flat' end-caps is really what I'm after.

Any ideas why this is happening, or how I could tackle this differently ?

Cheers !


Solution

  • Found out what was wrong here!

    Writing this down for others that might encounter something similar to this.

    When creating the widened geometry i've added that the 'FigureEnd' property is set to 'Open', this prevents the geometry of creating a 'closed loop' on itself, wich results in those artifacts.

    m_widenedPathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)
    Using sink As SimplifiedGeometrySink = m_widenedPathGeometry.Open()
        m_pathGeometry.Widen(0.2, sink)
        **sink.EndFigure(FigureEnd.Open)**   <- adding this line leaves the stroke open!
        sink.Close()
    End Using