c:\test>868223-gen -N=1000 | 868223-plot -RETAIN=50 #### #! perl -slw use strict; use Data::Dump qw[ pp ]; use List::Util qw[ max reduce ]; use GD; use constant { SCALE => 1000, OFFSET => 100, }; sub rgb2n { unpack 'N', pack 'CCCC', 0, @_ } sub rgba2n { unpack 'N', pack 'C4', pop, @_ } sub morton { my( $x, $y ) = @_; my $z = 0; for my $i ( 0 .. 31 ) { $z |= ( $x & 1<<$i )<<$i | ( $y & 1<<$i)<<( $i + 1 ); } return $z; } our $RETAIN //= 20; my( $maxX, $maxY ) = (0,0); my @points = sort{ $maxX = max( $maxX, $a->[0], $b->[0] ); $maxY = max( $maxY, $a->[1], $b->[1] ); $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1]; } map[ split ], <>; my $img = GD::Image->new( $maxX*SCALE+(OFFSET*2), $maxY*SCALE+(OFFSET*2), 1 ); $img->filledRectangle( 0,0, $img->getBounds, rgb2n( 255,255,255 ) ); my $last; for my $pt ( @points ) { my( $x, $y, $dy ) = map{ $_*SCALE+OFFSET } @{ $pt }; $dy -= OFFSET; $img->filledEllipse( $x, $y, $dy, $dy, rgba2n( 255, 0, 0, 90 ) ); $img->line( $x-10, $y, $x+10, $y, 0 ); $img->line( $x, $y-10, $x, $y+10, 0 ); if( $last ) { $img->line( $last->[0], $last->[1], $x, $y, rgb2n( 0,0,255 ) ); } $last = [ $x, $y ]; } my @ordered = map{ [ morton( int( $_->[0]*SCALE ), int( $_->[1]*SCALE ) ), $_ ] } @points; while( @ordered > $RETAIN ) { my( $nearest, $nDiff ) = ( 0, 1e308 ); for my $i ( 0 .. $#ordered - 1 ) { my $diff = abs( $ordered[ $i+1 ] - $ordered[ $i ] ); ( $nearest, $nDiff ) = ( $i, $diff ) if $diff < $nDiff; } my $discard = ( $ordered[ $nearest ][ 1 ][ 2 ] < $ordered[ $nearest+1 ][ 1 ][ 2 ] ) ? $nearest+1 : $nearest; splice @ordered, $discard, 1; } $last = undef; for my $pt ( map $_->[1], @ordered ) { my( $x, $y, $dy ) = map{ $_*SCALE } @{ $pt }; $x += OFFSET; $img->filledEllipse( $x, $y, $dy, $dy, rgba2n( 0, 255, 0, 90 ) ); $img->line( $x-10, $y, $x+10, $y, 0 ); $img->line( $x, $y-10, $x, $y+10, 0 ); if( $last ) { $img->line( $last->[0], $last->[1], $x, $y, rgb2n( 0, 255, 0 ) ); } $last = [ $x, $y ]; } $img->flipVertical; open PNG, '>:raw', "$0.png"; print PNG $img->png; close PNG; system 1, "$0.png";