Benutzer:Stündle/Baustelle
Zur Navigation springen
Zur Suche springen
#!/usr/bin/perl # # Trägheitskräfte als Scheinkräfte # # Zentrifugalkraft und Corioliskraft im Zusammenspiel # # Maßstabsgetreue Vektoren (hoffentlich) # use strict; use warnings; use Image::Magick; use utf8; use File::Copy; use FileHandle; use File::Path; use Math::Trig; # use Math::Round qw/round/; sub pfeil($$$$$$); sub grundfläche($); sub coriolisbahn(); sub hintergrund($); sub kugel($$); sub kugel_bewegt($$); sub nummer($); sub omega(); binmode(STDOUT, ":utf8"); print "Los geht's!\n"; #Global #my $schrittzahl = 90; # nur gerade Werte zulässig my $schritte_pro_umdrehung = int(92); # my $umdrehungen_drehscheibe = -2; my $umdrehungen_drehscheibe = -6; # * 0.75 #Lokal my $svg_dir = "./svg"; my $png_dir = "./png"; my $svg_rot_filename = $svg_dir . "/coriolis-%03d.svg"; my $png_rot_filename = $png_dir . "/coriolis-%03d.png"; my $gif_filename = "./coriolis-animation.gif"; my $error = ""; my $image = Image::Magick->new; my $animation = Image::Magick->new; my $hello = "Hällö Perl"; my $svg_fh = undef; my $zeit = time(); $image->Set(size=>'600x600'); mkdir($svg_dir); mkdir($png_dir); # Programmstruktur: Defs erzeugen my $header = '<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" baseProfile="full" width="600px" height="600px" viewBox="0 0 600 600">'."\n"; my $footer = '</svg>'; my $data = $header; my $drehrate = 1./9.; # 1/4 Umdrehung pro Sekunde? # will x Umdrehungen sehen # habe x Drehrate # habe x schritte_pro_umdrehung my $schrittzahl = abs($schritte_pro_umdrehung * $umdrehungen_drehscheibe); my $delay = 100./($schritte_pro_umdrehung * $drehrate); # in 10ms my $geschwindigkeit = 2 * pi * $drehrate * 100.; # pixel pro sekunde # r = 100px 2pi => Winkelgeschwindigkeit # my $geschwindigkeit = 40./3.; # pixel pro sekunde my $schrittweiteKugel = $geschwindigkeit * $delay/100.; for(my $s = int(0); $s < 0.75*$schrittzahl; $s++) { print "Schritt: ".$s."\n"; $header = '<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" baseProfile="full" width="600px" height="600px" viewBox="0 0 600 600">'."\n"; $footer = '</svg>'; # rotierendes Bezugsystem $data = $header; $image = Image::Magick->new; #$image->Set(size=>'600x600'); $data .= hintergrund((2 * pi * $umdrehungen_drehscheibe * $s) / $schrittzahl); $data .= grundfläche(0); #// 2 * pi * $bogen * $s / ($schrittzahl-1)); $data .= omega(); # schritte_pro_umdrehung if (($s%(1.5*$schritte_pro_umdrehung)) > 1 * $schritte_pro_umdrehung-2) { # zurück bewegen # hier: schritte_pro_umdrehung + 1 0..1 # $s 2*schritte_pro_umdrehung-1.....3*schritte_pro_umdrehung-1 $data .= nummer("4"); $data .= kugel_bewegt(1.-(($s%(1.5*$schritte_pro_umdrehung))-(1 * $schritte_pro_umdrehung-1))/($schritte_pro_umdrehung/2), -1); print "Zurück: " . ((($s%(1.5*$schritte_pro_umdrehung))-(1 * $schritte_pro_umdrehung-1))/($schritte_pro_umdrehung/2)) . " // " . $s . "\n"; } elsif (($s%(1.5*$schritte_pro_umdrehung)) > 0.75 * $schritte_pro_umdrehung) { # Kugle stoppt $data .= nummer("3"); $data .= kugel_bewegt(1, 0); print "Ruhe: " . 1 . " // " . $s . "\n"; } elsif (($s%(1.5*$schritte_pro_umdrehung)) > 0.25 * $schritte_pro_umdrehung - 1) { # vor bewegen # hier: schritte_pro_umdrehung + 1 0..1 # $s schritte_pro_umdrehung-2.....2*schritte_pro_umdrehung-2 $data .= nummer("2"); $data .= kugel_bewegt((($s%(1.5*$schritte_pro_umdrehung))-(0.25*$schritte_pro_umdrehung))/($schritte_pro_umdrehung/2), +1); print "Vor: " . ((($s%(1.5*$schritte_pro_umdrehung))-(0.25*$schritte_pro_umdrehung))/($schritte_pro_umdrehung/2)) . " // " . $s . "\n"; } else { # in Ruhe $data .= nummer("1"); $data .= kugel_bewegt(0, 0); print "Ruhe: " . 0 . " // " . $s . "\n"; } $data .= $footer; open($svg_fh, "> " . sprintf($svg_rot_filename, $s)); binmode( $svg_fh, ":utf8" ); print $svg_fh $data; close($svg_fh); $image = Image::Magick->new(); #$error = $image->Read(sprintf($svg_fix_filename, $s)); #warn "$error" if "$error"; $error = $image->Read(sprintf($svg_rot_filename, $s)); warn "$error" if "$error"; #$image->Resize(geometry=>"500x500"); #, width=>integer, height=>integer, $image->Write(sprintf($png_rot_filename, $s)); #$image->Resize(geometry=>"260x260"); #, width=>integer, height=>integer, push(@$animation, $image); } print "Animation erstellen: ".$gif_filename."\n"; print "Delay: " . $delay . "x10ms\n"; $animation->[0]->Coalesce(); $animation->Set(delay => $delay, loop => 0); # * 10ms $animation->Write( $gif_filename ); $zeit = time()-$zeit; print "Zeit: " . $zeit . " s\n"; print "\nFertig!\n"; sub grundfläche($) { #my $data = $_{'data'}; my $winkel = sprintf("%.2f", (180. * $_[0] / pi)); # in grad umrechnen my $body = '<g id="grundflaeche" transform="rotate('.$winkel.', 300, 300)">'."\n"; $body .= '<path d="M 300,300 L 300,50 A 250,250 0 0 0 50,300" fill="#ffcbcbff" stroke="none"/>'."\n"; $body .= '<path d="M 300,300 L 50,300 A 250,250 0 0 0 300,550" fill="#cbffcbff" stroke="none"/>'."\n"; $body .= '<path d="M 300,300 L 300,550 A 250,250 0 0 0 550,300" fill="#ffcbcbff" stroke="none"/>'."\n"; $body .= '<path d="M 300,300 L 550,300 A 250,250 0 0 0 300,50" fill="#cbffcbff" stroke="none"/>'."\n"; $body .= '<circle cx="300" cy="300" r="250" fill="none" stroke="#ff9b9bff" stroke-width="5px" />'."\n"; # $body .= coriolisbahn(); $body .= "</g>\n"; #$data .= $body; return $body; } sub hintergrund($) { my $winkel = sprintf("%.2f", (-1 * 180. * $_[0] / pi)); # in grad umrechnen my $data = '<g id="hintergrund" transform="rotate('.$winkel.', 300, 300)">'."\n"; $data .= '<circle cx="300" cy="300" r="300" fill="white" stroke="none" />'."\n"; #// -300 .. + 900 // 1200 div 20 => 60 for(my $x = -300; $x <= 900; $x += 40) { # horizontale Linien $data .= '<line x1="'.$x.'" y1="-300" x2="'.$x.'" y2="900" stroke-width="1px" stroke="lightgray" />'."\n"; } for(my $y = -300; $y <= 900; $y += 40) { # horizontale Linien $data .= '<line x1="-300" y1="'.$y.'" x2="900" y2="'.$y.'" stroke-width="1px" stroke="lightgray" />'."\n"; } $data .= '<line x1="-300" y1="300" x2="900" y2="300" stroke-width="3px" stroke="green" />'."\n"; $data .= '<line x1="300" y1="-300" x2="300" y2="900" stroke-width="3px" stroke="green" />'."\n"; $data .= "</g>\n"; return $data; } sub kugel($$) { my $pos = $_[0]; my $winkel = $_[1]; # sprintf("%.2f", (180. * $_[1] / pi)); # in grad umrechnen my $data = '<g id="kugel">'."\n"; my $x = 300 + 250 * $pos * sin($winkel*1); # 1/-1 Drehrichtung my $y = 300 + 250 * $pos * cos($winkel); $data .= '<circle cx="'.$x.'" cy="'.$y.'" r="20" fill="red" stroke="darkred" stroke-width="3px"/>'."\n"; $data .= "</g>\n"; return $data } sub kugel_bewegt($$) { my $position = $_[0] - 0.5; # -1..+1 my $direction = $_[1]; my $data = '<g id="kugel">'."\n"; my $x = 300 - 157.1 * 2 * $position; # 0.5*3*100*2pi/6 my $y = 300-100; my $winkel = 0; my $radius = sqrt((300-$y) * (300-$y) + ($x-300) * ($x-300)); # a^2 + b^2 = if($x > 300) { $winkel = atan((300-$y)/($x-300)); } elsif( $x < 300) { $winkel = atan((300-$y)/($x-300)); $winkel += pi; } else { $winkel = pi/2; } #$data .= '<circle cx="300" cy="300" r="185" fill="none" stroke="darkgray" stroke-width="3px"/>'."\n"; #$body .= '<path d="M 300,300 L 550,300 A 250,250 0 0 0 300,50" fill="none" stroke="3px"/>'."\n"; #TODO # Bahn festlegen # Coriolis und Zentrifugalkraft abstimmen # Alle Vektoren einbringen # Bahn $data .= '<line x1="126.8" y1="200" x2="473.2" y2="200" stroke-width="3px" stroke="orange" />'."\n"; #$data .= '<path d="M 300,300 A 185,185 0 0 0 300,115" fill="none" stroke="darkgray" stroke="3px"/>'."\n"; $data .= '<circle cx="'.$x.'" cy="'.$y.'" r="20" fill="red" stroke="darkred" stroke-width="3px"/>'."\n"; $data .= pfeil($x, $y, 175./100 * $radius/2. , $winkel + pi/2, "F_Z", "darkslategrey"); if ($direction != 0) { $data .= pfeil($x, $y, 85, -1 * pi/2 * $direction, "v'_ ", "darkslateblue"); $data .= pfeil($x, $y, 175. , pi/2 + pi/2 * $direction , "F_C", "darkslategrey"); } $data .= "</g>\n"; return $data } sub pfeil($$$$$$) { # Position, Betrag, Richtung my $x1 = $_[0]; my $y1 = $_[1]; my $betrag = $_[2]; my $winkel = $_[3]; my @text = split(/_/, $_[4]); my $farbe = $_[5]; # 5() my $data = ""; # '<g id="kugel">'."\n"; my $x2 = $x1 + ($betrag-20) * sin($winkel); my $y2 = $y1 + ($betrag-20) * cos($winkel); my $p1x = $x1 + ($betrag) * sin($winkel); # $x2; # x1 + ($betrag) * sin($winkel); my $p1y = $y1 + ($betrag) * cos($winkel); # $y2; my $p2x = $p1x - 25 * sin($winkel) - 8 * cos($winkel) ; # * sin($winkel+pi); my $p2y = $p1y + 8 * sin($winkel) - 25 * cos($winkel); my $p3x = $p1x - 25 * sin($winkel) + 8 * cos($winkel); # * sin($winkel+pi); my $p3y = $p1y - 8 * sin($winkel) - 25 * cos($winkel); my $tx = ($x1+$x2)/2 + 40 * cos($winkel); my $ty = ($y1+$y2)/2 - 40 * sin($winkel); my $t1x = $tx - 15; my $t1y = $ty; my $t2x = $t1x + 15; my $t2y = $t1y + 10; $data .= '<line x1="'.$x1.'" y1="'.$y1.'" x2="'.$x2.'" y2="'.$y2.'" stroke-width="2px" stroke="'.$farbe.'" />'."\n"; $data .= '<polyline points="'.$p1x.','.$p1y.' '.$p2x.','.$p2y.' '.$p3x.','.$p3y.'" fill="'.$farbe.'" stroke="none" />'."\n"; $data .= '<text x="'.$t1x.'" y="'.$t1y.'" font-size="40" font-style="italic" fill="'.$farbe.'" >'.$text[0].'</text>'."\n"; $data .= '<text x="'.$t2x.'" y="'.$t2y.'" font-size="25" font-style="normal" fill="'.$farbe.'" >'.$text[1].'</text>'."\n"; return $data; } sub nummer($) { my $data = '<g id="nummer">'."\n"; my $farbe = "black"; my $text = $_[0]; my $x = 35; my $y = 35; my $tx = 20; my $ty = 53; $data .= '<circle cx="'.$x.'" cy="'.$y.'" r="30" fill="lightgray" stroke="black" stroke-width="3px"/>'."\n"; $data .= '<text x="'.$tx.'" y="'.$ty.'" font-size="60" font-style="normal" fill="'.$farbe.'" >'.$text.'</text>'."\n"; $data .= "</g>\n"; return $data } sub omega() { my $winkel=-45; my $data = '<g id="omega">'."\n"; my $x = 315; my $y = 330; my $p1x = $x; my $p1y = $y; my $p2x = $p1x -25; # * sin($winkel+pi); my $p2y = $p1y +8; my $p3x = $p1x -25; # * sin($winkel+pi); my $p3y = $p1y - 8; $data .= '<path d=" M 300,330 A 30,30 0 1 1 330,300" stroke="#ff6b6bff" fill="none" stroke-width="3px" transform="rotate('.$winkel.', 300, 300)"/>'."\n"; $data .= '<polyline points="'.$p1x.','.$p1y.' '.$p2x.','.$p2y.' '.$p3x.','.$p3y.'" fill="#ff6b6bff" stroke="none" transform="rotate('.$winkel.', 300, 300)"/>'."\n"; $data .= '<text x="330" y="305" font-size="40" font-style="italic" fill="#ff6b6bff" >ω</text>'."\n"; $data .= "</g>\n"; #$data .= $body; return $data; } # EOF