Ham::WorldMap - Creates an Imager image containing an equirectangular projection of the world map, with optional Maidenhead locator grid and day/night illumination showing the area of enhanced propagation known as the 'grey line'. Also utility methods for adding dots at locator positions or lat/long coords, and filling grid squares with colour to provide a 'heat map' of activity from these squares.

A sample map:

Example map


The map used in this module came from Wikimedia commons: and is in the public domain.

(I resized it to have a width of 1920 pixels, shifted it right a little to match other amateur locator maps, took off the odd pixels at each side, and exported it as a PNG in InkScape. The code to do that is in another project that you don't need, but that also contains examples of the use of this module: )

The day/night illumination code is ported from John Walker's Earth and Moon viewer, at I do not profess to understand the maths behind this, but John's description should suffice:

  How do you calculate the day and night regions of the Earth?
    The position of the Sun with respect to the Earth is calculated by the algorithm given in Jean Meeus's "Astronomical
    Algorithms". Once the position of the Sun is known, the terminator (line separating day and night) is simply the
    circle where the plane perpendicular to the Earth-Sun vector and passing through the centre of the Earth intersects
    the globe, which is straightforward to calculate. Then it's simply a matter of colouring the hemisphere away from
    the Sun in subdued shades.


Version 0.01


To create a map with a station location, grid squares, and night/day boundary:

    use Ham::WorldMap;

    # By default, an OSX-specific font will be used for drawing text. If you're not on OSX, supply the name of a
    # font file...
    my $map = Ham::WorldMap->new();  # fine on OSX, uses Lucida Console.
    my $map = Ham::WorldMap->new('fontFile' => "C:\\Windows\\Fonts\\Arial.ttf");  # Windows, not tested.

    # The map now has the world on it.

    my $colour = Imager::Color->new(16, 16, 192);
    my $radius = 20;
    $map->dotAtLocator("JO01EE", $radius, $colour); # M0CUV is here!

    # World plus dot.

    my $dt = DateTime->new(
        year       => 2016,
        month      => 6,
        day        => 5,
        hour       => 0,
        minute     => 0,
        second     => 0,
        nanosecond => 0,
        time_zone  => 'UTC',

    # The world plus dot, with day/night on top.


    # The grid is on top of the world/dot/day/night.



No functions exported; this has a purely object-oriented module.



The constructor; takes a hash of arguments, returns a blessed hash.

Currently the only data in the argument hash is fontFile, the name of a TTF font. This code was written on OSX, and if not specified, Lucida Console.ttf will be used; you'll need to specify this on non-OSX.

    my $map = Ham::WorldMap->new('fontFile' => "C:\\Windows\\Fonts\\Arial.ttf");  # Windows, not tested.

Some instance data in the hash that you might find useful: I should probably expose these via methods: 'height' => the map image height 'width' => the map image width 'image' => the Imager image of the map 'gridx' => the width of each grid square 'gridy' => the height of each grid square

dotAtLocator($self, $gridLocation, $radius, $colour)

Takes a grid location at any granularity (e.g. 'JO', 'JO01', 'JO01EE'), a radius in pixels, and an Imager colour, then draws that dot.

locatorToXY($self, $gridLocation) = ($x, $y)

Converts a grid location of any granularity into X,Y coordinates for that location on the map image.


Draws the locator grid, large-granularity grid square identifiers (2 character, e.g. JO) on the map image.

heatMapGridSquare($self, $twoCharGridSquare, $proportion)

Colour a 2-char grid square (e.g. JO for South-East England) from a heat map, according to the proportion, which is in the range [0.0 .. 1.0]. 0.0 indicates 'no signals in this square'; 1.0 indicates 'all signals in this square'.

write($self, $filename)

Writes the map image to a file; e.g. "map.png".

drawNightRegions($self, $dateTime)

Draw the night regions onto the map, for a given UTC time/date. This is not a fast operation; it's computationally heavy.

createNightRegions($self, $dateTime) = $map

Create an Imager image of the day/night boundary, for a given UTC time/date. Does not modify current map image, gives back a new one that can be composed transparently onto the main image (you may just want to use drawNightRegions - this is a bit 'internal').


Matt Gumbley, M0CUV <devzendo at> @mattgumbley on twitter


The Mercurial source repository for this module is kindly hosted by Bitbucket, at:


Please report any bugs or feature requests to bug-ham-worldmap at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Ham::WorldMap

You can also look for information at:


Copyright 2016 Matt Gumbley.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at


Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.