足球顶点坐标的计算程序(Matlab)

                     

贡献者: addis

  • 本文处于草稿阶段。
预备知识 足球顶点坐标的计算
图
图 1:绘图结果,动画见这里

代码 1:body60.m
function [Pa,Pb,Pc,Pd,Pe,Pf,Pg,Ph,flat5,flat6]=body60(RorHorL,draw)

%生成平面上的五边形
R=1/2/sin(36/180*pi);
Pa=zeros(5,3); 
temp=linspace(pi/2,18/180*pi+2*pi,5);
Pa(:,1)=R*cos(temp)';
Pa(:,2)=R*sin(temp)';

%计算出第二层五个点
Pb(5,:)=P32P(Pa([1 5 4],:));
Pb(1,:)=P32P(Pa([2 1 5],:));
Pb(2,:)=P32P(Pa([3 2 1],:));
Pb(3,:)=P32P(Pa([4 3 2],:));
Pb(4,:)=P32P(Pa([5 4 3],:));

%仅用补全多边形的方法,就可以生成剩下所有的点

%第1层6边形
[Pc(9,:),Pc(10,:)]=hexagon([Pa([1 5],:); Pb(5,:)]);
[Pc(1,:),Pc(2,:)]=hexagon([Pa([2 1],:); Pb(1,:)]);
[Pc(3,:),Pc(4,:)]=hexagon([Pa([3 2],:); Pb(2,:)]);
[Pc(5,:),Pc(6,:)]=hexagon([Pa([4 3],:); Pb(3,:)]);
[Pc(7,:),Pc(8,:)]=hexagon([Pa([5 4],:); Pb(4,:)]);

%第2层5边形
[Pd(9,:),Pd(10,:)]=pentagon([Pc(1,:); Pb(1,:); Pc(10,:)]);
[Pd(1,:),Pd(2,:)]=pentagon([Pc(3,:); Pb(2,:); Pc(2,:)]);
[Pd(3,:),Pd(4,:)]=pentagon([Pc(5,:); Pb(3,:); Pc(4,:)]);
[Pd(5,:),Pd(6,:)]=pentagon([Pc(7,:); Pb(4,:); Pc(6,:)]);
[Pd(7,:),Pd(8,:)]=pentagon([Pc(9,:); Pb(5,:); Pc(8,:)]);
%-------------------------------------------------球心
%第2层6边形
[Pe(9,:),Pe(10,:)]=hexagon([Pc([10 9],:);Pd(8,:)]);
[Pe(1,:),Pe(2,:)]=hexagon([Pc([2 1],:);Pd(10,:)]);
[Pe(3,:),Pe(4,:)]=hexagon([Pc([4 3],:);Pd(2,:)]);
[Pe(5,:),Pe(6,:)]=hexagon([Pc([6 5],:);Pd(4,:)]);
[Pe(7,:),Pe(8,:)]=hexagon([Pc([8 7],:);Pd(6,:)]);

%第2层6边形
[Pf(10,:),Pf(1,:)]=hexagon([Pd([10 9],:);Pe(10,:)]);
[Pf(2,:),Pf(3,:)]=hexagon([Pd([2 1],:);Pe(2,:)]);
[Pf(4,:),Pf(5,:)]=hexagon([Pd([4 3],:);Pe(4,:)]);
[Pf(6,:),Pf(7,:)]=hexagon([Pd([6 5],:);Pe(6,:)]);
[Pf(8,:),Pf(9,:)]=hexagon([Pd([8 7],:);Pe(8,:)]);

%第3层5边形
Pg(5,:)=pentagon([Pe(10,:);Pe(9,:);Pf(9,:)]);
Pg(1,:)=pentagon([Pe([2 1],:);Pf(1,:)]);
Pg(2,:)=pentagon([Pe([4 3],:);Pf(3,:)]);
Pg(3,:)=pentagon([Pe([6 5],:);Pf(5,:)]);
Pg(4,:)=pentagon([Pe([8 7],:);Pf(7,:)]);

%第3层6边形
Ph(5,:)=hexagon([Pf([1 10],:);Pg(5,:)]);
Ph(1,:)=hexagon([Pf([3 2],:);Pg(1,:)]);
Ph(2,:)=hexagon([Pf([5 4],:);Pg(2,:)]);
Ph(3,:)=hexagon([Pf([7 6],:);Pg(3,:)]);
Ph(4,:)=hexagon([Pf([9 8],:);Pg(4,:)]);

%使球心落在原点
H=Ph(1,end)/2;
Pa(:,3)=Pa(:,3)-H; Pb(:,3)=Pb(:,3)-H;   Pc(:,3)=Pc(:,3)-H; Pd(:,3)=Pd(:,3)-H;
Pe(:,3)=Pe(:,3)-H; Pf(:,3)=Pf(:,3)-H;   Pg(:,3)=Pg(:,3)-H; Ph(:,3)=Ph(:,3)-H; 

if RorHorL=='R'
    R=sqrt(1/4/sin(36/180*pi)^2+H^2);
    Pa=Pa/R; Pb=Pb/R; Pc=Pc/R; Pd=Pd/R; 
    Pe=Pe/R; Pf=Pf/R; Pg=Pg/R; Ph=Ph/R; 
elseif RorHorL=='H'
    Pa=Pa/H; Pb=Pb/H; Pc=Pc/H; Pd=Pd/H; 
    Pe=Pe/H; Pf=Pf/H; Pg=Pg/H; Ph=Ph/H; 
% RorHorL=='L' 无需操作
end


%12个正5边形(从下到上)
flat5(:,:,12)=Ph;
flat5(:,:,1)=Pa;
%第2层5边形
flat5(:,:,2)=[Pb(1,:);Pc(1,:);Pd(10,:);Pd(9,:);Pc(10,:)];
flat5(:,:,3)=[Pb(2,:);Pc(3,:);Pd(2,:);Pd(1,:);Pc(2,:)];
flat5(:,:,4)=[Pb(3,:);Pc(5,:);Pd(4,:);Pd(3,:);Pc(4,:)];
flat5(:,:,5)=[Pb(4,:);Pc(7,:);Pd(6,:);Pd(5,:);Pc(6,:)];
flat5(:,:,6)=[Pb(5,:);Pc(9,:);Pd(8,:);Pd(7,:);Pc(8,:)];
%----------------------------------------------------
%第3层5边形
flat5(:,:,7)=[Pg(1,:);Pf(2,:);Pe(2,:);Pe(1,:);Pf(1,:)];
flat5(:,:,8)=[Pg(2,:);Pf(4,:);Pe(4,:);Pe(3,:);Pf(3,:)];
flat5(:,:,9)=[Pg(3,:);Pf(6,:);Pe(6,:);Pe(5,:);Pf(5,:)];
flat5(:,:,10)=[Pg(4,:);Pf(8,:);Pe(8,:);Pe(7,:);Pf(7,:)];
flat5(:,:,11)=[Pg(5,:);Pf(10,:);Pe(10,:);Pe(9,:);Pf(9,:)];


%20个正六边形
%第1层6边形
flat6(:,:,1)=[Pa([2 1],:);Pb(1,:);Pc([1 2],:);Pb(2,:)];
flat6(:,:,2)=[Pa([3 2],:);Pb(2,:);Pc([3 4],:);Pb(3,:)];
flat6(:,:,3)=[Pa([4 3],:);Pb(3,:);Pc([5 6],:);Pb(4,:)];
flat6(:,:,4)=[Pa([5 4],:);Pb(4,:);Pc([7 8],:);Pb(5,:)];
flat6(:,:,5)=[Pa([1 5],:);Pb(5,:);Pc([9 10],:);Pb(1,:)];
%第2层6边形
flat6(:,:,6)=[Pc([2 1],:);Pd(10,:);Pe([1 2],:);Pd(1,:)];
flat6(:,:,7)=[Pc([4 3],:);Pd(2,:);Pe([3 4],:);Pd(3,:)];
flat6(:,:,8)=[Pc([6 5],:);Pd(4,:);Pe([5 6],:);Pd(5,:)];
flat6(:,:,9)=[Pc([8 7],:);Pd(6,:);Pe([7 8],:);Pd(7,:)];
flat6(:,:,10)=[Pc([10 9],:);Pd(8,:);Pe([9 10],:);Pd(9,:)];
%-------------------------------------------------
%第3层6边形
flat6(:,:,11)=[Pd([2 1],:);Pe(2,:);Pf([2 3],:);Pe(3,:)];
flat6(:,:,12)=[Pd([4 3],:);Pe(4,:);Pf([4 5],:);Pe(5,:)];
flat6(:,:,13)=[Pd([6 5],:);Pe(6,:);Pf([6 7],:);Pe(7,:)];
flat6(:,:,14)=[Pd([8 7],:);Pe(8,:);Pf([8 9],:);Pe(9,:)];
flat6(:,:,15)=[Pd([10 9],:);Pe(10,:);Pf([10 1],:);Pe(1,:)];
%第4层6边形
flat6(:,:,16)=[Pf([3 2],:);Pg(1,:);Ph([1 2],:);Pg(2,:)];
flat6(:,:,17)=[Pf([5 4],:);Pg(2,:);Ph([2 3],:);Pg(3,:)];
flat6(:,:,18)=[Pf([7 6],:);Pg(3,:);Ph([3 4],:);Pg(4,:)];
flat6(:,:,19)=[Pf([9 8],:);Pg(4,:);Ph([4 5],:);Pg(5,:)];
flat6(:,:,20)=[Pf([1 10],:);Pg(5,:);Ph([5 1],:);Pg(1,:)];


%画图
if draw==1
    draw_football(flat5,flat6);
end

end

%已知五边形的3点,求第2点连出的线段的另一端的坐标
%size(P3)=[3,3];
function P=P32P(P3) %P3右手定则的法向向球外

v1=P3(2,:)-P3(1,:);
v2=P3(2,:)-P3(3,:);
C=1/2/cos(54/180*pi); S=sqrt(1-C^2);
v3=vunit(cross(v1,v2));
P=vunit(v1+v2)*C+P3(2,:)+v3*S;

end

%已知5边形的3点, 求出第4点和第5点
function [P4,P5]=pentagon(P3)

v1=P3(2,:)-P3(1,:); 
v2=P3(3,:)-P3(2,:);
C=cos(72/180*pi);
P4=P3(3,:)+v2*C*2-v1;
v3=P4-P3(3,:);
P5=P4+v3*C*2-v2;

end

%%已知6边形的3点, 求出第4,5,6点
function [P4,P5,P6]=hexagon(P3)
v1=P3(2,:)-P3(1,:); 
v2=P3(3,:)-P3(2,:);
P4=P3(3,:)+v2-v1;
v3=P4-P3(3,:);
P5=P4+v3-v2;
v4=P5-P4;
P6=P5+v4-v3;
end

   动画程序

代码 2:draw_football.m
%画出足球,flat5是所有的5边形,第n个5边形的第ii个点的坐标就是flat5(ii,:,n)
%flat6是所有6边形,类比flat5.

%如果输入vz和theta,画出静态的足球. 先绕z轴转动thetavz
%  , 再把轴转向vz方向; vz不为零即可.
%如果输入vz=Omega,theta=omega, 则z轴以Omega角速度旋转
% , 足球以角速度omega自转; 动画时间为T

%rec=1时, 在桌面生成录像

%生成视频的例子:
 % [Pa,Pb,Pc,Pd,Pe,Pf,Pg,Ph,flat5,flat6]=body60('R',0);
 % draw_football(flat5,flat6,pi/6,pi/3,5,1)

function mov=draw_football(flat5,flat6,vz,theta,T,rec) % 忽略错误
%设置播放帧率(可以是非整数)
f=20;
%f=7;%实时播放的频率

%判断模式, 初始化
if nargin==6 %avi模式, 生成avi视频
    flag='a'; 
    Omega=vz; %轴倾斜角速度
    omega=theta;%绕轴角速度
    Axis1=[0 0 1]; %轴
    kk_max=floor(f*T); %视频总帧数
    mov(1:kk_max)=struct('cdata', [], 'colormap', []); %视频矩阵
    
elseif nargin==5%movie模式, 动画演示或视频
    flag='m'; 
    Omega=vz; %轴倾斜角速度
    omega=theta;%绕轴角速度
    Axis1=[0 0 1]; %轴
    kk_max=floor(f*T); %视频总帧数
    
elseif nargin==4 %static模式, 旋转后的静态图像
    flag='s'; 
    kk_max=1; %视频总帧数
    Axis1=[0 0 1]; %轴
    
elseif nargin==2 %origin模式, 原始静态图像
    flag='o'; 
    kk_max=1; %视频总帧数
    Axis1=[0 0 1]; %轴
end

kk=0; %当前帧数
warning_mark=false;

%设置窗口
hf=figure;  
axis([-1.5 1.5 -1.5 1.5 -1.5 1.5]); 
 axis on;
view([26,38]); axis equal; grid on;
set(gca,'CameraViewAngleMode','manual');
input('调整窗口大小,按回车开始');
figure(hf);

%rect(1:2)是figure的左下角在电脑屏幕上的坐标, rect(3:4)是axis的右上角的
%刚好消除figure最外层的边框!(忽略掉窗口边界).
set(hf,'unit','pixels'); f_posi=get(hf,'position');
rect(1:2)=f_posi(1:2);
rect(3:4)=f_posi(1:2)+f_posi(3:4)-1;

time1=tic; %开始播放的时间
%播放循环, 一个循环播放一帧图像
while kk+1<=kk_max
    %转动足球所有坐标
    if flag=='m' || flag=='a'
        Axis=Axis1;
        %Axis绕y轴旋转得到Axis1
        Axis1=vturn(Axis,[0 1 0],Omega/f);
        %足球绕Axis旋转
        [flat5(:,1,:),flat5(:,2,:),flat5(:,3,:)]=...
            turn(flat5(:,1,:),flat5(:,2,:),flat5(:,3,:),Axis,omega/f);
        [flat6(:,1,:),flat6(:,2,:),flat6(:,3,:)]=...
            turn(flat6(:,1,:),flat6(:,2,:),flat6(:,3,:),Axis,omega/f);
        %%足球随着Axis转到Axis1
        [flat5(:,1,:),flat5(:,2,:),flat5(:,3,:)]=...
            turn(flat5(:,1,:),flat5(:,2,:),flat5(:,3,:),Axis,Axis1);
        [flat6(:,1,:),flat6(:,2,:),flat6(:,3,:)]=...
            turn(flat6(:,1,:),flat6(:,2,:),flat6(:,3,:),Axis,Axis1);
    elseif flag=='s'
        [flat5(:,1,:),flat5(:,2,:),flat5(:,3,:)]=...
            turn(flat5(:,1,:),flat5(:,2,:),flat5(:,3,:),[0 0 1],theta);
        [flat5(:,1,:),flat5(:,2,:),flat5(:,3,:)]=...
            turn(flat5(:,1,:),flat5(:,2,:),flat5(:,3,:),[0 0 1],vz);
    end
    
    %画图
    cla; hold on; %清除足球,坐标轴不变
    for ii=1:size(flat5,3);
        temp=flat5(:,:,ii);
        Fill3(temp,'k','LineStyle','none');
    end

    for ii=1:size(flat6,3);
        temp=flat6(:,:,ii);
        Fill3(temp,'w','FaceAlpha',0.85,'LineWidth',2);
    end
    light
    kk=kk+1; %当前帧数
    
    %播放控制
    if flag=='m' %动画模式
        now=toc(time1);
        temp=kk/f-now; %该周期中画完图后余下的时间
        if temp>0
            pause(temp);%补足该帧剩下的时间
        else
            warning_mark=true; %如果画图太慢, 在程序结束后警告;    
        end
        
    elseif  flag=='a' %录像模式
        pause(0.05); %等待作图
        temp=printScreen; %截屏
        %选取axis所在的区域rect
        Size=size(temp);%屏幕尺寸
        temp=temp(Size(1)-rect(4)+1:Size(1)-rect(2)+1, rect(1):rect(3),:);
        mov(kk).cdata=temp;
    end
    
end

%播放结束
% if  flag=='a' %制作电影;
%     frame=mov(1:kk);
%     cf; movie2avi(frame,'rotating_football','compression',....
%                                   'Cinepak','fps',20,'quality',100); 
% end

if warning_mark
    warning('帧数太高, 不能播放动画, 在line11设置');
end

if flag=='a'
    cf; movie2avi(mov,'rotating_football','compression','None','fps',f);
end

end

                     

© 小时科技 保留一切权利