File:Unnecessarily complicated gears a.gif

From The Jolly Contrarian
Jump to navigation Jump to search

Original file(840 × 700 pixels, file size: 15.79 MB, MIME type: image/gif, looped, 170 frames, 6.8 s)

Note: Due to technical limitations, thumbnails of high resolution GIF images such as this one will not be animated.

This file is from Wikimedia Commons and may be used by other projects. The description on its file description page there is shown below.

Summary

Description
العربية: رسمٌ مُتحرِّكٌ يُظهر نقل الحركة في التُرُوس التدويريَّة والجرائد المُسنَّنة.
Deutsch: Animation von Zahnrädern inkusive eines Planetengetriebes und einer Zahnstange.
English: Animation of Gears including epicyclic gears and a Rack and pinion.
Polski: Animacja przedstawiająca przekładnie zębate, w tym przekładnię obiegowązębatkę.
Українська: Анімація коліщат, включаючи епіциклічну передачу та рейкову передачу.
Čeština: Animace funkce převodu síly a pohybu pomocí ozubených kol včetně planetové převodovky a dalších aplikací.
Македонски: Анимација на механички пренос со планетарни запченици и назабена летва
Русский: Анимация различных видов зубчатой передачи, включая планетарную и реечную
Date
Source Own work
Author Jahobr
GIF development
InfoField
 
This diagram was created with MATLAB by Jahobr.
Source code
InfoField

MATLAB code

code
function unnecessarily_complicated_gears()
% source code for drawing unnecessarily complicated gearing
% The shape of the gears is not precise, it creates a decent GIF and a SVG.
%
% 2017-06-20 Jahobr (update 2019-04-14 Jahobr)

teethSun  = 48; % 
teethPlan = 12; % 
teethRing = teethSun+teethPlan*2;
nPlan = 12; % number of planets

teethSun_top = 24;
teethHub_spoked = 60;
teethHub_back = 24;
teethBigSpoke = 96;
teethRackTrans_Bottom = 25;
teethRackTrans_Top = 25/5*4;
teethRackDriver  = 16;

module_Epicyclic = 1;
module_Hub_Spoke = 1.8;
module_Sun_Hub = 1.5;
module_LL = 0.8;
module_top = 0.9;
module_Rack = 1.4;

RGB.edge      = [0    0    0   ]; % Edge color
RGB.bkgd      = [1    1    1   ]; % white background
RGB.carrier   = [0.1  0.7  0.1 ]; % green
RGB.sun       = [0.95 0.65 0   ]; % yellow (obviously)
RGB.palnet    = [0.2  0.2  1   ]; % blue   (obviously)
RGB.ring      = [1    0.2  0.2 ]; % red
RGB.hub       = [0.6  0.2  0.8 ]; % violet
RGB.spoke     = [0.5  0.5  0.5 ]; % 
RGB.rackTrans = [0.4  0.24 0.08]; % 
RGB.rack      = [1    0.5  0.2 ]; % 
RGB.rackDrive = [0.8  0.3  0.2 ]; % 
RGB.LL_1      = [0.4  0.6  0.6 ]; % 
RGB.LL_2      = [0.3  0.6  0.8 ]; % 
RGB.top       = [0.5  0.7  1   ]; % 

RGB = structfun(@(q)round(q*255)/255, RGB, 'UniformOutput',false); % round to values that are nicely uint8 compatible

diameterSun  = module_Epicyclic.*teethSun;
diameterPlan = module_Epicyclic.*teethPlan;
diameterCarr = diameterSun+diameterPlan;

dist_Sun_Hub = mean([module_Sun_Hub*teethSun_top, module_Sun_Hub*teethHub_spoked]);
centerHub = [dist_Sun_Hub*cosd(60) -dist_Sun_Hub*sind(60)];

dist_Hub_Spoke = mean([module_Hub_Spoke*teethHub_back, module_Hub_Spoke*teethBigSpoke]) ;
centerSpoke = [dist_Hub_Spoke*cosd(60) +dist_Hub_Spoke*sind(60)]+centerHub;

dist_Hub_RackTrans = mean([module_Sun_Hub*teethHub_spoked, module_Sun_Hub*teethRackTrans_Bottom]); 
centerRackTrans = [dist_Hub_RackTrans*cosd(53) +dist_Hub_RackTrans*sind(53)]+centerHub;

dist_RackTrans_RGB.rackDriver = mean([module_Rack*teethRackTrans_Top, module_Rack*teethRackDriver ]);
centerRackDriver = [dist_RackTrans_RGB.rackDriver*cosd(55) -dist_RackTrans_RGB.rackDriver*sind(55)]+centerRackTrans;

[pathstr,fname] = fileparts(which(mfilename)); % save files under the same name and at file location

xLimits = [-20 100];
yLimits = [-60  40];

xRange = xLimits(2)-xLimits(1);
yRange = yLimits(2)-yLimits(1);

ySize = 700; % final gif size
xSize = floor(ySize/yRange*xRange); % pixel
screenSize = get(groot,'Screensize')-[0 0 5 20]; % [1 1 width height] (minus tolerance for figure borders)
scaleReduction = min(...% reduction for nice antialiasing (for >1 you need a 4K monitor or a virtural combination of several monitors using "Nvidia Surround" to fit the figure)
    floor(screenSize(4)/ySize), floor(screenSize(3)/xSize)); 
linW = 2.5/1000 * (ySize*scaleReduction); % LineWidth
nFrames = 170;

figHandle = figure(15674455); clf
set(figHandle, 'Units','pixel');
set(figHandle, 'Position',[1 1 xSize*scaleReduction ySize*scaleReduction]); % big start image for antialiasing later [x y width height]
set(figHandle, 'GraphicsSmoothing','on') % requires at least version 2014b
set(figHandle,'MenuBar','none',  'ToolBar','none'); % free real estate for a maximally large image
set(figHandle, 'Color',RGB.bkgd); % white background
axesHandle = axes;
hold(axesHandle,'on');  
axis off % invisible axes (no ticks)
axis equal;
setXYlim(axesHandle,xLimits,yLimits);

angleCarrier = -linspace(0,pi*2/nPlan,nFrames+1); % define gear position in frames
angleCarrier = angleCarrier(1:end-1); % remove last frame, it would be double

anglePlan = angleCarrier.*( teethSun/teethPlan+1 ); % gear ratio
anglePlan = -anglePlan + (pi/teethPlan); % ALLIGNMENT; THIS MAY NEED MANUAL ADJUSTMENT

angleSun = angleCarrier.*  (1+teethRing/teethSun); % gear ratio
angleSun = angleSun + 0; % ALLIGNMENT; THIS MAY NEED MANUAL ADJUSTMENT

angleRing = zeros(size(anglePlan));
reducedRGBimage = uint8(ones(ySize,xSize,3,nFrames)); % allocate

for iFrame = 1:nFrames
    cla(axesHandle); % fresh frame
    
    %% background wheels
    % Hub background wheel  24 teeth rotates 2, interacts with spoked
    drawSpurWheel(centerHub,teethHub_back ,module_Hub_Spoke,... % center, number of teeth, module
        RGB.hub*0.6, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/2.5,... % angle of rotaion
        NaN, 1, 3, 1); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % fine Spoked wheel 96 teeth rotates 2
    drawSpurWheel(centerSpoke,teethBigSpoke, module_Hub_Spoke,... % center, number of teeth, module
        RGB.spoke, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/2.5/4 + pi/teethBigSpoke,... % angle of rotaion
        teethBigSpoke/2, 0.5, 0, 13.2); % nSpoke, spokeW, sideOffset, shaftDiameter
     
    %% %%%%%%%%%%     Epicyclic_Gearing    %%%%%%%%%%%%%%%%%%%%%
    % ring
    drawRingGear(teethRing,module_Epicyclic,RGB.ring,linW,RGB.edge,angleRing(iFrame))
    
    % sun
    drawSpurWheel([0 0],teethSun ,module_Epicyclic,... % center, number of teeth, module
        RGB.sun, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame),... % angle of rotaion
        NaN, 0, 0, 0); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % planets
    angPlan = linspace(0,2*pi,nPlan+1);
    angPlan = angPlan(1:end-1);
    for iPlan = angPlan
        [X,Y] = pol2cart(iPlan+angleCarrier(iFrame) ,diameterCarr/2);
        drawSpurWheel([X,Y],teethPlan,module_Epicyclic,... % center, number of teeth, module
            RGB.palnet, linW, RGB.edge,... % patch color, LineWidth, line color
            anglePlan(iFrame),... % angle of rotaion
            NaN, 0, 0, 0); % nSpoke, spokeW, sideOffset, shaftDiameter
    end
    
    % carrier
    angCarr = linspace(0,2*pi,nPlan+1);
    [X,Y] = pol2cart([angCarr  fliplr(angCarr)]+angleCarrier(iFrame) ,[ones(size(angCarr))*diameterCarr/2.07 ones(size(angCarr))* diameterCarr/1.93]);
    patch(X,Y,RGB.carrier,'EdgeColor',RGB.edge,'LineWidth',linW) % full outer disc
    
    for iPlan = angPlan
        [X,Y] = pol2cart(iPlan+angleCarrier(iFrame) ,diameterCarr/2);
        circlePatch(X,Y,diameterPlan*0.25,RGB.carrier,linW,RGB.edge);
        circlePatch(X,Y,diameterPlan*0.15,RGB.palnet, linW,RGB.edge);
    end
    
    %% connection Epicyclic Gearing and hub
    % 24 teeth, rotates 5 teeth
    drawSpurWheel([0 0],teethSun_top ,module_Sun_Hub,... % center, number of teeth, module
        1-(1-RGB.sun)*0.5, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame),... % angle of rotaion
        NaN, 0, 0, 3); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % spoked hub wheel: 60 teeth; rotates 5
    drawSpurWheel(centerHub,teethHub_spoked ,module_Sun_Hub,... % center, number of teeth, module
        RGB.hub, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/2.5 +pi/teethHub_spoked,... % angle of rotaion
        teethSun/2*2.5/5,... % 12 nSpoke,
        1, 5.5, 7); % spokeW, sideOffset, shaftDiameter
    
    %% chain of wheels on the Top
    % on top big spoked (wheel 96 teeth rotates 2) 48 teeth rotates 1
    drawSpurWheel(centerSpoke,48 ,module_top,... % center, number of teeth, module
        1-(1-RGB.spoke)*0.7, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/2.5/4+0.2,... % angle of rotaion
        NaN, 1, 0, 7); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % top idler , meshing with small wheel big spoked; 17 teeth rotates 1
    drawSpurWheel([57.35 31],17 ,module_top,... % center, number of teeth, module
        RGB.top, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/2.5/4 * 48/17  - 0.067,... % angle of rotaion
        NaN, 1, 0, 3); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % last on top, meshing with idler; 23 teeth rotates 1
    drawSpurWheel([42.34 41],23 ,module_top,... % center, number of teeth, module
        RGB.top*0.8, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/2.5/4 * 48/23  +0.12,... % angle of rotaion
        NaN, 1, 0, 3); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    %% Rack
    % Rack-Transmission; meshes in Hub-spoked 25 teeth rotates 5
    drawSpurWheel(centerRackTrans,teethRackTrans_Bottom,module_Sun_Hub,... % center, number of teeth, module
        RGB.rackTrans, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/teethRackTrans_Bottom*teethSun_top +0.003,... % angle of rotaion
        NaN, 1, 0, 0); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % Rack-Transmission; meshes in Rack-driver; 15 teeth rotates 3
    drawSpurWheel(centerRackTrans,teethRackTrans_Top,module_Rack,... % center, number of teeth, module
        1-(1-RGB.rackTrans)*0.7,linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/teethRackTrans_Bottom*teethSun_top +0.157,... % angle of rotaion
        NaN, 1, 0, 2.5); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    % Rack-driver; idler between Rack-Transmission and Rack
    drawSpurWheel(centerRackDriver,teethRackDriver ,module_Rack,... % center, number of teeth, module
        RGB.rackDrive, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/teethRackTrans_Bottom*teethSun_top *15/12 +pi/teethRackDriver ,... % angle of rotaion
        NaN, 0.5, 0, 2); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    drawRack([centerRackDriver(1)+module_Rack*teethRackDriver/2 centerRackDriver(2)],50,module_Rack,...
        RGB.rack,linW,RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/teethRackTrans_Bottom*teethSun_top *module_Rack/2*teethRackTrans_Top)
    
    %% lower left
    %  on top of hub; rotates 3 teeth
    drawSpurWheel(centerHub,36 ,module_LL,... % center, number of teeth, module
        1-(1-RGB.hub)*0.9, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/2.5,... % angle of rotaion
        NaN, 1, 3, 9); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    %  next to hub; lower left trasmission; bottom wheel; rotates 3 teeth
    drawSpurWheel([centerHub(1)-28.8 centerHub(2)],36 ,module_LL,... % center, number of teeth, module
        RGB.LL_1*0.5, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/2.5 +pi/36,... % angle of rotaion
        NaN, 1, 0, 1); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    %  lower left trasmission; top wheel; rotates 2 teeth
    drawSpurWheel([centerHub(1)-28.8 centerHub(2)],24 ,module_LL,... % center, number of teeth, module
        RGB.LL_1, linW, RGB.edge,... % patch color, LineWidth, line color
        angleSun(iFrame)/2.5 ,... % angle of rotaion
        NaN, 1, 0, 4); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    %  lower left wheel; rotates 2 teeth; rotates 1 spoke
    drawSpurWheel([centerHub(1)-57.6 centerHub(2)],48 ,module_LL,... % center, number of teeth, module
        RGB.LL_2, linW, RGB.edge,... % patch color, LineWidth, line color
        -angleSun(iFrame)/2.5  /2 +pi/48,... % angle of rotaion
        24, 1, 0, 10); % nSpoke, spokeW, sideOffset, shaftDiameter
    
    %% save animation
    setXYlim(axesHandle,xLimits,yLimits);
    f = getframe(figHandle);
    reducedRGBimage(:,:,:,iFrame) = imReduceSize(f.cdata,scaleReduction); % the size reduction: adds antialiasing
    
%     if iFrame == 10 % SVG
%         if ~isempty(which('plot2svg'))
%             plot2svg(fullfile(pathstr, [fname '_a.svg']),figHandle) % by Juerg Schwizer
%         else
%             disp('plot2svg.m not available; see http://www.zhinst.com/blogs/schwizer/');
%         end
%     end

end

map = createImMap(reducedRGBimage,128,struct2map(RGB)); % colormap

im = uint8(ones(ySize,xSize,1,nFrames)); % allocate
for iFrame = 1:nFrames
    im(:,:,1,iFrame) = rgb2ind(reducedRGBimage(:,:,:,iFrame),map,'nodither');
end

imwrite(im,map,fullfile(pathstr, [fname '_a.gif']),'DelayTime',1/25,'LoopCount',inf) % save gif
disp([fname '.gif  has ' num2str(numel(im)/10^6 ,4) ' Megapixels']) % Category:Animated GIF files exceeding the 100 MP limit


function drawSpurWheel(center,toothNumber,module,colFilling,linW,linC,startOffset,nSpoke,spokeW,sideOffset,shaftDia)
% DRAWSPURWHEEL - draw a simple Toothed Wheel
%    center:       [x y]
%    toothNumber:  scalar
%    module:       scalar tooth "size"
%    colFilling:   color of filling [r g b]
%    linW:         LineWidth (scalar)
%    linC:         LineColor
%    startOffset:  start rotation (scalar)[rad] 
%    nSpoke:       number of spokes; NaN for filled wheel (scalar integer) 
%    spokeW:       spoke width  [modules]
%    sideOffset:   spoke side offset  [modules]
%    shaftDia:     inner shaft diameter  [modules]

effectiveRadius = module*toothNumber/2; % effective effectiveRadius

outsideRadius =     effectiveRadius+1*  module; %                +---+             +---+
upperRisingRadius = effectiveRadius+0.5*module; %               /     \           /     \
% effective Radius                              %              /       \         /       \
lowerRisingRadius = effectiveRadius-0.5*module; %             I         I       I         I
rootRadius =        effectiveRadius-1.1*module; %     + - - - +         + - - - +         +

angleBetweenTeeth = 2*pi/toothNumber; % angle between 2 teeth

angleOffPoints = (0:angleBetweenTeeth/16:(2*pi));
angleOffPoints = angleOffPoints+startOffset; % apply rotation offset

angleOffPoints(7:16:end)  = angleOffPoints(7:16:end)  + 1/toothNumber^1.2; % hack to create smaller tooth tip
angleOffPoints(11:16:end) = angleOffPoints(11:16:end) - 1/toothNumber^1.2; % hack to create smaller tooth tip

angleOffPoints(8:16:end)  = (angleOffPoints(7:16:end)  + angleOffPoints(9:16:end))/2; % shift the neighbouring tip point in accordingly
angleOffPoints(10:16:end) = (angleOffPoints(11:16:end) + angleOffPoints(9:16:end))/2; % shift the neighbouring tip point in accordingly

angleOffPoints(6:16:end)  = angleOffPoints(6:16:end)  + 1/toothNumber^1.7; % hack to create slender upperRisingRadius
angleOffPoints(12:16:end) = angleOffPoints(12:16:end) - 1/toothNumber^1.7; % hack to create slender upperRisingRadius

radiusOffPoints = angleOffPoints; % allocate with correct site

radiusOffPoints( 1:16:end) = rootRadius;        % center bottom         I
radiusOffPoints( 2:16:end) = rootRadius;        % left bottom           I
radiusOffPoints( 3:16:end) = rootRadius;        % left bottom corner    +
radiusOffPoints( 4:16:end) = lowerRisingRadius; % lower rising bottom      \
radiusOffPoints( 5:16:end) = effectiveRadius;   % rising edge                 \
radiusOffPoints( 6:16:end) = upperRisingRadius; % upper rising edge              \
radiusOffPoints( 7:16:end) = outsideRadius;     % right top  corner                 +
radiusOffPoints( 8:16:end) = outsideRadius;     % right top                         I
radiusOffPoints( 9:16:end) = outsideRadius;     % center top                        I
radiusOffPoints(10:16:end) = outsideRadius;     % left top                          I
radiusOffPoints(11:16:end) = outsideRadius;     % left top  corner                  +
radiusOffPoints(12:16:end) = upperRisingRadius; % upper falling edge             /
radiusOffPoints(13:16:end) = effectiveRadius;   % falling edge                /
radiusOffPoints(14:16:end) = lowerRisingRadius; % lower falling edge       /
radiusOffPoints(15:16:end) = rootRadius;        % right bottom  corner  +
radiusOffPoints(16:16:end) = rootRadius;        % right bottom          I

[X,Y] = pol2cart(angleOffPoints,radiusOffPoints);
X = X+center(1); % center offset
Y = Y+center(2); % center offset

if ~isnan(nSpoke)
    for iSpoke = 1:nSpoke
        Xs = ([-1 1 1 -1]+sideOffset)*module*spokeW;
        Ys =  [ 1 1 0  0]*(rootRadius-1*module);
        [Xs,Ys] = rotateCordiantes(Xs,Ys,2*pi/nSpoke*iSpoke+startOffset);% apply rotation
        Xs = Xs+center(1); % center offset
        Ys = Ys+center(2); % center offset
        patch(Xs,Ys,colFilling*0.85,'EdgeColor',linC,'LineWidth',linW)
    end
    
    [Xc,Yc] = pol2cart(angleOffPoints,effectiveRadius-3*module);
    Xc = Xc+center(1); % center offset
    Yc = Yc+center(2); % center offset

    [Xc,Yc] = poly2cw(Xc,Yc);
    [X,Y] = poly2cw(X,Y);
    [Xb,Yb] = polybool('subtraction', X,Y,Xc,Yc);
    Xb = Xb(~isnan(Xb)); % notNaN
    Yb = Yb(~isnan(Yb)); % notNaN
    patch(Xb,Yb,colFilling,'EdgeColor','none')
    
    plot(X, Y, 'LineWidth',linW,'Color',linC); % extra line
    plot(Xc,Yc,'LineWidth',linW,'Color',linC); % extra line

else % filled
    patch(X,Y,colFilling,'EdgeColor',linC,'LineWidth',linW)
end
if and(~isnan(shaftDia),shaftDia>0)
    drawCirclePatch(center(1),center(2),shaftDia*module,1-(1-colFilling)*0.85,linW,linC);
end
% % effective Radius
% [X,Y] = pol2cart(angleOffPoints,effectiveRadius);
% X = X+center(1); % center offset
% Y = Y+center(2); % center offset
% plot(X,Y,'-.','Color',RGB.edge;


function h = circlePatch(x,y,r,col,linW,linC)
%    x and y:      coordinates of the center
%    r:            is the radius of the circle
%    fillC:        color of filling [r g b]
%    linW:         LineWidth
%    linC:         LineColor
angleOffPoints = linspace(0,2*pi,200);
xc = x + r*cos(angleOffPoints);
yc = y + r*sin(angleOffPoints);
% h = plot(xc,yc,'color',col,'LineWidth',linW,'LineStyle',sty);
h = patch(xc,yc,col,'EdgeColor',linC,'LineWidth',linW);


function [x,y] = rotateCordiantes(x,y,anglee)
%    x and y:      coordinates of the center
%    anglee:       angle of rotation in [rad]
rotM = [cos(anglee) -sin(anglee); sin(anglee) cos(anglee)];
x_y = rotM*[x(:)';y(:)'];
x = x_y(1,:);
y = x_y(2,:);


function drawRack(center,toothNumber,module,fillC,linW,linC,startOffset)
%    x and y:      coordinates of the center
%    toothNumber:  number of teeth
%    module:       scalar tooth "size"
%    fillC:        color of filling [r g b]
%    linW:         LineWidth
%    linC:         LineColor
%    startOffset: initial shift
y = (0:toothNumber*4-1)*pi*module/4;
y = y-mean(y)+center(2)+startOffset;
x = ones(size(y))*center(1);

x(1:4:end) = x(1:4:end)+1.1*module; %    +###I bottom
x(2:4:end) = x(2:4:end)-1  *module; % +######I tip
x(3:4:end) = x(3:4:end)-1  *module; % +######I tip
x(4:4:end) = x(4:4:end)+1.1*module; %    +###I bottom

y(1:4:end) = y(1:4:end)-0.14*module; % bottom smaller
y(2:4:end) = y(2:4:end)+0.14*module; % tip smaller
y(3:4:end) = y(3:4:end)-0.14*module; % tip smaller
y(4:4:end) = y(4:4:end)+0.14*module; % bottom smaller

y = [y(1) y y(end)];
x = [x(1)+5*module x x(end)+5*module];
patch(x,y,fillC,'EdgeColor',linC,'LineWidth',linW);


function drawCirclePatch(x,y,r,fillC,linW,linC)
%    x and y:      coordinates of the center
%    r:            is the radius of the circle
%    fillC:        color of filling [r g b]
%    linW:         LineWidth
%    linC:         LineColor
%    startOffset:  start rotation (scalar)[rad]
angleOffPoints = linspace(0,2.001*pi,200);
xc = x + r*cos(angleOffPoints);
yc = y + r*sin(angleOffPoints);
patch(xc,yc,fillC,'EdgeColor',linC,'LineWidth',linW);


function drawRingGear(toothNumber,module,fillC,linW,linC,startOffset)
% DRAWRINGGEAR - draw a outer gear
%
%  Input:
%    center:       [x y]
%    toothNumber:  scalar
%    module:       scalar tooth "size"
%    fillC:        color of filling [r g b]
%    linW:         LineWidth
%    linC:         LineColor
%    startOffset:  start rotation (scalar)[rad]
effectiveRadius = module*toothNumber/2; % effective effectiveRadius

outsideRadius     = effectiveRadius-1*  module; %                +---+             +---+
upperRisingRadius = effectiveRadius-0.5*module; %               /     \           /     \
% effective Radius                              %              /       \         /       \
lowerRisingRadius = effectiveRadius+0.5*module; %             I         I       I         I
rootRadius        = effectiveRadius+1.1*module; %     + - - - +         + - - - +         +

angleBetweenTeeth = 2*pi/toothNumber; % angle between 2 teeth
angleOffPoints = (0:angleBetweenTeeth/16:(2*pi));
angleOffPoints = angleOffPoints+startOffset; % apply rotation offset

%% outerEdge
maxRadius = rootRadius*1.2; % definition of outer line
[Xout,Yout] = pol2cart(angleOffPoints,maxRadius);

%% inner teeth
radiusOffPoints = angleOffPoints; % init

angleOffPoints( 7:16:end) = angleOffPoints(7:16:end)  + 1/toothNumber^1.2; % hack to create smaller tooth tip
angleOffPoints(11:16:end) = angleOffPoints(11:16:end) - 1/toothNumber^1.2; % hack to create smaller tooth tip

angleOffPoints( 8:16:end) = (angleOffPoints(7:16:end) +  angleOffPoints(9:16:end))/2; % shift the neighbouring tip point in accordingly
angleOffPoints(10:16:end) = (angleOffPoints(11:16:end) + angleOffPoints(9:16:end))/2; % shift the neighbouring tip point in accordingly

angleOffPoints( 6:16:end) = angleOffPoints(6:16:end)  + 1/toothNumber^1.7; % hack to create slender tooth
angleOffPoints(12:16:end) = angleOffPoints(12:16:end) - 1/toothNumber^1.7; % hack to create slender tooth

radiusOffPoints( 1:16:end) = rootRadius;        % center bottom         I
radiusOffPoints( 2:16:end) = rootRadius;        % left bottom           I
radiusOffPoints( 3:16:end) = rootRadius;        % left bottom corner    +
radiusOffPoints( 4:16:end) = lowerRisingRadius; % lower rising bottom      \
radiusOffPoints( 5:16:end) = effectiveRadius;   % rising edge                 \
radiusOffPoints( 6:16:end) = upperRisingRadius; % upper rising edge              \
radiusOffPoints( 7:16:end) = outsideRadius;     % right top corner                 +
radiusOffPoints( 8:16:end) = outsideRadius;     % right top                        I
radiusOffPoints( 9:16:end) = outsideRadius;     % center top                       I
radiusOffPoints(10:16:end) = outsideRadius;     % left top                         I
radiusOffPoints(11:16:end) = outsideRadius;     % left top corner                  +
radiusOffPoints(12:16:end) = upperRisingRadius; % upper falling edge             /
radiusOffPoints(13:16:end) = effectiveRadius;   % falling edge                /
radiusOffPoints(14:16:end) = lowerRisingRadius; % lower falling edge       /
radiusOffPoints(15:16:end) = rootRadius;        % right bottom corner   +
radiusOffPoints(16:16:end) = rootRadius;        % right bottom          I

[X,Y] = pol2cart(angleOffPoints,radiusOffPoints);

[Xout,Yout] = poly2cw(Xout,Yout);
[X,   Y   ] = poly2cw(X   ,Y   );
[Xb,Yb] = polybool('subtraction',Xout,Yout, X,Y);
Xb = Xb(~isnan(Xb)); % notNaN
Yb = Yb(~isnan(Yb)); % notNaN
patch(Xb,Yb,fillC,'EdgeColor','none')

plot(X,   Y,   'LineWidth',linW,'Color',linC); % draw teeth outline
plot(Xout,Yout,'LineWidth',linW,'Color',linC); % draw outer circle


function map = struct2map(RGB)
% RGB: struct of depth 1 with [r g b] in each field
fNames = fieldnames(RGB);
nNames = numel(fNames);
map = NaN(nNames,3); % allocate
for iName = 1:nNames
    map(iName,:) = RGB.(fNames{iName}); % 
end


function im = 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);

if redSize==1;  return;  end % nothing to do
if redSize~=round(abs(redSize));             error('"redSize" must be a positive integer');  end
if rem(nRow,redSize)~=0;     error('number of pixel-rows must be a multiple of "redSize"');  end
if rem(nCol,redSize)~=0;  error('number of pixel-columns must be a multiple of "redSize"');  end

nRowNew = 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=LKnqECcg6Gw
im = reshape(im, nRow, redSize, nColNew*nChannel*nStack); % packets of width redSize, as columns next to each other
im = 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 other
im = 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 dimension
im = uint8(sqrt(im./redSize^2)); % mean; re-normalize brightness: "scale linear to the human eye"; back in uint8


function map = 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,[1 2 4 3]); % step1; make unified column-image (handling possible nStack)
imRGBcolumn = reshape(imRGB,[],1,3,1); % step2; make unified column-image

fullMap = double(permute(imRGBcolumn,[1 3 2]))./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)']);

if nCol<=nColStart;  error('Not enough colors');        end
if nCol>nColFul;   warning('More colors than needed');  end

isPreDefCol = false(size(imMapColumn)); % init
 
for iCol = 1:nColStart
    diff = 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) color
    if mDiff>0.05 % color handling is not precise
        warning(['Predefined color ' num2str(iCol) ' does not appear in image'])
        continue
    end
    isThisPreDefCol = imMapColumn==index; % find all pixel with predefined color
    disp([num2str(sum(isThisPreDefCol(:))) ' pixel have predefined color ' num2str(iCol)]);
    isPreDefCol = or(isPreDefCol,isThisPreDefCol); % combine with overall list
end
[~,mapAdditional] = rgb2ind(imRGBcolumn(~isPreDefCol,:,:),nCol-nColStart,'nodither'); % create map of remaining colors
map = [startMap;mapAdditional];


function setXYlim(axesHandle,xLimits,yLimits)
% set limits; practically the axis overhangs the figure all around, to
% hide rendering errors at line-ends.
% Input:
%   axesHandle:        
%   xLimits, yLimits:  [min max]
overh = 0.05; % 5% overhang all around; 10% bigger in x and y
xlim([+xLimits(1)*(1+overh)-xLimits(2)*overh  -xLimits(1)*overh+xLimits(2)*(1+overh)])
ylim([+yLimits(1)*(1+overh)-yLimits(2)*overh  -yLimits(1)*overh+yLimits(2)*(1+overh)])
set(axesHandle,'Position',[-overh -overh  1+2*overh 1+2*overh]); % stretch axis as bigger as figure, [x y width height]
drawnow;

Assessment

Featured picture
Quality image
Quality image

Wikimedia CommonsWikipedia

This is a featured picture on Wikimedia Commons (Featured pictures) and is considered one of the finest images. See its nomination here.
This is a quality image and is considered to meet the quality image guidelines.

 This is a featured picture on the Arabic language Wikipedia (صور مختارة) and is considered one of the finest images. See its nomination here.
 This is a featured picture on the Persian language Wikipedia (نگاره‌های برگزیده) and is considered one of the finest images. See its nomination here.

If you have an image of similar quality that can be published under a suitable copyright license, be sure to upload it, tag it, and nominate it.

Media of the day This file was selected as the media of the day for 01 June 2019. It was captioned as follows:
English: Animation of gears including epicyclic gears and a rack and pinion
Other languages
Čeština: Animace funkce převodu síly a pohybu pomocí ozubených kol včetně planetové převodovky a dalších aplikací.
Deutsch: Animation von Zahnrädern inkusive eines Planetengetriebes und einer Zahnstange.
English: Animation of gears including epicyclic gears and a rack and pinion
Македонски: Анимација на механички пренос со планетарни запченици и назабена летва
Polski: Animacja przedstawiająca przekładnie zębate, w tym przekładnię obiegowązębatkę.
Русский: Анимация различных видов зубчатой передачи, включая планетарную и реечную
Українська: Анімація коліщат, включаючи епіциклічну передачу та рейкову передачу.

Licensing

I, the copyright holder of this work, hereby publish it under the following license:
Creative Commons CC-Zero This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
The person who associated a work with this deed has dedicated the work to the public domain by waiving all of their rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.

Captions

Add a one-line explanation of what this file represents

Items portrayed in this file

depicts

20 June 2017

image/gif

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current13:12, 14 April 2019Thumbnail for version as of 13:12, 14 April 2019840 × 700 (15.79 MB)wikimediacommons>JahobrWikimedia uses a 100MPx limit now. New render for this quality.

The following page uses this file: