Skip to content

Commit 4c5bfc2

Browse files
committed
Add useGeographic() so that we can pass lon lat coordinates
1 parent be48348 commit 4c5bfc2

File tree

8 files changed

+101
-51
lines changed

8 files changed

+101
-51
lines changed

docs/api/map.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22

33
::: openlayers.Map
44

5+
::: openlayers.view.View
6+
57
::: openlayers.MapWidget
8+

examples/standalone/ol_express.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# import json
22
# import openlayers as ol
3-
import openlayers.express as olx
3+
import openlayers.express as ox
44
from openlayers.basemaps import BasemapLayer
5+
from openlayers import View
56

6-
icon_layer = olx.IconLayer(
7+
icon_layer = ox.IconLayer(
78
# id="icon-layer",
89
data="https://openlayers.org/data/vector/populated-places.json",
910
icon_src="https://openlayers.org/en/latest/examples/data/icon.png",
@@ -20,7 +21,7 @@
2021

2122
line_data = "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart.geo.json"
2223

23-
generic_geojson_layer = olx.GeoJSONLayer(
24+
generic_geojson_layer = ox.GeoJSONLayer(
2425
data = line_data,
2526
#stroke_width = 5,
2627
#stroke_color = "green",
@@ -30,12 +31,12 @@
3031
#circle_radius = 7
3132
)
3233

33-
circle_layer = olx.CircleLayer(
34+
circle_layer = ox.CircleLayer(
3435
data="https://openlayers.org/data/vector/populated-places.json",
3536
circle_fill_color="yellow"
3637
)
3738

38-
fill_layer = olx.FillLayer(
39+
fill_layer = ox.FillLayer(
3940
data=None ,#"https://openlayers.org/en/v4.6.5/examples/data/geojson/countries.geojson",
4041
stroke_width=4,
4142
fill_color="yellow",
@@ -53,4 +54,6 @@
5354
# print(json.dumps(m.calls))
5455
# print(json.dumps(m.map_options))
5556

57+
# m.set_center((9.5, 51.31667))
58+
m.set_view(View(center=(9.5, 51.31667), zoom=14))
5659
m.save()

src/openlayers/anywidget.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212

1313

1414
class MapWidget(Map, AnyWidget):
15-
"""Map widget"""
15+
"""Initialize a new `MapWidget`instance
16+
17+
Note:
18+
See [Map](openlayers.Map) for details.
19+
"""
1620

1721
_esm = Path(__file__).parent / "js" / "openlayers.anywidget.js"
1822
_css = Path(__file__).parent / "js" / "openlayers.anywidget.css"

src/openlayers/js/openlayers.standalone.js

Lines changed: 30 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/openlayers/map.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ def add_view_call(self, method_name: str, *args: Any) -> None:
5757
view_call = dict(method=method_name, args=args)
5858
self.add_call("applyCallToView", view_call)
5959

60+
def set_view(self, view: View) -> None:
61+
"""Set the view state of the map
62+
63+
Args:
64+
view (View): The view state of the map
65+
"""
66+
self.add_call("setView", view.model_dump())
67+
6068
def set_zoom(self, zoom_level: float | int) -> None:
6169
"""Set the zoom level ot the map view
6270
@@ -66,15 +74,17 @@ def set_zoom(self, zoom_level: float | int) -> None:
6674
self.add_view_call("setZoom", zoom_level)
6775

6876
def set_center(
69-
self, lonlat: tuple[float, float] = None, center: tuple[float, float] = None
77+
self, lonlat: tuple[float, float] = None, transform: bool = True
7078
) -> None:
7179
"""Set the center of the map view
72-
80+
7381
Args:
74-
lonlat (tuple[float, float]): center as (lon, lat)
75-
center (tuple[float, float]) center as (x, y) of view projection
82+
lonlat (tuple[float, float]): The centerpoint of the map as `(lon, lat)` pair
83+
transform (bool): Whether coordinates should be transformed to `EPSG:3857`,
84+
which is the default projection of the view
7685
"""
77-
center = center or default_crs_transformer().transform(*lonlat)
86+
# center = default_crs_transformer().transform(*lonlat) if transform else lonlat
87+
center = lonlat
7888
self.add_view_call("setCenter", center)
7989

8090
def add_layer(self, layer: LayerT | LayerLike | dict) -> None:
@@ -165,8 +175,6 @@ def set_style(self, layer_id: str, style: FlatStyle | dict) -> None:
165175

166176
self.add_layer_call(layer_id, "setStyle", style)
167177

168-
def set_view(self, view: View) -> None: ...
169-
170178
def to_html(self, **kwargs) -> str:
171179
"""Render map to HTML"""
172180
data = self.map_options | dict(calls=self.calls)

src/openlayers/models/view.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from __future__ import annotations
22

3-
from ..abstracts import MyBaseModel
3+
from pydantic import Field
4+
5+
# from ..abstracts import MyBaseModel
46
from .core import OLBaseModel
57

68

9+
# TODO: Use pyproj instead
710
class Projection(object):
811
MERCATOR = "EPSG:4326"
912
WEB_MERCATOR = "EPSG:3857"
@@ -13,17 +16,32 @@ def from_epsg(code: int) -> str:
1316
return f"EPSG:{code}"
1417

1518

19+
# TODO: Obsolete, remove
20+
"""
1621
class ViewOptions(MyBaseModel):
1722
center: tuple[float, float] | None = (0, 0)
1823
zoom: float | None = 0
1924
projection: str | None = Projection.WEB_MERCATOR
2025
min_zoom: int | float | None = None
2126
max_zoom: int | float | None = None
27+
"""
2228

2329

2430
class View(OLBaseModel):
31+
"""View object
32+
33+
Note:
34+
See [module-ol_View-View.html](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html) for details.
35+
36+
Attributes:
37+
center (tuple[float, float]): The centerpoint of the map as `(lon, lat)` pair
38+
zoom (float | int): The zoom level of the map
39+
min_zoom (float | int): The minimum zoom level of the map
40+
max_zoom (float | int): The maximum zoom level of the map
41+
"""
42+
2543
center: tuple[float, float] | None = (0, 0)
26-
zoom: float | None = 0
44+
zoom: float | int | None = 0
2745
projection: str | None = Projection.WEB_MERCATOR
28-
min_zoom: int | float | None = None
29-
max_zoom: int | float | None = None
46+
min_zoom: int | float | None = Field(None, serialization_alias="minZoom")
47+
max_zoom: int | float | None = Field(None, serialization_alias="maxZoom")

src/openlayers/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import base64
44
from pathlib import Path
5-
from pyproj import Transformer, CRS
5+
6+
from pyproj import CRS, Transformer
7+
68

79
def create_icon_src_from_file(filename: str) -> bytes:
810
with open(filename, "rb") as f:
@@ -11,6 +13,7 @@ def create_icon_src_from_file(filename: str) -> bytes:
1113
image_type = Path(filename).suffix.replace(".", "")
1214
return f"data:image/{image_type};base64," + encoded_image
1315

16+
1417
def default_crs_transformer() -> Transformer:
1518
crs_from = CRS.from_epsg(4326)
1619
crs_to = CRS.from_epsg(3857)

srcjs/ipywidget-ts/map.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Map, View } from "ol";
22
import { defaults as defaultControls } from 'ol/control/defaults.js';
33
import GeoJSON from "ol/format/GeoJSON";
44
import Overlay from "ol/Overlay";
5-
import { fromLonLat, transformExtent } from "ol/proj";
5+
import { fromLonLat, transformExtent, useGeographic } from "ol/proj";
66
import { JSONConverter } from "./json";
77
import { addTooltip2 } from "./tooltip2";
88

@@ -29,16 +29,21 @@ const GEOJSON_IDENTIFIER = "@@geojson";
2929

3030
const jsonConverter = new JSONConverter();
3131

32+
// ...
33+
useGeographic();
34+
3235
// --- Helpers
3336
function parseViewDef(viewDef: JSONDef): View {
3437
const view = jsonConverter.parse(viewDef) as View;
3538
const center = view.getCenter();
36-
console.log("view center", center)
39+
console.log("view center", center);
40+
// Not needed anymore because of `useGeographic()`
41+
/*
3742
if (center && view.getProjection().getCode() !== "EPSG:4326") {
3843
const centerTransformed = fromLonLat(center);
3944
console.log("view center transformed", centerTransformed);
4045
view.setCenter(centerTransformed);
41-
}
46+
}*/
4247

4348
return view;
4449
}
@@ -128,11 +133,17 @@ export default class MapWidget {
128133
this._map.getView().fit(extent);
129134
}
130135

136+
// TODO: obsolete since `useGeographic()` does this for us
131137
fitBoundsFromLonLat(extentLonLat: any): void {
132138
const exent = transformExtent(extentLonLat, "EPSG:4326", this._map.getView().getProjection());
133139
this.fitBounds(exent);
134140
}
135141

142+
setView(viewDef: JSONDef): void {
143+
const view = jsonConverter.parse(viewDef) as View;
144+
this._map.setView(view);
145+
}
146+
136147
// --- View Methods
137148
applyCallToView(call: OLAnyWidgetCall): void {
138149
const view = this._map.getView();

0 commit comments

Comments
 (0)