gusucode.com > 三维模仿源码程序 > 三维模仿源码程序/MathRubik2/SetColors.m
function SetColors(varargin) %SetColors - UI for setting up a cube % houd per kleur bij welke "soorten kubussen" gekleurd zijn: % hoek, rand, midden % dit kan eenvoudig getoond worden in de kleuren-palet-plot if nargin==0|isnumeric(varargin{1})|isstruct(varargin{1}) hAxes=[]; Cube=[]; if nargin==0 try hAxes=FindRubikAxes; catch Cube=[]; end elseif isnumeric(varargin{1}) hAxes=varargin{1}; if nargin>1 if isstruct(varargin{2}) Cube=varargin{2}; end end end if isempty(Cube) if isempty(hAxes) Cube=InitCube; else Cube=get(hAxes,'UserData'); end Cube.Color(:,setdiff(1:27,[5 11 13 15 17 23]))=0; end Cube.history=[]; Cube.sol=[]; Cube.iSol=0; [f,hAxRub,Cube]=Rubik(Cube,'bPlot',false); axis off p=get(f,'Position'); set(f,'Position',[p(1:2) p(3)+120 p(4)],'Name','Rubik Cube Set Up' ... ,'WindowButtonMotionFcn','1;' ... ,'KeyPressFcn','SetColors(''key'')' ... ,'Tag','RubikSettingUp' ... ); hM=findobj(get(f,'Children'),'flat','Type','uimenu'); delete(get(hM,'Children')); sOnOff={'off','on'}; uimenu(hM,'Label','Clear Cube' ... ,'Callback','SetColors(''clear'');'); uimenu(hM,'Label','Clear Cube all' ... ,'Callback','SetColors(''clearall'');'); uimenu(hM,'Label','Set mid cubes' ... ,'Callback','SetColors(''midcubes'');'); uimenu(hM,'Label','Full clean Cube',... 'Callback','SetColors(''clean'');'); uimenu(hM,'Label','Reset to default' ... ,'Callback','SetColors(''reset'')' ... ,'Separator','on'); uimenu(hM,'Label','Reset to original' ... ,'Callback','SetColors(''tooriginal'')'); uimenu(hM,'Label','Set Texture...' ... ,'Callback','SetColors(''texture'')' ... ,'Separator','on'); uimenu(hM,'Label','Copy Cube' ... ,'Callback','SetColors(''copy'')'); uimenu(hM,'Label','full Cube' ... ,'Checked',sOnOff{Cube.bFullCube+1} ... ,'Tag','MenuFullCube' ... ,'Callback','SetColors(''fullcube'')' ... ,'Separator','on'); uimenu(hM,'Label','Show whole textures in pallette' ... ,'Checked','off' ... ,'Tag','MenuWholeTexture' ... ,'Callback','SetColors(''wholetexture'')'); %hM1=uimenu(hM,'Label','Small Cubes' ... % ,'Tag','MenuWholeTexture'); uimenu(hM,'Label','Toggle separate cubes' ... ,'Tag','MenuWholeTexture' ... ,'Callback','SetColors(''togglesepcubes'')'); hAxPal=axes('Units','pixel','Position',[p(3) 1 100 p(4)-2],'Tag','Palette'); hPal=zeros(1,6); hold on for i=1:6 C=repmat(reshape(Cube.ValColor(i+1,:),1,1,3),3,3); hPal(i)=image(1:3,i*3.2+(1:3),C ... ,'ButtonDownFcn',sprintf('SetColors(''setColor'',%d);',i) ... ,'UserData',i); end hold off axis off axis ij axis auto axis equal axLim=[-3.2 3.2]; hAxMids=axes('Units','pixel','Position',[0 0 140 140] ... ,'CameraPosition',[4.5 4 3.5]... ,'XLim',axLim,'YLim',axLim,'ZLim',axLim... ,'Tag','MidFaces'); hMid=zeros(1,6); ccc=Cube.ValColor; ccc(1,:)=[0.4 0.4 0.4]; for i=1:6 iC=Cube.RotLayerCube(i,5); k=Cube.Order(i,:); hMid(i)=patch(Cube.Nodes(k,1,iC),Cube.Nodes(k,2,iC),Cube.Nodes(k,3,iC) ... ,ccc(Cube.Color(i,iC)+1,:) ... ,'UserData',i ... ); end axis off posCorner=zeros(3,8); posEdge=zeros(2,12); c=[6;4]; for i=1:4 posCorner(:,i)=[2;c]; posCorner(:,i+4)=[1;c([2 1])]; posEdge(:,i)=[2;c(1)]; posEdge(:,i+4)=[1;c(1)]; posEdge(:,i+8)=c; c1=c(2); c(2)=bitxor(c(1)-1,1)+1; c(1)=c1; end %!!!?vreemde (?juiste?) omslachtige manier om orientatie te bepalen? C1=InitCube; orCorner=zeros(3,8); for i=1:8 c=C1.Color(:,C1.iCorner(i)); c=c(c>0); sc=sort(c); for j=1:8 if all(sc==sort(posCorner(:,j))) while c(1)~=posCorner(1,j) c=c([2:3 1]); end if c(2)~=posCorner(2,j) c=c([1 3 2]); end orCorner(:,i)=c; break end end end D=struct('f',f ... ,'hAxes',hAxes,'hAxPal',hAxPal ... ,'Cube0',Cube ... ,'C1',C1 ... ,'hAxRub',hAxRub,'hPal',hPal ... ,'hAxMids',hAxMids,'hMid',hMid ... ,'hCube',[] ... ,'orCorner',orCorner ... ,'nMid',0 ... ,'ccc',ccc ... ,'colSel',0 ... ,'posEdge',posEdge ... ,'availCorner',zeros(1,8),'availEdge',zeros(1,12) ... ,'bHoldColor',false ... ,'bShowWholeTexture',false ... ,'bCubeOK',true ... ); UpdateTexture(D,Cube) D=UpdatePalette(D,Cube); return end D=get(gcf,'UserData'); switch lower(varargin{1}) case {'clear','clearall'} Cube=get(D.hAxRub,'UserData'); if strcmp(lower(varargin{1}),'clear') ClearCube(D,Cube) else ClearAllCube(D,Cube) end case 'clean' CreateNewGame(0,D.hAxRub); case 'midcubes' Cube=get(D.hAxRub,'UserData'); i=setdiff(1:6,Cube.Color(Cube.iMidInd)); k=0; for j=1:6 if Cube.Color(Cube.iMidInd(j))==0 k=k+1; Cube.Color(Cube.iMidInd(j))=i(k); end end set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); case 'reset' Cube=get(D.hAxRub,'UserData'); Cube.Color(:)=0; Cube.ValColor=[0 0 0;1 0 0;1 0 1;0 0 1;0 1 0;1 1 0;1 1 1]; D.ccc=Cube.ValColor; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); case 'tooriginal' Cube=D.Cube0; D.ccc=Cube.ValColor; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); case 'texture' Cube=get(D.hAxRub,'UserData'); [fName,fPath]=uigetfile('*.mat','Give a file with texture data'); if ischar(fName) texture=load(fullfile(fPath,fName)); if ~Cube.bFullCube Cube.bFullCube=true; Cube=SetFullCube(D,Cube); end else if ~isempty(Cube.texture) b=questdlg('Do you want to remove the texture?','SetColor question' ... ,'Yes','No','Yes'); if strcmp(b,'No') return end end texture=[]; end D.colSel=0; set(get(D.hAxRub,'Parent'),'UserData',D) Cube.texture=texture; UpdateTexture(D,Cube) ClearCube(D,Cube) case 'setcolor' selType=get(D.f,'SelectionType'); Cube=get(D.hAxRub,'UserData'); if strcmp(selType,'alt')&isempty(Cube.texture) C=uisetcolor(Cube.ValColor(varargin{2}+1,:),'Set the color of this face'); if length(C)==3 Cube.ValColor(varargin{2}+1,:)=C; D.ccc=Cube.ValColor; set(D.hAxRub,'UserData',Cube); D=UpdatePalette(D,Cube); end elseif strcmp(selType,'open') % double click set(D.f,'Pointer','arrow') if ~isempty(Cube.texture)&D.colSel i=D.colSel; Cube.texture.XX{i}=Cube.texture.XX{i}(end:-1:1,:)'; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); end D.colSel=0; else % not alt-click if strcmp(selType,'alt') % (only possible if texture) % select the right part X=get(gco,'XData'); Y=get(gco,'YData'); p=get(gca,'CurrentPoint'); rX=(p(1)-min(X))/(max(X)-min(X)); rY=(p(1,2)-min(Y))/(max(Y)-min(Y)); end for i=1:6 set(D.hMid(i),'ButtonDownFcn' ... ,sprintf('SetColors(''setmid'',%d,%d)',i,varargin{2}) ... ); end set(D.f,'Pointer','cross') D.colSel=varargin{2}; D.bHoldColor=strcmp(selType,'extend'); end set(D.f,'UserData',D); case 'setcube' % used in colour mode Cube=get(D.hAxRub,'UserData'); iCube=get(gco,'UserData'); iN=[0 0 2 0 0 2 4 4 2 0 0 2 0 0 2 4 4 2 6 6 2 6 6 2 4 4 2 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 4 0 0 6 0 0 6 6 6 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6]; iL=iN(:,iCube); iL(iL<1)=[]; if isempty(iL) error('Kan niet') elseif length(iL)==1 % found else Xsel=get(gca,'CurrentPoint'); DXsel=diff(Xsel); A=[DXsel(1) -DXsel(2) 0;DXsel(1) 0 -DXsel(3);0 0 0]; B=A*Xsel(1,:)'; for i=iL' iNodes=Cube.Order(i,[1 2 4]); P=squeeze(Cube.Nodes(iNodes,:,iCube)); A(3,:)=cross(P(1,:)-P(3,:),P(2,:)-P(3,:)); B(3)=A(3,:)*P(1,:)'; XX=A\B; if XX(1)>=min(P(:,1))-1e-4&XX(1)<=max(P(:,1))+1e-4 ... &XX(2)>=min(P(:,2))-1e-4&XX(2)<=max(P(:,2))+1e-4 ... &XX(3)>=min(P(:,3))-1e-4&XX(3)<=max(P(:,3))+1e-4 iL=i; break; end end % for all possible colored faces of the small cube if length(iL)>1 warning('!!!!!!toch nog niet juist?') iL=iL(1); end end if any(iCube==Cube.iMid) Cube.Color(:,iCube)=0; end Cube.Color(iL,iCube)=D.colSel; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube,iCube,iL); if ~D.bHoldColor D.colSel=0; set(D.f,'Pointer','arrow') end set(D.f,'UserData',D); case 'setface' % used in texture mode Cube=get(D.hAxRub,'UserData'); iCube=get(gco,'UserData'); Cube.Color(iCube(1),iCube(2))=D.colSel; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube,iCube,iCube(1)); if ~D.bHoldColor D.colSel=0; set(D.f,'Pointer','arrow') end set(D.f,'UserData',D); case 'setmid' if D.colSel==0 return end Cube=get(D.hAxRub,'UserData'); i=varargin{2}; Cube.Color(Cube.iMidInd(i))=D.colSel; Cube.Color(Cube.iExtraFaces(i,:),Cube.iMid(i))=0; set(D.hAxRub,'UserData',Cube) if ~D.bHoldColor D.colSel=0; set(D.f,'Pointer','arrow') end D=UpdatePalette(D,Cube,Cube.iMidInd(varargin{2}),varargin{2}); set(D.f,'UserData',D) case 'cubebutton' iCube=get(gco,'UserData'); Cube=get(D.hAxRub,'UserData'); selType=get(D.f,'SelectionType'); if D.colSel if isempty(Cube.texture) SetColors('setCube') else SetColors('setFace') end elseif any(iCube(end)==Cube.iMid) % rotate mid cube ind=find(Cube.iMid==iCube(end)); Cube.Color(Cube.RotCubeFlat(ind,:),iCube(end)) = ... Cube.Color(:,iCube(end)); set(D.hAxRub,'UserData',Cube); D=PlotTheCube(D,Cube); elseif strcmp(selType,'alt') % clear colours of selected cube iCube=get(gco,'UserData'); iCube=iCube(end); Cube.Color(:,iCube)=0; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); set(D.f,'UserData',D); else RotateWithMouse(1); end case 'key' if D.colSel D.colSel=0; set(D.f,'Pointer','arrow') set(D.f,'UserData',D) end case 'rotated' UpdateLittleCube(D) case 'copy' if ~D.bCubeOK errordlg('Cube must not have any errors before I want to copy to a Rubik-figure!') return end Cube=get(D.hAxRub,'UserData'); if ~CheckComplete(Cube) errordlg('Cube has to be complete before I want to copy to a Rubik-figure!') return end Cube.history=[]; Cube.sol=[]; if isempty(D.hAxes)|D.hAxes==0|~ishandle(D.hAxes)|~strcmp(get(D.hAxes,'Tag'),'RubikAxes') fRub=Rubik(Cube); D.hAxes=FindRubikAxes; set(D.f,'UserData',D); else set(D.hAxes,'UserData',Cube) PlotCube(D.hAxes,Cube) ShowTitle(D.hAxes,Cube) end case 'fullcube' Cube=get(D.hAxRub,'UserData'); Cube.bFullCube=~Cube.bFullCube; set(D.hAxRub,'UserData',Cube); Cube=SetFullCube(D,Cube); PlotCube(D.hAxRub,Cube) set(D.hAxRub,'UserData',Cube); case 'wholetexture' ToggleWholeTexture(D) case 'togglesepcubes' Cube=get(D.hAxRub,'UserData'); Cube.Nodes=InitCube('toggleoffset',Cube); set(D.hAxRub,'UserData',Cube); PlotCube(D.hAxRub,Cube) otherwise warning(sprintf('Unknown use of SetColors (%s)',varargin{1})) end function D=UpdatePalette(D,Cube,iCube,iL) %!!!!!!iCube,iL nog niet gebruikt % bedoeld voor snellere (minder) bepalingen hAxPal=D.hAxPal; Cmid=Cube.Color(Cube.iMidInd); nMid=sum(Cmid>0); iImpossible=sum(Cmid>0)>length(unique(Cmid(Cmid>0))); bTexture=~isempty(Cube.texture); if iImpossible if D.nMid>=0 D.nMid=-1; end else if nMid==5 i=find(Cmid==0); Cube.Color(Cube.iMidInd(i))=setdiff(1:6,Cmid); nMid=6; end if nMid~=D.nMid D.nMid=nMid; if nMid==6 % Test of re-order of colors is necessary bReorder=false; C=Cube.Color; CO=C(Cube.iMidInd); CO2=floor((CO-1)/2); if any(CO2(1:2:6)~=CO2(2:2:6)) bReorder=true; else cc=diag(Cube.Color(1:2:5,Cube.RotLayerCube(1:2:5,5))); cnr=floor((cc-1)/2); csign=bitand(cc-1,1); s=rem(sum(csign),2); if mod(cnr(2)-cnr(1),3)>1 s=1-s; end if s bReorder=true; end end if bReorder % change order of colors (in place of other recalculations) % match (for current cube orientation) colors with face % positions for i=1:6 Cube.Color(C==CO(i))=i; end Cube.ValColor(2:end,:)=Cube.ValColor(CO+1,:); D.ccc(2:end,:)=Cube.ValColor(2:end,:); if bTexture Cube.texture.XX=Cube.texture.XX(CO); end end % reorder if Cube.bFullCube for i=1:6 iCube=Cube.iMid(i); if Cube.Color(Cube.iExtraFaces(i,1),Cube.iMid(i))==0 k=Cube.iExtraFaces(i,:); Cube.Color(k,Cube.iMid(i))=Cube.Color(Cube.iMidInd(k)); end end end % full cube - fill mid cubes end % nMid==6 end % nMid~=previous nMid if nMid==6 Cnrs=zeros(8,2); Ccs=zeros(6,3); Enrs=zeros(6,6); % Check Corners for i=1:8 % corners c=Cube.Color(D.orCorner(:,i),Cube.iCorner(i)); cc=c(c>0); nc=length(cc); cnr=floor((cc-1)/2); csign=bitand(cc-1,1); Cnr=sum(csign.*2.^cnr)+1; Cnrs(Cnr,2)=nc; for j=cc' Ccs(j)=Ccs(j)+1; end if nc>0&length(unique(cnr))~=nc iImpossible=10; elseif nc==3 s=rem(sum(csign),2); if mod(cnr(2)-cnr(1),3)>1 s=1-s; end if s iImpossible=20; end elseif nc==2 j=setdiff(0:2,cnr); nxt=2*j+rem(csign(1)+csign(2)+(c(2)==0)+(mod(cnr(2)-cnr(1),3)>1),2)+1; Cube.Color(D.orCorner(c==0,i),Cube.iCorner(i))=nxt; Ccs(nxt)=Ccs(nxt)+1; c=Cube.Color(D.orCorner(:,i),Cube.iCorner(i)); cc=c(c>0); nc=length(cc); cnr=floor((cc-1)/2); csign=bitand(cc-1,1); Cnr=sum(csign.*2.^cnr)+1; Cnrs(Cnr,2)=nc; elseif nc==1 Ccs(cc,2)=Ccs(cc,2)+1; Ccs(cc,3)=i; end if nc==3&~iImpossible if Cnrs(Cnr) iImpossible=30; else Cnrs(Cnr)=1; end end end % for i (corners) if ~iImpossible % Check edges for i=1:12 c=Cube.Color(:,Cube.iEdge(i)); cc=c(c>0); nc=length(cc); if nc==1 Enrs(cc,cc)=i; elseif nc==2 fcc=floor((cc-1)/2); if fcc(1)==fcc(2) iImpossible=11; elseif Enrs(cc(1),cc(2)) iImpossible=31; else Enrs(cc(1),cc(2))=1; Enrs(cc(2),cc(1))=1; end end end end if ~iImpossible for i=1:6 % colors % Auto-fill corners if Ccs(i)==4&Ccs(i,2)==1 iCorner=Ccs(i,3); iCube=Cube.iCorner(iCorner); k=floor((i-1)/2); cnr=setdiff(0:2,k); cnr=cnr([1 1 1 1],:); CSlist=[0 0;0 1;1 0;1 1]; bi=rem(i-1,2); C=sum(CSlist.*2.^cnr,2)+bi*2^k+1; if sum(Cnrs(C))~=3 warning('!!!!!!!het loopt hier fout!!!!') end j=find(Cnrs(C)==0); c=cnr(1,:)*2+CSlist(j,:)+1; csign=rem(sum(CSlist(j,:))+bi,2); j=D.orCorner(:,iCorner); bEmpty=Cube.Color(j,iCube)==0; Cube.Color(j(bEmpty),iCube)=c'; cnr=floor((Cube.Color(j,iCube)-1)/2); if csign~=(mod(cnr(2)-cnr(1),3)>1) Cube.Color(j(bEmpty),iCube)=c([2 1])'; end end % Auto-fill corners e=setdiff(1:6,[i bitxor(i-1,1)+1]); if Enrs(i,i)>0&sum(Enrs(i,e))==3 c=e(Enrs(i,e)==0); iCube=Cube.iEdge(Enrs(i,i)); j=find(D.C1.Color(:,iCube)&Cube.Color(:,iCube)==0); Cube.Color(j,iCube)=c; end end end else % not all mid-faces D.availCorner(:)=0; D.availEdge(:)=0; end end Left0=repmat([4,4,1],6,1); Left=Left0; TP=[1 2 1 2 3 2 1 2 1]; for i=1:6 for j=1:9 c=Cube.Color(i,Cube.RotLayerCube(i,j)); if c Left(c,TP(j))=Left(c,TP(j))-1; end end end if any(Left(:)<0) iImpossible=40; end if iImpossible warning(sprintf('!!onmogelijke plaatsing!!! (%d)',iImpossible)) end D.bCubeOK=iImpossible==0; [D,faces]=PlotTheCube(D,Cube); set(D.hAxRub,'UserData',Cube) set(D.f,'UserData',D) CCs={[3 3;3 1;1 3;1 1],[3 2;2 3;2 1;1 2],[2 2]}; Dleft=Left0-Left; if bTexture [sY,sX]=size(Cube.texture.XX{1}); iY=1:floor(sY/3); iX=1:floor(sX/3); end for i=1:6 if bTexture C=Cube.texture.XX{i}; else C=repmat(reshape(Cube.ValColor(i+1,:),1,1,3),3,3); end if isempty(faces) for j=1:3 for k=1:min(Dleft(i,j),Left0(i,j)) if bTexture if ~D.bShowWholeTexture C(round((CCs{j}(k,1)-1)*sY/3)+iY,round((CCs{j}(k,2)-1)*sX/3)+iX)=1; end else C(CCs{j}(k,1),CCs{j}(k,2),:)=0.4; end end end else % data for used small surfaces came from PlotCube % this data is giving the right positions for j=1:3 for k=1:3 if faces(j,k,i) if bTexture if ~D.bShowWholeTexture C(round((j-1)*sY/3)+iY,round((k-1)*sX/3)+iX)=1; end else % this is currently not possible C(j,k,:)=0.4; end end end end end set(D.hPal(i),'CData',C) end UpdateLittleCube(D) function ClearCube(D,Cube) i=setdiff(1:27,[5 11 13 15 17 23]); Cube.Color(:,i)=0; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); function ClearAllCube(D,Cube) i=1:27; Cube.Color(:,i)=0; set(D.hAxRub,'UserData',Cube) D=UpdatePalette(D,Cube); function UpdateLittleCube(D) Cube=get(D.hAxRub,'UserData'); if isempty(Cube.texture) for i=1:6 set(D.hMid(i),'FaceColor',D.ccc(Cube.Color(Cube.iMidInd(i))+1,:)) end else C=D.ccc(1:2,:); C(2,:)=[1 1 1]; for i=1:6 set(D.hMid(i),'FaceColor',C(min(Cube.Color(Cube.iMidInd(i)),1)+1,:)) end end function UpdateTexture(D,Cube) if isempty(Cube.texture) X=3; Y=3; else [Y,X]=size(Cube.texture.XX{1}); colormap(Cube.texture.map) end dx=3/X; x=dx/2+(0:X-1)*dx; dy=3/Y; y=dy/2+(0:Y-1)*dy; for i=1:6 set(D.hPal(i) ... ,'XData',x,'YData',y+3.2*i ... ) end function [D,faces]=PlotTheCube(D,Cube) [bNew,faces]=PlotCube(D.hAxRub,Cube,0,1); if bNew hL=findobj(D.hAxRub,'Tag','PCdummyLine'); DhL=get(hL,'UserData'); hCube=DhL.hCube; D.hCube=hCube; set(D.f,'UserData',D) set(D.hCube,'ButtonDownFcn','SetColors cubebutton') if isempty(Cube.texture) set(D.hCube,'EdgeColor',[0.8 0.8 0.8]) end set(D.f,'UserData',D) end if ~D.bCubeOK set(get(D.hAxRub,'Title'),'String','Impossible cube!'); end function Cube=SetFullCube(D,Cube) hM=findobj(D.f,'Tag','MenuFullCube'); sOnOff={'off','on'}; set(hM,'Checked',sOnOff{Cube.bFullCube+1}) if Cube.bFullCube Cube=MakeFullCube(Cube); end function ToggleWholeTexture(D) D.bShowWholeTexture=~D.bShowWholeTexture; hM=findobj(D.f,'Tag','MenuWholeTexture'); sOnOff={'off','on'}; set(hM,'Checked',sOnOff{D.bShowWholeTexture+1}) D=UpdatePalette(D,get(D.hAxRub,'UserData')); set(D.f,'UserData',D) function bComplete=CheckComplete(Cube) % Check if all required faces are filled NFilled=sum(Cube.Color>0); nFilled=sum(NFilled); % if full cube, easy check by the total number of filled faces. bComplete=all(NFilled(Cube.iCorner)>=3) ... &all(NFilled(Cube.iEdge)>=2) ... &all(NFilled(Cube.iMid)>=1) ... &(~Cube.bFullCube|nFilled>=78);