Points Map Rendering

Static PNG generation of GeoJSON points using GD::GIS, YAML styles and OpenStreetMap basemaps.

Render Preview

Preview of the generated PNG map using different point rendering modes: image icons, numeric markers, and alphabetic markers.

# Create output directory
mkdir output

# Install dependency
gem install libgd-gis

# Run the script
ruby points.rb

Expected output:

✔ Generated: output/aerial.png
Rendered Points map
Generated with libgd-gis · Basemap © OpenStreetMap
Rendered Points map
Generated with libgd-gis · Basemap © OpenStreetMap
Rendered Points map
Generated with libgd-gis · Basemap © OpenStreetMap

Style definition (solarized.yml)

global:
  label:
    color: [35, 35, 35, 20]

points:
  color: [0, 0, 127, 0]
  font_color: [250, 250, 250]
  font: /usr/share/fonts/truetype/lato/Lato-Regular.ttf
  size: 10
  icon: icon.png
  # icon can also be: numeric | alphabetic

Ruby script (points.rb)

require "gd/gis"
require_relative "fonts"

OUTPUT = "output/aerial.png"
GEOJSON = "data/aerial.geojson"

bbox = GD::GIS::Geometry.bbox_for_image(
  GEOJSON,
  zoom: 13,
  width: 800,
  height: 600,
  padding_px: 100
)

map = GD::GIS::Map.new(
  bbox: bbox,
  zoom: 15,
  width: 800,
  height: 600,
  basemap: :osm
)

map.style = GD::GIS::Style.load("solarized")
map.add_geojson(GEOJSON)

map.render
map.save(OUTPUT)

puts "✔ Generated: #{OUTPUT}"

macOS Font Support

On macOS, system fonts are stored in different directories than Linux. Some examples may fail to render labels or symbols unless font paths are explicitly provided.

To ensure portability, the examples include a small helper file (fonts.rb) that discovers available TrueType/OpenType fonts across common system locations.

# fonts.rb
module GD
  module Fonts
    PATHS = [
      # Linux system fonts
      "/usr/share/fonts",
      "/usr/local/share/fonts",

      # macOS system fonts
      "/System/Library/Fonts",
      "/Library/Fonts",

      # User fonts
      File.expand_path("~/Library/Fonts"), # macOS user fonts
      File.expand_path("~/.fonts")         # Linux user fonts
    ].freeze

    EXT = "{ttf,otf,ttc}".freeze

    def self.all
      @all ||= PATHS.flat_map do |p|
        next [] unless Dir.exist?(p)
        Dir.glob("#{p}/**/*.#{EXT}")
      end.uniq
    end

    def self.random
      all.sample or raise "GD::Fonts: no fonts found on system"
    end

    def self.find(name)
      n = name.downcase
      all.find { |f| File.basename(f).downcase.include?(n) }
    end
  end
end

Include this helper in your script when running on macOS:

require_relative "fonts"

Then reference a font path in your YAML style or dynamically select one:

font_path = GD::Fonts.find("Lato") || GD::Fonts.random

This ensures text rendering works reliably across Linux, macOS, Docker environments, and CI pipelines.