$item->set_simple_transform ($x, $y, $scale, $rotation) #### sub event_handler{ my ( $widget, $event ) = @_; print $widget ,' ',$event->type,"\n"; my ($x,$y) = ($event->x,$event->y); print "$x $y\n"; } #### #!/usr/bin/perl use warnings; use strict; use Gnome2::Canvas; use Gtk2 '-init'; my $window = Gtk2::Window->new(); my $sw = Gtk2::ScrolledWindow->new(); $sw->set_shadow_type ('etched-out'); $sw->set_policy ('automatic', 'always'); $sw->set_placement('top-right'); $sw->set_size_request (500, 500); $sw->set_border_width(0); my $black = Gtk2::Gdk::Color->new (0x0000,0x0000,0x0000); my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF); my $canvas = Gnome2::Canvas->new_aa(); $canvas->set_size_request(500,500); $canvas->set_scroll_region(0,0,1000,1000); $canvas->modify_bg('normal',$white); $canvas->set_center_scroll_region (0); my $root = $canvas->root(); my @points = (50,50,80,20,90,100); my $poly = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Polygon', points => \@points, fill_color_rgba => 0x0000ff80, outline_color => 'black'); $poly->{'points'} = \@points; my $id = Glib::Timeout->add (100, sub { &rotate($poly,10); return 1; }); # $ztree->set_pixels_per_unit(2); $sw->add($canvas); $window->signal_connect('destroy'=>sub { Gtk2->main_quit(); }); $window->set_default_size(450,350); $window->add($sw); $window->show_all(); Gtk2->main(); ############################################################################ sub rotate { my ( $item, $degree ) = @_; my @points = @{$item->{'points'}}; $item->destroy; @points = &rotate_poly($item, $degree); $poly = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Polygon', points => \@points, fill_color_rgba => 0xff000080, outline_color => 'black'); $poly->{'points'} = \@points; } ####################################################################3 sub rotate_poly { my ($ind, $angle, $midx, $midy) = @_; # Get the old coordinates. my @coords = @{$ind->{'points'}}; # Get the center of the poly. We use this to translate the # above coords back to the origin, and then rotate about # the origin, then translate back. (old) ($midx, $midy) = _get_CM( @coords ) unless defined $midx; my @new; # Precalculate the sin/cos of the angle, since we'll call # them a few times. my $rad = 3.1416*$angle/180; my $sin = sin $rad; my $cos = cos $rad; # Calculate the new coordinates of the line. while (my ($x, $y) = splice @coords, 0, 2) { my $x1 = $x - $midx; my $y1 = $y - $midy; push @new => $midx + ($x1 * $cos - $y1 * $sin); push @new => $midy + ($x1 * $sin + $y1 * $cos); } # Redraw the poly. return @new; } ################################################################# # This sub finds the center of mass of a polygon. # I grabbed the algorithm somewhere from the web. # I grabbed it from Ala Qumsieh's RotCanvas :-) sub _get_CM { my ($x, $y, $area); my $i = 0; while ($i < $#_) { my $x0 = $_[$i]; my $y0 = $_[$i+1]; my ($x1, $y1); if ($i+2 > $#_) { $x1 = $_[0]; $y1 = $_[1]; } else { $x1 = $_[$i+2]; $y1 = $_[$i+3]; } $i += 2; my $a1 = 0.5*($x0 + $x1); my $a2 = ($x0**2 + $x0*$x1 + $x1**2)/6; my $a3 = ($x0*$y1 + $y0*$x1 + 2*($x1*$y1 + $x0*$y0))/6; my $b0 = $y1 - $y0; $area += $a1 * $b0; $x += $a2 * $b0; $y += $a3 * $b0; } return split ' ', sprintf "%.0f %0.f" => $x/$area, $y/$area; } ####################################################################