我在圆圈内有一个点,圆圈外有另一个点。我想找到线与圆相交的点。我怎么能在Windows Phone 8中这样做。请给我任何想法。
答案 0 :(得分:7)
这既是一个简单而又复杂的问题,很大程度上取决于你的意思。我从你的开场白中说你正在谈论线段而不是真正的(无限)线。
在这种情况下,你有几个案例需要解决。交点仅在一个点位于圆内并且一个点位于圆外时发生。下面的算法没有捕获
的情况这些被归结为“无交叉”结果。这仅处理内部严格一个点和圆外一个点的情况。
首先你需要一些辅助功能。它们使用基本几何来确定点是在圆内还是在圆外(圆上的点被计为“外部”),以及两个点是否形成与圆相交的线段。
private bool IsInsideCircle(Point CirclePos, float CircleRad, Point checkPoint)
{
if (Math.Sqrt(Math.Pow((CirclePos.X - checkPoint.X), 2) +
Math.Pow((CirclePos.Y - checkPoint.Y), 2)) < CircleRad)
{ return true; } else return false;
}
private bool IsIntersecting(Point CirclePos, float CircleRad, Point LineStart,
Point LineEnd)
{
if (IsInsideCircle(CirclePos, CircleRad, LineStart) ^
IsInsideCircle(CirclePos, CircleRad, LineEnd))
{ return true; } else return false;
}
注意使用^
(异或) - 我们想要一个内部点和一个外部点。
有了这个,我们可以发挥更大的作用:
private int Intersect (Point CirclePos, float CircleRad,
Point LineStart, Point LineEnd, ref Point Intersection)
{
if (IsIntersecting(CirclePos, CircleRad, LineStart, LineEnd))
{
//Calculate terms of the linear and quadratic equations
var M = (LineEnd.Y - LineStart.Y) / (LineEnd.X - LineStart.X);
var B = LineStart.Y - M * LineStart.X;
var a = 1 + M*M;
var b = 2 * (M*B - M*CirclePos.Y - CirclePos.X);
var c = CirclePos.X * CirclePos.X + B * B + CirclePos.Y * CirclePos.Y -
CircleRad * CircleRad - 2 * B * CirclePos.Y;
// solve quadratic equation
var sqRtTerm = Math.Sqrt(b * b - 4 * a * c);
var x = ((-b) + sqRtTerm)/(2*a);
// make sure we have the correct root for our line segment
if ((x < Math.Min(LineStart.X, LineEnd.X) ||
(x > Math.Max(LineStart.X, LineEnd.X))))
{ x = ((-b) - sqRtTerm) / (2 * a); }
//solve for the y-component
var y = M * x + B;
// Intersection Calculated
Intersection = new Point(x, y);
return 0;
} else {
// Line segment does not intersect at one point. It is either
// fully outside, fully inside, intersects at two points, is
// tangential to, or one or more points is exactly on the
// circle radius.
Intersection = new Point(0, 0);
return -1;
}
}
此函数将交点作为ref
参数,并返回-1
(无交点)或0
(找到交点)。我使用int
返回值,以防您想要扩展它以区分边缘情况。交点是从基本几何计算的 - 记住一条线表示为(参见:Slope Intercept and Point Slope Form)
和一个圆圈(以(C.x, C.y)
为中心,半径为r
)
您可以通过替换来解决这个方程组:
扩展和收集您获得的条款:
这是形式
的标准二次方程可以通过二次公式求解(参见:Quadratic Formula):
这为我们的线段所在的无限线提供了两个根 - 我们在上面进行最后检查,以确保我们为特定线段选择解决方案。
这就是为什么在数学课上注意很重要!
现在......取决于你在做什么,有很多方法可以优化它。上面的解决方案概述了基本方法,但是如果需要的话,当然可以更快地完成这项工作。显然,参数可以根据您使用的任何类型的点或对象进行调整。我尽量让它变得一般。
另外,要展示如何调用它的示例:
Point iPt = new Point();
var rslt = Intersect(new Point(2,3), 5.0f, new Point(2,2),
new Point(8,6), ref iPt);
if (rslt == 0) {
MessageBox.Show(String.Format("Intersection at: x = {0}, y = {1}",
iPt.X, iPt.Y));
}
else {
MessageBox.Show("No Intersection");
}
答案 1 :(得分:0)
数学中有一个小错字。 c#代码没问题。
... r ^ 2 - B * C.y)= 0
应该是
... r ^ 2 - 2B * C.y)= 0
也 c =(C.x ^ 2 + C.y ^ 2 + B ^ 2 - r ^ 2 - 2B * C.y)