function bakteriensimulator(anzahl_Bakterien,Bildname,varargin)
%
% function bakteriensimulator(Anzahl,Bildname,varargin)
% generiert Bilder von (Pseudo-) Petrischalen mit
% Bakterienkulturen fuer die Abschlussaufgabe des
% Oktober-Matlabkurses 2007.
%
% Geforderter Eingabeparameter:
% bakteriensimulator(Bildname)
% Erzeugt ein Bild und speichert es unter dem Filenamen
% Bildname ab.
%
% Optionale Eingabeparameter:
% bakteriensimulator(Anzahl,Bildname, alle_richtungen)
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse)
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse,ueberlapp)
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse,ueberlapp,bildrauschen)
%
% Alle optionalen Eingabeparameter (alle_richtungen,
% variable_groesse,ueberlapp,bildrauschen)
% sind boolsche Variable, deren Standardwert "false" ist.
% Wenn fuer die jeweilige Variable ein "true" uebergeben wird,
% aendern sich folgende Eigenschaften des erzeugten
% Bildes:
%
% bakteriensimulator(Anzahl,Bildname, alle_richtungen)
% Es gibt nicht nur horizontal und vertikal ausgerichtete 
% Bakterien, sondern auch Zwischenwinkel
%
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse)
% Die Bakterien sind zusaetzlich nicht alle gleich gross, 
% sondern variieren in ihrer Groesse
%
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse,ueberlapp)
% Zusaetzlich koennen die Bakterien sich beruehren und ueberlappen
% (also uebereinander in der Petrischale liegen)
%
% bakteriensimulator(Anzahl,Bildname, alle_richtungen, variable_groesse,ueberlapp,bildrauschen)
% Zusaetzlich gibt es Pixelrauschen im Bild, so dass 
% nicht alle Bakterien ganz schwarz und der Hintergrund 
% ganz weiss ist.

% Setzen der Standardwerte fuer Parameter, 
% Kompaktversion fuer spaetere Abfrage:
opt_param=logical([0 0 0 0]);

% Abfrage der Parameter:
if nargin==0
    error('function bakteriensimulator(Bildname,varargin) erfordert mindestens die Eingabe des Filenamens zum Abspeichern des Bildes')
elseif (nargin>0 & ~ischar(Bildname))
    error('Erster Eingabeparameter muss der Dateiname zum Abspeichern des Bildes sein')
end
for optionalnr=1:4
    if (nargin>optionalnr)
        if varargin{optionalnr}==1
            opt_param(optionalnr)=logical(1);
        elseif varargin{optionalnr}~=0
            warning('Eingabeparameter ignoriert')
        end
    end
end
    
% Setzen der aussagekraeftigeren Variablennamen
alle_richtungen=opt_param(1)
variable_groesse=opt_param(2)
ueberlapp=opt_param(3)
bildrauschen=opt_param(4)
       
    
% Einige Grundparameter, die bei Bedarf geaendert 
% werden sollten:

% Anzahl Bakterien im Bild:

% Groesse des Bildes:
x_pixel=350;
y_pixel=350;

% Standard-Farben (Grauwerte)
bakt_farbe=uint8(50);
hintergrund_farbe=uint8(200);

% Standardabweichung des Pixelrauschens:
if bildrauschen
    bild_std=50;
else
    bild_std=0;
end

% Standard-Groesse einer Bakterie (Angaben in Pixel)
bakt_laenge=10;
bakt_breite=4;

% Standardabweichung der Bakteriengroessen (in Pixel)
if variable_groesse
    laengen_std=1.5;
    breiten_std=0.5;
else
    laengen_std=0;
    breiten_std=0;
end

% Erzeuge Hintergrund:
bild=hintergrund_farbe*uint8(ones(x_pixel,y_pixel));

% Erzeuge Matrix, in den alle mit Bakterien belegten 
% Pixel eingetragen werden:
belegt=[]; %spaeter werden jeweilige x- und y-Werte angehaengt

% Schleife zur Erzeugung der Bakterien:
for b_anz=1:anzahl_Bakterien
    gefunden=logical(0);
    while ~gefunden
        % Wuerfele neuen Startpunkt:
        startx=randperm(x_pixel);
        startx=startx(1);
        starty=randperm(y_pixel);
        starty=starty(1);
        % Erzeuge Indizes fuer neue Bakterie, die auf Startpunkt addiert werden:
        [x_vec,y_vec]=erzeuge_bakterie(bakt_laenge,bakt_breite, laengen_std,breiten_std,alle_richtungen);
        x_vec=startx+x_vec;
        y_vec=starty+y_vec;
        % Teste, ob Bakterie ueber den Rand geht:
        x_ok=min(x_vec)>=0 & max(x_vec)<=x_pixel;
        y_ok=min(y_vec)>=0 & max(y_vec)<=y_pixel;
        %Nur mit dieser Position weitermachen, wenn keine Punkte jenseits
        %des Randes liegen
        if x_ok & y_ok
            if ueberlapp  | isempty(belegt) %wenn Ueberlapp zugelassen ist oder es noch keinen Ueberlapp geben kann: Bakterie einfuegen
                gefunden=logical(1);
                belegt=[belegt [x_vec;y_vec]];
            else  %sonst muss noch getestet werden, ob es Ueberlapp gibt
                z=1; % Zaehler fuer den Vergleich
                ok=logical(1); % Flag, dass es bisher keinen Ueberlapp gab 
                while ok & z<=length(x_vec)
                    gemeinsame=find(belegt(1,:)==x_vec(z) & belegt(2,:)==y_vec(z));
                    if ~isempty(gemeinsame)
                        ok=logical(0);
                    else
                        z=z+1;
                    end
                end
                if ok  %Wenn kein Ueberlapp gefunden wurde
                   gefunden=logical(1);
                    belegt=[belegt [x_vec;y_vec]]; 
                end
            end
        end  % wenn keiner der Faelle zutrifft, bleibt gefunden==0 und die Schleife wird wiederholt
    end
end

% Berechne zu belegende Punkte in linearer Darstellung:
linind=belegt(1,:)+y_pixel*belegt(2,:)-y_pixel;


mini=min(linind);
maxi=max(linind);
if mini<0 | maxi>x_pixel*y_pixel
    warning('unmoegliche Lage')
end

% Bild erzeugen
bild(linind)=uint8(bakt_farbe);

%Verrauschen, falls gewuenscht:
if bildrauschen
    [x_laenge,y_laenge]=size(bild);
    rauschen=bild_std*randn(x_laenge,y_laenge);
    bild=uint8(double(bild)+rauschen);
end


%Darstellung als Grauwertbild:
imshow(bild)

%Abspeichern der Matrix und des Bildes:
save(Bildname,'bild')






