我已经从这里提升了数学,
好的,所以每个点都有 4 条“基本射线”,一条射线是一条穿过两点之间的无限线。
// A line in the form Ax+By=C from 2 points
public struct Ray
{
public readonly float A;
public readonly float B;
public readonly float C;
public Ray(PointF one, PointF two)
{
this.A = two.y - one.y;
this.B = one.x - two.x;
this.C = (this.A * one.x) + (this.B * two.x);
}
}
为了得到红衣主教,我们可以扩展PointF
private readonly SizeF NS = new SizeF(0.0F, 1.0F);
private readonly SizeF EW = new SizeF(1.0F, 0.0F);
private readonly SizeF NESW = new SizeF(1.0F, 1.0F);
private readonly SizeF NWSE = new SizeF(-1.0F, 1.0F);
public static IEnumerable<Ray> GetCardinals(this PointF point)
{
yield return new Ray(point + NS, point - NS);
yield return new Ray(point + EW, point - EW);
yield return new Ray(point + NESW, point - NESW);
yield return new Ray(point + NWSE, point - NWSE);
}
要找到两条射线的相交,我们可以做
static PointF Intersection(Ray one, Ray two)
{
var delta = (one.A * two.B) - (two.A * one.B);
if (delta == 0.0F)
{
//Lines are parallel
return PointF.Empty;
}
else
{
var x = ((two.B * one.C) - (one.B * two.C)) / delta;
var y = ((one.A * two.C) - (two.A * one.C)) / delta;
return new PointF(x, y);
}
}
所以,要得到两点基数的交点,
public static IEnumerable<PointF> GetCardinalIntersections(
this PointF point,
PointF other);
{
return point.GetCardianls().SelectMany(other.GetCardinals(), Intersection)
.Where(i => !i.IsEmpty());
}
然后启用,
public static IEnumerable<PointF> GetCardinalIntersections(
this PointF point,
IEnumerable<PointF> others);
{
return others.SelectMany((o) => point.GetCardinalIntersections(o));
}
然后我们可以像这样使用这个功能。
var point = new PointF(1.0F, 1.0F);
var others = new [] { new PointF(2.0F, 5.0F), new PointF(-13.0F, 32.0F) };
var intersections = point.GetCardinalIntersections(others);
显然这里有很多迭代,我没有编译或测试过这个,但是因为在它的核心,数学似乎相当有效,我对性能持乐观态度。