Browse Source

Merge pull request #6747 from RomanSoloweow/master

LineNode hit test optimization
release/0.10.9
Dan Walmsley 5 years ago
parent
commit
f1b0d18674
  1. 18
      src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs
  2. 45
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs

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

@ -83,6 +83,20 @@ namespace Avalonia.Rendering.SceneGraph
public override bool HitTest(Point p)
{
if (!Transform.HasInverse)
return false;
p *= Transform.Invert();
var halfThickness = Pen.Thickness / 2;
var minX = Math.Min(P1.X, P2.X) - halfThickness;
var maxX = Math.Max(P1.X, P2.X) + halfThickness;
var minY = Math.Min(P1.Y, P2.Y) - halfThickness;
var maxY = Math.Max(P1.Y, P2.Y) + halfThickness;
if (p.X < minX || p.X > maxX || p.Y < minY || p.Y > maxY)
return false;
var a = P1;
var b = P2;
@ -100,7 +114,7 @@ namespace Avalonia.Rendering.SceneGraph
var dot2 = Vector.Dot(a - b, bp);
if (dot2 < 0)
return bp.Length <= Pen.Thickness / 2;
return bp.Length <= halfThickness;
var bXaX = b.X - a.X;
var bYaY = b.Y - a.Y;
@ -108,7 +122,7 @@ namespace Avalonia.Rendering.SceneGraph
var distance = (bXaX * (p.Y - a.Y) - bYaY * (p.X - a.X)) /
(Math.Sqrt(bXaX * bXaX + bYaY * bYaY));
return Math.Abs(distance) <= Pen.Thickness / 2;
return Math.Abs(distance) <= halfThickness;
}
}
}

45
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs

@ -11,50 +11,49 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void HitTest_Should_Be_True()
{
var lineNode = new LineNode(
Matrix.Identity,
Matrix.Identity,
new Pen(Brushes.Black, 3),
new Point(15, 15),
new Point(150, 150));
new Point(15, 10),
new Point(150, 73));
var pointsInside = new List<Point>()
{
new Point(14, 14),
new Point(15, 15),
new Point(32.1, 30),
new Point(30, 32.1),
new Point(150, 150),
new Point(151, 151),
new Point(14, 8.9),
new Point(15, 10),
new Point(30, 15.5),
new Point(30, 18.5),
new Point(150, 73),
new Point(151, 71.9),
};
foreach (var point in pointsInside)
{
Assert.True(lineNode.HitTest(point));
Assert.True(lineNode.HitTest(point));
}
}
[Fact]
public void HitTest_Should_Be_False()
{
var lineNode = new LineNode(
Matrix.Identity,
Matrix.Identity,
new Pen(Brushes.Black, 3),
new Point(15, 15),
new Point(150, 150));
new Point(15, 10),
new Point(150, 73));
var pointsOutside= new List<Point>()
var pointsOutside = new List<Point>()
{
new Point(13.9, 13.9),
new Point(30, 32.2),
new Point(32.2, 30),
new Point(151.1, 151.1),
new Point(200, 200),
new Point(14, 8),
new Point(14, 8.8),
new Point(30, 15.3),
new Point(30, 18.7),
new Point(151, 71.8),
new Point(155, 75),
};
foreach (var point in pointsOutside)
{
Assert.False(lineNode.HitTest(point));
Assert.False(lineNode.HitTest(point));
}
}
}

Loading…
Cancel
Save