寻找方程的零点可以等价于寻找两个曲线的交点,因此这里放在一起进行讨论。
思路为:首先对应函数值y
0
,对自变量x进行插值,找出给定区间内所有满足f(x)=y
0
的x值,再令y
0
=0,即可得到方程的零点或者两曲线的交点横坐标。
首先必须找出y=y
0
直线上下交错排列的所有数据点,即(x
k
,y
k
)和(x
k+1
,y
k+1
),在此区间内认为函数y为单调的,可以用逻辑运算加移位来实现。代码如下:
function [x0,y0]=invinterp(x,y,y0)
x=x(:);y=y(:);
n=numel(y);
if y0<min(y) || y0>max(y)
x0=[];y0=[];%不存在则直接退出
below=y<y0;
above=y>=y0;
kth=(below(1:n-1)&above(2:n)) | (above(1:n-1)&below(2:n));
kp1=[false;kth];
alpha=(y0-y(kth))./(y(kp1)-y(kth));
x0=alpha.*(x(kp1)-x(kth))+x(kth);
y0=repmat(y0,size(x0));
以上函数实现给定x,y和y
0
的前提下利用线性插值找出对应y
0
的x值x
0
。
于是利用上面的函数即可实现寻找方程的零点或者曲线的交点。实例如下:
x=linspace(0,10);
y=sin(x);
z=2*cos(3*x);
x0=invinterp(x,y-z,0);
y0=interp1(x,y,x0);
plot(x,y,x,z,x0,y0,'o')
legend('曲线1:y=sin(x)','曲线2:y=2cos(3x)','交点')
http://liufanghit.blog.163.com/blog/static/402192201111141341151/
寻找方程的零点可以等价于寻找两个曲线的交点,因此这里放在一起进行讨论。思路为:首先对应函数值y0,对自变量x进行插值,找出给定区间内所有满足f(x)=y0的x值,再令y0=0,即可得到方程的零点或者两曲线的交点横坐标。首先必须找出y=y0直线上下交错排列的所有数据点,即(xk,yk)和(xk+1,yk+1),在此区间内认为函数y为单调的,可以用逻辑运算加移位来实现。代码如下:funct
该文件基于Duane Hanselman的“
曲线
相交”功能。 它扩展了函数的范围以处理任意线/多边形,这些线/多边形也可能具有垂直线段或具有非增加 x 值的线段。
描述计算两条二维线/多边形的
交点
。
用法[X,Y]=CURVEINTERSECT(H1,H2) 或 [X,Y]=CURVEINTERSECT([H1 H2]) 或[X,Y]=CURVEINTERSECT(X1,Y1,X2,Y2) 或-> (H1,H2) 线对象句柄-> (Xi,Yi) 线的坐标-> (X,Y)
交点
坐标
例子x1=rand(10,1); y1=rand(10,1); x2=rand(10,1); y2=rand(10,1); [x,y]=curveintersect(x1,y1,x2,y2); 情节(x1,y1,'k',x2,y2,'b',x,y,'ro')
matlab
–
找
两条
曲线
交点
并标注于图上的方法
无论是参加数学建模还是其他情况下,我们常常需要利用
matlab
的作图功能去更好的完成论文,这里介绍两种
找
出两条
曲线
的
交点
标注于图上的方法。
第一种方法:应用于两条
曲线
相差较大时
例如题目: 已知函数为y=exp(-0.5*x)*cos(x);
取x在[0,2π] 内1000 个点时的 y 值,同时对数据 y 叠加一个正弦干扰信号得到 y1。画出(x,y)(x,y1)图形并对
交点
标注。
matlab
代码如下:
clear
x=linspace(0,2*pi
曾经思考过曲面求交,结果发现是学术界的一个难题,并且也想出了一个当前广泛使用方法原理一样的近似解法(追踪法)。当然网上也有很多方法,只不过那些方法非常粗糙,无非就是meshgrid出离散网格,比较两曲面在某位置的坐标是否在某一精度范围内,然后标记显示之。这个方法仅仅当离散网格非常细的时候才比较精确。除此之外,还有个非常严重的问题:上面的“精度范围”不是你随心所欲给的,而且也没规律寻
找
,当给得不恰当的时候,在格点处两曲面点作比较,会出很多个符合要求的点,或者一个也没有。这样就会使得交线非常曲折,甚至断裂等,严重影响精确度。
———————————————————分割线————————————————————————
当然,既然有曲面求交,那么也有
曲线
求交,其基本结构就是两
曲线
求交。只是
曲线
求交问题,事先得澄清一些注意点:
1. 数学分析层面求两
曲线
交点
,其实就是方程组求解;
2. “
曲线
”概念包括“直线”(处处曲率半径为无穷大);
3.
Matlab
的重点是离散点 矩阵运算,因此所有运算都是基于离散的,因而这里的
曲线
并不是绝对光滑的。
4. 近似试探与未知函数表达式。
对于1,我想说的是,如果你想要求得两
曲线
的精确
交点
,并且一个不漏,那就直接求解方程组,不用看本帖下文;
对于2,直线在
Matlab
里面是
两个
点确定,因此
交点
如果是一段线(无穷个点)的情况,可能只是显示两端点为
交点
;
对于3,很简单的例子,参数方程 x=cos,y=sin 在数学分析(即连续空间)层面上是个圆,但是如果你在离散t的时候,间距比较大,那么最后
Matlab
绘制的图像不是圆,而是正多边形了。因此,此时我们讨论
曲线
交点
是这个离散点连线的图形与其他图形的
交点
,而非圆与其他
交点
。这也是我在标题中加了“离散点连成”的修饰词,防止被误会。
对于4,既然是求
曲线
交点
,那么本方法可以作为求方程组的近似解。当然,如果离散点够多,解的精确度可以保证,不过不能保证一个不漏。另外就是,对于一组离散点构成的
曲线
,很难知道它们的解析表达式,因此想通过非线性方程组求解的方法来求
交点
,就不大可能了(不过你可以用
曲线
拟合出函数解析式),因此,本帖的方法将会是一个较为有效求
交点
的方法。
废话了那么多,下面就说说
曲线
求
交点
的方法吧。除了求解方程组,很多人想到的方法就是“离散点 判断距离是否足够接近”,这个方法原理跟引言中曲面求交的方法是一样的。因此缺点也是一样的——太粗糙了。网上这种方法的代码也很多,这里就不上了。
下面将阐述我的方法以及给出例子代码。
我有两种思路,一种是高级绘图层面的(不涉及到底层操作),一种是底层的。我只给出了第一种的代码,因为我不会底层操作。
思路一:既然
matlab
曲线
绘图是通过有序离散点依次连线形成,也就是说,通过“以直代曲”的过程,那么
曲线
交点
无非就是离散点(结点)或者两线段
交点
。这比上面直接用
交点
附近的结点替代
交点
的方法要精确得多了。而两直线
交点
很容易求,只要知道四个点坐标,那么
交点
精确坐标自然可以表示出来。这就是求
交点
的原理。只是还有一些细节处理和要注意的地方,我会留到后面再详细说。
思路二:仔细观察两
曲线
交点
的特性,很容易发现,其实
交点
就是操作系统底层绘图重叠的那些像素点。因此,只要给要绘制的像素点做个标记,将那些重合的点突出显示(比如换个颜色),那么就相当于显示出
交点
了。这种方法由于是本质性的,因此不会遗漏任何
交点
,而且精确度极高,适用范围广。
Matlab
提供的plot plot3 surf等绘图函数都属于高级绘图,底层绘图(或称低级绘图)只有line surface以及patch等少数函数。但是,这里的“底层”并非真正的底层,因为它还是经过封装了的,而C 的MFC里面直接用刷子绘图,那才是依靠操作系统完成的真正的“底层”绘图操作(包括所有窗口都是操作系统绘制的)。这里扯远了,想要说明的就是底层绘图的概念而已。只是我不会用
matlab
实现这些底层绘图。
上面说了思路,下面就详细说说一些注意点和需要处理的细节。
为了算法的健壮性,就必须考虑各种奇异的情况,防止bug。我们要考虑
曲线
有分支(很多代数
曲线
是这样的,代数几何里面研究的东西)、间断跳跃(有绝对值函数或者存在渐近线情况)、首尾是
交点
、在切点相交,等等这些情况。而且对于定位
交点
处附近的四个最近端点也是个问题(因为这里存在一个情况,如果
曲线
1上的一条线段与
曲线
2上的两条或者以上的线段相交,我的程序因为这个问题没能有效解决,出现在一些非常特殊的情况下会遗漏部分
交点
)。上面的情况如果不考虑,那么你的程序就会出现各种各样的问题。
对于通常情况,我考虑使用变号法则来判断
交点
(也就是高数里面“连续函数变号端点内存在
零点
”),对于上面说的特殊情况,那么预先处理,比如先看是否存在eps内的,或者为零的结点,有则直接记录,没有的话,通过两线段求交来确定
交点
。至于遍历顺序的问题,为了简便,我指考虑两
曲线
离散点个数相同的情况(因为不同的话,会出现一些无法处理的情况),而且优先考虑离散点的坐标值中x或者y都相同的情况(比如x=0:0.1:pi; y1=sin, y2=x.^2这两条
曲线
的x值相同分布)。
下面是
曲线
y=cos.*exp)与y2=sin.^2 cos在[0:pi/18:2*pi]区间内的
交点
的代码:
注意:我没有写成接口的形式,虽然对于比那些较懒的人来说不太方便,但是这样做是为了让你能更好弄懂原理,并能自己改造代码。因此,下面的代码可以稍作修改,就能解决别的
曲线
求
交点
。这样,不愿思考的懒人就没法达到自己的目的了~% 绘制两离散
曲线
的
交点
% 注意:
% 1. 这里的“
交点
”指的是离散点连线绘出的图形的
交点
,而非函数或者方程理论分析上的
交点
,
% 因此,这个程序不能作为求根来用。
% 2. 要求两
曲线
的离散点的个数一样。
% 3.
两个
曲线
出现参数方程的话,大多数情况正常。但是经测试发现,对于某些非常特殊的情况会出现bug,
% 除非调用ezplot的数据(xdata,ydata)。
%
% by kastin @Mar 21, 2012
clear;
debug=false; %关闭显示求
交点
过程
%
曲线
1
x=0:pi/18:2*pi;
y=cos.*exp);
%
曲线
2
[x1 N]=sort; %此处对于C1参数方程,C2为显式函数;或者均为参数方程时候有用
% 下面几句代码在本个案下没有什么特殊作用,但是当出现参数方程的时候,下面的方法改动一下就会有用。
y1=sin.^2 cos; %用于作图
x2=x;
y2=sin.^2 cos; %用于寻点
h=plot;
y<=eps)=0; y20;
neg=cy<=0;
%确定变号位置
fro=diff~=0; %变号的前导位置
rel=diff~=0; %变号的尾巴位置
zpf=find; %记录索引
zpr=find 1; %记录索引
zpfr=[zpf; zpr];
hold on
% 观看求
交点
过程
if debug, hp=plot,y,'r.-',x2,y2,'g.-'); end
%线性求交
x0=.*-y)-x.*-y))./ y2-y-y2);
y0=y ).*-y)./-x);
if any), y0=y2; end
%加入已经判断为零的位置
x0=[x<=eps) x0].';
y0=[y<=eps) y0].';
hc=plot; %绘制
交点
if debug, legend;hp],'C1','C2','
交点
','微线段1','微线段2',0); end
legend
xlabel, ylabel, zlabel;
title
axis equal
hold off
disp
disp) %排除重复的点复制代码经测试十几种奇怪的
曲线
相交(包括参数方程形式的
曲线
),目前发现上述代码的方法有四种情况会出现遗漏一
两个
交点
。(其实上面代码本意是求显式函数的
曲线
交点
,或者未知表达式的离散点
曲线
的
交点
,并未针对参数方程,隐函数方程做优化,但是可以凑合着用用。)
x = 16*sin(t).^3;
y = 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t);
plot(x,y,'r','LineWidth',2)
希望这对您有帮助!