如何确定线段是否与圆相切?

时间:2016-07-27 03:25:33

标签: algorithm math graphics language-agnostic geometry

我有一个起源于(cx,cy)的圆圈。 半径是r。 然后,有一个由。定义的线段 两点:(x1,y1)和(x2,y2)。 如何确定线段(不是延长线) 与圆相切?如果是的话,两个人在哪里接触?

我现在在做什么:找出点的距离 (cx,cy)来自扩展线。如果距离!= r,那么 当然,线段不与圆相切。甚至 如果距离== r,那么我们需要找出这一点 他们触摸的地方。然后检查该点是否存在 (x1,y1)和(x2,y2)之间的段。如果是,行 段IS与圆相切 - 以及触点 已经计算好了。这有效,但涉及太多的数学。 并且都有浮点数或双变量。不存在吗? 更聪明,更快的算法来实现相同的结果?

谢谢和问候, 普拉莫德

3 个答案:

答案 0 :(得分:3)

我建议你停止使用斜坡进行推理,因为垂直方向的奇点总是很难处理。请尝试使用参数化表单:

p = p1 + t v   where   v = p2 - p1

现在将向量p1 - c投影到v上,取导数wrt t,设置为零,然后快速得到一个表达式t的表达式最接近c的无限线上的点,即切点:

    (c - p1) dot v
t = --------------
       v dot v

如果此值介于0和1之间,则切点位于p1p2之间。这是一个非常便宜的计算。如果确实如此,您可以跟进半径检查

(c - p1 - tv) dot (c - p1 - tv) ~= r^2  ?

请注意,上面已计算过子c - p1

您刚才提到圈子正在移动,因此您可以计算v dot v一次并保存。

答案 1 :(得分:2)

您可能知道如果f(x,y) = y-m*x-c是线段的属性,则|f(x1,y1)|/sqrt(1+m^2)表示该线距(x1,y1)的距离。因此:

double m = (y2-y1)/(x2-x1);//slope
double c = y1 - m*x1;//since (x1,y1) lies on the line f(x1,y1) is zero
double d = abs(cy - m*cx - c)/sqrt(1+m*m);//distance
if(d==r)//radius
 //Yeah its tangent and do whatever you want
else
 //Nope

第二部分是伪代码;

g1(x,y) = y+(1/m)*x-c1;//perpendicular line through (x1,y1)
g2(x,y) = y+(1/m)*x-c2;//perpendicular line through (x2,y2)
c1 = y1+(1/m)*x1;
c2 = y2+(1/m)*x2;
if(g1(cx,cy)*g2(cx,cy)<0)//condition if point lies between two lines.Here make sure the coeffecients of y and x are of same sign in g1 and g2
//yes
else
//no

答案 2 :(得分:0)

根据定义,切线必须垂直于半径线。在下图中,红线是一条切线,当且仅当它垂直于绿线(从中心到接触点)时。

enter image description here

因此,如果您知道切线M的斜率(从(x1,y1)(x2,y2)计算得出),那么半径线的斜率为-1/M。鉴于你知道

  • 圆圈的中心
  • 圆的半径
  • 绿线的斜率

很容易计算联系点。实际上,在圆圈的两侧有两个可能的接触点。

所以你需要做的就是检查两个可能的接触点中是否有一个在线段上。