import shapely shapes and NDArray only for type checking
This commit is contained in:
parent
60afb9fa60
commit
3d2b1dff4b
3 changed files with 31 additions and 27 deletions
|
@ -12,7 +12,7 @@ if [[ "$1" == "git" ]]; then
|
||||||
CONTEXT="https://github.com/c3nav/c3nav.git#${COMMIT}"
|
CONTEXT="https://github.com/c3nav/c3nav.git#${COMMIT}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker buildx build -f docker/Dockerfile \
|
podman buildx build -f docker/Dockerfile \
|
||||||
--platform linux/arm64,linux/amd64 \
|
--platform linux/arm64,linux/amd64 \
|
||||||
--build-arg "COMMIT=${COMMIT}" \
|
--build-arg "COMMIT=${COMMIT}" \
|
||||||
--label "org.opencontainers.image.version=${COMMIT}" \
|
--label "org.opencontainers.image.version=${COMMIT}" \
|
||||||
|
@ -25,7 +25,7 @@ docker buildx build -f docker/Dockerfile \
|
||||||
--cache-to "type=registry,ref=ghcr.io/c3nav/c3nav_cache:main,mode=max" \
|
--cache-to "type=registry,ref=ghcr.io/c3nav/c3nav_cache:main,mode=max" \
|
||||||
--push "${CONTEXT}"
|
--push "${CONTEXT}"
|
||||||
|
|
||||||
docker buildx build -f docker/tileserver.dockerfile \
|
podman buildx build -f docker/tileserver.dockerfile \
|
||||||
--platform linux/arm64,linux/amd64 \
|
--platform linux/arm64,linux/amd64 \
|
||||||
--build-arg "COMMIT=${COMMIT}" \
|
--build-arg "COMMIT=${COMMIT}" \
|
||||||
--label "org.opencontainers.image.version=${COMMIT}" \
|
--label "org.opencontainers.image.version=${COMMIT}" \
|
||||||
|
|
|
@ -2,11 +2,13 @@ import operator
|
||||||
import struct
|
import struct
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
from typing import Self, Iterator
|
from typing import Self, Iterator, Union, TYPE_CHECKING
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from numpy.typing import NDArray
|
|
||||||
from shapely import Polygon, MultiPolygon
|
if TYPE_CHECKING:
|
||||||
|
from numpy.typing import NDArray
|
||||||
|
from shapely import Polygon, MultiPolygon
|
||||||
|
|
||||||
from c3nav.mapdata.utils.cache.indexed import LevelGeometryIndexed
|
from c3nav.mapdata.utils.cache.indexed import LevelGeometryIndexed
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ class AccessRestrictionAffected(LevelGeometryIndexed):
|
||||||
self.restrictions.append(restriction)
|
self.restrictions.append(restriction)
|
||||||
return i
|
return i
|
||||||
|
|
||||||
def __getitem__(self, selector: tuple[slice, slice] | Polygon | MultiPolygon) -> "AccessRestrictionAffectedCells":
|
def __getitem__(self, selector: Union[tuple[slice, slice], 'Polygon', 'MultiPolygon']) -> "AccessRestrictionAffectedCells":
|
||||||
return AccessRestrictionAffectedCells(self, selector)
|
return AccessRestrictionAffectedCells(self, selector)
|
||||||
|
|
||||||
def __setitem__(self, selector, value):
|
def __setitem__(self, selector, value):
|
||||||
|
@ -68,15 +70,15 @@ class AccessRestrictionAffected(LevelGeometryIndexed):
|
||||||
|
|
||||||
class AccessRestrictionAffectedCells:
|
class AccessRestrictionAffectedCells:
|
||||||
def __init__(self, parent: AccessRestrictionAffected,
|
def __init__(self, parent: AccessRestrictionAffected,
|
||||||
selector: tuple[slice, slice] | Polygon | MultiPolygon):
|
selector: Union[tuple[slice, slice], 'Polygon','MultiPolygon']):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.selector = selector
|
self.selector = selector
|
||||||
self.values = self._get_values()
|
self.values = self._get_values()
|
||||||
|
|
||||||
def _get_values(self) -> NDArray:
|
def _get_values(self) -> 'NDArray':
|
||||||
return LevelGeometryIndexed.__getitem__(self.parent, self.selector)
|
return LevelGeometryIndexed.__getitem__(self.parent, self.selector)
|
||||||
|
|
||||||
def _set(self, values: NDArray):
|
def _set(self, values: 'NDArray'):
|
||||||
self.values = values
|
self.values = values
|
||||||
LevelGeometryIndexed.__setitem__(self.parent, self.selector, values)
|
LevelGeometryIndexed.__setitem__(self.parent, self.selector, values)
|
||||||
|
|
||||||
|
|
38
src/c3nav/mapdata/utils/cache/indexed.py
vendored
38
src/c3nav/mapdata/utils/cache/indexed.py
vendored
|
@ -2,10 +2,11 @@ import math
|
||||||
import struct
|
import struct
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Self, Optional
|
from typing import Self, Optional, Union, TYPE_CHECKING
|
||||||
|
|
||||||
from numpy.typing import NDArray
|
if TYPE_CHECKING:
|
||||||
from shapely import Polygon, MultiPolygon
|
from numpy.typing import NDArray
|
||||||
|
from shapely import Polygon, MultiPolygon
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
@ -29,18 +30,18 @@ class GeometryIndexed:
|
||||||
variant_id = 0
|
variant_id = 0
|
||||||
|
|
||||||
def __init__(self, resolution: Optional[int] = None, x: int = 0, y: int = 0,
|
def __init__(self, resolution: Optional[int] = None, x: int = 0, y: int = 0,
|
||||||
data: NDArray = None, filename: str | bytes | PathLike = None):
|
data: 'NDArray' = None, filename: str | bytes | PathLike = None):
|
||||||
if resolution is None:
|
if resolution is None:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
resolution = settings.CACHE_RESOLUTION
|
resolution = settings.CACHE_RESOLUTION
|
||||||
self.resolution: int = resolution
|
self.resolution: int = resolution
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
self.data: NDArray = data if data is not None else self._get_empty_array()
|
self.data: 'NDArray' = data if data is not None else self._get_empty_array()
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_empty_array(cls) -> NDArray:
|
def _get_empty_array(cls) -> 'NDArray':
|
||||||
return np.empty((0, 0), dtype=cls.dtype)
|
return np.empty((0, 0), dtype=cls.dtype)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -64,7 +65,8 @@ class GeometryIndexed:
|
||||||
cls._read_metadata(f, kwargs)
|
cls._read_metadata(f, kwargs)
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
kwargs['data'] = np.fromstring(f.read(width*height*cls.dtype().itemsize), cls.dtype).reshape((height, width))
|
kwargs['data'] = np.fromstring(f.read(width * height * cls.dtype().itemsize), cls.dtype).reshape(
|
||||||
|
(height, width))
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -88,7 +90,7 @@ class GeometryIndexed:
|
||||||
def _write_metadata(self, f):
|
def _write_metadata(self, f):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_geometry_bounds(self, geometry: Polygon | MultiPolygon) -> tuple[int, int, int, int]:
|
def get_geometry_bounds(self, geometry: Union['Polygon', 'MultiPolygon']) -> tuple[int, int, int, int]:
|
||||||
minx, miny, maxx, maxy = geometry.bounds
|
minx, miny, maxx, maxy = geometry.bounds
|
||||||
return (
|
return (
|
||||||
int(math.floor(minx / self.resolution)),
|
int(math.floor(minx / self.resolution)),
|
||||||
|
@ -117,8 +119,8 @@ class GeometryIndexed:
|
||||||
self.x = minx
|
self.x = minx
|
||||||
self.y = miny
|
self.y = miny
|
||||||
|
|
||||||
def get_geometry_cells(self, geometry: Polygon | MultiPolygon,
|
def get_geometry_cells(self, geometry: Union['Polygon','MultiPolygon'],
|
||||||
bounds: Optional[tuple[int, int, int, int]] = None) -> NDArray:
|
bounds: Optional[tuple[int, int, int, int]] = None) -> 'NDArray':
|
||||||
if bounds is None:
|
if bounds is None:
|
||||||
bounds = self.get_geometry_bounds(geometry)
|
bounds = self.get_geometry_bounds(geometry)
|
||||||
minx, miny, maxx, maxy = bounds
|
minx, miny, maxx, maxy = bounds
|
||||||
|
@ -145,9 +147,9 @@ class GeometryIndexed:
|
||||||
@property
|
@property
|
||||||
def bounds(self) -> tuple[int, int, int, int]:
|
def bounds(self) -> tuple[int, int, int, int]:
|
||||||
height, width = self.data.shape
|
height, width = self.data.shape
|
||||||
return self.x, self.y, self.x+width, self.y+height
|
return self.x, self.y, self.x + width, self.y + height
|
||||||
|
|
||||||
def __getitem__(self, key: tuple[slice, slice] | Polygon | MultiPolygon) -> int:
|
def __getitem__(self, key: Union[tuple[slice, slice], 'Polygon','MultiPolygon']) -> int:
|
||||||
if isinstance(key, tuple):
|
if isinstance(key, tuple):
|
||||||
xx, yy = key
|
xx, yy = key
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ class GeometryIndexed:
|
||||||
|
|
||||||
raise TypeError('GeometryIndexed index must be a shapely geometry or tuple, not %s' % type(key).__name__)
|
raise TypeError('GeometryIndexed index must be a shapely geometry or tuple, not %s' % type(key).__name__)
|
||||||
|
|
||||||
def __setitem__(self, key: Polygon | MultiPolygon, value: NDArray | int):
|
def __setitem__(self, key: Union['Polygon','MultiPolygon'], value: 'NDArray' | int):
|
||||||
from shapely.geometry.base import BaseGeometry
|
from shapely.geometry.base import BaseGeometry
|
||||||
if isinstance(key, BaseGeometry):
|
if isinstance(key, BaseGeometry):
|
||||||
bounds = self.get_geometry_bounds(key)
|
bounds = self.get_geometry_bounds(key)
|
||||||
|
@ -187,16 +189,16 @@ class GeometryIndexed:
|
||||||
(minx, miny), (maxx, maxy) = Source.max_bounds()
|
(minx, miny), (maxx, maxy) = Source.max_bounds()
|
||||||
|
|
||||||
height, width = self.data.shape
|
height, width = self.data.shape
|
||||||
image_data = np.zeros((int(math.ceil((maxy-miny)/self.resolution)),
|
image_data = np.zeros((int(math.ceil((maxy - miny) / self.resolution)),
|
||||||
int(math.ceil((maxx-minx)/self.resolution))), dtype=np.uint8)
|
int(math.ceil((maxx - minx) / self.resolution))), dtype=np.uint8)
|
||||||
|
|
||||||
if self.data.size:
|
if self.data.size:
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
minval = min(self.data.min(), 0)
|
minval = min(self.data.min(), 0)
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
maxval = max(self.data.max(), minval+0.01)
|
maxval = max(self.data.max(), minval + 0.01)
|
||||||
visible_data = ((self.data.astype(float)-minval)*255/(maxval-minval)).clip(0, 255).astype(np.uint8)
|
visible_data = ((self.data.astype(float) - minval) * 255 / (maxval - minval)).clip(0, 255).astype(np.uint8)
|
||||||
image_data[self.y:self.y+height, self.x:self.x+width] = visible_data
|
image_data[self.y:self.y + height, self.x:self.x + width] = visible_data
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
return Image.fromarray(np.flip(image_data, axis=0), 'L')
|
return Image.fromarray(np.flip(image_data, axis=0), 'L')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue