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

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

@ -4,45 +4,71 @@ using Avalonia.Utilities;
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 static readonly StyledProperty<double> StartAngleProperty = AvaloniaProperty.Register<Sector, double>(nameof(StartAngle), 0.0d);
public static readonly StyledProperty<double> AngleProperty = AvaloniaProperty.Register<Sector, double>(nameof(Angle), 0.0d);
/// <summary>
/// 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
{
get => GetValue(StartAngleProperty);
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);
set => SetValue(AngleProperty, value);
get => GetValue(SweepAngleProperty);
set => SetValue(SweepAngleProperty, value);
}
static Sector()
{
StrokeThicknessProperty.OverrideDefaultValue<Sector>(1.0d);
AffectsGeometry<Sector>(BoundsProperty, StrokeThicknessProperty, StartAngleProperty, AngleProperty);
AffectsGeometry<Sector>(
BoundsProperty,
StrokeThicknessProperty,
StartAngleProperty,
SweepAngleProperty);
}
/// <inheritdoc/>
protected override Geometry? CreateDefiningGeometry()
{
Rect rect = new Rect(Bounds.Size);
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);
}
if (Angle == 0.0d)
if (SweepAngle == 0.0d)
{
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);
double radiusX = deflatedRect.Width * 0.5d;
@ -51,13 +77,19 @@ namespace Avalonia.Controls.Shapes
Point endCurvePoint = MathUtilities.GetEllipsePoint(centre, radiusX, radiusY, endAngle);
Size size = new Size(radiusX, radiusY);
StreamGeometry streamGeometry = new StreamGeometry();
using StreamGeometryContext streamGeometryContext = streamGeometry.Open();
streamGeometryContext.BeginFigure(startCurvePoint, false);
streamGeometryContext.ArcTo(endCurvePoint, size, 0.0d, Math.Abs(Angle) > 180.0d, SweepDirection.Clockwise);
streamGeometryContext.LineTo(centre);
streamGeometryContext.EndFigure(true);
var streamGeometry = new StreamGeometry();
using (StreamGeometryContext context = streamGeometry.Open())
{
context.BeginFigure(startCurvePoint, false);
context.ArcTo(
endCurvePoint,
size,
rotationAngle: 0.0d,
isLargeArc: Math.Abs(SweepAngle) > 180.0d,
SweepDirection.Clockwise);
context.LineTo(centre);
context.EndFigure(true);
}
return streamGeometry;
}

Loading…
Cancel
Save