Ponca  7b3f8ad3fde25a027e6452783ccee143798a71b8
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#include "./concepts.h"
16
17#define MIN_NOISE 0.99
18#define MAX_NOISE 1.01
19
20namespace Ponca
21{
22
24 template <typename DataPoint>
25 [[nodiscard]] DataPoint getPointOnSphere(const typename DataPoint::Scalar _radius,
26 const typename DataPoint::VectorType _vCenter,
27 const bool _bAddPositionNoise = true, const bool _bAddNormalNoise = true,
28 const bool _bReverseNormals = false)
29 {
30 using Scalar = typename DataPoint::Scalar;
31 using VectorType = typename DataPoint::VectorType;
32
33 VectorType vNormal = VectorType::Random().normalized();
34 VectorType vPosition = _vCenter + vNormal * _radius;
35
37 {
38 vPosition = vPosition + VectorType::Random().normalized() *
39 Eigen::internal::random<Scalar>(Scalar(0.), Scalar(1. - MIN_NOISE));
41 }
42
44 {
45 VectorType vTempPos = vPosition + VectorType::Random().normalized() *
46 Eigen::internal::random<Scalar>(Scalar(0.), Scalar(1. - MIN_NOISE));
48 }
50 {
51 const float reverse = Eigen::internal::random<float>(0.f, 1.f);
52 if (reverse > 0.5f)
54 }
55
56 return DataPoint(vPosition, vNormal);
57 }
58
60 template <typename VectorType>
61 [[nodiscard]] VectorType getPointOnCircle(typename VectorType::Scalar _radius, VectorType _vCenter)
62 {
63 using Scalar = typename VectorType::Scalar;
64 // Generate random angle
65 const Scalar theta = Eigen::internal::random<Scalar>(0, Scalar(2. * EIGEN_PI));
66
67 // Generate random radius (adjusted for uniform area distribution)
68 const Scalar r = _radius * std::sqrt(Eigen::internal::random<Scalar>(0, 1));
69
70 // Convert to Cartesian coordinates
71 VectorType p = _vCenter;
72 p.x() += r * std::cos(theta);
73 p.y() += r * std::sin(theta);
74
75 return p;
76 }
77
79 template <typename DataPoint>
80 [[nodiscard]] DataPoint getPointOnRectangularPlane(const typename DataPoint::VectorType& _vPosition,
81 const typename DataPoint::VectorType& /*_vNormal*/,
82 const typename DataPoint::Scalar& _width,
83 const typename DataPoint::Scalar& _height,
84 const typename DataPoint::VectorType& _localxAxis,
85 const typename DataPoint::VectorType& _localyAxis,
86 const bool _bAddPositionNoise = true)
87 {
88 using Scalar = typename DataPoint::Scalar;
89 using VectorType = typename DataPoint::VectorType;
90
91 const Scalar u = Eigen::internal::random<Scalar>(-_width / Scalar(2), _width / Scalar(2));
92 const Scalar v = Eigen::internal::random<Scalar>(-_height / Scalar(2), _height / Scalar(2));
93
95
97 {
99 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(0., 1. - MIN_NOISE);
100 }
101
102 return DataPoint(vRandomPosition);
103 }
104
106 template <typename DataPoint>
107 [[nodiscard]] DataPoint getPointOnPlane(const typename DataPoint::VectorType _vPosition,
108 const typename DataPoint::VectorType _vNormal,
109 const typename DataPoint::Scalar _radius,
110 const bool _bAddPositionNoise = true, const bool _bAddNormalNoise = true,
111 const bool _bReverseNormals = false)
112 {
113 using Scalar = typename DataPoint::Scalar;
114 using VectorType = typename DataPoint::VectorType;
115 using QuaternionType = Eigen::Quaternion<Scalar>;
116
117 VectorType vRandom;
118 VectorType vRandomDirection = VectorType::Zero();
119 VectorType vRandomPoint = VectorType::Zero();
120 VectorType vLocalUp = _vNormal;
121
122 do
123 {
124 vRandom = VectorType::Random().normalized(); // Direction in the unit sphere
126 } while (vRandomDirection == VectorType::Zero());
127
128 vRandomDirection = vRandomDirection.normalized();
131
133 {
134 vRandomPoint = vRandomPoint + VectorType::Random().normalized() *
135 Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
136 }
137
139 {
140 VectorType vLocalLeft = vLocalUp.cross(vRandomDirection);
141 VectorType vLocalFront = vLocalLeft.cross(vLocalUp);
142
143 Scalar rotationAngle = Eigen::internal::random<Scalar>(Scalar(-M_PI / 16.), Scalar(M_PI / 16.));
144 VectorType vRotationAxis = vLocalLeft;
146 qRotation = qRotation.normalized();
148
149 rotationAngle = Eigen::internal::random<Scalar>(Scalar(-M_PI / 16.), Scalar(M_PI / 16.));
151 qRotation = QuaternionType(Eigen::AngleAxis<Scalar>(rotationAngle, vRotationAxis));
152 qRotation = qRotation.normalized();
154 }
155
157 {
158 const float reverse = Eigen::internal::random<float>(0.f, 1.f);
159 if (reverse > 0.5f)
161 }
162
163 return DataPoint(vRandomPoint, vLocalUp);
164 }
165
166 namespace internal
167 {
169 template <typename Scalar>
170 [[nodiscard]] inline Scalar getParaboloidZ(const Scalar _x, const Scalar _y, const Scalar _a, const Scalar _b)
171 {
172 return _a * _x * _x + _b * _y * _y;
173 }
174
176 template <typename Scalar>
177 [[nodiscard]] inline Scalar getParaboloidZ(Scalar _x, Scalar _y, Scalar _a, Scalar _b, Scalar _c, Scalar _d,
178 Scalar _e, Scalar _f)
179 {
180 return _a * _x * _x + _b * _y * _y + _c * _x * _y + _d * _x + _e * _y + _f;
181 }
182
184 template <typename VectorType>
185 [[nodiscard]] inline VectorType getParaboloidNormal(const VectorType& in, const typename VectorType::Scalar _a,
186 const typename VectorType::Scalar _b)
187 {
188 return VectorType((_a * in.x()), (_b * in.y()), -1.).normalized();
189 ;
190 }
191 template <IsPointNormal DataPoint>
192 inline void getParaboloidNormal(DataPoint& in, typename DataPoint::Scalar _a, typename DataPoint::Scalar _b,
193 typename DataPoint::Scalar _c, typename DataPoint::Scalar _d,
194 typename DataPoint::Scalar _e, typename DataPoint::Scalar _f)
195 {
196 static constexpr typename DataPoint::Scalar two{2};
197 auto& pos = in.pos();
198 in.normal() = typename DataPoint::VectorType(two * _a * pos.x() + _c * pos.y() + _d,
199 two * _b * pos.y() + _c * pos.x() + _d, -1.)
200 .normalized();
201 }
202 } // namespace internal
203
208 template <typename DataPoint>
209 [[nodiscard]] DataPoint getPointOnParaboloid(const typename DataPoint::Scalar _a,
210 const typename DataPoint::Scalar _b,
211 const typename DataPoint::Scalar _s, const bool _bAddNoise = true)
212 {
213 using Scalar = typename DataPoint::Scalar;
214 using VectorType = typename DataPoint::VectorType;
215
216 VectorType vNormal;
217 VectorType vPosition;
218
219 const Scalar x = Eigen::internal::random<Scalar>(-_s, _s), y = Eigen::internal::random<Scalar>(-_s, _s);
220
223
224 if (_bAddNoise) // spherical noise
225 vPosition +=
226 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
227
228 return DataPoint(vPosition, vNormal);
229 }
230
234 template <typename DataPoint>
235 [[nodiscard]] DataPoint getPointOnParaboloid(typename DataPoint::Scalar _a, typename DataPoint::Scalar _b,
236 typename DataPoint::Scalar _c, typename DataPoint::Scalar _d,
237 typename DataPoint::Scalar _e, typename DataPoint::Scalar _f,
238 typename DataPoint::Scalar _s, bool _bAddNoise = true)
239 {
240 using Scalar = typename DataPoint::Scalar;
241 using VectorType = typename DataPoint::VectorType;
242
243 DataPoint out;
244
245 // generate random position in polar coordinates to get points on the circle
246 out.pos() = getPointOnCircle(_s, VectorType({0, 0, 0}));
247 out.pos().z() = internal::getParaboloidZ(out.pos().x(), out.pos().y(), _a, _b, _c, _d, _e, _f);
248
249 // does nothing if the point type does not have a normal field.
251
252 if (_bAddNoise) // spherical noise
253 {
254 out.pos() +=
255 VectorType::Random().normalized() * Eigen::internal::random<Scalar>(Scalar(0), Scalar(1. - MIN_NOISE));
256 }
257
258 return out;
259 }
260
261 template <typename DataPoint, typename Params>
262 [[nodiscard]] DataPoint getPointOnParaboloid(const Params& _params, typename DataPoint::Scalar _s,
263 bool _bAddNoise = true)
264 {
265 return getPointOnParaboloid<DataPoint>(_params(0), _params(1), _params(2), _params(3), _params(4), _params(5),
266 _s, _bAddNoise);
267 }
268
270 template <typename DataPoint>
271 [[nodiscard]] DataPoint getRandomPoint()
272 {
273 using Scalar = typename DataPoint::Scalar;
274 using VectorType = typename DataPoint::VectorType;
275 const VectorType n = VectorType::Random().normalized();
276 const VectorType p = n * Eigen::internal::random<Scalar>(MIN_NOISE, MAX_NOISE);
277 return {p, (n + VectorType::Random() * Scalar(0.1)).normalized()};
278 }
279} // namespace Ponca
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:294
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.
Definition concepts.h:11
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.