in reply to Tk Zooming Fractal Problems

Hi, another approach you might consider, instead of calculating the fractal center around the mouse click, is to calculate it's center, by taking the bbox of the fractal, and move the center point with tags.

For instance, tag all your lines with 'fractal', after you build the fractal, get a bbox of the tag fractal, take the midpoint values, and store it. Then on each new fractal build, just repeat, take the new bbox, then compute how much you need to move it, to center it on the mouse event point.

I'm not doing the computations here, but this shows the basics.

#!/usr/bin/perl use warnings; use strict; use Tk; my $c_size = 100; my $scale = 1; my $centerx; my $centery; my $mw = MainWindow -> new; my $canvas = $mw -> Canvas(-height=>$c_size, -width=>$c_size) -> pack; $canvas -> Tk::bind('all', '<ButtonPress-1>' => [\&transit,Ev('x'), Ev +('y') ]); &MakeMan(); MainLoop; sub transit{ my ($canv, $x, $y) = @_; print "(x,y) = ", $canv->canvasx($x), ", ", $canv->canvasy($y), "\n" +; my $dx = $x - $centerx; my $dy = $y - $centery; $canvas->move('fractal',$dx,$dy); } sub MakeMan(){ my ($e, $canv_x, $canv_y)=(0,$c_size/2,$c_size/2); if($scale > 1){ $e = $canvas -> XEvent; $canv_x = $e->x; $canv_y = $e->y; } my $icount = 1; #problem here... my $i = -2/$scale + (($canv_y-($c_size/2)) / ($c_size/$scale));# + $ +lasti; my $rgb; while($icount <= $c_size){ #... and here... my $r = -2/$scale + (($canv_x-($c_size/2)) / ($c_size/$scale));# + + $lastr; my $rcount = 1; while($rcount <= $c_size){ my $tr = $r; my $ti = $i; $rgb = '#000000'; for my $n(1..15){ ($tr, $ti) = (($tr ** 2) - ($ti ** 2) + ($r), (2 * $tr * $ti) ++ ($i)); if((($tr * $tr) + ($ti * $ti)) > 4){ $rgb = '#ffffff'; last; } } $canvas -> createLine($rcount, $icount, $rcount+1, $icount, -fill => $rgb, -width => 1, -tags => ['fractal'] ); $rcount ++; $r += (4/$scale)/$c_size; } $icount ++; $i += (4/$scale)/$c_size; } $scale = $scale * 2; my ($x1,$y1,$x2,$y2) = $canvas->bbox('fractal'); $centerx = ($x1+$x2)/2; $centery = ($y1+$y2)/2; print "center-> $centerx $centery\n"; }

I'm not really a human, but I play one on earth. Cogito ergo sum a bum

Replies are listed 'Best First'.
Re^2: Tk Zooming Fractal Problems
by Melly (Chaplain) on Dec 07, 2006 at 17:37 UTC

    Well, I don't know if it's what you intended, but you gave me a clue to solving the problem - I was making my job much harder than it needed to be by constantly trying to handle transitions from Mandelbrot scale to canvas scale + edges to centre...

    y concentrating on tracking the center I was able finally to get my head around what was needed... below is the working code - you can pass it a param of canvas size (e.g. "200"), or just let it use the default of 100.

    Thanks all.

    use strict; use Tk; my $c_size = ($ARGV[0] =~ /^\d+$/ && $ARGV[0]>0) ? $ARGV[0] : 100; my $scale = my $oldscale = 1; my ($lasti, $lastr)=(0,-0.5); my $mw = MainWindow -> new; my $canvas = $mw -> Canvas(-height=>$c_size, -width=>$c_size) -> pack; $canvas -> Tk::bind('all', '<ButtonPress-1>' => \&MakeMan); MakeMan(); MainLoop; sub MakeMan(){ $canvas -> delete('all'); my ($e, $canv_x, $canv_y)=(0,$c_size/2,$c_size/2); if($scale > 1){ $e = $canvas -> XEvent; $canv_x = $e->x; $canv_y = $e->y; } my $px_old = (4/$oldscale)/$c_size; my $px_new = (4/$scale)/$c_size; my $i = $lasti = $lasti + ($canv_y - ($c_size/2))*$px_old; # centre $i = $i - (($c_size/2)*$px_new); # left edge my $rconst = $lastr = $lastr + ($canv_x - ($c_size/2))*$px_old; # ce +ntre $rconst = $rconst - (($c_size/2)*$px_new); # top edge my $icount = 1; while($icount <= $c_size){ my $r = $rconst; my $rcount = 1; while($rcount <= $c_size){ my $iter = ($c_size/10)*($scale**0.5); my $tr = $r; my $ti = $i; my $rgb_out = '#000000'; my $rgb = 255; for my $n(1..$iter){ ($tr, $ti) = (($tr ** 2) - ($ti ** 2) + ($r), (2 * $tr * $ti) ++ ($i)); $rgb -= int(255/$iter); if((($tr * $tr) + ($ti * $ti)) > 4){ $rgb_out = '#' . (sprintf("%2.2X", $rgb))x3; last; } } $canvas -> createLine($rcount, $icount, $rcount+1, $icount, -fil +l => $rgb_out, -width => 1); $rcount ++; $r += ((4/$scale)/$c_size); } $icount ++; $i += ((4/$scale)/$c_size); } $oldscale = $scale; $scale = $scale * 2; }
    map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
    Tom Melly, pm@tomandlu.co.uk