Repository navigation
[Feature]: Point labels try other positions around the point when the chosen one collides #1011
Description
Before you start
- I searched the existing issues and the roadmap and did not find a duplicate request.
What problem does this solve?
Step 1 of #995. A point label is tried at one position only, the one its label class chooses (Above Right, say). If that position collides with another label, the label is dropped, even when there is room on the other side of the point. On a busy map of towns or stations, many labels are left out that ArcGIS Pro and QGIS would place.
In the code, each feature and class gives one candidate (type Candidate, crates/render/src/lib.rs), already set at its position. place_labels places it if it fits and otherwise moves on.
The QGIS importer feels this too: QGIS's "around point" and "cartographic" placements are imported as Automatic (crates/map/src/qgis/labels.rs), because there is nothing to map their choice of position onto.
Proposed solution
An option on the label class, "Try other positions when it doesn't fit", off by default.
- With it on, a point label tries the class's position first, then the others around the point, in QGIS's cartographic order: Above Right, Above Left, Below Right, Below Left, Right, Left, Above, Below (each tried once, the chosen one first). Automatic and Centered start at their own position, then go through the same list.
- The first position that fits wins. If none fits, the label is unplaced, and View Unplaced shows it once, at the chosen position.
- Lines and polygons are labelled as today: candidates along lines are step 2, inside and outside polygons step 4.
- Off by default, because placement is greedy: a higher-priority label taking another position can take the spot a lower-priority label uses today. With the option off, a saved project looks exactly as it does now. The new setting is
#[serde(default)]and left out when saved off, as in feat(labels): a halo's own colour and width, and letter spacing, as QGIS's buffer and spacing #964.
How it works:
- The other positions travel inside the one candidate as alternatives, not as candidates of their own. The turned and tilted views and the extrusion and terrain lifts already move a label's icon along with its text; they move the alternatives the same way.
- A label still counts once against the candidate caps (40,000 / 20,000).
- The tilted view's "one candidate per key" rule still holds.
place_labelstries the label's position and then each alternative against the grid, in order. The sort stays stable, so the same map and view always give the same labels.- The label lock keeps which position won (
Map::label_lockholds the key and the alternative's index), so a locked label doesn't jump when the map moves. - In the UI, a checkbox in the Labeling pane's Position tab (feat(labels): the Labeling pane in a tab per topic, the map's settings left to the ribbon #917), next to the position. No ribbon control (see How should the ribbon be organised? A look at what's there today #862).
- An engine command to set it, as for the other class settings, so scripts and the Python API can use it.
Two PRs:
- Render: alternatives in the candidate,
place_labels, the turned / tilted / lifted paths and the lock, with tests onplace_labelsstraight from candidates. Nothing changes for users yet. - Model and UI: the class setting, the order of positions, the engine command, the pane checkbox, and a test that an old project opens and labels the same.
Once it is in, the QGIS importer can map "around point" and "cartographic" to Automatic with the option on (@pick2510).
Tests: a point whose chosen position is blocked is placed at the next free one; with the option off, it is dropped as today; the same labels in a turned and a tilted view; a locked label stays at the position it won; an old project file gives the same labels.
Estimated scope
Medium: a broader feature that is feasible in a reasonable timeframe
Alternatives considered
- Each position as a candidate of its own, with the same key. Simpler in
place_labels, but eight candidates per point reach the 40,000 cap with 5,000 points and change which labels survive. They also collapse in tilted views, which keep one candidate per key, and need de-duplicating in View Unplaced and in the lock. - On by default. More labels on every map at once, but existing projects would change: labels placed today could move or disappear behind a label that took another position.
- ArcGIS Pro's Standard engine priority matrix (a rank per position, 0 for never). More control, more UI. The fixed order covers the common case, and a matrix can replace the order later without changing the model of alternatives.
Activity