From: Martin Mares Date: Fri, 30 Nov 2007 14:30:59 +0000 (+0100) Subject: A quick-and-dirty demo of Fortune's algorithm. X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=73b82638794ec6fd9102c97b9b9a9d93ed334555;p=anim.git A quick-and-dirty demo of Fortune's algorithm. --- diff --git a/x.pl b/x.pl new file mode 100755 index 0000000..0e94b1b --- /dev/null +++ b/x.pl @@ -0,0 +1,142 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Gtk2 -init; +use Cairo; + +my $pi = 3.1415926536; + +sub para($$$$$) { + # draw a parabola y=a(x-x0)^2 + y0 + my ($cairo,$a,$x0,$y0,$ww) = @_; + my $been = 0; + for (my $x=0; $x<$ww; $x++) { + my $y = $a*($x-$x0)*($x-$x0) + $y0; + next if ($y < -10000 || $y > 10000); + if ($been++) { + $cairo->line_to($x, $y); + } else { + $cairo->move_to($x, $y); + } + } + $cairo->stroke; +} + +sub solve_para($$$) { + my ($h0, $x0, $y0) = @_; + my $h = $y0 - $h0; + return (1/(2*$h), $x0, $h0 + $h/2); +} + +sub solve_circ($$$$$$) { + my ($x0, $y0, $x1, $y1, $x2, $y2) = @_; + my $axc = ($x0 + $x1) / 2; + my $ayc = ($y0 + $y1) / 2; + my $adx = $y1 - $y0; + my $ady = $x0 - $x1; + my $bxc = ($x1 + $x2) / 2; + my $byc = ($y1 + $y2) / 2; + my $bdx = $y2 - $y1; + my $bdy = $x1 - $x2; + my $alpha = (($bxc-$axc)*(-$bdy) - ($byc-$ayc)*(-$bdx)) / + ($adx*(-$bdy) - $ady*(-$bdx)); + my $x = $axc + $alpha*$adx; + my $y = $ayc + $alpha*$ady; + my $r = sqrt(($x-$x0)*($x-$x0) + ($y-$y0)*($y-$y0)); + return ($x, $y, $r); +} + +my $area = Gtk2::DrawingArea->new(); +my $cairo; +my $dh = 625; +sub draw() { + my $win = $area->window; + my $alloc = $area->allocation; + my $w = $alloc->width; + my $h = $alloc->height; + + $cairo = Gtk2::Gdk::Cairo::Context->create($win); + $cairo->rectangle(0, 0, $w, $h); + $cairo->set_source_rgb(0, 0, 0); + $cairo->fill; + + my @pts = ( [$w/3, $h-600], [$w/2, $h-700], [2*$w/3, $h-650] ); + my ($cx, $cy, $cr) = solve_circ($pts[0]->[0], $pts[0]->[1], $pts[1]->[0], $pts[1]->[1], $pts[2]->[0], $pts[2]->[1]); + + for (my $i=0; $i<$#pts; $i++) { + my $p = $pts[$i]; + my $q = $pts[$i+1]; + my $xc = ($p->[0] + $q->[0]) / 2; + my $yc = ($p->[1] + $q->[1]) / 2; + my $dx = ($q->[1] - $p->[1]); + my $dy = ($p->[0] - $q->[0]); + $cairo->set_source_rgb(0.5, 0, 0.5); + $cairo->move_to($xc - 10*$dx, $yc - 10*$dy); + $cairo->line_to($xc + 10*$dx, $yc + 10*$dy); + $cairo->stroke; + $cairo->set_source_rgb(0.5, 0.5, 0.5); + $cairo->move_to($p->[0], $p->[1]); + $cairo->line_to($q->[0], $q->[1]); + $cairo->stroke; + } + { + my $p = $pts[0]; + my $q = $pts[2]; + my $xc = ($p->[0] + $q->[0]) / 2; + my $yc = ($p->[1] + $q->[1]) / 2; + my $dx = ($q->[1] - $p->[1]); + my $dy = ($p->[0] - $q->[0]); + $cairo->set_source_rgb(0.5, 0, 0.5); + $cairo->move_to($xc - 10*$dx, $yc - 10*$dy); + $cairo->line_to($xc + 10*$dx, $yc + 10*$dy); + $cairo->stroke; + $cairo->set_source_rgb(0.5, 0.5, 0.5); + $cairo->move_to($p->[0], $p->[1]); + $cairo->line_to($q->[0], $q->[1]); + $cairo->stroke; + } + + $cairo->set_source_rgb(1, 0, 1); + $cairo->arc($cx, $cy, $cr, 0, 2*$pi); + $cairo->stroke; + + $cairo->set_source_rgb(1, 1, 1); + my $h0 = $h-$dh; + $cairo->move_to(0, $h0); + $cairo->line_to($w, $h0); + $cairo->stroke; + + foreach my $p (@pts) { + $cairo->arc($p->[0], $p->[1], 2, 0, 2*$pi); + $cairo->fill; + } + + $cairo->set_source_rgb(0, 1, 0); + foreach my $p (@pts) { + next if ($p->[1] > $h0); + my ($pa,$px,$py) = solve_para($h0, $p->[0], $p->[1]); + para($cairo, $pa, $px, $py, $w); + } +} + +my $timer; +$area->signal_connect("expose-event" => sub { + draw(); +}); + +my $window = Gtk2::Window->new ('toplevel'); +$window->signal_connect ("delete-event" => sub { Gtk2->main_quit }); +$window->set_title("Brum"); +$window->set_wmclass("anim", "Anim"); +$window->set_default_size(640, 480); +$window->add ($area); +$window->show_all; +$window->fullscreen; +$window->signal_connect("key-press-event" => sub { + $dh -= 10; + draw(); +}); + +Gtk2->main;