in reply to Goo Canvas Scaling and X-Y coordinates
where $x and $y will be the center point of the scale; presumably the weighted center of your item. Computing the weighted center can be tricky for odd shapes, so you may have to resort to making a special group for each item to be scaled, add the item to the group centered, move the group, and scale it.$item->set_simple_transform ($x, $y, $scale, $rotation)
It's one of those things you just need to play with to get right. Look at the 'animation' section of the Goo demo.
As far as the x,y coordinates of the mouse I think you need to setup an event handler on the canvas and the items.
Once again, look at the demo and see how it does the Events tab.sub event_handler{ my ( $widget, $event ) = @_; print $widget ,' ',$event->type,"\n"; my ($x,$y) = ($event->x,$event->y); print "$x $y\n"; }
Just to show you how difficult a centered rotation can be, here is an example on the Gnome2::Canvas, you will then appreciate Goo's set_simple_transform :-)
#!/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::Polygo +n', 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::Poly +gon', 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; } ####################################################################
|
|---|