##################################################################
# Modul fuer Diagramme
# Letzte Aenderung: 06.01.2012
##################################################################
use POSIX qw /floor ceil/;
use Math::Trig;
use strict;
use warnings;

my $achsen = 0;

## Achsen werden gezeichnet
sub setachsen {
	my ($wert) = @_;
	$achsen = $wert;
}

sub getachsen { return $achsen; }

my ( $balken, $saeule, $relativ, $pikto );

$balken = $saeule = $relativ = $pikto = 0;

sub setbalken { $balken = 1; }
sub getbalken { return $balken; }

sub setsaeule { $saeule = 1; }
sub getsaeule { return $saeule; }

sub setrelativ { $relativ = 1; }
sub getrelativ { return $relativ; }
sub setpikto   { $pikto   = 1; }
sub getpikto   { return $pikto; }

sub setymaxstat {
	my ($max) = @_;
	setachsengraph( getachsengraph("xmin"), getachsengraph("ymin"),
		getachsengraph("xmax"), $max );
}

sub saeule {
	my (
		$layer,           $x,             $y,        $dx,
		$dy,              $farbe,         $fuellart, $fuellfarbe,
		$linienart,       $linienstaerke, $text,     $textwinkel,
		$textausrichtung, $welcherbalken, $parameter
	) = @_;

	setachsengraph( $x, $y, $x + 2 * $dx, $y + $dy );

	#    achsengraph( $x,       $y );
	#    achsengraph( $x + $dx, $y + $dy );
	if ( $dx == 0 ) {
		linie( $layer, $x, $y, "", $x, $y + $dy, "", $linienart, $linienstaerke,
			$farbe, $parameter, "-" );
	}
	elsif ( $dy == 0 ) {
		linie( $layer, $x, $y, "", $x + $dx, $y, "", $linienart, $linienstaerke,
			$farbe, $parameter, "-" );
	}
	else {
		rechteck(
			$layer, nachkommastellen( $x, 5 ),
			nachkommastellen( $y,  5 ), nachkommastellen( $dx, 5 ),
			nachkommastellen( $dy, 5 ), 0,
			$farbe,         $fuellart,
			$fuellfarbe,    $linienart,
			$linienstaerke, $parameter
		);
	}

	if ( $welcherbalken eq "s" ) {
		if ( $textausrichtung eq "auf" ) {
			beschriftung( $layer + 1, "black", $x + $dx / 2,
				$y, $textwinkel, 90, $text );
		}
		elsif ( $textausrichtung eq "mitte" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $dy / 2,
				$textwinkel, "c", $text
			);
		}
		elsif ( $textausrichtung eq "unten" ) {
			beschriftung( $layer + 1, "black", $x + $dx / 2,
				$y - 0.5, $textwinkel, 90, $text );
		}
		elsif ( $textausrichtung eq "oben" ) {
			beschriftung( $layer + 1, "black", $x + $dx / 2,
				$y + $dy, $textwinkel, 90, $text );
		}
		else {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $textausrichtung,
				$textwinkel, "c", $text
			);
		}
	}
	if ( $welcherbalken eq "b" ) {
		if ( $textausrichtung eq "auf" ) {
			beschriftung( $layer + 1, "black", $x, $y + $dy / 2,
				$textwinkel, 0, $text );
		}
		elsif ( $textausrichtung eq "mitte" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $dy / 2,
				$textwinkel, "c", $text
			);
		}
		elsif ( $textausrichtung eq "links" ) {
			beschriftung( $layer, "black", $x - 0.5, $y + $dy / 2,
				$textwinkel, "l", $text );
		}
		elsif ( $textausrichtung eq "rechts" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx + $dx / 4,
				$y + $dy / 2,
				$textwinkel, "r", $text
			);
		}
		else {
			beschriftung(
				$layer + 1, "black",
				$x + $textausrichtung,
				$y + $dy / 2,
				$textwinkel, 90, $text
			);
		}
	}
}

sub saeuledreieck {
	my (
		$layer,           $x,             $y,        $dx,
		$dy,              $farbe,         $fuellart, $fuellfarbe,
		$linienart,       $linienstaerke, $text,     $textwinkel,
		$textausrichtung, $welcherbalken, $parameter
	) = @_;

	achsengraph( $x,       $y );
	achsengraph( $x + $dx, $y + $dy );

	if ( $welcherbalken eq "s" ) {
		dreieck(
			$layer,      $x,         $y,             "",
			$x + $dx,    $y,         "",             $x + $dx / 2,
			$y + $dy,    "",         $farbe,         $fuellart,
			$fuellfarbe, $linienart, $linienstaerke, $parameter
		);
		if ( $textausrichtung eq "auf" ) {
			beschriftung( $layer + 1, "black", $x + $dx / 2,
				$y, $textwinkel, 90, $text );
		}
		elsif ( $textausrichtung eq "mitte" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $dy / 2,
				$textwinkel, "c", $text
			);
		}
		elsif ( $textausrichtung eq "unten" ) {
			beschriftung( $layer + 1, "black", $x + $dx / 2,
				$y - 0.5, $textwinkel, 90, $text );
		}
		elsif ( $textausrichtung eq "oben" ) {
			beschriftung( $layer, "black", $x + $dx / 2,
				$y + $dy, $textwinkel, 90, $text );
		}
		else {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $textausrichtung,
				$textwinkel, 90, $text
			);
		}
	}
	if ( $welcherbalken eq "b" ) {
		dreieck(
			$layer,      $x,           $y,             "",
			$x + $dx,    $y + $dy / 2, "",             $x,
			$y + $dy,    "",           $farbe,         $fuellart,
			$fuellfarbe, $linienart,   $linienstaerke, $parameter
		);
		if ( $textausrichtung eq "auf" ) {
			beschriftung( $layer + 1, "black", $x, $y + $dy / 2,
				$textwinkel, 0, $text );
		}
		elsif ( $textausrichtung eq "mitte" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx / 2,
				$y + $dy / 2,
				$textwinkel, "c", $text
			);
		}
		elsif ( $textausrichtung eq "links" ) {
			beschriftung( $layer + 1, "black", $x - 0.5, $y + $dy / 2,
				$textwinkel, "l", $text );
		}
		elsif ( $textausrichtung eq "rechts" ) {
			beschriftung(
				$layer + 1, "black",
				$x + $dx + $dx / 4,
				$y + $dy / 2,
				$textwinkel, "r", $text
			);
		}
		else {
			beschriftung(
				$layer + 1, "black",
				$x + $textausrichtung,
				$y + $dy / 2,
				$textwinkel, 0, $text
			);
		}
	}
}
### Tortendiagramm
sub torte {
	my (
		$layer,        $x,          $y,               $winkel,
		$winkelanfang, $radius,     $abstand,         $farbe,
		$fuellart,     $fuellfarbe, $linienart,       $linienstaerke,
		$text,         $textwinkel, $textausrichtung, $parameter
	) = @_;

	my $xneu = $x + cos( degtorad( $winkelanfang + $winkel / 2 ) ) * $abstand;
	my $yneu = $y + sin( degtorad( $winkelanfang + $winkel / 2 ) ) * $abstand;
	my $xtext =
	  $xneu + cos( degtorad( $winkelanfang + $winkel / 2 ) ) * $radius / 2;
	my $ytext =
	  $yneu + sin( degtorad( $winkelanfang + $winkel / 2 ) ) * $radius / 2;
	kreisbogen(
		$layer,         $linienart,
		$linienstaerke, $xneu,
		$yneu,          $radius,
		$winkelanfang,  $winkelanfang + $winkel,
		$farbe,         $fuellart,
		$fuellfarbe,    "ja",
		$parameter,     ""
	);
	beschriftung( $layer + 1, $farbe, $xtext, $ytext, $textwinkel, 90, $text );
}
### Ringdiagramm
sub ringdiagramm {
	my (
		$layer,         $x,        $y,          $winkel,
		$winkelanfang,  $radius,   $dicke,      $abstand,
		$farbe,         $fuellart, $fuellfarbe, $linienart,
		$linienstaerke, $text,     $textwinkel, $textausrichtung,
		$parameter
	) = @_;

	my $radiusmitte = $radius - $dicke / 2;
	my $xneu        = nachkommastellen(
		$x + cos( degtorad( $winkelanfang + $winkel / 2 ) ) * $abstand, 4 );
	my $yneu = nachkommastellen(
		$y + sin( degtorad( $winkelanfang + $winkel / 2 ) ) * $abstand, 4 );
	my $xtext = nachkommastellen(
		$xneu + cos( degtorad( $winkelanfang + $winkel / 2 ) ) * $radiusmitte,
		4 );
	my $ytext = nachkommastellen(
		$yneu + sin( degtorad( $winkelanfang + $winkel / 2 ) ) * $radiusmitte,
		4 );
	setachsengraph(
		$xneu - $radius,
		$yneu - $radius,
		$xneu + $radius,
		$yneu + $radius
	);
	ring(
		$layer, $linienart,    $linienstaerke,
		$xneu,  $yneu,         $radius,
		$dicke, $winkelanfang, $winkelanfang + $winkel,
		$farbe, $fuellart,     $fuellfarbe,
		$parameter
	);
	beschriftung( $layer, "black", $xtext, $ytext, $textwinkel, 90, $text );
}

### Bilddiagramm

sub bilddiagramm {
	my (
		$layer, $bild,       $anzahl,          $xstart,
		$y,     $breite,     $winkel,          $abstand,
		$text,  $textwinkel, $textausrichtung, $parameter
	) = @_;
	my ( $i, $xende );

	$xende = $xstart + ( $breite + $abstand ) * $anzahl - 1;
	minmax( $xstart, $y, $xende * 2, $y + $breite );
	setachsengraph( $xstart, $y, $xende, $y );
	schleife( $layer, "nx", $xstart, $xende, $abstand + $breite );
	bild( $layer, "\\nx", $y, "", $breite, $winkel, $bild );
	schleifenende($layer);
	beschriftung(
		$layer, "black",
		$xstart + $textausrichtung,
		$y + bildhoeheberechnet( $bild, $breite ) / 2,
		$textwinkel, 0, $text
	);
}

### Binomialverteilung
sub fac {
	my ($n) = @_;
	my $ergebnis = 1;
	my $i;
	for ( $i = $n ; $i > 1 ; $i = $i - 1 ) { $ergebnis = $ergebnis * $i; }
	return $ergebnis;
}

sub binom {
	my ( $n, $k ) = @_;
	my ( $i, $j );
	my @temp;
	return 0 if ( ( $n < 0 ) || ( $k < 0 ) || ( $k > $n ) );
	for ( $i = 0 ; $i <= $n ; $i++ ) {
		for ( $j = $i ; $j >= 0 ; $j-- ) {
			$temp[$j] =
			  ( ( $j == $i ) || ( $j == 0 ) )
			  ? 1
			  : $temp[$j] + $temp[ $j - 1 ];
		}
	}
	return $temp[$k];
}

my $strich = 0;

sub setbinostrich { $strich = 1; }

sub binomial {
	my (
		$layer,     $n,             $p,          $aufsummiert,
		$breite,    $farbe,         $fuellart,   $fuellfarbe,
		$linienart, $linienstaerke, $markierung, $parameter
	) = @_;

	binomialteil(
		$layer,      $n,           $p,         0,
		$n,          $aufsummiert, $breite,    $farbe,
		$fuellart,   $fuellfarbe,  $linienart, $linienstaerke,
		$markierung, $parameter
	);

}

## Eine Strichliste wird erzeugt

sub strichliste {
	my (
		$layer, $xstart,        $ystart,
		$wert,  $hoehe,         $abstand,
		$farbe, $linienstaerke, $linienart
	) = @_;
	my ( $x, $y, $i, $rest, $anzahl, $abstandfuenf );

	$anzahl = abrunden( $wert / 5, 1 );
	$rest   = $wert % 5;
	$y      = $ystart;

	for ( $i = 1 ; $i <= $wert ; $i++ ) {
		$x = $xstart + $i * $abstand;

		if ( $i % 5 == 0 ) {
			linie(
				$layer, $x - 4 * $abstand,
				$y, "",
				$x - 1 * $abstand,
				$y + $hoehe,
				"", $linienart, $linienstaerke, $farbe, "", ""
			);
		}
		else {
			if ( $i >= $wert - $rest ) {
				linie( $layer, $x, $y, "", $x, $y + $hoehe,
					"", $linienart, $linienstaerke, $farbe, "", "" );
			}
		}

	}

	for ( $i = 1 ; $i <= $anzahl ; $i++ ) {
		$x = $xstart + $i * $abstand * 5;
		schleifeanzahl( $layer, "nx", $x - 4 * $abstand, 4, $abstand );
		linie( $layer, "\\nx", $y, "", "\\nx", $y + $hoehe,
			"", $linienart, $linienstaerke, $farbe, "", "" );
		schleifenende($layer);
	}
}

## Die Binomialverteilung fuer einen Teil zeichnen
sub binomialteil {
	my (
		$layer,      $n,           $p,         $anfang,
		$ende,       $aufsummiert, $breite,    $farbe,
		$fuellart,   $fuellfarbe,  $linienart, $linienstaerke,
		$markierung, $parameter
	) = @_;

	#    setmitte();
	my $q     = 1 - $p;
	my $bern2 = 0;
	my $i     = 0;
	my ( $bern, $bino, $max, $yschritte );
	my $farbeersatz         = getfarbe();
	my $fuellartersatz      = getfuellart();
	my $fuellfarbeersatz    = getfuellfarbe();
	my $linienstaerkeersatz = getlinienstaerke();
	my $linienartersatz     = getlinienart();

	minmax( -$n, -1, $n, 1 );

	if ( $aufsummiert eq "ja" ) { setymaxstat(1); }
	else {
		for ( $i = 0 ; $i <= $n ; $i++ ) {
			$bino = binom( $n, $i );
			$max = $bino * $p**($i) * $q**( $n - $i );
			setymaxstat($max);
		}
	}

	if ( $markierung == 0 ) {
		if ( $n > 9 ) {
			$markierung = schoenetabelle( $n * $breite * 100 ) / 100;
		}
		else { $markierung = 1; }
	}
	else { $markierung = $markierung; }
	setymaxstat( aufrunden( getachsengraph("ymax") * 10, 1 ) / 10 );
	$yschritte = schoenetabelle( getachsengraph("ymax") * 10 ) / 10;
	setymaxstat( $yschritte * 10 );

	if ( getgitter() == 1 ) {
		kariert(
			$layer,                     "lightgray",
			0.8,                        "solid",
			0,                          0,
			$n * $breite + $breite + 1, getachsengraph("ymax"),
			$n * $breite + $breite + 1, 0,
			0,                          $yschritte,
			0,                          0
		);
		setgitter(2);
	}
	if ( getachsen() == 1 ) {
		achsen(
			$layer + 1,                 getfarbe(),
			getlinienstaerke(),         $linienart,
			getpfeilart(),              0,
			$n * $breite + $breite + 1, 0,
			getachsengraph("ymax"),     $n * $breite + $markierung,
			"normal",                   getmarkierung("x"),
			$yschritte,                 "normal",
			getmarkierung("y")
		);

	}

	if ( $n > 1 ) {
		pstricks( $layer, "{" );
		einstellungen( $layer, $farbe, $fuellart, $fuellfarbe, $linienart,
			$linienstaerke, $parameter );

		for ( $i = 0 ; $i <= $n ; $i++ ) {
			$bern = binom( $n, $i );
			$bern = $bern * $p**($i) * $q**( $n - $i );
			if ( $aufsummiert ne "nein" ) {
				$bern2 = $bern2 + nachkommastellen( $bern, 4 );
			}
			else { $bern2 = nachkommastellen( $bern, 4 ); }
			if ( $p != 0 ) {
				if ( ( $i >= $anfang ) && ( $i <= $ende ) ) {
					if ( $strich == 1 ) {
						linie(
							$layer,
							$i * $breite + $breite / 2,
							0,
							"",
							$i * $breite + $breite / 2,
							$bern2,
							"",
							$linienart,
							$linienstaerke,
							$farbe,
							$parameter,
							"|-|"
						);
					}
					else {
						saeule(
							$layer,     $i * $breite,
							0,          $breite,
							$bern2,     $farbe,
							$fuellart,  $fuellfarbe,
							$linienart, $linienstaerke,
							"",         0,
							0,          "s",
							$parameter
						);
					}
				}
			}
			if ( $markierung == $n ) { }
			else {
				if ( ( $i % $markierung ) == 0 ) {
					if ( getachsen() == 1 ) {
						xmarkierungohne( $layer, $i * $breite + $breite / 2,
							$i, "black" );
					}
				}
			}
		}
		pstricks( $layer, "}" );
	}
	else {
		for ( $i = 0 ; $i <= $n ; $i++ ) {
			$bern = binom( $n, $i );
			$bern = $bern * $p**($i) * $q**( $n - $i );
			if ( $aufsummiert ne "nein" ) {
				$bern2 = $bern2 + sprintf( "%0.4f", $bern );
			}
			else { $bern2 = nachkommastellen( $bern, 4 ); }
			if ( $p != 0 ) {
				if ( ( $i >= $anfang ) && ( $i <= $ende ) ) {
					if ( $strich == 1 ) {
						linie(
							$layer,
							$i * $breite + $breite / 2,
							0,
							"",
							$i * $breite + $breite / 2,
							$bern2,
							"",
							$linienart,
							$linienstaerke,
							$farbe,
							$parameter,
							"|-|"
						);
					}
					else {
						saeule(
							$layer,     $i * $breite,
							0,          $breite,
							$bern2,     $farbe,
							$fuellart,  $fuellfarbe,
							$linienart, $linienstaerke,
							"",         0,
							0,          "s",
							$parameter
						);
					}
				}
			}
			if ( $markierung == $n ) { }
			else {
				if ( ( $i % $markierung ) == 0 ) {
					if ( getachsen() == 1 ) {
						xmarkierung( $layer, $i * $breite + $breite / 2,
							$i, "black" );
					}
				}
			}
		}
	}

	xmarkierungmulti( $layer, 0, $n, $breite, getfarbe() );

	setachsen(2);
	setfarbe($farbeersatz);
	setfuellart($fuellartersatz);
	setfuellfarbe($fuellfarbeersatz);
	setlinienstaerke($linienstaerkeersatz);
	setlinienart($linienartersatz);
}

1;

