Here is a PDL version, that still has loops (gasp) but uses Judd Taylor's excellent PDL binding for GD. It goes about 5 times quicker than the version in the OP (edit to note: actually, for the fancy -M=4 -P=1.5 -S=200 -L=10 one, the OP takes about 70s, this PDL one takes 7s, so 10x quicker):
#! perl -sw use strict; use PDL; use PDL::Constants qw(PI DEGRAD); use PDL::IO::GD; use constant FNAME => 'CGScrewPDL'; use constant { COS30 => 0.86602540378443864676372317075294, TAN30 => 0.57735026918962576450914878050196, }; use enum qw[ X Y A ]; ## Construct thread profile segment sub constructThreadProfile { my @points; my( $dia, $pitch, $yInc ) = @_; my $H = $pitch * COS30; # draw flat crest my $x = $dia / 2; my $y = -$yInc; my $yLim = $pitch / 16; push @points, [ $x, $y += $yInc, 1 ] while $y < $yLim; ## draw upper 30deg flank. my $xd = $yInc / TAN30; $yLim = $y + 5 / 16 * $pitch; push @points, [ $x -= $xd, $y += $yInc, 0.5 ] while $y < $yLim; ## draw root radius $yLim = $y + 4 / 16 * $pitch; my( $cx, $cy, $r ) = ( ( $dia/2 - 7/8*$H + $H/3 ), $pitch / 2, $H +/ 6 ); while( $y < $yLim ) { my $dy = $cy - $y; my $dx = sqrt( $r**2 - $dy**2 ); push @points, [ $cx - $dx, $y, $dx / $r ]; $y += $yInc; } $y -= $yInc; ## draw lower 30deg flank $yLim = $y + 5 / 16 * $pitch; push @points, [ $x += $xd, $y += $yInc, - 0.5 ] while $y < $yLim; $yLim = $pitch; push @points, [ $x, $y += $yInc, 1 ] while $y < $yLim; return pdl \@points; } our $M //= 10; our $P //= 1.5; our $L //= 2; our $S //= 100; my $fname = sprintf "%sM%.2fxP%.2fxL%.2fxS%d.png", FNAME, $M, $P, $L, +$S; my $profilePDL = constructThreadProfile( $M, $P, 1 / ( 10* $S ) ); my( $w, $h ) = ( $M * $S + 200, int( $L / $P + 1 ) * $P * $S + 200 ); my $xc = $w / 2; my $imPDL = zeroes(byte, $w, $h) + 128; # no RGB as all same, dummy at + end my $yTrans = $P / 360; my $maxRad = $M * $S / 2; my $yOff = 100; my $turns = sequence(indx, $L / $P); for my $turn ( $turns->list ) { for my $p ( map $_/2, -$maxRad*2 .. $maxRad*2 ) { my $rot = atan2( sqrt( $maxRad**2 - $p**2 ), $p ); my $this_profile = $profilePDL + [0, $yTrans * DEGRAD * $rot, +0]; $this_profile *= [cos($rot), 1, cos( PI/2 - $rot)]; my ($newX, $newY) = ($xc + $this_profile->slice([X,0,0]) * $S, + $yOff + $this_profile->slice([Y,0,0]) * $S); my $color = $this_profile->slice([A,0,0])->abs * 256 + (100 - +$newY); $imPDL->indexND( $newX->cat($newY)->mv(-1,0) ) .= $color; } $yOff += $P * $S; } my $im = PDL::IO::GD->new({pdl=> $imPDL->dummy(2,3)}); $im->String( gdFontGetSmall, 0,0, $fname, 0 ); $im->write_Png($fname);
You can see I eliminated the "Z" enum and entry in the "profile" and "xformPoints" (inlined as a couple of PDL operations here). That made the original run about 10% faster. Top tip for programmers! If you don't want to waste 45 minutes cursing your existence in confusion, if you eliminate part of a fixed-size tuple, make sure you eliminate it in all places. Unexpected results will happen otherwise!

In reply to Re: Reflections on graphic screwing! by etj
in thread Reflections on graphic screwing! by BrowserUk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • 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:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.