izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
a60-svg-grid-matrix-systems.h
Go to the documentation of this file.
1// svg grid and matrix placement -*- mode: C++ -*-
2
3// Copyright (c) 2021,2024 Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the izzi library. This library is free
6// software; you can redistribute it and/or modify it under the terms
7// of the GNU General Public License as published by the Free Software
8// Foundation; either version 3, or (at your option) any later
9// version.
10
11// This library is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15
16#ifndef MiL_SVG_GRID_MATRIX_SYSTEMS_H
17#define MiL_SVG_GRID_MATRIX_SYSTEMS_H 1
18
19namespace svg {
20
21/// Maximum number of individual items to be placed in grid cells.
22/// A 1x4 grid can contain up to 4 items.
23/// A 2x4 grid can contain up to 8 items.
24/// A 3x3 grid can contain up to 9 items.
25constexpr uint matrix_max_items = 8;
26
27
28/// Grid style mode.
30
31
32/// Cell size 3x3 for n items with margin spacing on either size.
34cell_size_3x3_matrix(const area<> a, const uint n, const double margin)
35{
36 const auto [width, height] = a;
37 const auto minsz = std::min(width, height);
38 const double minszadj = minsz - (2 * margin);
39 const ulong delta = minszadj / ((n / 3) + 1);
40 return delta;
41}
42
43/**
44 Move around a three by three grid of glyphs
45
46 1 2 3
47 4 5 6
48 7 8 9
49
50 given
51
52 1. a center point located at iteration 5,
53 2. cell width,
54 3. and iteration or cell number [0,8]
55
56 The centerweight matrix_variant has cells arranged as above.
57 The other variant styles, distort the matrix as specified below.
58*/
60to_point_in_3x3_matrix(const area<> a, const uint i, const double margin,
62{
63 using std::make_tuple;
64
65 // v0 Centerweight grid layout.
66 std::array<point_2t, 9> kernel;
68 {
69 constexpr std::array<point_2t, 9> kernelcw
70 {
71 make_tuple(-1, 1), make_tuple(0, 1), make_tuple(1, 1),
72 make_tuple(-1, 0), make_tuple(0, 0), make_tuple(1, 0),
73 make_tuple(-1, -1), make_tuple(0, -1), make_tuple(1, -1)
74 };
75 kernel = kernelcw;
76 }
77
78 // v3 Centerweight grid layout, svg coordinate system.
80 {
81 constexpr std::array<point_2t, 9> kernelcwsvg
82 {
83 make_tuple(-1, -1), make_tuple(0, -1), make_tuple(1, -1),
84 make_tuple(-1, 0), make_tuple(0, 0), make_tuple(1, 0),
85 make_tuple(-1, 1), make_tuple(0, 1), make_tuple(1, 1)
86 };
87 kernel = kernelcwsvg;
88 }
89
90 // v1 Veronica layout 1.
91 if (vnt == matrix_variant::veronica)
92 {
93 constexpr std::array<point_2t, 9> kernelver
94 {
95 make_tuple(-1, 0), make_tuple(0, 0), make_tuple(1, 0),
96 make_tuple(-1, 1), make_tuple(0, -1), make_tuple(0, 0),
97 make_tuple(-1, -1), make_tuple(0, 1), make_tuple(1, 0)
98 };
99 kernel = kernelver;
100 }
101
102 // v2 Very Slim layout 2.
103 if (vnt == matrix_variant::slim)
104 {
105 constexpr std::array<point_2t, 9> kernelslim
106 {
107 make_tuple(-1, -1), make_tuple(0, -1), make_tuple(1, -1),
108 make_tuple(0, 0), make_tuple(1, 0), make_tuple(-1, 0),
109 make_tuple(-1, 1), make_tuple(0, 1), make_tuple(1, 1)
110 };
111 kernel = kernelslim;
112 };
113
114
115 // Sanity check iteration count.
116 if (i > 8)
117 {
118 string m("to_point_in_3x3_matrix: ");
119 m += "error iteration count too big for matrix, i is: ";
120 m += std::to_string(i);
121 m += k::newline;
122 throw std::runtime_error(m);
123 }
124
125 const auto delta = cell_size_3x3_matrix(a, matrix_max_items, margin);
126 const point_2t origin = a.center_point();
127 auto [ x, y ] = origin;
128 auto [ xm, ym ] = kernel[i];
129 auto xnew = x + (xm * delta);
130 auto ynew = y + (ym * delta);
131 return make_tuple(xnew, ynew);
132}
133
134
135/**
136 Move around a 2 by 4 grid of glyphs
137
138 1 2 3 4
139 5 6 7 8
140
141 given
142
143 1. a center point located equidistant to 2, 3, 6, 7,
144 2. cell width,
145 3. and iteration or cell number [0,7]
146*/
148to_point_in_2x4_matrix(const area<> a, const uint i, const double margin)
149{
150 const point_2t origin = a.center_point();
151
152 const auto [width, height] = a;
153 const double widthadj = width - (2 * margin);
154 const ulong xdelta = widthadj / ((matrix_max_items / 2) + 1);
155
156 const double heightadj = height - (2 * margin);
157 const ulong ydelta = heightadj / 2;
158
159 using p2d = point_2t;
160 static std::array<point_2t, 8> kernel =
161 {
162 // Modified centerweight grid layout.
163 p2d(-1.5, -0.5), p2d(-0.5, -0.5), p2d(0.5, -0.5), p2d(1.5, -0.5),
164 p2d(-1.5, 0.5), p2d(-0.5, 0.5), p2d(0.5, 0.5), p2d(1.5, 0.5)
165 };
166
167 // Sanity check iteration count.
168 if (i > 7)
169 {
170 string m("to_point_in_2x4_matrix: ");
171 m += "error iteration count too big for matrix, i is: ";
172 m += std::to_string(i);
173 m += k::newline;
174 throw std::runtime_error(m);
175 }
176
177 auto [ x, y ] = origin;
178 auto [ xm, ym ] = kernel[i];
179 auto xnew = x + (xm * xdelta);
180 auto ynew = y + (ym * ydelta);
181 return std::make_tuple(xnew, ynew);
182}
183
184
185/// For positioning a linear list of glyphs along a horizontal line.
186/// Assuming i is from find_id_index with tag, so is an offset starting at zero.
188to_point_in_1x8_matrix(const area<> a, const uint i, const double margin)
189{
190 using std::make_tuple;
191
192 const auto [width, height] = a;
193 const auto widthadj = width - (2 * margin);
194 const ulong xdelta = widthadj / (matrix_max_items + 1);
195
196 const uint xoff = margin + xdelta + (i * xdelta);
197 const uint yoff = height / 2;
198
199 return make_tuple(xoff, yoff);
200}
201
202
203/// For positioning a linear list of glyphs along a horizontal line.
204/// @param n is number of matrix cells, greater than one.
205/// @param i is from find_id_index with tag, so is an offset starting at zero.
206/// @param centeredp adjusts to the center of the cell, default is left aligned.
207/// @param y is what y axis to use.
209to_point_in_1xn_matrix(const area<> a, const uint n, const uint i,
210 const double margin, const double y,
211 const bool centeredp = false)
212{
213 using std::make_tuple;
214
215 const auto [width, height] = a;
216 const auto widthadj = width - (2 * margin);
217 const double xdelta = widthadj / n;
218
219 double xoff = margin + (i * xdelta);
220
221 if (centeredp)
222 xoff += xdelta / 2;
223
224 return make_tuple(xoff, y);
225}
226
227
228/// Default matrix position.
230to_point_in_matrix(const area<> a, const uint i, const double margin)
231{ return to_point_in_3x3_matrix(a, i, margin); }
232
233
234} // namespace svg
235
236
237#endif
point_2t to_point_in_3x3_matrix(const area<> a, const uint i, const double margin, const matrix_variant vnt=matrix_variant::slim)
point_2t to_point_in_2x4_matrix(const area<> a, const uint i, const double margin)
ulong cell_size_3x3_matrix(const area<> a, const uint n, const double margin)
Cell size 3x3 for n items with margin spacing on either size.
unsigned long ulong
Definition a60-svg.h:58
matrix_variant
Grid style mode.
point_2t to_point_in_1xn_matrix(const area<> a, const uint n, const uint i, const double margin, const double y, const bool centeredp=false)
For positioning a linear list of glyphs along a horizontal line.
constexpr uint matrix_max_items
Maximum number of individual items to be placed in grid cells. A 1x4 grid can contain up to 4 items....
point_2t to_point_in_matrix(const area<> a, const uint i, const double margin)
Default matrix position.
point_2t to_point_in_1x8_matrix(const area<> a, const uint i, const double margin)
For positioning a linear list of glyphs along a horizontal line. Assuming i is from find_id_index wit...
unsigned int uint
Definition a60-svg.h:57
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space.
Definition a60-svg.h:65