How to draw arc with radius and start and stop angle

前端 未结 2 1047
一生所求
一生所求 2020-12-01 11:14

If I have the following four properties in my DataContext of my Canvas element

Point  Center
double Radius
double StartAngle
double EndAngle
<
2条回答
  •  一个人的身影
    2020-12-01 11:41

    May I offer a slightly different solution?

    class ArcII:FrameworkElement
    {
        /// 
        /// Center point of Arc.
        /// 
        [Category("Arc")]
        public Point Center
        {
            get { return (Point)GetValue(CenterProperty); }
            set { SetValue(CenterProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for Center.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CenterProperty =
            DependencyProperty.Register("Center", typeof(Point), typeof(ArcII), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender));
    
        /// 
        /// Forces the Arc to the center of the Parent container.
        /// 
        [Category("Arc")]
        public bool OverrideCenter
        {
            get { return (bool)GetValue(OverrideCenterProperty); }
            set { SetValue(OverrideCenterProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for OverrideCenter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OverrideCenterProperty =
            DependencyProperty.Register("OverrideCenter", typeof(bool), typeof(ArcII), new FrameworkPropertyMetadata((bool)false, FrameworkPropertyMetadataOptions.AffectsRender));
    
        /// 
        /// Start angle of arc, using standard coordinates. (Zero is right, CCW positive direction)
        /// 
        [Category("Arc")]
        public double StartAngle
        {
            get { return (double)GetValue(StartAngleProperty); }
            set { SetValue(StartAngleProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for StartAngle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StartAngleProperty =
            DependencyProperty.Register("StartAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
    
        /// 
        /// Length of Arc in degrees.
        /// 
        [Category("Arc")]
        public double SweepAngle
        {
            get { return (double)GetValue(SweepAngleProperty); }
            set { SetValue(SweepAngleProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for SweepAngle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SweepAngleProperty =
            DependencyProperty.Register("SweepAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)180, FrameworkPropertyMetadataOptions.AffectsRender));
    
        /// 
        /// Size of Arc.
        /// 
        [Category("Arc")]
        public double Radius
        {
            get { return (double)GetValue(RadiusProperty); }
            set { SetValue(RadiusProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for Radius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RadiusProperty =
            DependencyProperty.Register("Radius", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
    
        [Category("Arc")]
        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for Stroke.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StrokeProperty =
            DependencyProperty.Register("Stroke", typeof(Brush), typeof(ArcII), new FrameworkPropertyMetadata((Brush)Brushes.Black,FrameworkPropertyMetadataOptions.AffectsRender));
    
        [Category("Arc")]
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for StrokeThickness.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StrokeThicknessProperty =
            DependencyProperty.Register("StrokeThickness", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)1,FrameworkPropertyMetadataOptions.AffectsRender));
    
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);
            Draw(dc);
        }
    
        private void Draw(DrawingContext dc)
        {
            Point center = new Point();
            if (OverrideCenter)
            {
                Rect rect = new Rect(RenderSize);
                center = Polar.CenterPointFromRect(rect);
            }
            else
            {
                center = Center;
            }
    
            Point startPoint = Polar.PolarToCartesian(StartAngle, Radius, center);
            Point endPoint = Polar.PolarToCartesian(StartAngle + SweepAngle, Radius, center);
            Size size = new Size(Radius, Radius);
    
            bool isLarge = (StartAngle + SweepAngle) - StartAngle > 180;
    
            List segments = new List(1);
            segments.Add(new ArcSegment(endPoint, new Size(Radius, Radius), 0.0, isLarge, SweepDirection.Clockwise, true));
    
            List figures = new List(1);
            PathFigure pf = new PathFigure(startPoint, segments, true);
            pf.IsClosed = false;
            figures.Add(pf);
            Geometry g = new PathGeometry(figures, FillRule.EvenOdd, null);
    
            dc.DrawGeometry(null, new Pen(Stroke,StrokeThickness), g);
        }
    }
    

    Usage:

        
        
    
        
        
    
        
        
    
        
        
    
        
        
    

    Notes: A) This will not do a 360 SweepAngle, for that use an ellipse. B) OverrideCenter: This puts the center of the Arc in the center of its parent. Note that elements like a Grid that can be partitioned, still have a center, which may not be the column or row the Arc is in.

提交回复
热议问题