Skip to content

shorter URL with flex polyline and compressed names/custom_model#453

Open
karussell wants to merge 5 commits into
masterfrom
shorter_url
Open

shorter URL with flex polyline and compressed names/custom_model#453
karussell wants to merge 5 commits into
masterfrom
shorter_url

Conversation

@karussell
Copy link
Copy Markdown
Member

@karussell karussell commented May 20, 2026

Try here.

Especially for many way points or with a custom_model the URL length can get very long. This change uses the flex polyline algorithm from HERE to reduce length for point= (starting with 4 points) and creates a new parameter fpolyline. It also compresses the text of the points and the custom model parameter.

E.g. with 7 points the following URL with 147 characters:

fpolyline=BGqgunhDgwkhVzk5C-2gGrw5B4tqDu3xBqh5YzlwJlt0Jj5-E3pN9sjFhrkD&cnames=cy1KKy0q0VEIySgtysxLz0zUUXBPLcpNzKvU0tLySs1LxCEFAA&profile=car&l=oms

is equivalent to this URL with 283 characters:

point=50.977797%2C11.028736_Erfurt%2C+Thuringia%2C+Germany&point=50.932155%2C11.127407&point=50.902709%2C11.181899&point=50.928172%2C11.587936_Jena%2C+Thuringia%2C+Germany&point=50.772434%2C11.430029&point=50.691136%2C11.423217&point=50.607473%2C11.37184&profile=car&layer=Omniscale

Or here for a simple custom model that uses an area (210 vs. 444 chars):

cmodel=bY3BCoMwDIbfJeciK1MEr4Odd5ciVaMEqpEaD0V8d0s32AZCLt-fP192WDyxJwlQ1TvQABXQ3HQs0m4rKJg2J7S40LSxATc4jALr0a5Q7SBhwZg-0crm8cHOYSfEc7wb3tmatP-9uKU-4vfJiDyh-PDjfLELYzJ1zL6n2UqS1bXOs7tWhc7KwqhE-QWVH9IXVBhjjiPOCQ
custom_model=%7B%22priority%22%3A%5B%7B%22if%22%3A%22in_cottbus%22%2C%22multiply_by%22%3A%220%22%7D%5D%2C%22areas%22%3A%7B%22type%22%3A%22FeatureCollection%22%2C%22features%22%3A%5B%7B%22type%22%3A%22Feature%22%2C%22id%22%3A%22cottbus%22%2C%22geometry%22%3A%7B%22type%22%3A%22Polygon%22%2C%22coordinates%22%3A%5B%5B%5B14.31%2C51.75%5D%2C%5B14.34%2C51.75%5D%2C%5B14.34%2C51.77%5D%2C%5B14.31%2C51.77%5D%2C%5B14.31%2C51.75%5D%5D%5D%7D%7D%5D%7D%7D

For smaller custom models that just exclude the motorway it is still a nice improvement (95 vs. 122):

cmodel=q1YqKMrML8osqVSyiq5WykxTslIqyk9MiU_OSSwutrX19Q_xDwp3jFTSUcotzSnJLMipjE8CqlUy0DNQqo2tBQA
custom_model=%7B%22priority%22%3A%5B%7B%22if%22%3A%22road_class%3D%3DMOTORWAY%22%2C%22multiply_by%22%3A%220.0%22%7D%5D%7D

Note that the polyline encoding is used without additional compression as it does not seem to reduce the length further and also polyline encoding is nearly always more compact than generic compression. Furthermore flex polyline encoding seems to give 10-10% more compact results compared to standard polyline encoding. Also note that the flex polyline website says it is 'lossy' but this applies only for coordinates with higher than specified (1e-6) precision.

Also note that we use CompressionStream instead of an external library like lz-string or pako because it is often more compact for our use case and also keeps the dependency list small.

Minor: have also reduced the length a bit via using l=osm instead of layer=OpenStreetMap etc.

TODO: should be possible to disable the compression for e.g. debugging purposes via the settings?

karussell and others added 2 commits May 20, 2026 14:59
…er layer parameter

New URL params: `fpolyline=` for routes with 4+ waypoints, `cnames=` for
waypoint names, `cmodel=` for the custom model, and `l=<shortCode>` for the
map layer.

Legacy `point=`, `custom_model=`, `layer=`, and `vehicle=` URLs still parse.

flexPolyline.ts vendored from heremaps/flexible-polyline (MIT); see NOTICE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@karussell karussell added the enhancement New feature or request label May 20, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces GraphHopper Maps share URL length by introducing compact encoding for waypoints, point names, and custom models. It adds a new fpolyline parameter (HERE flexible polyline) for waypoint coordinates (used from 4 points onward), compresses waypoint names via cnames, compresses custom models via cmodel, and switches map layer URLs to a short l=<code> format while keeping legacy parsing support.

Changes:

  • Add flexible polyline encoding/decoding utilities and use them in NavBar to emit/parse fpolyline.
  • Add CompressionStream-based deflate/base64url helpers and use them to emit/parse cnames and cmodel.
  • Introduce StyleOption.shortName and emit l=<shortName> while still accepting legacy layer=<fullName>.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/NavBar.ts Emits/reads the new compact URL params (fpolyline, cnames, cmodel, l) with legacy fallback.
src/stores/MapOptionsStore.ts Adds shortName for styles and allows selecting by either full name or short code.
src/util/flexPolyline.ts Vendored flexible polyline implementation + Coordinate wrappers for encoding/decoding waypoints.
src/util/urlCompress.ts CompressionStream-based deflate-raw + base64url helpers for URL-safe compression.
test/NavBar.test.ts Expands URL sync/parse tests to cover new params and legacy compatibility.
test/flexPolyline.test.ts Validates encoding/decoding against canonical upstream vectors + URL-safe output.
test/urlCompress.test.ts Validates compression feature detection and roundtrips (incl. non-ASCII).
NOTICE.md Adds attribution note for the vendored flexible polyline code.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/NavBar.ts
Comment on lines 46 to 52
async startSyncingUrlWithAppState() {
// our first history entry shall be the one that we end up with when the app loads for the first time
window.history.replaceState(null, '', this.createUrlFromState())
const url = await this.createUrlFromState()
window.history.replaceState(null, '', url)
this.queryStore.register(() => this.updateUrlFromState())
this.mapStore.register(() => this.updateUrlFromState())
}
Comment thread src/NavBar.ts
Comment on lines 258 to +273

const parsedLayer = NavBar.parseLayer(url)
if (parsedLayer) Dispatcher.dispatch(new SelectMapLayer(parsedLayer))

const customModelParam = url.searchParams.get('custom_model')
if (customModelParam != null) Dispatcher.dispatch(new SetCustomModel(customModelParam, false))
else Dispatcher.dispatch(new DisableCustomModel())
const customModelStr = await NavBar.parseCustomModel(url)
if (customModelStr) {
// Pretty-print so the editor shows readable JSON (URL form is minified).
// Mirrors QueryStore.getInitialState behaviour for the initial-load case.
let prettyStr = customModelStr
try {
prettyStr = customModel2prettyString(JSON.parse(customModelStr))
} catch {}
Dispatcher.dispatch(new SetCustomModel(prettyStr, true))
} else {
Dispatcher.dispatch(new DisableCustomModel())
}
Comment thread src/util/flexPolyline.ts Outdated
Comment thread NOTICE.md
karussell and others added 2 commits May 20, 2026 22:15
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants