[MATLAB]matlab鼠标操作画两圆,做出两圆的公切线

一、 问题描述

编写程序,实现如下功能:给定平面上两个圆,根据圆心位置和半径,判别它们是否有公切线。如果有的话,绘制两个圆的所有公切线。 要求:
1、用鼠标交互绘制两个圆,程序获取圆心坐标和半径;
2、通过对两个圆心连线的几何变换绘制所有的公切线。

二、 求解思路

使用ginput函数获取用户选择的两个圆的圆心和圆环上一点以确定圆的位置和半径,首先判断两个圆的半径是否相同,在两个圆半径相同时,若两圆外离,则有4条切线,其中两条外切线直接由圆心的连线顺着圆心连线在两圆心的垂线移动半径的长度得到,两个内切线由比例关系,获取两连线的中心,根据比例关系获得使得线与圆相切时的角度,利用数学关系获得顺时针和逆时针旋转所获得的切线。若两个圆的半径不同,则分外离,相交,内含(外切与内切包含在外离和相交的情形中,即所画的有两条切线重合)。
外离时,两个圆有四条切线,内切线和半径相同时的画法相同,外切线需要将两圆心连线朝着半径小的圆的方向延长,根据几何关系计算出切线与延长线的交点以及切线与延长线的夹角,利用数学表达式得到旋转后的延长线上两点的坐标(一点直接为两线的交点,另外一点选取大圆的圆心),即获得了大圆圆心绕两线交点的点,连结此点与两线交点即可获得切线,由于顺时针旋转和逆时针旋转,所以有两条外切线。
相交时,只有外切线,画法与外离时的画法相同
内含时,没有切线。

三、 程序代码


%Main.m
clear;
clc;
close all
axis([0 100 0 100])
ax=axes('XLim',[0,100],'YLim',[0,100]);
set(gcf,'Renderer','opengl')
axis equal
[h1,x_long1,y_long1,r1]=draw_circle;
set(h1,'Color','g','LineWidth',2)
[h2,x_long2,y_long2,r2]=draw_circle;
set(h2,'Color','g','LineWidth',2)
%默认h1为半径大的圆
hm=max(r1,r2);
if isequal(hm,r2)
    [h1,h2]=swap(h1,h2);
    [x_long1,x_long2]=swap(x_long1,x_long2);
    [y_long1,y_long2]=swap(y_long1,y_long2);
    [r1,r2]=swap(r1,r2);
end
    
hx(1,:)=get(h1,'Xdata');
hy(1,:)=get(h1,'Ydata');
hx(2,:)=get(h2,'Xdata');
hy(2,:)=get(h2,'Ydata');
d=sqrt((hx(1,1)-hx(2,1))^2+(hy(1,1)-hy(2,1))^2);
line_ab=line([hx(1,1),hx(2,1)],[hy(1,1),hy(2,1)]);
set(line_ab,'Color','k','LineWidth',1)

if r1==r2
    if d>(r1+r2)
        draw_x(r1,r2,hx,hy)
        draw_nei(r1,r2,hx,hy)
    elseif d<(r1+r2) && d>=(r1-r2)
        draw_x(r1,r2,hx,hy)
    end
elseif d>(r1+r2)
    draw_wai(r1,r2,hx,hy)
    draw_nei(r1,r2,hx,hy)
elseif d<(r1+r2) && d>=(r1-r2)
    draw_wai(r1,r2,hx,hy)
end
zoom on

%draw_circle.m
function[h,x_long,y_long,r]=draw_circle
h=draw_line;
hold on
h1=get(h,'Xdata');
h2=get(h,'Ydata');
r=sqrt((h1(2)-h1(1))^2+(h2(2)-h2(1))^2);
x_long=zeros(1,360);
y_long=zeros(1,360);
figure(1)
for i=1:360
    x_long(i)=h1(1)+r*cos(i*180/pi);
    y_long(i)=h2(1)+r*sin(i*180/pi);
    plot(x_long(i),y_long(i),'r.','MarkerSize',1);
    pause(0.002)
    hold on
end
end
function h=draw_line
    x1=zeros(2,2);
    x1(1,:)=draw_point;
    x1(2,:)=draw_point;
    h=line(x1(:,1),x1(:,2));
end
function x1=draw_point
     x1=roundn(ginput(1),-1);
     text(x1(1),x1(2),['(',num2str(x1(1)),',',num2str(x1(2)),')']);
end

%画外切线
draw_wai.m
function draw_wai(r1,r2,hx,hy)
[theta,point]=prep_wai(r1,r2,hx,hy);
kx=point(1)+(hx(1,1)-point(1))*cos(theta)-(hy(1,1)-point(2))*sin(theta);
ky=point(2)+(hy(1,1)-point(2))*cos(theta)+(hx(1,1)-point(1))*sin(theta);
lineq=line([kx point(1)],[ky point(2)]);
set(lineq,'LineWidth',3)

kx=point(1)+(hx(1,1)-point(1))*cos(theta)+(hy(1,1)-point(2))*sin(theta);
ky=point(2)+(hy(1,1)-point(2))*cos(theta)-(hx(1,1)-point(1))*sin(theta);
lineq1=line([kx point(1)],[ky point(2)]);
set(lineq1,'LineWidth',3)
end
function [theta,point]=prep_wai(r1,r2,hx,hy)
    d=sqrt((hx(1,1)-hx(2,1))^2+(hy(1,1)-hy(2,1))^2);
    dp=d/(r1/r2-1);
    theta=asin(r2/dp);
    point=zeros(1,2);
    point(1)=hx(2,1)+(hx(2,1)-hx(1,1))*dp/d;
    point(2)=hy(2,1)+(hy(2,1)-hy(1,1))*dp/d;
    point=roundn(point,-1);
    plot(point(1),point(2),'r','MarkerSize',3)
    text(point(1),point(2),['(',num2str(point(1)),',',num2str(point(2)),')'])
end

%画内切线
draw.nei.m
function draw_nei(r1,r2,hx,hy)
    [thetas,points]=prep_nei(r1,r2,hx,hy);
    px1=points(1)+(hx(1,1)-points(1))*cos(thetas)-(hy(1,1)-points(2))*sin(thetas);
    py1=points(2)+(hy(1,1)-points(2))*cos(thetas)+(hx(1,1)-points(1))*sin(thetas);
    
    px2=points(1)+(hx(2,1)-points(1))*cos(thetas)-(hy(2,1)-points(2))*sin(thetas);
    py2=points(2)+(hy(2,1)-points(2))*cos(thetas)+(hx(2,1)-points(1))*sin(thetas);
    
    lineqs=line([px1 px2],[py1 py2]);
    set(lineqs,'LineWidth',3)
    
    px10=points(1)+(hx(1,1)-points(1))*cos(thetas)+(hy(1,1)-points(2))*sin(thetas);
    py10=points(2)+(hy(1,1)-points(2))*cos(thetas)-(hx(1,1)-points(1))*sin(thetas);
    
    px20=points(1)+(hx(2,1)-points(1))*cos(thetas)+(hy(2,1)-points(2))*sin(thetas);
    py20=points(2)+(hy(2,1)-points(2))*cos(thetas)-(hx(2,1)-points(1))*sin(thetas);
    
    lineqs1=line([px10 px20],[py10 py20]);
    set(lineqs1,'LineWidth',3)
end
function [thetas,points]=prep_nei(r1,r2,hx,hy)
d=sqrt((hx(1,1)-hx(2,1))^2+(hy(1,1)-hy(2,1))^2);
d1=d/(r2/r1+1);
thetas=asin(r1/d1);
points=zeros(1,2);
points(1)=hx(1,1)+(hx(2,1)-hx(1,1))*d1/d;
points(2)=hy(1,1)+(hy(2,1)-hy(1,1))*d1/d;
points=roundn(points,-1);
plot(points(1),points(2),'r','MarkerSize',3)
text(points(1),points(2),['(',num2str(points(1)),',',num2str(points(2)),')'])
end


%画两个圆半径相等时的外切线
draw_x.m
function draw_x(r1,r2,hx,hy)
    d=sqrt((hx(1,1)-hx(2,1))^2+(hy(1,1)-hy(2,1))^2);
    fx=(hx(2,1)-hx(1,1))/d;
    fy=(hy(2,1)-hy(1,1))/d;
    xnew1=hx(1,1)-fy*r1;
    ynew1=hy(1,1)+fx*r1;
    xnew2=hx(2,1)-fy*r1;
    ynew2=hy(2,1)+fx*r1;
    line1=line([xnew1,xnew2],[ynew1,ynew2]);
    set(line1,'LineWidth',3)

    xnew3=hx(1,1)+fy*r1;
    ynew3=hy(1,1)-fx*r1;
    xnew4=hx(2,1)+fy*r1;
    ynew4=hy(2,1)-fx*r1;
line2=line([xnew3,xnew4],[ynew3,ynew4]);
set(line2,'LineWidth',3)

end



四、 实验结果

两个圆半径相等时外切
在这里插入图片描述

两个圆半径相等时相交
在这里插入图片描述

两个圆外离时
在这里插入图片描述

两个圆相交时
在这里插入图片描述

两个圆内含时
在这里插入图片描述

五、 实验心得

  1. 注意分类讨论,针对特殊情况
  2. 注意合理使用函数,减少代码量
  3. 合理使用数学表达式
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值