Table of Contents
A simple SVG renderer for 2D grids. Grids cells can contain references to tiles defined as SVG elements of size 1x1.
Implementation
from dataclasses import dataclass, field @dataclass class Renderer: width: int height: int patterns: dict[str, str] = field(default_factory=dict) _grid: dict[(int, int), str] = field(default_factory=dict) def set_tile(self, x: int, y: int, key: str): self._grid[(x, y)] = key def _format_pattern(self, key: str, value: str): return f''' <symbol id="{key}" viewBox="0 0 1 1"> {value} </symbol> ''' def _format_outline(self, width: int, height: int): return f''' <rect x="0" y="0" width="{width}" height="{height}" stroke="gray" fill="none" /> ''' def _format_tile(self, x: int, y: int, key: str, tile_size: int): return f''' <use x="{x * tile_size}" y="{y * tile_size}" width="{tile_size}" height="{tile_size}" href="#{key}" /> ''' def _format(self, tile_size: int): width = self.width * tile_size height = self.height * tile_size yield f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}">\n' yield '<defs>' for key, value in self.patterns.items(): yield self._format_pattern(key, value) yield '</defs>' yield self._format_outline(width, height) for (x, y), key in self._grid.items(): yield self._format_tile(x, y, key, tile_size) yield '</svg>' def render_file(self, path: str, tile_size: int): with open(path, "w") as f: for line in self._format(tile_size): f.write(line) def render_inline(self, tile_size: int) -> str: return "\n".join(self._format(tile_size))
Example
<<svg_tile_renderer>> r = Renderer(6, 3) r.patterns["v"] = '<line x1="0.5" y1="0" x2="0.5" y2="1" stroke="black" stroke-width="0.1"/>' r.patterns["h"] = '<line x1="0" y1="0.5" x2="1" y2="0.5" stroke="black" stroke-width="0.1"/>' r.patterns["c"] = '<circle cx="0.5" cy="0.5" r="0.5" fill="red"/>' r.set_tile(0, 0, "v") r.set_tile(0, 1, "c") r.set_tile(1, 1, "h") r.set_tile(2, 1, "h") r.set_tile(3, 1, "h") r.set_tile(4, 1, "c") r.set_tile(5, 1, "h") r.set_tile(4, 2, "v") r.render_file("images/svg_tiles/test.svg", tile_size=40)