Skip to content

Keep zoom() at top level in route-stop circle expressions (#1927)#1929

Merged
bmander merged 1 commit into
mainfrom
fix/1927-maplibre-zoom-expression
Jul 17, 2026
Merged

Keep zoom() at top level in route-stop circle expressions (#1927)#1929
bmander merged 1 commit into
mainfrom
fix/1927-maplibre-zoom-expression

Conversation

@bmander

@bmander bmander commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Fixes #1927

Problem

After the MapLibre 11 → 13 upgrade, MapLibreRouteStopCircleLayer fails runtime style-expression validation at launch:

zoom expression may only be used as input to a top-level step or interpolate expression

The layer built a zoom()-driven radius interpolation once, then wrapped that whole interpolation inside product() to derive two properties:

  • the outer circle's circleStrokeWidth (radius × stroke/radius ratio)
  • the selected-stop inner circle's circleRadius (radius × inner scale)

MapLibre 11.5.2 tolerated a zoom() nested inside product(); 13.3.1 rejects it. The top-level circleRadius() interpolation still validated, so only those two nested usages broke — route-stop circles rendered without their stroke ring, and selected stops lost their zoom-scaled radius highlighting.

Fix

radiusExpression(scale) now folds the scale factor into each interpolation stop output rather than wrapping the interpolation:

interpolate(linear(), zoom(),
    stop(START, get(prop) × scale),
    stop(END,   get(prop) × scale))

zoom() stays at the top level (valid). Because the interpolation is linear, scaling each endpoint is mathematically identical to scaling the whole interpolation — including the clamped regions outside the zoom band. The default scale = 1f reproduces the original bare-get() outputs for the outer radius.

Testing

  • ✅ Compiles clean under the CI gate: ./gradlew :onebusaway-android:compileObaMaplibreDebugKotlin -PwarningsAsErrors=true
  • This is a MapLibre-runtime style-validation bug with a purely visual symptom, so there is no unit-test surface. Confirming the rendered result (logcat clear of the validation error, stroke rings present, selected-stop highlight scaling with zoom) requires launching the obaMaplibreDebug build on a device.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved map stop-circle rendering across zoom levels.
    • Updated stop markers and outlines to maintain more consistent sizing and proportions as the map scale changes.
    • Improved visual alignment between the outer stop circle, inner circle, and border.

MapLibre 13.3.1 rejects a zoom() expression nested inside anything but a
top-level step/interpolate ("zoom expression may only be used as input to
a top-level step or interpolate expression"). The route-stop circle layer
wrapped its zoom()-driven radius interpolation in product() to derive the
outer stroke width and the selected inner-circle radius, so those two
layers failed validation under MapLibre 13 — circles lost their stroke
ring and selected stops lost zoom-scaled highlighting. MapLibre 11.5.2
tolerated the nesting.

Fold the scale factor into each interpolation stop's output instead of
wrapping the whole interpolation, keeping zoom() at the top level. For a
linear interpolation, scaling each endpoint is mathematically identical to
scaling the interpolation, including the clamped regions outside the band.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 80859534-491f-440d-82c3-159563fddba9

📥 Commits

Reviewing files that changed from the base of the PR and between 6c71ddd and e75915a.

📒 Files selected for processing (1)
  • onebusaway-android/src/maplibre/java/org/onebusaway/android/map/maplibre/MapLibreRouteStopCircleLayer.kt

📝 Walkthrough

Walkthrough

The route-stop circle layer now applies outer stroke and inner-circle scaling within interpolation stop outputs, preserving a top-level zoom() expression for MapLibre radius and stroke-width properties.

Changes

Stop-circle expression scaling

Layer / File(s) Summary
Parameterized radius expressions
onebusaway-android/src/maplibre/.../MapLibreRouteStopCircleLayer.kt
radiusExpression accepts an optional scale and applies it to interpolation outputs; outer radius, stroke width, and inner radius properties use the parameterized expression.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: keeping zoom() top-level in route-stop circle expressions.
Linked Issues check ✅ Passed The change folds scale into interpolation stops and preserves top-level zoom(), matching issue #1927's required fix.
Out of Scope Changes check ✅ Passed The PR is limited to the MapLibre route-stop circle expression refactor and stays within the linked issue's scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1927-maplibre-zoom-expression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@bmander
bmander merged commit 4e3dcec into main Jul 17, 2026
3 checks passed
@bmander
bmander deleted the fix/1927-maplibre-zoom-expression branch July 17, 2026 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MapLibre 13 rejects route-stop circle-radius/circle-stroke-width expressions (zoom nested in product); circles lose stroke ring

1 participant