www.gusucode.com > 三维模仿源码程序 > 三维模仿源码程序/MathRubik2/PlotCube.m

    function [bNewPlot,faces]=PlotCube(hAxes,Cube,bCoor,bColor)
%PlotCube - plot the cube Cube in axes hAxes
%    PlotCube(hAxes,Cube)

%!!zaken worden teveel dubbel (meervoudig) gedaan!!!
bDoPlot=false;
axes(hAxes); % current axes for draw
if nargin<2
	Cube=get(hAxes,'UserData');
elseif nargin>2
	if bCoor<0
		bDoPlot=true;
	end
end
hL=findobj(hAxes,'Type','line','Tag','PCdummyLine');
bTexture=~isempty(Cube.texture);
if isempty(hL)
	bDoPlot=true;
else
	DhL=get(hL,'UserData');
	if ~isequal(Cube.texture,DhL.texture)
		bDoPlot=true;
	end
end
Cmid=Cube.Color(Cube.iMidInd);
nMid=sum(Cmid>0);
if bTexture&nMid==6
	faces=zeros(3,3,6);
	faces(2,2,:)=1;
else
	faces=[];
end
Color=Cube.Color;
if bDoPlot
	if isempty(hL)
		hL=line(0,0,'Tag','PCdummyLine');
	else
		DhL=get(hL,'UserData');
		hCube=DhL.hCube;
		hCube(hCube==0)=[];
		delete(hCube)
	end
	if bTexture
		%(!!surface (bij standaard flat facecolor) geeft niet al de punten waar!!)
		%(vandaar dat nu ceil gebruikt werd ipv floor bij bepaling grootte)
		h=zeros(3,9);
		T0=ClearTexture(Cube);
		[m,n]=size(T0);
		colormap(Cube.texture.map)
		xx=(0:n-1)/(n-1)*2-1;
		yy=(0:m-1)'/(m-1)*2-1;
		mxXYZ=max(Cube.Nodes(:));
		dd=Cube.Nodes(1,1,2)-Cube.Nodes(1,1,1);
		for ih=1:3
			switch ih
			case 1
				XX=zeros(size(T0))+mxXYZ;
				YY=xx(ones(1,m),:);
				ZZ=yy(end:-1:1,ones(1,n));
				DX=[0 0];
				DY=[dd 0];
				DZ=[0 dd];
			case 2
				XX=xx(ones(1,m),end:-1:1);
				YY=zeros(size(T0))+mxXYZ;
				ZZ=yy(end:-1:1,ones(1,n));
				DX=[-dd 0];
				DY=[0 0];
				DZ=[0 dd];
			otherwise
				XX=yy(:,ones(1,n));
				YY=xx(ones(1,n),:);
				ZZ=zeros(size(T0))+mxXYZ;
				DX=[0 -dd];
				DY=[dd 0];
				DZ=[0 0];
			end
			iFace=ih*2;
			for kh=1:9
				iCube=Cube.RotLayerCube(iFace,kh);
				c=rem(kh-1,3)-1;
				r=floor((kh-1)/3)-1;
				dx=DX*[c;r];
				dy=DY*[c;r];
				dz=DZ*[c;r];
				currColor = Color(iFace,iCube);
				if currColor
					[Image,coor]=GetImage(Cube,currColor,c,r,iFace,iCube,0);
					if ~isempty(coor)
						faces(coor(1)+1,coor(2)+1,currColor)=1;
					end
				else
					Image=T0;
				end
				h(ih,kh)=surface(XX+dx,YY+dy,ZZ+dz,Image,'CDataMapping','direct','EdgeColor','none');
				set(h(ih,kh),'ButtonDownFcn','RotateWithMouse;'	...
					,'UserData',[iFace,iCube]	...
					);
			end	% for kh
		end	% for ih
	else	% simple cube-patches
		h=zeros(1,27);
		for iCube=1:27,
			CurrNodes = Cube.Nodes(:,:,iCube);
			currColor = Color(:,iCube)+1;
			h(iCube)=patch('Vertices',CurrNodes,'Faces',Cube.Order,...
			    'FaceVertexCData',Cube.ValColor(currColor,:),'FaceColor','flat',...
			    'ButtonDownFcn','RotateWithMouse;'	...
				,'UserData',iCube	...
				);
		end
	end
	set(hL,'UserData',struct('hCube',h,'texture',Cube.texture));
else
	DhL=get(hL,'UserData');
	hCube=DhL.hCube;
	if nargin<4
		bColor=true;
		if nargin<3
			bCoor=true;
		end
	end
	if bTexture
		T0=ClearTexture(Cube);
		for ih=1:3
			iFace=ih*2;
			for kh=1:9
				iCube=Cube.RotLayerCube(iFace,kh);
				c=rem(kh-1,3)-1;
				r=floor((kh-1)/3)-1;
				currColor=Color(iFace,iCube);
				if currColor
					[Image,coor]=GetImage(Cube,currColor,c,r,iFace,iCube,0);
					if ~isempty(coor)
						faces(coor(1)+1,coor(2)+1,currColor)=1;
					end
					set(hCube(ih,kh),'CData',Image)
				elseif hCube(ih,kh)
					set(hCube(ih,kh),'CData',T0)
				end
			end	% for kh
		end	% for ih
	else % no texture
		for iCube=1:27
			if bCoor
				set(hCube(iCube),'Vertices',Cube.Nodes(:,:,iCube));
			end
			if bColor
				set(hCube(iCube),'FaceVertexCData',Cube.ValColor(Color(:,iCube)+1,:))
			end
		end
	end
end
if ~isempty(faces)&bTexture	% (normally only one test is necessary, but, ..., maybe in the future...)
	for ih=1:3
		iFace=ih*2-1;
		for kh=[1:4 6:9];
			iCube=Cube.RotLayerCube(iFace,kh);
			c=rem(kh-1,3)-1;
			r=floor((kh-1)/3)-1;
			currColor=Color(iFace,iCube);
			if currColor
				[Image,coor]=GetImage(Cube,currColor,c,r,iFace,iCube,1);
				if ~isempty(coor)
					faces(coor(1)+1,coor(2)+1,currColor)=1;
				end
			end
		end	% for kh
	end	% for ih
end
if nargout
	bNewPlot=bDoPlot;
end

function T0=ClearTexture(Cube)
T0=ones(ceil(size(Cube.texture.XX{1})/3));
mxT0=max(T0(:));
T0(:,[1 end])=mxT0;
T0([1 end],:)=mxT0;

function [Image,coor]=GetImage(Cube,currColor,c,r,iFace,iCube,bOnlyCoor)
persistent POSCsurfs TOPdirection POSEsurfs
if isempty(POSCsurfs)
	POSCsurfs=reshape([	...	positions of corner surfaces
			3 3 3 1 3 1;
			3 1 3 3 1 1;
			3 1 3 3 3 3;
			3 3 3 1 1 3;
			1 3 1 1 1 1;
			1 1 1 3 3 1;
			1 1 1 3 1 3;
			1 3 1 1 3 3]'	...
		,2,3,8);
	POSCsurfs(3,:,:)=6.5+POSCsurfs(1,:,:).*POSCsurfs(2,:,:)/2-2*POSCsurfs(1,:,:)-POSCsurfs(2,:,:);
	TOPdirection=[6 6 6 6 2 1];	% direction of top of texture for each color
	POSEsurfs=[	...
		0 0 6 4 8 2;	...	positions of edge surfaces
		0 0 4 6 8 2;
		4 6 0 0 8 2;
		6 4 0 0 8 2;
		8 2 4 6 0 0;
		2 8 4 6 0 0];
end
[m,n]=size(Cube.texture.XX{1});
m1=ceil(m/3);
n1=ceil(n/3);
i1=-1;
nRot=0;
if all(Cube.Color(Cube.iMidInd))
	if c*r	% corner
		if sum(Cube.Color(:,iCube)>0)==3
			cc=Cube.Color(:,iCube);
			cc=cc(cc>0);
			cnr=floor((cc-1)/2);
			csign=bitand(cc-1,1);
			Cnr=sum(csign.*2.^cnr)+1;
			posS1=POSCsurfs(:,floor((currColor+1)/2),Cnr);
			posS2=2.5-r*c/2+r;
			nRot=posS1(3)-posS2;
			i1=posS1(1)-1;
			j1=posS1(2)-1;
		end
	elseif c|r	% edge
		if sum(Cube.Color(:,iCube)>0)==2
			cc=Cube.Color(:,iCube);
			cc=cc(cc>0&cc~=currColor);
			if ~isempty(cc)	% impossible cube
				posS1=POSEsurfs(currColor,cc);
				i1=floor((posS1-1)/3);
				j1=rem(posS1-1,3);
				%posS2=(5-r*3)*abs(r)+(c+5)*abs(c);
				posS2=(2+r)*abs(r)+(3-c)*abs(c);
				nRot=(3-i1)*abs(i1-1)+(4+j1)*abs(j1-1)-posS2;
			end
		end
	else % mid
		i1=r+1;
		j1=c+1;
		MyColor=Cube.Color(:,iCube);
		if Cube.bFullCube
			cCheck=TOPdirection(currColor);
			z=TOPdirection(iFace);	% face of small midcube to test
			% count needed rotations
			while MyColor(z)~=cCheck
				nRot=nRot-1;
				MyColor(Cube.RotCubeFlat(iFace,:))=MyColor;
				if nRot<-4	% normally not possible!!!!
					warning(sprintf(	...
							'!!!!!!Ik kan de juiste orientatie niet vinden!!!! (face %d, color %d, check %d)'	...
							,iFace,currColor,cCheck));
					break;
				end
			end
		end
	end
end
if bOnlyCoor
	Image=[];
	if i1<0
		coor=[];
	else
		coor=[i1 j1];
	end
	return
end
if i1<0
	coor=[];
	Image=Cube.texture.XX{currColor}(1:3:end,1:3:end);
	if size(Image,1)<m1
		Image(m1,:)=0;
	end
	if size(Image,2)<n1
		Image(:,n1)=0;
	end
else
	coor=[i1 j1];
	i1=round(i1/3*m)+1;
	j1=round(j1/3*n)+1;
	if i1+m1-1>m
		i1=i1-1;
	end
	if j1+n1-1>n
		j1=j1-1;
	end
	Image=Cube.texture.XX{currColor}(i1:i1+m1-1,j1:j1+n1-1);
	%disp([c r iFace iCube nRot])
	switch mod(nRot,4)
	case 1
		Image=Image(m1:-1:1,:)';
	case 2
		Image=Image(m1:-1:1,n1:-1:1);
	case 3
		Image=Image(:,n1:-1:1)';
	end
end
Image=double(Image+1);