All pastes #582058 Raw Edit

omg arrow. lol

public text v1 · immutable
·published 2007-06-21 20:40 UTC
rendered paste body
#!/usr/bin/env perl

use strict;
use warnings;

use GD;
use Math::Trig;
my $pi = 3.14159265;

my $img = new GD::Image(200, 200);
my $white = $img->colorAllocate(255, 255, 255);
my $black = $img->colorAllocate(0, 0, 0);
$img->transparent($white);

# Draw 24 arrows uniformly in a circle.
my $A = [ 100, 100 ];
print $img->gifanimbegin();
for(my $i = 0; $i < 24; $i++){
  my $frame = new GD::Image($img->getBounds());

  # draw our main arrow line
  my $B = polar_to_cartesian(75, $i * $pi/12);
  $B->[0] += $A->[0];
  $B->[1] += $A->[1];
  draw_line($frame, $A, $B);

  # draw the arrow
  my @arrow = arrow_points($A, $B, 50);
  draw_line($frame, $arrow[0], $arrow[1]);
  draw_line($frame, $arrow[0], $arrow[2]);

  print $frame->gifanimadd();
}
print $img->gifanimend();

# arrow_points(point A, point B, segment length)
#  Returns 3 points to make the arrow head.
#  First point is the common point. Last two are the segment ends.
sub arrow_points {
  my ($ar, $br, $len) = @_;
  # Calculate line segment AB's angle
  # The domain of arccosine is from 0 to pi. If our arrow passes beyond pi,
  # (B_y component is negative relative to A_y), adjust $alpha.
  my $alpha = acos (($br->[0] - $ar->[0]) /
                    sqrt(($br->[0] - $ar->[0])**2 + ($br->[1] - $ar->[1])**2));
  if($br->[1] - $ar->[1] < 0){
    $alpha = 2 * $pi - $alpha;
  }

  # Add arrow's angle to segment AB's and convert to
  # cartesian cordinates
  my $X = [ $len * cos((3 * $pi)/4 + $alpha) + $br->[0],
            $len * sin((3 * $pi)/4 + $alpha) + $br->[1] ];
  my $Y = [ $len * cos((5 * $pi)/4 + $alpha) + $br->[0],
            $len * sin((5 * $pi)/4 + $alpha) + $br->[1] ];

  return ($br, $X, $Y);
}

# polar_to_cartesian(radius, theta):
#  Converts a polar cordinate to a cartesian one.
#  theta is in radians.
sub polar_to_cartesian {
  my ($r, $theta) = @_;
  return [ $r * cos($theta), $r * sin($theta) ];
}

# draw_line(image handle, point A, point B):
#  Draw a line in Q1 space.
sub draw_line {
  my ($img, $ar, $br) = @_;
  # convert from postive-y Q4 space to Q1
  my ($width, $height) = $img->getBounds();
  $img->line($ar->[0], $height - $ar->[1],
             $br->[0], $height - $br->[1],
             $black);
}