Convert path to geometric shape

JTIM picture JTIM · Apr 10, 2014 · Viewed 9k times · Source

Hey everyone I have tried to sum up and come with the basic question and my idea which does not work so far :S

Basicly my question is: The user adds elements together, and I want to create a new element based on these figures, such that a new path can be made for the users defined element. Lets say I have a square and a triangle. The user combines this to a house. Now I want to make the house an element for the user. For this I need the path of the element, how do I create this?

My Idea The figure elements which are used are based on path strings. Therefore I want these to be converted to a geometry element that I can use later on. I use the code supplied by André Meneses in the answer below, the code replicated here:

public static Geometry PathMarkupToGeometry(ShieldGearViewModel shieldGearModelRec)
    {
        string pathMarkup = shieldGearModelRec.Gear.Path;
        try
        {
            string xaml =
            "<Path " +
            "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" +
            "<Path.Data>" + pathMarkup + "</Path.Data></Path>";
            var path = System.Windows.Markup.XamlReader.Load(xaml) as System.Windows.Shapes.Path;
            // Detach the PathGeometry from the Path
            if (path != null)
            {
                path.Height = shieldGearModelRec.Gear.Height;
                path.Width = shieldGearModelRec.Gear.Width;
                path.Fill = new SolidColorBrush(Colors.Green);
                path.Stretch = Stretch.Fill;
                Geometry geometry = path.Data;
                //Test not working, exception is thrown
                //Rect transRect = new Rect(shieldGearModelRec.Gear.x, shieldGearModelRec.Gear.y, shieldGearModelRec.Gear.Width, shieldGearModelRec.Gear.Height);
                //geometry.Transform.TransformBounds(transRect);
                path.Data = null;
                return geometry;
            }
            return null;
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
        return null;
    }

This I do to get a Geometry to follow the example from this link describes. The problem with the above is that I cannot access x or y positions, of the new geometry element, so how do I specify this position?

For the position I think this link might be a solution, just haven't gotten it working yet? :)

When this is done I add it to a geometrygroup based on the before link, such that I can get a path, for the new element. But the geometrygroup has 0 as bounds. So for this to work I need to define x and y for the individual geometry elements, and then this might solve the geomtrygroup problem or I then have to look at this after :) Question has been standing for toooo long :|

TEXT BELOW IS THE OLD QUESTION AND THOUGHTS

I have a string that I would like to convert to a geometric shape in the code behind. So I found this on Stackoverflow WPF C# Path: How to get from a string with Path Data to Geometry in Code (not in XAML)

This link suggests that one can convert a string to path using parse with the following code:

var path = new Path();
path.Data = Geometry.Parse("M 100,200 C 100,25 400,350 400,175 H 280");

However parse is not available on Windows Phone. My other efforts has not solved the issue. I tried with pathGeometry but did not seem to be possible to set a string as the path?

So my problem is how to convert a string to a geometric shape in code behind not binding to an element on view.

First Step So I succeeded in creating a path with the following

var pathTesting = new System.Windows.Shapes.Path();
var b = new System.Windows.Data.Binding
{
    Source = DecorationOnShield[i].Gear.Path
};
System.Windows.Data.BindingOperations.SetBinding(pathTesting, System.Windows.Shapes.Path.DataProperty, b);

Now I am trying to convert the path to a geometric shape.

Extra

My idea is to do the same as this link describes. Where the example shows :

var blackRectGeometry = new RectangleGeometry();
Rect rct = new Rect();
rct.X = 80;
rct.Y = 167;
rct.Width = 150;
rct.Height = 30;
blackRectGeometry.Rect = rct;

But instead of rectangle I would like to use an arbitrary shape in form of a path, but still be able to set information such as coordinates and size.

Extra

I was thinking of defining a usercontrol which consisted of a path only looking like this:

<UserControl x:Class="UndoRedoShield.View.Geometry"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
mc:Ignorable="d"
Canvas.Left="{Binding Gear.x}" Canvas.Top="{Binding Gear.y}">


<Path Data="{Binding Gear.Path}" Fill="{Binding Gear.Color}" Stretch="Fill" UseLayoutRounding="False" Height="{Binding Gear.Height}" Width="{Binding Gear.Width}" Opacity="{Binding Gear.Opacity}">
    <Path.RenderTransform>
        <ScaleTransform ScaleX="{Binding Gear.Scale}" ScaleY="{Binding Gear.Scale}"/>
    </Path.RenderTransform>

</Path>

</UserControl>

But have not been able to use it in any way regarding geometry. Anyone have any idea using this method? Any method is appreciated ! :)

extra extra :)

Is it possible to create a geometric shape out of uielements, such that a usercontrol that is rendered Can be converted to a geometric Path?

Progress

I found this link Where I can create a geometry from a path. The path has the property width and height.

But the properties I do not have in geometry or path is the following:

  1. Canvas.Left
  2. Canvas.Top
  3. Canvas.ZIndex (I think this is possible when I add it to a GeometryGroup)

Seems like this can be done through the bounds property of the Path.Data. But not ZIndex. So this still needs to be tested with geometryGroup, and the Geometry needs to be added to the GeometryGroup.

Answer

meneses.pt picture meneses.pt · Aug 7, 2014

Some time ago, while searching for a solution for this and I ended up creating this function. Maybe it will help you.

    public static Geometry PathMarkupToGeometry(string pathMarkup)
    {
        try
        {
            string xaml =
            "<Path " +
            "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" +
            "<Path.Data>" + pathMarkup + "</Path.Data></Path>";
            var path = XamlReader.Load(xaml) as Path;
            // Detach the PathGeometry from the Path
            if (path != null)
            {
                Geometry geometry = path.Data;
                path.Data = null;
                return geometry;
            }
            return null;
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
        return null;
    }

Then I call this function like this:

     var arrow = new Path
     {
        Data = DesignHelpers.PathMarkupToGeometry("M-1,0 L0,1 L1,0"),
        Fill = new SolidColorBrush(Colors.Black),
        Stretch = Stretch.Fill,
        Height = 12,
        Width = 18,
        HorizontalAlignment = HorizontalAlignment.Center
    };

I don't know if this will fit your needs exactly but maybe it can help.