84namespace ca_svg_detail {
88 constexpr char digits[] =
"0123456789abcdef";
89 std::string
out =
"#000000";
101 double min_x = std::numeric_limits<double>::infinity();
102 double min_y = std::numeric_limits<double>::infinity();
103 double max_x = -std::numeric_limits<double>::infinity();
104 double max_y = -std::numeric_limits<double>::infinity();
106 void include(
const double x,
const double y)
noexcept
117 const double pad =
opts.draw_grid ?
opts.stroke_width : 0.0;
122 out <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
123 out <<
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" << x <<
' ' <<
y <<
' ' <<
w <<
' '
124 <<
h <<
"\" width=\"" <<
w <<
"\" height=\"" <<
h <<
"\">\n";
130 out <<
" stroke=\"" <<
rgb_hex(
opts.stroke_colour) <<
"\" stroke-width=\"" <<
opts.stroke_width
133 out <<
" stroke=\"none\"";
138 for (std::size_t i = 0; i <
pts.size(); ++i)
150 for (
int k = 0;
k < 6; ++
k)
152 constexpr double pi = 3.14159265358979323846;
153 const double angle = (60.0 *
static_cast<double>(
k) - 30.0) * pi / 180.0;
154 pts.append(std::array<double, 2>{
centre[0] + radius * std::cos(
angle),
162 constexpr double sqrt3 = 1.7320508075688772;
167 using Pt = std::array<double, 2>;
204template <
typename Lattice,
typename Palette>
212 { p(v) } -> std::convertible_to<RGB8>;
216 static_assert(
Lattice::rank == 2,
"render_lattice_svg requires a rank-2 frame");
219 ca_svg_detail::Bounds b;
223 for (
ca_size_t q = 0; q < frame.cols(); ++q)
224 for (
const auto &p : ca_svg_detail::
hex_points(
226 b.include(p[0], p[1]);
229 if (frame.rows() == 0
or frame.cols() == 0)
232 b.include(
static_cast<double>(frame.cols()) *
opts.cell_size,
233 static_cast<double>(frame.rows()) *
opts.cell_size);
239 for (
ca_size_t c = 0; c < frame.cols(); ++c)
240 for (
const auto &p : ca_svg_detail::
tri_points(
242 b.include(p[0], p[1]);
243 if (frame.rows() == 0
or frame.cols() == 0)
246 b.include(
static_cast<double>(frame.cols()) *
opts.cell_size,
247 static_cast<double>(frame.rows()) *
opts.cell_size);
253 b.include(
static_cast<double>(frame.
size(1)) *
opts.cell_size,
254 static_cast<double>(frame.
size(0)) *
opts.cell_size);
261 for (
ca_size_t q = 0; q < frame.cols(); ++q)
264 const auto state = frame.at_axial(a);
267 out <<
" <polygon points=\"";
277 for (
ca_size_t c = 0; c < frame.cols(); ++c)
280 const auto state = frame.at_tri(
tc);
283 out <<
" <polygon points=\"";
300 out <<
" <rect x=\"" <<
static_cast<double>(c) *
opts.cell_size <<
"\" y=\""
301 <<
static_cast<double>(
r) *
opts.cell_size <<
"\" width=\"" <<
opts.cell_size
302 <<
"\" height=\"" <<
opts.cell_size <<
"\" fill=\""
321template <
typename Lattice>
343template <
typename Lattice,
typename Palette>
351 { p(v) } -> std::convertible_to<RGB8>;
354 std::ostringstream
out;
363template <
typename Palette>
381 const std::size_t zero_pad = 6)
400 template <
typename Lattice>
419 template <
typename Lattice>
425 if (
const auto parent = path.parent_path();
not parent.empty())
426 std::filesystem::create_directories(parent);
427 std::ofstream
out(path);
436template <
typename Palette>
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
size_t size_t int32_t * out
Directory-backed frame sinks for CA trajectories.
File-format readers and writers for cellular-automata frames.
Simple dynamic array with automatic resizing and functional operations.
Lattice that adds boundary-aware access on top of a storage.
typename Storage::state_type state_type
typename Storage::coord_type coord_type
static constexpr std::size_t rank
ca_size_t size() const noexcept
state_type at(const coord_type &c) const
Strict access: throws if c is out of range.
Path-pattern sink that writes one SVG file per accepted frame.
void accept(const std::size_t step, const Lattice &frame)
Write one SVG frame using the default dead state.
std::filesystem::path pattern_
void accept(const std::size_t step, const Lattice &frame, const typename Lattice::state_type &dead_state)
Write one SVG frame, threading the lattice-specific dead state.
static void flush()
SVG frames are written eagerly; this is a no-op.
Svg_Frame_Sink(std::filesystem::path path_pattern, Palette palette, SVG_Render_Options opts={}, const std::size_t zero_pad=6)
Build an SVG frame sink.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
void write_svg_header(std::ostream &out, const Bounds &b, const SVG_Render_Options &opts)
Array< std::array< double, 2 > > hex_points(Hex_Axial a, const double radius)
void write_points(std::ostream &out, const Array< std::array< double, 2 > > &pts)
Array< std::array< double, 2 > > tri_points(Tri_Coord c, const double side)
std::string rgb_hex(const RGB8 c)
void write_style(std::ostream &out, const SVG_Render_Options &opts)
std::array< double, 2 > tri_pixel_centre(const Tri_Coord &c, const double side) noexcept
Cartesian centre of a triangle in (i, j) units.
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
std::array< double, 2 > axial_to_pixel_pointy(Hex_Axial a, double radius) noexcept
Pointy-top pixel coordinates of an axial cell.
std::filesystem::path format_step_path(const std::filesystem::path &pattern, const std::size_t step, const std::size_t zero_pad=6)
Format a step-indexed file path.
void render_lattice_svg(std::ostream &out, const Lattice &frame, Palette &&palette, const SVG_Render_Options &opts={}, const typename Lattice::state_type &dead_state=typename Lattice::state_type{})
Render a supported rank-2 CA frame as SVG.
constexpr bool tri_is_up(const Tri_Coord &c) noexcept
std::size_t ca_size_t
Unsigned size component used for extents and counts.
std::string render_lattice_svg_string(const Lattice &frame, Palette &&palette, const SVG_Render_Options &opts={}, const typename Lattice::state_type &dead_state=typename Lattice::state_type{})
Return a frame rendered as SVG.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Axial integer coordinates (q, r) of a hex cell.
RGB byte triplet used by PPM exporters.
std::uint8_t g
green channel
std::uint8_t b
blue channel
std::uint8_t r
red channel
double stroke_width
grid stroke width
RGB8 stroke_colour
grid colour
double cell_size
logical cell size in SVG units
bool draw_grid
draw cell borders
bool omit_dead_cells
skip cells equal to dead_state
Coordinates of a triangular cell as (i, j) integers.
void include(const double x, const double y) noexcept
Dynamic array container with automatic resizing.
C++20 concepts for the Cellular Automata module.
Hexagonal lattice with axial / offset / cube coordinate conversions and a TikZ-compatible pixel mappi...
Triangular lattice with up/down parity helpers and pixel mapping suitable for visualisation.