Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: Goo Canvas Scaling and X-Y coordinates

by zentara (Archbishop)
on Jul 28, 2008 at 13:41 UTC ( [id://700524]=note: print w/replies, xml ) Need Help??


in reply to Goo Canvas Scaling and X-Y coordinates

Scaling and rotations can be tricky because they are predefined to the group's origin (usually root group at 0,0, but it may be the canvas center point, depends on the canvas type and setup). The first time you try to rotate something, people ar usually surprised to see the item fly off the screen because the $cx and $cy is 0,0 (unless you moved the root group). I havn't tried it yet, but it looks like you want to use
$item->set_simple_transform ($x, $y, $scale, $rotation)
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.

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.

sub event_handler{ my ( $widget, $event ) = @_; print $widget ,' ',$event->type,"\n"; my ($x,$y) = ($event->x,$event->y); print "$x $y\n"; }
Once again, look at the demo and see how it does the Events tab.

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; } ####################################################################

I'm not really a human, but I play one on earth Remember How Lucky You Are

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://700524]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-23 07:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found