From fd34b52bba48e87c23c869c061964a8595584239 Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 16 Oct 2021 00:06:15 +0300 Subject: [PATCH 1/5] LineNode hit test --- .../Rendering/SceneGraph/LineNode.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs index 54a9ff733d..3d5de96bf6 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs +++ b/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(Math.Pow(bXaX, 2) + Math.Pow(bYaY, 2))); + + return Math.Abs(distance) <= Pen.Thickness/2; } } } From ee84eae5cfcebda0f8559e1ed41aacf9cc5c468c Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 16 Oct 2021 00:15:50 +0300 Subject: [PATCH 2/5] Spaces --- .../Rendering/SceneGraph/LineNode.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs index 3d5de96bf6..5d7df770aa 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs @@ -85,30 +85,30 @@ namespace Avalonia.Rendering.SceneGraph { 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; + 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; + + 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(Math.Pow(bXaX, 2) + Math.Pow(bYaY, 2))); - - return Math.Abs(distance) <= Pen.Thickness/2; + + return Math.Abs(distance) <= Pen.Thickness / 2; } } } From 22ff7af2ae1156ed32ebc981c232111feea88d5c Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 16 Oct 2021 03:37:13 +0300 Subject: [PATCH 3/5] replace Math.Pow(x, 2) on x*x --- src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs index 5d7df770aa..19b751f66c 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/LineNode.cs @@ -106,7 +106,7 @@ namespace Avalonia.Rendering.SceneGraph var bYaY = b.Y - a.Y; var distance = (bXaX * (p.Y - a.Y) - bYaY * (p.X - a.X)) / - (Math.Sqrt(Math.Pow(bXaX, 2) + Math.Pow(bYaY, 2))); + (Math.Sqrt(bXaX * bXaX + bYaY * bYaY)); return Math.Abs(distance) <= Pen.Thickness / 2; } From 721e088911c03490be9b54550521cbbe43d268b1 Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 16 Oct 2021 03:37:34 +0300 Subject: [PATCH 4/5] LineNode tests --- .../Rendering/SceneGraph/LineNodeTests.cs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs new file mode 100644 index 0000000000..f065e7def0 --- /dev/null +++ b/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)); + + + List pointsInside = new() + { + 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)); + + + List pointsOutside= new() + { + 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)); + } + } + } +} From ce21eee1554d7e31afff4c09e699af05a5fad577 Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 16 Oct 2021 03:45:25 +0300 Subject: [PATCH 5/5] replace target-typed object creation --- .../Rendering/SceneGraph/LineNodeTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs index f065e7def0..d4d4a29dfd 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/LineNodeTests.cs @@ -17,7 +17,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph new Point(150, 150)); - List pointsInside = new() + var pointsInside = new List() { new Point(14, 14), new Point(15, 15), @@ -43,7 +43,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph new Point(150, 150)); - List pointsOutside= new() + var pointsOutside= new List() { new Point(13.9, 13.9), new Point(30, 32.2),