-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add Leaflet.encoded
plugin: Enable creating PolyLine and Polygon from encoded string
#1928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conengmo
merged 8 commits into
python-visualization:main
from
achieveordie:plugin/leaflet-encoded
May 7, 2024
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2396458
add plugin to visualize the polyline from an encoded string
achieveordie 6cdee23
correct import in user guide
achieveordie 3f31f5d
Update polyline_encoded.py
hansthen a71112d
rework encoded plugin to include PolygonFromEncoded
achieveordie 8b557ba
include doc and tests for PolygonFromEncoded
achieveordie b9d4167
update doc to include the link of the algo
achieveordie 9170da6
use path_options instead of parse_options
achieveordie 982c31c
set path_options to an attribute
achieveordie File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
```{code-cell} ipython3 | ||
--- | ||
nbsphinx: hidden | ||
--- | ||
import folium | ||
from folium import plugins | ||
``` | ||
|
||
# PolygonFromEncoded | ||
|
||
Create a Polygon directly from an encoded polyline string. To understand the encoding algorithm | ||
refer to [this](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) link. | ||
|
||
```{code-cell} ipython3 | ||
|
||
m = folium.Map(location=[40, -80], zoom_start=5) | ||
|
||
encoded = r"w`j~FpxivO}jz@qnnCd}~Bsa{@~f`C`lkH" | ||
plugins.PolygonFromEncoded(encoded=encoded).add_to(m) | ||
|
||
m | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
```{code-cell} ipython3 | ||
--- | ||
nbsphinx: hidden | ||
--- | ||
import folium | ||
from folium import plugins | ||
``` | ||
|
||
# PolyLineFromEncoded | ||
|
||
Create a PolyLine directly from an encoded polyline string. To understand the encoding algorithm | ||
refer to [this](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) link. | ||
|
||
```{code-cell} ipython3 | ||
|
||
m = folium.Map(location=[40, -120], zoom_start=5) | ||
|
||
encoded = r"_p~iF~cn~U_ulLn{vA_mqNvxq`@" | ||
plugins.PolyLineFromEncoded(encoded=encoded).add_to(m) | ||
|
||
m | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
from jinja2 import Template | ||
|
||
from folium.elements import JSCSSMixin | ||
from folium.features import MacroElement | ||
from folium.vector_layers import path_options | ||
|
||
|
||
class _BaseFromEncoded(JSCSSMixin, MacroElement, ABC): | ||
"""Base Interface to create folium objects from encoded strings. | ||
|
||
Derived classes must define `_encoding_type` property which returns the string | ||
representation of the folium object to create from the encoded string. | ||
|
||
Parameters | ||
---------- | ||
encoded: str | ||
The raw encoded string from the Polyline Encoding Algorithm. See: | ||
https://developers.google.com/maps/documentation/utilities/polylinealgorithm | ||
**kwargs: | ||
Object options as accepted by leaflet. | ||
""" | ||
|
||
_template = Template( | ||
""" | ||
{% macro script(this, kwargs) %} | ||
|
||
var {{ this.get_name() }} = L.{{ this._encoding_type }}.fromEncoded( | ||
{{ this.encoded|tojson }}, | ||
{{ this.options|tojson }} | ||
).addTo({{ this._parent.get_name() }}); | ||
|
||
{% endmacro %} | ||
""" | ||
) | ||
|
||
default_js = [ | ||
( | ||
"polyline-encoded", | ||
"https://cdn.jsdelivr.net/npm/[email protected]/Polyline.encoded.js", | ||
) | ||
] | ||
|
||
def __init__(self, encoded: str): | ||
super().__init__() | ||
self.encoded = encoded | ||
|
||
@property | ||
@abstractmethod | ||
def _encoding_type(self) -> str: | ||
"""An abstract getter to return the type of folium object to create.""" | ||
raise NotImplementedError | ||
|
||
|
||
class PolyLineFromEncoded(_BaseFromEncoded): | ||
"""Create PolyLines directly from the encoded string. | ||
|
||
Parameters | ||
---------- | ||
encoded: str | ||
The raw encoded string from the Polyline Encoding Algorithm. See: | ||
https://developers.google.com/maps/documentation/utilities/polylinealgorithm | ||
**kwargs: | ||
Polyline options as accepted by leaflet. See: | ||
https://leafletjs.com/reference.html#polyline | ||
|
||
Adapted from https://github.com/jieter/Leaflet.encoded | ||
|
||
Examples | ||
-------- | ||
>>> from folium import Map | ||
>>> from folium.plugins import PolyLineFromEncoded | ||
>>> m = Map() | ||
>>> encoded = r"_p~iF~cn~U_ulLn{vA_mqNvxq`@" | ||
>>> PolyLineFromEncoded(encoded=encoded, color="green").add_to(m) | ||
""" | ||
|
||
def __init__(self, encoded: str, **kwargs): | ||
self._name = "PolyLineFromEncoded" | ||
super().__init__(encoded=encoded) | ||
self.options = path_options(line=True, **kwargs) | ||
|
||
@property | ||
def _encoding_type(self) -> str: | ||
"""Return the name of folium object created from the encoded.""" | ||
return "Polyline" | ||
|
||
|
||
class PolygonFromEncoded(_BaseFromEncoded): | ||
"""Create Polygons directly from the encoded string. | ||
|
||
Parameters | ||
---------- | ||
encoded: str | ||
The raw encoded string from the Polyline Encoding Algorithm. See: | ||
https://developers.google.com/maps/documentation/utilities/polylinealgorithm | ||
**kwargs: | ||
Polygon options as accepted by leaflet. See: | ||
https://leafletjs.com/reference.html#polygon | ||
|
||
Adapted from https://github.com/jieter/Leaflet.encoded | ||
|
||
Examples | ||
-------- | ||
>>> from folium import Map | ||
>>> from folium.plugins import PolygonFromEncoded | ||
>>> m = Map() | ||
>>> encoded = r"w`j~FpxivO}jz@qnnCd}~Bsa{@~f`C`lkH" | ||
>>> PolygonFromEncoded(encoded=encoded).add_to(m) | ||
""" | ||
|
||
def __init__(self, encoded: str, **kwargs): | ||
self._name = "PolygonFromEncoded" | ||
super().__init__(encoded) | ||
self.options = path_options(line=True, radius=None, **kwargs) | ||
|
||
@property | ||
def _encoding_type(self) -> str: | ||
"""Return the name of folium object created from the encoded.""" | ||
return "Polygon" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
"""Test PolyLineFromEncoded Plugin.""" | ||
|
||
from jinja2 import Template | ||
|
||
from folium import Map | ||
from folium.plugins import PolygonFromEncoded, PolyLineFromEncoded | ||
from folium.utilities import normalize | ||
|
||
|
||
def test_polyline_from_encoded(): | ||
"""Test `PolyLineFromEncoded` plugin. | ||
|
||
The test ensures: | ||
- The original JS script is present in the HTML file. | ||
- The rendering from `PolyLineFromEncoded` and the original plugin gives the | ||
same output. | ||
""" | ||
|
||
m = Map([35.0, -120.0], zoom_start=3) | ||
|
||
encoded = r"_p~iF~cn~U_ulLn{vA_mqNvxq`@" | ||
kwargs = {"color": "green"} | ||
polyline = PolyLineFromEncoded(encoded=encoded, **kwargs) | ||
|
||
polyline.add_to(m) | ||
|
||
out = normalize(m._parent.render()) | ||
|
||
script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/Polyline.encoded.js"></script>' | ||
assert script in out | ||
|
||
tmpl = Template( | ||
""" | ||
var {{this.get_name()}} = L.Polyline.fromEncoded( | ||
{{ this.encoded|tojson }}, | ||
{{ this.options|tojson }} | ||
).addTo({{this._parent.get_name()}}); | ||
""" | ||
) | ||
|
||
expected_render = tmpl.render(this=polyline) | ||
actual_render = polyline._template.module.script(polyline) | ||
|
||
assert normalize(expected_render) == normalize(actual_render) | ||
|
||
|
||
def test_polygon_from_encoded(): | ||
"""Test `PolygonFromEncoded` plugin. | ||
|
||
The test ensures: | ||
- The original JS script is present in the HTML file. | ||
- The rendering from `PolygonFromEncoded` and the original plugin gives the | ||
same output. | ||
""" | ||
|
||
m = Map([40.0, -80.0], zoom_start=3) | ||
|
||
encoded = r"w`j~FpxivO}jz@qnnCd}~Bsa{@~f`C`lkH" | ||
polygon = PolygonFromEncoded(encoded=encoded, kwargs={}) | ||
|
||
polygon.add_to(m) | ||
|
||
out = normalize(m._parent.render()) | ||
|
||
script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/Polyline.encoded.js"></script>' | ||
assert script in out | ||
|
||
tmpl = Template( | ||
""" | ||
var {{this.get_name()}} = L.Polygon.fromEncoded( | ||
{{ this.encoded|tojson }}, | ||
{{ this.options|tojson }} | ||
) | ||
.addTo({{this._parent.get_name()}}); | ||
""" | ||
) | ||
|
||
expected_render = tmpl.render(this=polygon) | ||
|
||
actual_render = polygon._template.module.script(polygon) | ||
|
||
assert normalize(expected_render) == normalize(actual_render) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.