#!/usr/pkg/bin/perl  
# Needs perl/Tk!

use Tk qw/:eventtypes DoOneEvent DONT_WAIT/;

$NRANGES=7;
$PI=3.14159265358979323846;

$m         = 1.0;
$l         = 1.0;
$deltaT    = 0.0025;
$alpha0    = 55.0*($PI/180.0);
$alphaDot0 = 1.5;
$a0        = 10.0;
$g         = 9.81;
$A1        = 50000.0;

$CANVAS_H  = 100;

$Bumper_alphaDot = 0.5;
$Bumper_alpha    = 10.0*($PI/180.0);

$reliefstyle="groove";


###########################################################################
sub myeval
{
    local($x)=@_;
    #print "$x\n";
    eval($x);
}

###########################################################################
sub init
{
    for ($i=0; $i<$NRANGES; $i++){
	$b_a[$i]            = 0.0;
	$b_alpha[$i]        = 0.0;
	$b_alphaDot[$i]     = 0.0;

	$b_a_txt[$i]        = sprintf("%5.3f", $b_a[$i]); 
	$b_alpha_txt[$i]    = sprintf("%5.3f", $b_a[$i]); 
	$b_alphaDot_txt[$i] = sprintf("%5.3f", $b_a[$i]); 
    }

    $a        = 0.0;
    $alpha    = $alpha0;
    $alphaDot = $alphaDot0;
    $Fg       = $m * $g;

    $xpos = 300;
    $xwinkel = 0;
    
    $NB = 0;
    $NM = 1;
    $NS = 2;
    $ZE = 3;
    $PS = 4;
    $PM = 5;
    $PB = 6;
    
    #/* Grenzen fuer Alpha */
    $b_alpha_l[$NB] = -30.0;   $b_alpha_u[$NB] =  30.0;
    $b_alpha_l[$NM] =   0.0;   $b_alpha_u[$NM] =  60.0;
    $b_alpha_l[$NS] =  30.0;   $b_alpha_u[$NS] =  90.0;
    $b_alpha_l[$ZE] =  60.0;   $b_alpha_u[$ZE] = 120.0;
    $b_alpha_l[$PS] =  90.0;   $b_alpha_u[$PS] = 150.0;
    $b_alpha_l[$PM] = 120.0;   $b_alpha_u[$PM] = 180.0;
    $b_alpha_l[$PB] = 150.0;   $b_alpha_u[$PB] = 210.0;
    $b_alpha_min = -30.0;
    $b_alpha_max = 210.0; 

    for($i=0;$i<$NRANGES;$i++){
	$b_alpha_l[$i] = $b_alpha_l[$i]*$PI/180.0;
	$b_alpha_u[$i] = $b_alpha_u[$i]*$PI/180.0;
    }
    $b_alpha_min = $b_alpha_min*$PI/180.0;
    $b_alpha_max = $b_alpha_max*$PI/180.0;

    #/* Grenzen fuer alphaDot */
    $b_alphaDot_l[$NB] = -5.0;   $b_alphaDot_u[$NB] = -1.0;
    $b_alphaDot_l[$NM] = -3.0;   $b_alphaDot_u[$NM] = -1.0;
    $b_alphaDot_l[$NS] = -2.0;   $b_alphaDot_u[$NS] =  1.0;
    $b_alphaDot_l[$ZE] = -0.5;   $b_alphaDot_u[$ZE] =  0.5;
    $b_alphaDot_l[$PS] = -1.0;   $b_alphaDot_u[$PS] =  2.0;
    $b_alphaDot_l[$PM] =  1.0;   $b_alphaDot_u[$PM] =  3.0;
    $b_alphaDot_l[$PB] =  1.0;   $b_alphaDot_u[$PB] =  5.0;
    $b_alphaDot_min = -5.0;
    $b_alphaDot_max =  5.0;

    # Dummy-Grenzen fuer a
    for ($j=0; $j<$NRANGES; $j++){
	$b_a_l[$j] = $j-int($NRANGES/2)-0.5;
	$b_a_u[$j] = $j-int($NRANGES/2)+0.5;
    }
    $b_a_min = 0 - int($NRANGES/2) - 0.5 - 0.1;
    $b_a_max = ($NRANGES-1) - int($NRANGES/2) + 0.5 + 0.1;

    #/* Regeln definieren */
    $b_rule_alpha[0]=$PM; $b_rule_alphaDot[0]=$ZE; $b_rule_a[0]=$PM;
    $b_rule_alpha[1]=$PS; $b_rule_alphaDot[1]=$PS; $b_rule_a[1]=$PS;
    $b_rule_alpha[2]=$PS; $b_rule_alphaDot[2]=$NS; $b_rule_a[2]=$ZE;
    $b_rule_alpha[3]=$NM; $b_rule_alphaDot[3]=$ZE; $b_rule_a[3]=$NM;
    $b_rule_alpha[4]=$NS; $b_rule_alphaDot[4]=$NS; $b_rule_a[4]=$NS;
    $b_rule_alpha[5]=$NS; $b_rule_alphaDot[5]=$PS; $b_rule_a[5]=$ZE;
    $b_rule_alpha[6]=$ZE; $b_rule_alphaDot[6]=$ZE; $b_rule_a[6]=$ZE;
    $NRULES=7;

    #/* Bezeichnungen fuer Indizes */
    $b_bez[$NB] = "NB";
    $b_bez[$NM] = "NM";
    $b_bez[$NS] = "NS";
    $b_bez[$ZE] = "ZE";
    $b_bez[$PS] = "PS";
    $b_bez[$PM] = "PM";
    $b_bez[$PB] = "PB";
}

###########################################################################
sub mkboard
{
    local($i)=@_;
    
    $t = '
          $f_$i = $zahlen->Frame(-relief => $reliefstyle,
			         -borderwidth=>3);
          $f_$i->pack(-fill => x, -expand=>yes, -side => left);
          $f_$i_titel = $f_$i->Label(-text => "$i");
          $f_$i_titel->pack();';
    $t=~s/\$i/$i/g;
    myeval($t);

    for($j=0; $j<$NRANGES; $j++){
	$t = '
              $f_$i_f$j = $f_$i->Frame();
	      $f_$i_f$j->pack(-fill=>x, -expand=>yes);

	      $f_$i_f$j_label = $f_$i_f$j->Label(-text => "$X: ");
	      $f_$i_f$j_label->pack(-side=>left);
	
	      $f_$i_f$j_val = $f_$i_f$j->Label(-textvariable => \$b_$i_txt[$j]);
	      $f_$i_f$j_val->pack(-side=>right);';
	$t=~s/\$i/$i/g;
	$t=~s/\$X/$b_bez[$j]/g;
	$t=~s/\$j/$j/g;
	myeval($t);
    }
    
    $t = '
          $f_$i_fcanvas = $f_$i->Frame(-borderwidth=>3, -relief=>$reliefstyle);
          $f_$i_fcanvas->pack(-fill=>x, -expand=>yes);
    
          $f_$i_canvas = $f_$i_fcanvas->Canvas(-bg => white,
                                               -width => 200,
                                               -height => $CANVAS_H,
                                              );
          $f_$i_canvas->pack(-fill=>x, -expand=>yes);';
    $t=~s/\$i/$i/g;
    myeval($t);

    $t = '
	  $f_$i_fval = $f_$i->Frame();
          $f_$i_fval->pack(-side=>left);
    
          $f_$i_fval_lab = $f_$i_fval->Label(-text => "$i  = ");
          $f_$i_fval_lab->pack(-side=>left);
    
          $f_$i_fval_val = $f_$i_fval->Label(-textvariable => \$$i_txt);
          $f_$i_fval_val->pack(-side=>left);';
    $t=~s/\$i/$i/g;
    myeval($t);
    
    $t = '
          $f_$i_fval_val = $f_$i_fval->Label(-text => "");
          $f_$i_fval_val->pack(-side=>left, -fill=>x, -expand=>yes);';
    $t=~s/\$i/$i/g;
    myeval($t);
    
}

###########################################################################
sub initUI
{
    my $main = new MainWindow;

    $help = $main->Balloon();
    
    {
	# Menueleiste

	$menubar=$main->Frame(-relief => 'raised',
			      -borderwidth => 2);
	$menubar->pack(-side => top, -fill => x, -expand => yes);
	$f=$menubar->Menubutton(-text => 'File',
				-underline => 0,
				-menuitems => [
					       [Button => 'Reset',        -command => sub{reset_fn();} ], 
					       [Button => 'Set defaults', -command => sub{set_defaults_fn();} ], 
					       [Button => 'About',        -command => sub{about_fn();} ],
					       [Separator => ''], 
					       [Button => 'Quit',         -command => sub{quit_fn();} ],
					       ]
				);
	$f->pack(-side => left);
	$s=$menubar->Menubutton(-text => 'Simulation',
				-underline => 0,
				-menuitems => [
					       [Button => 'Start', -command => sub{startstop_fn() if !$running} ], 
					       [Button => 'Stop',  -command => sub{startstop_fn() if $running} ], 
					       ]
				);
	$s->pack(-side => left);
    }
    
    
    {
	$titel=$main->Label( -text => "Fuzzy Pendel",
			     -font => "-*-helvetica-*-r-*--*-240-*-*-*-*-iso8859-1"
			     );
	$titel->pack();
    }

    {
	# Pendel-Rahmen mit Bump-Buttons
	
	$display=$main->Frame(-relief => $reliefstyle,
			      -borderwidth => 3
			      );
	$display->pack(-fill => x );
	
	$b_bump_left = $display->Button(-text => "<",
					-command => sub{bump_left();});
	$b_bump_left->pack(-side => left );
	$help->attach($b_bump_left,
		      -balloonmsg => "Bump to the left",
		      );
	
	$pendel=$display->Canvas(-bg => white,
				 -height => $CANVAS_H
				 );
	$pendel->pack(-side => left,
		      -fill => x,
		      -expand => yes );
	
	$b_bump_right = $display->Button(-text => ">",
					 -command => sub{bump_right();});
	$b_bump_right->pack(-side => right );
	$help->attach($b_bump_right,
		      -balloonmsg => "Bump to the right",
		      );
    }
    
    {
	# Graph mit Winkel
	
	$f_winkel=$main->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	$f_winkel->pack(-fill => x,
			-expand => yes);
	
	$winkel=$f_winkel->Canvas(-bg => white,
				  -height => $CANVAS_H
				  );
	$winkel->pack(-fill => x,
		      -expand => yes);
	$winkel->create('line',
			0,$CANVAS_H/2,10000,$CANVAS_H/2
			);
    }
    
    {
	# Zahlentabellen fuer alpha, alphaDot, a
	
	$zahlen=$main->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	$zahlen->pack(-fill => x, -expand=>yes);
	
	foreach $i ( "alpha", "alphaDot", "a")
	{
	    # print "$i:\n";
	    mkboard($i);
	}
    }
    
    if(0){
	# Fuellrahmen
	
	$fill=$main->Frame(-relief=>sunken, -borderwidth=>3, -bg=>red);
	$fill->pack(-expand => yes,
		    -fill => both);
    }
    
    {
	# Unterste Button-Lsiets: Start/Stop, Step, Quit
	
	$buttons=$main->Frame(-relief=>$reliefstyle,
			      -borderwidth => 3
			      );
	$buttons->pack(-side => bottom,
		       -fill => x);
	
	$b_startstop=$buttons->Button( -text => $running?"Stop":"Start",
				       -command => sub{startstop_fn();}
				       );
	$b_startstop->pack(-side => left,
			   -fill => x, 
			   -expand => yes);
	$help->attach($b_startstop,
		      -balloonmsg=>"Start/stop simulation");
	
	$b_step=$buttons->Button( -text => "Step",
				  -command => sub{startstop_fn() if $running; step_fn();}
				  );
	$b_step->pack(-side => left, 
		      -fill => x, 
		      -expand => yes);
	$help->attach($b_step,
		      -balloonmsg=>"Stop simulation and perform single step");
	
	$b_quit=$buttons->Button( -text => "Quit",
				  -command => sub{quit_fn();}
				  );
	$b_quit->pack(-side => right,
		      -fill => x, 
		      -expand => yes);
	$help->attach($b_quit,
		      -balloonmsg=>"Quit program");
    }
}

###########################################################################
sub arccos
{
    atan2( sqrt(1.0 - $_[0] * $_[0]), $_[0] );
}

###########################################################################
sub sqr
{
    $_[0] * $_[0];
}

###########################################################################
sub startstop_fn
{
    $running=!$running;
    
    $b_startstop->configure(-text=>$running?"Stop":"Start");
    
    # print $running?"started":"stopped", "\n";
}

###########################################################################
sub calculate
{
    # f2: Ausgleichen der Pendelbewegung
    $a = balance($alpha, $alphaDot);
    $Fa = $m * $a * $a0;
    
    # f1: Pendel-Verhalten nach Ch. Ziegaus
    $Fres       = sqrt (sqr($Fg) + sqr($Fa));
    $rho        = $alpha - arccos ($Fa / $Fres);
    $Fz         = sin ($rho) * $Fres;
    $deltaAlpha = $Fz / (2.0 * $m * $l) * sqr($deltaT) + $alphaDot*$deltaT;
    $alphaDot   = $Fz / ($m * $l) * $deltaT + $alphaDot;
    $alpha      = $alpha + $deltaAlpha;

    $xpos = $xpos + 0.5 * $a * sqr($deltaT) * $A1;

    if ($xpos > $pendel->winfo(width)) {
	$xpos = 0;
    }
    if ($xpos < 0) {
	$xpos = $pendel->winfo(width);
    }

    if ($alpha > $PI) {
	$alpha = $PI;
	$alphaDot = 0;
	startstop_fn();
    }
    if ($alpha < 0) {
	$alpha = 0;
	$alphaDot = 0;
	startstop_fn();
    }
}

###########################################################################
sub step_fn
{
    calculate();
    paint();    
}

###########################################################################
sub quit_fn
{
    exit(0);
}

###########################################################################
sub bump_left
{
    $alphaDot = $alphaDot + $Bumper_alphaDot;
    $alpha    = $alpha    + $Bumper_alpha;

    paint();
}

###########################################################################
sub bump_right
{
    $alphaDot = $alphaDot - $Bumper_alphaDot;
    $alpha    = $alpha    - $Bumper_alpha;
    
    paint();
}

###########################################################################
sub balance
{
    local($alpha, $alphaDot) = @_;

    # Gewichte von alpha ausrechnen
    for ($i=0; $i < $NRANGES; $i++){
	if(($b_alpha_u[$i] > $alpha) && ($alpha > $b_alpha_l[$i])){
	    $mid = ($b_alpha_u[$i]+$b_alpha_l[$i])/2.0;
	    if ($alpha>$mid) {
		#/* rechte Haelfte */
		$b_alpha[$i] = 1.0-($alpha-$mid)/($b_alpha_u[$i]-$mid);
	    }else{
		#/* linke Haelfte */
		$b_alpha[$i] = ($alpha-$b_alpha_l[$i])/($mid-$b_alpha_l[$i]);
	    }
	}else{
	    $b_alpha[$i] = 0.0;
	}
    }

    # Gewichte von alphaDot ausrechnen
    for($i=0; $i < $NRANGES; $i++){
	if(($b_alphaDot_u[$i] > $alphaDot) && ($alphaDot > $b_alphaDot_l[$i])){
	    $mid = ($b_alphaDot_u[$i]+$b_alphaDot_l[$i])/2.0;
	    if ($alphaDot > $mid) {
		#/* rechte Haelfte */
		$b_alphaDot[$i] = 1.0-($alphaDot-$mid)/($b_alphaDot_u[$i]-$mid);
	    }else{
		#/* linke Haelfte */
		$b_alphaDot[$i] =
		    ($alphaDot-$b_alphaDot_l[$i])/($mid-$b_alphaDot_l[$i]);
	    }
	}else{
	    $b_alphaDot[$i] = 0.0;
	}
    }
    
    #/* Regeln anwenden */
    for($i=0; $i<$NRANGES; $i++){
	$b_a[$i] = 0.0;
    }
    for($i=0; $i<$NRULES; $i++){
	$b_a[$b_rule_a[$i]] = Max($b_a[$b_rule_a[$i]],
				  Min($b_alpha[$b_rule_alpha[$i]],
				      $b_alphaDot[$b_rule_alphaDot[$i]]));
    }

    #/* Mittelwert ausrechnen */
    $max=0.0;
    for ($i=0; $i<$NRANGES; $i++) {
	$max = $max + ($i-int($NRANGES/2))*$b_a[$i];
    }

    return -$max;
}

###########################################################################
sub Max
{
    ($_[0] > $_[1]) ? $_[0] : $_[1];
}

###########################################################################
sub Min
{
    ($_[0] < $_[1]) ? $_[0] : $_[1];
}

###########################################################################
sub paint
{
    #print "HF: alpha=$alpha, alphaDot = $alphaDot\n";

    $a_txt        = sprintf("%5.3f", $a);
    $alpha_txt    = sprintf("%5.3f°", $alpha*180.0/$PI);
    $alphaDot_txt = sprintf("%5.3f", $alphaDot);

    # $pendel
    $pendel->delete('strich');
    $pendel->create('line',
		    $xpos, $CANVAS_H,
		    $xpos+cos($alpha)*$CANVAS_H*0.8, $CANVAS_H-0.8*$CANVAS_H*sin($alpha),,
		    -tags => 'strich',
		    -width => 2, 
		    );

    # $winkel
    $wcnt--;
    if ($wcnt<0){
	$wcnt=10;
	
	$xwinkel += 2;
	if ( $xwinkel > $winkel->winfo(width) ){
	    $xwinkel = 0;
	    $winkel->delete('punkte');
	}
	$winmax=$winkel->winfo(height);
	#$y=$winmax/2 +  $winmax * ($alpha-$PI/2)/$PI;
	$y=$winmax/2 +  0.97 * $winmax/2*cos($alpha);
	$ptsz=1;
	$winkel->create('oval',
			$xwinkel-$ptsz, $y - $ptsz -2,
			$xwinkel+$ptsz, $y + $ptsz -2, 
			-tags => 'punkte',
			);
    }

    # tafeln
    $tcnt--;
    if ($tcnt<0) {
	$tcnt=50;
	
	for($i=0; $i<$NRANGES; $i++){
	    $b_a_txt[$i]        = sprintf("%5.3f", $b_a[$i]); 
	    $b_alpha_txt[$i]    = sprintf("%5.3f", $b_alpha[$i]); 
	    $b_alphaDot_txt[$i] = sprintf("%5.3f", $b_alphaDot[$i]); 
	}
    }

    # boards
    $bcnt--;
    if ($bcnt < 0) {
	$bcnt=100;
	
	{
	    # alpha
	    my($w) = $f_alpha_canvas->width;
	    my($h) = $f_alpha_canvas->height;
	    my($mid, $d, $d2);
	    
	    $f_alpha_canvas->delete('striche');
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		$mid = ($b_alpha_l[$j] + $b_alpha_u[$j]) / 2.0;
		$d = $b_alpha_u[$j] - $b_alpha_l[$j];
		$d2 = $b_alpha_max - $b_alpha_min;

		$f_alpha_canvas->create('line', 
					$w*($b_alpha_l[$j]-$b_alpha_min)/$d2,
					$h,
					$w*(($mid-$b_alpha_min)/$d2),
					0,
					-tags => 'striche'
					);
		$f_alpha_canvas->create('line', 
					$w*(($mid-$b_alpha_min)/$d2),
					0,
					$w*($b_alpha_u[$j]-$b_alpha_min)/$d2,
					$h,
					-tags => 'striche'
					);
	    }
	}
	{
	    # alphaDot
	    my($w) = $f_alphaDot_canvas->width;
	    my($h) = $f_alphaDot_canvas->height;
	    my($mid, $d, $d2);
	    
	    $f_alphaDot_canvas->delete('striche');
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		$mid = ($b_alphaDot_l[$j] + $b_alphaDot_u[$j]) / 2.0;
		$d = $b_alphaDot_u[$j] - $b_alphaDot_l[$j];
		$d2 = $b_alphaDot_max - $b_alphaDot_min;
		
		$f_alphaDot_canvas->create('line', 
					   $w*($b_alphaDot_l[$j]-$b_alphaDot_min)/$d2,
					   $h,
					   $w*(($mid-$b_alphaDot_min)/$d2),
					   0, 
					   -tags => 'striche'
					   );
		$f_alphaDot_canvas->create('line', 
					   $w*(($mid-$b_alphaDot_min)/$d2),
					   0,
					   $w*($b_alphaDot_u[$j]-$b_alphaDot_min)/$d2,
					   $h,
					   -tags => 'striche'
					   );
	    }
	}
	{
	    # a
	    my($w) = $f_a_canvas->width;
	    my($h) = $f_a_canvas->height;
	    my($mid, $d, $d2);

	    $f_a_canvas->delete('striche');
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		$mid = ($b_a_l[$j] + $b_a_u[$j]) / 2.0;
		$d = $b_a_u[$j] - $b_a_l[$j];
		$d2 = $b_a_max - $b_a_min;
		
		$f_a_canvas->create('line', 
				    $w*($b_a_l[$j]-$b_a_min)/$d2,
				    $h,
				    $w*(($mid-$b_a_min)/$d2),
				    0, 
				    -tags => 'striche'
				    );
		$f_a_canvas->create('line', 
				    $w*(($mid-$b_a_min)/$d2),
				    0,
				    $w*($b_a_u[$j]-$b_a_min)/$d2,
				    $h,
				    -tags => 'striche'
				    );
	    }
	}
    }

    # exakte werte (rote striche)
    $scnt--;
    if ($scnt<0) {
	$scnt=5;

	{
	    # Exakter Wert fuer alpha
	    my($x);
	    $x = $f_alpha_canvas->winfo(width)
	        *($alpha-$b_alpha_min)
		    /($b_alpha_max - $b_alpha_min);
	    
	    $f_alpha_canvas->delete('strich-alpha');
	    $f_alpha_canvas->create('line',
				    $x, 0, $x, $f_alpha_canvas->winfo(height),
				    -tags => 'strich-alpha',
				    -width => 2, 
				    -fill => red, 
				    );
	}
	{
	    # Exakter Wert fuer alphaDot
	    my($x);
	    $x = $f_alphaDot_canvas->winfo(width)
	        *($alphaDot-$b_alphaDot_min)
		    /($b_alphaDot_max - $b_alphaDot_min);
	    
	    $f_alphaDot_canvas->delete('strich-alphaDot');
	    $f_alphaDot_canvas->create('line',
				       $x, 0, $x, $f_alphaDot_canvas->winfo(height),
				       -tags => 'strich-alphaDot',
				       -width => 2, 
				       -fill => red, 
				       );
	}
	{
	    # Exakter Wert fuer a
	    my($x);
	    $x = $f_a_canvas->winfo(width)
	        *($a-$b_a_min)
		    /($b_a_max - $b_a_min);
	    
	    $f_a_canvas->delete('strich-a');
	    $f_a_canvas->create('line',
				$x, 0, $x, $f_a_canvas->winfo(height),
				-tags => 'strich-a',
				-width => 2, 
				-fill => red, 
				);
	}
    }

    # Trapeze
    $trpcnt--;
    if ($trpcnt<0) {
	$trpcnt=50;
	
	{
	    # alpha
	    my($w) = $f_alpha_canvas->width;
	    my($h) = $f_alpha_canvas->height;
	    my($d, $d2, $x1, $x2);
	    
	    $f_alpha_canvas->delete('trapeze');
	    $d2 = $b_alpha_max - $b_alpha_min;
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		if ($b_alpha[$j] > 0) {
		    $d = ($b_alpha_u[$j] - $b_alpha_l[$j]) / 2.0;
		    
		    $x1 = $b_alpha_l[$j] + ($d * $b_alpha[$j]);
		    $x2 = $b_alpha_u[$j] - ($d * $b_alpha[$j]);
		    
		    $f_alpha_canvas->create('polygon',
					    $w*($b_alpha_l[$j]-$b_alpha_min)/$d2, 
					    $h,
					    $w*($x1-$b_alpha_min)/$d2,
					    $h*(1.0-$b_alpha[$j]),
					    $w*($x2-$b_alpha_min)/$d2,
					    $h*(1.0-$b_alpha[$j]),
					    $w*($b_alpha_u[$j]-$b_alpha_min)/$d2, 
					    $h,
					    -fill => yellow,
					    -outline => black, 
					    -tags => 'trapeze'
					    );
		}
	    }
	}
	{
	    # alphaDot
	    my($w) = $f_alphaDot_canvas->width;
	    my($h) = $f_alphaDot_canvas->height;
	    my($d, $d2, $x1, $x2);
	    
	    $f_alphaDot_canvas->delete('trapeze');
	    $d2 = $b_alphaDot_max - $b_alphaDot_min;
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		if ($b_alphaDot[$j] > 0) {
		    $d = ($b_alphaDot_u[$j] - $b_alphaDot_l[$j]) / 2.0;
		    
		    $x1 = $b_alphaDot_l[$j] + ($d * $b_alphaDot[$j]);
		    $x2 = $b_alphaDot_u[$j] - ($d * $b_alphaDot[$j]);
		    
		    $f_alphaDot_canvas->create('polygon',
					    $w*($b_alphaDot_l[$j]-$b_alphaDot_min)/$d2, 
					    $h,
					    $w*($x1-$b_alphaDot_min)/$d2,
					    $h*(1.0-$b_alphaDot[$j]),
					    $w*($x2-$b_alphaDot_min)/$d2,
					    $h*(1.0-$b_alphaDot[$j]),
					    $w*($b_alphaDot_u[$j]-$b_alphaDot_min)/$d2, 
					    $h,
					    -fill => yellow,
					    -outline => black, 
					    -tags => 'trapeze'
					    );
		}
	    }
	}
	{
	    # a
	    my($w) = $f_a_canvas->width;
	    my($h) = $f_a_canvas->height;
	    my($d, $d2, $x1, $x2);
	    
	    $f_a_canvas->delete('trapeze');
	    $d2 = $b_a_max - $b_a_min;
	    
	    for ($j = 0; $j < $NRANGES; $j++){
		if ($b_a[$j] > 0) {
		    $d = ($b_a_u[$j] - $b_a_l[$j]) / 2.0;
		    
		    $x1 = $b_a_l[$j] + ($d * $b_a[$j]);
		    $x2 = $b_a_u[$j] - ($d * $b_a[$j]);
		    
		    $f_a_canvas->create('polygon',
					    $w*($b_a_l[$j]-$b_a_min)/$d2, 
					    $h,
					    $w*($x1-$b_a_min)/$d2,
					    $h*(1.0-$b_a[$j]),
					    $w*($x2-$b_a_min)/$d2,
					    $h*(1.0-$b_a[$j]),
					    $w*($b_a_u[$j]-$b_a_min)/$d2, 
					    $h,
					    -fill => yellow,
					    -outline => black, 
					    -tags => 'trapeze'
					    );
		}
	    }
	}
    }
}

###########################################################################
sub set_defaults_fn
{
    $alpha0deg=$alpha0*180.0/$PI;
    
    if (not $about) {
	$about = new MainWindow;
	
	$title=$about->Label(-text => "Set Defaults", 
			     -font => "-*-helvetica-*-r-*--*-240-*-*-*-*-iso8859-1"
			     );
	$title->pack(-side => top);

	{
	    $deff1=$about->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	    $deff1->pack(-expand=>yes, -fill=>both);

	    $deff11=$deff1->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	    $deff11->pack(-expand=>yes, -fill=>both);
	    $def_alpha0_lab=$deff11->Label(-text=>"alpha0:");
	    $def_alpha0_lab->pack(-side=>left);
	    $def_alpha0_ent=$deff11->Entry(-textvariable=>\$alpha0deg);
	    $def_alpha0_ent->pack(-side=>left);

	    $deff12=$deff1->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	    $deff12->pack(-expand=>yes, -fill=>both);
	    $def_alphaDot0_lab=$deff12->Label(-text=>"alphaDot0:");
	    $def_alphaDot0_lab->pack(-side=>left);
	    $def_alphaDot0_ent=$deff12->Entry(-textvariable=>\$alphaDot0);
	    $def_alphaDot0_ent->pack(-side=>left);
	    
	    $deff13=$deff1->Frame(-relief=>$reliefstyle, -borderwidth=>3);
	    $deff13->pack(-expand=>yes, -fill=>both);
	    $def_a0_lab=$deff13->Label(-text=>"a0:");
	    $def_a0_lab->pack(-side=>left);	    
	    $def_a0_ent=$deff13->Entry(-textvariable=>\$a0);
	    $def_a0_ent->pack(-side=>left);
	}

	{
	    $deff2=$about->Frame(-relief=>$reliefstyle);
	    $deff2->pack(-expand=>yes, -fill=>both);
	    
	    $deff2
		->Button(-text=>"OK", -command=>sub{do_set_defaults()})
	        ->pack(-side=>left);
	    $deff2
		->Button(-text=>"Cancel", -command=>sub{$about->destroy;})
		->pack(-side=>left);
	}
    }
}

###########################################################################
sub do_set_defaults
{
    $about->bell;
    $about->destroy;

    undef $about;
    
    $alpha0=$alpha0deg*$PI/180.0;

    reset_fn();

}

###########################################################################
sub about_fn
{
    print "FuzzyPendel, by Hubert Feyrer <hubert.feyrer\@informatik.fh-regensburg.de>\n";
}

###########################################################################
sub reset_fn
{
    init();

    $winkel->delete('punkte');

    if ($running) {
	startstop_fn();
    }

    $wcnt=0;
    $tcnt=0;
    $bcnt=0;
    $scnt=0;
    $trpcnt=0;

    paint();
}

###########################################################################
###########################################################################
##
##  M A I N
##
###########################################################################
###########################################################################

init();
initUI();

paint();

while (1) {
    DoOneEvent($running ? DONT_WAIT : ALL_EVENTS);
    if ($running) {
	step_fn();
    }

    #select(undef, undef, undef, 0.01) if $running;
}
