matlab画三维动态魔方/旋转魔方/旋转立方体(代码片段)

嗑药的皮皮虾 嗑药的皮皮虾     2022-12-03     285

关键词:

以下是我的思路

先了解几个重要的函数

patch()函数

原理:点按顺序连成封闭多边形。

使用:

point_sequence=[1,2,3,4]; %点连接的顺序
square_xyz=[3,1,3;1,1,3;1,-1,3;3,-1,3]; %三维坐标4x3矩阵
patch('Faces',point_sequence,'Vertices',square_xyz,'FaceColor','blue');
axis([-3,3,-3,3,-3,3]);%坐标系范围
view(3);

rotx()、roty()、rotz()函数

作用:生成三阶旋转矩阵,例如点A以x为轴逆时针旋转90°得到点B,旋转矩阵为Q,则B=QA,A,B为列向量。rotx(theta);%theta为逆时针旋转角度

使用:

A = [1,1,1]';
Q=rotx(90);
B=Q*A

>>B =
     1
    -1
     1

如何实现旋转

用patch()函数生成patch对象句柄,用句柄查看patch对象的属性,使用get()函数获取坐标属性值,使用set()函数重新设置坐标矩阵从而实现旋转。

例如将蓝色正方形绕x轴旋转45°,程序如下:

point_sequence=[1,2,3,4]; %点连接的顺序
square_xyz=[3,1,3;1,1,3;1,-1,3;3,-1,3]; %三维坐标4x3矩阵,行向量坐标

axis([-3,3,-3,3,-3,3]);%坐标系范围
xlabel('X');
ylabel('Y');
zlabel('Z');
view(3);%三维视角
patch_handles=patch('Faces',point_sequence,'Vertices',square_xyz,'FaceColor','blue');
Vertices=get(patch_handles,'Vertices') %得到三维坐标4x3矩阵,行向量坐标
R = rotx(45); %绕x轴旋转45°生成旋转矩阵
Vertices = (R*Vertices')'; %得到旋转后的矩阵
pause(1); %暂停1秒
set(patch_handles,'Vertices',Vertices); %设置坐标矩阵

效果:

确定三维坐标

如何确定魔方6个面共54个色卡,每个色块4个顶点的坐标呢?如果一个一个点确定坐标,然后得到一个一个色块的4x3矩阵(行向量),工程量太大也容易出错,而且不易修改尺寸,这里我提供一个方法。

以魔方的正中心为原点(0,0,0),通过单轴坐标平移得到6个面的中心点坐标,取一个面的中心点坐标通过双轴坐标平移得到每个色块的中心点坐标,再取一个色块的中心点坐标通过双轴坐标平移得到色块4个顶点的坐标。双轴坐标平移都是有规律的。

取一个色块边长为2个单位,因为是双轴坐标平移有一个坐标轴是不变的,所以下面这两个全局变量是4x2矩阵(行向量)。

global anticlockwise_4point_xyxzyz %逆时针4个点,逆时针即夹角增大的方向
anticlockwise_4point_xyxzyz=[1,1;-1,1;-1,-1;1,-1];
global anticlockwise_9point_xyxzyz %逆时针9个点,最后一个坐标原点
anticlockwise_9point_xyxzyz=[2,0;2,2;0,2;-2,2;-2,0;-2,-2;0,-2;2,-2;0,0];

编写3个函数

函数一:一个中心点生成9个中心点

%双轴坐标平移,得到每个面的9个中心点,最后一个是中心块的坐标
function central_9point_xyz=get_central_9point_xyz_fun(xyz_axis) 
global anticlockwise_9point_xyxzyz;
temp=anticlockwise_9point_xyxzyz;
central_9point_xyz=ones(9,3).*3;%原点(0,0,0)向某个轴正方向移动3个单位
switch xyz_axis
    case '+x' %垂直+x轴的面上的点坐标平移
        central_9point_xyz(:,2:3)=temp;
    case '-x'
        central_9point_xyz=-central_9point_xyz; %负方向移动3个单位
        central_9point_xyz(:,2:3)=temp;        
    case '+y'
        central_9point_xyz(:,1)=temp(:,1);
        central_9point_xyz(:,3)=temp(:,2);
    case '-y'
        central_9point_xyz=-central_9point_xyz;
        central_9point_xyz(:,1)=temp(:,1);
        central_9point_xyz(:,3)=temp(:,2);
    case '+z'
        central_9point_xyz(:,1:2)=temp;
    case '-z'
        central_9point_xyz=-central_9point_xyz;
        central_9point_xyz(:,1:2)=temp;       
end
end

 函数二:一个中心点生成色块4个顶点

%双轴坐标平移,一个色块的中心点得到色块4个顶点
function square_4point_xyz=get_square_4point_xyz_fun(xyz_axis,central_point_xyz) 
global anticlockwise_4point_xyxzyz
temp=anticlockwise_4point_xyxzyz;
increment=central_point_xyz; %中心点为偏移量
square_4point_xyz=zeros(4,3); %色块的坐标矩阵
switch xyz_axis
    case '+x'
        square_4point_xyz(:,2:3)=temp;
    case '-x'
        square_4point_xyz=-square_4point_xyz;
        square_4point_xyz(:,2:3)=temp;        
    case '+y'
        square_4point_xyz(:,1)=temp(:,1);
        square_4point_xyz(:,3)=temp(:,2);
    case '-y'
        square_4point_xyz=-square_4point_xyz;
        square_4point_xyz(:,1)=temp(:,1);
        square_4point_xyz(:,3)=temp(:,2);
    case '+z'
        square_4point_xyz(:,1:2)=temp;
    case '-z'
        square_4point_xyz=-square_4point_xyz;
        square_4point_xyz(:,1:2)=temp;       
end
for i=1:4 
    square_4point_xyz(i,:)=square_4point_xyz(i,:)+increment; %每个点加上偏移量
end
end

 函数三:拼成36x3阶矩阵(行向量),包含一个面9个色块的顶点坐标,调用了函数二

%得到一个面九个色块顶点的坐标,36x3阶矩阵(行向量)
function face_9square_xyz=get_face_9square_xyz_fun(xyz_axis,face_central_9point_xyz) 
face_9square_xyz=zeros(36,3);
for i=1:9
    face_9square_xyz((i-1)*4+1:i*4,:)=get_square_4point_xyz_fun(xyz_axis,face_central_9point_xyz(i,:));   
end
end

 旋转魔方一个面的思路

1、句柄

前面举例说了修改patch句柄的'Vertices'属性即顶点坐标可实现色块的移动,可以用一维数组patch_handles存储54个色块的54个句柄,用patch()函数生成句柄,第一个色块的句柄就是patch_handles(1)=patch()。patch_handles为全局变量。

global patch_handles %patch对象句柄
patch_handles=[];

patch_handles(1)=patch('Faces',point_sequence,'Vertices',Uface_9square_xyz(1:4,:),'FaceColor',Uface_color);

2、找要旋转色块句柄的索引

流程为:

确定色块所在平面垂直的坐标轴,如x正半轴表示为'+x'。下面以'+x'为例

用get()函数获取色块句柄的'XData'属性得到四个顶点的x坐标组成的列向量xyz

用find()函数判断列向量xyz中是否存在等于3的元素,因为垂直正半x轴面上的点的x轴坐标必=3

记下索引存储到index数组中

函数如下返回值为索引数组index:

function index=get_index_fun(xyz_axes) %找要旋转色块句柄的索引
global patch_handles
index=[];
XYZData_str='';
compare=0;
switch xyz_axes
    case '+x'
        XYZData_str='XData';
        compare=3;
    case '-x'
        XYZData_str='XData';
        compare=-3;
    case '+y'
        XYZData_str='YData';
        compare=3;
    case '-y'
        XYZData_str='YData';
        compare=-3;
    case '+z'
        XYZData_str='ZData';
        compare=3;
    case '-z'
        XYZData_str='ZData';
        compare=-3;
end
for i=1:54   
    xyz=get(patch_handles(i),XYZData_str);
    f=find(xyz==compare);
    if ~isempty(f)
        index=[index,i];
    end
    if length(index)==21
        break;
    end
end
end

3、设置句柄属性实现旋转

要注意坐标矩阵V与旋转矩阵R相乘后可能出现分数,就不能用某个轴坐标等于3或-3判断色块所在面,需使用四舍五入取整函数对坐标矩阵取整,应该在最后一轮设置坐标属性时取整,因为旋转90°分为9次每次旋转10°实现动态旋转,应该在第9次时对坐标矩阵四舍五入取整,取整早了魔方会缩小。

函数如下:

function rotation_90(xyz_axes,direction) %旋转在xyz_axes轴上的面90°并画色块
global patch_handles
index=get_index_fun(xyz_axes);
L=length(index); %需要旋转21个色块
per_degree=10; %每次旋转10°
time=9; %一共旋转9次
switch xyz_axes
    case '+x'
        R=rotx(per_degree*direction); %绕x轴旋转生成的旋转矩阵R
    case '-x'
        R=rotx(per_degree*direction);
    case '+y'
        R=roty(per_degree*direction);
    case '-y'
        R=roty(per_degree*direction);
    case '+z'
        R=rotz(per_degree*direction);
    case '-z'
        R=rotz(per_degree*direction);
end
for t=1:time-1
    for i=1:L
        V=get(patch_handles(index(i)),'Vertices');%获得4x3坐标矩阵
        V=(R*V')'; %得到旋转后的矩阵
        set(patch_handles(index(i)),'Vertices',V); %画色块
    end
    pause(0.1);
end
%最后一次旋转坐标四舍五入取整
for i=1:L
    V=get(patch_handles(index(i)),'Vertices');%获得4x3坐标矩阵
    V=(R*V')'; %得到旋转后的矩阵
    V=round(V); %非常重要,四舍五入取整
    set(patch_handles(index(i)),'Vertices',V); %画色块
end
end

主函数和运行效果

以下是部分主函数,很多重复的没有贴出来,例如给patch_handles赋值54个句柄。 

clc;
clear;
global patch_handles %patch对象句柄
patch_handles=[];
global point_sequence
point_sequence=[1,2,3,4];
global anticlockwise_4point_xyxzyz %逆时针4个点
anticlockwise_4point_xyxzyz=[1,1;-1,1;-1,-1;1,-1];
global anticlockwise_9point_xyxzyz %逆时针9个点,逆时针即夹角增大的方向
anticlockwise_9point_xyxzyz=[2,0;2,2;0,2;-2,2;-2,0;-2,-2;0,-2;2,-2;0,0];%逆时针8个中心点,加一个(0,0)点
%六个面颜色
Uface_color='y';
Dface_color='w';
Fface_color='b';
Bface_color='g';
Lface_color=[1,0.5,0];%橙色
Rface_color='r';

Uface_central_9point_xyz=get_central_9point_xyz_fun('+z'); %F面9个中心点的坐标
Uface_9square_xyz=get_face_9square_xyz_fun('+z',Uface_central_9point_xyz);

axis([-5,5,-5,5,-5,5]);%坐标系范围
title('魔方');
axis off
view(3);%三维视角

patch_handles(1)=patch('Faces',point_sequence,'Vertices',Uface_9square_xyz(1:4,:),'FaceColor',Uface_color);

pause(1);
rotation_90('+x',1);
rotation_90('+z',-1);
rotation_90('+y',1);
rotation_90('+y',-1);
rotation_90('+z',1);
rotation_90('+x',-1);

结尾

你可以根据我的思路自己写一个,以上就是全部函数没有漏的。或者另辟蹊径。

下一篇文章:给魔方加一个GUI操作界面

http://t.csdn.cn/yk9wDhttp://t.csdn.cn/yk9wD

原创不易还请支持

https://download.csdn.net/download/qq_42053235/85240749https://download.csdn.net/download/qq_42053235/85240749

基于matlabgui的魔方三维动态还原仿真程序(代码片段)

...MATLABR2019A1、程序介绍使用MATLABGUI功能设计制作一个魔方三维动态还原仿真程序,点击魔方旋转按钮U\\D\\F\\B\\L\\R旋转方面相应面,逆\\顺时针按钮切换旋转方向,文字编辑框输入旋转步骤如U1B2L3再点击开始还原按钮然... 查看详情

如何写一个魔方二维动态还原matlab仿真程序(代码片段)

    之前文章写过一个魔方二维动态还原MATLAB程序,写得不怎么好,过于复杂,现在重新写了一个,用简单的方法编写MATLAB程序。 1、基础知识了解魔方表示方法:魔方状态字符串,可以看我之前的文章... 查看详情

魔方 Unity 5 [关闭]

...于Android的游戏,该游戏是魔方。我没有使用触摸来移动立方体,而是使用按钮来移动立方体的行和列,并且对他来说都旋转了另一组按钮。我的问题是第二组按钮它们必须具有两个功能,一个旋转整个立方体,另一个取决于另... 查看详情

用css代码做出一个简单的自动旋转正方体(css魔方原理)

所需要的技术有:1、position(定位)首先要了解position存在的意义:元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法。这里... 查看详情

用css代码做出一个简单的自动旋转正方体(css魔方原理)

所需要的技术有:1、position(定位)首先要了解position存在的意义:元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法。这里... 查看详情

css变形动画实现的旋转魔方

<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>魔方</title><styletype="text/css">body{height:100vh;width:100vw;/*background-image:url(../img/rubick.jpeg) 查看详情

简单说用css做一个魔方旋转的效果(代码片段)

说明魔方大家应该是不会陌生的,这次我们来一起用CSS实现一个魔方旋转的特效,先来看看效果图!解释我们要做这样的效果,重点在于怎么把6张图片,摆放成魔方的样子,而把它们摆放成魔方的样子,重点在于用好CSS的transfor... 查看详情

二阶魔方旋转魔方可以对它的6个面自由旋转。我们来操作一个2阶魔方(如图1所示):(代码片段)

/*二阶魔方旋转魔方可以对它的6个面自由旋转。我们来操作一个2阶魔方(如图1所示):为了描述方便,我们为它建立了坐标系。各个面的初始状态如下:x轴正向:绿x轴反向:蓝y轴正向:红y轴反... 查看详情

蓝桥杯---二阶魔方旋转(代码片段)

魔方可以对它的6个面自由旋转。我们来操作一个2阶魔方(如图1所示):为了描述方便,我们为它建立了坐标系。各个面的初始状态如下:x轴正向:绿x轴反向:蓝y轴正向:红y轴反向:橙z轴正... 查看详情

每天一个javascript小特效——会魔法的旋转魔方相册(代码片段)

...盒子模型,完成html代码编写设置样式,利用transform3D做出魔方JS构建事件1.HTML篇魔方中用&lt;li&gt;标签包含图片,方便用&lt;ul&gt;包裹,后面给ul添加3D模式便可进行翻折比较简单不过多讲解,代码如下:2.CSS篇2.1基础设置... 查看详情

cad的三维立体图形如何旋转角度?

...详细的教程。1、以下面的例子做演示,即如将下图中的立方体贴着A物体旋转2、首先,选中该立方体,直接输入ROTATE3D命令,按空格键确定3、最后,确认立方体的一条线以作为旋转轴,然后输入旋转角度,按空格键确认,即可完... 查看详情

css3景深三维变换属性及旋转三维立方体的实现

浏览器坐标系在讲正式语法之前,首先需要了解浏览器坐标系 这需要我们把浏览器界面想象成一个立体的场景这是网上流传很广的浏览器坐标系图片 从左到右的方向是浏览器x轴的正方向 从上到下的方向是浏览器y轴... 查看详情

OpenGL rubiks cube - 用鼠标旋转面部

...。这是我到目前为止的简单截图的链接(myrubikscube)旋转立方体是通过按住鼠标右键拖动鼠标来完成的。这可以使用NeHeTutorials(NeHeArcball) 查看详情

魔方二维动态还原过程matlab仿真/魔方二维平面展开(代码片段)

关键词:魔方还原;魔方二维平面展开1.魔方基础知识1.1魔方各面表示根据魔方各面所处位置将三阶魔方六个面分别用六个大写英文字母进行表示,相应面上的颜色也分别用这六个大写英文字母进行表示。魔方六个面... 查看详情

html+css+js实现❤️3d旋转魔方图片相册特效❤️(代码片段)

 效果演示:  代码目录:主要代码实现:部分CSS样式:background:url(../img/s3.jpg);background-size:100%100%;opacity:0.8;transform:rotateY(90deg)translateZ(200px);.box.box1.leftbackground:url(../i 查看详情

directx11--实现一个3d魔方(代码片段)

原文:DirectX11--实现一个3D魔方(3)前言(2019/1/909:23)上一章我们主要讲述了魔方的旋转,这个旋转真是有毒啊,搞完这个部分搭键鼠操作不到半天应该就可以搭完了吧...(2019/1/921:25)啊,真香有人发这张图片问我写魔方的目的是不是这... 查看详情

canvas实现3d魔方

...个):棱块的表面是两个正方形,结构类似一个长方体从立方体的一个边凸出来。3.角块(8个):角块的表面是三个正方形,结构类似一个小立方体从立方体的一个边凸出来,这样的结构可以让角块嵌在三个棱块之间。4.可见方... 查看详情

opengles绘制魔方(代码片段)

1前言​在立方体贴图(6张图)中,绘制了一个立方体,贴了6张图,本文的魔方案例,将实现绘制27个立方体,贴162张图。贴图图片如下:​说明:inside.png为魔方内部色块,用粉红色块代替白色块是为了凸显白色线框。​读者如... 查看详情