GCC Code Coverage Report


Directory: libimgdoc2/
File: libimgdoc2/inc/types.h
Date: 2025-02-03 12:41:04
Exec Total Coverage
Lines: 77 77 100.0%
Functions: 35 35 100.0%
Branches: 43 70 61.4%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 Carl Zeiss Microscopy GmbH
2 //
3 // SPDX-License-Identifier: MIT
4
5 #pragma once
6
7 #include <cstdint>
8 #include <stdexcept>
9 #include <cmath>
10 #include <iomanip>
11 #include <sstream>
12
13 namespace imgdoc2
14 {
15 /// This defines the time for a primary key, used to uniquely identify a record in a table.
16 typedef std::int64_t dbIndex;
17
18 /// Defines an alias representing the "dimension". Legal dimensions are a-z and A-Z. Use IsDimensionValid(Dimension) to check for a legal dimension value.
19 typedef char Dimension;
20
21 /// Queries if the specified value is a legal dimension. Legal dimensions are a-z and A-Z.
22 /// \param dimension The dimension.
23 /// \returns True if the dimension is valid, false if not.
24 340 inline bool IsDimensionValid(Dimension dimension)
25 {
26
7/8
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 138 times.
✓ Branch 4 taken 202 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 198 times.
✓ Branch 7 taken 4 times.
340 return ((dimension >= 'a' && dimension <= 'z') || (dimension >= 'A' && dimension <= 'Z'));
27 }
28
29 /// Throw an invalid_argument exception if the specified dimension is invalid.
30 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
31 /// \param dimension The dimension.
32 334 inline void ThrowIfDimensionInvalid(Dimension dimension)
33 {
34
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 332 times.
334 if (!imgdoc2::IsDimensionValid(dimension))
35 {
36
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 std::ostringstream ss;
37
8/16
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
2 ss << "The character '" << (isprint(dimension) ? dimension : '?') << "'=0x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(dimension) << " is not a valid dimension specifier.";
38
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 throw std::invalid_argument(ss.str());
39 2 }
40 332 }
41
42 /// Structure defining a point in two dimensions.
43 /// \tparam t Generic type parameter.
44 template <typename t>
45 struct PointT
46 {
47 /// Default constructor which sets all properties to zero.
48 PointT() :x(0), y(0) {}
49
50 /// Constructor
51 /// \param x The x-coordinate of the point.
52 /// \param y The y-coordinate of the point.
53 16 PointT(t x, t y) :x(x), y(y) {}
54
55 t x; ///< The x-coordinate of the point.
56 t y; ///< The y-coordinate of the point.
57 };
58
59 /// Structure defining a point in two dimensions with floats representing the coordinates.
60 struct PointF : PointT<float>
61 {
62 /// Default constructor which sets all properties to zero.
63 PointF() :PointT<float>() {}
64
65 /// Constructor
66 /// \param x The x-coordinate of the point.
67 /// \param y The y-coordinate of the point.
68 4 PointF(float x, float y) :PointT<float>(x, y) {}
69 };
70
71 /// Structure defining a point in two dimensions with doubles representing the coordinates.
72 struct PointD : PointT<double>
73 {
74 /// Default constructor which sets all properties to zero.
75 PointD() :PointT<double>() {}
76
77 /// Constructor
78 /// \param x The x-coordinate of the point.
79 /// \param y The y-coordinate of the point.
80 4 PointD(double x, double y) :PointT<double>(x, y) {}
81 };
82
83 /// Structure defining a point in three dimensions.
84 /// \tparam t Generic type parameter.
85 template <typename t>
86 struct Point3dT
87 {
88 /// Default constructor which sets all properties to zero.
89 Point3dT() :x(0), y(0), z(0) {}
90
91 /// Constructor
92 /// \param x The x-coordinate of the point.
93 /// \param y The y-coordinate of the point.
94 /// \param z The z-coordinate of the point.
95 8564 Point3dT(t x, t y, t z) :x(x), y(y), z(z) {}
96
97 t x; ///< The x-coordinate of the point.
98 t y; ///< The y-coordinate of the point.
99 t z; ///< The z-coordinate of the point.
100 };
101
102 /// Structure defining a point in three dimensions with floats representing the coordinates.
103 struct Point3dF : Point3dT<float>
104 {
105 Point3dF() :Point3dT<float>() {}
106
107 /// Constructor.
108 /// \param x The x coordinate.
109 /// \param y The y coordinate.
110 /// \param z The z coordinate.
111 4 Point3dF(float x, float y, float z) :Point3dT<float>(x, y, z) {}
112 };
113
114 /// Structure defining a point in three dimensions with doubles representing the coordinates.
115 struct Point3dD : Point3dT<double>
116 {
117 Point3dD() :Point3dT<double>() {}
118
119 /// Constructor.
120 /// \param x The x coordinate.
121 /// \param y The y coordinate.
122 /// \param z The z coordinate.
123 88 Point3dD(double x, double y, double z) :Point3dT<double>(x, y, z) {}
124 };
125
126 /// Structure defining an axis-aligned rectangle in two dimensions.
127 /// \tparam t Generic type parameter.
128 template<typename t>
129 struct RectangleT
130 {
131 /// Default constructor which sets all properties to zero.
132 RectangleT() :x(0), y(0), w(0), h(0) {}
133
134 /// Constructor
135 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
136 /// \param x The x-coordinate of the edge point of the rectangle.
137 /// \param y The y-coordinate of the edge point of the rectangle.
138 /// \param w The width of the rectangle.
139 /// \param h The height of the rectangle.
140 24 RectangleT(t x, t y, t w, t h)
141 {
142
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
24 if (w < 0 || h < 0)
143 {
144
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
6 throw std::invalid_argument("width and height must be non-negative");
145 }
146
147 18 this->x = x;
148 18 this->y = y;
149 18 this->w = w;
150 18 this->h = h;
151 18 }
152
153 t x; ///< The x-coordinate of the edge point of the rectangle.
154 t y; ///< The y-coordinate of the edge point of the rectangle.
155 t w; ///< The width of the rectangle.
156 t h; ///< The height of the rectangle.
157
158 /// Query if the specified point 'p' is inside the rectangle.
159 /// \param p The point to test.
160 /// \returns True if point inside, false if not.
161 16 inline bool IsPointInside(const PointT<t>& p) const
162 {
163
5/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
16 if (this->x <= p.x && (this->x + this->w) >= p.x && this->y <= p.y && (this->y + this->h) >= p.y)
164 {
165 8 return true;
166 }
167
168 8 return false;
169 }
170 };
171
172 /// Structure defining an axis-aligned rectangle in two dimensions with floats representing the coordinates.
173 struct RectangleF : RectangleT<float>
174 {
175 RectangleF() :RectangleT<float>() {}
176
177 // Constructor.
178 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
179 /// \param x The x-coordinate of the edge point of the rectangle.
180 /// \param y The y-coordinate of the edge point of the rectangle.
181 /// \param w The width of the rectangle.
182 /// \param h The height of the rectangle.
183 4 RectangleF(float x, float y, float w, float h) :RectangleT<float>(x, y, w, h) {}
184 };
185
186 /// Structure defining an axis-aligned rectangle in two dimensions with doubles representing the coordinates.
187 struct RectangleD : RectangleT<double>
188 {
189 RectangleD() :RectangleT<double>() {}
190
191 // Constructor.
192 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
193 /// \param x The x-coordinate of the edge point of the rectangle.
194 /// \param y The y-coordinate of the edge point of the rectangle.
195 /// \param w The width of the rectangle.
196 /// \param h The height of the rectangle.
197 16 RectangleD(double x, double y, double w, double h) :RectangleT<double>(x, y, w, h) {}
198 };
199
200 /// This structure defines a line in two dimensions by specifying two points on this line.
201 /// Coordinates are represented by floats.
202 struct LineThruTwoPointsF
203 {
204 PointF a; ///< The first point on the line.
205 PointF b; ///< The second point on the line.
206 };
207
208 /// This structure defines a line in two dimensions by specifying two points on this line.
209 /// Coordinates are represented by doubles.
210 struct LineThruTwoPointsD
211 {
212 PointD a; ///< The first point on the line.
213 PointD b; ///< The second point on the line.
214 };
215
216 template <typename t> struct Vector3dT;
217 template<typename T> struct Plane_NormalAndDist;
218
219 /// Structure defining an axis-aligned cuboid in three dimensions.
220 /// \tparam t Generic type parameter.
221 template<typename t>
222 struct CuboidT
223 {
224 /// Default constructor. All properties are set to zero.
225 CuboidT() :x(0), y(0), z(0), w(0), h(0), d(0) {}
226
227 /// Constructor.
228 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
229 /// \param x The x-coordinate of the edge point of the cuboid.
230 /// \param y The y-coordinate of the edge point of the cuboid.
231 /// \param z The z-coordinate of the edge point of the cuboid.
232 /// \param w The width of the cuboid (i.e. the extent in x-direction).
233 /// \param h The height of the cuboid (i.e. the extent in y-direction).
234 /// \param d The depth of the cuboid (i.e. the extent in z-direction).
235 8488 CuboidT(t x, t y, t z, t w, t h, t d)
236 {
237
4/6
✓ Branch 0 taken 8484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8480 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8480 times.
8488 if (w < 0 || h < 0 || d < 0)
238 {
239
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
6 throw std::invalid_argument("width and height must be non-negative");
240 }
241
242 8482 this->x = x;
243 8482 this->y = y;
244 8482 this->z = z;
245 8482 this->w = w;
246 8482 this->h = h;
247 8482 this->d = d;
248 8482 }
249
250 t x; ///< The x-coordinate of the edge point of the cuboid.
251 t y; ///< The y-coordinate of the edge point of the cuboid.
252 t z; ///< The z-coordinate of the edge point of the cuboid.
253 t w; ///< The width of the cuboid (i.e. the extent in x-direction).
254 t h; ///< The height of the cuboid (i.e. the extent in y-direction).
255 t d; ///< The depth of the cuboid (i.e. the extent in z-direction).
256
257 /// Query if the specified point 'p' is inside the cubiod.
258 /// \param p The point to test.
259 /// \returns True if point inside, false if not.
260 16 bool IsPointInside(const Point3dT<t>& p) const
261 {
262
7/12
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
16 if (this->x <= p.x && (this->x + this->w) >= p.x && this->y <= p.y && (this->y + this->h) >= p.y && this->z <= p.z && (this->z + this->d) >= p.z)
263 {
264 8 return true;
265 }
266
267 8 return false;
268 }
269
270 /// Calculate the center point of the cuboid.
271 /// \returns The center point of the cuboid.
272 8468 Point3dT<t> CenterPoint() const
273 {
274 8468 return Point3dT<t>(this->x + this->w / 2, this->y + this->h / 2, this->z + this->d / 2);
275 }
276
277 /// Test whether the specified cuboid is intersecting with the specified plane.
278 /// \param aabb The axis-aligned cuboid.
279 /// \param plane The plane (given in plane-and-normal representation).
280 /// \returns True if the two objects intersect; false otherwise.
281 static bool DoIntersect(const imgdoc2::CuboidT<t>& aabb, const imgdoc2::Plane_NormalAndDist<t>& plane);
282
283 /// Test whether the specified plane is intersecting with the cuboid instance.
284 /// \param plane The plane (given in plane-and-normal representation).
285 /// \returns True if the two objects intersect; false otherwise.
286 8468 bool DoesIntersectWith(const imgdoc2::Plane_NormalAndDist<t>& plane) const
287 {
288 8468 return DoIntersect(*this, plane);
289 }
290 };
291
292 /// Structure defining an axis-aligned cuboid in three dimensions with floats representing the coordinates.
293 struct CuboidF : CuboidT<float>
294 {
295 CuboidF() :CuboidT<float>() {}
296
297 /// Constructor.
298 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
299 /// \param x The x-coordinate of the edge point of the cuboid.
300 /// \param y The y-coordinate of the edge point of the cuboid.
301 /// \param z The z-coordinate of the edge point of the cuboid.
302 /// \param w The width of the cuboid (i.e. the extent in x-direction).
303 /// \param h The height of the cuboid (i.e. the extent in y-direction).
304 /// \param d The depth of the cuboid (i.e. the extent in z-direction).
305 4 CuboidF(float x, float y, float z, float w, float h, float d) :CuboidT<float>(x, y, z, w, h, d) {}
306 };
307
308 /// Structure defining an axis-aligned cuboid in three dimensions with doubles representing the coordinates.
309 struct CuboidD : CuboidT<double>
310 {
311 CuboidD() :CuboidT<double>() {}
312
313 /// Constructor.
314 /// \exception std::invalid_argument Thrown when an invalid argument error condition occurs.
315 /// \param x The x-coordinate of the edge point of the cuboid.
316 /// \param y The y-coordinate of the edge point of the cuboid.
317 /// \param z The z-coordinate of the edge point of the cuboid.
318 /// \param w The width of the cuboid (i.e. the extent in x-direction).
319 /// \param h The height of the cuboid (i.e. the extent in y-direction).
320 /// \param d The depth of the cuboid (i.e. the extent in z-direction).
321 8480 CuboidD(double x, double y, double z, double w, double h, double d) :CuboidT<double>(x, y, z, w, h, d) {}
322 };
323
324 /// Structure defining a vector in three dimensions.
325 /// \tparam t Generic type parameter.
326 template <typename t>
327 struct Vector3dT
328 {
329 /// Default constructor. All properties are set to zero.
330 Vector3dT() :x(0), y(0), z(0) {}
331
332 /// Constructor.
333 /// \param x The component of the vector in x-direction.
334 /// \param y The component of the vector in y-direction.
335 /// \param z The component of the vector in z-direction.
336 17076 Vector3dT(t x, t y, t z) :x(x), y(y), z(z) {}
337
338 /// Constructor.
339 /// \param p A Point3dT&lt;t&gt; to convert into a vector.
340 8496 explicit Vector3dT(const Point3dT<t> p) : Vector3dT(p.x, p.y, p.z) {}
341
342 t x; ///< The component of the vector in x-direction.
343 t y; ///< The component of the vector in y-direction.
344 t z; ///< The component of the vector in z-direction.
345
346 /// Gets a normalized vector.
347 /// \returns The normalized vector.
348 28 Vector3dT<t> Normalize() const
349 {
350 28 t absVal = this->AbsoluteValue();
351 28 return Vector3dT(this->x / absVal, this->y / absVal, this->z / absVal);
352 }
353
354 /// Calculate the squared length of the vector.
355 /// \returns The squared length of the vector.
356 28 t AbsoluteValueSquared() const
357 {
358 28 return this->x * this->x + this->y * this->y + this->z * this->z;
359 }
360
361 /// Calculate the length of the vector.
362 /// \returns The length of the vector.
363 28 t AbsoluteValue() const
364 {
365 28 return std::sqrt(this->AbsoluteValueSquared());
366 }
367
368 /// Calculate the cross-product of two vectors.
369 /// \param vectorA The first vector.
370 /// \param vectorB The second vector.
371 /// \returns The cross-product of the two vectors.
372 28 static Vector3dT<t> Cross(const Vector3dT<t>& vectorA, const Vector3dT<t>& vectorB)
373 {
374 return Vector3dT
375 {
376 28 vectorA.y * vectorB.z - vectorA.z * vectorB.y,
377 28 vectorA.z * vectorB.x - vectorA.x * vectorB.z,
378 28 vectorA.x * vectorB.y - vectorA.y * vectorB.x
379 28 };
380 }
381
382 /// Calculate the dot-product of two vectors.
383 /// \param vectorA The first vector.
384 /// \param vectorB The second vector.
385 /// \returns The dot-product of the two vectors.
386 8496 static t Dot(const Vector3dT<t>& vectorA, const Vector3dT<t>& vectorB)
387 {
388 8496 return vectorA.x * vectorB.x + vectorA.y * vectorB.y + vectorA.z * vectorB.z;
389 }
390 };
391
392 /// Structure defining a vector in three dimensions with floats representing the coordinates.
393 struct Vector3dF : Vector3dT<float>
394 {
395 Vector3dF() :Vector3dT<float>() {}
396
397 /// Constructor.
398 /// \param x The component of the vector in x-direction.
399 /// \param y The component of the vector in y-direction.
400 /// \param z The component of the vector in z-direction.
401 Vector3dF(float x, float y, float z) :Vector3dT<float>(x, y, z) {}
402 };
403
404 /// Structure defining a vector in three dimensions with doubles representing the coordinates.
405 struct Vector3dD : Vector3dT<double>
406 {
407 Vector3dD() :Vector3dT<double>() {}
408
409 /// Constructor.
410 /// \param x The component of the vector in x-direction.
411 /// \param y The component of the vector in y-direction.
412 /// \param z The component of the vector in z-direction.
413 8468 Vector3dD(double x, double y, double z) :Vector3dT<double>(x, y, z) {}
414 };
415
416 /// Parametrization of a plane, parametrized as a normal-vector and the distance to the origin (aka "Hesse normal form").
417 /// The normal must be normalized.
418 /// The equation of the plane is: dot( x, normal) = distance.
419 template<typename T>
420 struct Plane_NormalAndDist
421 {
422 Vector3dT<T> normal; ///< The normal of the plane.
423 T distance; ///< The distance of the plane to the origin.
424
425 /// Default constructor. All properties are initialized to zero.
426 Plane_NormalAndDist() :distance(0) {}
427
428 /// Constructor.
429 /// \param n The normal.
430 /// \param d The distance to the origin.
431 28 Plane_NormalAndDist(const Vector3dT<T>& n, T d) :normal(n), distance(d) {}
432
433 /// Create the normal-representation of a plane for a plane defined by three points.
434 /// Precondition (not checked currently) is that the points are distinct.
435 /// \param a The first point on the plane.
436 /// \param b The second point on the plane.
437 /// \param c The third point on the plane.
438 /// \returns Normal-representation of the plane.
439 28 static Plane_NormalAndDist<T> FromThreePoints(Point3dT<T> a, Point3dT<T> b, Point3dT<T> c)
440 {
441
1/2
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 const auto n = Vector3dT<T>::Cross(Vector3dT<T>(b.x - a.x, b.y - a.y, b.z - a.z), Vector3dT<T>(c.x - a.x, c.y - a.y, c.z - a.z)).Normalize();
442 28 const auto dist = Vector3dT<T>::Dot(n, Vector3dT<T>(a));
443 56 return Plane_NormalAndDist<T>(n, dist);
444 }
445 };
446
447 /// Defines an alias representing a parametrization of a plane, parametrized as a normal-vector and the distance to the origin.
448 /// Coordinates are represented by floats.
449 typedef Plane_NormalAndDist<float> Plane_NormalAndDistF;
450
451 /// Defines an alias representing a parametrization of a plane, parametrized as a normal-vector and the distance to the origin.
452 /// Coordinates are represented by doubles.
453 typedef Plane_NormalAndDist<double> Plane_NormalAndDistD;
454
455 8468 /*static*/template<typename t> inline bool CuboidT<t>::DoIntersect(const imgdoc2::CuboidT<t>& aabb, const imgdoc2::Plane_NormalAndDist<t>& plane)
456 {
457 // -> https://gdbooks.gitbooks.io/3dcollisions/content/Chapter2/static_aabb_plane.html
458 8468 const auto centerAabb = aabb.CenterPoint();
459
1/2
✓ Branch 1 taken 8468 times.
✗ Branch 2 not taken.
8468 const Vector3dT<t> aabbExtents = Vector3dD(aabb.w / 2, aabb.h / 2, aabb.d / 2);
460
461 // Compute the projection interval radius of b onto L(t) = b.c + t * p.n
462 8468 const auto r = aabbExtents.x * fabs(plane.normal.x) + aabbExtents.y * fabs(plane.normal.y) + aabbExtents.z * fabs(plane.normal.z);
463
464 // Compute distance of box center from plane
465 8468 const auto s = Vector3dT<t>::Dot(plane.normal, Vector3dT<t>(centerAabb)) - plane.distance;
466
467 // Intersection occurs when distance s falls within [-r,+r] interval
468 8468 return fabs(s) <= r;
469 }
470 }
471