You can get the coordinates for the end point of the arc with the following subroutine:
use strict; use warnings; use Math::Trig; sub getArcEnd { my ($x, $y, $x2, $y2, $start, $extent) = @_; # -------------------------------------- # Note: this was added in response to liverpole's note below # Optional patch to allow denormalized bounding boxes if ($x2 < $x) { my $tmp = $x; $x=$x2; $x2=$tmp; } if ($y2 < $y) { my $tmp = $y; $y=$y2; $y2=$tmp; } # -------------------------------------- # $x, $y, $x2, $y2 can be the bounding box of an # ellipse (not just a circle) so calculate vertical # and horizontal radius separately my $radiusX = ($x2 - $x)/2; my $centerX = $x + $radiusX; my $radiusY = ($y2 - $y)/2; my $centerY = $y + $radiusY; # Tk expects the starting angle and length of the # arc (extent) to be in degrees but cos and sin expect # them in radian my $radians = deg2rad($start + $extent); # [ x coord of arc end point, y coord of arc end point ] # the coordinate system for Tk::Canvas makes "down" # positive so we need to subtract the Y component # rather than add it. return [ $centerX + $radiusX*cos($radians) , $centerY - $radiusY*sin($radians) ]; }
The only way to get the arrow head to orient correctly on a line attached to the end of the circle would be to angle the line. That would require a very short line tangent to the circle. I'm not exactly sure how Tk draws its circles, but usually a circle is drawn just as you tried to do it with a series of very short lines. However, there is some smoothing going on so that the line looks less choppy to the human eye. In some cases the points of that short line may not coincide exactly with the points of the circle and you will see a slight thickening at the point where you want to join your arrow. Depending on the size of your arrow and the radius of your arc, it may or may not be noticable.
Another option is to draw your own arrow. To get the arrow aligned right, the arrow's coordinates need to be rotated clockwise 45 degrees (-45). To get you started, here is a quick routine that draws a very simple arrow head.
sub drawArrow { my ($xEnd, $yEnd, $start, $extent, $arrowLength) = @_; my $radians = deg2rad($start + $degrees-45); my $xArrow = $arrowLength * cos($radians); my $yArrow = $arrowLength * sin($radians); $can->createLine($xEnd, $yEnd, $xEnd+$xArrow, $yEnd-$yArrow); $can->createLine($xEnd, $yEnd, $xEnd+$yArrow, $yEnd+$xArrow); }
Best, beth
Update: Added explanation of how to draw a properly oriented arrow head.
Update 2: Added optional patch to allow non-normalized bounding boxes - see below, liverpole's note and responses for further discussion.
In reply to Re: Tk:Canvas - Arc with an arrow?
by ELISHEVA
in thread Tk:Canvas - Arc with an arrow?
by cmv
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |