求两圆共切线的算法

clethe 2005-05-23 05:13:03
已知两圆相离,求其内公切线方程。

小弟谢了先。
...全文
838 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
ihsgnep 2005-07-03
  • 打赏
  • 举报
回复
Mark
cosio 2005-06-30
  • 打赏
  • 举报
回复
先判断圆心的距离,在确定它的切线!初中的题目!
mathe 2005-05-27
  • 打赏
  • 举报
回复
假设圆心坐标分别为(x1,y1),(x2,y2),半径分别为r1,r2
假设切线方程为ax+by+c=0
那么
a*x1+b*y1+c=r1*sqrt(a^2+b^2) (1)
a*x2+b*y2+c=-r2*sqrt(a^2+b^2) (2)
这个可以求出一条内公切线方程(也就是两个点到直线距离分别为r1,r2,分布再两旁)
另外一组方程是
a*x1+b*y1+c=-r1*sqrt(a^2+b^2)
a*x2+b*y2+c=r2*sqrt(a^2+b^2)

比如解方程组(1),(2),我们可以(1)-(2),消去c,然后记cos(s)=a/sqrt(a^2+b^2),sin(s)=b/sqrt(a^2+b^2)
得到
(x1-x2)cos(s)+(y1-y2)sin(s)=r1+r2
Let u=sqrt( (x1-x2)^2+(y1-y2)^2 ),
cos(t)=(x1-x2)/u, sin(t)=(y1-y2)/u,我们可以先计算出t
所以cos(t)cos(s)+sin(t)sin(s)=(r1+r2)/u
cos(t-s)=(r1+r2)/u
通过这个方法,我们可以解出s
tuxw 2005-05-25
  • 打赏
  • 举报
回复
上下切线,内外切线的规定为:

以圆心1指向圆2的向量为准,与该向量交叉的为内切线、不相交的为外切线
与向量夹角(逆时针为正)在90°以内为上切线,-90°以内为下切线
tuxw 2005-05-25
  • 打赏
  • 举报
回复
/*
* 功能:两下圆的切线
* 参数:
* x1, y1 --- 圆心1坐标
* x2, y2 --- 圆心2坐标
* r1, r2 --- 两个圆的半径
* type --- 切线类型(两个圆共有四条切线)
*/
#define sq2(x) (x)*(x)
#define PI 3.14159265358979323846

void tline(int x1,int y1,int x2,int y2,int r1,int r2,char type)
{ / * 0 is up-out... 1 is up-in... 2 is down-out.. 3 is down-in.. * /
/ * 0 表示上切线并且是外切线,其它类推* /

float a1; // 连心线与X轴夹角
float a2; // 公切线与连心线夹角
float k, distance=0; // 切点-圆心角度、圆心距
int dx11,dy11,dx22,dy22; // 待求切点坐标
int temp;

if((type < 0) || (type > 3))
return;

// 规定一个标准方向,将左边的圆定为圆1
// 使后面的夹角符号参考统一
if(x1 > x2) {
temp=x1,x1=x2,x2=temp;
temp=y1,y1=y2,y2=temp;
temp=r1,r1=r2,r2=temp;
}

// 计算圆心距与连心线角度
if(x1 == x2) {
distance = abs(y2-y1);
if(y1 > y2)
a1=PI/2;
else
a1=-PI/2;
}
else
a1=atan((float)(y1-y2)/(x2-x1));

if(y1 == y2)
distance=abs(x2-x1);
if(distance <= 0.0)
distance=sqrt((long)sq2(y2-y1)+(long)sq2(x2-x1));

// 公切线与连心线夹角
if(type % 2 == 0)
a2=asin((float)(r2-r1)/distance);
else
a2=asin((float)(r2+r1)/distance);

// 四条切线的不同由两个平夹角不同组合组成
// 组成的角度 k 为圆心与切点的连线与X轴的夹角
switch(type)
{
case 0:
k=a1+a2;
dx11=x1-r1*sin(k);dy11=y1-r1*cos(k);
dx22=x2-r2*sin(k);dy22=y2-r2*cos(k);
break;
case 2:
k=a1-a2;
dx11=x1+r1*sin(k);dy11=y1+r1*cos(k);
dx22=x2+r2*sin(k);dy22=y2+r2*cos(k);
break;
case 1:
k=a1-a2;
dx11=x1-r1*sin(k);dy11=y1-r1*cos(k);
dx22=x2+r2*sin(k);dy22=y2+r2*cos(k);
break;
case 3:
k=a1+a2;
dx11=x1+r1*sin(k);dy11=y1+r1*cos(k);
dx22=x2-r2*sin(k);dy22=y2-r2*cos(k);
break;
default:
break;
}
myline(dx11,dy11,dx22,dy22); // 直线
}

void myline(int x1, int y1, int x2, int y2)
{
//不同环境下的直函数函数
line(x1, y1, x2, y2); // TC
}


在TC下的测试代码
#include <conio.h>
#include <graphics.h>
#include <math.h>

#define sq2(x) (x)*(x)
#define PI 3.14159265358979323846
void tline(int x1,int y1,int x2,int y2,int r1,int r2,char type);

void main()
{
int x1 = 150, y1 = 120, r1 = 40;
int x2 = 400, y2 = 280, r2 = 60;

int gd = DETECT, gm;
initgraph(&gd, &gm, "");

circle(x1, y1, r1);
circle(x2, y2, r2);

tline(x1, y1, x2, y2, r1, r2, 0);
tline(x1, y1, x2, y2, r1, r2, 1);
tline(x1, y1, x2, y2, r1, r2, 2);
tline(x1, y1, x2, y2, r1, r2, 3);

getch();
closegraph();
}


寻开心 2005-05-23
  • 打赏
  • 举报
回复
有了交点和斜率,自然就知道了内切线的方程了
需要注意的是出于算法安全性的考虑,应该先计算两个圆心之间的距离L是否大于两个圆半径的和r1+r2,否则计算结果无效的
寻开心 2005-05-23
  • 打赏
  • 举报
回复
知道了Q点的坐标,就还可以知道圆心连线和内切线之间的夹角
因为他们的正弦数值就是 r1/x = r2/(L-x)

使用atan2函数可以计算出来,圆心连线的直线斜率
根据atan2(r1, r2*L/(r1+r2) = atan2( r1+r2, L )
就可以计算夹角相差多大了
注意可正可负,没有区别的,因为内切线是两条
寻开心 2005-05-23
  • 打赏
  • 举报
回复
我们做一个图,
两个圆,各自的半径分别是r1,r2,圆心O1,O2
两个圆心之间的距离是L
对于所求的一个内切线来说,和两个圆的交点非别是P1,P2
假定P1P2的连线和两个圆心的连线O1O2相交于Q点

假定,Q点到O1的距离长度为x
根据三角形的相似定理,显然有
r1/r2 = x/ (L-x)
从而可用推导出
x = r1*L/(r1+r2)
知道了这个点Q,那么显然内切点很容易就算出来了
jp1984 2005-05-23
  • 打赏
  • 举报
回复
对两方程分别求导得到各自圆周上切线方程,联立两方程可求切点。讲切点代入前面所求任一切线的方程,即为所求

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧