Browse Source

move to static LineBoundsHelper class.

pull/3909/head
Dan Walmsley 6 years ago
parent
commit
0808e2810e
  1. 75
      samples/ControlCatalog/MainWindow.xaml.cs
  2. 72
      src/Avalonia.Visuals/Rendering/SceneGraph/LineBoundsHelper.cs
  3. 72
      src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs

75
samples/ControlCatalog/MainWindow.xaml.cs

@ -3,6 +3,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Threading;
namespace ControlCatalog
@ -20,95 +21,31 @@ namespace ControlCatalog
t.Tick += (sender, e) =>
{
angle += 1;
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
};
t.Start();
}
const double degreeToRadians = Math.PI / 180.0;
private static double CalculateAngle(Point p1, Point p2)
{
var xDiff = p2.X - p1.X;
var yDiff = p2.Y - p1.Y;
return Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI;
}
private static double CalculateOppSide(double angle, double hyp)
{
return Math.Sin(angle * degreeToRadians) * hyp;
}
private static double CalculateAdjSide(double angle, double hyp)
{
return Math.Cos(angle * degreeToRadians) * hyp;
}
static Rect CalculateBounds(Point p1, Point p2, double thickness, double angleToCorner)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner + 90, thickness / 2);
return new Rect(pts.p1, pts.p2);
}
static (Point p1, Point p2) TranslatePointsAlongTangent(Point p1, Point p2, double angle, double distance)
{
var xDiff = CalculateOppSide(angle, distance);
var yDiff = CalculateAdjSide(angle, distance);
var c1 = new Point(p1.X + xDiff, p1.Y - yDiff);
var c2 = new Point(p1.X - xDiff, p1.Y + yDiff);
var c3 = new Point(p2.X + xDiff, p2.Y - yDiff);
var c4 = new Point(p2.X - xDiff, p2.Y + yDiff);
var minX = Math.Min(c1.X, Math.Min(c2.X, Math.Min(c3.X, c4.X)));
var minY = Math.Min(c1.Y, Math.Min(c2.Y, Math.Min(c3.Y, c4.Y)));
var maxX = Math.Max(c1.X, Math.Max(c2.X, Math.Max(c3.X, c4.X)));
var maxY = Math.Max(c1.Y, Math.Max(c2.Y, Math.Max(c3.Y, c4.Y)));
return (new Point(minX, minY), new Point(maxX, maxY));
}
static Rect CalculateBounds (Point p1, Point p2, Pen p)
{
var angle = CalculateAngle(p1, p2);
var angleToCorner = 90 - angle;
if (p.LineCap != PenLineCap.Flat)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner, p.Thickness / 2);
return CalculateBounds(pts.p1, pts.p2, p.Thickness, angleToCorner);
}
else
{
return CalculateBounds(p1, p2, p.Thickness, angleToCorner);
}
}
public override void Render(DrawingContext drawingContext)
{
var lineLength = Math.Sqrt((100 * 100) + (100 * 100));
var diffX = CalculateAdjSide(angle, lineLength);
var diffY = CalculateOppSide(angle, lineLength);
var diffX = LineBoundsHelper.CalculateAdjSide(angle, lineLength);
var diffY = LineBoundsHelper.CalculateOppSide(angle, lineLength);
var p1 = new Point(400, 400);
var p2 = new Point(p1.X + diffX, p1.Y + diffY);
var pen = new Pen(Brushes.Green, 20, lineCap: PenLineCap.Round);
var pen = new Pen(Brushes.Green, 20, lineCap: PenLineCap.Square);
var boundPen = new Pen(Brushes.Black);
drawingContext.DrawLine(pen, p1, p2);
drawingContext.DrawRectangle(boundPen, CalculateBounds(p1, p2, pen));
drawingContext.DrawRectangle(boundPen, LineBoundsHelper.CalculateBounds(p1, p2, pen));
//Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
}

72
src/Avalonia.Visuals/Rendering/SceneGraph/LineBoundsHelper.cs

@ -0,0 +1,72 @@
using System;
using Avalonia.Media;
namespace Avalonia.Rendering.SceneGraph
{
public static class LineBoundsHelper
{
private const double degreeToRadians = Math.PI / 180.0;
private static double CalculateAngle(Point p1, Point p2)
{
var xDiff = p2.X - p1.X;
var yDiff = p2.Y - p1.Y;
return Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI;
}
public static double CalculateOppSide(double angle, double hyp)
{
return Math.Sin(angle * degreeToRadians) * hyp;
}
public static double CalculateAdjSide(double angle, double hyp)
{
return Math.Cos(angle * degreeToRadians) * hyp;
}
private static (Point p1, Point p2) TranslatePointsAlongTangent(Point p1, Point p2, double angle, double distance)
{
var xDiff = CalculateAdjSide(angle, distance);
var yDiff = CalculateOppSide(angle, distance);
var c1 = new Point(p1.X + xDiff, p1.Y - yDiff);
var c2 = new Point(p1.X - xDiff, p1.Y + yDiff);
var c3 = new Point(p2.X + xDiff, p2.Y - yDiff);
var c4 = new Point(p2.X - xDiff, p2.Y + yDiff);
var minX = Math.Min(c1.X, Math.Min(c2.X, Math.Min(c3.X, c4.X)));
var minY = Math.Min(c1.Y, Math.Min(c2.Y, Math.Min(c3.Y, c4.Y)));
var maxX = Math.Max(c1.X, Math.Max(c2.X, Math.Max(c3.X, c4.X)));
var maxY = Math.Max(c1.Y, Math.Max(c2.Y, Math.Max(c3.Y, c4.Y)));
return (new Point(minX, minY), new Point(maxX, maxY));
}
private static Rect CalculateBounds(Point p1, Point p2, double thickness, double angleToCorner)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner, thickness / 2);
return new Rect(pts.p1, pts.p2);
}
public static Rect CalculateBounds(Point p1, Point p2, IPen p)
{
var angle = CalculateAngle(p1, p2);
var angleToCorner = 90 - angle;
if (p.LineCap != PenLineCap.Flat)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner - 90, p.Thickness / 2);
return CalculateBounds(pts.p1, pts.p2, p.Thickness, angleToCorner);
}
else
{
return CalculateBounds(p1, p2, p.Thickness, angleToCorner);
}
}
}
}

72
src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
@ -7,78 +6,11 @@ using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph
{
/// <summary>
/// A node in the scene graph which represents a line draw.
/// </summary>
internal class LineNode : BrushDrawOperation
{
const double degreeToRadians = Math.PI / 180.0;
private static double CalculateAngle(Point p1, Point p2)
{
var xDiff = p2.X - p1.X;
var yDiff = p2.Y - p1.Y;
return Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI;
}
private static double CalculateOppSide(double angle, double hyp)
{
return Math.Sin(angle * degreeToRadians) * hyp;
}
private static double CalculateAdjSide(double angle, double hyp)
{
return Math.Cos(angle * degreeToRadians) * hyp;
}
static Rect CalculateBounds(Point p1, Point p2, double thickness, double angleToCorner)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner + 90, thickness / 2);
return new Rect(pts.p1, pts.p2);
}
static (Point p1, Point p2) TranslatePointsAlongTangent(Point p1, Point p2, double angle, double distance)
{
var xDiff = CalculateOppSide(angle, distance);
var yDiff = CalculateAdjSide(angle, distance);
var c1 = new Point(p1.X + xDiff, p1.Y - yDiff);
var c2 = new Point(p1.X - xDiff, p1.Y + yDiff);
var c3 = new Point(p2.X + xDiff, p2.Y - yDiff);
var c4 = new Point(p2.X - xDiff, p2.Y + yDiff);
var minX = Math.Min(c1.X, Math.Min(c2.X, Math.Min(c3.X, c4.X)));
var minY = Math.Min(c1.Y, Math.Min(c2.Y, Math.Min(c3.Y, c4.Y)));
var maxX = Math.Max(c1.X, Math.Max(c2.X, Math.Max(c3.X, c4.X)));
var maxY = Math.Max(c1.Y, Math.Max(c2.Y, Math.Max(c3.Y, c4.Y)));
return (new Point(minX, minY), new Point(maxX, maxY));
}
static Rect CalculateBounds(Point p1, Point p2, IPen p)
{
var angle = CalculateAngle(p1, p2);
var angleToCorner = 90 - angle;
if (p.LineCap != PenLineCap.Flat)
{
var pts = TranslatePointsAlongTangent(p1, p2, angleToCorner, p.Thickness / 2);
return CalculateBounds(pts.p1, pts.p2, p.Thickness, angleToCorner);
}
else
{
return CalculateBounds(p1, p2, p.Thickness, angleToCorner);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="GeometryNode"/> class.
/// </summary>
@ -93,7 +25,7 @@ namespace Avalonia.Rendering.SceneGraph
Point p1,
Point p2,
IDictionary<IVisual, Scene> childScenes = null)
: base(CalculateBounds(p1, p2, pen), transform, pen)
: base(LineBoundsHelper.CalculateBounds(p1, p2, pen), transform, pen)
{
Transform = transform;
Pen = pen?.ToImmutable();

Loading…
Cancel
Save