[ 10.7685250292969 24.0294289818115 ] [ 10.764576366333 24.0289633201904 ] ------ [ 11.8467422927246 22.0280153343506 ] [ 11.8505748185425 22.0356987510986 ] ------ [ 10.3691293842163 22.0120664238281 ] [ 10.3718005385742 22.0104366081543 ] ------ [ 10.9817528293457 22.6283695793457 ] [ 10.974320052002 22.6306978874512 ] ------ [ 12.2627455496826 23.6263988487549 ] [ 12.2549643609009 23.62430337146 ] ------ [ 13.0046296383057 23.9849582969971 ] [ 13.0082298898315 23.9801852653809 ] ------ [ 12.3460158833618 23.0528201469727 ] [ 12.3482224891357 23.0609692253418 ] ------ [ 13.6142335176392 24.0877530998535 ] [ 13.619808100647 24.0818159141846 ] ------ [ 10.4141905968628 21.2074031425781 ] [ 10.4150035568848 21.2060061577148 ] ------ [ 11.0738495861206 23.2290730705566 ] [ 11.0661845344849 23.2240672081299 ] [ 11.0827921463623 23.2314013786621 ] ------ [ 10.8340263796387 21.6198629234619 ] [ 10.8307745395508 21.6281284172363 ] [ 10.8416914312744 21.6245195396729 ] ------ #### #! perl -slw use strict; use Data::Dump qw[ pp ]; use List::Util qw[ reduce ]; use GD; use constant { WHITE => 16777215, MinX => 10.318842, MaxX => 14.124424, MinY => 21.097507, MaxY => 24.912207, }; use constant { SpanX => MaxX - MinX, SpanY => MaxY - MinY, }; sub rgb2n{ unpack 'N', pack 'CCCC', 0, @_ } sub n2rgb{ unpack 'xCCC', pack 'N', $_[0] } our $POINTS ||= 300_000; my @points = map [ MinX + rand( SpanX ), MinY + rand( SpanY ) ], 1 .. $POINTS; ## Normalise to our grid, scale by 1000 and integerise my @scaled = map [ int( ( $_->[ 0 ] - MinX ) * 1000 ), int( ( $_->[ 1 ] - MinY ) * 1000 ), ], @points; my( $sizeX, $sizeY ) = ( int( SpanX * 1000 ), int( SpanY * 1000 ) ); my $img = GD::Image->new( $sizeX, $sizeY , 1 ); $img->filledRectangle( 0, 0, $sizeX, $sizeY, rgb2n( 255, 255, 255 ) ); my %groups; for my $i ( 0 .. $#scaled ) { my $color = $img->getPixel( @{ $scaled[ $i ] } ); if( $color != WHITE ) { push @{ $groups{ $color } }, $i; } else { $color = $i; } $img->filledEllipse( @{ $scaled[ $i ] }, 20, 20, $i ); } ## Save the image showing all points/circles open IMG, '>:raw', '694790all.png' or die $!; print IMG $img->png; close IMG; system 1, '694790all.png'; undef $img; ## Produce a file of clusters of points open OUT, '>', '694790.groups' or die $!; for my $key ( sort { $a <=> $b } keys %groups ) { print OUT "[ @{ $points[ $_ ] } ]" for $key, @{ $groups{ $key } }; print OUT "------"; } close OUT; ## Produce second image showing just the clustered points. $img = GD::Image->new( $sizeX, $sizeY , 1 ); $img->filledRectangle( 0, 0, $sizeX, $sizeY, rgb2n( 255, 255, 255 ) ); for my $key ( sort { $a <=> $b } keys %groups ) { $img->filledEllipse( @{ $scaled[ $key ] }, 20, 20, $key ); $img->filledEllipse( @{ $scaled[ $_ ] }, 20, 20, $key ) for @{ $groups{ $key } }; } open IMG, '>:raw', '694790grouped.png' or die $!; print IMG $img->png; close IMG; system 1, '694790grouped.png'; __END__ Latitude stats: Minimum: 10.318842 Maximum: 14.124424 Mean: 11.24719 Standard Deviation: 0.805771 Longitude stats: Minimum: 21.097507 Maximum: 24.912207 Mean: 22.474358 Standard Deviation: 0.974835