T形积木(T puzzle)

目录

积木绘制

积木拼接

练习

[1. 停止标志](#1. 停止标志)

[2. 跳跃旋转](#2. 跳跃旋转)

[3. 小步平移](#3. 小步平移)


积木绘制


(1)复数欧拉公式:

(2)复数的极坐标形式:

其中

(3)T形积木问题利用了复数乘以将该复数值旋转b角的事实。
findobj 查找具有特定属性的图形对象

复制代码
function t_puzzle

% Playing pieces and puzzle shapes.

   % Four playing pieces.

   s = sqrt(2);
   T{1} = [0 1 1+2*i 3*i 0];
   T{2} = [0 s/2+s/2*i 1+(s-1)*i 1+(2*s-1)*i 2*s*i 0];
   T{3} = [0 1 i 0];
   T{4} = [0 1 1+(2-s)*i (3-s)*i 0];

   % Three puzzle shapes for subplot.

   P{1} = [2 2 1 1 0 0 -1 -1 2]-1/2 + [2 1 1 -2 -2 1 1 2 2]*i;
   P{2} = [0 2 2-s 2-s 1-s 1-s -2 0] + [2 0 0 -2 -2 0 0 2]*i;
   P{3} = [1 3 0 -2 1]-1/2 + [1 -1 -1 1 1]*i;

   init_plot(T);
   init_subplot(P);
   init_buttons

   % ------------------------
   
   function button_motion(varargin)
      % Button motion, either drag or rotate a piece.
      % Use complex arithmetic.
      
      point = get(gca,'currentpoint');
      v = point(1,1) + point(1,2)*i;
      hit = get(gca,'userdata');
      if ~isempty(hit) && ishandle(hit) && hit ~= 1
         u = get(hit,'xdata') + get(hit,'ydata')*i;
         z = get(hit,'userdata');
         % Check if closer to center or vertex.
         w  = mean(u(1:end-1));
         if abs(w-v) < min(abs(u-v))
            % Drag
            u = u - (z - v);
         else
            % Rotate about the center by an integer
            % multiple of pi/20, which is 9 degrees.
            dtheta = pi/20;
            theta = angle(v-w) - angle(z-w);
            theta = round(theta/dtheta)*dtheta;
            omega = exp(i*theta);
            u = omega*(u-w) + w;
            v = omega*(z-w) + w;
         end
         set(hit,'xdata',real(u),'ydata',imag(u),'userdata',v);
      end
   end
   
   % ------------------------
   
   function init_plot(T)
      % Initialize primary plot.
      clf
      shg
      set(gcf,'numbertitle','off','menubar','none','name','T-puzzle')
      ax(1) = axes('pos',[0 0 1 1],'color',get(gcf,'color'), ...
         'xlim',[-4 4],'ylim',[-3 3],'userdata',[]);
      hold on
      axis off
      bluegreen = [0 1/2 1/2];
      init_shift = [-2-i -1/2-i 1-i 1+i/4];
      for k = 1:4
         t = T{k} + init_shift(k);
         fill(real(t),imag(t),bluegreen, ...
            'markeredgecolor','black','linewidth',2)
      end
      set(gcf,'userdata',ax);
   end
   
   % ------------------------
   
   function init_subplot(P)
      % Initialize puzzle shapes subplot.
      ax = get(gcf,'userdata');
      ax(2) = axes('units','normal','position',[.02 .02 .24 .24]);
      shape = 1;
      t = P{shape};
      buttoncolor = [.8314 .8157 .7843];
      bluegreen = [0 1/2 1/2];
      fill(real(t),imag(t),bluegreen, ...
         'markeredgecolor','black','linewidth',1)
      set(ax(2),'xtick',[],'ytick',[],'xlim',[-4 4],'ylim',[-3 3], ...
         'color',buttoncolor,'userdata',shape);
      set(gcf,'userdata',ax);
   end
   
   % ------------------------
   
   function init_buttons
      % Initialize buttons and callbacks.
      ax = get(gcf,'userdata');
      axis(ax(1));
      set(gcf,'windowbuttondownfcn',@button_down, ...
         'windowbuttonmotionfcn',@button_motion, ...
         'windowbuttonupfcn',@button_up)
      uicontrol('units','normal','pos',[.83 .12 .12 .05],'style','toggle', ...
         'callback','t_puzzle','string','restart')
      uicontrol('units','normal','pos',[.83 .06 .12 .05],'style','push', ...
         'callback','close(gcf)','string','exit')
   end
   
   % ------------------------
   
   function button_down(varargin)
      ax = get(gcf,'userdata');
      if gca == ax(1)
         select_piece;
      else
         cycle_subplot(P)
      end
   end
   
   % ------------------------
   
   function select_piece;
      % Select a piece and remember it in ax(1) userdata.
      point = get(gca,'currentpoint');
      z = point(1,1) + point(1,2)*i;
      delete(findobj(gca,'type','line'))
      h = flipud(get(gca,'children'));
      h = h(1:4);
      hit  = [];
      for k = 1:length(h)
         x = get(h(k),'xdata');
         y = get(h(k),'ydata');
         if inregion(real(z),imag(z),x,y)
            hit = h(k);
            set(hit,'userdata',z)
            break
         end
      end
      set(gca,'userdata',hit)
   
      % Right click reflects piece about center horizontally.
   
      if ~isempty(hit) && isequal(get(gcf,'selectiontype'),'alt')
         x = 2*mean(x(1:end-1))-x;
         set(hit,'xdata',x)
      end
   end
   
   % ------------------------
   
   function cycle_subplot(P)
      % Cycle through puzzle shapes in subplot.
      ax = get(gcf,'userdata');
      shape = get(ax(2),'userdata');
      shape = mod(shape,3)+1;
      t = P{shape};
      f = get(ax(2),'child');
      set(f,'xdata',real(t),'ydata',imag(t))
      set(ax(1),'userdata',[])
      set(ax(2),'userdata',shape)
      axes(ax(1))
   end
   
   % ------------------------
   
   function button_up(varargin)
      % Button up, snap to any nearby piece, then deselect.
      % Use complex arithmetic.
   
      delete(findobj(gca,'type','line'))
      hit = get(gca,'userdata');
      set(gca,'userdata',[])
     
      % Compute distance to nearest vertex of other pieces.
   
      z = get(hit,'xdata') + get(hit,'ydata')*i;
      h = get(gca,'children');
      w = [];
      for k = 1:length(h)
         if h(k) ~= hit
            w = [w; get(h(k),'xdata')+get(h(k),'ydata')*i];
         end
      end
      dz = 1;
      for k = 1:length(z);
         d = z(k)-w;
         dw = d(find(abs(d)==min(abs(d)),1));
         if abs(dw) < abs(dz)
            dz = dw;
         end
      end
   
      % If close enough, snap to nearby piece.
   
      tol = 1/8;
      if abs(dz) < tol
         set(hit,'xdata',real(z-dz),'ydata',imag(z-dz))
         bluegreen = [0 1/2 1/2];
         set(hit,'facecolor',1.25*bluegreen)
         pause(.25)
         set(hit,'facecolor',bluegreen)
      end
   end
end % t_puzzle

积木拼接


T形&箭头形&平行四边形


练习


1. 停止标志

复制代码
n=8
z=exp(2*pi*i*(0:n)'/n)
plot(z,'-o'), axis square
s=sum(z)

2. 跳跃旋转

旋转操作是通过**固定的角度(9度或π/20弧度)**来进行的。这会导致在旋转过程中可能出现明显的跳跃,特别是在慢速旋转时,可能感觉不够平滑。

复制代码
dtheta = pi/20;
theta = angle(v-w) - angle(z-w);
theta = round(theta/dtheta)*dtheta;
omega = exp(i*theta);
u = omega*(u-w) + w;
v = omega*(z-w) + w;

3. 小步平移

程序中的button_up函数负责处理鼠标释放事件,即在将T形积木拖动到其他块体附近并释放鼠标键时,程序会检测是否有其他块体的顶点靠近被释放的积木,如果有足够近的块体,则将积木自动吸附到靠近的块体上。

复制代码
   function button_up(varargin)
      % Button up, snap to any nearby piece, then deselect.
      % Use complex arithmetic.
   
      delete(findobj(gca,'type','line'))
      hit = get(gca,'userdata');
      set(gca,'userdata',[])
     
      % Compute distance to nearest vertex of other pieces.
   
      z = get(hit,'xdata') + get(hit,'ydata')*i;
      h = get(gca,'children');
      w = [];
      for k = 1:length(h)
         if h(k) ~= hit
            w = [w; get(h(k),'xdata')+get(h(k),'ydata')*i];
         end
      end
      dz = 1;
      for k = 1:length(z);
         d = z(k)-w;
         dw = d(find(abs(d)==min(abs(d)),1));
         if abs(dw) < abs(dz)
            dz = dw;
         end
      end
   
      % If close enough, snap to nearby piece.
   
      tol = 1/8;
      if abs(dz) < tol
         set(hit,'xdata',real(z-dz),'ydata',imag(z-dz))
         bluegreen = [0 1/2 1/2];
         set(hit,'facecolor',1.25*bluegreen)
         pause(.25)
         set(hit,'facecolor',bluegreen)
      end
   end
end % t_puzzle
相关推荐
rit84324992 小时前
有限元法求转子临界转速的MATLAB实现
开发语言·matlab
Matlab程序设计与单片机3 小时前
【机器人最短路径规划】基于标准蚁群算法
matlab·蚁群算法·路径规划问题
Marye_爱吃樱桃3 小时前
MATLAB R2024b的安装、简单设置——保姆级教程
开发语言·matlab
IT猿手15 小时前
基于控制障碍函数的多无人机编队动态避障控制方法研究,MATLAB代码
开发语言·matlab·无人机·openclaw·多无人机动态避障路径规划·无人机编队
Evand J20 小时前
【MATLAB复现RRT(快速随机树)算法】用于二维平面上的无人车路径规划与避障,含性能分析与可视化
算法·matlab·平面·无人车·rrt·避障
s090713620 小时前
【声纳成像】基于滑动子孔径与加权拼接的条带式多子阵SAS连续成像(MATLAB仿真)
开发语言·算法·matlab·合成孔径声呐·后向投影算法·条带拼接
IT猿手1 天前
基于 ZOH 离散化与增量 PID 的四旋翼无人机轨迹跟踪控制研究,MATLAB代码
开发语言·算法·matlab·无人机·动态路径规划·openclaw
IT猿手1 天前
基于控制障碍函数(Control Barrier Function, CBF)的无人机编队三维动态避障路径规划,MATLAB代码
开发语言·matlab·无人机·动态路径规划·无人机编队
SugarFreeOixi1 天前
MATLAB绘图风格记录NP类型
python·matlab·numpy
IT猿手1 天前
基于 CBF 的多无人机编队动态避障路径规划研究,无人机及障碍物数量可以自定义修改,MATLAB代码
开发语言·matlab·无人机·动态路径规划