Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Feature]: Line labels try other places along the line, and sit a distance above or below it. Part 2

Open
#1,187 0 comments 0 reactions 0 assignees View on GitHub

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

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

enhancement
Before you start
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's dist and 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 a PlacedLabel does. 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:

  1. 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_labels straight from candidates. Nothing changes for labels with the option off.
  2. 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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from opengeos/RustGIS

All issues in opengeos/RustGIS

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.