the*_*end 0 c# geometry windows-phone-8
我在圆圈内有一个点,在圆圈外有另一个点.我想找到线与圆相交的点.我怎么能在Windows Phone 8中这样做.请给我任何想法.
这既是一个简单而复杂的问题,很大程度上取决于你的意思.我从你的开场发帖中得知你所说的线段而不是真正的(无限)线.
在这种情况下,你有几个案例需要解决.交点仅在一个点位于圆内并且一个点位于圆外时发生.下面的算法没有捕捉到的情况
这些都集中在"无交叉"结果中.这仅处理内部严格一个点和圆外一个点的情况.
首先,您需要一些辅助功能.这些使用基本几何来确定点是在圆内还是在圆外(圆上的点被计为"外"),以及两个点是否形成与圆相交的线段.
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;
}
Run Code Online (Sandbox Code Playgroud)
注意使用^(异或) - 我们希望内部有一个点,外部有一个点.
有了这个,我们可以发挥更大的作用:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
此函数将交点作为ref参数并返回-1(无交点)或0(找到交点).我使用了一个int返回值,以防你想扩展它以区分边缘情况.交点是从基本几何计算的 - 记住一条线表示为(参见:坡度截距和坡度坡度表格)
和圆(以(C.x, C.y)半径为中心r)是
你通过替换来解决这个方程组:
扩展和收集您获得的条款:
这是形式的标准二次方程
这可以通过二次公式求解(参见:二次公式):
这为我们的线段所在的无限线提供了两个根 - 我们在上面进行最后检查,以确保我们为特定线段选择解决方案.
这就是为什么在数学课上注意很重要!
现在......取决于你在做什么,有很多方法可以优化它.上面的解决方案概述了基本方法,但是如果需要的话,当然可以更快地完成这项工作.显然,参数可以根据您使用的任何类型的点或对象进行调整.我试图让它尽可能一般.
另外,要显示如何调用它的示例:
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");
}
Run Code Online (Sandbox Code Playgroud)