【并联机构工作空间分析系列1】 多个圆/圆环求交 得到重叠部分边界 Matlab程序
目录
- 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 求交点
首先考虑最一般的情况,及两圆相交,有两个交点。如何求相交点呢?
第一种方法是联立两圆方程求解,这种方法比较暴力,鄙人喜欢温柔一点的。
第二种方式是几何方法:
- 求圆心向量AB与X轴夹角θ
- 求向量AC与向量AB的夹角α
联立方程,求出AD
AD2+ CD2= r12
DB2+ CD2= r22
r12+ r22=AB2
α=acos(AD/AC)
上述方程没有考虑到∠ACB是否为90°,所以有问题。这里采用余弦定理
α=acos((r12+AB2-r22)/2*r1*AB) - 那么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 操作
需要注意的是,探测点与内外圆的判断是不一样的。
- 对于外圆,重合部分的探测点到该圆圆心的距离应<=该圆半径
- 对于内圆,重合部分的探测点到该圆圆心的距离应>=该圆半径
其他部分都一样
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程序相关推荐
- BlogEngine.Net架构与源代码分析系列(转载)
01.BlogEngine.Net架构与源代码分析系列part1:开篇介绍 02.BlogEngine.Net架构与源代码分析系列part2:业务对象--共同的父类BusinessBase 03.Bl ...
- 脑电分析系列 | eeglab汇总
1 脑电分析系列eeglab教程 eeglab教程系列(1)-安装教程 eeglab教程系列(2)-加载.显示数据 eeglab教程系列(3)-绘制脑电头皮图 eeglab教程系列(4)-绘制通道光谱 ...
- 脑电分析系列 | MNE-Python汇总
1 脑电分析系列MNE-Python教程 [MNE-1]| MNE-Python详细安装与使用(更新) [MNE-2]| MNE中数据结构Raw及其用法简介(更新) [MNE-3]| MNE中数据结构 ...
- 脑电分析系列[MNE-Python-19]| 可视化Evoked数据
在前面我们介绍过Evoked的数据结构以及如何创建Evoked对象: 脑电分析系列[MNE-Python-4]| MNE中数据结构Evoked及其对象创建 Evoked potential(EP)诱发 ...
- 脑电分析系列[MNE-Python-5]| Python机器学习算法随机森林判断睡眠类型
案例介绍 本案例通过对多导睡眠图(Polysomnography,PSG)数据进行睡眠阶段的分类来判断睡眠类型. 训练:对Alice的睡眠数据进行训练: 测试:利用训练结果对Bob的睡眠数据进行测试, ...
- 脑电分析系列[MNE-Python-2]| MNE中数据结构Raw及其用法简介(更新)
Raw对象主要用来存储连续型数据,核心数据为n_channels和times,也包含Info对象. 下面可以通过几个案例来说明Raw对象和相关用法. Raw结构查看: # 引入python库 impo ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- MyBatis 源码分析系列文章合集
1.简介 我从七月份开始阅读MyBatis源码,并在随后的40天内陆续更新了7篇文章.起初,我只是打算通过博客的形式进行分享.但在写作的过程中,发现要分析的代码太多,以至于文章篇幅特别大.在这7篇文章 ...
- MyBatis 源码分析系列文章导读
1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...
- Spring IOC 容器源码分析系列文章导读
1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...
最新文章
- 六十八、完成Vue项目推荐和周末游组件,并使用Ajax发起ajax请求
- AMD GPU+VS2010的OpenCL配置
- Simulink_Debug的使用
- scrapy导入配置文件setting.py,防止运行时找不到文件
- BCD与ASCII码互转-C语言实现
- 江苏省计算机二级c语言考试知识点,计算机二级考试C语言常考知识点归纳
- 利用HttpOnly来防御xss攻击
- 群晖NAS教程(十五)、利用Web Station安装typecho博客
- TwinCAT 3 马达程序
- 服务器宕机监控、检测、报警程序(139绑定手机短信报警)monitor_down.sh
- 关闭Win10强制自动更新驱动
- ASPxGridViewHelper自定义多表头及合并单元格
- 数据结构——图的邻接表实现
- Python数据挖掘——烟火图像分类:传统机器学习建模方法与卷积神经网络性能比较
- Win10无法更改账户名称怎么办
- PowerPC PPC460-S MMU(三 Access Control)
- 最好的五款骨传导耳机推荐,双十一必入骨传导蓝牙耳机
- 重磅综述|大脑内在神经时间尺度:时间整合与分离
- Matlab批量保存图片到指定路径
- 小型局域网络搭建(可访问外网)