#! 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