Browse Source

Comment and standardize Sector with Arc

pull/8749/head
robloo 4 years ago
parent
commit
a96b317e46
  1. 36
      src/Avalonia.Controls/Shapes/Arc.cs
  2. 64
      src/Avalonia.Controls/Shapes/Sector.cs

36
src/Avalonia.Controls/Shapes/Arc.cs

@ -1,8 +1,12 @@
using System; using System;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Utilities;
namespace Avalonia.Controls.Shapes namespace Avalonia.Controls.Shapes
{ {
/// <summary>
/// Represents a circular or elliptical arc (a segment of a curve).
/// </summary>
public class Arc : Shape public class Arc : Shape
{ {
/// <summary> /// <summary>
@ -19,8 +23,12 @@ namespace Avalonia.Controls.Shapes
static Arc() static Arc()
{ {
StrokeThicknessProperty.OverrideDefaultValue<Arc>(1); StrokeThicknessProperty.OverrideDefaultValue<Arc>(1.0d);
AffectsGeometry<Arc>(BoundsProperty, StrokeThicknessProperty, StartAngleProperty, SweepAngleProperty); AffectsGeometry<Arc>(
BoundsProperty,
StrokeThicknessProperty,
StartAngleProperty,
SweepAngleProperty);
} }
/// <summary> /// <summary>
@ -42,10 +50,11 @@ namespace Avalonia.Controls.Shapes
set => SetValue(SweepAngleProperty, value); set => SetValue(SweepAngleProperty, value);
} }
/// <inheritdoc/>
protected override Geometry CreateDefiningGeometry() protected override Geometry CreateDefiningGeometry()
{ {
var angle1 = DegreesToRad(StartAngle); var angle1 = MathUtilities.Deg2Rad(StartAngle);
var angle2 = angle1 + DegreesToRad(SweepAngle); var angle2 = angle1 + MathUtilities.Deg2Rad(SweepAngle);
var startAngle = Math.Min(angle1, angle2); var startAngle = Math.Min(angle1, angle2);
var sweepAngle = Math.Max(angle1, angle2); var sweepAngle = Math.Max(angle1, angle2);
@ -80,24 +89,25 @@ namespace Avalonia.Controls.Shapes
var arcGeometry = new StreamGeometry(); var arcGeometry = new StreamGeometry();
using (var ctx = arcGeometry.Open()) using (StreamGeometryContext context = arcGeometry.Open())
{ {
ctx.BeginFigure(startPoint, false); context.BeginFigure(startPoint, false);
ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI, context.ArcTo(
endPoint,
new Size(radiusX, radiusY),
rotationAngle: angleGap,
isLargeArc: angleGap >= Math.PI,
SweepDirection.Clockwise); SweepDirection.Clockwise);
ctx.EndFigure(false); context.EndFigure(false);
} }
return arcGeometry; return arcGeometry;
} }
} }
static double DegreesToRad(double inAngle) => private static double RadToNormRad(double inAngle) => ((inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2);
inAngle * Math.PI / 180;
static double RadToNormRad(double inAngle) => ((inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2); private static Point GetRingPoint(double radiusX, double radiusY, double centerX, double centerY, double angle) =>
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); new Point((radiusX * Math.Cos(angle)) + centerX, (radiusY * Math.Sin(angle)) + centerY);
} }
} }

64
src/Avalonia.Controls/Shapes/Sector.cs

@ -4,45 +4,71 @@ using Avalonia.Utilities;
namespace Avalonia.Controls.Shapes namespace Avalonia.Controls.Shapes
{ {
/// <summary>
/// Represents a circular or elliptical sector (a pie-shaped closed region of a circle or ellipse).
/// </summary>
public class Sector : Shape public class Sector : Shape
{ {
public static readonly StyledProperty<double> StartAngleProperty = AvaloniaProperty.Register<Sector, double>(nameof(StartAngle), 0.0d); /// <summary>
public static readonly StyledProperty<double> AngleProperty = AvaloniaProperty.Register<Sector, double>(nameof(Angle), 0.0d); /// Defines the <see cref="StartAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> StartAngleProperty =
AvaloniaProperty.Register<Sector, double>(nameof(StartAngle), 0.0d);
/// <summary>
/// Defines the <see cref="SweepAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> SweepAngleProperty =
AvaloniaProperty.Register<Sector, double>(nameof(SweepAngle), 0.0d);
/// <summary>
/// Gets or sets the angle at which the sector's arc starts, in degrees.
/// </summary>
public double StartAngle public double StartAngle
{ {
get => GetValue(StartAngleProperty); get => GetValue(StartAngleProperty);
set => SetValue(StartAngleProperty, value); set => SetValue(StartAngleProperty, value);
} }
public double Angle /// <summary>
/// Gets or sets the angle, in degrees, added to the <see cref="StartAngle"/> defining where the sector's arc ends.
/// A positive value is clockwise, negative is counter-clockwise.
/// </summary>
public double SweepAngle
{ {
get => GetValue(AngleProperty); get => GetValue(SweepAngleProperty);
set => SetValue(AngleProperty, value); set => SetValue(SweepAngleProperty, value);
} }
static Sector() static Sector()
{ {
StrokeThicknessProperty.OverrideDefaultValue<Sector>(1.0d); StrokeThicknessProperty.OverrideDefaultValue<Sector>(1.0d);
AffectsGeometry<Sector>(BoundsProperty, StrokeThicknessProperty, StartAngleProperty, AngleProperty); AffectsGeometry<Sector>(
BoundsProperty,
StrokeThicknessProperty,
StartAngleProperty,
SweepAngleProperty);
} }
/// <inheritdoc/>
protected override Geometry? CreateDefiningGeometry() protected override Geometry? CreateDefiningGeometry()
{ {
Rect rect = new Rect(Bounds.Size); Rect rect = new Rect(Bounds.Size);
Rect deflatedRect = rect.Deflate(StrokeThickness * 0.5d); Rect deflatedRect = rect.Deflate(StrokeThickness * 0.5d);
if (Angle >= 360.0d || Angle <= -360.0d) if (SweepAngle >= 360.0d || SweepAngle <= -360.0d)
{ {
return new EllipseGeometry(deflatedRect); return new EllipseGeometry(deflatedRect);
} }
if (Angle == 0.0d) if (SweepAngle == 0.0d)
{ {
return new StreamGeometry(); return new StreamGeometry();
} }
(double startAngle, double endAngle) = MathUtilities.GetMinMaxFromDelta(MathUtilities.Deg2Rad(StartAngle), MathUtilities.Deg2Rad(Angle)); (double startAngle, double endAngle) = MathUtilities.GetMinMaxFromDelta(
MathUtilities.Deg2Rad(StartAngle),
MathUtilities.Deg2Rad(SweepAngle));
Point centre = new Point(rect.Width * 0.5d, rect.Height * 0.5d); Point centre = new Point(rect.Width * 0.5d, rect.Height * 0.5d);
double radiusX = deflatedRect.Width * 0.5d; double radiusX = deflatedRect.Width * 0.5d;
@ -51,13 +77,19 @@ namespace Avalonia.Controls.Shapes
Point endCurvePoint = MathUtilities.GetEllipsePoint(centre, radiusX, radiusY, endAngle); Point endCurvePoint = MathUtilities.GetEllipsePoint(centre, radiusX, radiusY, endAngle);
Size size = new Size(radiusX, radiusY); Size size = new Size(radiusX, radiusY);
StreamGeometry streamGeometry = new StreamGeometry(); var streamGeometry = new StreamGeometry();
using StreamGeometryContext streamGeometryContext = streamGeometry.Open(); using (StreamGeometryContext context = streamGeometry.Open())
{
streamGeometryContext.BeginFigure(startCurvePoint, false); context.BeginFigure(startCurvePoint, false);
streamGeometryContext.ArcTo(endCurvePoint, size, 0.0d, Math.Abs(Angle) > 180.0d, SweepDirection.Clockwise); context.ArcTo(
streamGeometryContext.LineTo(centre); endCurvePoint,
streamGeometryContext.EndFigure(true); size,
rotationAngle: 0.0d,
isLargeArc: Math.Abs(SweepAngle) > 180.0d,
SweepDirection.Clockwise);
context.LineTo(centre);
context.EndFigure(true);
}
return streamGeometry; return streamGeometry;
} }

Loading…
Cancel
Save