目录
1.前景介绍
今天上午的数学建模培训王老师介绍的这个数学建模相关的经验真的是让我受益匪浅,让我对于数学建模有了更加清晰的认识,数学建模除了优化类,评价类,预测类问题,还有就是今天的追逐仿真问题,就是在一个坐标系里面去解决问题,下面就是一个简单的案例;
2.题目描述
正方形的四个顶点上面都有一个人,四个人之间相互追逐,这个题目就是想要我们画出来这个追逐的轨迹;(下面可能会使用1,2,3,4分别代表ABCD四个顶点)
3.核心思路
追逐仿真问题核心思路就是把这个连续的问题离散成为一系列的特定的状态;
就是每一次追逐的过程,都会产生一个状态的画面:下面就是一系列的特定的状态(部分截图,方便大家的理解);
就是A向上边走一个步长,B向左边走一个步长,C向下D向右,这个样经过一轮之后就组成了一个下面的新的正方形,然后按照这个逻辑继续进行下去;
4.思路分析
我们可以假设这个边长是1,每一次走0.05,也就是步长为0.05,每次经过一个步长之后重新去计算这个点的坐标和对应的方向向量;
我们首先要确定这4个顶点的坐标,每次更新之后还有去确定这4个顶点的新的坐标,实际上确定的是这4个直线的方向向量;
这个实际上是一个循环,当这4个点里面的某两个之间的距离小于我们的步长的时候,这个循环实际上就会停止,因为这个时候我们再走一步就会相遇了,所以这个时候就需要停止运行了;
最后我们使用plot函数进行绘制动图,绘制出来整个过程的动画,并且使用pause把这个过程逐个展示出来;
5.代码分析
5.1准备工作
我们首先确定这四个点的坐标以及之间的方向向量,设置步长为0.05,DD为记录这个过程中的4个点的坐标的变化情况,并且把这个坐标的相关数据放置在DD矩阵里面去;
DD是一个2*4的矩阵,这个矩阵的每一列代表一个坐标,第一类10就是A点的坐标,11就是B点的坐标,以此类推,相当于这个矩阵的第一行就是横坐标,第二行就是纵坐标;
V表示的就是方向向量,这个后面的投影也是使用的方向向量进行计算的,我们的这个V实际上是有拼接得到的,2-1求解两个点之间的方向向量,3-2,4-3同样可以求解,这个时候没有办法去求解1-4就是1,4这两个点之间的
这个就是第一次计算得到的方向向量结果展示:
5.2设置循环
我们假设这个循环次数是1000次,实际上肯定是不会进行这么多次的循环,我们中间满足某一个条件的时候会终止这个循环;
dx就是每走一步在x方向上面的变化量L就是步长,后面乘以的相当于就是cos角,就是这个步长在x方向上面的投影,cos的计算就是△x/(△x^2+△y^2)^0.5,这个实际上就是我们的cos的计算过程,就是利用的向量的知识,同理这个dy就是计算的在y方向上面的投影长度;
计算出来这个dx,dy之后,我们要更新这个位置坐标,我们原来的位置坐标是放置在D这个矩阵里面的,我们把这个D+dxy实际上得到的就是走一步之后得到的新的位置坐标;
得到新的坐标,我们的这个新的方向向量也是需要进行更新的,V就是更新的新的方向向量,DD记录每一次这个里面的4个顶点的坐标的具体数值;
5.3终止循环
上面也介绍到了,两个顶点之间的距离小于步长L的时候这个循环就会停止,我们计算两个顶点之间的距离,可以自己去写一个式子(我下面的注释就是的),也可以调用norm函数,参数使用减号进行连接,两个方式是等效的,选择合适的即可;
5.4绘制图形
plot的第一个参数就是x坐标,第二个参数就是y坐标,但是我们的D(1,:)和D(2,:)只能关联上12,23,34,这个14没有建立联系,所以我们使用矩阵的拼接把两个点额外的搞上去;
hold就是新的图形不会覆盖原来的图形;
pause就是每一次绘制完成之后停顿时间为0.1秒,方便我们观察这个过程;
5.5完整代码
cpp
clear;
clc;
D=[1 1 0 0
0 1 1 0];
%%计算方向向量
V=[D(:,2:end)-D(:,1:end-1) D(:,1)-D(:,end)];
%%设定步长大小
L=0.05;
DD=[];
for i=1:1000
%%分别计算xy方向上的投影长度
dx=L*V(1,:)./((V(1,:).^2+V(2,:).^2).^0.5);
dy=L*V(2,:)./((V(1,:).^2+V(2,:).^2).^0.5);
dxy=[dx;
dy];
D=D+dxy;
DD=[DD;D];
%%计算新的方向向量
V=[D(:,2:end)-D(:,1:end-1) D(:,1)-D(:,end)];
%%循环结束条件
if norm(D(:,2)-D(:,1))<=L
break;
end
% if ((D(1,2)-D(1,1)).^2+(D(2,2)-D(2,1)).^2).^0.5<=L
% break;
% end
%%绘制图形
plot([D(1,:) D(1,1)],[D(2,:) D(2,1)],'r');
hold on;
pause(0.1);
end