一、 问题描述

编写程序,实现如下功能:给定平面上两个圆,根据圆心位置和半径,判别它们是否有公切线。如果有的话,绘制两个圆的所有公切线。 要求:
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);
endhx(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==r2if 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:360x_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_linex1=zeros(2,2);x1(1,:)=draw_point;x1(2,:)=draw_point;h=line(x1(:,1),x1(:,2));
end
function x1=draw_pointx1=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. 合理使用数学表达式

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

  1. Opencv 学习笔记之——鼠标操作画出感兴趣区域

     本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 作者 ...

  2. opencv鼠标操作,画矩形

    opencv鼠标操作,画矩形 效果图 主要两个函数在作用 //-------------------全局函数声明部分------------------------- //描述:全局函数的声明 //- ...

  3. Matlab GUI鼠标画线

    (代码: 1\UI_line.m) % 窗体打开前,先执行该函数 function UI_line_OpeningFcn(hObject, eventdata, handles, varargin)h ...

  4. Matlab中用Simulink快速画Bode图及 .m 文件画Bode图

    Matlab中用Simulink快速画Bode图及 .m 文件画Bode图 Simulink画Bode图 .m 文件画Bode图 Simulink画Bode图 一万年没用matlab画过Bode图了, ...

  5. python如何画3个相切的圆_如何在几何画板中画出三个两两相切的圆

    <圆和圆的位置关系>是人教版九年级数学必学内容,在学习圆与圆的位置关系时,我们都知道圆与圆的位置关系有:相离,外切,相交,内切,内含,它们之间的位置是由圆心距与两半径的长度来确定的.那么如 ...

  6. matlab对图像操作函数的详解(笔记1)

    matlab对图像操作函数的详解 一. 读写图像文件 1. imread imread函数用于读入各种图像文件,如:a=imread('e:\w01.tif') 注:计算机E盘上要有w01相应的.ti ...

  7. matlab中plot函数画线时 颜色和类型

    转自 https://blog.csdn.net/garfielder007/article/details/50449140 matlab里plot函数画线时有很多的颜色和类型可以选择,下面列举一些 ...

  8. 大数据矩阵计算基础(二):R、Excel、Matlab中矩阵操作

    一.R语言 构造矩阵 a=matrix(c(1,2,3,4),ncol=2,byrow=T) b=matrix(c(5,6,7,8),ncol=2,byrow=T) c=matrix(c(1,2,3, ...

  9. Matlab的plot函数画线显示空白问题解决

    Matlab的plot函数画线无法显示问题解决 前言:在使用matlab中的plot函数画图时,没有任何报错,但是画不出线,却能画出点.在查阅资料后找到问题的原因. 这里我们使用y=x^2图像来进行分 ...

  10. 设置matlab图像线框,matlab在图像中画长方形(框)

    function [state,result]=draw_rect(data,pointAll,windSize,showOrNot) % 函数调用:[state,result]=draw_rect( ...

最新文章

  1. php 防止刷新重复提交,php防止刷新与重复提交实例代码
  2. 使用Reactor进行反应式编程最全教程
  3. 人工智能选go还是python_深圳人工智能学Python还是go,真实经历分享
  4. Linux文本查看命令之uniq
  5. oracle adf_Oracle ADF移动世界! 你好!
  6. 阿里云 x 蒙牛 | 打通数据孤岛,基于MaxCompute实现产销协同的智慧运营
  7. java 生成pdf 乱码_利用java处理fop导出pdf的中文乱码问题解决方案
  8. 【Python】修改pip默认缓存位置
  9. 查看python进程_[原创] 如何查看一个Python进程在”干什么”: py-spy 来帮忙 – 编码无悔 / Intent Focused...
  10. Spring : @Qualifier 注解
  11. python连接数据库设置编码_python操作mysql中文显示乱码的解决方法
  12. GoAhead2.5源代码分析之10-web server主程序(main.c)
  13. 深入掌握JMS(五):实战Topic 1
  14. Hog特征、Haar特征
  15. 最新 Hostinger域名转出教程 (2019年6月版本)
  16. Leetcode520Detect Capital检测大写字母
  17. 「雷军万字总结」小米十周年公开演讲全文
  18. 台式计算机全网页截图,电脑如何截图整个网页并保存?实现整个网页截图的最简单办法...
  19. 【问题】PPS、PPSX自动放映格式打开直接进入编辑模式
  20. unity开发xbox手柄 驱动坑

热门文章

  1. 年会抽奖程序:200行HTML+JavaScript写个桌面程序
  2. Linux远程终端工具之Xmanager----Xbrowser篇
  3. 【转载】秦九韶算法 Horner算法
  4. 浅析C/S、B/S与P2P架构
  5. 服务器终端性能测试之MBW内存测试
  6. 数据库用户配额问题ORA-01536: space quota exceeded for tablespace 'TFR_DATA' #
  7. 路由器输入正确的dns服务器,路由器显示DNS服务器异常怎么解决
  8. 泛函极值问题与变分法
  9. android 8.0 红米note3,红米Note3抢在小米6前面升到8.0,但是bug满天飞
  10. 使用while循环实现xyz+yzz=532