From 82d2ee175f39f044b6cc7864899167eafb4712c9 Mon Sep 17 00:00:00 2001 From: Splitwirez Date: Sat, 19 Jun 2021 15:36:58 -0400 Subject: [PATCH 1/4] Add `Arc`...again... --- src/Avalonia.Controls/Shapes/Arc.cs | 99 +++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/Avalonia.Controls/Shapes/Arc.cs diff --git a/src/Avalonia.Controls/Shapes/Arc.cs b/src/Avalonia.Controls/Shapes/Arc.cs new file mode 100644 index 0000000000..f6738e10f2 --- /dev/null +++ b/src/Avalonia.Controls/Shapes/Arc.cs @@ -0,0 +1,99 @@ +using System; +using Avalonia.Media; + +namespace Avalonia.Controls.Shapes +{ + public class Arc : Shape + { + /// + /// Defines the property. + /// + public static readonly StyledProperty StartAngleProperty = + AvaloniaProperty.Register(nameof(StartAngle), 0.0); + + /// + /// Defines the property. + /// + public static readonly StyledProperty SweepAngleProperty = + AvaloniaProperty.Register(nameof(SweepAngle), 0.0); + + static Arc() + { + StrokeThicknessProperty.OverrideDefaultValue(1); + AffectsGeometry(BoundsProperty, StrokeThicknessProperty, StartAngleProperty, SweepAngleProperty); + } + + /// + /// Gets or sets the angle at which the arc starts, in degrees. + /// + public double StartAngle + { + get { return GetValue(StartAngleProperty); } + set { SetValue(StartAngleProperty, value); } + } + + /// + /// Gets or sets the angle at which the arc ends relative to the start angle, in degrees. + /// + public double SweepAngle + { + get { return GetValue(SweepAngleProperty); } + set { SetValue(SweepAngleProperty, value); } + } + + protected override Geometry CreateDefiningGeometry() + { + double angle1 = DegreesToRad(StartAngle); + double angle2 = angle1 + DegreesToRad(SweepAngle); + + double startAngle = Math.Min(angle1, angle2); + double sweepAngle = Math.Max(angle1, angle2); + + double normStart = RadToNormRad(startAngle); + double normEnd = RadToNormRad(sweepAngle); + + var rect = new Rect(Bounds.Size); + + if ((normStart == normEnd) && (startAngle != sweepAngle)) //complete ring + { + return new EllipseGeometry(rect.Deflate(StrokeThickness / 2)); + } + else if (SweepAngle == 0) + { + return new StreamGeometry(); + } + else //partial arc + { + var deflatedRect = rect.Deflate(StrokeThickness / 2); + + double centerX = rect.Center.X; + double centerY = rect.Center.Y; + + double radiusX = deflatedRect.Width / 2; + double radiusY = deflatedRect.Height / 2; + + double angleGap = RadToNormRad(sweepAngle - startAngle); + + Point startPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, startAngle); + Point endPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, sweepAngle); + + StreamGeometry arcGeometry = new StreamGeometry(); + using (var ctx = arcGeometry.Open()) + { + ctx.BeginFigure(startPoint, false); + ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI, SweepDirection.Clockwise); + ctx.EndFigure(false); + } + return arcGeometry; + } + } + + static double DegreesToRad(double inAngle) => + inAngle * Math.PI / 180; + + static double RadToNormRad(double inAngle) => (0 + (inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); + + static Point GetRingPoint(double radiusX, double radiusY, double centerX, double centerY, double angle) => + new Point((radiusX * Math.Cos(angle)) + centerX, (radiusY * Math.Sin(angle)) + centerY); + } +} From 6e99f1240634c36bc164a87399333af03b513ba9 Mon Sep 17 00:00:00 2001 From: Splitwirez Date: Sat, 3 Jul 2021 11:17:19 -0400 Subject: [PATCH 2/4] Fix comments --- src/Avalonia.Controls/Shapes/Arc.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Shapes/Arc.cs b/src/Avalonia.Controls/Shapes/Arc.cs index f6738e10f2..4ce72319aa 100644 --- a/src/Avalonia.Controls/Shapes/Arc.cs +++ b/src/Avalonia.Controls/Shapes/Arc.cs @@ -33,7 +33,7 @@ namespace Avalonia.Controls.Shapes } /// - /// Gets or sets the angle at which the arc ends relative to the start angle, in degrees. + /// Gets or sets the angle, in degrees, added to the defining where the arc ends. A positive value is clockwise, negative is counter-clockwise. /// public double SweepAngle { @@ -54,7 +54,7 @@ namespace Avalonia.Controls.Shapes var rect = new Rect(Bounds.Size); - if ((normStart == normEnd) && (startAngle != sweepAngle)) //complete ring + if ((normStart == normEnd) && (startAngle != sweepAngle)) // complete ring { return new EllipseGeometry(rect.Deflate(StrokeThickness / 2)); } @@ -62,7 +62,7 @@ namespace Avalonia.Controls.Shapes { return new StreamGeometry(); } - else //partial arc + else // partial arc { var deflatedRect = rect.Deflate(StrokeThickness / 2); From f5ded2632133803632116efad9e5465f4811fee8 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 8 Jul 2021 13:07:59 +0800 Subject: [PATCH 3/4] Update Arc.cs --- src/Avalonia.Controls/Shapes/Arc.cs | 47 +++++++++++++++-------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/Avalonia.Controls/Shapes/Arc.cs b/src/Avalonia.Controls/Shapes/Arc.cs index 4ce72319aa..dad47875c3 100644 --- a/src/Avalonia.Controls/Shapes/Arc.cs +++ b/src/Avalonia.Controls/Shapes/Arc.cs @@ -28,33 +28,34 @@ namespace Avalonia.Controls.Shapes /// public double StartAngle { - get { return GetValue(StartAngleProperty); } - set { SetValue(StartAngleProperty, value); } + get => GetValue(StartAngleProperty); + set => SetValue(StartAngleProperty, value); } /// - /// Gets or sets the angle, in degrees, added to the defining where the arc ends. A positive value is clockwise, negative is counter-clockwise. + /// Gets or sets the angle, in degrees, added to the defining where the arc ends. + /// A positive value is clockwise, negative is counter-clockwise. /// public double SweepAngle { - get { return GetValue(SweepAngleProperty); } - set { SetValue(SweepAngleProperty, value); } + get => GetValue(SweepAngleProperty); + set => SetValue(SweepAngleProperty, value); } protected override Geometry CreateDefiningGeometry() { - double angle1 = DegreesToRad(StartAngle); - double angle2 = angle1 + DegreesToRad(SweepAngle); + var angle1 = DegreesToRad(StartAngle); + var angle2 = angle1 + DegreesToRad(SweepAngle); - double startAngle = Math.Min(angle1, angle2); - double sweepAngle = Math.Max(angle1, angle2); + var startAngle = Math.Min(angle1, angle2); + var sweepAngle = Math.Max(angle1, angle2); - double normStart = RadToNormRad(startAngle); - double normEnd = RadToNormRad(sweepAngle); + var normStart = RadToNormRad(startAngle); + var normEnd = RadToNormRad(sweepAngle); var rect = new Rect(Bounds.Size); - if ((normStart == normEnd) && (startAngle != sweepAngle)) // complete ring + if ((normStart == normEnd) && (startAngle != sweepAngle)) // Complete ring. { return new EllipseGeometry(rect.Deflate(StrokeThickness / 2)); } @@ -62,28 +63,30 @@ namespace Avalonia.Controls.Shapes { return new StreamGeometry(); } - else // partial arc + else // Partial arc. { var deflatedRect = rect.Deflate(StrokeThickness / 2); - double centerX = rect.Center.X; - double centerY = rect.Center.Y; + var centerX = rect.Center.X; + var centerY = rect.Center.Y; - double radiusX = deflatedRect.Width / 2; - double radiusY = deflatedRect.Height / 2; + var radiusX = deflatedRect.Width / 2; + var radiusY = deflatedRect.Height / 2; - double angleGap = RadToNormRad(sweepAngle - startAngle); + var angleGap = RadToNormRad(sweepAngle - startAngle); - Point startPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, startAngle); - Point endPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, sweepAngle); + var startPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, startAngle); + var endPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, sweepAngle); - StreamGeometry arcGeometry = new StreamGeometry(); + var arcGeometry = new StreamGeometry(); + using (var ctx = arcGeometry.Open()) { ctx.BeginFigure(startPoint, false); ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI, SweepDirection.Clockwise); ctx.EndFigure(false); } + return arcGeometry; } } @@ -91,7 +94,7 @@ namespace Avalonia.Controls.Shapes static double DegreesToRad(double inAngle) => inAngle * Math.PI / 180; - static double RadToNormRad(double inAngle) => (0 + (inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); + static double RadToNormRad(double inAngle) => (inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); static Point GetRingPoint(double radiusX, double radiusY, double centerX, double centerY, double angle) => new Point((radiusX * Math.Cos(angle)) + centerX, (radiusY * Math.Sin(angle)) + centerY); From 3740c9d9733693e118454aca541c671bce110a85 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:33:18 +0800 Subject: [PATCH 4/4] Update Arc.cs --- src/Avalonia.Controls/Shapes/Arc.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/Shapes/Arc.cs b/src/Avalonia.Controls/Shapes/Arc.cs index dad47875c3..5ebb321f9b 100644 --- a/src/Avalonia.Controls/Shapes/Arc.cs +++ b/src/Avalonia.Controls/Shapes/Arc.cs @@ -41,12 +41,12 @@ namespace Avalonia.Controls.Shapes get => GetValue(SweepAngleProperty); set => SetValue(SweepAngleProperty, value); } - + protected override Geometry CreateDefiningGeometry() { var angle1 = DegreesToRad(StartAngle); var angle2 = angle1 + DegreesToRad(SweepAngle); - + var startAngle = Math.Min(angle1, angle2); var sweepAngle = Math.Max(angle1, angle2); @@ -72,29 +72,30 @@ namespace Avalonia.Controls.Shapes var radiusX = deflatedRect.Width / 2; var radiusY = deflatedRect.Height / 2; - + var angleGap = RadToNormRad(sweepAngle - startAngle); var startPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, startAngle); var endPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, sweepAngle); var arcGeometry = new StreamGeometry(); - + using (var ctx = arcGeometry.Open()) { ctx.BeginFigure(startPoint, false); - ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI, SweepDirection.Clockwise); + ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI, + SweepDirection.Clockwise); ctx.EndFigure(false); } - + return arcGeometry; } } static double DegreesToRad(double inAngle) => inAngle * Math.PI / 180; - - static double RadToNormRad(double inAngle) => (inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); + + static double RadToNormRad(double inAngle) => ((inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); static Point GetRingPoint(double radiusX, double radiusY, double centerX, double centerY, double angle) => new Point((radiusX * Math.Cos(angle)) + centerX, (radiusY * Math.Sin(angle)) + centerY);