Skip to content

Commit 0a2521d

Browse files
committed
Feat: Line2D.DistanceTo(point)
1 parent 8cae855 commit 0a2521d

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

src/Spatial.Tests/Euclidean/Line2DTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,30 @@ public void ToStringCheck()
210210

211211
Assert.AreEqual("StartPoint: (0,\u00A00), EndPoint: (1,\u00A01)", check);
212212
}
213+
214+
[TestCase("0,0", "1,0", "0,1",-1)]
215+
[TestCase("0,0", "1,0", "0,2", -2)]
216+
[TestCase("0,0", "0,1", "2,0", +2)]
217+
public void SignedDistanceTo(string sp1, string sp2, string sp, double expectedDistance)
218+
{
219+
var line = Line2D.Parse(sp1, sp2);
220+
var point = Point2D.Parse(sp);
221+
222+
var actual = line.SignedDistanceTo(point);
223+
Assert.That(actual, Is.EqualTo(expectedDistance));
224+
}
225+
226+
227+
[TestCase("0,0", "1,0", "0,1", 1)]
228+
[TestCase("0,0", "1,0", "0,2", 2)]
229+
[TestCase("0,0", "0,1", "2,0", 2)]
230+
public void DistanceTo(string sp1, string sp2, string sp, double expectedDistance)
231+
{
232+
var line = Line2D.Parse(sp1, sp2);
233+
var point = Point2D.Parse(sp);
234+
235+
var actual = line.DistanceTo(point);
236+
Assert.That(actual, Is.EqualTo(expectedDistance));
237+
}
213238
}
214239
}

src/Spatial/Euclidean/Line2D.cs

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
using System;
2-
using System.Diagnostics.Contracts;
3-
using System.Xml.Schema;
4-
using System.Xml;
5-
using System.Xml.Serialization;
6-
using MathNet.Numerics;
1+
using MathNet.Numerics;
72
using MathNet.Spatial.Internals;
83
using MathNet.Spatial.Units;
4+
using System;
5+
using System.Diagnostics.Contracts;
6+
using System.Xml;
97
using System.Xml.Linq;
8+
using System.Xml.Schema;
9+
using System.Xml.Serialization;
1010

1111
namespace MathNet.Spatial.Euclidean
1212
{
@@ -27,6 +27,21 @@ public struct Line2D : IEquatable<Line2D>, IXmlSerializable
2727
/// </summary>
2828
public Point2D EndPoint { get; private set; }
2929

30+
/// <summary>
31+
/// The parameter `a` in the line equation: ax + by + c = 0
32+
/// </summary>
33+
public double A { get; private set; }
34+
35+
/// <summary>
36+
/// The parameter `b` in the line equation: ax + by + c = 0
37+
/// </summary>
38+
public double B { get; private set; }
39+
40+
/// <summary>
41+
/// The parameter `c` in the line equation: ax + by + c = 0
42+
/// </summary>
43+
public double C { get; private set; }
44+
3045
/// <summary>
3146
/// Initializes a new instance of the <see cref="Line2D"/> struct.
3247
/// Throws an ArgumentException if the <paramref name="startPoint"/> is equal to the <paramref name="endPoint"/>.
@@ -40,8 +55,27 @@ public Line2D(Point2D startPoint, Point2D endPoint)
4055
throw new ArgumentException("The Line2D starting and ending points cannot be identical");
4156
}
4257

58+
//substitution
59+
//points
4360
StartPoint = startPoint;
4461
EndPoint = endPoint;
62+
63+
//doubles
64+
var x1 = startPoint.X;
65+
var x2 = endPoint.X;
66+
var y1 = startPoint.Y;
67+
var y2 = endPoint.Y;
68+
69+
//computation
70+
var a = y2 - y1;
71+
var b = x1 - x2;
72+
var c = (x2 - x1) * y1 - (y2 - y1) * x1;
73+
74+
//normalize
75+
var length = Math.Sqrt(a * a + b * b);
76+
A = a / length;
77+
B = b / length;
78+
C = c / length;
4579
}
4680

4781
/// <summary>
@@ -294,5 +328,26 @@ void IXmlSerializable.WriteXml(XmlWriter writer)
294328
writer.WriteElement("StartPoint", StartPoint);
295329
writer.WriteElement("EndPoint", EndPoint);
296330
}
331+
332+
/// <summary>
333+
/// Compute the signed distance from this `line` to the given point `p`. If the sign of the distance is positive, the normal vector from the line is in the same side to the point.
334+
/// </summary>
335+
/// <param name="p"></param>
336+
/// <returns></returns>
337+
public double SignedDistanceTo(Point2D p)
338+
{
339+
var result = A * p.X + B * p.Y + C;
340+
return result;
341+
}
342+
343+
/// <summary>
344+
/// Compute the absolute distance from this `line` to the given point `p`.
345+
/// </summary>
346+
/// <param name="p"></param>
347+
/// <returns></returns>
348+
public double DistanceTo(Point2D p)
349+
{
350+
return Math.Abs(SignedDistanceTo(p));
351+
}
297352
}
298353
}

0 commit comments

Comments
 (0)