izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
a60-svg.h
Go to the documentation of this file.
1// svg API -*- mode: C++ -*-
2
3// Copyright (C) 2019-2025 Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the alpha60-MiL SVG library. This library is
6// free software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the Free
8// Software Foundation; either version 3, or (at your option) any
9// later 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_H
17#define MiL_SVG_H 1
18
19#include <cstddef>
20#include <cmath>
21#include <algorithm>
22#include <array>
23#include <tuple>
24#include <string>
25#include <vector>
26#include <set>
27#include <unordered_map>
28#include <sstream>
29
30/**
31 * Scalable Vector Graphics (SVG) namespace
32 */
33namespace svg {
34
35/// Base string types.
36using std::string;
37using strings = std::vector<string>;
39using vvstrings = std::vector<strings>;
40
41// Utility function, like regex_replace.
42inline void
43string_replace(std::string& target, const std::string& match,
44 const std::string& replace)
45{
46 size_t pos = 0;
47 while((pos = target.find(match, pos)) != std::string::npos)
48 {
49 target.replace(pos, match.length(), replace);
50 pos += replace.length();
51 }
52}
53
54
55/// Base integer type: positive and negative, signed integral value.
56using ushort = unsigned short;
57using uint = unsigned int;
58using ulong = unsigned long;
59using ssize_type = int;
60
61/// Base floating point type.
62using space_type = double;
63
64/// Point (x,y) in 2D space.
65using point_2t = std::tuple<space_type, space_type>;
66
67/// Point (x,y) in 2D space with weight n.
68using point_2tn = std::tuple<point_2t, ssize_type>;
69
70
71/// Convert point_2t to string.
72string
74{
75 auto [ x, y ] = p;
76 std::ostringstream oss;
77 oss << x << ',' << y;
78 return oss.str();
79}
80
81/// Split range, so one dimension of (x,y) cartesian plane.
82using vspace = std::vector<double>;
83
84/// Latitude and Longitude Ranges.
85using srange = std::set<point_2t>;
86using vrange = std::vector<point_2t>;
87using vvranges = std::vector<vrange>;
88
89
90/// Decompose/split 2D ranges to 1D spaces, perhaps with scaling.
91void
92split_vrange(const vrange& cpoints, vspace& xpoints, vspace& ypoints,
93 const double xscale = 1, const double yscale = 1)
94{
95 for (const auto& [x, y] : cpoints)
96 {
97 xpoints.push_back(x / xscale);
98 ypoints.push_back(y / yscale);
99 }
100}
101
102
103/// Union two ranges.
104vrange
105union_vrange(const vrange& r1, const vrange& r2)
106{
107 vrange vr;
108 vr.insert(vr.end(), r1.begin(), r1.end());
109 vr.insert(vr.end(), r2.begin(), r2.end());
110 return vr;
111}
112
113
114/// For each dimension of vrnage, find min/max and return (xmax, ymax)
115/// NB: Assumes zero is min.
117max_vrange(vspace& xpoints, vspace& ypoints, const uint pown)
118{
119 point_2t rangemaxx = { 0, 0 };
120 if (!xpoints.empty() && !ypoints.empty())
121 {
122 sort(xpoints.begin(), xpoints.end());
123 sort(ypoints.begin(), ypoints.end());
124
125 // For x axis, need to insert padding iff axes are scaled down
126 // and/or have values with truncated significant digits.
127 const bool padp(true);
128 if (padp)
129 {
130 const double sigd = pow(10, pown);
131
132 const double dx = xpoints.back();
133 double ix = std::round(dx * sigd) / sigd;
134 if (ix > dx)
135 xpoints.push_back(ix);
136
137 const double dy = ypoints.back();
138 uint iy = std::round(dy * sigd) / sigd;
139 if (iy > dy)
140 ypoints.push_back(iy);
141 }
142
143 // Find combined ranges, assume zero start.
144 rangemaxx = std::make_tuple(xpoints.back(), ypoints.back());
145 }
146 return rangemaxx;
147}
148
149
150/// Just the range info, none of the temporary objects.
152max_vrange(const vrange& points, const uint pown,
153 const double xscale = 1, const double yscale = 1)
154{
155 vspace pointsx;
156 vspace pointsy;
157 split_vrange(points, pointsx, pointsy, xscale, yscale);
158 point_2t ret = max_vrange(pointsx, pointsy, pown);
159 return ret;
160}
161
162
163/// Truncate double to double with pown signifigant digits.
164vspace
165narrow_vspace(const vspace& points, uint pown)
166{
167 const double sigd = pow(10, pown);
168 vspace npoints;
169 for (const double& d : points)
170 {
171 double dn(d);
172 if (dn > 0)
173 {
174 uint itrunc(dn * sigd);
175 npoints.push_back(itrunc / sigd);
176 }
177 else
178 npoints.push_back(dn);
179 }
180 return npoints;
181}
182
183
184/// Scale value from min to max on range (nfloor, nceil).
185double
187 const ssize_type max,
188 const ssize_type nfloor, const ssize_type nceil)
189{
190 double rmultp(nceil - nfloor);
191 double valnum(value - min);
192 double valdenom(max - min);
193 double weightn = (rmultp * (valnum / valdenom)) + nfloor;
194 return weightn;
195}
196
197
198/// Find cartesian distance between two 2D points.
199space_type
201{
202 auto [ x1, y1 ] = p1;
203 auto [ x2, y2 ] = p2;
204 auto distancex = (x2 - x1) * (x2 - x1);
205 auto distancey = (y2 - y1) * (y2 - y1);
206 space_type distance = sqrt(distancex + distancey);
207 return distance;
208}
209
210
211// Does point p1 of radius r1 intersect point p2 with radius r2?
212// https://developer.mozilla.org x 2D_collision_detection
213bool
214detect_collision(const point_2t& p1, const int r1, const point_2t& p2,
215 const int r2)
216{
217 bool ret(false);
218 if (distance_cartesian(p1, p2) < r1 + r2)
219 ret = true;
220 return ret;
221}
222
223
224/// Resolution of output display device.
225double&
227{
228 static double dpi(96.0);
229 return dpi;
230}
231
232
233/// Conversion between point size to pixels given dpi density.
234double
235pt_to_px(const uint i = 1)
236{
237 // 1pt is equal to exactly 1/72th of an inch.
238 // On a 72dpi output device (display), this is 1 (aka 72 * 1/72).
239 // On a 90dpi output device (display), this is 1.25 (aka 90 * 1/72).
240 // On a 96dpi output device (display), this is 1.33 (aka 96 * 1/72).
241 // constexpr double dpimult = (get_dpi() / 72);
242
243 // Or 18 pt -> 13.5 px -> 1.33
244 // Or 30 pt -> 22.5 px -> 1.33
245 constexpr double dpimult = 1.33;
246 return std::lround(i * dpimult);
247}
248
249
250/// Approximate pixel height of type of point size @sz.
251constexpr double
253{ return 0.58 * sz; }
254
255
256/// Approximate pixel height of type of point size @sz.
257constexpr double
259{ return 0.94 * sz; }
260
261
262/**
263 * SVG Constants
264 */
265namespace constants {
266
267/// Formatting character constants.
268constexpr char space(' ');
269constexpr char quote('"');
270constexpr char hyphen('-');
271constexpr char comma(',');
272constexpr char tab('\t');
273constexpr char newline('\n');
274
275
276/**
277 Numeric constants.
278 pi = double(22)/double(7);
279 pi = 3.14159265358979323846
280*/
281constexpr double pi(3.14159265358979323846);
282
283} // namespace constants
284
285/// Inject nested namepace constants into svg namespace with alias k.
286namespace k = constants;
287
288} // namespace svg
289
290
291#include "a60-svg-color.h" // color, color_qi, color_qf
293#include "a60-svg-color-band.h"
294#include "a60-svg-base-types.h" // area, style, filter, transform, typography
295#include "a60-svg-constants.h"
296#include "a60-svg-elements.h"
298#include "a60-svg-render-state.h"
301#include "a60-svg-sequences.h"
302
303#endif
constexpr double pi(3.14159265358979323846)
constexpr char quote('"')
constexpr char comma(',')
constexpr char newline('\n')
constexpr char space(' ')
Formatting character constants.
constexpr char tab('\t')
constexpr char hyphen('-')
unsigned short ushort
Base integer type: positive and negative, signed integral value.
Definition a60-svg.h:56
bool detect_collision(const point_2t &p1, const int r1, const point_2t &p2, const int r2)
Definition a60-svg.h:214
vspace narrow_vspace(const vspace &points, uint pown)
Truncate double to double with pown signifigant digits.
Definition a60-svg.h:165
vrange union_vrange(const vrange &r1, const vrange &r2)
Union two ranges.
Definition a60-svg.h:105
std::set< point_2t > srange
Latitude and Longitude Ranges.
Definition a60-svg.h:85
double scale_value_on_range(const ssize_type value, const ssize_type min, const ssize_type max, const ssize_type nfloor, const ssize_type nceil)
Scale value from min to max on range (nfloor, nceil).
Definition a60-svg.h:186
int ssize_type
Definition a60-svg.h:59
const string to_string(const unit e)
void string_replace(std::string &target, const std::string &match, const std::string &replace)
Definition a60-svg.h:43
double pt_to_px(const uint i=1)
Conversion between point size to pixels given dpi density.
Definition a60-svg.h:235
double space_type
Base floating point type.
Definition a60-svg.h:62
unsigned long ulong
Definition a60-svg.h:58
std::vector< strings > vvstrings
Definition a60-svg.h:39
std::vector< vrange > vvranges
Definition a60-svg.h:87
std::vector< point_2t > vrange
Definition a60-svg.h:86
point_2t max_vrange(vspace &xpoints, vspace &ypoints, const uint pown)
For each dimension of vrnage, find min/max and return (xmax, ymax) NB: Assumes zero is min.
Definition a60-svg.h:117
std::tuple< point_2t, ssize_type > point_2tn
Point (x,y) in 2D space with weight n.
Definition a60-svg.h:68
constexpr double char_width_to_px(const uint sz)
Approximate pixel height of type of point size @sz.
Definition a60-svg.h:252
std::vector< double > vspace
Split range, so one dimension of (x,y) cartesian plane.
Definition a60-svg.h:82
strings vstrings
Definition a60-svg.h:38
constexpr double char_height_to_px(const uint sz)
Approximate pixel height of type of point size @sz.
Definition a60-svg.h:258
void split_vrange(const vrange &cpoints, vspace &xpoints, vspace &ypoints, const double xscale=1, const double yscale=1)
Decompose/split 2D ranges to 1D spaces, perhaps with scaling.
Definition a60-svg.h:92
double & get_dpi()
Resolution of output display device.
Definition a60-svg.h:226
unsigned int uint
Definition a60-svg.h:57
space_type distance_cartesian(const point_2t &p1, const point_2t &p2)
Find cartesian distance between two 2D points.
Definition a60-svg.h:200
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space.
Definition a60-svg.h:65
std::vector< string > strings
Definition a60-svg.h:37