12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- """Utility data and functions for WFC. Implementation based on https://github.com/ikarth/wfc_2019f"""
- from __future__ import annotations
- import collections
- import logging
- import numpy as np
- from numpy.typing import NDArray
- logger = logging.getLogger(__name__)
- CoordXY = collections.namedtuple("CoordXY", ["x", "y"])
- CoordRC = collections.namedtuple("CoordRC", ["row", "column"])
- def hash_downto(a: NDArray[np.integer], rank: int, seed=0) -> NDArray[np.int64]:
- state = np.random.RandomState(seed)
- # np_random = np.random.default_rng(seed)
- assert rank < len(a.shape)
- u: NDArray[np.integer] = a.reshape((np.prod(a.shape[:rank], dtype=np.int64), -1))
- v = state.randint(1 - (1 << 63), 1 << 63, np.prod(a.shape[rank:]), dtype=np.int64)
- # v = np_random.integers(1 - (1 << 63), 1 << 63, np.prod(a.shape[rank:]), dtype=np.int64)
- return np.asarray(np.inner(u, v).reshape(a.shape[:rank]), dtype=np.int64)
- def find_pattern_center(wfc_ns):
- # wfc_ns.pattern_center = (math.floor((wfc_ns.pattern_width - 1) / 2), math.floor((wfc_ns.pattern_width - 1) / 2))
- wfc_ns.pattern_center = (0, 0)
- return wfc_ns
- def tile_grid_to_image(
- tile_grid: NDArray[np.int64],
- tile_catalog: dict[int, NDArray[np.integer]],
- tile_size: tuple[int, int],
- partial: bool = False,
- color_channels: int = 3,
- ) -> NDArray[np.integer]:
- """
- Takes a tile_grid and transforms it into an image, using the information
- in tile_catalog. We use tile_size to figure out the size the new image
- should be.
- """
- tile_dtype = next(iter(tile_catalog.values())).dtype
- new_img = np.zeros(
- (
- tile_grid.shape[0] * tile_size[0],
- tile_grid.shape[1] * tile_size[1],
- color_channels,
- ),
- dtype=tile_dtype,
- )
- if partial and (len(tile_grid.shape)) > 2:
- # TODO: implement rendering partially completed solution
- # Call tile_grid_to_average() instead.
- assert False
- else:
- for i in range(tile_grid.shape[0]):
- for j in range(tile_grid.shape[1]):
- tile = tile_grid[i, j]
- for u in range(tile_size[0]):
- for v in range(tile_size[1]):
- pixel = [200, 0, 200]
- # If we want to display a partial pattern, it is helpful to
- # be able to show empty cells.
- pixel = tile_catalog[tile][u, v]
- # TODO: will need to change if using an image with more than 3 channels
- new_img[
- (i * tile_size[0]) + u, (j * tile_size[1]) + v
- ] = np.resize(
- pixel,
- new_img[
- (i * tile_size[0]) + u, (j * tile_size[1]) + v
- ].shape,
- )
- return new_img
|