BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:
I posted Re^3: How to draw a curved arrow in perl Tk canvas ? as an answer, but I've since discovered that about 1 or 2 times in 20 randomly generated uses, something goes wrong and it draws a 300° arc instead of a 60° arc.
Look as long as I have, I still cannot see why. It is obviously a math error, but I can't tell if it is mine or atan or Tk::Canvas that is the root of the problem. Can any of you mathematicians see the mistake?
Update:The problem arises when the atan2 calculations are around the vertical. I know that tan gets weird around 90°, but I thought the whole point of atan2 was to compensate for that?
Here is a version of the code that generates 10 random pairs of points and connects with a pair of arcs. The bad ones stand out like a sore thumb, but I cannot see the pattern to them:
#! perl -slw use strict; use Tk; use constant PI => 3.1415926535897932384626433832795; use constant RAD => 180 / PI; sub curvedArrow { my( $cnv, $x1, $y1, $x2, $y2, $color ) = @_; my $rad = sqrt( abs( $x1 - $x2 )**2 + abs( $y1 - $y2 )**2 ); my $q = sqrt( ( $x2 - $x1 )**2 + ( $y2 - $y1 )**2 ); my( $x3, $y3 ) = ( ( $x1 + $x2 ) / 2, ( $y1 + $y2 ) / 2 ); my $xc = $x3 + sqrt( $rad**2 - ( $q / 2 )**2 ) * ( $y1 - $y2 ) / $ +q; my $yc = $y3 + sqrt( $rad**2 - ( $q / 2 )**2 ) * ( $x2 - $x1 ) / $ +q; my $a1 = atan2( ( $yc - $y1 ) , -( $xc - $x1 ) ) * RAD; my $a2 = atan2( ( $yc - $y2 ) , -( $xc - $x2 ) ) * RAD; $cnv->createArc( $xc - $rad, $yc - $rad, $xc + $rad, $yc + $rad, -style => 'arc', -start => $a1, -extent => $a2 - $a1, -outline=> $color ); my $r2 = $rad / 15; $cnv->createArc( $x1-$r2, $y1-$r2, $x1+$r2, $y1+$r2, -start=>$a1-77, -extent=>($a2-$a1)/2, -fill=> $color ); $cnv->createArc( $x2-$r2, $y2-$r2, $x2+$r2, $y2+$r2, -start=> ( $a2+107 ) %360, -extent=>($a2-$a1)/2, -fill=> $colo +r ); return $xc, $yc; } our $W //= 1000; our $H //= 800; my $mw = new MainWindow(-title => 'Test'); my $canvas = $mw->Canvas(-width => $W, -height => $H )->pack; for( 1 .. 10 ) { my( $x1, $y1 ) = ( int( rand( $W ) ), int( rand( $H ) ) ); $canvas->createLine( $x1-5, $y1, $x1+5, $y1, -fill => 'blue' ); $canvas->createLine( $x1, $y1-5, $x1, $y1+5, -fill => 'blue' ); my( $x2, $y2 ) = ( int( rand $W ), int( rand $H ) ); $canvas->createLine( $x2-5, $y2, $x2+5, $y2, -fill => 'green' ); $canvas->createLine( $x2, $y2-5, $x2, $y2+5, -fill => 'green' ); my( $xc, $yc ) = curvedArrow( $canvas, $x1, $y1, $x2, $y2, 'black' + ); $canvas->createLine( $xc-5, $yc, $xc+5, $yc, -fill => 'red' ); $canvas->createLine( $xc, $yc-5, $xc, $yc+5, -fill => 'red' ); ( $xc, $yc ) = curvedArrow( $canvas, $x2, $y2, $x1, $y1, 'red' ) +; $canvas->createLine( $xc-5, $yc, $xc+5, $yc, -fill => 'red' ); $canvas->createLine( $xc, $yc-5, $xc, $yc+5, -fill => 'red' ); } MainLoop;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: My math error or Perl's? (Solved:mine)
by BrowserUk (Patriarch) on Aug 01, 2012 at 08:38 UTC | |
|
Re: My math error or Perl's?
by Anonymous Monk on Aug 01, 2012 at 02:14 UTC | |
by BrowserUk (Patriarch) on Aug 01, 2012 at 09:29 UTC |