]> mj.ucw.cz Git - anim.git/commitdiff
A quick-and-dirty demo of Fortune's algorithm.
authorMartin Mares <mj@ucw.cz>
Fri, 30 Nov 2007 14:30:59 +0000 (15:30 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 30 Nov 2007 14:30:59 +0000 (15:30 +0100)
x.pl [new file with mode: 0755]

diff --git a/x.pl b/x.pl
new file mode 100755 (executable)
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;