91 lines
3.1 KiB
C#
91 lines
3.1 KiB
C#
|
|
using System;
|
|||
|
|
|
|||
|
|
namespace Microsoft.Msagl.GraphmapsWithMesh
|
|||
|
|
{
|
|||
|
|
public class PointToSegmentDistance
|
|||
|
|
{
|
|||
|
|
public static double GetDistance(Microsoft.Msagl.Core.Geometry.Point pointA, Microsoft.Msagl.Core.Geometry.Point pointB, Microsoft.Msagl.Core.Geometry.Point pointC)
|
|||
|
|
{
|
|||
|
|
return GetDistance(new Vertex((int)pointA.X, (int)pointA.Y), new Vertex((int)pointB.X, (int)pointB.Y), new Vertex((int)pointC.X, (int)pointC.Y));
|
|||
|
|
}
|
|||
|
|
public static Microsoft.Msagl.Core.Geometry.Point getClosestPoint(Vertex pointA, Vertex pointB, Vertex pointP)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
double[] AP = new double[2];
|
|||
|
|
AP[0] = pointP.XLoc - pointA.XLoc;
|
|||
|
|
AP[1] = pointP.YLoc - pointA.YLoc;
|
|||
|
|
|
|||
|
|
double[] AB = new double[2];
|
|||
|
|
AB[0] = pointB.XLoc - pointA.XLoc;
|
|||
|
|
AB[1] = pointB.YLoc - pointA.YLoc;
|
|||
|
|
|
|||
|
|
double AB_length = AB[0] * AB[0] + AB[1] * AB[1];
|
|||
|
|
double AP_AB_Dot = AP[0] * AB[0] + AP[1] * AB[1];
|
|||
|
|
double t = AP_AB_Dot / AB_length;
|
|||
|
|
|
|||
|
|
if (t < 0) t = 0;
|
|||
|
|
if (t > 1) t = 1;
|
|||
|
|
double pointx = pointA.XLoc + AB[0] * t;
|
|||
|
|
double pointy = pointA.YLoc + AB[1] * t;
|
|||
|
|
return new Microsoft.Msagl.Core.Geometry.Point(pointx, pointy);
|
|||
|
|
}
|
|||
|
|
//Compute the distance from AB to C
|
|||
|
|
//if isSegment is true, AB is a segment, not a line.
|
|||
|
|
public static double GetDistance(Vertex pointA, Vertex pointB, Vertex pointC)
|
|||
|
|
{
|
|||
|
|
double dist = CrossProduct(pointA, pointB, pointC) / Distance(pointA, pointB);
|
|||
|
|
|
|||
|
|
double dot1 = DotProduct(pointA, pointB, pointC);
|
|||
|
|
if (dot1 > 0)
|
|||
|
|
return Distance(pointB, pointC);
|
|||
|
|
|
|||
|
|
double dot2 = DotProduct(pointB, pointA, pointC);
|
|||
|
|
if (dot2 > 0)
|
|||
|
|
return Distance(pointA, pointC);
|
|||
|
|
|
|||
|
|
return Math.Abs(dist);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
//Compute the dot product AB . AC
|
|||
|
|
private static double DotProduct(Vertex pointA, Vertex pointB, Vertex pointC)
|
|||
|
|
{
|
|||
|
|
double[] ab = new double[2];
|
|||
|
|
double[] bc = new double[2];
|
|||
|
|
ab[0] = pointB.XLoc - pointA.XLoc;
|
|||
|
|
ab[1] = pointB.YLoc - pointA.YLoc;
|
|||
|
|
bc[0] = pointC.XLoc - pointB.XLoc;
|
|||
|
|
bc[1] = pointC.YLoc - pointB.YLoc;
|
|||
|
|
double dot = ab[0] * bc[0] + ab[1] * bc[1];
|
|||
|
|
|
|||
|
|
return dot;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Compute the cross product AB x AC
|
|||
|
|
static private double CrossProduct(Vertex pointA, Vertex pointB, Vertex pointC)
|
|||
|
|
{
|
|||
|
|
double[] ab = new double[2];
|
|||
|
|
double[] ac = new double[2];
|
|||
|
|
ab[0] = pointB.XLoc - pointA.XLoc;
|
|||
|
|
ab[1] = pointB.YLoc - pointA.YLoc;
|
|||
|
|
ac[0] = pointC.XLoc - pointA.XLoc;
|
|||
|
|
ac[1] = pointC.YLoc - pointA.YLoc;
|
|||
|
|
double cross = ab[0] * ac[1] - ab[1] * ac[0];
|
|||
|
|
|
|||
|
|
return cross;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Compute the distance from A to B
|
|||
|
|
static double Distance(Vertex pointA, Vertex pointB)
|
|||
|
|
{
|
|||
|
|
double d1 = pointA.XLoc - pointB.XLoc;
|
|||
|
|
double d2 = pointA.YLoc - pointB.YLoc;
|
|||
|
|
|
|||
|
|
return Math.Sqrt(d1 * d1 + d2 * d2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|