Ponca  7d8ac87a7de01d881c9fde3c42e397b44bffb901
Point Cloud Analysis library
Loading...
Searching...
No Matches
pointGeneration.h
1/*
2This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5*/
6
7#pragma once
8
13#include "Eigen/Eigen"
14#include "./defines.h"
15
16#define MIN_NOISE 0.99
17#define MAX_NOISE 1.01
18
19namespace Ponca
20{
21
23 template <typename DataPoint>
24 [[nodiscard]] DataPoint getPointOnSphere(const typename DataPoint::Scalar _radius,
25 const typename DataPoint::VectorType _vCenter,
26 const bool _bAddPositionNoise = true, const bool _bAddNormalNoise = true,
27 const bool _bReverseNormals = false)
28 {
29 using Scalar = typename DataPoint::Scalar;
30 using VectorType = typename DataPoint::VectorType;
31
32 VectorType vNormal = VectorType::Random().normalized();
33 VectorType vPosition = _vCenter + vNormal * _radius;
34
36 {
37 vPosition = vPosition + VectorType::Random().normalized() *
38 Eigen::internal::random<Scalar>(Scalar(0.), Scalar(1. - MIN_NOISE));
40 }
41
43 {
44 VectorType vTempPos = vPosition + VectorType::Random().normalized() *
45 Eigen::internal::random<Scalar>(Scalar(0.), Scalar(1. - MIN_NOISE));
47 }
49 {
50 const float reverse = Eigen::internal::random<float>(0.f, 1.f);
51 if (reverse > 0.5f)
53 }
54
55 return DataPoint(vPosition, vNormal);
56 }
57
59 template <typename VectorType>
60 [[nodiscard]] VectorType getPointOnCircle(typename VectorType::Scalar _radius, VectorType _vCenter)
61 {
62 using Scalar = typename VectorType::Scalar;
63 // Generate random angle
64 const Scalar theta = Eigen::internal::random<Scalar>(0, Scalar(2. * EIGEN_PI));
65
66 // Generate random radius (adjusted for uniform area distribution)
67 const Scalar r = _radius * std::sqrt(Eigen::internal::random<Scalar>(0, 1));
68
69 // Convert to Cartesian coordinates
70 VectorType p = _vCenter;
71 p.x() += r * std::cos(theta);
72 p.y() += r * std::sin(theta);
73
74 return p;
75 }
76
78 template <typename DataPoint>
79 [[nodiscard]] DataPoint getPointOnRectangularPlane(const typename DataPoint::VectorType& _vPosition,
80 const typename DataPoint::VectorType& /*_vNormal*/,
81 const typename DataPoint::Scalar& _width,
82 const typename DataPoint::Scalar& _height,
83 const typename DataPoint::VectorType& _localxAxis,
84 const typename DataPoint::VectorType& _localyAxis,
85 const bool _bAddPositionNoise = true)
86 {
87 using Scalar = typename DataPoint::Scalar;
88 using VectorType = typename DataPoint::VectorType;
89
90 const Scalar u = Eigen::internal::random<Scalar>(-_width / Scalar(2), _width / Scalar(2));
91 const Scalar v = Eigen::internal::random<Scalar>(-_height / Scalar(2), _height / Scalar(2));
92
94
96 {
98 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(0., 1. - MIN_NOISE);
99 }
100
101 return DataPoint(vRandomPosition);
102 }
103
105 template <typename DataPoint>
106 [[nodiscard]] DataPoint getPointOnPlane(const typename DataPoint::VectorType _vPosition,
107 const typename DataPoint::VectorType _vNormal,
108 const typename DataPoint::Scalar _radius,
109 const bool _bAddPositionNoise = true, const bool _bAddNormalNoise = true,
110 const bool _bReverseNormals = false)
111 {
112 using Scalar = typename DataPoint::Scalar;
113 using VectorType = typename DataPoint::VectorType;
114 using QuaternionType = Eigen::Quaternion<Scalar>;
115
116 VectorType vRandom;
117 VectorType vRandomDirection = VectorType::Zero();
118 VectorType vRandomPoint = VectorType::Zero();
119 VectorType vLocalUp = _vNormal;
120
121 do
122 {
123 vRandom = VectorType::Random().normalized(); // Direction in the unit sphere
125 } while (vRandomDirection == VectorType::Zero());
126
127 vRandomDirection = vRandomDirection.normalized();
130
132 {
133 vRandomPoint = vRandomPoint + VectorType::Random().normalized() *
134 Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
135 }
136
138 {
139 VectorType vLocalLeft = vLocalUp.cross(vRandomDirection);
140 VectorType vLocalFront = vLocalLeft.cross(vLocalUp);
141
142 Scalar rotationAngle = Eigen::internal::random<Scalar>(Scalar(-M_PI / 16.), Scalar(M_PI / 16.));
143 VectorType vRotationAxis = vLocalLeft;
145 qRotation = qRotation.normalized();
147
148 rotationAngle = Eigen::internal::random<Scalar>(Scalar(-M_PI / 16.), Scalar(M_PI / 16.));
150 qRotation = QuaternionType(Eigen::AngleAxis<Scalar>(rotationAngle, vRotationAxis));
151 qRotation = qRotation.normalized();
153 }
154
156 {
157 const float reverse = Eigen::internal::random<float>(0.f, 1.f);
158 if (reverse > 0.5f)
160 }
161
162 return DataPoint(vRandomPoint, vLocalUp);
163 }
164
165 namespace internal
166 {
168 template <typename Scalar>
169 [[nodiscard]] inline Scalar getParaboloidZ(const Scalar _x, const Scalar _y, const Scalar _a, const Scalar _b)
170 {
171 return _a * _x * _x + _b * _y * _y;
172 }
173
175 template <typename Scalar>
176 [[nodiscard]] inline Scalar getParaboloidZ(Scalar _x, Scalar _y, Scalar _a, Scalar _b, Scalar _c, Scalar _d,
177 Scalar _e, Scalar _f)
178 {
179 return _a * _x * _x + _b * _y * _y + _c * _x * _y + _d * _x + _e * _y + _f;
180 }
181
183 template <typename VectorType>
184 [[nodiscard]] inline VectorType getParaboloidNormal(const VectorType& in, const typename VectorType::Scalar _a,
185 const typename VectorType::Scalar _b)
186 {
187 return VectorType((_a * in.x()), (_b * in.y()), -1.).normalized();
188 ;
189 }
190 template <typename DataPoint>
191 inline typename std::enable_if<Ponca::hasNormal<DataPoint>::value, void>::type getParaboloidNormal(
192 DataPoint& in, typename DataPoint::Scalar _a, typename DataPoint::Scalar _b, typename DataPoint::Scalar _c,
193 typename DataPoint::Scalar _d, typename DataPoint::Scalar _e, typename DataPoint::Scalar _f)
194 {
195 static constexpr typename DataPoint::Scalar two{2};
196 auto& pos = in.pos();
197 in.normal() = typename DataPoint::VectorType(two * _a * pos.x() + _c * pos.y() + _d,
198 two * _b * pos.y() + _c * pos.x() + _d, -1.)
199 .normalized();
200 }
201
202 template <typename DataPoint>
203 inline typename std::enable_if<!Ponca::hasNormal<DataPoint>::value, void>::type getParaboloidNormal(
204 DataPoint& in, typename DataPoint::Scalar _a, typename DataPoint::Scalar _b, typename DataPoint::Scalar _c,
205 typename DataPoint::Scalar _d, typename DataPoint::Scalar _e, typename DataPoint::Scalar _f)
206 {
207 }
208 } // namespace internal
209
214 template <typename DataPoint>
215 [[nodiscard]] DataPoint getPointOnParaboloid(const typename DataPoint::Scalar _a,
216 const typename DataPoint::Scalar _b,
217 const typename DataPoint::Scalar _s, const bool _bAddNoise = true)
218 {
219 using Scalar = typename DataPoint::Scalar;
220 using VectorType = typename DataPoint::VectorType;
221
222 VectorType vNormal;
223 VectorType vPosition;
224
225 const Scalar x = Eigen::internal::random<Scalar>(-_s, _s), y = Eigen::internal::random<Scalar>(-_s, _s);
226
229
230 if (_bAddNoise) // spherical noise
231 vPosition +=
232 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
233
234 return DataPoint(vPosition, vNormal);
235 }
236
240 template <typename DataPoint>
241 [[nodiscard]] DataPoint getPointOnParaboloid(typename DataPoint::Scalar _a, typename DataPoint::Scalar _b,
242 typename DataPoint::Scalar _c, typename DataPoint::Scalar _d,
243 typename DataPoint::Scalar _e, typename DataPoint::Scalar _f,
244 typename DataPoint::Scalar _s, bool _bAddNoise = true)
245 {
246 using Scalar = typename DataPoint::Scalar;
247 using VectorType = typename DataPoint::VectorType;
248
249 DataPoint out;
250
251 // generate random position in polar coordinates to get points on the circle
252 out.pos() = getPointOnCircle(_s, VectorType({0, 0, 0}));
253 out.pos().z() = internal::getParaboloidZ(out.pos().x(), out.pos().y(), _a, _b, _c, _d, _e, _f);
254
255 // does nothing if the point type does not have a normal field.
257
258 if (_bAddNoise) // spherical noise
259 {
260 out.pos() +=
261 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
262 }
263
264 return out;
265 }
266
267 template <typename DataPoint, typename Params>
268 [[nodiscard]] DataPoint getPointOnParaboloid(const Params& _params, typename DataPoint::Scalar _s,
269 bool _bAddNoise = true)
270 {
271 return getPointOnParaboloid<DataPoint>(_params(0), _params(1), _params(2), _params(3), _params(4), _params(5),
272 _s, _bAddNoise);
273 }
274
276 template <typename DataPoint>
277 [[nodiscard]] DataPoint getRandomPoint()
278 {
279 using Scalar = typename DataPoint::Scalar;
280 using VectorType = typename DataPoint::VectorType;
281 const VectorType n = VectorType::Random().normalized();
282 const VectorType p = n * Eigen::internal::random<Scalar>(MIN_NOISE, MAX_NOISE);
283 return {p, (n + VectorType::Random() * Scalar(0.1)).normalized()};
284 }
285} // namespace Ponca
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:318
VectorType getParaboloidNormal(const VectorType &in, const typename VectorType::Scalar _a, const typename VectorType::Scalar _b)
Generate z value using the equation z = ax^2 + by^2.
Scalar getParaboloidZ(const Scalar _x, const Scalar _y, const Scalar _a, const Scalar _b)
Generate z value using the equation z = ax^2 + by^2.
This Source Code Form is subject to the terms of the Mozilla Public License, v.
DataPoint getPointOnPlane(const typename DataPoint::VectorType _vPosition, const typename DataPoint::VectorType _vNormal, const typename DataPoint::Scalar _radius, const bool _bAddPositionNoise=true, const bool _bAddNormalNoise=true, const bool _bReverseNormals=false)
Generate points on a plane.
DataPoint getPointOnParaboloid(const typename DataPoint::Scalar _a, const typename DataPoint::Scalar _b, const typename DataPoint::Scalar _s, const bool _bAddNoise=true)
Generate point samples on the primitive z = ax^2 + by^2.
DataPoint getRandomPoint()
Generate a random points.
DataPoint getPointOnSphere(const typename DataPoint::Scalar _radius, const typename DataPoint::VectorType _vCenter, const bool _bAddPositionNoise=true, const bool _bAddNormalNoise=true, const bool _bReverseNormals=false)
Generate points on a sphere.
DataPoint getPointOnRectangularPlane(const typename DataPoint::VectorType &_vPosition, const typename DataPoint::VectorType &, const typename DataPoint::Scalar &_width, const typename DataPoint::Scalar &_height, const typename DataPoint::VectorType &_localxAxis, const typename DataPoint::VectorType &_localyAxis, const bool _bAddPositionNoise=true)
Generate points on a plane without normals.
VectorType getPointOnCircle(typename VectorType::Scalar _radius, VectorType _vCenter)
Sample points on a circle in the xy plane.