# Geometric Transformation Options in prettymaps: Scale and Rotation Parameters Explained

> Discover how to use scale_x, scale_y, and rotation in prettymaps plot to resize, stretch, mirror, or rotate maps before rendering with Matplotlib.

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

---

**Use `scale_x`, `scale_y`, and `rotation` in `prettymaps.plot()` to resize, stretch, mirror, or rotate any map before Matplotlib renders it.**

The prettymaps library provides precise control over map geometry through three transformation parameters passed directly to the `plot()` function. These parameters leverage **Shapely's affine transformation** engine to manipulate every GeoDataFrame in the map—streets, buildings, water, and land-use layers—before any drawing occurs. Understanding these geometric transformation options in prettymaps unlocks creative possibilities from mirrored cityscapes to rotated artistic layouts.

## Scale Parameters: `scale_x` and `scale_y`

The scaling parameters control dimensional stretching along each Cartesian axis independently.

| Parameter | Type | Default | Effect |
|-----------|------|---------|--------|
| `scale_x` | `float` | `1` | Horizontal scaling: >1 enlarges, <1 shrinks, negative values flip horizontally |
| `scale_y` | `float` | `1` | Vertical scaling: >1 enlarges, <1 shrinks, negative values flip vertically |

When both parameters share the same value, the map maintains its aspect ratio while changing overall size. Different values produce non-uniform stretching that can emphasize particular geographic directions.

### Scaling Implementation in [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py)

The scaling operation occurs at lines 656–669 in [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py), where the geometry collection transforms via:

```python
collection = shapely.affinity.scale(collection, scale_x, scale_y)

```

This Shapely call applies the scaling matrix to all geometries simultaneously, preserving topological relationships between features.

### Uniform Scaling Example

Shrink a map to half its original size for overview compositions:

```python
import prettymaps as pm

pm.plot(
    "Porto Alegre",
    x=0, y=0,
    scale_x=0.5,
    scale_y=0.5,
    show=True,
)

```

### Non-Uniform Scaling Example

Stretch horizontally while compressing vertically to fit wide page formats:

```python
import prettymaps as pm

pm.plot(
    "Porto Alegre",
    x=0, y=0,
    scale_x=1.2,   # 20% wider

    scale_y=0.8,   # 20% shorter

    show=True,
)

```

### Mirroring with Negative Scale Values

Negative scale values produce reflection transformations across the specified axis:

```python
import prettymaps as pm

pm.plot(
    "Porto Alegre",
    x=0, y=0,
    scale_x=-1,    # horizontal mirror

    scale_y=1,
    show=True,
)

```

## Rotation Parameter

The `rotation` parameter controls angular orientation of the entire map geometry.

| Parameter | Type | Default | Effect |
|-----------|------|---------|--------|
| `rotation` | `float` (degrees) | `0` | Counter-clockwise rotation around the origin point (`x`, `y`) |

### Rotation Implementation in [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py)

Following the scaling step, rotation applies at lines 682–687:

```python
collection = shapely.affinity.rotate(collection, rotation, origin="center")

```

The rotation uses `"center"` as origin, meaning geometries rotate around their collective centroid rather than the coordinate (0,0). This prevents unexpected positional drift during transformation.

### Basic Rotation Example

Tilt a map 45 degrees counter-clockwise for diagonal presentation:

```python
import prettymaps as pm

pm.plot(
    "Porto Alegre",
    x=0, y=0,
    rotation=45,
    show=True,
)

```

## Complete Transformation Pipeline

According to the prettymaps source code, transformations execute in strict sequence for every map render:

1. **Translation** — map geometry moves to coordinates specified by `x` and `y`
2. **Scaling** — `scale_x` and `scale_y` apply via `shapely.affinity.scale()`
3. **Rotation** — `rotation` degrees apply via `shapely.affinity.rotate()`

This order matters: scaling occurs before rotation, so rotation angles remain geometrically intuitive regardless of stretch factors.

### Combined Transformation Example

Position, scale, rotate, and mirror in a single call:

```python
import prettymaps as pm

pm.plot(
    "Porto Alegre",
    x=5, y=10,           # translate to (5, 10)

    scale_x=0.7,         # shrink width

    scale_y=0.7,         # shrink height proportionally

    rotation=30,         # 30-degree counter-clockwise tilt

    show=True,
)

```

## Key Source Files for Transformation Logic

| File | Lines | Purpose |
|------|-------|---------|
| [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) | 656–669 | `scale_x`/`scale_y` parameter handling and scaling operation |
| [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) | 682–687 | `rotation` parameter handling and rotation operation |
| [`prettymaps/__init__.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/__init__.py) | — | Public `plot()` entry point forwarding arguments |
| [`tests/test.py`](https://github.com/marceloprates/prettymaps/blob/main/tests/test.py) | — | Unit tests validating transformation combinations |

The transformation parameters are defined and consumed entirely within [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py), making this the authoritative reference for geometric manipulation behavior.

## Summary

- **`scale_x`** and **`scale_y`** control independent axis scaling with negative values enabling mirroring
- **`rotation`** rotates the entire map counter-clockwise around its centroid in degrees
- Transformations apply to **all GeoDataFrames** (streets, water, land-use, buildings) before Matplotlib rendering
- The pipeline order is: translate → scale → rotate, as implemented in [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py)
- Shapely's `affinity.scale()` and `affinity.rotate()` perform the actual geometric mathematics

## Frequently Asked Questions

### Can I scale and rotate a prettymaps plot simultaneously?

Yes. Pass all desired parameters to `prettymaps.plot()`—the library applies scaling first, then rotation automatically. The transformations compose mathematically without requiring manual coordinate calculations.

### Why does negative `scale_x` flip my map horizontally?

Negative scaling factors multiply coordinate values by that factor, inverting their sign. A point at x=10 becomes x=-10 when `scale_x=-1`, creating a mirror image across the vertical axis. This behavior matches standard affine transformation mathematics.

### Does rotation occur before or after scaling in prettymaps?

Rotation occurs **after** scaling. In [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) lines 656–687, the code executes `shapely.affinity.scale()` on line 656, then `shapely.affinity.rotate()` on line 682. This sequencing ensures rotation angles describe the final oriented geometry, not pre-stretched coordinates.

### What units does the `rotation` parameter use?

Degrees. Positive values rotate counter-clockwise; negative values rotate clockwise. The rotation uses the geometry's center as origin, preventing positional drift that would occur if rotating around (0,0).