# Generating Output for Pen Plotters Using vsketch Plotter Mode in prettymaps

> Generate optimized SVG output for pen plotters using prettymaps plotter mode. Leverage the integrated vsketch engine for seamless plotter integration.

- Repository: [Marcelo de Oliveira Rosa Prates/prettymaps](https://github.com/marceloprates/prettymaps)
- Tags: how-to-guide
- Published: 2026-08-20

---

**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`](https://github.com/marceloprates/prettymaps/blob/main/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`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py)

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

```python
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:

```python
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:

```python
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:

```python
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:

```python
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`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) | Drawing engine with vsketch integration | `plot()`, `init_plot()`, `draw_layers()`, `plot_gdf()` |
| [`prettymaps/__init__.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/__init__.py) | Public API exposure | `plot()`, `Subplot()`, `multiplot()` |
| [`prettymaps/fetch.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/fetch.py) | OSM data retrieval | `get_osm_geometries()` |
| [`app.py`](https://github.com/marceloprates/prettymaps/blob/main/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`](https://github.com/marceloprates/prettymaps/blob/main/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`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) to accept a `paper_size` parameter before the `Vsketch` initialization.