Rename test to tests; fix equator length.

This commit is contained in:
Sergey Vartanov 2021-09-02 02:33:11 +03:00
parent f744c601d0
commit ba26c1d4d7
19 changed files with 71 additions and 33 deletions

View file

@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
echo "Checking code format with Black..." echo "Checking code format with Black..."
if ! black -l 80 --check test roentgen roentgen.py; then if ! black -l 80 --check tests roentgen roentgen.py; then
black -l 80 --diff test roentgen roentgen.py black -l 80 --diff tests roentgen roentgen.py
echo "FAIL" echo "FAIL"
exit 1 exit 1
fi fi
@ -13,5 +13,5 @@ echo "Lint with Flake8..."
flake8 \ flake8 \
--max-line-length=80 \ --max-line-length=80 \
--ignore=E203,W503,ANN002,ANN003,ANN101,ANN102 \ --ignore=E203,W503,ANN002,ANN003,ANN101,ANN102 \
--exclude=work,precommit.py,test/test_road.py \ --exclude=work,precommit.py,tests/test_road.py \
|| { echo "FAIL"; exit 1; } || { echo "FAIL"; exit 1; }

View file

@ -10,8 +10,8 @@ else
fi fi
echo "Checking code format with Black..." echo "Checking code format with Black..."
if ! black -l 80 --check test roentgen roentgen.py; then if ! black -l 80 --check tests roentgen roentgen.py; then
black -l 80 --diff test roentgen roentgen.py black -l 80 --diff tests roentgen roentgen.py
echo "FAIL" echo "FAIL"
exit 1 exit 1
fi fi
@ -22,7 +22,7 @@ echo "Lint with Flake8..."
flake8 \ flake8 \
--max-line-length=80 \ --max-line-length=80 \
--ignore=E203,W503,ANN002,ANN003,ANN101,ANN102 \ --ignore=E203,W503,ANN002,ANN003,ANN101,ANN102 \
--exclude=work,precommit.py,test/test_road.py \ --exclude=work,precommit.py,tests/test_road.py \
|| { echo "FAIL"; exit 1; } || { echo "FAIL"; exit 1; }
# Unit tests with pytest. # Unit tests with pytest.
@ -33,7 +33,7 @@ pytest -v || { echo "FAIL"; exit 1; }
# Integration tests. # Integration tests.
echo "Test render" echo "Test render"
python3 roentgen.py render -b 10.000,20.000,10.001,20.001 --cache test/data \ python3 roentgen.py render -b 10.000,20.000,10.001,20.001 --cache tests/data \
|| { echo "FAIL"; exit 1; } || { echo "FAIL"; exit 1; }
grep "natural: tree" out/map.svg || { echo "FAIL"; exit 1; } grep "natural: tree" out/map.svg || { echo "FAIL"; exit 1; }
@ -48,7 +48,7 @@ python3 roentgen.py element --node amenity=bench,material=wood \
|| { echo "FAIL"; exit 1; } || { echo "FAIL"; exit 1; }
echo "Test tile generation" echo "Test tile generation"
python3 roentgen.py tile --coordinates 50.000,40.000 --cache test/data \ python3 roentgen.py tile --coordinates 50.000,40.000 --cache tests/data \
|| { echo "FAIL"; exit 1; } || { echo "FAIL"; exit 1; }
exit 0 exit 0

View file

@ -43,22 +43,24 @@ class Tile:
x: int x: int
y: int y: int
zoom_level: int zoom_level: int
equator_length: float
@classmethod @classmethod
def from_coordinates( def from_coordinates(
cls, coordinates: np.ndarray, zoom_level: int cls, coordinates: np.ndarray, zoom_level: int, equator_length: float
) -> "Tile": ) -> "Tile":
""" """
Code from https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames Code from https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
:param coordinates: any coordinates inside tile, (latitude, longitude) :param coordinates: any coordinates inside tile, (latitude, longitude)
:param zoom_level: zoom level in OpenStreetMap terminology :param zoom_level: zoom level in OpenStreetMap terminology
:param equator_length: celestial body equator length in meters
""" """
lat_rad: np.ndarray = np.radians(coordinates[0]) lat_rad: np.ndarray = np.radians(coordinates[0])
n: float = 2.0 ** zoom_level n: float = 2.0 ** zoom_level
x: int = int((coordinates[1] + 180.0) / 360.0 * n) x: int = int((coordinates[1] + 180.0) / 360.0 * n)
y: int = int((1.0 - np.arcsinh(np.tan(lat_rad)) / np.pi) / 2.0 * n) y: int = int((1.0 - np.arcsinh(np.tan(lat_rad)) / np.pi) / 2.0 * n)
return cls(x, y, zoom_level) return cls(x, y, zoom_level, equator_length)
def get_coordinates(self) -> np.ndarray: def get_coordinates(self) -> np.ndarray:
""" """
@ -79,14 +81,16 @@ class Tile:
""" """
return ( return (
self.get_coordinates(), self.get_coordinates(),
Tile(self.x + 1, self.y + 1, self.zoom_level).get_coordinates(), Tile(
self.x + 1, self.y + 1, self.zoom_level, self.equator_length
).get_coordinates(),
) )
def get_extended_boundary_box(self) -> BoundaryBox: def get_extended_boundary_box(self) -> BoundaryBox:
"""Same as get_boundary_box, but with extended boundaries.""" """Same as get_boundary_box, but with extended boundaries."""
point_1: np.ndarray = self.get_coordinates() point_1: np.ndarray = self.get_coordinates()
point_2: np.ndarray = Tile( point_2: np.ndarray = Tile(
self.x + 1, self.y + 1, self.zoom_level self.x + 1, self.y + 1, self.zoom_level, self.equator_length
).get_coordinates() ).get_coordinates()
return BoundaryBox( return BoundaryBox(
@ -150,11 +154,13 @@ class Tile:
"""Draw SVG and PNG tile using OpenStreetMap data.""" """Draw SVG and PNG tile using OpenStreetMap data."""
top, left = self.get_coordinates() top, left = self.get_coordinates()
bottom, right = Tile( bottom, right = Tile(
self.x + 1, self.y + 1, self.zoom_level self.x + 1, self.y + 1, self.zoom_level, self.equator_length
).get_coordinates() ).get_coordinates()
flinger: Flinger = Flinger( flinger: Flinger = Flinger(
BoundaryBox(left, bottom, right, top), self.zoom_level BoundaryBox(left, bottom, right, top),
self.zoom_level,
self.equator_length,
) )
size: np.ndarray = flinger.size size: np.ndarray = flinger.size
@ -194,7 +200,13 @@ class Tile:
n: int = 2 ** (zoom_level - self.zoom_level) n: int = 2 ** (zoom_level - self.zoom_level)
for i in range(n): for i in range(n):
for j in range(n): for j in range(n):
tiles.append(Tile(n * self.x + i, n * self.y + j, zoom_level)) tile: Tile = Tile(
n * self.x + i,
n * self.y + j,
zoom_level,
self.equator_length,
)
tiles.append(tile)
return tiles return tiles
@ -209,31 +221,33 @@ class Tiles:
tile_2: Tile # Right bottom tile. tile_2: Tile # Right bottom tile.
zoom_level: int # OpenStreetMap zoom level. zoom_level: int # OpenStreetMap zoom level.
boundary_box: BoundaryBox boundary_box: BoundaryBox
equator_length: float
@classmethod @classmethod
def from_boundary_box( def from_boundary_box(
cls, boundary_box: BoundaryBox, zoom_level: int cls, boundary_box: BoundaryBox, zoom_level: int, equator_length: float
) -> "Tiles": ) -> "Tiles":
""" """
Create minimal set of tiles that covers boundary box. Create minimal set of tiles that covers boundary box.
:param boundary_box: area to be covered by tiles :param boundary_box: area to be covered by tiles
:param zoom_level: zoom level in OpenStreetMap terminology :param zoom_level: zoom level in OpenStreetMap terminology
:param equator_length: celestial body equator length in meters
""" """
tiles: list[Tile] = [] tiles: list[Tile] = []
tile_1: Tile = Tile.from_coordinates( tile_1: Tile = Tile.from_coordinates(
boundary_box.get_left_top(), zoom_level boundary_box.get_left_top(), zoom_level, equator_length
) )
tile_2: Tile = Tile.from_coordinates( tile_2: Tile = Tile.from_coordinates(
boundary_box.get_right_bottom(), zoom_level boundary_box.get_right_bottom(), zoom_level, equator_length
) )
for x in range(tile_1.x, tile_2.x + 1): for x in range(tile_1.x, tile_2.x + 1):
for y in range(tile_1.y, tile_2.y + 1): for y in range(tile_1.y, tile_2.y + 1):
tiles.append(Tile(x, y, zoom_level)) tiles.append(Tile(x, y, zoom_level, equator_length))
latitude_2, longitude_1 = tile_1.get_coordinates() latitude_2, longitude_1 = tile_1.get_coordinates()
latitude_1, longitude_2 = Tile( latitude_1, longitude_2 = Tile(
tile_2.x + 1, tile_2.y + 1, zoom_level tile_2.x + 1, tile_2.y + 1, zoom_level, equator_length
).get_coordinates() ).get_coordinates()
assert longitude_2 > longitude_1 assert longitude_2 > longitude_1
assert latitude_2 > latitude_1 assert latitude_2 > latitude_1
@ -242,7 +256,14 @@ class Tiles:
longitude_1, latitude_1, longitude_2, latitude_2 longitude_1, latitude_1, longitude_2, latitude_2
).round() ).round()
return cls(tiles, tile_1, tile_2, zoom_level, extended_boundary_box) return cls(
tiles,
tile_1,
tile_2,
zoom_level,
extended_boundary_box,
equator_length,
)
def load_osm_data(self, cache_path: Path) -> OSMData: def load_osm_data(self, cache_path: Path) -> OSMData:
"""Load OpenStreetMap data.""" """Load OpenStreetMap data."""
@ -359,7 +380,10 @@ class Tiles:
if not output_path.exists(): if not output_path.exists():
top, left = self.tile_1.get_coordinates() top, left = self.tile_1.get_coordinates()
bottom, right = Tile( bottom, right = Tile(
self.tile_2.x + 1, self.tile_2.y + 1, self.zoom_level self.tile_2.x + 1,
self.tile_2.y + 1,
self.zoom_level,
self.equator_length,
).get_coordinates() ).get_coordinates()
flinger: Flinger = Flinger( flinger: Flinger = Flinger(
@ -399,7 +423,14 @@ class Tiles:
tiles: list[Tile] = [] tiles: list[Tile] = []
for tile in self.tiles: for tile in self.tiles:
tiles += tile.subdivide(zoom_level) tiles += tile.subdivide(zoom_level)
return Tiles(tiles, tiles[0], tiles[-1], zoom_level, self.boundary_box) return Tiles(
tiles,
tiles[0],
tiles[-1],
zoom_level,
self.boundary_box,
self.equator_length,
)
class ScaleConfigurationException(Exception): class ScaleConfigurationException(Exception):
@ -440,6 +471,7 @@ def ui(options: argparse.Namespace) -> None:
"""Simple user interface for tile generation.""" """Simple user interface for tile generation."""
directory: Path = workspace.get_tile_path() directory: Path = workspace.get_tile_path()
equator_length: float = options.equator_length
zoom_levels: list[int] = parse_zoom_level(options.zoom) zoom_levels: list[int] = parse_zoom_level(options.zoom)
min_zoom_level: int = min(zoom_levels) min_zoom_level: int = min(zoom_levels)
@ -448,7 +480,7 @@ def ui(options: argparse.Namespace) -> None:
map(float, options.coordinates.strip().split(",")) map(float, options.coordinates.strip().split(","))
) )
min_tile: Tile = Tile.from_coordinates( min_tile: Tile = Tile.from_coordinates(
np.array(coordinates), min_zoom_level np.array(coordinates), min_zoom_level, equator_length
) )
try: try:
osm_data: OSMData = min_tile.load_osm_data(Path(options.cache)) osm_data: OSMData = min_tile.load_osm_data(Path(options.cache))
@ -457,7 +489,7 @@ def ui(options: argparse.Namespace) -> None:
for zoom_level in zoom_levels: for zoom_level in zoom_levels:
tile: Tile = Tile.from_coordinates( tile: Tile = Tile.from_coordinates(
np.array(coordinates), zoom_level np.array(coordinates), zoom_level, equator_length
) )
try: try:
configuration: MapConfiguration = MapConfiguration.from_options( configuration: MapConfiguration = MapConfiguration.from_options(
@ -468,7 +500,7 @@ def ui(options: argparse.Namespace) -> None:
logging.fatal(e.message) logging.fatal(e.message)
elif options.tile: elif options.tile:
zoom_level, x, y = map(int, options.tile.split("/")) zoom_level, x, y = map(int, options.tile.split("/"))
tile: Tile = Tile(x, y, zoom_level) tile: Tile = Tile(x, y, zoom_level, equator_length)
configuration: MapConfiguration = MapConfiguration.from_options( configuration: MapConfiguration = MapConfiguration.from_options(
options, zoom_level options, zoom_level
) )
@ -479,7 +511,9 @@ def ui(options: argparse.Namespace) -> None:
) )
if boundary_box is None: if boundary_box is None:
sys.exit(1) sys.exit(1)
min_tiles: Tiles = Tiles.from_boundary_box(boundary_box, min_zoom_level) min_tiles: Tiles = Tiles.from_boundary_box(
boundary_box, min_zoom_level, equator_length
)
try: try:
osm_data: OSMData = min_tiles.load_osm_data(Path(options.cache)) osm_data: OSMData = min_tiles.load_osm_data(Path(options.cache))
except NetworkError as e: except NetworkError as e:
@ -489,7 +523,9 @@ def ui(options: argparse.Namespace) -> None:
if EXTEND_TO_BIGGER_TILE: if EXTEND_TO_BIGGER_TILE:
tiles: Tiles = min_tiles.subdivide(zoom_level) tiles: Tiles = min_tiles.subdivide(zoom_level)
else: else:
tiles: Tiles = Tiles.from_boundary_box(boundary_box, zoom_level) tiles: Tiles = Tiles.from_boundary_box(
boundary_box, zoom_level, equator_length
)
configuration: MapConfiguration = MapConfiguration.from_options( configuration: MapConfiguration = MapConfiguration.from_options(
options, zoom_level options, zoom_level
) )
@ -503,7 +539,9 @@ def ui(options: argparse.Namespace) -> None:
configuration: MapConfiguration = MapConfiguration.from_options( configuration: MapConfiguration = MapConfiguration.from_options(
options, zoom_level options, zoom_level
) )
tiles: Tiles = Tiles.from_boundary_box(boundary_box, zoom_level) tiles: Tiles = Tiles.from_boundary_box(
boundary_box, zoom_level, equator_length
)
tiles.draw(directory, Path(options.cache), configuration, osm_data) tiles.draw(directory, Path(options.cache), configuration, osm_data)
else: else:
logging.fatal( logging.fatal(

View file

@ -5,7 +5,7 @@ import pytest
from roentgen.grid import IconCollection from roentgen.grid import IconCollection
from roentgen.icon import IconSet from roentgen.icon import IconSet
from test import SCHEME, SHAPE_EXTRACTOR, workspace from tests import SCHEME, SHAPE_EXTRACTOR, workspace
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"

View file

@ -2,7 +2,7 @@
Test label generation for nodes. Test label generation for nodes.
""" """
from roentgen.text import Label from roentgen.text import Label
from test import SCHEME from tests import SCHEME
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"

View file

@ -3,7 +3,7 @@ Test MapCSS generation.
""" """
from roentgen.mapcss import MapCSSWriter from roentgen.mapcss import MapCSSWriter
from roentgen.scheme import NodeMatcher from roentgen.scheme import NodeMatcher
from test import SCHEME from tests import SCHEME
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"

View file

@ -1,7 +1,7 @@
""" """
Test style constructing for ways and areas. Test style constructing for ways and areas.
""" """
from test import SCHEME from tests import SCHEME
__author__ = "Sergey Vartanov" __author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru" __email__ = "me@enzet.ru"