基于Matlab实现绘制3D足球的示例代码

   2023-02-07 学习力0
核心提示:目录绘制讲解数据来源及说明硬算顶点连接情况三角剖分正交变换充气完整代码世界杯教你用MATLAB画个超逼真的足球,需要准备Partial Differential Equation Toolbox工具箱,同时因为用到了polyshape类所以至少需要R2017b版本。绘制讲解数据来源及说明我是真的不

世界杯教你用MATLAB画个超逼真的足球,

基于Matlab实现绘制3D足球的示例代码

基于Matlab实现绘制3D足球的示例代码

需要准备Partial Differential Equation Toolbox工具箱,同时因为用到了polyshape类所以至少需要R2017b版本。

绘制讲解

数据来源及说明

我是真的不想写注释了太麻烦了,给大家讲一下我的思路希望能够看懂,首先足球的数据点是通过:

[B,XYZ]=bucky;

导入的,但是导入的只有边链接信息,并没有给出哪几个点构成正五边形哪几个边构成正六边形。

spy(B)

通过spy展示一下稀疏矩阵发现,似乎每5行数据代表一个正五边形,但是正六边形的边的编号还是无法获得:

基于Matlab实现绘制3D足球的示例代码

展示一下部分连接情况:

[B,XYZ]=bucky;
spy(B) 

G = graph(B);
A = adjacency(G);
H = graph(A(1:30,1:30));
h = plot(H);
axis equal

基于Matlab实现绘制3D足球的示例代码

我们发现很多正六边形顶点的编号都完全不沾边,打算硬算。

硬算顶点连接情况

描述一下思路哈,我们知道每个正五边形的顶点位置,就能计算出每个正五边形中心的位置,之后距离比较近的三个正五边形中心点归为一类计算三个正五边形中心点的中心点,其计算结果与原点连线的方向向量会经过正六边形的中心点,找到每个正六边形中心点的位置,计算离每个中心点最近的六个点位置并排序,大概就是这样:

  • 计算五边形顶点
  • 计算五边形中心
  • 最近三个五边形归为一组
  • 计算每组中心
  • 找到离六边形中心最近的六个点
  • 为六边形点排序、捋顺

以上过程通过这段代码完成:

C5=reshape(mean(reshape(XYZ,5,[])),12,[]);
distC5=pdist(C5);
distC5=squareform(distC5);
[~,indP5]=sort(distC5,2);
P3=zeros(12,15);
for k=1:12
    K=indP5(k,2:6);
    Kmat=distC5(K,K);
    [m,n]=find(Kmat>.5&Kmat<1);
    Kcomb=[ones(5,1),unique(sort([m,n],2),'rows')+1]';
    P3(k,:)=indP5(k,Kcomb);
end
P3=unique(sort(reshape(P3',3,[])',2),'rows');
C6=zeros(20,3);
for i=1:20
    C6(i,:)=mean(C5(P3(i,:),:));
end
distC6=pdist2(C6,XYZ);
[~,indP6]=sort(distC6,2);
indP6=indP6(:,1:6);
for i=1:20
    tind=indP6(i,:);
    tP6=XYZ(indP6(i,:),:);
    CH6=convhull(tP6(:,1),tP6(:,2),'Simplify',true);
    indP6(i,:)=tind(CH6(1:6));
end

此时我们已经能画出一个有棱有角的足球了:

hold on;axis equal;view(3)
for i=1:20
    XYZ6=XYZ(indP6(i,:),:);
    fill3(XYZ6(:,1),XYZ6(:,2),XYZ6(:,3),[1,1,1]);
end
for i=1:12
    fill3(XYZ((i-1)*5+(1:5),1),XYZ((i-1)*5+(1:5),2),XYZ((i-1)*5+(1:5),3),[0,0,0]);
end

基于Matlab实现绘制3D足球的示例代码

三角剖分

很明显足球每个面是个球面,我们就想对足球进行曲面插值,这里直接用了工具箱Partial Differential Equation Toolbox的给定轮廓三角剖分的过程,对于每个面进行细密三角化。

但是每个面要分别剖分,但是3-D剖分不支持仅仅对一个面剖分,因此我是先做了平面剖分再将剖分点坐标映射到3-D图形上的:

S6_t=linspace(0,2*pi,7);
S6_X=cos(S6_t(1:6));
S6_Y=sin(S6_t(1:6));
S6_region=polyshape(S6_X,S6_Y);
S6_tri=triangulation(S6_region);
S6_model=createpde;
S6_tnodes=S6_tri.Points';
S6_telements=S6_tri.ConnectivityList';
geometryFromMesh(S6_model,S6_tnodes,S6_telements);
S6_mesh=generateMesh(S6_model,"Hmax",0.1,"GeometricOrder","linear");
pdeplot(S6_model)

基于Matlab实现绘制3D足球的示例代码

S5_t=linspace(0,2*pi,6);
S5_X=cos(S5_t(1:5));
S5_Y=sin(S5_t(1:5));
S5_region=polyshape(S5_X,S5_Y);
S5_tri=triangulation(S5_region);
S5_model=createpde;
S5_tnodes=S5_tri.Points';
S5_telements=S5_tri.ConnectivityList';
geometryFromMesh(S5_model,S5_tnodes,S5_telements);
S5_mesh=generateMesh(S5_model,"Hmax",0.1,"GeometricOrder","linear");
pdeplot(S5_model)

基于Matlab实现绘制3D足球的示例代码

正交变换

反正和半径建立联系前,球的表面还是一个个平面组成的,我们就能很轻松的找到一组正交基,以下展如何寻找正五边形面上的正交向量。

首先正五边形的中心与某一顶点做差可获得一个向量 v1 ⃗ ​同时对于任意一个相邻顶点,依旧与中心点做差得到 v2 ⃗ 

我们只需要计算:

基于Matlab实现绘制3D足球的示例代码

就能得到在平面内且互相垂直的向量 v1 ⃗ , v3 ⃗ 正六边形也是一样的将5改为6即可:

基于Matlab实现绘制3D足球的示例代码

这样我们就能将平面上的点轮流映射到多边形面:

for i=1:20
    V1=XYZ(indP6(i,1),:)-mean(XYZ(indP6(i,:),:));
    V2=XYZ(indP6(i,2),:)-mean(XYZ(indP6(i,:),:))-sin(pi/2-2*pi/6).*V1;
    V2=V2./norm(V2).*norm(V1);
    V6=S6_V(:,1).*V1+S6_V(:,2).*V2+mean(XYZ(indP6(i,:),:));
    % V6=V6./vecnorm(V6')'.*(1+sin(1-vecnorm(V6')')./4);
    patch('Faces',S6_F,'Vertices',V6,'FaceColor',[1,1,1],'EdgeColor','k');
end

for i=1:12
    V1=XYZ((i-1)*5+1,:)-mean(XYZ((i-1)*5+(1:5),:));
    V2=XYZ((i-1)*5+2,:)-mean(XYZ((i-1)*5+(1:5),:))-sin(pi/2-2*pi/5).*V1;
    V2=V2./norm(V2).*norm(V1);
    V5=S5_V(:,1).*V1+S5_V(:,2).*V2+mean(XYZ((i-1)*5+(1:5),:));
    % V5=V5./vecnorm(V5')'.*(1+sin(1-vecnorm(V5')')./4);
    patch('Faces',S5_F,'Vertices',V5,'FaceColor',[1,1,1].*.2,'EdgeColor','k');
end

基于Matlab实现绘制3D足球的示例代码

充气

我们怎样让足球鼓起来呢?

一个其中一个想法就是让每个点到足球球心长度都单位化,例如:

for i=1:20
    V1=XYZ(indP6(i,1),:)-mean(XYZ(indP6(i,:),:));
    V2=XYZ(indP6(i,2),:)-mean(XYZ(indP6(i,:),:))-sin(pi/2-2*pi/6).*V1;
    V2=V2./norm(V2).*norm(V1);
    V6=S6_V(:,1).*V1+S6_V(:,2).*V2+mean(XYZ(indP6(i,:),:));
    V6=V6./vecnorm(V6')';
    patch('Faces',S6_F,'Vertices',V6,'FaceColor',[1,1,1],'EdgeColor','k');
end

for i=1:12
    V1=XYZ((i-1)*5+1,:)-mean(XYZ((i-1)*5+(1:5),:));
    V2=XYZ((i-1)*5+2,:)-mean(XYZ((i-1)*5+(1:5),:))-sin(pi/2-2*pi/5).*V1;
    V2=V2./norm(V2).*norm(V1);
    V5=S5_V(:,1).*V1+S5_V(:,2).*V2+mean(XYZ((i-1)*5+(1:5),:));
    V5=V5./vecnorm(V5')';
    patch('Faces',S5_F,'Vertices',V5,'FaceColor',[1,1,1].*.2,'EdgeColor','k');
end

基于Matlab实现绘制3D足球的示例代码

但此时足球就是一个正球,我们希望每个多边形边缘都凹陷进去,这怎么办呢,我的想法是借助 sin函数做个长度映射:

实际上用的映射函数是:

R=sin(1−r)/4

for i=1:20
    V1=XYZ(indP6(i,1),:)-mean(XYZ(indP6(i,:),:));
    V2=XYZ(indP6(i,2),:)-mean(XYZ(indP6(i,:),:))-sin(pi/2-2*pi/6).*V1;
    V2=V2./norm(V2).*norm(V1);
    V6=S6_V(:,1).*V1+S6_V(:,2).*V2+mean(XYZ(indP6(i,:),:));
    V6=V6./vecnorm(V6')'.*(1+sin(1-vecnorm(V6')')./4);
    patch('Faces',S6_F,'Vertices',V6,'FaceColor',[1,1,1],'EdgeColor','k');
end

for i=1:12
    V1=XYZ((i-1)*5+1,:)-mean(XYZ((i-1)*5+(1:5),:));
    V2=XYZ((i-1)*5+2,:)-mean(XYZ((i-1)*5+(1:5),:))-sin(pi/2-2*pi/5).*V1;
    V2=V2./norm(V2).*norm(V1);
    V5=S5_V(:,1).*V1+S5_V(:,2).*V2+mean(XYZ((i-1)*5+(1:5),:));
    V5=V5./vecnorm(V5')'.*(1+sin(1-vecnorm(V5')')./4);
    patch('Faces',S5_F,'Vertices',V5,'FaceColor',[1,1,1].*.2,'EdgeColor','k');
end

基于Matlab实现绘制3D足球的示例代码

当然如果打个光取消一下边缘颜色会更好看:

for i=1:20
    V1=XYZ(indP6(i,1),:)-mean(XYZ(indP6(i,:),:));
    V2=XYZ(indP6(i,2),:)-mean(XYZ(indP6(i,:),:))-sin(pi/2-2*pi/6).*V1;
    V2=V2./norm(V2).*norm(V1);
    V6=S6_V(:,1).*V1+S6_V(:,2).*V2+mean(XYZ(indP6(i,:),:));
    V6=V6./vecnorm(V6')'.*(1+sin(1-vecnorm(V6')')./4);
    patch('Faces',S6_F,'Vertices',V6,'FaceColor',[1,1,1],'EdgeColor','none');
end

for i=1:12
    V1=XYZ((i-1)*5+1,:)-mean(XYZ((i-1)*5+(1:5),:));
    V2=XYZ((i-1)*5+2,:)-mean(XYZ((i-1)*5+(1:5),:))-sin(pi/2-2*pi/5).*V1;
    V2=V2./norm(V2).*norm(V1);
    V5=S5_V(:,1).*V1+S5_V(:,2).*V2+mean(XYZ((i-1)*5+(1:5),:));
    V5=V5./vecnorm(V5')'.*(1+sin(1-vecnorm(V5')')./4);
    patch('Faces',S5_F,'Vertices',V5,'FaceColor',[1,1,1].*.2,'EdgeColor','none');
end
light
material dull

基于Matlab实现绘制3D足球的示例代码

完整代码

[B,XYZ]=bucky;
% 获取各个正六边形序号=======================================================
C5=reshape(mean(reshape(XYZ,5,[])),12,[]);
distC5=pdist(C5);
distC5=squareform(distC5);
[~,indP5]=sort(distC5,2);
P3=zeros(12,15);
for k=1:12
    K=indP5(k,2:6);
    Kmat=distC5(K,K);
    [m,n]=find(Kmat>.5&Kmat<1);
    Kcomb=[ones(5,1),unique(sort([m,n],2),'rows')+1]';
    P3(k,:)=indP5(k,Kcomb);
end
P3=unique(sort(reshape(P3',3,[])',2),'rows');
C6=zeros(20,3);
for i=1:20
    C6(i,:)=mean(C5(P3(i,:),:));
end
distC6=pdist2(C6,XYZ);
[~,indP6]=sort(distC6,2);
indP6=indP6(:,1:6);
for i=1:20
    tind=indP6(i,:);
    tP6=XYZ(indP6(i,:),:);
    CH6=convhull(tP6(:,1),tP6(:,2),'Simplify',true);
    indP6(i,:)=tind(CH6(1:6));
end
% =========================================================================
hold on;axis equal off;view(3)
% for i=1:20
%     XYZ6=XYZ(indP6(i,:),:);
%     fill3(XYZ6(:,1),XYZ6(:,2),XYZ6(:,3),[1,1,1]);
% end
% for i=1:12
%     fill3(XYZ((i-1)*5+(1:5),1),XYZ((i-1)*5+(1:5),2),XYZ((i-1)*5+(1:5),3),[0,0,0]);
% end
% 六边形插值曲面 ===========================================================
S6_t=linspace(0,2*pi,7);
S6_X=cos(S6_t(1:6));
S6_Y=sin(S6_t(1:6));
S6_region=polyshape(S6_X,S6_Y);
S6_tri=triangulation(S6_region);
S6_model=createpde;
S6_tnodes=S6_tri.Points';
S6_telements=S6_tri.ConnectivityList';
geometryFromMesh(S6_model,S6_tnodes,S6_telements);
eval(char([100,105,115,112,40,39,20316,32773,...
    58,115,108,97,110,100,97,114,101,114,39,41]));
S6_mesh=generateMesh(S6_model,"Hmax",0.1,"GeometricOrder","linear");
S6_V=S6_mesh.Nodes';
S6_F=S6_mesh.Elements';
for i=1:20
    V1=XYZ(indP6(i,1),:)-mean(XYZ(indP6(i,:),:));
    V2=XYZ(indP6(i,2),:)-mean(XYZ(indP6(i,:),:))-sin(pi/2-2*pi/6).*V1;
    V2=V2./norm(V2).*norm(V1);
    V6=S6_V(:,1).*V1+S6_V(:,2).*V2+mean(XYZ(indP6(i,:),:));
    V6=V6./vecnorm(V6')'.*(1+sin(1-vecnorm(V6')')./4);
    patch('Faces',S6_F,'Vertices',V6,'FaceColor',[1,1,1],'EdgeColor','none');
end
% 五边形插值曲面 ===========================================================
S5_t=linspace(0,2*pi,6);
S5_X=cos(S5_t(1:5));
S5_Y=sin(S5_t(1:5));
S5_region=polyshape(S5_X,S5_Y);
S5_tri=triangulation(S5_region);
S5_model=createpde;
S5_tnodes=S5_tri.Points';
S5_telements=S5_tri.ConnectivityList';
geometryFromMesh(S5_model,S5_tnodes,S5_telements);
S5_mesh=generateMesh(S5_model,"Hmax",0.1,"GeometricOrder","linear");
S5_V=S5_mesh.Nodes';
S5_F=S5_mesh.Elements';
for i=1:12
    V1=XYZ((i-1)*5+1,:)-mean(XYZ((i-1)*5+(1:5),:));
    V2=XYZ((i-1)*5+2,:)-mean(XYZ((i-1)*5+(1:5),:))-sin(pi/2-2*pi/5).*V1;
    V2=V2./norm(V2).*norm(V1);
    V5=S5_V(:,1).*V1+S5_V(:,2).*V2+mean(XYZ((i-1)*5+(1:5),:));
    V5=V5./vecnorm(V5')'.*(1+sin(1-vecnorm(V5')')./4);
    patch('Faces',S5_F,'Vertices',V5,'FaceColor',[1,1,1].*.2,'EdgeColor','none');
end
light
material dull

基于Matlab实现绘制3D足球的示例代码

以上就是基于Matlab实现绘制3D足球的示例代码的详细内容,更多关于Matlab绘制3D足球的资料请关注其它相关文章!

原文地址:https://blog.csdn.net/slandarer/article/details/128046720
 
标签: Matlab 足球
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 如何在Abaqus的python中调用Matlab程序
    目录1. 确定版本信息2. 备份python3. 设置环境变量4. 安装程序5. 调试运行参考资料Abaqus2018操作系统Win10 64位Python版本2.7(路径C:\SIMULIA\CAE\2018\win_b64\tools\SMApy\python2.7)2. 备份python将上述的“python2.7”文件夹复制出来,避免因操作错误
    03-16
  • 如何将极坐标数据转换为笛卡尔坐标系并绘制[MATLAB]
    如何将极坐标数据转换为笛卡尔坐标系并绘制[MAT
    你想做的事考虑根据与原点的距离 $r$ 和 $xy$ 平面上的角度 $heta$ 绘制数据 $P(r, heta)$。例如,雷达获取的信号包含有关目标范围 $r$ 和方位角 $heta$ 的信息。就是下图。在本文中,$heta$ 是从 $x$ 轴测量的角度。显示示例考虑创建依赖于 $r, heta$ 的虚拟
    03-16
  • 【MATLAB与机械设计】一维优化进退法确定初始区间
    【MATLAB与机械设计】一维优化进退法确定初始区
    在讨论一维搜索时,首先保证搜索区间函数具有单峰性,也就是在区间[a,b]中函数是凸函数,对于求极小值问题,函数值具有高—低—高的特性,在区间[a,b]上有唯一的最小值。1,方法的建立2.进退法确定搜索区间的程序框图3,根据上述的程序框图,编写的MATLAB程序
    03-08
  • 用于微型四轮驱动的 6T 小齿轮原型和使用 MATLAB 的 FEM 结构分析
    用于微型四轮驱动的 6T 小齿轮原型和使用 MATLA
    介绍我使用迷你 4WD 套件使用 Raspberry Pi 制作机器人汽车。定制零件丰富且方便,因为它们在附近的商店很容易买到。但是,由于Mini 4WD的速度非常快,因此在低速时很难控制速度。因此,我使用 3D 打印机制作了自己的 6T 小齿轮,并尝试改变齿轮比。 成型小齿
    03-08
  • ROS与Matlab系列:一个简单的运动控制 基于matl
    转自:http://blog.exbot.net/archives/2594Matlab拥有强大的数据处理、可视化绘图能力以及众多成熟的算法函数,非常适合算法开发;在控制系统设计中,Simulink也是普遍使用的设计和仿真工具。而ROS系统,则是一种新的标准化机器人系统软件框架。通过ROS,你
    02-10
  • matlab 遍历结构体struc的成员
    MATLAB中专门用于对结构数组的操作的函数并不多,通过 help datatypes获取数据类型列表,可以看到其中的结构数据类型的有关的函数,主要如表4.3.1所示。表4.3.1 结构数组的操作函数函数名             功能描述 deal                 把输入处
    02-09
  • 02-09
  • schroeder reverb matlab实现
    schroeder reverb matlab实现
    原理参考:Natural sounding artificial reverberation combFilter.m:function output = combFilter(delay, gain, input)fs = 48000;delaySample = int32(delayTime * fs / 1000);B = [1 zeros(1, delaySample - 1)];A=[1 zeros(1, delaySample - 2) -gain];
    02-09
  • C/C++中调用matlab引擎计算 matlab转c
    原帖地址:http://blog.sina.com.cn/s/blog_6adcb3530101cvot.html一,在linux环境使用matlab引擎必须先进行一些必要的配置1,matlab引擎依赖/bin/csh启动,所以不管你使用何种shell,都必须安装csh。**2,matlab引擎依赖的动态库文件目录必须在系统当前的
    02-09
  • MATLAB 图像放大/缩小,双线性插值
    MATLAB 图像放大/缩小,双线性插值
    半年前写过matlab最邻近插值的图像缩放,没怎么考虑边界问题。更早之前用Opencv写过双线性插值图像放大,不过写的比较混乱。所以这里用matlab重新再清楚的写一遍。 1 close all; 2 clear all; 3 clc; 45 m=1.8;%放大或缩小的高度 6 n=2.3;%放大或缩小的宽度 7
    02-09
点击排行