Browse Source

Merge pull request #6746 from RomanSoloweow/master

LineNode hit test
release/0.10.9
Max Katz 4 years ago
committed by Dan Walmsley
parent
commit
4bb99fd73b
  1. 31
      src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs
  2. 61
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs

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

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
@ -82,8 +83,32 @@ namespace Avalonia.Rendering.SceneGraph
public override bool HitTest(Point p)
{
// TODO: Implement line hit testing.
return false;
var a = P1;
var b = P2;
//If dot1 or dot2 is negative, then the angle between the perpendicular and the segment is obtuse.
//The distance from a point to a straight line is defined as the
//length of the vector formed by the point and the closest point of the segment
Vector ap = p - a;
var dot1 = Vector.Dot(b - a, ap);
if (dot1 < 0)
return ap.Length <= Pen.Thickness / 2;
Vector bp = p - b;
var dot2 = Vector.Dot(a - b, bp);
if (dot2 < 0)
return bp.Length <= Pen.Thickness / 2;
var bXaX = b.X - a.X;
var bYaY = b.Y - a.Y;
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;
}
}
}

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

@ -0,0 +1,61 @@
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Rendering.SceneGraph;
using Xunit;
namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
{
public class LineNodeTests
{
[Fact]
public void HitTest_Should_Be_True()
{
var lineNode = new LineNode(
Matrix.Identity,
new Pen(Brushes.Black, 3),
new Point(15, 15),
new Point(150, 150));
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),
};
foreach (var point in pointsInside)
{
Assert.True(lineNode.HitTest(point));
}
}
[Fact]
public void HitTest_Should_Be_False()
{
var lineNode = new LineNode(
Matrix.Identity,
new Pen(Brushes.Black, 3),
new Point(15, 15),
new Point(150, 150));
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),
};
foreach (var point in pointsOutside)
{
Assert.False(lineNode.HitTest(point));
}
}
}
}
Loading…
Cancel
Save