3

Does anybody know whether there is a possiblity to save or convert a DrawingContext to a Geometry?

E.g. after

using (DrawingContext dc = RenderOpen())
{
    dc.DrawLine(penSelected, Data.MidTop, Data.MidTop + vertical);
    dc.DrawLine(pen, Data.MidTop - horizontal, Data.MidTop + thickness);
    dc.DrawLine(pen, Data.MidTop + vertical - thickness, Data.MidTop + horizontal + vertical);
    dc.DrawText(new FormattedText(Data.Time2.ToString("0.0"), cultureinfo, FlowDirection.LeftToRight, typeface, 8, Brushes.Black),
        Data.MidTop + 3 * thickness);
    dc.DrawText(new FormattedText(Data.Time2.ToString("0.0"), cultureinfo, FlowDirection.LeftToRight, typeface, 8, Brushes.Black),
        Data.MidTop + vertical - horizontal - 3 * thickness);
}

to somehow save the drawn objects in a geometry?

Gerard
  • 13,023
  • 14
  • 72
  • 125
  • 2
    The question is how to get one single Geometry from all the drawn content in a DrawingVisual? – Clemens Apr 04 '14 at 12:42

1 Answers1

9

When you populate a DrawingVisual with visual content, you are effectively creating a hierarchical collection of Drawing objects, which are accessible by the DrawingVisual's Drawing property (of type DrawingGroup). Each of these Drawing objects is actually of one of the following types:

  • GeometryDrawing
  • GlyphRunDrawing
  • ImageDrawing
  • VideoDrawing
  • DrawingGroup

Two of these provide a property or method to get a Geometry. Obviously, GeometryDrawing has a Geometry property, whereas GlyphRunDrawing has a GlyphRun property that returns a GlyphRun object, which in turn has a BuildGeometry method. This method returns a Geometry of the outline of the GlyphRun's text.

A static helper method to create a Geometry from a DrawingGroup may look like this:

public static Geometry CreateGeometry(DrawingGroup drawingGroup)
{
    var geometry = new GeometryGroup();

    foreach (var drawing in drawingGroup.Children)
    {
        if (drawing is GeometryDrawing)
        {
            geometry.Children.Add(((GeometryDrawing)drawing).Geometry);
        }
        else if (drawing is GlyphRunDrawing)
        {
            geometry.Children.Add(((GlyphRunDrawing)drawing).GlyphRun.BuildGeometry());
        }
        else if (drawing is DrawingGroup)
        {
            geometry.Children.Add(CreateGeometry((DrawingGroup)drawing));
        }
    }

    geometry.Transform = drawingGroup.Transform;
    return geometry;
}

You would just pass the value of the DrawingVisual's Drawing property to this method:

var geometry = CreateGeometry(visual.Drawing);
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • That's great, +1! Notice that you should also apply the transform of the Drawing on the Geometry, if not null. Also, to cover the two additional cases (Image and Video) you can use the Rect property - its correctness depends on the purpose of the geometry. – MaMazav Apr 04 '14 at 14:11