# Interactive map helper functions


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

``` python
cml = open_cml_sample()
```

<div>

> **Warning**
>
> These functions were originally created for Plotly, which uses Mapbox
> internally. This is unlike Leaflet, which Folium uses internally. This
> is why the estimated zoom may differ slightly from the actual required
> zoom. Please feel free to report any bugs you find.

</div>

When creating the map, we want the initial view to be centred and zoomed
properly so that all the links are clearly visible at once. While the
geopandas.explore function does this automatically, in some cases we
might want to create a Map instance and then add geometries or tiles to
it. To provide a good user experience, we need to be able to centre and
zoom the map to the correct position. We will start by computing the
centre.

------------------------------------------------------------------------

### get_center

``` python

def get_center(
    cml:xarray.core.dataarray.DataArray | xarray.core.dataset.Dataset
)->tuple:

```

*Get the center point of a set of CML in OpenSense standard*

``` python
get_center(cml)
```

    (4.0407554999999995, 9.743189999999998)

To ensure that all links are clearly visible on the map, it is important
to calculate an appropriate zoom level based on the spatial extent of
the data. In particular, we need to determine the zoom required to fit
the latitude and longitude ranges of the links within the map view.

We will first compute the zoom level required to represent the latitude.
The zoom in meters per pixel can be estimated as follows:

$$
\text{meters\\per\\pixel} = \frac{v_0 \cdot \cos\left(lat\_{center}\right)}{2^{\text{zoom\\level}}}
$$

We need a zoom such that:

$$
\text{meters\\per\\pixel} = \frac{|lat\_{\max} - lat\_{\min}| \cdot \text{meters\\per\\degree}}{\text{height\\pixels}}
$$

Thus, the required zoom level for latitude can be computed as:

$$
\text{zoom\\level} = \log_2 \left( \frac{v_0 \cdot \cos\left(lat\_{center}\right) \cdot \text{height\\pixels}}{|lat\_{\max} - lat\_{\min}| \cdot \text{meters\\per\\degree}} \right)
$$

Where:

- *v*<sub>0</sub> = initial resolution (meters/pixel at zoom level 0).
  It can be obtained from plotly
  [website](https://docs.mapbox.com/help/glossary/zoom-level/#zoom-levels-and-geographical-distance)
- height_pixels = height of the map layout in pixels
- *l**a**t*<sub>max</sub>, *l**a**t*<sub>min</sub> = maximum and minimum
  latitude in the data
- meters_per_degree = number of meters per degree of latitude (typically
  111320 m/degree)
- *l**a**t*<sub>*c**e**n**t**e**r*</sub> = center latitude of the
  bounding box,
  i.e. $lat\_{center} = \frac{lat\_{\max} + lat\_{\min}}{2}$

Implementing this in python is straightforward.

Next, we need to estimate the required zoom level for longitude. Unlike
latitude, the number of meters per degree of longitude changes with
latitude, and we also need to use the map’s width (in pixels) instead of
its height. The formula for meters per pixel along the longitude
direction is:

$$
\text{meters\\per\\pixel} = \frac{|lon\_{\max} - lon\_{\min}| \cdot \text{meters\\per\\degree} \cdot \cos\left(lat\_{center}\right)}{\text{width\\pixels}}
$$

From this, we can derive the formula for the required zoom level:

$$
\text{zoom\\level} = \log_2 \left( \frac{v_0 \cdot \text{width\\pixels}}{|lon\_{\max} - lon\_{\min}| \cdot \text{meters\\per\\degree}} \right)
$$

where width_pixels is the width of the map layout in pixels.

As before, implementing this calculation in Python is straightforward.

So, the final zoom level for the map should be set to the minimum of the
zoom levels calculated for latitude and longitude. This approach ensures
that all links are fully visible within the map’s bounding box, both
vertically and horizontally.

------------------------------------------------------------------------

### get_zoom_start

``` python

def get_zoom_start(
    cml, height:int=1200, width:int=1200
):

```

*Call self as a function.*

``` python
get_zoom_start(cml)
```

    12.406704259110562

``` python
folium.Map(get_center(cml), zoom_start=get_zoom_start(cml))
```
