diff options
| author | Lex Neva <github.com@lexneva.name> | 2023-01-16 14:27:06 -0500 |
|---|---|---|
| committer | Lex Neva <github.com@lexneva.name> | 2023-02-20 15:27:55 -0500 |
| commit | ba835b4f5e33f404b7bed9369a1b425a67b312c5 (patch) | |
| tree | 95a22285d40dcf526973a56a193eaf5fdea53dfb /lib/tiles.py | |
| parent | b76146aa91824817f297e9463094ec5231950e3f (diff) | |
meander fill: initial version
Diffstat (limited to 'lib/tiles.py')
| -rw-r--r-- | lib/tiles.py | 96 |
1 files changed, 61 insertions, 35 deletions
diff --git a/lib/tiles.py b/lib/tiles.py index 34097f67..e9f0305a 100644 --- a/lib/tiles.py +++ b/lib/tiles.py @@ -5,8 +5,10 @@ import os from shapely.geometry import LineString from shapely.prepared import prep +from .debug import debug from .svg import apply_transforms -from .utils import get_bundled_dir, guess_inkscape_config_path, Point +from .svg.tags import SODIPODI_NAMEDVIEW +from .utils import cache, get_bundled_dir, guess_inkscape_config_path, Point from random import random @@ -15,51 +17,68 @@ class Tile: self._load_tile(path) def _load_tile(self, tile_path): - tile_svg = inkex.load_svg(tile_path) - self.name = self._get_name(tile_path) - self._load_paths(tile_svg) - self._load_dimensions(tile_svg) - self._load_buffer_size(tile_svg) - self._load_parallelogram(tile_svg) + self.tile_svg = inkex.load_svg(tile_path) + self.tile_path = tile_path + self.name = self._get_name(self.tile_svg, tile_path) + self.tile = None + self.width = None + self.height = None + self.buffer_size = None + self.shift0 = None + self.shift1 = None def __repr__(self): return f"Tile({self.name}, {self.shift0}, {self.shift1})" __str__ = __repr__ - def _get_name(self, tile_path): - return os.path.splitext(os.path.basename(tile_path))[0] + def _get_name(self, tile_svg, tile_path): + name = tile_svg.get(SODIPODI_NAMEDVIEW) + if name: + return name + else: + return os.path.splitext(os.path.basename(tile_path))[0] + + def _load(self): + self._load_paths(self.tile_svg) + self._load_dimensions(self.tile_svg) + self._load_buffer_size(self.tile_svg) + self._load_parallelogram(self.tile_svg) def _load_paths(self, tile_svg): - path_elements = tile_svg.findall('.//svg:path', namespaces=inkex.NSS) - self.tile = self._path_elements_to_line_strings(path_elements) - # self.center, ignore, ignore = self._get_center_and_dimensions(self.tile) + if self.tile is None: + path_elements = tile_svg.findall('.//svg:path', namespaces=inkex.NSS) + self.tile = self._path_elements_to_line_strings(path_elements) + # self.center, ignore, ignore = self._get_center_and_dimensions(self.tile) def _load_dimensions(self, tile_svg): - svg_element = tile_svg.getroot() - self.width = svg_element.viewport_width - self.height = svg_element.viewport_height + if self.width is None: + svg_element = tile_svg.getroot() + self.width = svg_element.viewport_width + self.height = svg_element.viewport_height def _load_buffer_size(self, tile_svg): - circle_elements = tile_svg.findall('.//svg:circle', namespaces=inkex.NSS) - if circle_elements: - self.buffer_size = circle_elements[0].radius - else: - self.buffer_size = 0 + if self.buffer_size is None: + circle_elements = tile_svg.findall('.//svg:circle', namespaces=inkex.NSS) + if circle_elements: + self.buffer_size = circle_elements[0].radius + else: + self.buffer_size = 0 def _load_parallelogram(self, tile_svg): - parallelogram_elements = tile_svg.findall(".//svg:*[@class='para']", namespaces=inkex.NSS) - if parallelogram_elements: - path_element = parallelogram_elements[0] - path = apply_transforms(path_element.get_path(), path_element) - subpaths = path.to_superpath() - subpath = subpaths[0] - points = [Point.from_tuple(p[1]) for p in subpath] - self.shift0 = points[1] - points[0] - self.shift1 = points[2] - points[1] - else: - self.shift0 = Point(self.width, 0) - self.shift1 = Point(0, self.height) + if self.shift0 is None: + parallelogram_elements = tile_svg.findall(".//svg:*[@class='para']", namespaces=inkex.NSS) + if parallelogram_elements: + path_element = parallelogram_elements[0] + path = apply_transforms(path_element.get_path(), path_element) + subpaths = path.to_superpath() + subpath = subpaths[0] + points = [Point.from_tuple(p[1]) for p in subpath] + self.shift0 = points[1] - points[0] + self.shift1 = points[2] - points[1] + else: + self.shift0 = Point(self.width, 0) + self.shift1 = Point(0, self.height) def _path_elements_to_line_strings(self, path_elements): lines = [] @@ -80,7 +99,7 @@ class Tile: return center, width, height - def translate_tile(self, shift): + def _translate_tile(self, shift): translated_tile = [] for start, end in self.tile: @@ -90,6 +109,7 @@ class Tile: return translated_tile + @debug.time def to_graph(self, shape, only_inside=True, pad=True): """Apply this tile to a shape, repeating as necessary. @@ -98,6 +118,8 @@ class Tile: Each edge has an attribute 'line_string' with the LineString representation of this edge. """ + self._load() + shape_center, shape_width, shape_height = self._get_center_and_dimensions(shape) shape_diagonal = (shape_width ** 2 + shape_height ** 2) ** 0.5 graph = Graph() @@ -113,7 +135,7 @@ class Tile: for repeat1 in range(floor(-tiles1 / 2), ceil(tiles1 / 2)): shift0 = repeat0 * self.shift0 + shape_center shift1 = repeat1 * self.shift1 + shape_center - this_tile = self.translate_tile(shift0 + shift1) + this_tile = self._translate_tile(shift0 + shift1) for line in this_tile: line_string = LineString(line) if not only_inside or prepared_shape.contains(line_string): @@ -127,10 +149,14 @@ def all_tile_paths(): get_bundled_dir('tiles')] +@cache def all_tiles(): + tiles = [] for tile_dir in all_tile_paths(): try: for tile_file in sorted(os.listdir(tile_dir)): - yield Tile(os.path.join(tile_dir, tile_file)) + tiles.append(Tile(os.path.join(tile_dir, tile_file))) except FileNotFoundError: pass + + return tiles |
