目录

  • 1 两圆求交
    • 1.1 思路
    • 1.2 求交点
    • 1.3 选取探测点
    • 1.4 相离 包含情况
  • 2 多圆求交
  • 3 圆环求交
    • 3.1 思路
    • 3.2 操作
  • 3 多圆环求交
  • 4 matlab代码

1 两圆求交

1.1 思路

可以将两圆的位置关系分为3种情况:相交相离包含(这里我将外部相切的情况归为相离,内部相切归为包含。)
我们知道两圆的圆心坐标以及半径,就可以根据圆心距与两圆半径距离进行相交情况判断。伪代码如下

%dis为圆心距
if(dis >= r1+r2||abs(r1-r2) >= dis) %相离、包含else%相交
end

1.2 求交点

首先考虑最一般的情况,及两圆相交,有两个交点。如何求相交点呢?

第一种方法是联立两圆方程求解,这种方法比较暴力,鄙人喜欢温柔一点的。
第二种方式是几何方法:

  1. 求圆心向量AB与X轴夹角θ
  2. 求向量AC与向量AB的夹角α
    联立方程,求出AD
    AD2+ CD2= r12
    DB2+ CD2= r22
    r12+ r22=AB2
    α=acos(AD/AC)
    上述方程没有考虑到∠ACB是否为90°,所以有问题。这里采用余弦定理
    α=acos((r12+AB2-r22)/2*r1*AB)
  3. 那么C点和E点坐标也就知道了。


具体代码如下

%两圆心连线与X轴夹角,逆时针为正
theta = atan2d(y2-y1,x2-x1);
ad = (r1^2-r2^2+dis^2)/(2*dis);
%交点与圆心1连线的向量与两圆心连线的夹角
alpha = acosd(ad/r1);
crosspoint1 = [x1+r1*cosd(theta+alpha);y1+r1*sind(theta+alpha)];
crosspoint2 = [x1+r1*cosd(theta-alpha);y1+r1*sind(theta-alpha)];
crosspoint = [crosspoint1 crosspoint2];

1.3 选取探测点

找到交点(图中红点)后下一步就是找两圆重合部分,这里以找到重合部分的边界(图中红线)为目标。

我们知道一个圆上2个点可以将圆分为2段弧,3个点可以分为3段弧。现在相交圆上有两段弧,我们可以在每段弧中间再取一个点,作为试探点(上图中蓝点),检查该点是否同时满足距离两圆圆心距离小于其圆的半径,若满足则说明该试探点所在的弧为重合部分的边界(即重合弧)。
遍历两圆上的试探点,我们就得到了所有重合弧的信息啦!弧的表示方法有很多种,这里我用5个参数表示一段弧。

x %弧所在圆的坐标
y
r%弧所在圆的半径
startAngle%弧的起始角
plusAngle%弧的增加角

圆弧的表示

1.4 相离 包含情况

需要注意的是,当两圆为相离或包含关系时是没有交点的,但是怎么确定包含关系时的重合边界呢?
这里可以将整个圆当做一条弧,规定当圆上没有相交点时,人为的增加一个探测点。然后再进行探测点遍历就可以啦

相离情况

包含情况

2 多圆求交

多个圆相交也是上面的思路,首先对所有圆进行遍历,两两求交点,根据交点求每一个圆上的探测点;再对所有圆进行遍历,检验探测点是否满足条件,满足的话该探测点所在的弧即为重合的边界(重合弧)。

3 圆环求交

3.1 思路

圆如何求交我们已经搞清楚了,两个圆环求交呢?
首先考虑一个圆环是由两个同心圆组成的,一个内圆一个外圆。我们完全可以把一个圆环看成两个圆,从而两个圆环求交的问题就转化成了4个圆求交的问题。

3.2 操作

需要注意的是,探测点与内外圆的判断是不一样的。

  1. 对于外圆,重合部分的探测点到该圆圆心的距离应<=该圆半径
  2. 对于内圆,重合部分的探测点到该圆圆心的距离应>=该圆半径

其他部分都一样

3 多圆环求交

想必你已经会了

4 matlab代码

使用了面向对象编程思想,将圆封装成了一个类,包含了圆的位置坐标,半径,交点等属性。
完整程序下载链接: matlab 多圆/圆环求交.

觉得有帮助的话就给我个赞吧!!!

main函数

clear all
% circle = 5*rand(3,4);%随机生成10个圆
%3圆环 前两行为XY坐标,第三行为半径,第四行为内外圆标志
circle = [0,0,4,4,2,2;0,0,0,0,3,3;1,6,1,6,1,6;-1,1,-1,1,-1,1];
%2圆环
% circle = [0,0,5,5;
%     0,0,0,0;
%     3,6,3,6;
%     -1,1,-1,1];
%3外圆
% circle = [-1,1,0;
%           0,0,2;
%          3,3,3;
%           1,1,1];
[~,col] = size(circle);
%-------交点列表 用于画图-------
crossPointsList = [];
%---------弧列表初始化----------
arcList = [];
%---------圆列表初始化----------
cirList(col) = Circle();%建立类对象数组
for i = 1:colcirList(i).cirNum = i;cirList(i).cirPro = circle(1:3,i) ;cirList(i).cirType = circle(4,i) ;
end
%---------遍历所有圆,两两求交--------
for i = 1:colfor j = i+1:col%两圆交点crossPoint = ArcIntersection(cirList(i),cirList(j));%如果有交点if ~isempty(crossPoint)%将交点放入交点列表crossPointsList(:,end+1:end+2) = crossPoint;endendPlotCir(cirList(i));%画圆hold on;cirList(i).CrossPointsAngle();%画出两交点的中心点if ~isempty(cirList(i).middlePoints)plot(cirList(i).middlePoints(1,:), ...cirList(i).middlePoints(2,:), ...'b.','MarkerSize',25);hold on;end
end
%--------画出交点-----------
if isempty(crossPointsList)fprintf('无任何交点\n');
elseplot(crossPointsList(1,:),crossPointsList(2,:),'r.','MarkerSize',25);hold on;
end%% 判断哪些弧属于重合弧
for i = 1:colarcFlag = (1:cirList(i).numArc);for j = 1:col%跳过自身判断if (i == j)continueendpos = cirList(i).middlePoints - cirList(j).cirPro(1:2,:);d = (pos(1,:).^2+pos(2,:).^2).^0.5;%如果是外圆if cirList(j).cirType == 1 arcOder_temp = find(d <= cirList(j).cirPro(3)); %满足要求的弧的序号else %如果是内圆arcOder_temp = find(d >= cirList(j).cirPro(3)); %满足要求的弧的序号endarcFlag = intersect(arcFlag,arcOder_temp);end%如果没有n次相交弧if isempty(arcFlag)fprintf('%d号圆没有n次相交弧\n', cirList(i).cirNum);continue;elsearcList_temp = ones(3,size(arcFlag,2)).*cirList(i).cirPro;arcList_temp(4,:) = cirList(i).cirArcList(1,arcFlag);arcList_temp(5,:) = cirList(i).cirArcList(2,arcFlag);arcList = [arcList arcList_temp];end
end
%画圆弧
PlotArc(arcList,20)
title('三圆环求交')
xlabel('x')
ylabel('y')
%axis([-5 5 -5 5])

Circle类

classdef Circle < handle%圆类properties%圆的编号cirNum%圆的属性 x y rcirPro%圆的类型 1代表外环 -1代表内圆 0代表默认值cirType%圆的交点列表 交点的 x ycirCrossPoints%圆弧列表 第一行是弧的起点角度 第二行是弧转过的角度(逆时针)cirArcList%圆弧数量numArc%交点中间点 x y anglemiddlePointsendmethods%构造函数function obj = Circle(ciecle,type)if nargin == 0obj.cirPro = zeros(3,1);obj.cirType = 0;elseif nargin == 1obj.cirPro = ciecle;obj.cirType = 0;elseif nargin == 2obj.cirPro = ciecle;obj.cirType = type;endend%求交点与圆心连线 与 X轴夹角function CrossPointsAngle(obj)xr = obj.cirPro(1);yr = obj.cirPro(2);r = obj.cirPro(3);if  ~isempty(obj.cirCrossPoints)vector = [obj.cirCrossPoints(1,:)-xr;obj.cirCrossPoints(2,:)-yr];%向量与X轴夹角angle = atan2d(vector(2,:),vector(1,:));%根据夹角排序angleOrder = CrossPointsSort(angle);%生成圆弧列表obj.cirArcList(1,:) = angleOrder;obj.cirArcList(2,:) = [diff(angleOrder),angleOrder(1)-angleOrder(end)+360];%计算圆弧数量obj.numArc = size(obj.cirArcList,2);%生成每个段圆弧的中间的探测点middleAngle = obj.cirArcList(1,:) + obj.cirArcList(2,:)/2;obj.middlePoints = [xr+cosd(middleAngle).*r;yr+sind(middleAngle).*r];else %如果一个圆和其他圆没有交点,规定一个默认探测点obj.cirArcList(1,:)=0;obj.cirArcList(2,:)=360;obj.numArc = 1;%生成每个段圆弧的中间的探测点middleAngle = obj.cirArcList(1,:) + obj.cirArcList(2,:)/2;obj.middlePoints = [xr+cosd(middleAngle).*r;yr+sind(middleAngle).*r];%fprintf('%d号圆与其他圆均无交点\n',obj.cirNum);endendend
end%圆的交点排序 交点与X轴夹角从小到大排序
function angleOrder = CrossPointsSort(angle)
array = find(angle<0);
%将小于0°的角度 转为大于0°
angle(array)=angle(array)+360;
%对圆的交点列表进行排序 因为是行排序 用sortrows时需要转置
tempAngle = sortrows(angle',1);
angleOrder = tempAngle';
end

【并联机构工作空间分析系列1】 多个圆/圆环求交 得到重叠部分边界 Matlab程序相关推荐

  1. BlogEngine.Net架构与源代码分析系列(转载)

    01.BlogEngine.Net架构与源代码分析系列part1:开篇介绍 02.BlogEngine.Net架构与源代码分析系列part2:业务对象--共同的父类BusinessBase 03.Bl ...

  2. 脑电分析系列 | eeglab汇总

    1 脑电分析系列eeglab教程 eeglab教程系列(1)-安装教程 eeglab教程系列(2)-加载.显示数据 eeglab教程系列(3)-绘制脑电头皮图 eeglab教程系列(4)-绘制通道光谱 ...

  3. 脑电分析系列 | MNE-Python汇总

    1 脑电分析系列MNE-Python教程 [MNE-1]| MNE-Python详细安装与使用(更新) [MNE-2]| MNE中数据结构Raw及其用法简介(更新) [MNE-3]| MNE中数据结构 ...

  4. 脑电分析系列[MNE-Python-19]| 可视化Evoked数据

    在前面我们介绍过Evoked的数据结构以及如何创建Evoked对象: 脑电分析系列[MNE-Python-4]| MNE中数据结构Evoked及其对象创建 Evoked potential(EP)诱发 ...

  5. 脑电分析系列[MNE-Python-5]| Python机器学习算法随机森林判断睡眠类型

    案例介绍 本案例通过对多导睡眠图(Polysomnography,PSG)数据进行睡眠阶段的分类来判断睡眠类型. 训练:对Alice的睡眠数据进行训练: 测试:利用训练结果对Bob的睡眠数据进行测试, ...

  6. 脑电分析系列[MNE-Python-2]| MNE中数据结构Raw及其用法简介(更新)

    Raw对象主要用来存储连续型数据,核心数据为n_channels和times,也包含Info对象. 下面可以通过几个案例来说明Raw对象和相关用法. Raw结构查看: # 引入python库 impo ...

  7. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  8. MyBatis 源码分析系列文章合集

    1.简介 我从七月份开始阅读MyBatis源码,并在随后的40天内陆续更新了7篇文章.起初,我只是打算通过博客的形式进行分享.但在写作的过程中,发现要分析的代码太多,以至于文章篇幅特别大.在这7篇文章 ...

  9. MyBatis 源码分析系列文章导读

    1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...

  10. Spring IOC 容器源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

最新文章

  1. 六十八、完成Vue项目推荐和周末游组件,并使用Ajax发起ajax请求
  2. AMD GPU+VS2010的OpenCL配置
  3. Simulink_Debug的使用
  4. scrapy导入配置文件setting.py,防止运行时找不到文件
  5. BCD与ASCII码互转-C语言实现
  6. 江苏省计算机二级c语言考试知识点,计算机二级考试C语言常考知识点归纳
  7. 利用HttpOnly来防御xss攻击
  8. 群晖NAS教程(十五)、利用Web Station安装typecho博客
  9. TwinCAT 3 马达程序
  10. 服务器宕机监控、检测、报警程序(139绑定手机短信报警)monitor_down.sh
  11. 关闭Win10强制自动更新驱动
  12. ASPxGridViewHelper自定义多表头及合并单元格
  13. 数据结构——图的邻接表实现
  14. Python数据挖掘——烟火图像分类:传统机器学习建模方法与卷积神经网络性能比较
  15. Win10无法更改账户名称怎么办
  16. PowerPC PPC460-S MMU(三 Access Control)
  17. 最好的五款骨传导耳机推荐,双十一必入骨传导蓝牙耳机
  18. 重磅综述|大脑内在神经时间尺度:时间整合与分离
  19. Matlab批量保存图片到指定路径
  20. 小型局域网络搭建(可访问外网)

热门文章

  1. MySQL数据库主从双向同步
  2. Tekla二次开发 第4节 曲梁及双截面梁
  3. php 使用PayPal 支付
  4. 大一html网页制作PPT,HTML网页制作.ppt
  5. angular Meterial错误 Did you add it to @NgModule.entryComponents
  6. 关于JS跨域访问简述
  7. 记录下macbook中maven环境变量配置遇到的问题
  8. 刚做微商引流太慢怎么办?微商没有客源怎么办,微商引流需要注意什么
  9. Java遍历文件夹及图像缩放批处理
  10. Python入门学习十:Python绘图