izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
izzi-points.h
Go to the documentation of this file.
1// izzi 2d points -*- mode: C++ -*-
2
3// Copyright (c) 2025, Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the alpha60 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 izzi_POINTS_H
17#define izzi_POINTS_H 1
18
19namespace svg {
20
21/// Point (x,y) in 2D space, space_type defaults to double.
22using point_2t = std::tuple<space_type, space_type>;
23
24/// Point (x,y) in 2D space with weight n.
25using point_2tn = std::tuple<ulong, point_2t>;
26
27/// Named Point (x,y) in 2D space.
28using point_2ts = std::tuple<string, point_2t>;
29
30/// Point (x,y,z) in 3D space, space_type defaults to double.
31using point_3t = std::tuple<space_type, space_type, space_type>;
32
33
34/// Convert point_2t to string.
35string
37{
38 auto [ x, y ] = p;
39 std::ostringstream oss;
40 oss << x << ',' << y;
41 return oss.str();
42}
43
44/// Convert point_3t to string.
45string
47{
48 auto [ x, y, z ] = p;
49 std::ostringstream oss;
50 oss << x << ',' << y << ',' << z;
51 return oss.str();
52}
53
54
55/// Split range, so one dimension of (x,y) cartesian plane.
56using vspace = std::vector<space_type>;
57
58/// Latitude and Longitude Ranges.
59using srange = std::set<point_2t>;
60using srangen = std::set<point_2tn>;
61using vrange = std::vector<point_2t>;
62using vrangen = std::vector<point_2tn>;
63using vvranges = std::vector<vrange>;
64
65using vrangenamed = std::vector<point_2ts>;
66
67
68/// Decompose/split 2D ranges to 1D spaces, perhaps with scaling.
69void
70split_vrange(const vrange& cpoints, vspace& xpoints, vspace& ypoints,
71 const double xscale = 1, const double yscale = 1)
72{
73 for (const auto& [x, y] : cpoints)
74 {
75 xpoints.push_back(x / xscale);
76 ypoints.push_back(y / yscale);
77 }
78}
79
80
81/// Union two ranges.
83union_vrange(const vrange& r1, const vrange& r2)
84{
85 vrange vr;
86 vr.insert(vr.end(), r1.begin(), r1.end());
87 vr.insert(vr.end(), r2.begin(), r2.end());
88 return vr;
89}
90
91
92/// For each dimension of vrnage, find min/max and return (xmax, ymax)
93/// NB: Assumes zero is min.
95max_vrange(vspace& xpoints, vspace& ypoints, const uint pown)
96{
97 point_2t rangemaxx = { 0, 0 };
98 if (!xpoints.empty() && !ypoints.empty())
99 {
100 sort(xpoints.begin(), xpoints.end());
101 sort(ypoints.begin(), ypoints.end());
102
103 // For x axis, need to insert padding iff axes are scaled down
104 // and/or have values with truncated significant digits.
105 const bool padp(true);
106 if (padp)
107 {
108 const double sigd = pow(10, pown);
109
110 const double dx = xpoints.back();
111 double ix = std::round(dx * sigd) / sigd;
112 if (ix > dx)
113 xpoints.push_back(ix);
114
115 const double dy = ypoints.back();
116 uint iy = std::round(dy * sigd) / sigd;
117 if (iy > dy)
118 ypoints.push_back(iy);
119 }
120
121 // Find combined ranges, assume zero start.
122 rangemaxx = std::make_tuple(xpoints.back(), ypoints.back());
123 }
124 return rangemaxx;
125}
126
127
128/// Just the range info, none of the temporary objects.
130max_vrange(const vrange& points, const uint pown,
131 const double xscale = 1, const double yscale = 1)
132{
133 vspace pointsx;
134 vspace pointsy;
135 split_vrange(points, pointsx, pointsy, xscale, yscale);
136 point_2t ret = max_vrange(pointsx, pointsy, pown);
137 return ret;
138}
139
140
141/// Truncate double to double with pown signifigant digits.
142vspace
143narrow_vspace(const vspace& points, uint pown)
144{
145 const double sigd = pow(10, pown);
146 vspace npoints;
147 for (const double& d : points)
148 {
149 double dn(d);
150 if (dn > 0)
151 {
152 uint itrunc(dn * sigd);
153 npoints.push_back(itrunc / sigd);
154 }
155 else
156 npoints.push_back(dn);
157 }
158 return npoints;
159}
160
161/// Find cartesian distance between two 2D points.
164{
165 auto [ x1, y1 ] = p1;
166 auto [ x2, y2 ] = p2;
167 auto distancex = (x2 - x1) * (x2 - x1);
168 auto distancey = (y2 - y1) * (y2 - y1);
169 space_type distance = sqrt(distancex + distancey);
170 return distance;
171}
172
173
174// Does point p1 of radius r1 intersect point p2 with radius r2?
175// https://developer.mozilla.org x 2D_collision_detection
176bool
177detect_collision(const point_2t& p1, const int r1,
178 const point_2t& p2, const int r2)
179{
180 bool ret(false);
181 if (distance_cartesian(p1, p2) < r1 + r2)
182 ret = true;
183 return ret;
184}
185
186} // namespace svg
187
188struct Point
189{
190 double x, y;
191 std::string name;
192
193 Point(double x = 0, double y = 0, const std::string s = "")
194 : x(x), y(y), name(s) { }
195
196 double
197 distance(const Point& other) const
198 { return std::hypot(x - other.x, y - other.y); }
199
200 bool
201 operator==(const Point& other) const
202 { return x == other.x && y == other.y; }
203
204 Point
205 operator+(const Point& other) const
206 { return Point(x + other.x, y + other.y); }
207
208 Point
209 operator/(double scalar) const
210 { return Point(x / scalar, y / scalar); }
211};
212
214{
216 size_t weight;
217
218 WeightedPoint(const Point& p, size_t w)
219 : pt(p.x, p.y, p.name), weight(w) { }
220};
221
222using vpoints = std::vector<Point>;
223using vwpoints = std::vector<WeightedPoint>;
224
225
226namespace svg {
227
228/// Convert point_2ts to Point.
231{
232 vpoints outpoints;
233 outpoints.reserve(inpoints.size());
234
235 auto lconv = [](const point_2ts& p)
236 { auto [ s, pt ] = p; auto [x, y] = pt; return Point(x, y, s); };
237 std::ranges::transform(inpoints, std::back_inserter(outpoints), lconv);
238 return outpoints;
239}
240
241/// Convert Point to point_2t
244{
245 using std::make_tuple;
246 vrangenamed outpoints;
247 outpoints.reserve(inpoints.size());
248
249 auto lconv = [](const Point& p){auto pt = make_tuple(p.x, p.y); return make_tuple(p.name, pt); };
250 std::ranges::transform(inpoints, std::back_inserter(outpoints), lconv);
251 return outpoints;
252}
253
254} // namespace svg
255
256#endif
std::vector< Point > vpoints
std::vector< WeightedPoint > vwpoints
@ pt
Point where 1 pixel x 1/72 dpi x 96 PPI = .26 mm.
bool detect_collision(const point_2t &p1, const int r1, const point_2t &p2, const int r2)
vspace narrow_vspace(const vspace &points, uint pown)
Truncate double to double with pown signifigant digits.
vrange union_vrange(const vrange &r1, const vrange &r2)
Union two ranges.
Definition izzi-points.h:83
std::vector< point_2ts > vrangenamed
Definition izzi-points.h:65
std::set< point_2t > srange
Latitude and Longitude Ranges.
Definition izzi-points.h:59
std::tuple< ulong, point_2t > point_2tn
Point (x,y) in 2D space with weight n.
Definition izzi-points.h:25
const string to_string(const unit e)
double space_type
Base floating point type.
Definition a60-svg.h:63
std::vector< point_2tn > vrangen
Definition izzi-points.h:62
std::set< point_2tn > srangen
Definition izzi-points.h:60
std::vector< vrange > vvranges
Definition izzi-points.h:63
std::vector< point_2t > vrange
Definition izzi-points.h:61
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 izzi-points.h:95
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 izzi-points.h:70
vpoints vrangenamed_to_points(const vrangenamed &inpoints)
Convert point_2ts to Point.
std::tuple< string, point_2t > point_2ts
Named Point (x,y) in 2D space.
Definition izzi-points.h:28
std::vector< space_type > vspace
Split range, so one dimension of (x,y) cartesian plane.
Definition izzi-points.h:56
unsigned int uint
Definition a60-svg.h:58
space_type distance_cartesian(const point_2t &p1, const point_2t &p2)
Find cartesian distance between two 2D points.
std::tuple< space_type, space_type, space_type > point_3t
Point (x,y,z) in 3D space, space_type defaults to double.
Definition izzi-points.h:31
vrangenamed points_to_vrangenamed(const vpoints &inpoints)
Convert Point to point_2t.
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space, space_type defaults to double.
Definition izzi-points.h:22
double distance(const Point &other) const
Point operator+(const Point &other) const
bool operator==(const Point &other) const
Point(double x=0, double y=0, const std::string s="")
double x
Point operator/(double scalar) const
std::string name
double y
WeightedPoint(const Point &p, size_t w)