function pendel_anim

% Animationstool fuer die Pendelgleichung
%
% Matlab-Programm zum Buch
% 
%  Gewoehnliche Differentialgleichungen -- 
%  Eine Einfuehrung aus der Perspektive der dynamischen Systeme
%  Lars Gruene, Oliver Junge, Vieweg+Teubner 2009
%  www.dgl-buch.de
%
% fuer Informationen zu diesem Programm siehe die obige Webseite
% 
% (C) Lars Gruene, Oliver Junge 2008

% Modellvariablen Voreinstellung 

k = 0.5;
g = 9.81;
l = 1.0;

% Anfangsbedingung Voreinstellung

tt = 0;
x0 = [3.1, 0];

% Rechenintervall fuer ein Animationsbild

dt = 0.03;

% Achsen-Voreinstellung

% Pendelmodell
ax1default = [-1.5,1.5,-1.5,1.5];
% Phasenportrait
ax2default = [-3.5,3.5,-6,6];
% (t,x)-Grafik
ax3default = [0,5,-6,6];

% Scrollfaktor (t,x)-Achsen

sfaktor = 0.5;

% Modell-Sichtbarkeit Voreinstellung

lin_visible = 'off';
nl_visible  = 'on';

% Merkvariable fuer Fenstergroesse

hfp_alt=[0 0 0 0];

% Optionen fuer ode45

options = odeset('RelTol',1e-6);

% Erstellen des Hauptfensters

hf = figure;
set(hf,'Units', 'normalized');

% Erstellen der GUI-Elemente:

% Gleiter fuer k

hs = uicontrol(hf,'Style','slider',...
                'String','k = ',...
                'Units','normalized',...
                'Max',1,'Min',-1,'Value',0.5,...
                'SliderStep',[0.005 0.05],...
                'Callback',{@kslider_Callback},...
                'TooltipString','Reibung',...
                'Position',[0.16 0.49 0.25 0.04]);
ht = uicontrol(hf,'Style','text','FontSize',12,...
                'Units','normalized',...
                'String',sprintf('k = %1.1g',k),...
                'HorizontalAlignment','right',...
                'TooltipString','Reibung',...
                'Position',[0.05 0.49 0.1 0.04]);

% Koordinaten Ein- und Ausgabe
            
hti = uicontrol(hf,'Style','text','FontSize',12,...
                'Units','normalized',...
                'String','nichtlinear',...
                'HorizontalAlignment','left',...
                'Position',[0.16 0.39 0.13 0.04]);
he1 = uicontrol(hf,'Style','edit','FontSize',12,...
                'Units','normalized',...
                'HorizontalAlignment','left',...
                'Callback',{@e1_Callback},...
                'TooltipString',...
                'x_1 Komponente nichtlineares Modell',...
                'Position',[0.16 0.34 0.1 0.04]);
ht1 = uicontrol(hf,'Style','text','FontSize',12,...
                'Units','normalized',...
                'String','x_1 = ',...
                'HorizontalAlignment','right',...
                'Position',[0.05 0.34 0.1 0.04]);
he2 = uicontrol(hf,'Style','edit','FontSize',12,...
                'Units','normalized',...
                'HorizontalAlignment','left',...
                'Callback',{@e2_Callback},...
                'TooltipString',...
                'x_2 Komponente nichtlineares Modell',...
                'Position',[0.16 0.29 0.1 0.04]);
ht2 = uicontrol(hf,'Style','text','FontSize',12,...
                'Units','normalized',...
                'String','x_2 = ',...
                'HorizontalAlignment','right',...
                'Position',[0.05 0.29 0.1 0.04]);

htil = uicontrol(hf,'Style','text','FontSize',12,...
                'Units','normalized',...
                'String','linear',...
                'HorizontalAlignment','left',...
                'Position',[0.30 0.39 0.09 0.04]);
he1l = uicontrol(hf,'Style','edit','FontSize',12,...
                'Units','normalized',...
                'HorizontalAlignment','left',...
                'Callback',{@e1l_Callback},...
                'TooltipString',...
                'x_1 Komponente lineares Modell',...
                'Position',[0.30 0.34 0.1 0.04]);
he2l = uicontrol(hf,'Style','edit','FontSize',12,...
                'Units','normalized',...
                'HorizontalAlignment','left',...
                'Callback',{@e2l_Callback},...
                'TooltipString',...
                'x_2 Komponente lineares Modell',...
                'Position',[0.30 0.29 0.1 0.04]);

% Zeit Ein- und Ausgabe            
            
htt = uicontrol(hf,'Style','text','FontSize',12,...
                 'Units','normalized',...
                 'String','t = ',...
                 'HorizontalAlignment','right',...
                 'Position',[0.05 0.23 0.1 0.04]);
het = uicontrol(hf,'Style','edit','FontSize',12,...
                'Units','normalized',...
                'HorizontalAlignment','left',...
                'Callback',{@et_Callback},...
                'TooltipString','Zeit',...
                'Position',[0.16 0.23 0.1 0.04]);

% Radioknoepfe fuer Modellwahl

hr = uibuttongroup('visible','off','Position',[0.05 0.05 0.14 0.1]);

u0 = uicontrol('Style','Radio','String','nichtlinear',...
            'Units','normalized','FontSize',12,...
            'pos',[0.0 0.67 1 0.33],'parent',hr,...
            'TooltipString', 'nichtlineares Modell darstellen',...
            'HandleVisibility','off');

u1 = uicontrol('Style','Radio','String','linear',...
            'Units','normalized','FontSize',12,...
            'pos',[0.0 0.33 1 0.33],'parent',hr,...
            'TooltipString', 'lineares Modell darstellen',...
            'HandleVisibility','off');
        
u2 = uicontrol('Style','Radio','String','beides',...
            'Units','normalized','FontSize',12,...
            'pos',[0.0 0.00 1 0.33],'parent',hr,...
            'TooltipString',...
            'nichtlineares und lineares Modell darstellen',...
            'HandleVisibility','off');
        
set(hr,'SelectionChangeFcn',@linearnichtlinear_Callback);
set(hr,'SelectedObject',u0);  
set(hr,'Visible','on');

% Loeschen-Knopf

hgl = uicontrol('Style','pushbutton','FontSize',12,...
                'Units','normalized',...
                'String','Grafik loeschen',...
                'TooltipString','alle Trajektorien loeschen',...
                'Position',[0.20 0.05 0.1 0.1],...
                'Callback',@loeschen_Callback);           

% Start-Stop-Knopf            
            
hb = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','Start',...
                'TooltipString','Rechnung starten',...
                'Position',[0.33 0.05 0.12 0.11],...
                'Callback',@start_Callback);           

% Zoommenu Phasenportrait            
            
h2p = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','+',...
                'TooltipString','hineinzoomen',...
                'Position',[0.92 0.88 0.04 0.04],...
                'Callback',@h2p_Callback);           
h2m = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','-',...
                'TooltipString','herauszoomen',...
                'Position',[0.92 0.83 0.04 0.04],...
                'Callback',@h2m_Callback);           
h2o = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','o',...
                'TooltipString','an Loesung anpassen',...
                'Position',[0.92 0.78 0.04 0.04],...
                'Callback',@h2o_Callback);           
h2r = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','><',...
                'TooltipString','zuruecksetzen',...
                'Position',[0.92 0.73 0.04 0.04],...
                'Callback',@h2r_Callback);           

% Zoommenu (t,x)-Darstellung            
            
h3xp = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','x+',...
                'TooltipString','x hineinzoomen',...
                'Position',[0.92 0.405 0.04 0.04],...
                'Callback',@h3xp_Callback);           
h3xm = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','x-',...
                'TooltipString','x herauszoomen',...
                'Position',[0.92 0.355 0.04 0.04],...
                'Callback',@h3xm_Callback);           
h3tp = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','t+',...
                'TooltipString','t hineinzoomen',...
                'Position',[0.92 0.305 0.04 0.04],...
                'Callback',@h3tp_Callback);           
h3tm = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','t-',...
                'TooltipString','t herauszoomen',...
                'Position',[0.92 0.255 0.04 0.04],...
                'Callback',@h3tm_Callback);           
h3o = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','o',...
                'TooltipString','an Loesung anpassen',...
                'Position',[0.92 0.205 0.04 0.04],...
                'Callback',@h3o_Callback);           
h3r = uicontrol('Style','pushbutton',...
                'Units','normalized',...
                'String','><',...
                'TooltipString','zuruecksetzen',...
                'Position',[0.92 0.155 0.04 0.04],...
                'Callback',@h3r_Callback);           

% Erstellen der Animationsachsen
            
h1 = subplot(2,2,1);
set(h1,'ButtonDownFcn',{@anim_ButtonDownFcn});
axis(ax1default);
axis square;

% Grafikelemente fuer Animation nichtlineares Modell

masse = line( ...
        'Marker','.', ...
        'markersize',100, ...
        'markeredgecolor','r', ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
punkt = line( ...
        'Marker','.', ...
        'markersize',25, ...
        'markeredgecolor','k', ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
stab  = line( ...
        'linewidth', 2, ...
        'color','b', ...
        'LineStyle','-', ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);

% Grafikelemente fuer Animation lineares Modell
    
lmasse = line( ...
        'color','b', ...
        'LineStyle','-', ...
        'Marker','o', ...
        'markersize',27, ...
        'markeredgecolor', [1.0, 0, 0], ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
lstab  = line( ...
        'linewidth', 2, ...
        'color',[0.3, 0.3, 1.0], ...
        'LineStyle','-', ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
    
% Erstellen der Phasenportrait-Achsen    
    
h2 = subplot(2,2,2);
set(h2,'ButtonDownFcn',{@phase_ButtonDownFcn});
axis(ax2default);
title('Phasenportrait');
xlabel('x_1(t)');
ylabel('x_2(t)');
    
% Grafikelemente fuer Animation des Phasenportraits

lxlsg = line( ...
        'linewidth', 1, ...
        'color',[0.7 0.7 0.7], ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
xlsg  = line( ...
        'linewidth', 1, ...
        'color','k', ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
aw    = line( ...
        'color','w', ...
        'LineStyle','-', ...
        'Marker','o', ...
        'markersize',6, ...
        'markeredgecolor', 'k', ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
law    = line( ...
        'color', 'w', ...
        'LineStyle','-', ...
        'Marker','o', ...
        'markersize',5, ...
        'markeredgecolor', [0.7 0.7 0.7], ...
        'erase','xor', ...
        'xdata',[],'ydata',[],'zdata',[]);
    
% Erstellen der (t,x)-Achsen    
    
h3 = subplot(2,2,4);
axis(ax3default);
title('Loesungskomponenten abhaengig von t');
xlabel('t');
ylabel('{\color{blue} x_1(t)}, {\color{red} x_2(t)}');

% Grafikelemente fuer Animation der (t,x)-Loesungen

lx1   = line( ...
        'linewidth', 1, ...
        'color',[0.7, 0.7, 1.0], ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
lx2   = line( ...
        'linewidth', 1, ...
        'color',[1.0, 0.7, 0.7], ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
     
x1   = line( ...
        'linewidth', 1, ...
        'color','b', ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
x2   = line( ...
        'linewidth', 1, ...
        'color','r', ...
        'LineStyle','-', ...
        'erase','none', ...
        'xdata',[],'ydata',[],'zdata',[]);
     
% Variablen fuer Animation Voreinstellung    
    
tspan = [tt(1), tt(1)+dt];
y = x0;
ly = x0;

% Ausgabe der Voerinstellungen im Fenster (Text/Grafik)

set(he1,'string',num2str(y(1)));
set(he2,'string',num2str(y(2)));
set(he1l,'string',num2str(ly(1)));
set(he2l,'string',num2str(ly(2)));
set(het, 'String',sprintf('%5.2f',tspan(1)));

zeichne_pendel();
zeichne_anfangswert();

% Deklaration der Variablen zur Speicherung der nichtlinearen 
% Loesungen (Animation laeuft damit deutlich schneller)

tglob=zeros(1,1000000);
yglob=zeros(1000000,2);

% Index des letzten Eintrags in tglob und yglob

tgl = 0;

% Indizes der Trajektorienenden

neustart = [];

% Variablen fuer line-Strukturen fuer die Trajektorien 

xxtra  = [];
x1tra  = [];
x2tra  = [];

% Anzahl Trajektorien im Speicher

numtra = 0;

% Wie oben, nun fuer das lineare Modell

ltglob=zeros(1,1000000);
lyglob=zeros(1000000,2);
ltgl = 0;
lneustart = [];

lxxtra = [];
lx1tra = [];
lx2tra = [];

% Sichtbar/unsichtbarmachen der Koordinaten-Ein/Ausgabe

sichtbar();

% Rechnung wird nicht automatisch gestartet

cont = 0;

% Animationsschleife, Abbruch durch setzen von cont=0 in
% start_Callback 

    function run
        hfp_alt = [0 0 0 0];
        while cont
            
            % Text-Ausgabe von Koordinaten und Zeit 
                
            set(he1, 'String',sprintf('%2.2g', y(1)));
            set(he2, 'String',sprintf('%2.2g', y(2)));
            set(he1l,'String',sprintf('%2.2g',ly(1)));
            set(he2l,'String',sprintf('%2.2g',ly(2)));
            set(het, 'String',sprintf('%5.2f',tspan(1)));
            
            % Loesung nichtlineares Modell, ein Animationsschritt
            
            [t,yy] = ode45(@pendel_anim_f, tspan, y, options);
            
            % Speichern in globaler Loesungsvariable
            
            tglob(tgl+1:tgl+length(t)) = t;
            yglob(tgl+1:tgl+length(t),:) = yy;
            tgl = tgl + length(t);
            
            % Anfangswert fuer naechsten Animationsschritt
            
            y = yy(length(yy),:);
            
            % wie oben fuer lineares Modell
            
            [lt,lyy] = ode45(@pendel_anim_lin_f,tspan, ly, options);
            ltglob(ltgl+1:ltgl+length(lt)) = lt;
            lyglob(ltgl+1:ltgl+length(lt),:) = lyy;
            ltgl = ltgl + length(lt);
            ly = lyy(length(yy),:);

            % Zeitspanne fuwe naechten Animationsschritt
            
            tspan = [tspan(2), tspan(2)+dt];
  
            % Pendel Zeichnen
            
            zeichne_pendel();
            
            % Aktuellen Wert im Phasenportrait zeichnen
            
            zeichne_anfangswert();
            
            % falls noetig, (t,x)-Achse scrollen
            
            ax = axis(h3);
            if (t(length(t))>ax(2))
                
                % Achsen verschieben
                
                tp = (ax(2)-ax(1))*sfaktor;
                ax(1) = ax(1) + tp;
                ax(2) = ax(2) + tp;
                axis(h3,ax);
                
                % Nach Verschieben des Fensters globale 
                % Loesungen neu zeichnen
                
                loesungen_neu_zeichnen();

                % neue_trajektorie();

                drawnow;
            end;

            % Berechneten Loesungsschritt im (t,x) Fenster...
            
            set(lx1,'xdata',lt,'ydata',lyy(:,1));
            set(lx2,'xdata',lt,'ydata',lyy(:,2));
            set(x1,'xdata',t,'ydata',yy(:,1));
            set(x2,'xdata',t,'ydata',yy(:,2));

            % ... und im Phasenportrait zeichnen
            
            set(lxlsg,'xdata',lyy(:,1),'ydata',lyy(:,2));
            set(xlsg,'xdata',yy(:,1),'ydata',yy(:,2));

            % Anmerkung: die Reihenfolge 
            % 'erst linear dann nichtlinear' sorgt dafuer, dass die 
            % nichtlineare ueber die lineare Loesung geplottet wird
            
            drawnow;
        end
    end

    % Vektorfeld, nichtlineares Modell

    function y = pendel_anim_f(t,x)

        y = zeros(2,1);
        y(1) =  x(2);
        y(2) =  -k.*x(2) -g.*sin(x(1));

    end

    % Vektorfeld lineares Modell

    function y = pendel_anim_lin_f(t,x)

        y = zeros(2,1);
        y(1) =  x(2);
        y(2) =  -k.*x(2) -g.*x(1);
        
    end

    % Callback zur Wahl des Anfangswertes im Animationsfenster
    
    function anim_ButtonDownFcn(ha, event)

        delay = 0.3;
        p1 = get(ha,'CurrentPoint');
        alpha1 = atan2(p1(1,1),-p1(1,2));
        pause(delay);
        p2 = get(ha,'CurrentPoint');
        alpha2 = atan2(p2(1,1),-p2(1,2));
        dalpha = (alpha2-alpha1)/delay;
        y  = [alpha1 dalpha];
        ly = [alpha1 dalpha];
        set(he1,'string',num2str(y(1)));
        set(he2,'string',num2str(y(2)));
     	set(he1l,'string',num2str(ly(1)));
        set(he2l,'string',num2str(ly(2)));
        zeichne_pendel();
        zeichne_anfangswert();
   
    end

    % Callback zur Wahl des Anfangswertes im Phasenportrait

    function phase_ButtonDownFcn(ha, event)

        p1 = get(ha,'CurrentPoint');
        y  = p1(1,1:2);
        ly = p1(1,1:2);
        set(he1,'string',num2str(y(1)));
        set(he2,'string',num2str(y(2)));
        set(he1l,'string',num2str(ly(1)));
        set(he2l,'string',num2str(ly(2)));
        zeichne_pendel();
        zeichne_anfangswert();

    end

    % Callback Eingabe x_1 nichtlinear

    function e1_Callback(hObject, event, handles)
        user_entry = str2double(get(hObject,'string'));
        if isnan(user_entry)
            errordlg('Bitte Zahlenwert eingeben (mit Dezimalpunkt statt Komma)',...
                     'Falsche Eingabe','modal')
            return
        end
        y(1) = user_entry;
        zeichne_pendel();
        zeichne_anfangswert();
    end

    % Callback Eingabe x_2 nichtlinear

    function e2_Callback(hObject, event, handles)
        user_entry = str2double(get(hObject,'string'));
        if isnan(user_entry)
            errordlg('Bitte Zahlenwert eingeben (mit Dezimalpunkt statt Komma)',...
                     'Falsche Eingabe','modal')
            return
        end
        y(2) = user_entry;
        zeichne_pendel();
        zeichne_anfangswert();
    end

    % Callback Eingabe t

    function et_Callback(hObject, event, handles)
        user_entry = str2double(get(hObject,'string'));
        if isnan(user_entry)
            errordlg('Bitte Zahlenwert eingeben (mit Dezimalpunkt statt Komma)',...
                     'Falsche Eingeba','modal')
            return
        end
        tspan = [user_entry,user_entry+dt];
        zeichne_pendel();
        zeichne_anfangswert();
    end

    % Callback Eingabe x_1 linear

    function e1l_Callback(hObject, event, handles)
        user_entry = str2double(get(hObject,'string'));
        if isnan(user_entry)
            errordlg('Bitte Zahlenwert eingeben (mit Dezimalpunkt statt Komma)',...
                     'Falsche Eingabe','modal')
            return
        end
        ly(1) = user_entry;
        zeichne_pendel();
        zeichne_anfangswert();
    end

    % Callback Eingabe x_2 linear

    function e2l_Callback(hObject, event, handles)
        user_entry = str2double(get(hObject,'string'));
        if isnan(user_entry)
            errordlg('Bitte Zahlenwert eingeben (mit Dezimalpunkt statt Komma)',...
                     'Falsche Eingabe','modal')
            return
        end
        ly(2) = user_entry;
        zeichne_pendel();
        zeichne_anfangswert();
    end

    % Callback fuer Start/Stop-Knopf

    function start_Callback(handle, event)
        
        if cont
            % Rechnung stoppen
            cont = 0;
            % Start/Stop-Knopf neu beschriften
            set(hb,'string','Start');
            set(hb,'TooltipString','Rechnung starten');
            % Text im 'Grafik loeschen'-Knopf -> schwarz
            set(hgl,'ForegroundColor',[0 0 0]);
            % Fenster aktualisieren
            refresh(hf);
            loesungen_neu_zeichnen();
        else
            % Rechnung starten
            cont = 1;
            % Start/Stop-Knopf neu beschriften
            set(hb,'string','Stop');
            set(hb,'TooltipString','Rechnung stoppen');
            % Text im 'Grafik loeschen'-Knopf -> grau
            set(hgl,'ForegroundColor',[0.7 0.7 0.7]);
            % Grafikelemente fuer globale Darstellung der 
            % neuen Trajektorie erzeugen
            neue_trajektorie();        
            % (t,x)-Achsen an Anfangszeit anpassen
            ax = axis(h3);
            if (tspan(1)<ax(1))
              tp = ax(2)-ax(1);
              ax(1) = tspan(1);
              ax(2) = ax(1) + tp;
              axis(h3,ax);
              drawnow;
            end;
            % Animationsschleife aufrufen
            run;
        end
    end
            
    % Callback fuer 'Grafik loeschen'-Knopf
 
    function loeschen_Callback(handle, event)

        % nur ausfuehren, wenn keine Rechnung laeuft
        if cont
          return
        else
          % Indizes fuer Trajektorienende loeschen
          tgl = 0;
          neustart = [];
  
          ltgl = 0;
          lneustart = [];
          
          % t-Achse auf Null setzen
          ax = axis(h3);
          tp = ax(2)-ax(1);
          ax(1) = 0.0;
          ax(2) = tp;
          axis(h3,ax);
          
          % Anfangszeit auf Null zuruecksetzen...
          tspan = [tt(1), tt(1)+dt];
          % ... und ausgeben
          set(het, 'String',sprintf('%5.2f',tspan(1)));
  
          % Grafikelemente fuer Animation in Phasenportrait und 
          % (t,x)-Darstellung zuruecksetzen
          set(x1  ,'xdata',[],'ydata',[]);
          set(x2  ,'xdata',[],'ydata',[]);
          set(xlsg,'xdata',[],'ydata',[]);
          
          set(lx1  ,'xdata',[],'ydata',[]);
          set(lx2  ,'xdata',[],'ydata',[]);
          set(lxlsg,'xdata',[],'ydata',[]);
          
          % Grafikelemente fuer globale Loesungsdarstellung loeschen
          for i=1:numtra
              delete(xxtra(i));
              delete(lxxtra(i));
              delete(x1tra(i));
              delete(lx1tra(i));
              delete(x2tra(i));
              delete(lx2tra(i));
          end             
 
          % Anzahl Trajektorien im Speicher zuruecksetzen
          numtra = 0;
          
          % Fenster aktualisieren
          refresh(hf);    
        end
    end

    % Callbacks fuer Zoommenu Phasenportrait

    % hineinzoomen    
    function h2p_Callback(handle, event)
        
        subplot(h2);
        ax = axis;
        d1 = (ax(2)-ax(1))/4.0;
        d2 = (ax(4)-ax(3))/4.0;
        axis([ax(1)+d1,ax(2)-d1,ax(3)+d2,ax(4)-d2]);
    
    end
            
    % herauszoomen
    function h2m_Callback(handle, event)
        
        subplot(h2);
        ax = axis;
        d1 = (ax(2)-ax(1))/2.0;
        d2 = (ax(4)-ax(3))/2.0;
        axis([ax(1)-d1,ax(2)+d1,ax(3)-d2,ax(4)+d2]);
    
    end
            
    % an Loesung anpassen
    function h2o_Callback(handle, event)
        
        subplot(h2);
        axis tight;
    
    end
            
    % reset
    function h2r_Callback(handle, event)
        
        subplot(h2);
        axis(ax2default);
    
    end
           
    % Callbacks fuer Zoommenu (t,x)-Achsen

    % x hineinzoomen
    function h3xp_Callback(handle, event)
        
        subplot(h3);
        ax = axis;
        d2 = (ax(4)-ax(3))/4.0;
        axis([ax(1),ax(2),ax(3)+d2,ax(4)-d2]);
    
    end
            
    % t hineinzoomen
    function h3tp_Callback(handle, event)
        
        subplot(h3);
        ax = axis;
        d1 = (ax(2)-ax(1))/4.0;
        axis([ax(1)+d1,ax(2)-d1,ax(3),ax(4)]);
    end
            
    % x herauszoomen
    function h3xm_Callback(handle, event)
        
        subplot(h3);
        ax = axis;
        d2 = (ax(4)-ax(3))/2.0;
        axis([ax(1),ax(2),ax(3)-d2,ax(4)+d2]);
    
    end
            
    % t herauszoomen
    function h3tm_Callback(handle, event)
        
        subplot(h3);
        ax = axis;
        d1 = (ax(2)-ax(1))/2.0;
        axis([ax(1)-d1,ax(2)+d1,ax(3),ax(4)]);
     
    end
            
    % an Loesung anpassen
    function h3o_Callback(handle, event)
        
        subplot(h3);
        axis tight;
    end
            
    % reset
    function h3r_Callback(handle, event)
        
        subplot(h3);
        ax = axis;
        tp = ax3default(2)-ax3default(1);
        if (tgl>0)
            ax(2) = tglob(tgl);
            ax(1) = ax(2)-tp;
        else
            ax(1:2) = ax3default(1:2);
        end;
        ax(3:4) = ax3default(3:4);
        axis(ax);
    
    end
           

    % Callback fuer Radiokn�pfe Modellauswahl
    
    function linearnichtlinear_Callback(handle,event)
    
        % Sichtbarkeitsvariablen setzen...
        s = get(event.NewValue,'String');
        if (strcmp(s,'linear'))
            lin_visible = 'on';
            nl_visible  = 'off';
        elseif (strcmp(s,'nichtlinear')) 
            lin_visible = 'off';
            nl_visible  = 'on';
        else
            lin_visible = 'on';
            nl_visible  = 'on';
        end

        % ...und Sichtbarkeit einstellen
        sichtbar();
        
        % Fenster aktualisieren
        refresh(hf);
        loesungen_neu_zeichnen();
        
    end

    % Callback fuer k-Gleiter

    function kslider_Callback(handle,event)
        
        k = round(get(hs,'Value')*100)/100;
        set(ht,'String',sprintf('k = %1.2f',k));
        set(hs,'Value',k);
      
    end

    % Sichtbarkeit einstellen

    function sichtbar()
        
        % Sichtbarkeit aller relevanten Elemente auf Werte in
        % nl_visible (nichtline) bzw. lin_visible (linear) setzen
        
        set(masse,'Visible',nl_visible);
        set(stab, 'Visible',nl_visible);
        
        set(xlsg, 'Visible',nl_visible);
        set(aw,   'Visible',nl_visible);
        
        set(x1,   'Visible',nl_visible);
        set(x2,   'Visible',nl_visible);
        
        set(hti,  'Visible',nl_visible);
        set(he1,  'Visible',nl_visible);
        set(he2,  'Visible',nl_visible);

        set(lmasse,'Visible',lin_visible);
        set(lstab, 'Visible',lin_visible);
        
        set(lxlsg, 'Visible',lin_visible);
        set(law,   'Visible',lin_visible);
        
        set(lx1,   'Visible',lin_visible);
        set(lx2,   'Visible',lin_visible);
        
        set(htil,  'Visible',lin_visible);
        set(he1l,  'Visible',lin_visible);
        set(he2l,  'Visible',lin_visible);

        for i = 1:numtra
            set( xxtra(i), 'Visible',  nl_visible);
            set( x1tra(i), 'Visible',  nl_visible);
            set( x2tra(i), 'Visible',  nl_visible);
            set(lxxtra(i), 'Visible', lin_visible);
            set(lx1tra(i), 'Visible', lin_visible);
            set(lx2tra(i), 'Visible', lin_visible);
        end
    end

    % Funktion zum Zeichnen der aktuellen globalen Loesung
    % 
    % Die Funktion muss aufgerufen werden wenn: 
    % 
    % - Achsen ver�ndert wurden (durch Scrollen)
    % - ein "Refresh" ausgef�hrt wurde (wann ein "Refresh" 
    %   vom System ausgeloest wird, ist systemabhaengig; in Windows 
    %   passiert dies oefter als in Linux)
    %
    % In diesen Faellen wird stets nur das letzte in der Animation 
    % geplotteten "Loesungsstueckchen" aktualisiert; der Rest geht 
    % verloren.
    %
    % Zur Abhilfe wird jede Trajektorie zusaetzlich "global" durch 
    % Linienelemente dargestellt, die in 'neue_trajektorie' (s.u.)
    % definiert werden. Diese werden von matlab automatisch 
    % verwaltet; es muss nur dafuer gesorgt werden, dass sie 
    % die jeweils aktuellen numerischen Daten enthalten.
    % Daf�r sorgt diese Funktion.
    
    function loesungen_neu_zeichnen()

        % Nur ausfuehren, wenn bereits etwas berechnet wurde
        if (tgl>0)
          % Phasenportrait linear
          set(lxxtra(numtra),...
                'xdata',lyglob(lneustart(numtra)+1:ltgl,1),...
                'ydata',lyglob(lneustart(numtra)+1:ltgl,2) );

          % Phasenportrait nichtlinear
          set(xxtra(numtra),...
                'xdata',yglob(neustart(numtra)+1:tgl,1),...
                'ydata',yglob(neustart(numtra)+1:tgl,2) );
   
          % x_1(t) linear
          set(lx1tra(numtra),...
                'xdata',ltglob(lneustart(numtra)+1:ltgl),...
                'ydata',lyglob(lneustart(numtra)+1:ltgl,1) );
             
          % x_2(t) linear  
          set(lx2tra(numtra),...
                'xdata',ltglob(lneustart(numtra)+1:ltgl),...
                'ydata',lyglob(lneustart(numtra)+1:ltgl,2) );

          % x1(t) nichtlinear
          set(x1tra(numtra),...
                'xdata',tglob(neustart(numtra)+1:tgl),...
                'ydata',yglob(neustart(numtra)+1:tgl,1) );
            
          % x_2(t) nichtlinear   
          set(x2tra(numtra),...
                'xdata',tglob(neustart(numtra)+1:tgl),...
                'ydata',yglob(neustart(numtra)+1:tgl,2) );

          % Anmerkung: die Reihenfolge 
          % 'erst linear dann nichtlinear' sorgt dafuer, dass die 
          % nichtlineare ueber die lineare Loesung geplottet wird
          
         drawnow;
        end
    end

    % Anfangswert ins Phasenportrait zeichnen
    % (auch zum Zeichnen des aktuellen Zustandes in der 
    %  Animation verwendet)

    function zeichne_anfangswert()
        
        set(aw, 'xdata', y(1),'ydata', y(2));
        set(law,'xdata',ly(1),'ydata',ly(2));
        
        drawnow;
        
    end

    % Pendelmodell zeichnen

    function zeichne_pendel()
   
        % Dicke der Elemente an Fenstergeroesse anpassen, 
        % falls diese ge�ndert wurde
        hfp = get(hf,'Position');
        if (hfp~=hfp_alt)
            hfp_alt = hfp;
            hfsize = min(hfp(3),hfp(4));
            set(masse,'markersize', ceil(100*hfsize));
            set(stab, 'linewidth',  ceil(2*hfsize));
            set(punkt,'markersize', ceil(25*hfsize));
            set(lmasse,'markersize', ceil(27*hfsize));
            set(lstab, 'linewidth',  ceil(2*hfsize));
        end;
      
        % aktuelle numerische Daten den Elementen zuweisen
        set(stab,'ydata',[0, -l.*cos(y(1))], ...
                 'xdata',[0,l.*sin(y(1))] );
        set(punkt,'ydata',0, 'xdata',0);
        set(masse,'ydata',-l.*cos(y(1)), 'xdata',l.*sin(y(1)) );
        set(lstab,'ydata',[0, -l.*cos(ly(1))], ...
                  'xdata',[0,l.*sin(ly(1))] );
        set(lmasse,'ydata',-l.*cos(ly(1)), 'xdata',l.*sin(ly(1)) );
            
        drawnow;

    end

    % Grafikelemente fuer die globale Darstellung einer neuen 
    % Trajektorie anlegen. Die Elemente werden in 
    % 'loesungen_neu_zeichnen' mit numerischen Werten belegt.
    
    function neue_trajektorie()
        
        % Zaehler und Indizes weiterzaehlen
        
        numtra = numtra + 1;
        neustart  = [ neustart;  tgl];
        lneustart = [lneustart; ltgl];

        % Neue Grafikelemente anlegen
        
        subplot(h2);
        
        % Phasenportrait linear
        lxxtra(numtra) = line( ...
                        'linewidth', 1, ...
                        'color',[0.7 0.7 0.7], ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);
                    
        % Phasenportrait nichtlinear                    
        xxtra(numtra)  = line( ...
                        'linewidth', 1, ...
                        'color','k', ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);
    
        subplot(h3);
        
        % x_1(t) linear
        lx1tra(numtra) = line( ...
                        'linewidth', 1, ...
                        'color',[0.7, 0.7, 1.0], ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);
                    
        % x_2(t) linear                    
        lx2tra(numtra) = line( ...
                        'linewidth', 1, ...
                        'color',[1.0, 0.7, 0.7], ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);

        % x_1(t) nichtlinear                    
        x1tra(numtra) = line( ...
                        'linewidth', 1, ...
                        'color','b', ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);
                    
        % x_2(t) nichtlinear            
        x2tra(numtra) = line( ...
                        'linewidth', 1, ...
                        'color','r', ...
                        'LineStyle','-', ...
                        'erase','none', ...
                        'xdata',[],'ydata',[],'zdata',[]);
     
        % Sichtbarkeiten setzen 
        set( xxtra(numtra), 'Visible',  nl_visible);
        set( x1tra(numtra), 'Visible',  nl_visible);
        set( x2tra(numtra), 'Visible',  nl_visible);
        set(lxxtra(numtra), 'Visible', lin_visible);
        set(lx1tra(numtra), 'Visible', lin_visible);
        set(lx2tra(numtra), 'Visible', lin_visible);
  
    end

end
