Question

I have an ellipse geometry. I want to show the radius of the ellipse by a line drawn from the center to the edge of the circle using C#. How can I achieve this?

Note: The center of the ellipse and the radius are not fixed and are defined by the user.

enter image description here

Was it helpful?

Solution

Suppose you have an ellipse with known center and radius:

        Path path = new Path();
        EllipseGeometry eg = new EllipseGeometry();
        eg.Center = new Point(left + side / 2, top + side / 2);
        eg.RadiusX = side / 2;
        eg.RadiusY = side / 2;
        path.Data = eg;
        paths.Add(path);
        canvas1.Children.Add(paths[paths.Count - 1]);
        .
        .
        path = new Path();
        borderColor.Color = Colors.Red;
        path.Stroke = borderColor;
        path.StrokeThickness = 2;
        LineGeometry r = new LineGeometry();
        r.StartPoint = eg.Center;
        r.EndPoint = new Point(eg.Center.X + eg.RadiusX, eg.Center.Y);
        path.Data = r;
        paths.Add(path);
        canvas1.Children.Add(paths[paths.Count - 1]);

enter image description here

OTHER TIPS

There's many different ways of doing this. Here is one, that may or may not meet your needs. It's just a user control. The radius of the circle is dependent on the size of the user control, and it will force the control to be uniform in size. Positioning the user control will be up to you. The angle of the inner line is bind-able.

User control xaml

<UserControl x:Class="TestWPF.CircleTest"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Foreground="Blue" Background="White"
             x:Name="CT" SnapsToDevicePixels="True">
    <Grid>
        <Ellipse Stroke="{Binding Foreground, ElementName=CT}" Fill="{Binding Background, ElementName=CT}" />
        <Line X1="{Binding Center.X, ElementName=CT}" X2="{Binding EndPoint.X, ElementName=CT}" Y1="{Binding Center.Y, ElementName=CT}" Y2="{Binding EndPoint.Y, ElementName=CT}" 
              Stroke="{Binding Foreground, ElementName=CT}">
            <Line.RenderTransform>
                <RotateTransform Angle="{Binding Angle, ElementName=CT}" CenterX="{Binding Center.X, ElementName=CT}" CenterY="{Binding Center.Y, ElementName=CT}" /> 
            </Line.RenderTransform>  
        </Line>
        <TextBlock Text="{Binding Angle, ElementName=CT, StringFormat='N2'}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="3" />
    </Grid>
</UserControl>

User control code behind

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace TestWPF
{
    public partial class CircleTest : UserControl, INotifyPropertyChanged
    {
        public CircleTest()
        {
            InitializeComponent();

            this.SizeChanged += CircleTest_SizeChanged;
        }

        void CircleTest_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            double radius;
            if (ActualHeight < ActualWidth)
            {
                Width = ActualHeight;
                _center = new Point(Width / 2, ActualHeight / 2);
                radius = ActualHeight / 2;
            }
            else
            {
                Height = ActualWidth;
                _center = new Point(ActualWidth / 2, Height / 2);
                radius = ActualWidth / 2;
            }

            _endPoint = new Point(Center.X, Center.Y - radius);

            NotifyOfPropertyChange("Center");
            NotifyOfPropertyChange("EndPoint");
        }

        public double Angle
        {
            get { return (double)GetValue(AngleProperty); }
            set { SetValue(AngleProperty, value); }
        }
        public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(CircleTest), new PropertyMetadata(45.0));

        private Point _center;
        public Point Center
        {
            get { return _center; }
        }

        private Point _endPoint;
        public Point EndPoint
        {
            get { return _endPoint; }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyOfPropertyChange(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

You'd use it like this:

<Window x:Class="TestWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:test="clr-namespace:TestWPF"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <test:CircleTest Width="200" Height="200" Foreground="Purple" Angle="{Binding Value, ElementName=SL}" />
        <Slider x:Name="SL" Minimum="0" Maximum="360" VerticalAlignment="Bottom" Margin="20" />
    </Grid>
</Window>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top