All started a week ago when I saw a
unicursal hexagram and I started wondering the logic behind drawing a n-points unicursal star, so I gone thorough some wikipedia articles and finally created a method that can draw a
unicursal star polygon of n points for any natural* number.
For those wondering, any non-convex polygon in star form could be considered a star polygon, but only those where the lines can be draw starting and ending at the same point, passing through all the other points exactly one time are unicursal star polygons
Although my code works like I wanted, I still don't like
how it does it, so I would like to hear what the perlmonks have to say about it.
And here is the code:
#!/usr/bin/perl
use warnings;
die "need number of points\n" unless @ARGV;
$n = shift;
die "need valid number\n" if($n!~m/^\d+$/ || $n < 1);
use constant PI => 4*atan2(1,1);
$rad = 150; # radius of circunference, size of star
$alpha = 3*PI/2; # angle of starting point
$beta = 2*PI/$n; # angle variation
for(0..$n-1) # finding necessary points
{
$x = $rad + $rad * cos($alpha);
$y = $rad + $rad * sin($alpha);
$pts{$_}{x} = $x;
$pts{$_}{y} = $y;
$alpha += $beta;
}
# svg header
print "<?xml version='1.0' standalone='no'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'
'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg width='100%' height='100%' version='1.1'
xmlns='http://www.w3.org/2000/svg'>\n\n";
$mod = calcMagic($n); # interval of points
print STDERR "mod: $mod\n";
$oldp = 0;
$p = 1;
while($p != 0)
{
$mod = hexMagic($oldp) if($n == 6); # hexagrams are irregular
$p = ($oldp + $mod) % $n; # find next point
print STDERR "LINE: $oldp <-> $p\n";
$x1 = $pts{$oldp}{x};
$y1 = $pts{$oldp}{y};
$x2 = $pts{$p}{x};
$y2 = $pts{$p}{y};
print "<line x1='$x1' y1='$y1' x2='$x2' y2='$y2' style='stroke:rgb
+(0,0,0);stroke-width:1'/>\n";
$oldp = $p;
}
print "\n</svg>\n";
# calculate the interval
# based on number of points
sub calcMagic
{
($n) = @_;
$m = -1;
$mod = 1;
for(1..$n)
{
$mod += $m;
$m = nextMagic($m);
}
return $mod;
}
# have no idea
sub nextMagic
{
($oldm) = @_;
return 3 if($oldm == -1);
return -2 if($oldm == 3);
return 2 if($oldm == -2);
return -1 if($oldm == 2);
}
# special case,
# hexagram intervals
sub hexMagic
{
($p) = @_;
return 2 if($p == 0);
return 3 if($p == 2);
return 4 if($p == 5);
return 4 if($p == 3);
return 3 if($p == 1);
return 2 if($p == 4);
}
As you can see, it actually outputs a
SVG image, you can run it like:
$perl draw_star.pl N > img.svg ,where N is the points number
and open the result in your favorite browser/image viewer.
The main problem is finding the
$mod number, this is how much points it will 'jump' from the current point to draw the next line.
Notice that this is where things get dirty,
calcMagic was called this ways because I failed in understand the logic(if any) behind it.
There is also a side problem, take a look again in the
unicursal hexagram and you will notice that it's irregular, which means the
$mod number changes depending on the current point.
..and, although I was a Anonymous Monk for quite a time, I sill not sure if this is the right place for this, even after reading
Where should I post X?, so I'm sorry if it isn't.
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.