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/// Convert point_2t to string.
31string
33{
34 auto [ x, y ] = p;
35 std::ostringstream oss;
36 oss << x << ',' << y;
37 return oss.str();
38}
39
40/// Split range, so one dimension of (x,y) cartesian plane.
41using vspace = std::vector<space_type>;
42
43/// Latitude and Longitude Ranges.
44using srange = std::set<point_2t>;
45using srangen = std::set<point_2tn>;
46using vrange = std::vector<point_2t>;
47using vrangen = std::vector<point_2tn>;
48using vvranges = std::vector<vrange>;
49
50using vrangenamed = std::vector<point_2ts>;
51
52
53/// Decompose/split 2D ranges to 1D spaces, perhaps with scaling.
54void
55split_vrange(const vrange& cpoints, vspace& xpoints, vspace& ypoints,
56 const double xscale = 1, const double yscale = 1)
57{
58 for (const auto& [x, y] : cpoints)
59 {
60 xpoints.push_back(x / xscale);
61 ypoints.push_back(y / yscale);
62 }
63}
64
65
66/// Union two ranges.
68union_vrange(const vrange& r1, const vrange& r2)
69{
70 vrange vr;
71 vr.insert(vr.end(), r1.begin(), r1.end());
72 vr.insert(vr.end(), r2.begin(), r2.end());
73 return vr;
74}
75
76
77/// For each dimension of vrnage, find min/max and return (xmax, ymax)
78/// NB: Assumes zero is min.
80max_vrange(vspace& xpoints, vspace& ypoints, const uint pown)
81{
82 point_2t rangemaxx = { 0, 0 };
83 if (!xpoints.empty() && !ypoints.empty())
84 {
85 sort(xpoints.begin(), xpoints.end());
86 sort(ypoints.begin(), ypoints.end());
87
88 // For x axis, need to insert padding iff axes are scaled down
89 // and/or have values with truncated significant digits.
90 const bool padp(true);
91 if (padp)
92 {
93 const double sigd = pow(10, pown);
94
95 const double dx = xpoints.back();
96 double ix = std::round(dx * sigd) / sigd;
97 if (ix > dx)
98 xpoints.push_back(ix);
99
100 const double dy = ypoints.back();
101 uint iy = std::round(dy * sigd) / sigd;
102 if (iy > dy)
103 ypoints.push_back(iy);
104 }
105
106 // Find combined ranges, assume zero start.
107 rangemaxx = std::make_tuple(xpoints.back(), ypoints.back());
108 }
109 return rangemaxx;
110}
111
112
113/// Just the range info, none of the temporary objects.
115max_vrange(const vrange& points, const uint pown,
116 const double xscale = 1, const double yscale = 1)
117{
118 vspace pointsx;
119 vspace pointsy;
120 split_vrange(points, pointsx, pointsy, xscale, yscale);
121 point_2t ret = max_vrange(pointsx, pointsy, pown);
122 return ret;
123}
124
125
126/// Truncate double to double with pown signifigant digits.
127vspace
128narrow_vspace(const vspace& points, uint pown)
129{
130 const double sigd = pow(10, pown);
131 vspace npoints;
132 for (const double& d : points)
133 {
134 double dn(d);
135 if (dn > 0)
136 {
137 uint itrunc(dn * sigd);
138 npoints.push_back(itrunc / sigd);
139 }
140 else
141 npoints.push_back(dn);
142 }
143 return npoints;
144}
145
146/// Find cartesian distance between two 2D points.
149{
150 auto [ x1, y1 ] = p1;
151 auto [ x2, y2 ] = p2;
152 auto distancex = (x2 - x1) * (x2 - x1);
153 auto distancey = (y2 - y1) * (y2 - y1);
154 space_type distance = sqrt(distancex + distancey);
155 return distance;
156}
157
158
159// Does point p1 of radius r1 intersect point p2 with radius r2?
160// https://developer.mozilla.org x 2D_collision_detection
161bool
162detect_collision(const point_2t& p1, const int r1,
163 const point_2t& p2, const int r2)
164{
165 bool ret(false);
166 if (distance_cartesian(p1, p2) < r1 + r2)
167 ret = true;
168 return ret;
169}
170
171} // namespace svg
172
173struct Point
174{
175 double x, y;
176 std::string name;
177
178 Point(double x = 0, double y = 0, const std::string s = "")
179 : x(x), y(y), name(s) { }
180
181 double
182 distance(const Point& other) const
183 { return std::hypot(x - other.x, y - other.y); }
184
185 bool
186 operator==(const Point& other) const
187 { return x == other.x && y == other.y; }
188
189 Point
190 operator+(const Point& other) const
191 { return Point(x + other.x, y + other.y); }
192
193 Point
194 operator/(double scalar) const
195 { return Point(x / scalar, y / scalar); }
196};
197
199{
201 size_t weight;
202
203 WeightedPoint(const Point& p, size_t w)
204 : pt(p.x, p.y, p.name), weight(w) { }
205};
206
207using vpoints = std::vector<Point>;
208using vwpoints = std::vector<WeightedPoint>;
209
210
211namespace svg {
212
213/// Convert point_2ts to Point.
216{
217 vpoints outpoints;
218 outpoints.reserve(inpoints.size());
219
220 auto lconv = [](const point_2ts& p)
221 { auto [ s, pt ] = p; auto [x, y] = pt; return Point(x, y, s); };
222 std::ranges::transform(inpoints, std::back_inserter(outpoints), lconv);
223 return outpoints;
224}
225
226/// Convert Point to point_2t
229{
230 using std::make_tuple;
231 vrangenamed outpoints;
232 outpoints.reserve(inpoints.size());
233
234 auto lconv = [](const Point& p){auto pt = make_tuple(p.x, p.y); return make_tuple(p.name, pt); };
235 std::ranges::transform(inpoints, std::back_inserter(outpoints), lconv);
236 return outpoints;
237}
238
239} // namespace svg
240
241#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:68
std::vector< point_2ts > vrangenamed
Definition izzi-points.h:50
std::set< point_2t > srange
Latitude and Longitude Ranges.
Definition izzi-points.h:44
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:62
std::vector< point_2tn > vrangen
Definition izzi-points.h:47
std::set< point_2tn > srangen
Definition izzi-points.h:45
std::vector< vrange > vvranges
Definition izzi-points.h:48
std::vector< point_2t > vrange
Definition izzi-points.h:46
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:80
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:55
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:41
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.
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)