#!/usr/bin/env perl # This program connects to the database and creates one image at a time in a loop # It can thus be run in parallel use strict; use warnings; use JSON; use Image::Magick; my $data = ''; my $forks = 0; if ($ARGV[0] eq '-f' ) { shift; $forks = shift; } while (<>) { $data .= $_; } warn "read data\n"; my $json = JSON->new; my $run = $json->decode($data); warn "parsed json\n"; my %coords; my (@min, @max); # bounding box so we can know how big to make the image my $scale = 5; # get the vertex coordinates for each hex if (0) { my $i=0; foreach my $hex (@{$run->{hexlist}}) { my $c = `./hexverts $scale $hex`; chomp $c; $coords{$hex} = $c; $i++; warn "$i $hex = $c\n"; } } else { %coords = do 'verts.pl'; } #warn keys %coords, "\n"; warn "got coords\n"; my @forks = (); if ($forks > 0) { my $elems = @{$run->{gendata}}; my $perfork = int($elems / $forks); my $leftover = $elems - $perfork * $forks; my $start = 0; for my $fork (0..$forks-1) { $forks[$fork] = { start => $start, end => $start + $perfork-1 }; $forks[$fork]{end}++ if $fork < $leftover; $start = $forks[$fork]{end}+1; } } my $forkinfo = join(' ', map { sprintf('[%s %s]', $_->{start}, $_->{end}) } @forks); warn "forks = $forkinfo\n"; while (my $f = shift @forks) { my $pid = fork; next if $pid; foreach my $gen (@{$run->{gendata}}[$f->{start}..$f->{end}]) { my $image = Image::Magick->new(size => '364x404'); $image->ReadImage('canvas:white'); # foreach (qw(background fill size colorspace)) { # warn "$_ ", $image->Get($_), "\n"; # } my %drawn = (); foreach my $hex (@{$gen->{hexes}}) { my $frac = $hex->{freq}[0]/$hex->{pop}/2.0; my $maxgenfrac = $hex->{pop} / $gen->{maxpop}; my @hsv = ( (4.0 / (1.0 + exp(-($frac - 0.5 ))) - 1.5) / 2.0 + 0.075, # hue 1.0, # saturation 0.15+0.85*sqrt($maxgenfrac) # value ); for (@hsv) { $_ = 1.0 if $_ > 1.0; $_ = 0.0 if $_ < 0.0; } my $color = sprintf('hsb(%f%%, %f%%, %f%%)', 100 * $hsv[0], 100 * $hsv[1], 100 * $hsv[2]); #warn "drawing $color\n"; die "missing coords for hex ", $hex->{hex}, "\n" unless exists $coords{$hex->{hex}}; $image->Draw(fill => $color, primitive=>'polygon', antialias => 1, points => $coords{$hex->{hex}}); $drawn{$hex->{hex}} = 1; } foreach my $hex (keys %coords) { next if $drawn{$hex}; $image->Draw(fill => 'black', primitive=>'polygon', points => $coords{$hex}); } # make a band on the top for a label # make sure this is a multiple of four, some # of the movie formats require it $image->Splice(geometry => '0x20', background => 'white', gravity => 'North'); # now annotate the image my $x = 5; # where to put the annotation my $y = 220; my $font = 'SourceCodePro-Light.ttf'; my %params = ( font => $font, fill => 'black', stroke => 'black', pointsize => 15, antialias => 1, ); # set up a title caption # my @lines = ( sprintf('gen: %8d', $gen->{gen}), sprintf(q{pop: %8d}, $gen->{pop}), sprintf(q{ybp: %8d}, $gen->{year}), ); for (@lines) { $image->Annotate(%params, x => $x, y => $y, text => $_); $y += 15; } # $text = sprintf(q{ams: %8d}, $genlen*$gen); # $image->Annotate(x => $x, y => $y, -text => $text); $y += 15; my $prefix = $ENV{IMGPREFIX}; $prefix ||= ''; my $name = $prefix . sprintf('%04d.png', $gen->{gen}); $image->Write($name); warn sprintf("%s gen %d pop %d\n", $name, $gen->{gen}, $gen->{pop}); } exit 0; } while (wait != -1) {}; sub mkdirp { my $path = '.'; foreach my $comp (@_) { $path .= "/$comp"; mkdir $path unless -d $path; die "can't make director $path: $!" unless -d $path; } } __END__