Generating Output for Pen Plotters Using vsketch Plotter Mode in prettymaps

Set mode="plotter" in prettymaps.plot() to generate SVG output optimized for pen plotters via the integrated vsketch engine.

The prettymaps library extends beyond Matplotlib raster rendering to produce clean, scalable vector graphics suitable for physical pen plotters. By activating the vsketch plotter mode, the library translates OpenStreetMap geometries directly into SVG path commands that AxiDraw, Makelangelo, and other plotter hardware can execute without conversion.

How the vsketch Plotter Mode Works

The plotter pipeline lives entirely within prettymaps/draw.py and replaces the standard Matplotlib backend with a vsketch.Vsketch instance. The workflow proceeds through four coordinated stages:

  1. Mode detection — init_plot() instantiates vsketch.Vsketch() instead of Matplotlib Figure/Axes
  2. Layer iteration — draw_layers() passes geometries to plot_gdf() with vsketch context
  3. Geometry dispatch — plot_gdf() issues vsk.geometry() commands for each shapely object
  4. SVG output — vsk.display() flushes the drawing queue to file

Core Implementation in prettymaps/draw.py

The mode branch occurs at lines 1010‑1014 in init_plot():

def init_plot(
    title: str = "",
    mode: str = "matplotlib",
    ...
):
    if mode == "plotter":
        vsk = vsketch.Vsketch()
        vsk.size("a4", landscape=True)
        return vsk, None
    else:
        # Standard Matplotlib path

        fig, ax = plt.subplots(figsize=figsize)
        return fig, ax

When mode="plotter", the function returns a Vsketch object and None for the axes handle, signaling downstream functions to use vsketch commands exclusively.

Drawing Geometries with vsketch Commands

The plot_gdf() function (lines 402‑424) handles the translation from GeoDataFrames to vsketch primitives. For each geometry in the layer:

if mode == "plotter":
    vsk.stroke(kwargs.get("stroke", 1))
    vsk.penWidth(kwargs.get("penWidth", 0.3))
    vsk.fill(kwargs.get("fill", False))
    vsk.geometry(shape)

Key vsketch parameters:

  • stroke — Controls stroke color (mapped from matplotlib ec or explicit value)
  • penWidth — Physical pen width in millimeters (default 0.3mm)
  • fill — Boolean toggle for polygon fills; use False for outline-only plotter art
  • geometry() — Accepts any shapely Polygon, LineString, MultiPolygon, or GeometryCollection

After all layers process through draw_layers() (lines 995‑1005), the main plot() function executes vsk.display() at lines 1268‑1270 to finalize the SVG.

Practical Examples for Pen Plotter Output

Basic Plotter Mode Call

Generate a single-location SVG for water features:

import prettymaps

prettymaps.plot(
    "Porto, Portugal",
    mode="plotter",
    layers={"water": {"tags": {"natural": "water"}}},
    style={"water": {"fc": "#a1e3ff", "ec": "#2F3737"}},
    save_as="porto.svg",
    show=False,
)

The save_as parameter ensures the SVG writes to disk; show=False suppresses the Matplotlib preview window.

Multiplot Layout for Plotters

Create composited maps on a single plotter canvas:

import prettymaps

sub1 = prettymaps.Subplot("São Paulo, Brazil")
sub2 = prettymaps.Subplot("Rio de Janeiro, Brazil")

prettymaps.multiplot(
    sub1, sub2,
    mode="plotter",
    figsize=(21, 14),  # A3 dimensions in centimeters

    save_as="brazil.svg",
    show=False,
)

According to the prettymaps source code, multiplot() reuses the same Vsketch instance across subplots, positioning each map via vsketch's native coordinate transformation.

Fine-Tuned Pen Plotter Styling

Control physical pen characteristics for detailed architectural drawings:

prettymaps.plot(
    "Amsterdam, Netherlands",
    mode="plotter",
    layers={"building": {"tags": {"building": True}}},
    style={
        "building": {
            "palette": ["#FFC857", "#E9724C", "#C5283D"],
            "stroke": 0.5,      # Stroke color index or value

            "penWidth": 0.1,    # 0.1mm pen for fine lines

            "fill": True,       # Hatched fills via vsketch

        }
    },
    save_as="amsterdam.svg",
    show=False,
)

The penWidth parameter directly sets vsketch.penWidth(), enabling precise control over line weight without post-processing.

Preset and Style Integration

Plotter mode respects the same preset system as Matplotlib mode. The manage_presets() and override_params() functions (lines 1089‑1125) normalize style dictionaries before they reach plot_gdf(). This means:

  • Preset .json files work unchanged between modes
  • Color values (fc, ec) convert to vsketch-compatible stroke/fill specifications
  • Layer-specific overrides pass through transparently

Source File Reference

File Purpose Key Functions
prettymaps/draw.py Drawing engine with vsketch integration plot(), init_plot(), draw_layers(), plot_gdf()
prettymaps/__init__.py Public API exposure plot(), Subplot(), multiplot()
prettymaps/fetch.py OSM data retrieval get_osm_geometries()
app.py Streamlit interface with plotter support Wrapper calls to plot(mode="plotter")

Summary

  • Activate plotter mode by passing mode="plotter" to prettymaps.plot() or prettymaps.multiplot()
  • The vsketch backend creates clean SVG output without external dependencies, as implemented in prettymaps/draw.py
  • Pen characteristics are controlled via penWidth, stroke, and fill parameters in layer style dictionaries
  • Multiplot layouts render multiple maps on a single plotter canvas using shared Vsketch state
  • Output SVGs are ready for direct use with AxiDraw, Makelangelo, and other standard pen plotters

Frequently Asked Questions

What pen plotter hardware works with prettymaps output?

Any device that accepts standard SVG files works directly. The vsketch-generated SVGs use simple path elements without proprietary extensions, making them compatible with Evil Mad Scientist's AxiDraw, Marginally Clever's Makelangelo, and most other consumer plotters. No additional conversion software is required.

How do I control hatch patterns for filled areas?

Set fill=True in your layer style and rely on vsketch's default hatching behavior, or export with fill=False and manually add hatching in Inkscape or your plotter control software. The current plot_gdf() implementation delegates fill rendering entirely to vsketch's internal algorithms.

Can I mix Matplotlib and plotter outputs in the same script?

Yes. Each call to prettymaps.plot() is independent; specify mode="matplotlib" for preview and mode="plotter" for final vector output. The show=False parameter prevents window conflicts when alternating modes in Jupyter notebooks or automated pipelines.

Why is my SVG output in A4 landscape format?

init_plot() hardcodes vsk.size("a4", landscape=True) at lines 1012‑1013. For custom dimensions, fork the repository or patch prettymaps/draw.py to accept a paper_size parameter before the Vsketch initialization.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →