Search code examples
c#wpfpolygoninkcanvas

Selecting polygon on InkCanvas


I have an application where I draw polygons on inkCanvas. I would like to add a function where after clicking one of drawn polygons it would be in editing mode and then I could change some of this proporties for example Fill.

I wrote this code but it selects all area from top left of inkcanvas to the end of my polygon but I need only polygon area.

Xaml:

<DockPanel>
    <ToolBarTray DockPanel.Dock="Left" Orientation="Vertical" IsLocked="True">
        <ToolBar Padding="2">
            <RadioButton x:Name="rbDraw" IsChecked="False"
                    ToolTip="Add Rectangle" Margin="3" Checked="rbDraw_Checked">
                <Rectangle Width="20" Height="12" Stroke="Blue"
                    Fill="LightBlue" />
            </RadioButton>
            <RadioButton x:Name="rbSelect" IsChecked="False"
                ToolTip="Select" Margin="3">
                <Path Stroke="Blue" Fill="LightBlue" Width="20" Height="20">
                    <Path.Data>
                        <PathGeometry Figures="M5,15L 10,0 15,15 12,15 12,20 8,20 8,15Z">
                            <PathGeometry.Transform>
                                <RotateTransform CenterX="10" CenterY="10" Angle="45"/>
                            </PathGeometry.Transform>
                        </PathGeometry>
                    </Path.Data>
                </Path>
            </RadioButton>
        </ToolBar>
    </ToolBarTray>
    <Border BorderThickness="1" BorderBrush="Black">
        <InkCanvas x:Name="canvas1" MouseMove="canvas1_MouseMove" PreviewMouseLeftButtonDown="canvas1_PreviewMouseLeftButtonDown" EditingMode="None">
        </InkCanvas>
    </Border>
</DockPanel>

Code behind

   private Polyline polyline;
    private PointCollection polylinePoints;
    private bool drawOnMove = false;
    private List<Polygon> polygons = new List<Polygon>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void canvas1_MouseMove(object sender, MouseEventArgs e)
    {
        if (drawOnMove && (bool)rbDraw.IsChecked)
        {
            polyline.Points = polylinePoints.Clone();
            polyline.Points.Add(e.GetPosition(canvas1));
        }
    }

    private void canvas1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (rbDraw.IsChecked ?? false)
        {
            if (e.OriginalSource is Ellipse)
            {
                canvas1.Children.Remove((Ellipse)e.OriginalSource);
                canvas1.Children.Remove(polyline);
                Polygon tmpPolygon = new Polygon();
                tmpPolygon.StrokeThickness = 2;
                tmpPolygon.Stroke = Brushes.Black;
                tmpPolygon.Points = polylinePoints.Clone();
                polylinePoints.Clear();

                polygons.Add(tmpPolygon);
                drawOnMove = false;
                rbDraw.IsChecked = false;
                tmpPolygon.Fill = Brushes.Gray;
                canvas1.Children.Add(tmpPolygon);
                rbSelect.IsChecked = true;

            }
            else
            {
                polylinePoints.Add(e.GetPosition(canvas1));
                polyline.Points = polylinePoints.Clone();

                if (polyline.Points.Count == 1)
                {
                    Ellipse el = new Ellipse();
                    el.Width = 10;
                    el.Height = 10;
                    el.Stroke = Brushes.Black;
                    el.StrokeThickness = 2;
                    el.Fill = new SolidColorBrush { Color = Colors.Yellow };
                    el.Margin =
                        new Thickness(left: polyline.Points[0].X - el.Width / 2, top: polyline.Points[0].Y - el.Height / 2, right: 0, bottom: 0);
                    canvas1.Children.Add(el);
                }

                drawOnMove = true;
            }
        }
        else if (rbSelect.IsChecked ?? false) 
        {
            if (e.OriginalSource is Polygon)
            {
                Polygon pol = (Polygon)e.OriginalSource;

                canvas1.Select(new UIElement[] { pol });
            }
        }
    }

    private void rbDraw_Checked(object sender, RoutedEventArgs e)
    {
        polyline = new Polyline();
        polylinePoints = new PointCollection();
        polyline.StrokeThickness = 2;
        polyline.Stroke = Brushes.Black;
        canvas1.Children.Add(polyline);
    }

Edit: I edited my code my first sample was a little too general. Selecting polygon looks like this but I want to select only polygon area.

Example


Solution

  • Ok I solved my problem I added a custom Dependency Property to my Window which holds selected polygon. To show that polygon is selected I change its opacity.

     public static readonly DependencyProperty SelectedShapeProperty =
           DependencyProperty.Register
           ("SelectedShape", typeof(Polygon), typeof(MainWindow));
    
        public Polygon Polygon 
        {
            set{SetValue(SelectedShapeProperty, value);}
            get{return (Polygon) GetValue(SelectedShapeProperty);}
        }
    
    
     private void canvas1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (rbDraw.IsChecked ?? false)
            {
                if (e.OriginalSource is Ellipse)
                {
                    canvas1.Children.Remove((Ellipse)e.OriginalSource);
                    canvas1.Children.Remove(polyline);
                    Polygon tmpPolygon = new Polygon();
                    tmpPolygon.StrokeThickness = 2;
                    tmpPolygon.Stroke = Brushes.Black;
                    tmpPolygon.Points = polylinePoints.Clone();
                    polylinePoints.Clear();
    
                    polygons.Add(tmpPolygon);
                    drawOnMove = false;
                    rbDraw.IsChecked = false;
                    tmpPolygon.Fill = Brushes.Gray;
                    canvas1.Children.Add(tmpPolygon);
                    rbSelect.IsChecked = true;
    
                }
                else
                {
                    polylinePoints.Add(e.GetPosition(canvas1));
                    polyline.Points = polylinePoints.Clone();
    
                    if (polyline.Points.Count == 1)
                    {
                        Ellipse el = new Ellipse();
                        el.Width = 10;
                        el.Height = 10;
                        el.Stroke = Brushes.Black;
                        el.StrokeThickness = 2;
                        el.Fill = new SolidColorBrush { Color = Colors.Yellow };
                        InkCanvas.SetLeft(el, polyline.Points[0].X - el.Width / 2);
                        InkCanvas.SetTop(el, polyline.Points[0].Y - el.Height / 2);
    
                        el.Margin =
                            new Thickness(left: polyline.Points[0].X - el.Width / 2, top: polyline.Points[0].Y - el.Height / 2, right: 0, bottom: 0);
                        canvas1.Children.Add(el);
                    }
    
                    drawOnMove = true;
                }
            }
            else if (rbSelect.IsChecked ?? false)
            {
                if (e.OriginalSource is Polygon && Polygon == null)
                {
                    Shape s = (Shape)e.OriginalSource;
                    Polygon = (Polygon)s;
                    Polygon.Opacity = 0.75;
                }
                else if (e.OriginalSource is Polygon && Polygon != null)
                {
                    Polygon.Opacity = 1;
                    Polygon = null;
                    Shape s = (Shape)e.OriginalSource;
                    Polygon = (Polygon)s;
                    Polygon.Opacity = 0.75;
                }
                else if (Polygon != null)
                {
                    Polygon.Opacity = 1;
                    Polygon = null;
                }
            }
            else
            {
                if(Polygon != null)
                    Polygon = null;
            }
        }