Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b6fe5ea
render: support affine raster source crops
EthanOConnor Jul 16, 2026
f07bfbf
raster: share bounded asynchronous resources
EthanOConnor Jul 16, 2026
2e48681
raster: support direct image-to-map tiles
EthanOConnor Jul 16, 2026
c7deabc
imagery: add resolved source snapshot core
EthanOConnor Jul 16, 2026
c651eb4
imagery: add bounded shared tile transport
EthanOConnor Jul 16, 2026
a1c57bc
imagery: complete native online sources and OIC catalogs
EthanOConnor Jul 16, 2026
03ee2c3
imagery: smooth zoom transitions and bound screen extent
EthanOConnor Jul 17, 2026
5a6d243
render: fill exposed imagery during zoom handoff
EthanOConnor Jul 17, 2026
81b4a4c
imagery: retain requested overscan in screen scenes
EthanOConnor Jul 17, 2026
ede2810
imagery: redraw when cached screen window changes
EthanOConnor Jul 17, 2026
abfdd58
render: synchronize imagery geometry with view scale
EthanOConnor Jul 17, 2026
84895d0
imagery: preserve coverage across zoom levels
EthanOConnor Jul 17, 2026
19bf9e2
imagery: retain nearby zoom work for fallback
EthanOConnor Jul 17, 2026
bbb46d5
render: make imagery zoom handoff atomic
EthanOConnor Jul 17, 2026
faca0d4
Fix zoom limit overshoot and feedback
EthanOConnor Jul 17, 2026
9a529e2
render: streamline multi-layer raster admission
EthanOConnor Jul 18, 2026
d50c254
render: restore cosmetic baseline strokes
EthanOConnor Jul 18, 2026
f45e5d4
Merge modern tiled imagery foundation for map lifecycle workflow
EthanOConnor Jul 18, 2026
2d86cf9
Add connected Map Hub workflow
EthanOConnor Jul 18, 2026
def2681
Keep production assignments out of Mapper workspaces
EthanOConnor Jul 18, 2026
f6bc69d
Add Map Hub first-use connection flow
EthanOConnor Jul 18, 2026
be7645a
Orient Map Hub browsing around venues and events
EthanOConnor Jul 18, 2026
65ec938
Bound tiled raster viewport admission
EthanOConnor Jul 19, 2026
a15e6ad
Complete imagery action icon resources
EthanOConnor Jul 19, 2026
106a49b
Fix Map Hub cross-platform builds
EthanOConnor Jul 19, 2026
7bf734c
Fix Map Hub platform CI regressions
EthanOConnor Jul 19, 2026
a9ccec4
Disambiguate URL clearing across compilers
EthanOConnor Jul 19, 2026
15aabc1
Harden scheduler-sensitive network tests
EthanOConnor Jul 19, 2026
6e23d2e
Avoid reentrant network cancellation completion
EthanOConnor Jul 19, 2026
3941804
Queue network reply completion safely
EthanOConnor Jul 19, 2026
43176f8
Isolate delivery-bound test from timeouts
EthanOConnor Jul 19, 2026
6c54dee
Stabilize controlled network test fixtures
EthanOConnor Jul 19, 2026
71bfacc
Temporarily diagnose macOS network crash
EthanOConnor Jul 19, 2026
b30ee83
Serialize network integration tests
EthanOConnor Jul 19, 2026
b520618
Include Windows base types before credential API
EthanOConnor Jul 19, 2026
fee2f25
Materialize Windows credential target strings
EthanOConnor Jul 19, 2026
86b1bf9
Remove KMZ staging files through their owner
EthanOConnor Jul 19, 2026
dbb87fc
Use browser passkey setup for Map Hub accounts
EthanOConnor Jul 19, 2026
35d8b8a
Harden Map Hub connection workflows
EthanOConnor Jul 19, 2026
fd6aa30
Bound Map Hub tiles and retain native raster metadata
EthanOConnor Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ if(Mapper_WITH_COVE)
add_feature_info(Mapper_WITH_COVE ON "Contour line vectorization")
add_subdirectory(3rd-party/cove)
endif()
add_subdirectory(src/imagery)
if(Mapper_USE_GDAL)
add_subdirectory(src/gdal)
endif()
Expand Down
143 changes: 143 additions & 0 deletions doc/manual/pages/online-imagery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: Online imagery
keywords: Templates, Imagery, OIC, XYZ, TMS, ArcGIS
parent: Templates and Data
nav_order: 0.2
last_modified_date: 16 July 2026
---

Online imagery is a georeferenced raster template which loads only the tiles
needed for the current view or output. The map must be georeferenced, but it
does not need to be saved before imagery is added.

Open **Templates → Add online imagery…**, or use **Add template… → Add online
imagery…** in the template setup window.

## Choosing a source

The source browser lists sources from installed OpenOrienteering Imagery
Catalog (OIC) files. Search matches source names, descriptions, identifiers and
categories. Unsupported catalog entries remain visible with an explanation.

Selecting a source shows its catalog revision, imagery dates, coordinate
reference system, zoom range, request hosts, attribution and terms. The
template name may be changed without changing the catalog source identity.

When the source is added, Mapper stores a complete, checksummed source snapshot
inside the map. Updating or removing the installed catalog does not silently
change an existing map.

## Entering a URL

Choose **Enter a tile or service URL…** to add a source which is not in a
catalog.

Direct tiled sources use an HTTP or HTTPS URL containing all three
`{z}`, `{x}` and `{y}` placeholders. The documented `${z}`, `${x}` and `${y}`
spellings are accepted and normalized. Advanced settings make the row scheme
(XYZ or TMS), zoom range, 256 or 512 pixel tile size, HTTP Referer, empty-tile
status codes and attribution explicit.

Cached ArcGIS MapServer and ImageServer links are checked by reading their
published `f=pjson` metadata. Mapper derives the tile grid, levels, origin,
coordinate reference system, format and endpoint from the service rather than
assuming Web Mercator or a fixed zoom range.

WMS, WMTS and remote GeoTIFF links are recognized but are not currently
executed by the native tiled raster template. Mapper reports them as
unsupported instead of guessing an incompatible source configuration.

## Catalogs

Choose **Manage catalogs…** to import, update or remove OIC catalogs.

Before installation, Mapper shows:

- catalog identity, revision, publisher, origin and document SHA-256;
- added, removed, operationally changed and metadata-only source counts;
- usable, invalid and unsupported source counts;
- request hosts and duplicate-source counts;
- warnings for downgrade, republished revisions, HTTP, local-network
endpoints, registration corrections and credential-like query parameters.

Catalog updates use ETag and Last-Modified validators when available. An
interrupted update cannot replace the current catalog with a partial file, and
the previous snapshot is retained for recovery.

## Network privacy and credentials

Cookies and HTTP authentication are not used for imagery requests. Redirects,
response sizes and timeouts are bounded. HTTPS-to-HTTP redirects are rejected.

Private and local-network origins require an explicit permission stored only
on the current installation. A catalog or map file cannot grant this
permission. This includes private, shared, link-local, documentation,
benchmarking and other special-purpose address ranges, whether written
directly in a URL or returned by DNS.

Choose **Templates → Imagery network permissions…** to review or revoke saved
permissions. The same dialog lists origins from requests Mapper blocked after
DNS resolution; approving one is always a deliberate user action. Merely
opening a map may add a blocked origin to the review list, but never grants it
network access or opens a permission prompt.

Mapper's hostname preflight is defense in depth: Qt's network stack performs
its own connection-time resolution, so operating-system firewall and network
policy remain the hard isolation boundary.

URLs containing token-like query parameters are not added to a recent-sources
list. Mapper warns before embedding the complete endpoint in the map. Anyone
who can read that map file may be able to read the endpoint, including its
query parameters.

## Screen extent and zooming

On screen, imagery is clipped to the map's drawn-object extent with 20 percent
padding on every side, and tiles wholly outside that area are not requested.
This keeps a broad service coverage area from changing **Zoom entire map** or
using cache space far beyond the working map. A map with no drawn objects falls
back to the source's published tile extent.

Before each screen frame, Mapper publishes the current view and zoom to every
visible imagery source. Cached parent tiles fill zoom-in transitions; cached
child tiles fill zoom-out transitions while the new level loads. The
already-requested one-tile safety ring is retained around the viewport. Both
fallback directions reuse source pixels but rebuild raster geometry for the
current zoom, so Mapper does not stretch an older reprojected scene whose
approximation was calculated for a different scale.

## Offline use

Enable **Templates → Work offline for imagery** to prevent network access and
use only tiles already present in the local HTTP cache. Turning offline mode
off allows missing tiles to be requested again.

Referer-dependent imagery is not retained in the shared offline cache because
serving it later without the original request context can be incorrect.

## Printing and export

Screen display may temporarily use cached tiles from an adjacent level while
the requested level loads. Print, PDF, image and KML/KMZ output do not use
provisional level fallback.
Mapper prepares the exact requested source level before opening the output
paint engine. A missing or permanently failed tile stops exact output with an
error instead of silently producing an incomplete map.

Large translucent output is prepared as bounded, non-overlapping atlas chunks.
Chunk sizes account for both source and reprojected output geometry, and
neighbor pixels are sampled before each chunk is cropped to its own coverage.
This retains seam-free alpha blending without requiring one page-sized raster
allocation. Exact preparation also reserves the renderer snapshot memory it
will need before reporting that output is ready.

Exact-imagery preparation and multi-tile KML/KMZ export can be canceled. A
user cancellation is reported as canceled rather than as a rendering failure.
Incomplete staged PDF, image and KMZ files are discarded. Image exports with
a world file use a destination lock, recovery journal and old-image backup; if
the two-file commit is interrupted, Mapper restores the matching old pair or
finishes cleanup before the next export. Direct KML image sidecars are
published through a unique asset directory; unreferenced directories left by
a process interruption are recovered on the next export. Interrupted KML/KMZ
staging files are scoped to their absolute destination and safely removed when
that destination is exported again.
4 changes: 3 additions & 1 deletion doc/manual/pages/templates-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ has_children: true
[Introduction to Templates](templates.md){: .subpage}
Types of templates, loading and positioning

[Online imagery](online-imagery.md){: .subpage}
Streaming tiled imagery and OIC catalogs

[Adjusting template positions](template_adjust.md){: .subpage}
For non-georeferenced templates

Expand All @@ -17,4 +20,3 @@ Vectorizing line features in raster graphics templates.

[Geospatial data](gdal.md){: .subpage}
Geospatial raster data and vector data support based on GDAL.

4 changes: 3 additions & 1 deletion doc/manual/pages/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ OpenOrienteering Mapper supports the following file formats to be loaded as temp
- [Raster images](#image-templates) (bmp, jpg, png, gif and [formats supported by GDAL](gdal.md))
- Geospatial vector data (cf. [geospatial data support with GDAL](gdal.md))
- [GPX tracks](#track-templates) (gpx)
- [Map files](#map-templates) (omap, xmap, ocd)
- [Map files](#map-templates) (omap, xmap, ocd)
- [Online imagery](online-imagery.md) (OIC catalog sources, XYZ/TMS tiles and
cached ArcGIS services)


Additionally, templates can be classified into **georeferenced** and **non-georeferenced** templates. For georeferenced templates, information about the exact positioning of the template in a known world coordinate system is available - see [georeferencing](georeferencing.md). This way, they can be positioned on the map automatically provided that the map is georeferenced too. For non-georeferenced templates, this information is not available, so they have to be [positioned manually](#positioning).
Expand Down
26 changes: 23 additions & 3 deletions doc/manual/pages/templates_menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,29 @@ last_modified_date: 20 January 2018
Switches the display of the [template setup window](templates.md#setup) on the map screen. This provides access to the functions required to open, scale, and position a template, and to close it.


---

#### Open template...
---

#### Add online imagery...

Opens the [online imagery source browser](online-imagery.md). Sources may come
from installed OIC catalogs, a direct XYZ/TMS URL, or a cached ArcGIS service.


#### Manage imagery catalogs...

Imports, reviews, updates and removes OIC catalogs. Existing maps keep their
embedded source snapshots when a catalog changes.


#### Work offline for imagery

Prevents imagery network access and uses only tiles already present in the
local cache.


---

#### Open template...

Opens a template file directly without going through the setup window.

Expand Down
3 changes: 3 additions & 0 deletions doc/modernization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ The modernization foundation was completed and published at
are historical design and verification context. The architecture and product
scenarios below remain current guidance for descendants of the tag.

Product descendants add their own focused contracts. The map-lifecycle branch
is documented in the [connected Map Hub workflow](map-hub-workflow.md).

## Scope

This is pure modernization. There is no feature work in this campaign. GNSS,
Expand Down
105 changes: 105 additions & 0 deletions doc/modernization/map-hub-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Connected Map Hub workflow

Mapper remains a complete standalone editor. The connected workflow adds a
server-backed lifecycle around an ordinary native `.omap` file; it does not
replace `.omap`, embed a database document in it, or weaken OCAD import/export.

## User flow

1. Open **Map Hub** and enter the HTTPS server. An invitation opens account
setup in the system browser, where passkey creation is the default and a
password remains available. Copy the one-time Mapper connection token back
into Mapper; it is stored in the operating-system credential store. A
previously issued Mapper API token can be pasted directly instead.
2. Open **Map Hub — library and my work** from the home screen, File menu, or
toolbar. The two views show the current library and assignments for the
connected account. Library records expose the exact approved revision and
checksum, but never open a detached editable copy; editing starts from an
assigned managed workspace. Course-design and print-production assignments
remain visible, but are managed in Map Hub instead of being opened as map
workspaces; Purple Pen remains the producer of their course files and PDFs.
3. Starting an assignment asks the server for the current workspace and, when
required, an exclusive editing lease. Mapper downloads the approved base to
a new local workspace, verifies its SHA-256 before opening it, and
synchronizes project-authorized raster tile layers into the immutable OIC
catalog store. A native OMAP base remains OMAP. An OCAD base is preserved
byte-for-byte beside a normalized native `.omap` editing workspace.
4. Normal Save is always local and offline-capable. **Checkpoint to Map Hub**
saves first, uploads the exact native `.omap`, supplies the exact base
revision and a stable idempotency key, and records the returned immutable
revision. A stale base never overwrites local work.
5. **Submit for review** checkpoints if necessary, submits that exact revision,
and releases the editing lease. Approval remains a server-side librarian or
director action.
6. **New connected map** captures one or more venues, predecessor lineage,
work type, assignee, source provenance, target CRS/scale/symbol standard,
and exclusive-editing policy. It creates the database project, work
package, assignment, and server workspace first. Only after the idempotent
server transaction succeeds does Mapper create and save the local `.omap`.
Mapper locks the required scale, configures and validates the CRS, and
restricts installed symbol-set choices to the required standard (with an
explicit confirmation for a custom symbol file) before binding the file.

## Local records and credentials

Managed-workspace records live under Qt's application data directory in
`managed-workspaces/`, addressed by the canonical local map path. They contain
stable organization/project/work-package/workspace/revision IDs, checksums, and
lease expiry, but no bearer secret. They are app-private sidecars, not siblings
of the map, so exporting or emailing an `.omap` does not disclose lifecycle
state.

The account token and each workspace lease use macOS Keychain, Windows
Credential Manager, or an Android Keystore-backed encrypted value. Linux uses
Secret Service when `secret-tool` is available; minimal Unix systems use an
explicit owner-only application credential file fallback. Tokens are never
stored in QSettings, URLs, imagery catalogs, or map documents.

Map Hub can register an in-memory bearer credential for its exact tile origin.
The tiled network scheduler sends it only to that exact origin, strips it on a
cross-origin redirect, and bypasses the shared HTTP disk cache for authenticated
requests. Project manifests containing credential-like tile URL query fields
are rejected instead of being persisted.

## API contract used by Mapper

- `GET /api/v1/library`
- `GET /api/v1/projects/{project_id}/manifest`
- `POST /api/v1/projects` with `Idempotency-Key`
- `POST /api/v1/assignments/{assignment_id}/start`
- `GET /api/v1/artifacts/{artifact_id}/download`
- `POST /api/v1/workspaces/{workspace_id}/checkpoint` with
`Idempotency-Key`, exact `base_revision_id`, and `X-Editing-Lease` when
exclusive
- `POST /api/v1/workspaces/{workspace_id}/renew`
- `POST /api/v1/revisions/{revision_id}/submit` with `X-Editing-Lease` when
exclusive
- `POST /api/v1/invites/redeem`

All protected calls use `Authorization: Bearer …`; Mapper accepts a non-TLS
server only on localhost for development. JSON responses are capped at 8 MiB;
map transfers are capped at 2 GiB and every download write and final checksum
must succeed before Mapper opens the artifact.

## Public event-map render

`mapper-map-render` is the headless companion for freezing an approved event
revision into the feedback workflow:

```sh
mapper-map-render event.omap event-map.png event-map.json
```

It accepts native OMAP and imported OCAD maps with usable georeferencing. The
saved print area is the output boundary. The PNG contains map objects only—no
authoring helper symbols, templates, or street basemap. The JSON manifest
records the exact source and image SHA-256 values, pixel dimensions, render
resolution, boundary kind, and the four WGS84 image corners in top-left,
top-right, bottom-right, bottom-left order. Map Hub verifies that manifest
against the frozen revision before it exposes the image through an
event-specific feedback capability URL.

The default output's longest edge is 4096 pixels. Use `--max-dimension` for a
different bounded size or `--pixels-per-mm` for a fixed render resolution; no
dimension may exceed 16384 pixels. The tool selects Qt's offscreen platform
automatically when no platform was configured.
Loading
Loading