]> mj.ucw.cz Git - anim.git/commitdiff
Goldbergovske variace.
authorMartin Mares <mj@ucw.cz>
Sun, 28 Oct 2007 21:02:56 +0000 (22:02 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 28 Oct 2007 21:02:56 +0000 (22:02 +0100)
AA.pm
AA/Gfx.pm
AA/Graph.pm
AA/Net.pm
a.pl

diff --git a/AA.pm b/AA.pm
index b2dc926bdc69b7cd05cca4531321c0b201314e76..c4fcc59ad7874222cb4aae72eb6cf47724ed6c5e 100644 (file)
--- a/AA.pm
+++ b/AA.pm
@@ -128,6 +128,8 @@ sub Bind($$$) {
 sub Calc($$) {
        my ($o, $a) = @_;
        die if $record_deps;
+       return unless defined $o->{"f:$a"};
+
        $record_deps = $o->{"d:$a"};
        $record_dep_obj = $o;
        $record_dep_attr = $a;
@@ -171,4 +173,17 @@ sub Notify($$) {
        }
 }
 
+sub MultiSet($@) {
+       my $o = shift @_;
+       my ($a, $v);
+       while ($a = shift @_) {
+               $v = shift @_;
+               if (ref $v eq "CODE") {
+                       $o->Bind($a, $v);
+               } else {
+                       $o->Set($a, $v);
+               }
+       }
+}
+
 1;
index 6a1eadc58b5dd62c2901bdf0904ff70fb7bacf59..f55ed7ee97968a48ac1eea8ba17f5e207503cdbd 100644 (file)
--- a/AA/Gfx.pm
+++ b/AA/Gfx.pm
@@ -19,4 +19,31 @@ sub Draw($$) {
        $cairo->fill;
 }
 
+package AA::Label;
+
+@ISA = ('AA');
+
+sub new($$) {
+       my ($class, $id) = @_;
+       my $t = AA::new($class, $id);
+       $t->DefSet('d', 10);
+       $t->DefSet('x', 100);
+       $t->DefSet('y', 100);
+       $t->DefSet('color', [1, 1, 1]);
+       $t->DefSet('size', 12);
+       $t->DefSet('text', '');
+       return $t;
+}
+
+sub Draw($$) {
+       my ($t, $cairo) = @_;
+       my $text = $t->Get('text');
+       $cairo->set_source_rgb(@{$t->Get('color')});
+       $cairo->set_font_size($t->Get('size'));
+       my $xt = $cairo->text_extents($text);
+       $cairo->move_to($t->Get("x") - $xt->{'width'}/2 - $xt->{'x_bearing'},
+                       $t->Get("y") - $xt->{'height'}/2 - $xt->{'y_bearing'});
+       $cairo->show_text($text);
+}
+
 1;
index dbd17f50b924bc81e3d8a0d9492577d414b2011a..afd1d6ce3a428107f684fd622189cc442d4b9e35 100644 (file)
@@ -66,9 +66,19 @@ sub new($$$$) {
        $e->DefSet('color', [1, 1, 1]);
        $e->DefSet('width', 3);
        $e->DefSet('arrow', 0);
-       $e->DefSet('arrow-dist', 20);
-       $e->DefSet('arrow-span', 6);
+       $e->DefSet('arrow-size', 20);   # distance between arrow tip and back
+       $e->DefSet('arrow-span', 0.5);  # fraction of arrow-size
        $e->DefSet('overshoot', 3);
+       $e->DefBind('dir', sub {
+               my $dx = $w->Get('x') - $v->Get('x');
+               my $dy = $w->Get('y') - $v->Get('y');
+               my $d = sqrt($dx*$dx + $dy*$dy);
+               if ($d) {
+                       return [$dx/$d, $dy/$d];
+               } else {
+                       return [0, 0];
+               }
+       });
        $e->DefBind('ends', sub {
                my $over = $e->Get('overshoot');
                my $x1 = $v->Get('x');
@@ -77,53 +87,38 @@ sub new($$$$) {
                my $x2 = $w->Get('x');
                my $y2 = $w->Get('y');
                my $r2 = $w->Get('r') - $over;
-               my $dx = $x2 - $x1;
-               my $dy = $y2 - $y1;
-               my $d = sqrt($dx*$dx + $dy*$dy);
-               $x1 += $dx * $r1/$d;
-               $y1 += $dy * $r1/$d;
-               $x2 -= $dx * $r2/$d;
-               $y2 -= $dy * $r2/$d;
-               return [ $x1, $y1, $x2, $y2 ];
-       });
-       $e->DefBind('apos', sub {
-               my $type = $e->Get('arrow') or return undef;
-               my $span = $e->Get('arrow-span');
-               my $dist = $e->Get('arrow-dist');
-               my ($x1, $y1, $x2, $y2) = @{$e->Get('ends')};
-               my $dx = $x2 - $x1;
-               my $dy = $y2 - $y1;
-               my $d = sqrt($dx*$dx + $dy*$dy);
-               my $ax = $x2 - $dx * $dist/$d;
-               my $ay = $y2 - $dy * $dist/$d;
-               my $adx = -$dy;
-               my $ady = $dx;
-               ($adx, $ady) = ($adx * $span/$d, $ady * $span/$d);
-               return [ $ax+$adx, $ay+$ady,
-                        $ax-$adx, $ay-$ady ];
+               my ($dx,$dy) = @{$e->Get('dir')};
+               return [ $x1+$r1*$dx, $y1+$r1*$dy, $x2-$r2*$dx, $y2-$r2*$dy ];
        });
        $e->DefSet('d', 10);
        return $e;
 }
 
 sub Draw($$) {
-       my ($v, $cairo) = @_;
-
-       my ($x1, $y1, $x2, $y2) = @{$v->Get('ends')};
-       $cairo->set_source_rgb(@{$v->Get('color')});
-
-       $cairo->move_to($x1, $y1);
-       $cairo->line_to($x2, $y2);
-       $cairo->set_line_width($v->Get('width'));
-       $cairo->stroke;
-
-       if ($v->Get('arrow')) {
-               my ($ax1, $ay1, $ax2, $ay2) = @{$v->Get('apos')};
+       my ($e, $cairo) = @_;
+       my ($x1, $y1, $x2, $y2) = @{$e->Get('ends')};
+       $cairo->set_source_rgb(@{$e->Get('color')});
+       $cairo->set_line_width($e->Get('width'));
+       if (my $arrow = $e->Get('arrow')) {
+               my $size = $e->Get('arrow-size');
+               my $span = $size * $e->Get('arrow-span');
+               my ($dx,$dy) = @{$e->Get('dir')};
+               # line
+               $cairo->move_to($x1, $y1);
+               $cairo->line_to($x2 - $dx*$size*0.9, $y2 - $dy*$size*0.9);
+               $cairo->stroke;
+               # arrow
+               my ($ax,$ay) = (-$dy,$dx);
+               my ($bx,$by) = ($x2 - $dx*$size, $y2 - $dy*$size);
                $cairo->move_to($x2, $y2);
-               $cairo->line_to($ax1, $ay1);
-               $cairo->line_to($ax2, $ay2);
+               $cairo->line_to($bx + $ax*$span, $by + $ay*$span);
+               $cairo->line_to($bx - $ax*$span, $by - $ay*$span);
                $cairo->close_path;
                $cairo->fill;
+       } else {
+               $cairo->move_to($x1, $y1);
+               $cairo->line_to($x2, $y2);
+               $cairo->stroke;
        }
 }
 
index 9c06d42f74e6a1419edca2ab379302876ae01a16..d0d074a7d534c38bd2f827621166e01c9599f4e9 100644 (file)
--- a/AA/Net.pm
+++ b/AA/Net.pm
@@ -8,8 +8,48 @@ sub new($$$$) {
        $v->Set('x', 100);
        $v->DefSet('y0', 100);
        $v->DefSet('h', 0);
-       $v->Bind('y', sub { $v->Get("y0") + 100*$v->Get("h") });
+       $v->DefSet('xs', '');
+       $v->Bind('y', sub { $v->Get("y0") - 50*$v->Get("h") });
+       $v->{XS} = AA::Label->new("$id-label");
+       $v->{XS}->MultiSet(
+               'x' => sub { $v->Get('x') },
+               'y' => sub { $v->Get('y') + 80 },
+               'size' => 50,
+               'text' => sub { $v->Get('xs') },
+               'color' => sub { $v->Get('xs') ? [1,0,0] : [1,1,1] },
+       );
        return $v;
 }
 
+package AA::NetE;
+
+our @ISA = ('AA');
+
+sub new($$$$) {
+       my ($class, $id, $v, $w) = @_;
+       my $e = AA::new($class, $id);
+       $e->{E} = AA::Edge->new("$id-e", $v, $w);
+       $e->{E}->Set('arrow', 1);
+       $e->{E}->Set('color', [1,0,0]);
+       $e->DefSet('c', 1);
+       $e->DefSet('f', 0);
+       $e->DefSet('d', 9);
+       $e->DefDep('ends', $e->{E}, 'ends');
+       $e->{E}->Bind('width', sub { $e->Get('f') * 5 + 1 });
+#      $e->{E}->Bind('overshoot', sub { $e->Get('f') * 3 + 3});
+       $e->{E}->Bind('arrow-size', sub { $e->Get('f') * 5 + 20});
+       return $e;
+}
+
+sub Draw($$) {
+       my ($e, $cairo) = @_;
+       my ($x1, $y1, $x2, $y2) = @{$e->Get('ends')};
+       $cairo->new_path;
+       $cairo->set_source_rgb(0.3, 1, 0);
+       $cairo->set_line_width($e->Get('c') * 5 + 1);
+       $cairo->move_to($x1, $y1);
+       $cairo->line_to($x2, $y2);
+       $cairo->stroke;
+}
+
 1;
diff --git a/a.pl b/a.pl
index d8df74d3f041f8f1811de63848eea0d5a29006f9..48a9c04626ae9892d626f8445dd520d0fdbb65df 100755 (executable)
--- a/a.pl
+++ b/a.pl
@@ -17,30 +17,99 @@ my $ui = AA::UI->new('');
 
 my $back = AA::Background->new('bg');
 
-my $v = AA::NetV->new('v');
-$v->Set('x', 100);
-$v->Set('y0', 100);
-$v->Set('label', '1');
+my @v;
+for (my $i=0; $i<5; $i++) {
+       my $v = AA::NetV->new("v$i");
+       $v->MultiSet(
+               'x' => 100 + 180*$i,
+               'y0' => 600,
+               'label' => ($i == 0) ? "Z" : ($i == 4) ? "S" : $i,
+               'h' => ($i == 0) ? 5 : 0,
+       );
+       push @v, $v;
+}
 
-my $w = AA::NetV->new('w');
-$w->Bind('x', AA::Anim->ticker(200, 600, 200));
-$w->Set('y0', 100);
-$w->Set('label', '2');
+my @e;
+for (my $i=0; $i<4; $i++) {
+       my $e = AA::NetE->new("e$i", $v[$i], $v[$i+1]);
+       $e->Set('c', 5);
+       $e->Set('f', 0);
+       push @e, $e;
+}
 
-my $e = AA::Edge->new('e', $v, $w);
-$e->Set('arrow', 1);
+for (my $i=1; $i<@v; $i++) {
+       my $ii = $i;    # need to keep a copy in the current closure
+       $v[$i]->Bind('xs', sub { $e[$ii-1]->Get('f') - (($ii == @v-1) ? 0 : $e[$ii]->Get('f')) });
+}
+$v[4]->{XS}->Set('color', [0,1,0]);
+
+sub flow($$) {
+       my ($i,$df) = @_;
+       $e[$i]->Set('f', $e[$i]->Get('f') + $df);
+}
+
+sub up($) {
+       my ($i) = @_;
+       $v[$i]->Set('h', $v[$i]->Get('h') + 1);
+}
 
 my $scenario = [
-       sub {
-               $v->Set("h", 1);
-               $w->Set("h", 1);
-       },
-       sub {
-               $v->Set("h", 1);
-               $w->Set("h", 2);
-       }
+       sub { flow(0, 5); },
+       sub { up(1); },
+       sub { flow(1, 5); },
+       sub { up(2); },
+       sub { flow(2, 5); },
+       sub { up(3); },
+       sub { flow(3, 5); },
 ];
 
+if (1) {
+       for (my $i=0; $i<@v-1; $i++) {
+               $e[$i]->Set('c', 5-$i);
+       }
+       $scenario = [
+               sub { flow(0, 5); },
+               sub { up(1); },
+               sub { flow(1, 4); },
+               sub { up(2); },
+               sub { flow(2, 3); },
+               sub { up(3); },
+               sub { flow(3, 2); },
+               sub { up(3); },
+               sub { flow(2, -1); },
+               sub { up(2); },
+               sub { flow(1, -1); },
+               sub { up(1); },
+               sub { up(1); },
+               sub { flow(1, 1); },
+               sub { up(1); },
+               sub { up(1); },
+               sub { up(1); },
+               sub { flow(0, -1); },
+               sub { up(2); },
+               sub { flow(2, 1); },
+               sub { up(3); },
+               sub { up(3); },
+               sub { flow(2, -1); },
+               sub { up(2); },
+               sub { up(2); },
+               sub { flow(2, 1); },
+               sub { up(3); },
+               sub { up(3); },
+               sub { flow(2, -1); },
+               sub { up(2); },
+               sub { up(2); },
+               sub { flow(2, 1); },
+               sub { flow(1, -1); },
+               sub { flow(0, -1); },
+               sub { up(3); },
+               sub { up(3); },
+               sub { flow(2, -1); },
+               sub { flow(1, -1); },
+               sub { flow(0, -1); },
+       ];
+}
+
 $ui->RunScenario($scenario, 1);
 
 exit 0;