use strict; use warnings; use PDF::API2; use constant PAGE_WIDTH => 595; use constant PAGE_HEIGHT => 842; use constant LINE_WIDTH => 0.5; use constant THIN_LINE_WIDTH => 0.25; use constant CM => 28.346457; # 1 cm in points sub log16 { my $n = shift; return log($n) / log(16); } sub angle { my $theta = shift; return -360.0 * log16($theta) } sub run { my $pdf = PDF::API2->new; my $font = $pdf->corefont("TimesNewRoman"); $pdf->mediabox(PAGE_HEIGHT, PAGE_WIDTH); my $gfx = $pdf->page->gfx; $gfx->strokecolor( '#000' ); $gfx->linewidth( THIN_LINE_WIDTH ); my $yc = PAGE_WIDTH / 2.0; my $radius = PAGE_HEIGHT / 4.0 - 1 * CM; my @tick16 = map( $_ / 16.0, (16 .. 255) ); my %outerDisk = (centre => PAGE_HEIGHT / 4.0, dir => +1, bigLetter => 0.35 * CM, smallLetter => 0.18 * CM ); my %innerDisk = (centre => 3.0 * PAGE_HEIGHT / 4.0, dir => -1, bigLetter => -0.6 * CM, smallLetter => -0.3 * CM ); for my $disk ( \%outerDisk, \%innerDisk ) { $gfx->save(); $gfx->translate($$disk{centre}, $yc); $gfx->linewidth( LINE_WIDTH ); $gfx->circle(0, 0, 1); $gfx->circle(0, 0, $radius); $gfx->circle(0, 0, $radius + 0.75 * CM * $$disk{dir}); $gfx->stroke(); $gfx->linewidth( THIN_LINE_WIDTH ); $gfx->move(0, -0.5 * CM); $gfx->line(0, 0.5 * CM); $gfx->stroke(); $gfx->move(-0.5 * CM, 0); $gfx->line(0.5 * CM, 0); $gfx->stroke(); for my $i (@tick16) { my $angle = angle($i); $gfx->rotate($angle); if ($i * 16 % 16 == 0) { $gfx->move(0, $radius); $gfx->line(0, $radius + 0.3 * CM * $$disk{dir}); $gfx->stroke; $gfx->textlabel(0, $radius + $$disk{bigLetter}, $font, 10, sprintf("%X", $i), -align => 'center'); } elsif ($i * 16 % 4 == 0) { $gfx->move(0, $radius); $gfx->line(0, $radius + 0.15 * CM * $$disk{dir}); $gfx->stroke; } else { $gfx->move(0, $radius); $gfx->line(0, $radius + 0.1 * CM * $$disk{dir}); $gfx->stroke; } if ($i < 4.0 and $i * 16 % 16 != 0) { $gfx->textlabel(0, $radius + $$disk{smallLetter}, $font, 5, sprintf("%X", $i * 16 % 16), -align => 'center'); } if ($i > 4.0 and $i < 8.0 and $i * 16 % 2 == 0 and $i * 16 % 16 != 0) { $gfx->textlabel(0, $radius + $$disk{smallLetter}, $font, 5, sprintf("%X", $i * 16 % 16), -align => 'center'); } if ($i > 8.0 and $i * 16 % 4 == 0 and $i * 16 % 16 != 0) { $gfx->textlabel(0, $radius + $$disk{smallLetter}, $font, 5, sprintf("%X", $i * 16 % 16), -align => 'center'); } $gfx->rotate(-$angle); } $gfx->restore(); } $pdf->saveas("hex_slide_rule.pdf"); } run();