[Feature]: Line labels try other places along the line, and sit a distance above or below it. Part 2
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- rust
- Domain
- computer-graphics
Research direction
Start in crates/render/src/lib.rs with line_labels::Line and longest_on_screen to see how candidates are placed. Read #995 and #1011 for context, then extend Candidate::alternatives to carry PlacedLabel-style places. Run place_labels and budget_tests.rs; done means line labels try other positions with distance option and old projects label unchanged.
Written by the indexing model from the issue text.
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 2 of #995. A label along a line (Parallel or Curved) is tried at one place only: the middle of the line's longest stretch in view (longest_on_screen and line_labels::Line, crates/render/src/lib.rs). If that place collides with another label, the label is dropped, even when the rest of the line is free. A curved label is also dropped where the line bends too sharply at its middle (more than 25° between characters, line_labels::MAX_TURN), even if the line is straight a little further on. On a map of roads or rivers, many lines end up with no name that ArcGIS Pro and QGIS would label.
A line label also always sits on the line. QGIS's distance from the line (dist, above or below it) has nothing to map onto, so the QGIS importer notes it as not read (as agreed with @pick2510 in #995, this step takes it).
Proposed solution
Other places along the line, with the option #1011 added.
- The label class's "Try other positions when it doesn't fit" (
other_positions, off by default, from #1011) also applies to line labels: with it on, a Parallel or Curved label tries the middle first, then places either side of it along the same stretch, nearest first (at most 8). - The first place where the label fits, and for a curved label where it can bend, wins. If none does, the label is unplaced, and View Unplaced shows it once, at the middle.
- With the option off, labels are placed exactly as today, so a saved project looks the same.
- A line repeated every so many points (#1014) keeps its repeats as they are: each repeat is already a place of its own, so repeats get no alternatives.
A distance from the line.
- A new label class setting, the distance (points) from the line, with Above or Below. 0 is on the line, as today.
- With "Try other positions" on and a distance set, the other side of the line is tried too (above, then below, or the other way round).
#[serde(default)]and left out when saved at 0, as in #964. The importer can then map QGIS'sdistand its above/below line flags onto it.
How it works:
- Alternatives become places, not just points. Today a candidate's alternatives are screen points (
Candidate::alternatives: Vec<(f32, f32)>). A place along a line also needs its angle (Parallel) or its characters' turns (Curved), so each alternative carries the position, angle and glyphs, as aPlacedLabeldoes. Point labels use them without angle or glyphs. - The turned and tilted views and the extrusion and terrain lifts already move a candidate's alternatives with it. They move the new places the same way, glyphs included.
- A label still counts once against the candidate caps, and the tilted view's rules for one candidate per key are unchanged.
- The label lock keeps which place won (the key and the alternative's index, as for points), so a locked line label doesn't slide along the line when the map moves.
- Curving is the expensive part: each curved place lays out its characters again. Places are laid out only when the one before doesn't fit, and the budget tests (
budget_tests.rs) measure a dense view of curved labels. - Callouts (#1128) don't move labels along lines, so the two don't meet.
In the UI: the existing checkbox in the Labeling pane's Position tab, now also for Parallel and Curved. A distance box with Above / Below next to it, shown for line placements. labels.placement takes the distance as it takes the other position settings. No ribbon control (see #862).
Two PRs:
- Render: places as alternatives, places along the line for line labels with the option on, the turned / tilted / lifted paths and the lock, with tests on
place_labelsstraight from candidates. Nothing changes for labels with the option off. - Model and UI: the distance from the line (setting,
labels.placement, Position tab, docs) and the other side as an alternative, with a test that an old project opens and labels the same.
Tests:
- a line label whose middle is taken is placed at the next free place along the line, and is dropped as today with the option off;
- a curved label at a sharp bend at the middle is placed further along;
- repeats are unchanged;
- the same labels in a turned and a tilted view;
- a locked line label stays at the place it won;
- a label above the line by its distance, and below it when above is taken;
- an old project file gives the same labels.
Estimated scope
Medium: a broader feature that is feasible in a reasonable timeframe
Alternatives considered
- Each place as a candidate of its own, with the same key. The same reasons as in #1011: eight places per line fill the candidate caps and change which labels survive, and tilted views keep one candidate per key.
- Choosing the best place along the line by cost (straightness, distance from the middle, as Maplex does). It gives better spots, but needs a cost model before there is a mechanism to use it. The order "middle first, then nearest either side" is the same as today when the middle fits, and a cost can reorder the places later without changing the model.
- A separate option for lines. One option per class is easier to explain: "try other positions" means round a point for points and along the line for lines.
- On by default. Existing maps would change: a label taking another place can take the spot another label uses today.
- Dominant language
- Rust
- Stars
- 1.9k
- Forks
- 268
- Avg merge
- 3h 37m
- Merged PRs (30d)
- 818
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from opengeos/RustGIS
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
[Feature]: Join Field: match a text key with a number key, so Census tables join to TIGER tractsPossibly taken @PawelKra claimed this today. Openenhancement
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
opengeos/RustGIS#1175 · 2 reactions ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 65/100
Maintainers usually reply within 1 day
All issues in opengeos/RustGIS
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
penso/herdr-gpui#934 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Y-ASLant/ElegantClipboard#178 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
linxiv-dev/linXiv#384 · 1 comment ·
Maintainers usually reply within 1 day
-
priority middle
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
KATO-Hiro/AtCoderClans#12945 ·
Maintainers usually reply within 1 day
-
bug drawings ui
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
userFRM/egui-charts#1595 ·
Maintainers usually reply within 1 day