Diese Datei stammt aus Wikimedia Commons und kann von anderen Projekten verwendet werden. Die Beschreibung von deren Dateibeschreibungsseite wird unten angezeigt.
function[]=Oil_Damper()% Programmed in Matlab R2017a.% Animation of a twin and mono tube oil damper.% Before anything is drawn the algorithm loops the frames% to determine the particle pathes.% Several versions are created.% .gif, .mp4 and .webm%% 2020-08-07 Jahobr - Licensing: CC0 1.0 Universal Public Domain Dedication[pathstr,fname]=fileparts(which(mfilename));% save files under the same name and at file locationRGB.edge=[000];RGB.white=[111];RGB.brightGrey=[0.80.80.8];% housingRGB.blueGrey=[0.750.750.9];% moving metalRGB.oil=[0.90.90];RGB=structfun(@(q)round(q*255)/255,RGB,'UniformOutput',false);% round to values that are nicely uint8 compatiblescreenSize=get(groot,'Screensize')-[00520];% [1 1 width height] (minus tolerance for figure borders)formode={'Twin_Tube_Damper','Mono_Tube_Damper'}%%% y-axis-dimensions (Twin is default)% _______________________________________________________________wall=0.5;% wall width ¦outerRad=4.5;% ,-------------------------outerRadius--------------------, ¦% % ¦ ____________________________________________________¦ ¦% % ¦ ¦ wall width ¦innerRad=3.0;% ¦ ¦ ,---------,====,--innerRadius-(pistonRadius)--, ¦% % ¦ ¦__¦ ¦____¦ ¦ ¦holeY=[2.21.5];% ¦ :__: holeY :____: ¦ ¦% % ¦ ¦ ¦ ¦ ¦ ¦ ¦rodRad=1.0;% ¦ ¦ ¦ ¦ '--------rodRadius-----------------------------,% % ¦ ¦ ¦ ¦ ¦%% x-axis-dimensions + centerline - - - - - - - - - - - - - - - - - - - - - - - - - - - - +% % ¦ ¦ 0-Position¦ ¦rodLenght=20;% ¦ ¦ ¦ ¦ ,<----------------rodLenght------------------->'% % ¦ ¦__¦ ¦ ¦ ¦ ¦pistonWidth=3;% ¦ :__: pistonWidth ¦ ¦l_inner=0.0;% ¦ ¦ ¦l_inner ¦ ¦ ¦ ¦r_inner=20;% ¦ ¦ '----------====------------------------r_inner' ¦% % ¦ ¦____________________________________________________, ¦l_outer=-2.5;% ¦left_outer ¦ ¦r_outer=r_inner+3*wall;% ---------------------------------------------r_outer' ¦% %_______________________________________________________________¦xLimits=[-4.138.2];% ADJUSTyLimits=[-5.85.8];% ADJUSTswitchmode{1}%case'Mono_Tube_Damper'l_inner=-4.0;xLimits=[-5.538.2];% ADJUSTyLimits=[-4.74.7];% ADJUSTendnParticlesOil=250;% number of moving particles (oil "bubbles")nParticlesGas=50;% number of moving particles (gas)xRange=xLimits(2)-xLimits(1);yRange=yLimits(2)-yLimits(1);imageAspectRatio=xRange/yRange;forform={'gif'}% {'mp4','gif'} % file formatswitchform{1}%case'gif'nFrames=520;pistonPosList=cos(linspace(2*pi,0,nFrames));% [1 -1 1] one loopdelayTime=ones(1,nFrames)*1/30;% delay per frame% delayTime(1) = 0.5; % keep first frame longer (did not look good)% delayTime(end) = 0.5; % keep last frame longer (did not look good)% delayTime(round(nFrames/2)) = 1; % keep other extreme position frame longerMegaPixelTarget=100*10^6;% Category:Animated GIF files exceeding the 100 MP limitpxPerImage=MegaPixelTarget/nFrames;% pixel per gif frameySize=sqrt(pxPerImage/imageAspectRatio);% gif heightxSize=ySize*imageAspectRatio;% gif widthxSize=floor(xSize);ySize=floor(ySize);% full pixelsscaleReduction=min(...% repeat as often as possible for nice antialiasingfloor(screenSize(4)/ySize),floor(screenSize(3)/xSize));ifscaleReduction==0;error('"MegaPixelTarget" not possible; use smaller target or bigger monitor');end% checkcase'mp4'repetitions=3;nFrames=520*repetitions;%nFrames = 30;pistonPosList=cos(linspace(2*pi*repetitions,0,nFrames));% [1 -1 1] one loopxSize=screenSize(3);%max sizeySize=xSize/imageAspectRatio;% gif widthxSize=floor(xSize/16)*16;ySize=floor(ySize/16)*16;% full pixels, multiple-of-16 boundaries (MPEG splits the video into 16x16 squares called macroblocks)scaleReduction=1;% not usefull for mp4 or webm (gif only)otherwiseerror('unknown mode')endoilRed=ceil(xSize*scaleReduction/500);% size reduction factor to speed things upfigPos=[11xSize*scaleReductionySize*scaleReduction];% big start image for antialiasing later [x y width height]liSc=ySize*scaleReduction/150;% LineWidth scale; LineWidth is absolute, a bigger images needs thicker lines to keep them in proportionyRange=xRange*ySize/xSize;% xSize and ySize were rounded; we have the adjust the yRange to stay in the same aspect ratioyLimits=[-yRange/2yRange/2];% xSize and ySize were rounded; we have the adjust the yRange to stay in the same aspect ratiofigHandle=figure(117854461);clfaxesHandleOil=axes;hold(axesHandleOil,'on')set(figHandle,'Position',figPos);if~all(get(figHandle,'Position')==figPos);error('figure Position could not be set');end% checkset(figHandle,'Color',RGB.white);% white backgroundset(axesHandleOil,'Position',[0011]);% stretch axis as big as figure, [x y width height]xlim(xLimits);ylim(yLimits);% set axis limitsaxisoff% invisible axes (no ticks)axisequal;drawnow;firstIter=true;pistonPosList=(pistonPosList(:)+1)*0.5;% normalize range to [0 1]fullPistonPosTravel=r_inner-pistonWidth;% left end is defined as 0pistonPosList=(pistonPosList*fullPistonPosTravel*0.75)+(fullPistonPosTravel*0.125);% 75% travel% pistonPosList = pistonPosList*fullPistonPosTravel; % 100% travelctrs=NaN(nParticlesOil,2,nFrames);% allocate paths of clusters(numberOFCluster, x-y-coordinate, frame)oilPos=18-pistonPosList;% Twin_Tube_DamperpistonPos=[pistonPosListpistonPosList+pistonWidth];% Mono & Twin_Tube_DamperAirOilSeparatorPos=5+((pistonPosList-fullPistonPosTravel)/3);% Mono_Tube_DamperAirOilSeparatorPos=[AirOilSeparatorPos-wall*4AirOilSeparatorPos];% Mono_Tube_Damper%% particle path loop% r g bOilColStatic=[000];% black, staticOilColOuter=[001];% blue, outer chamber moves left slowOilColHolesB=[010];% green, holes base moves right fastOilColHolesP=[100];% red, holes piston moves left fastOilColBase=[110];% yellow, outer moves left slowOilColBaseUp=[101];% magenta, vertical movementOilColBaseDo=[011];% cyan, vertical movementforiFrame=1:nFramesfigure(figHandle);claplotBox([pistonPos(iFrame,2)r_inner],[innerRadrodRad],OilColStatic,'none',liSc)%inneroilchamberabovetherodplotBox([pistonPos(iFrame,2)r_inner],[-rodRad-innerRad],OilColStatic,'none',liSc)% inner oil chamber below the rodifstrcmp(mode{1},'Twin_Tube_Damper')plotBox([l_innerpistonPos(iFrame,1)],[-11]*innerRad,OilColBase,'none',liSc)% inner oil chamber, in front of the pistonelse% Mono_Tube_DamperplotBox([AirOilSeparatorPos(iFrame,2)pistonPos(iFrame,1)],[-11]*innerRad,OilColBase,'none',liSc)% inner oil chamber, in front of the pistonendplotBox(pistonPos(iFrame,:)+[-wallwall]*2,+holeY,OilColHolesP,'none',liSc)% upper hole, through the pistonplotBox(pistonPos(iFrame,:)+[-wallwall]*2,-holeY,OilColHolesP,'none',liSc)% lower hole, through the piston ifstrcmp(mode{1},'Twin_Tube_Damper')plotBox([l_outeroilPos(iFrame)],[innerRad+wallouterRad],OilColOuter,'none',liSc)% upper outer oil chamberplotBox([l_outeroilPos(iFrame)],-[innerRad+wallouterRad],OilColOuter,'none',liSc)% lower outer oil chamberplotBox([l_outerl_inner-2*wall],[-11]*(innerRad+wall),OilColStatic,'none',liSc)% outer oil chamber bottom, static oilplotBox([l_outerl_inner-2*wall],[-outerRad+wall-holeY(2)],OilColBaseUp,'none',liSc)% outer oil chamber bottom, oil upplotBox([l_outerl_inner-2*wall],[+outerRad-wall+holeY(2)],OilColBaseDo,'none',liSc)% outer oil chamber bottom, oil downplotBox([l_outerl_inner+wall*2],+holeY,OilColHolesB,'none',liSc)% upper hole, connecting inner and outer volumeplotBox([l_outerl_inner+wall*2],-holeY,OilColHolesB,'none',liSc)% lower hole, connecting inner and outer volumeendxlim(xLimits);ylim(yLimits);% set axis limitsaxisequal;drawnow;f=getframe(figHandle);OilImage=f.cdata;isOilMap=~and(and(OilImage(:,:,1)==uint8(255),OilImage(:,:,2)==uint8(255)),OilImage(:,:,3)==uint8(255));isOilMap=imerode(isOilMap,strel('rectangle',[11].*round(ySize*scaleReduction/35)));% paricles away from borderOilImage=randSubsampling(OilImage,oilRed);% reduce sizeisOilMap=randSubsampling(isOilMap,oilRed);% reduce sizefigure(23446);clfimage(isOilMap*255)[row,col]=find(isOilMap);optsFirst=statset('Display','final','UseParallel',true,'MaxIter',3000);optsIter=statset('Display','final','UseParallel',true,'MaxIter',1);iffirstIter[idx,ctrs(:,:,iFrame)]=kmeans([row,col],nParticlesOil,'Distance','sqEuclidean','start','uniform',...'Options',optsFirst,'replicates',40);firstIter=false;elsedisp('nextIter')movSpeed=pistonPosList(iFrame)-pistonPosList(iFrame-1);movSpeedPx=movSpeed/xRange*xSize/oilRed*scaleReduction;ctrs(:,:,iFrame)=ctrs(:,:,iFrame-1);% use previous stateforiCluster=1:nParticlesOilcolorParticle=OilImage(round(ctrs(iCluster,1,iFrame)),round(ctrs(iCluster,2,iFrame)),:);colorParticle=colorParticle(:)';if(all(colorParticle==OilColStatic*255))% black static% do nothingelseif(all(colorParticle==OilColOuter*255))% = [0 0 1]; blue, outer chamber moves left slowctrs(iCluster,2,iFrame)=ctrs(iCluster,2,iFrame)-movSpeedPx;elseif(all(colorParticle==OilColHolesB*255))% = [0 1 0]; green, holes base moves right fastctrs(iCluster,2,iFrame)=ctrs(iCluster,2,iFrame)+1.5*movSpeedPx;elseif(all(colorParticle==OilColHolesP*255))% = [1 0 0]; red, holes piston moves left fastctrs(iCluster,2,iFrame)=ctrs(iCluster,2,iFrame)-3.5*movSpeedPx;% 3 3.2elseif(all(colorParticle==OilColBase*255))% = [1 1 0]; yellow, outer moves left slowctrs(iCluster,2,iFrame)=ctrs(iCluster,2,iFrame)+0.4*movSpeedPx;% 0.3333elseif(all(colorParticle==OilColBaseUp*255))% = [1 0 1]; magenta, vertical movement downctrs(iCluster,1,iFrame)=ctrs(iCluster,1,iFrame)-movSpeedPx*0.8;elseif(all(colorParticle==OilColBaseDo*255))% = [0 1 1]; cyan, vertical movement upctrs(iCluster,1,iFrame)=ctrs(iCluster,1,iFrame)+movSpeedPx*0.8;endend[idx,ctrs(:,:,iFrame)]=kmeans([row,col],nParticlesOil,'Distance','sqEuclidean','start',ctrs(:,:,iFrame),...'Options',optsIter);endend%% filter paths% figure(2376574); clf; hold on% xlim([1 xSize]/oilRed); ylim([1 ySize]/oilRed); % set axis limitswind=4;foriCluster=1:nParticlesOil% for all cluster-enters (particles)% cla% plot(permute(ctrs(iCluster,2,:),[3,2,1]),permute(ctrs(iCluster,1,:),[3,2,1]),'b-');ctrs(iCluster,1,:)=filtfilt(ones(1,wind)/wind,1,ctrs(iCluster,1,:));% filter particle path x-coordinatectrs(iCluster,2,:)=filtfilt(ones(1,wind)/wind,1,ctrs(iCluster,2,:));% filter particle path y-coordinate% plot(permute(ctrs(iCluster,2,:),[3,2,1]),permute(ctrs(iCluster,1,:),[3,2,1]),'m-');% pause()endswitchform{1}%case'gif'reducedRGBimage=ones([ySize,xSize,3,nFrames],'uint8');% allocatecase'mp4'vid=VideoWriter(mode{1},'MPEG-4');% Prepare the new filevid.FrameRate=30;vid.Quality=100;% quality in [0% 100%]open(vid);endgasColMap=cool(100);minOilPos=min(oilPos);maxOilPos=max(oilPos);ifstrcmp(mode{1},'Twin_Tube_Damper')gasOffset_x=0.75*((rand(nParticlesGas/2,2).*wall)-wall/2);% gas positions distribution.gasOffset_x(1,:)=0;% avoid the leftmost particle get over the linegasOffset_x(end,:)=0;% avoid the rightmost particle get over the linegasOffset_x=gasOffset_x(:);gasOffset_y=(rand(nParticlesGas,1).*wall*0.2)+0.09;% gas positions distribution.gasOffset_y=gasOffset_y.*(2*rem((1:nParticlesGas)',2)-1);% alternate 1 -1 1 -1 offsetcolorShading=[ones(nParticlesGas/2,1)*0.5;ones(nParticlesGas/2,1)*0.7];gasPos_x=linspace(0,1,(nParticlesGas)+1)';gasPos_x=[gasPos_x(2:2:end);gasPos_x(2:2:end)];gasPos_y=mean(outerRad-wall,innerRad)*ones(nParticlesGas/2,1);gasPos_y_scale=[gasPos_y;-gasPos_y];elseXY_gasPos=net(haltonset(2,'Skip',1),nParticlesGas*1.2);% generate quasi random numbers, 'Skip',1 to remove the point at 0,0 clusterIndex=clusterdata(XY_gasPos,nParticlesGas);% XY_gasPos contains still some very close neighbours (touching particles)[~,representativeOfCluster]=unique(clusterIndex);% get only one member of each clustergasPos_x=XY_gasPos(representativeOfCluster,1);% extract nicely distributed quasi-random random numbersgasPos_y=XY_gasPos(representativeOfCluster,2);% extract nicely distributed quasi-random random numberscolorShading=interp1([01],[0.70.5],gasPos_y);gasPos_y_scale=(gasPos_y-0.5)*2*(innerRad-wall/2);% scale to full radiusgasOffset_x=(rand(nParticlesGas,1)-0.5).*wall*0.3;% gasOffset_y=(rand(nParticlesGas,1)-0.5).*wall*0.3;% end%% plot loopforiFrame=1:nFramesfigure(figHandle);clagasTempPercent=round((oilPos(iFrame)-minOilPos)/(maxOilPos-minOilPos)*99)+1;ifstrcmp(mode{1},'Twin_Tube_Damper')plotBox([l_outer-2*walll_outer],[-11]*(outerRad+wall),RGB.brightGrey,RGB.edge,liSc)% outer body left, bottomplotCylinder([l_outeroilPos(iFrame)],[-11]*outerRad,RGB.oil,RGB.edge,liSc,false)% outer body inner void (oil)plotCylinder([oilPos(iFrame)r_outer],[-11]*outerRad,gasColMap(gasTempPercent,:),RGB.edge,liSc,false)% outer body inner void (air)xLid=[...r_outerr_outer+2*wall;... box1r_innerr_inner+3*wall];% box2, both boxes will be unified into one objectyLid=[...[-11]*(outerRad+wall);... box1[-11]*innerRad];% box2, both boxes will be unified into one objectplotBox(xLid,yLid,RGB.brightGrey,RGB.edge,liSc)% outer body right, lidplotBox([l_outer-wallr_outer+wall],[outerRadouterRad+wall],RGB.brightGrey,RGB.edge,liSc)% outer body upper wallplotBox([l_outer-wallr_outer+wall],-[outerRadouterRad+wall],RGB.brightGrey,RGB.edge,liSc)% outer body lower wallplotCylinder([l_innerr_inner],[-11]*innerRad,RGB.oil,RGB.edge,liSc,false)% inner body oil fillingelse% Mono_Tube_DamperplotCylinder([AirOilSeparatorPos(iFrame,2)r_inner],[-11]*innerRad,RGB.oil,RGB.edge,liSc,false)% inner body oil fillingplotBox(AirOilSeparatorPos(iFrame,:),[-11]*innerRad,RGB.blueGrey,RGB.edge,liSc)% 2nd piston between oil and airplotCylinder([l_innerAirOilSeparatorPos(iFrame,1)],[-11]*innerRad,gasColMap(gasTempPercent,:),RGB.edge,liSc,false)% inner body air fillingplotBox(AirOilSeparatorPos(iFrame,:)+[wall-wall],[0-wall/2]+innerRad,[0.10.10.1],RGB.edge,liSc)% flat piston sealplotBox(AirOilSeparatorPos(iFrame,:)+[wall-wall],[0+wall/2]-innerRad,[0.10.10.1],RGB.edge,liSc)% flat piston sealplotBox([r_innerr_outer+3*wall],[-11]*(innerRad+wall),RGB.brightGrey,RGB.edge,liSc)% outer body right, lidendplotBox([l_inner-2*walll_inner],[-11]*(innerRad+wall),RGB.brightGrey,RGB.edge,liSc)% inner body left, bottomplotBox([l_inner-wallr_inner+3*wall],[innerRadinnerRad+wall],RGB.brightGrey,RGB.edge,liSc)% inner body upper wallplotBox([l_inner-wallr_inner+3*wall],-[innerRadinnerRad+wall],RGB.brightGrey,RGB.edge,liSc)% inner body upper wallifstrcmp(mode{1},'Twin_Tube_Damper')plotCylinder([l_inner-2*walll_inner],+holeY,RGB.oil,RGB.edge,liSc,false)% hole in inner lidplotCylinder([l_inner-2*walll_inner],-holeY,RGB.oil,RGB.edge,liSc,false)% hole in inner lidendplotSeal([12]*wall+r_outer,[0wall]+rodRad,RGB.brightGrey,RGB.edge,liSc,'\')% plot upper wiper sealplotSeal([12]*wall+r_outer,[0-wall]-rodRad,RGB.brightGrey,RGB.edge,liSc,'/')% plot lower wiper sealplotSeal([12]*wall+r_inner,[0wall]+rodRad,RGB.brightGrey,RGB.edge,liSc,'o')% plot o-RingplotSeal([12]*wall+r_inner,[0-wall]-rodRad,RGB.brightGrey,RGB.edge,liSc,'o')% plot o-RingplotCylinder(pistonPos(iFrame,2)+[0rodLenght],[-11]*rodRad,RGB.blueGrey,RGB.edge,liSc,true)% rodplotBox(pistonPos(iFrame,:),[-11]*innerRad,RGB.blueGrey,RGB.edge,liSc)% pistonplotCylinder(pistonPos(iFrame,:),+holeY,RGB.oil,RGB.edge,liSc,false)% hole in pistonplotCylinder(pistonPos(iFrame,:),-holeY,RGB.oil,RGB.edge,liSc,false)% hole in pistonplotBox(pistonPos(iFrame,:)+[wall-wall],[0-wall/2]+innerRad,[0.10.10.1],RGB.edge,liSc)% flat piston sealplotBox(pistonPos(iFrame,:)+[wall-wall],[0+wall/2]-innerRad,[0.10.10.1],RGB.edge,liSc)% flat piston sealfigure(figHandle)scatter(... % plot oil particles(ctrs(:,2,iFrame)*oilRed/scaleReduction-1)*(xRange/xSize)+xLimits(1),... % x-pos(ctrs(:,1,iFrame)*oilRed/scaleReduction-1)*(yRange/ySize)+yLimits(1),... % y-pos(liSc^2)*10,'o',... % size and shape'LineWidth',liSc,...'MarkerEdgeColor',RGB.oil.*0.6,...'MarkerFaceColor',RGB.oil.*0.9,...'MarkerEdgeAlpha',0.5,...'MarkerFaceAlpha',0.5)ifstrcmp(mode{1},'Twin_Tube_Damper')gasPos_x_scale=interp1([01],[oilPos(iFrame)+wall/4,r_outer-wall/4],gasPos_x);else% Mono_Tube_DampergasPos_x_scale=interp1([01],[l_inner+wall/2,AirOilSeparatorPos(iFrame,1)-wall/2],gasPos_x);endscatter(... % plot gas particlesgasPos_x_scale+gasOffset_x*gasTempPercent/100+randn(nParticlesGas,1)*0.05*gasTempPercent/100,... % x-posgasPos_y_scale+gasOffset_y*gasTempPercent/100+randn(nParticlesGas,1)*0.05*gasTempPercent/100,... % y-pos200+(pistonPos(iFrame,2)^2*(liSc^2)*0.8),...colorShading*gasColMap(gasTempPercent,:),...'.')%% save animationxlim(xLimits);ylim(yLimits);% set axis limitsaxisequal;drawnow;f=getframe(figHandle);switchform{1}% Init frame(s)case{'mp4'}writeVideo(vid,rot90(f.cdata));% save video framescase{'gif'}reducedRGBimage(:,:,:,iFrame)=imReduceSize(f.cdata,scaleReduction);% the size reduction: adds antialiasingendifiFrame==nFramesplot((col*oilRed/scaleReduction-1)*(xRange/xSize)+xLimits(1),(row*oilRed/scaleReduction-1)*(yRange/ySize)+yLimits(1),'.b')% check points for clustering (debug)endend% plot loopswitchform{1}%case'gif'colormapImage=permute(reducedRGBimage(:,:,:,:),[1243]);% step1; make unified imagecolormapImage=reshape(colormapImage,[ySize,xSize*(nFrames)31]);% step2; make unified imagemap=createImMap(colormapImage,256,[RGB.edge;RGB.white;RGB.brightGrey;RGB.blueGrey;RGB.oil;min(colorShading)*gasColMap(end,:)]);% colormapforiFrame=1:nFramesim=rgb2ind(reducedRGBimage(:,:,:,iFrame),map,'dither');ifiFrame==1imwrite(rot90(im),map,fullfile(pathstr,[mode{1}'.gif']),'LoopCount',Inf,'DelayTime',delayTime(iFrame));% individual timingselseimwrite(rot90(im),map,fullfile(pathstr,[mode{1}'.gif']),'WriteMode','append','DelayTime',delayTime(iFrame));% individual timingsendenddisp([mode{1}'.gif has 'num2str(numel(reducedRGBimage)/3/10^6,4)' Megapixels'])% Category:Animated GIF files exceeding the 100 MP limitcase'mp4'close(vid);disp(['MP4 completed: 'mode{1}'.mp4']);disp(['Conversion of 'mode{1}' from MP4 to WebM (Matlab currently does not support webm)']);ifexist('ffmpeg.exe','file')==2% check if it is a valid path to an existing filetrydosCommand=['!ffmpeg -i 'mode{1}'.mp4 '... % Command and source'-c:v libvpx-vp9 -crf 30 -b:v 0 -deadline best '... % constant (best) quality; see: https://trac.ffmpeg.org/wiki/Encode/VP9'-metadata title="'mode{1}'" '... % see: https://wiki.multimedia.cx/index.php/FFmpeg_Metadata'-metadata author="Jahobr" -metadata copyright="CC0 1.0 Universal Public Domain Dedication" '...'-metadata license="CC0 1.0 Universal Public Domain Dedication" '...mode{1}'.webm'];% conversion targeteval(dosCommand);% run conversion from mp4 to webm% delete(fullfile(pathstr,[mode{1} '.mp4'])); % delete mp4 version after conversion (to save disc space)catchMEdisp(ME)endelsedisp(['"ffmpeg.exe" not available in path "'pathstr'" (or other problem); see https://ffmpeg.zeranoe.com/builds/']);endendendendfunctiondisc(x,y,r,colFa)% x coordinates of the center% y coordinates of the center% r is the radius of the circle% colFa face color [r g b]angleOffPoints=linspace(0,2*pi,300);xc=x+r*sin(angleOffPoints);yc=y+r*cos(angleOffPoints);patch(xc,yc,'k','LineWidth',1,'EdgeColor','none','FaceColor',colFa);functionplotSeal(x,y,colFa,colEd,linw,type)% x [left right]% y [top bottom]% colFa face color [r g b]% colEd edge color [r g b]% linw line widthx=sort(x);y=sort(y);% just nor make sureplotBox(x,y,colFa,colEd,linw)switchtypecase{'o','O'}disc(mean(x),mean(y),(y(2)-y(1))/2.3,[0.10.10.1])case'/'plot(x,y,'Color',colEd,'LineWidth',linw*1.5)case'\'plot([x(2)x(1)],y,'Color',colEd,'LineWidth',linw*1.5)endfunctionplotBox(x,y,colFa,colEd,linw)% x [left right]% y [top bottom]% Or % x [left right;... box1% left right] % box2, both boxes will be unified int one object% y [left right;... box1% left right] % box2, both boxes will be unified int one object% colFa face color [r g b]% colEd edge color [r g b]% linw line widthxs=[];% xys=[];% yforiBox=1:size(x,1)xAdd=[x(iBox,2)x(iBox,2)x(iBox,1)x(iBox,1)x(iBox,2)x(iBox,2)];% xyAdd=[mean(y(iBox,:))y(iBox,1)y(iBox,1)y(iBox,2)y(iBox,2)mean(y(iBox,:))];% y joint in the middle of an edge to get nice corners[xs,ys]=polybool('union',xs,ys,xAdd,yAdd);endifstrcmp(colFa,'none')plot(xs,ys,'Color',colEd,'LineWidth',linw)%elsepatch(xs,ys,colFa,'EdgeColor',colEd,'LineWidth',linw)%endfunctionplotCylinder(x,y,colFa,colEd,linw,material_or_hole)% x [left right]% y [top bottom]% colFa face color [r g b]% colEd edge color [r g b]% linw line width% material_or_hole: 1 Material, Highlight in top% 0 Hole, Highlight in bottomx=sort(x);y=sort(y);ifmaterial_or_holey=flip(y);endy_center=mean(y);y_highlight=mean([y(1)y_center]);vertex_matrix=[% clockwise 8----1x(1)y(1);% 1 right top ¦ ¦x(1)y_highlight;% 2 right upper highlight 7----2x(1)y_center;% 3 right center ¦ ¦x(1)y(2);% 4 right bottom 6----3x(2)y(2);% 5 left bottom ¦ ¦x(2)y_center;% 6 left center ¦ ¦x(2)y_highlight;% 7 left upper highlight ¦ ¦x(2)y(1)];% 8 left top 5----4vertex_color=[% color matrixcolFa;% 1 top 1-(1-colFa)*0.6;% 2 upper highlight (brighter)colFa;% 3 center colFa*0.8];% 4 bottom (darker)vertex_color=[vertex_color;flipud(vertex_color)];% colors 5 to 8 in inverse orderfaces_matrix=[% top to bottom127;% top to highlight, upper right triangle178;% top to highlight, lower left triangle236;% highlight to center, upper right triangle267;% highlight to center, lower left triangle345;% center to bottom, upper right triangle356];% center to bottom, lower left trianglepatch('Vertices',vertex_matrix,'Faces',faces_matrix,...'FaceVertexCData',vertex_color,'FaceColor','interp',...'Edgecolor','none');plotBox(x,y,'none',colEd,linw)functionim=imReduceSize(im,redSize)% Input:% im: image, [imRows x imColumns x nChannel x nStack] (unit8)% imRows, imColumns: must be divisible by redSize% nChannel: usually 3 (RGB) or 1 (grey)% nStack: number of stacked images% usually 1; >1 for animations% redSize: 2 = half the size (quarter of pixels)% 3 = third the size (ninth of pixels)% ... and so on% Output:% im: [imRows/redSize x imColumns/redSize x nChannel x nStack] (unit8)%% an alternative is: imNew = imresize(im,1/reduceImage,'bilinear');% BUT 'bicubic' & 'bilinear' produces fuzzy lines% IMHO this function produces nicer results as "imresize"[nRow,nCol,nChannel,nStack]=size(im);ifredSize==1;return;end% nothing to doifredSize~=round(abs(redSize));error('"redSize" must be a positive integer');endifrem(nRow,redSize)~=0;error('number of pixel-rows must be a multiple of "redSize"');endifrem(nCol,redSize)~=0;error('number of pixel-columns must be a multiple of "redSize"');endnRowNew=nRow/redSize;nColNew=nCol/redSize;im=double(im).^2;% brightness rescaling from "linear to the human eye" to the "physics domain"; see youtube: /watch?v=LKnqECcg6Gwim=reshape(im,nRow,redSize,nColNew*nChannel*nStack);% packets of width redSize, as columns next to each otherim=sum(im,2);% sum in all rows. Size of result: [nRow, 1, nColNew*nChannel]im=permute(im,[3,1,2,4]);% move singleton-dimension-2 to dimension-3; transpose image. Size of result: [nColNew*nChannel, nRow, 1]im=reshape(im,nColNew*nChannel*nStack,redSize,nRowNew);% packets of width redSize, as columns next to each otherim=sum(im,2);% sum in all rows. Size of result: [nColNew*nChannel, 1, nRowNew]im=permute(im,[3,1,2,4]);% move singleton-dimension-2 to dimension-3; transpose image back. Size of result: [nRowNew, nColNew*nChannel, 1]im=reshape(im,nRowNew,nColNew,nChannel,nStack);% putting all channels (rgb) back behind each other in the third dimensionim=uint8(sqrt(im./redSize^2));% mean; re-normalize brightness: "scale linear to the human eye"; back in uint8functionmap=createImMap(imRGB,nCol,startMap)% createImMap creates a color-map including predefined colors.% "rgb2ind" creates a map but there is no option to predefine some colors,% and it does not handle stacked images.% Input:% imRGB: image, [imRows x imColumns x 3(RGB) x nStack] (unit8)% nCol: total number of colors the map should have, [integer]% startMap: predefined colors; colormap format, [p x 3] (double)imRGB=permute(imRGB,[1243]);% step1; make unified column-image (handling possible nStack)imRGBcolumn=reshape(imRGB,[],1,3,1);% step2; make unified column-imagefullMap=double(permute(imRGBcolumn,[132]))./255;% "column image" to color map [fullMap,~,imMapColumn]=unique(fullMap,'rows');% find all unique colors; create indexed colormap-image% "cmunique" could be used but is buggy and inconvenient because the output changes between "uint8" and "double"nColFul=size(fullMap,1);nColStart=size(startMap,1);disp(['Number of colors: 'num2str(nColFul)' (including 'num2str(nColStart)' self defined)']);ifnCol<=nColStart;error('Not enough colors');endifnCol>nColFul;warning('More colors than needed');endisPreDefCol=false(size(imMapColumn));% initforiCol=1:nColStartdiff=sum(abs(fullMap-repmat(startMap(iCol,:),nColFul,1)),2);% difference between a predefined and all colors[mDiff,index]=min(diff);% find matching (or most similar) colorifmDiff>0.05% color handling is not precisewarning(['Predefined color 'num2str(iCol)' does not appear in image'])continueendisThisPreDefCol=imMapColumn==index;% find all pixel with predefined colordisp([num2str(sum(isThisPreDefCol(:)))' pixel have predefined color 'num2str(iCol)]);isPreDefCol=or(isPreDefCol,isThisPreDefCol);% combine with overall listend[~,mapAdditional]=rgb2ind(imRGBcolumn(~isPreDefCol,:,:),nCol-nColStart,'nodither');% create map of remaining colorsmap=[startMap;mapAdditional];functionim=randSubsampling(im, imRed)% Input:% Subsampling image. Colors are not mixed, no new colors are created.% im: image, [imRows x imColumns x nChannel] (unit8)% imRows, imColumns: must be divisible by redSize% nChannel: usually 3 (RGB) or 1 (grey)% redSize: 2 = half the size (quarter of pixels)% 3 = third the size (ninth of pixels)% ... and so on% Example: imRed=3 results in use of one 010 000 000 000 100 000 000% random specimen chosen from 000 000 001 010 000 000 001% the 3x3-origal pixel block 000 100 000 000 000 100 000 [nRow,nCol,nChannel]=size(im);index=reshape(1:nRow*nCol,nRow,nCol);% build index matrix using linear indexingindex=index(1:imRed:end,1:imRed:end);% reduce size (this uses effectively the upper left corner of each sub-box)[nRowTarget,nColTarget]=size(index);% new sizerandRowOffset=randi([0imRed-1],nRowTarget,nColTarget);% rand row-offset within pixel blockindexCheckLimRow=nRowTarget*imRed+randRowOffset(end,:)>nRow;% find creation of index out of original image sizerandRowOffset(end,indexCheckLimRow)=0;% avoid creation of index out of original image sizerandColOffset=randi([0imRed-1],nRowTarget,nColTarget);% rand col-offset within pixel blockindexCheckLimCol=nColTarget*imRed+randColOffset(:,end)>nCol;% find creation of index out of original image sizerandColOffset(indexCheckLimCol,end)=0;% avoid creation of index out of original image sizeindex=index+randRowOffset+randColOffset*nRow;% create linear indexing that chooses random pixel in each pixel blockifnChannel==3index=repmat(index,1,1,3);% for each color channelindex(:,:,2)=index(:,:,2)+nRow*nCol;% for each color channelindex(:,:,3)=index(:,:,3)+nRow*nCol*2;% for each color channelendim=im(index);
Lizenz
Ich, der Urheber dieses Werkes, veröffentliche es unter der folgenden Lizenz:
Die Person, die das Werk mit diesem Dokument verbunden hat, übergibt dieses weltweit der Gemeinfreiheit, indem sie alle Urheberrechte und damit verbundenen weiteren Rechte – im Rahmen der jeweils geltenden gesetzlichen Bestimmungen – aufgibt. Das Werk kann – selbst für kommerzielle Zwecke – kopiert, modifiziert und weiterverteilt werden, ohne hierfür um Erlaubnis bitten zu müssen.
http://creativecommons.org/publicdomain/zero/1.0/deed.enCC0Creative Commons Zero, Public Domain Dedicationfalsefalse
Kurzbeschreibungen
Ergänze eine einzeilige Erklärung, was diese Datei darstellt.