我有一个起源于(cx,cy)的圆圈。 半径是r。 然后,有一个由。定义的线段 两点:(x1,y1)和(x2,y2)。 如何确定线段(不是延长线) 与圆相切?如果是的话,两个人在哪里接触?
我现在在做什么:找出点的距离 (cx,cy)来自扩展线。如果距离!= r,那么 当然,线段不与圆相切。甚至 如果距离== r,那么我们需要找出这一点 他们触摸的地方。然后检查该点是否存在 (x1,y1)和(x2,y2)之间的段。如果是,行 段IS与圆相切 - 以及触点 已经计算好了。这有效,但涉及太多的数学。 并且都有浮点数或双变量。不存在吗? 更聪明,更快的算法来实现相同的结果?
谢谢和问候, 普拉莫德
答案 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之间,则切点位于p1
和p2
之间。这是一个非常便宜的计算。如果确实如此,您可以跟进半径检查
(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)