Releases: sgraaf/papermap
2026.1.0
Highlights
This first major release in the year 2026 features comprehensive geodetic coordinate conversion support, a massive expansion of tile providers, and significant architectural improvements.
The new geodesy module implements high-precision coordinate conversions between geographic (lat/lon), UTM, MGRS, and ECEF coordinate systems using Karney (2011) and Bowring (1985) algorithms. The tile provider ecosystem has grown from 20+ to over 100 providers, including OpenStreetMap variants, Stadia Maps, CartoDB, ESRI, NASA GIBS, and regional providers. The HTTP client has been modernized by migrating from requests to httpx, and tile downloads now gracefully handle failures by default. This release also drops support for Python 3.7-3.10 and adds support for Python 3.12-3.14.
Full Changelog
Added
- Added new
geodesymodule for comprehensive coordinate conversions between different coordinate systems:- Geographic coordinates (latitude/longitude in WGS84)
- UTM (Universal Transverse Mercator) coordinates
- MGRS (Military Grid Reference System) coordinates
- ECEF (Earth-Centered, Earth-Fixed) Cartesian coordinates
- Added public API functions for coordinate conversions (exported from
papermappackage):latlon_to_utm()- Convert geographic coordinates to UTMutm_to_latlon()- Convert UTM coordinates to geographiclatlon_to_mgrs()- Convert geographic coordinates to MGRSmgrs_to_latlon()- Convert MGRS coordinates to geographiclatlon_to_ecef()- Convert geographic coordinates to ECEF Cartesianecef_to_latlon()- Convert ECEF Cartesian to geographicformat_latlon(),format_utm(),format_mgrs(),format_ecef()- Format coordinates as human-readable strings
- Added coordinate type classes:
LatLonCoordinate,UTMCoordinate,MGRSCoordinate,ECEFCoordinate(NamedTuples) - Added
Ellipsoiddataclass for reference ellipsoid parameters withWGS_84_ELLIPSOIDconstant - Added
PaperMap.from_utm()classmethod to create a PaperMap instance from UTM coordinates - Added
PaperMap.from_mgrs()classmethod to create a PaperMap instance from MGRS coordinates (supports both MGRSCoordinate objects and MGRS strings) - Added
PaperMap.from_ecef()classmethod to create a PaperMap instance from ECEF coordinates - Added
mgrs, andecefCLI sub-commands to generate paper maps from MGRS and ECEF coordinates, respectively - Added
--strictflag to CLI andstrict_downloadparameter toPaperMapclass to control tile download failure behavior. By default (strict=False), PaperMap now allows graceful degradation when some tiles fail to download, rendering failed tiles as background color and issuing a warning. When strict=True, the previous behavior is maintained where any tile download failure raises an exception. - Added new
tile_providerssubpackage with provider-based organization for improved maintainability - Added 100+ new tile providers from various providers including:
- OpenStreetMap regional variants (DE, CH, France, HOT, BZH)
- Stadia Maps (including Stamen styles: Toner, Terrain, Watercolor)
- CartoDB/Carto (Positron, Dark Matter, Voyager)
- Esri (WorldStreetMap, WorldImagery, WorldTopoMap, and more)
- HERE Maps (requires API key)
- USGS (USTopo, USImagery)
- NASA GIBS (satellite imagery)
- MapTiler (requires API key)
- Jawg Maps (requires API key)
- TomTom (requires API key)
- CyclOSM (bicycle-oriented maps)
- OpenSeaMap (nautical charts)
- Waymarked Trails (hiking, cycling, MTB, slopes, riding, skating)
- Regional providers: BasemapAT (Austria), NLMaps (Netherlands), SwissFederalGeoportal
- And many more specialty maps
- Added support for Python 3.12, 3.13 and 3.14.
Changed
- Improved coordinate conversion accuracy by implementing Karney's (2011) series expansion of the Transverse Mercator projection for UTM conversions, achieving sub-millimeter accuracy
- Refactored coordinate conversion functions from
utils.pyinto the newgeodesymodule with improved implementations:- Replaced
spherical_to_utm()andutm_to_spherical()withlatlon_to_utm()andutm_to_latlon()using high-accuracy Karney (2011) algorithms - Replaced
spherical_to_cartesian()andcartesian_to_spherical()withlatlon_to_ecef()andecef_to_latlon()using Bowring (1985) iterative method - Consolidated angle wrapping functions (
wrap(),wrap90(),wrap180(),wrap360()) intowrap_angle(),wrap_lat(), andwrap_lon()
- Replaced
- Migrated from
requeststohttpxfor HTTP client functionality, utilizing modern features such as improved connection pooling and timeout handling - Refactored tests to use
pytest-httpxfor cleaner and more maintainable HTTP mocking - Reorganized package structure by consolidating
defaults.py,constants.py, andtyping.pyinto their logical homes:- Tile provider configurations moved to new
tile_providerssubpackage - Paper sizes and default values moved to
papermap.py - Geodetic coordinate conversion functions and constants moved to new
geodesymodule
- Tile provider configurations moved to new
- Renamed
TileServerclass toTileProviderand enhanced it with new properties:- Added
keyproperty for tile provider key (lowercase with dashes) - Added
nameproperty for tile provider display name - Added
html_attributionproperty for HTML-formatted attribution with hyperlinks - Added
boundsproperty for geographic bounds (optional) - Renamed
mirrorstosubdomainsfor better clarity - Renamed
mirrors_cycletosubdomains_cycle - Updated URL template placeholders:
{zoom}→{z},{mirror}→{s},{api_key}→{a}
- Added
- Renamed some tile providers for consistency
- Refactored
PaperMap.__init__method into smaller, focused private methods to improve readability and testability:- Extracted coordinate validation into
_validate_coordinates - Extracted tile provider setup into
_validate_and_set_tile_provider - Extracted paper size configuration into
_validate_and_set_paper_size - Extracted zoom calculations into
_compute_zoom_and_resize_factor - Extracted image dimension calculations into
_compute_image_dimensions - Extracted tile initialization into
_initialize_tiles - Extracted PDF initialization into
_initialize_pdf
- Extracted coordinate validation into
- Renamed
PaperMaptopapermap(purely aesthetically, no changes in installation or usage required).
Removed
- Removed support for Python 3.7, 3.8, 3.9 and 3.10.
- Removed
papermap.defaults,papermap.constants, andpapermap.typingmodules (contents redistributed to other modules)
0.3.0
0.3.0 (2022-11-09)
This is a pretty big release with a completely overhauled codebase. For this, I used my new cookiecutter-python-package Python package template. As such, this release comes with much higher code quality, documentation, automation and some important changes to the core functionality of PaperMap.
Changes
- Completely refactored codebase, with:
- Added documentation via Read the Docs
- Added CI/CD via GitHub Actions
- Added pre-commit hooks w/ CI-integration
- Switched to Click for the CLI
- Switched to flit for building & releasing the package
papermap v0.2.2
Added support for custom fonts.
papermap v0.2.1
Another reformat
papermap v0.1.1
Initial release of papermap: v0.1.1