Skip to content

Commit

Permalink
Improve add_image function
Browse files Browse the repository at this point in the history
  • Loading branch information
giswqs committed Jun 22, 2024
1 parent f9500a7 commit 9a08fb1
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 8 deletions.
205 changes: 205 additions & 0 deletions docs/maplibre/geojson_points.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[![image](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://demo.leafmap.org/lab/index.html?path=maplibre/geojson_points.ipynb)\n",
"[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/leafmap/blob/master/docs/maplibre/geojson_points.ipynb)\n",
"[![image](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/opengeos/leafmap/HEAD)\n",
"\n",
"**Draw GeoJSON points**\n",
"\n",
"Draw points from a GeoJSON collection to a map.\n",
"\n",
"This source code of this example is adapted from the MapLibre GL JS example - [Draw GeoJSON points](https://maplibre.org/maplibre-gl-js/docs/examples/geojson-markers).\n",
"\n",
"Uncomment the following line to install [leafmap](https://leafmap.org) if needed."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# %pip install \"leafmap[maplibre]\""
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import leafmap.maplibregl as leafmap"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"MAPTILER_KEY = os.environ.get(\"MAPTILER_KEY\")\n",
"style = f\"https://api.maptiler.com/maps/positron/style.json?key={MAPTILER_KEY}\""
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "39710eb583cc491d82401844315fc35a",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"Map(height='600px', map_options={'bearing': 0.0, 'center': (0, 0), 'pitch': 0.0, 'style': 'https://api.maptile…"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m = leafmap.Map(center=[0, 0], zoom=1, style=style)\n",
"image = \"https://maplibre.org/maplibre-gl-js/docs/assets/osgeo-logo.png\"\n",
"m.add_image(\"custom-marker\", image)\n",
"source = {\n",
" 'type': 'geojson',\n",
" 'data': {\n",
" 'type': 'FeatureCollection',\n",
" 'features': [\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [100.4933, 13.7551]},\n",
" 'properties': {'year': '2004'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [6.6523, 46.5535]},\n",
" 'properties': {'year': '2006'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-123.3596, 48.4268]},\n",
" 'properties': {'year': '2007'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [18.4264, -33.9224]},\n",
" 'properties': {'year': '2008'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [151.195, -33.8552]},\n",
" 'properties': {'year': '2009'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [2.1404, 41.3925]},\n",
" 'properties': {'year': '2010'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-104.8548, 39.7644]},\n",
" 'properties': {'year': '2011'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-1.1665, 52.9539]},\n",
" 'properties': {'year': '2013'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-122.6544, 45.5428]},\n",
" 'properties': {'year': '2014'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [126.974, 37.5651]},\n",
" 'properties': {'year': '2015'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [7.1112, 50.7255]},\n",
" 'properties': {'year': '2016'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-71.0314, 42.3539]},\n",
" 'properties': {'year': '2017'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [39.2794, -6.8173]},\n",
" 'properties': {'year': '2018'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [26.0961, 44.4379]},\n",
" 'properties': {'year': '2019'},\n",
" },\n",
" {\n",
" 'type': 'Feature',\n",
" 'geometry': {'type': 'Point', 'coordinates': [-114.0879, 51.0279]},\n",
" 'properties': {'year': '2020'},\n",
" },\n",
" ],\n",
" },\n",
"}\n",
"\n",
"m.add_source(\"conferences\", source)\n",
"layer = {\n",
" 'id': 'conferences',\n",
" 'type': 'symbol',\n",
" 'source': 'conferences',\n",
" 'layout': {\n",
" 'icon-image': 'custom-marker',\n",
" 'text-field': ['get', 'year'],\n",
" 'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],\n",
" 'text-offset': [0, 1.25],\n",
" 'text-anchor': 'top',\n",
" },\n",
"}\n",
"\n",
"m.add_layer(layer)\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](https://i.imgur.com/cJsnBby.png)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
6 changes: 6 additions & 0 deletions docs/maplibre/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ Toggle between current view and fullscreen mode.

[![](https://i.imgur.com/Vn3carH.png)](https://leafmap.org/maplibre/fullscreen)

## Draw GeoJSON points

Draw points from a GeoJSON collection to a map.

[![](https://i.imgur.com/cJsnBby.png)](https://leafmap.org/maplibre/geojson_points)

## Add a GeoJSON line

Add a GeoJSON line to a map using addSource, then style it using addLayer’s paint properties.
Expand Down
70 changes: 62 additions & 8 deletions leafmap/maplibregl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1561,22 +1561,40 @@ def _read_image(self, image: str) -> Dict[str, Union[int, List[int]]]:

import os
from PIL import Image
import requests
from io import BytesIO
import numpy as np

if isinstance(image, str):
try:
if os.path.isfile(image):
if image.startswith("http"):
image = download_file(
image, temp_file_path(image.split(".")[-1]), quiet=True
)
if os.path.exists(image):
img = Image.open(image)
else:
response = requests.get(image)
img = Image.open(BytesIO(response.content))
raise ValueError("The image file does not exist.")

width, height = img.size

# Convert image to numpy array and then flatten it
img_data = np.array(img, dtype="uint8")
if len(img_data.shape) == 3 and img_data.shape[2] == 2:
# Split the grayscale and alpha channels
gray_channel = img_data[:, :, 0]
alpha_channel = img_data[:, :, 1]

# Create the R, G, and B channels by duplicating the grayscale channel
R_channel = gray_channel
G_channel = gray_channel
B_channel = gray_channel

# Combine the channels into an RGBA image
RGBA_image_data = np.stack(
(R_channel, G_channel, B_channel, alpha_channel), axis=-1
)

# Update img_data to the new RGBA image data
img_data = RGBA_image_data

flat_img_data = img_data.flatten()

# Create the image dictionary with the flattened data
Expand All @@ -1594,7 +1612,14 @@ def _read_image(self, image: str) -> Dict[str, Union[int, List[int]]]:
raise ValueError("The image must be a URL or a local file path.")

def add_image(
self, id: str, image: Union[str, Dict], width: int = None, height: int = None
self,
id: str,
image: Union[str, Dict],
width: int = None,
height: int = None,
coordinates: List[float] = None,
icon_size: float = 1.0,
**kwargs: Any,
) -> None:
"""Add an image to the map.
Expand All @@ -1605,6 +1630,9 @@ def add_image(
array representing the image.
width (int, optional): The width of the image. Defaults to None.
height (int, optional): The height of the image. Defaults to None.
coordinates (List[float], optional): The longitude and latitude
coordinates to place the image.
icon_size (float, optional): The size of the icon. Defaults to 1.0.
Returns:
None
Expand All @@ -1619,14 +1647,40 @@ def add_image(
image_dict = {
"width": width,
"height": height,
"data": image.tolist(),
"data": image.flatten().tolist(),
}
else:
raise ValueError(
"The image must be a URL, a local file path, or a numpy array."
)
super().add_call("addImage", id, image_dict)

if coordinates is not None:

source = {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": coordinates},
}
],
},
}

self.add_source("image_point", source)

kwargs["id"] = "image_points"
kwargs["type"] = "symbol"
kwargs["source"] = "image_point"
if "layout" not in kwargs:
kwargs["layout"] = {}
kwargs["layout"]["icon-image"] = id
kwargs["layout"]["icon-size"] = icon_size
self.add_layer(kwargs)

def to_streamlit(
self,
width: Optional[int] = None,
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ nav:
- maplibre/fly_to.ipynb
- maplibre/fly_to_options.ipynb
- maplibre/fullscreen.ipynb
- maplibre/geojson_points.ipynb
- maplibre/geojson_line.ipynb
- maplibre/geojson_polygon.ipynb
- maplibre/heatmap_layer.ipynb
Expand Down

0 comments on commit 9a08fb1

Please sign in to comment.