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!#! 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);
In reply to Re: Reflections on graphic screwing!
by etj
in thread Reflections on graphic screwing!
by BrowserUk
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |