Source code for sepal_ui.mapping.draw_control
"""Customized drawing control."""
from copy import deepcopy
from typing import Optional
import geopandas as gpd
import ipyleaflet as ipl
from shapely import geometry as sg
from sepal_ui import color
[docs]
class DrawControl(ipl.DrawControl):
m: Optional[ipl.Map] = None
"the map on which he drawControl is displayed. It will help control the visibility"
[docs]
def __init__(self, m: ipl.Map, **kwargs) -> None:
"""A custom DrawingControl object to handle edition of features.
Args:
m: the map on which he drawControl is displayed
kwargs: any available arguments from a ipyleaflet.DrawingControl
"""
# set some default parameters
options = {"shapeOptions": {"color": color.info}}
kwargs.setdefault("marker", {})
kwargs.setdefault("circlemarker", {})
kwargs.setdefault("polyline", {})
kwargs.setdefault("rectangle", options)
kwargs.setdefault("circle", options)
kwargs.setdefault("polygon", options)
# save the map in the member of the objects
self.m = m
super().__init__(**kwargs)
[docs]
def show(self) -> None:
"""Show the drawing control on the map. and clear it's content."""
self.clear()
self in self.m.controls or self.m.add(self)
return
[docs]
def hide(self) -> None:
"""Hide the drawing control from the map, and clear it's content."""
self.clear()
self not in self.m.controls or self.m.remove(self)
return
[docs]
def to_json(self) -> dict:
"""Return the content of the DrawControl data.
Returned without the styling properties and using a polygonized representation of circles. The output is fully compatible with __geo_interface__.
Returns:
the json representation of all the geometries draw on the map
"""
features = [self.polygonize(feat) for feat in deepcopy(self.data)]
[feat["properties"].pop("style") for feat in features]
return {"type": "FeatureCollection", "features": features}
[docs]
@staticmethod
def polygonize(geo_json: dict) -> dict:
"""Transform a ipyleaflet circle (a point with a radius) into a GeoJson polygon.
The methods preserves all the geo_json other attributes.
If the geometry is not a circle (don't require polygonisation), do nothing.
Params:
geo_json: the circle geojson
Returns:
the polygonised feature
"""
if "Point" not in geo_json["geometry"]["type"]:
return geo_json
# create shapely point
center = sg.Point(geo_json["geometry"]["coordinates"])
point = gpd.GeoSeries([center], crs=4326)
radius = geo_json["properties"]["style"]["radius"]
circle = point.to_crs(3857).buffer(radius).to_crs(4326)
# insert it in the geo_json
output = geo_json.copy()
output["geometry"] = circle[0].__geo_interface__
return output