cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
point_impl.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <iterator> // For std::make_move_iterator
5#include <limits>
6#include <ostream>
7#include <stdexcept>
8#include <type_traits> // For std::is_floating_point_v, std::is_integral_v
9#include <vector>
10
11#include <cpp-toolbox/types/point.hpp> // Include the header with declarations
12
13namespace toolbox::types
14{
15
16// --- point_t Implementations ---
17
18template<typename T>
19point_t<T>::point_t(T x_coord, T y_coord, T z_coord)
20 : x(x_coord)
21 , y(y_coord)
22 , z(z_coord)
23{
24}
25
26template<typename T>
28 : x(T {})
29 , y(T {})
30 , z(T {})
31{
32}
33
34template<typename T>
36{
37 x += other.x;
38 y += other.y;
39 z += other.z;
40 return *this;
41}
42
43template<typename T>
45{
46 x -= other.x;
47 y -= other.y;
48 z -= other.z;
49 return *this;
50}
51
52template<typename T>
54{
55 x *= scalar;
56 y *= scalar;
57 z *= scalar;
58 return *this;
59}
60
61template<typename T>
63{
64 if constexpr (std::is_floating_point_v<T>) {
65 constexpr T epsilon = std::numeric_limits<T>::epsilon();
66 if (std::abs(scalar) < epsilon) {
67 throw std::runtime_error("Division by zero in point_t::operator/=");
68 }
69 } else if constexpr (std::is_integral_v<T>) {
70 if (scalar == T {0}) {
71 throw std::runtime_error("Division by zero in point_t::operator/=");
72 }
73 }
74
75 x /= scalar;
76 y /= scalar;
77 z /= scalar;
78 return *this;
79}
80
81template<typename T>
82[[nodiscard]] auto point_t<T>::dot(const point_t& other) const -> T
83{
84 return (x * other.x) + (y * other.y) + (z * other.z);
85}
87template<typename T>
88[[nodiscard]] auto point_t<T>::cross(const point_t& other) const -> point_t
89{
90 return point_t((y * other.z) - (z * other.y),
91 (z * other.x) - (x * other.z),
92 (x * other.y) - (y * other.x));
94
95template<typename T>
96[[nodiscard]] auto point_t<T>::norm() const -> double
97{
98 const double dx = static_cast<double>(x);
99 const double dy = static_cast<double>(y);
100 const double dz = static_cast<double>(z);
101 return std::sqrt((dx * dx) + (dy * dy) + (dz * dz));
102}
103
104template<typename T>
105[[nodiscard]] auto point_t<T>::normalize() const -> point_t<double>
106{
107 const double length = this->norm();
108 constexpr double epsilon = std::numeric_limits<double>::epsilon();
109 if (std::abs(length) < epsilon) {
110 return point_t<double>(0.0, 0.0, 0.0);
111 }
112 return point_t<double>(static_cast<double>(x) / length,
113 static_cast<double>(y) / length,
114 static_cast<double>(z) / length);
116
117template<typename T>
118[[nodiscard]] auto point_t<T>::p_norm(const double& p_value) const -> double
119{
120 const double dx = static_cast<double>(x);
121 const double dy = static_cast<double>(y);
122 const double dz = static_cast<double>(z);
123 return std::pow(std::pow(std::abs(dx), p_value)
124 + std::pow(std::abs(dy), p_value)
125 + std::pow(std::abs(dz), p_value),
126 1.0 / p_value);
127}
128
129template<typename T>
130[[nodiscard]] auto point_t<T>::p_normalize(const double& p_value) const
132{
133 const double length = this->p_norm(p_value);
134 constexpr double epsilon = std::numeric_limits<double>::epsilon();
135 if (std::abs(length) < epsilon) {
136 return point_t<double>(0.0, 0.0, 0.0);
137 }
138 return point_t<double>(static_cast<double>(x) / length,
139 static_cast<double>(y) / length,
140 static_cast<double>(z) / length);
141}
142
143template<typename T>
144[[nodiscard]] auto point_t<T>::distance(const point_t& other) const -> double
145{
146 const point_t diff(other.x - x, other.y - y, other.z - z);
147 return diff.norm();
148}
149
150template<typename T>
151[[nodiscard]] auto point_t<T>::distance_p(const point_t& other,
152 const double& p_value) const -> double
153{
154 const point_t diff(other.x - x, other.y - y, other.z - z);
155 return diff.p_norm(p_value);
156}
157
158template<typename T>
159bool point_t<T>::operator==(const point_t& other) const
161 if constexpr (std::is_floating_point_v<T>) {
162 constexpr T epsilon = std::numeric_limits<T>::epsilon() * 100;
163 return (std::abs(x - other.x) <= epsilon)
164 && (std::abs(y - other.y) <= epsilon)
165 && (std::abs(z - other.z) <= epsilon);
166 } else {
167 // For integral types, direct comparison is sufficient
168 return (x == other.x) && (y == other.y) && (z == other.z);
169 }
170}
171
172template<typename T>
173bool point_t<T>::operator!=(const point_t& other) const
175 return !(*this == other);
176}
177
178template<typename T>
179bool point_t<T>::operator<(const point_t& other) const
180{
181 if constexpr (std::is_floating_point_v<T>) {
182 constexpr T epsilon = std::numeric_limits<T>::epsilon() * 100;
183 if (std::abs(x - other.x) > epsilon) {
184 return x < other.x;
186 if (std::abs(y - other.y) > epsilon) {
187 return y < other.y;
188 }
189 // Compare z directly if x and y are close enough
190 // Use a small adjustment for floating point comparison robustness
191 return z < other.z - epsilon;
192 } else {
193 // For integral types, direct comparison is fine
194 if (x != other.x) {
195 return x < other.x;
196 }
197 if (y != other.y) {
198 return y < other.y;
199 }
200 return z < other.z;
201 }
202}
203
204// Static member general template definitions
205template<typename T>
207{
208 if constexpr (std::numeric_limits<T>::is_specialized) {
209 T min_val = std::numeric_limits<T>::is_integer
210 ? std::numeric_limits<T>::min()
211 : std::numeric_limits<T>::lowest();
212 return point_t<T>(min_val, min_val, min_val);
213 } else {
214 // Provide a default for types without numeric_limits (though unlikely for
215 // points)
216 return point_t<T>();
217 }
218}
219
220template<typename T>
222{
223 if constexpr (std::numeric_limits<T>::is_specialized) {
224 return point_t<T>(std::numeric_limits<T>::max(),
225 std::numeric_limits<T>::max(),
226 std::numeric_limits<T>::max());
227 } else {
228 // Provide a default for types without numeric_limits
229 return point_t<T>();
230 }
231}
232
233// --- point_cloud_t Implementations ---
234
235template<typename T>
237 : intensity(T {})
238{
239}
240
241template<typename T>
243 : base_file_data_t(other) // Assuming base class needs copy construction
244 , points(other.points)
245 , normals(other.normals)
246 , colors(other.colors)
247 , intensity(other.intensity)
248{
249}
250
251template<typename T>
253 : base_file_data_t(
254 std::move(other)) // Assuming base class needs move construction
255 , points(std::move(other.points))
256 , normals(std::move(other.normals))
257 , colors(std::move(other.colors))
258 , intensity(std::move(other.intensity))
259{
260 other.intensity = T {}; // Reset moved-from object
261}
262
263template<typename T>
265{
266 if (this != &other) {
267 // Assuming base class needs copy assignment
268 base_file_data_t::operator=(other);
269 points = other.points;
270 normals = other.normals;
271 colors = other.colors;
272 intensity = other.intensity;
273 }
274 return *this;
275}
276
277template<typename T>
280 if (this != &other) {
281 // Assuming base class needs move assignment
282 base_file_data_t::operator=(std::move(other));
283 points = std::move(other.points);
284 normals = std::move(other.normals);
285 colors = std::move(other.colors);
286 intensity = std::move(other.intensity);
287 other.intensity = T {}; // Reset moved-from object
289 return *this;
290}
291
292template<typename T>
293[[nodiscard]] auto point_cloud_t<T>::size() const -> std::size_t
295 return points.size();
296}
297
298template<typename T>
299[[nodiscard]] auto point_cloud_t<T>::empty() const -> bool
300{
301 return points.empty();
302}
303
304template<typename T>
307 points.clear();
308 normals.clear();
309 colors.clear();
310 intensity = T {};
311}
312
313template<typename T>
314void point_cloud_t<T>::reserve(const std::size_t& required_size)
315{
316 points.reserve(required_size);
317 // Only reserve if normals/colors might be used - adjust if needed
318 if (!normals.empty() || required_size > 0) // Simple heuristic
319 normals.reserve(required_size);
320 if (!colors.empty() || required_size > 0) // Simple heuristic
321 colors.reserve(required_size);
322}
323
324template<typename T>
325[[nodiscard]] auto point_cloud_t<T>::operator+(const point_cloud_t& other) const
327{
328 point_cloud_t result = *this;
329 result += other; // Use the += operator
330 return result;
331}
332
333template<typename T>
334[[nodiscard]] auto point_cloud_t<T>::operator+(const point_t<T>& point) const
336{
337 point_cloud_t result = *this;
338 result += point; // Use the += operator
339 return result;
340}
341
342template<typename T>
343[[nodiscard]] auto point_cloud_t<T>::operator+(point_t<T>&& point) const
345{
346 point_cloud_t result = *this;
347 result += std::move(point); // Use the move += operator
348 return result;
350
351template<typename T>
352[[nodiscard]] auto point_cloud_t<T>::operator+(point_cloud_t&& other) const
354{
355 point_cloud_t result = *this;
356 result += std::move(other); // Use the move += operator
357 return result;
358}
359
360template<typename T>
362{
363 points.push_back(point);
364 // Handle potential mismatch if normals/colors exist
365 if (!normals.empty())
366 normals.emplace_back(); // Add default normal if needed
367 if (!colors.empty())
368 colors.emplace_back(); // Add default color if needed
369 return *this;
370}
371
372template<typename T>
374{
375 points.push_back(std::move(point));
376 // Handle potential mismatch if normals/colors exist
377 if (!normals.empty())
378 normals.emplace_back(); // Add default normal if needed
379 if (!colors.empty())
380 colors.emplace_back(); // Add default color if needed
381 return *this;
382}
383
384template<typename T>
386{
387 if (this != &other) {
388 const std::size_t original_size = points.size();
389 points.insert(points.end(), other.points.begin(), other.points.end());
390
391 const bool this_has_normals = !normals.empty();
392 const bool other_has_normals = !other.normals.empty();
393 const bool this_has_colors = !colors.empty();
394 const bool other_has_colors = !other.colors.empty();
395
396 if (this_has_normals && other_has_normals) {
397 normals.insert(normals.end(), other.normals.begin(), other.normals.end());
398 } else if (other_has_normals) { // Only other has normals
399 normals.resize(original_size); // Ensure original part has defaults
400 normals.insert(normals.end(), other.normals.begin(), other.normals.end());
401 } else if (this_has_normals) { // Only this has normals
402 normals.resize(points.size()); // Resize to new total size with defaults
403 }
404 // If neither has normals, do nothing.
405
406 if (this_has_colors && other_has_colors) {
407 colors.insert(colors.end(), other.colors.begin(), other.colors.end());
408 } else if (other_has_colors) { // Only other has colors
409 colors.resize(original_size); // Ensure original part has defaults
410 colors.insert(colors.end(), other.colors.begin(), other.colors.end());
411 } else if (this_has_colors) { // Only this has colors
412 colors.resize(points.size()); // Resize to new total size with defaults
413 }
414 // If neither has colors, do nothing.
415
416 // Note: Intensity addition might not always be meaningful, depends on
417 // context.
418 intensity += other.intensity;
419 }
420 return *this;
421}
422
423template<typename T>
425{
426 if (this != &other) {
427 const std::size_t original_size = points.size();
428 // Use move iterators for potentially better performance
429 points.insert(points.end(),
430 std::make_move_iterator(other.points.begin()),
431 std::make_move_iterator(other.points.end()));
432
433 const bool this_has_normals = !normals.empty();
434 const bool other_has_normals = !other.normals.empty();
435 const bool this_has_colors = !colors.empty();
436 const bool other_has_colors = !other.colors.empty();
437
438 if (this_has_normals && other_has_normals) {
439 normals.insert(normals.end(),
440 std::make_move_iterator(other.normals.begin()),
441 std::make_move_iterator(other.normals.end()));
442 } else if (other_has_normals) { // Only other has normals
443 normals.resize(original_size); // Ensure original part has defaults
444 normals.insert(normals.end(),
445 std::make_move_iterator(other.normals.begin()),
446 std::make_move_iterator(other.normals.end()));
447 } else if (this_has_normals) { // Only this has normals
448 normals.resize(points.size()); // Resize to new total size with defaults
449 }
450 // If neither has normals, do nothing.
451
452 if (this_has_colors && other_has_colors) {
453 colors.insert(colors.end(),
454 std::make_move_iterator(other.colors.begin()),
455 std::make_move_iterator(other.colors.end()));
456 } else if (other_has_colors) { // Only other has colors
457 colors.resize(original_size); // Ensure original part has defaults
458 colors.insert(colors.end(),
459 std::make_move_iterator(other.colors.begin()),
460 std::make_move_iterator(other.colors.end()));
461 } else if (this_has_colors) { // Only this has colors
462 colors.resize(points.size()); // Resize to new total size with defaults
463 }
464 // If neither has colors, do nothing.
465
466 intensity += other.intensity; // Add intensity
467 other.clear(); // Clear the moved-from object
468 }
469 return *this;
470}
471
472// --- operator<< Implementation ---
473
474template<typename T>
475auto operator<<(std::ostream& output_stream, const point_t<T>& pt)
476 -> std::ostream&
477{
478 // Consider using iomanip for better formatting control if needed
479 output_stream << "(" << pt.x << ", " << pt.y << ", " << pt.z << ")";
480 return output_stream;
481}
482
483} // namespace toolbox::types
包含点和相关数据的点云类 / A point cloud class containing points and associated data
Definition point.hpp:268
std::vector< point_t< T > > colors
点颜色(可选) / Point colors (optional)
Definition point.hpp:272
auto operator+(const point_cloud_t &other) const -> point_cloud_t
合并两个点云 / Add two point clouds
Definition point_impl.hpp:325
void clear()
清除点云中的所有数据 / Clear all data from cloud
Definition point_impl.hpp:305
point_cloud_t()
Definition point_impl.hpp:236
std::vector< point_t< T > > points
点坐标 / Point coordinates
Definition point.hpp:270
point_cloud_t & operator+=(const point_t< T > &point)
向点云添加点 / Add point to cloud
Definition point_impl.hpp:361
std::vector< point_t< T > > normals
点法线(可选) / Point normals (optional)
Definition point.hpp:271
point_cloud_t & operator=(const point_cloud_t &other)
Definition point_impl.hpp:264
T intensity
全局强度值 / Global intensity value
Definition point.hpp:273
void reserve(const std::size_t &required_size)
为点预留内存 / Reserve memory for points
Definition point_impl.hpp:314
auto size() const -> std::size_t
获取点云中的点数 / Get number of points in cloud
Definition point_impl.hpp:293
auto empty() const -> bool
检查点云是否为空 / Check if cloud is empty
Definition point_impl.hpp:299
Definition minmax_impl.hpp:21
auto operator<<(std::ostream &output_stream, const point_t< T > &pt) -> std::ostream &
point_t的流输出运算符 - 仅声明 / Stream output operator for point_t - Declaration Only
Definition point_impl.hpp:475
3D点/向量模板类 / A 3D point/vector template class
Definition point.hpp:48
auto p_normalize(const double &p_value) const -> point_t< double >
返回p范数归一化向量 / Return p-normalized vector
Definition point_impl.hpp:130
point_t()
默认构造函数,初始化为原点(0,0,0) / Default constructor, initializes to origin (0,0,0)
Definition point_impl.hpp:27
static auto min_value() -> point_t
获取具有最小可能值的点 / Get point with minimum possible values
Definition point_impl.hpp:206
auto p_norm(const double &p_value) const -> double
计算向量的p范数 / Calculate p-norm of vector
Definition point_impl.hpp:118
T x
X坐标 / X coordinate.
Definition point.hpp:51
auto cross(const point_t &other) const -> point_t
计算与另一点的叉积 / Calculate cross product with another point
Definition point_impl.hpp:88
auto normalize() const -> point_t< double >
返回归一化向量(单位长度) / Return normalized vector (unit length)
Definition point_impl.hpp:105
T z
Z坐标 / Z coordinate.
Definition point.hpp:53
auto norm() const -> double
计算向量的欧几里得范数(长度) / Calculate Euclidean norm (length) of vector
Definition point_impl.hpp:96
point_t & operator-=(const point_t &other)
分量式减去另一个点 / Subtract another point component-wise
Definition point_impl.hpp:44
auto distance(const point_t &other) const -> double
计算到另一点的欧几里得距离 / Calculate Euclidean distance to another point
Definition point_impl.hpp:144
bool operator==(const point_t &other) const
Definition point_impl.hpp:159
bool operator<(const point_t &other) const
Definition point_impl.hpp:179
point_t & operator+=(const point_t &other)
分量式加上另一个点 / Add another point component-wise
Definition point_impl.hpp:35
static auto max_value() -> point_t
获取具有最大可能值的点 / Get point with maximum possible values
Definition point_impl.hpp:221
point_t & operator/=(const T &scalar)
坐标除以标量 / Divide coordinates by a scalar
Definition point_impl.hpp:62
auto dot(const point_t &other) const -> T
计算与另一点的点积 / Calculate dot product with another point
Definition point_impl.hpp:82
auto distance_p(const point_t &other, const double &p_value) const -> double
计算到另一点的p距离 / Calculate p-distance to another point
Definition point_impl.hpp:151
bool operator!=(const point_t &other) const
Definition point_impl.hpp:173
point_t & operator*=(const T &scalar)
坐标乘以标量 / Multiply coordinates by a scalar
Definition point_impl.hpp:53
T y
Y坐标 / Y coordinate.
Definition point.hpp:52