Browse Source

Merge pull request #6747 from RomanSoloweow/master

LineNode hit test optimization
pull/6755/head
Dan Walmsley 5 years ago
committed by GitHub
parent
commit
48e26a2883
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  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