Sphere.h
Go to the documentation of this file.
1#ifndef SPHERE_HEADER
2#define SPHERE_HEADER
3#include <stdio.h>
4
5#include <istream>
6#include <ostream>
7#include <stdexcept>
8#include <utility>
9
10#include "LevMarFitting.h"
11#include "LevMarLSWeight.h"
12#include "PointCloud.h"
13#include "basic.h"
16#include <MiscLib/Vector.h>
17
18#ifndef DLL_LINKAGE
19#define DLL_LINKAGE
20#endif
21
22struct DLL_LINKAGE InvalidTetrahedonError : public std::runtime_error
23{
25};
26
28{
29public:
30 enum
31 {
33 };
34
35 Sphere();
36 Sphere(const Vec3f& center, float radius);
37 Sphere(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4);
38 bool Init(const MiscLib::Vector<Vec3f>& samples);
39 bool Init(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4);
40 bool Init2(const Vec3f& p1, const Vec3f& p2, const Vec3f& n1, const Vec3f& n2);
41 bool Init(bool binary, std::istream* i);
42 void Init(FILE* i);
43 void Init(float* array);
44 inline float Distance(const Vec3f& p) const;
45 inline void Normal(const Vec3f& p, Vec3f* normal) const;
46 inline float DistanceAndNormal(const Vec3f& p, Vec3f* normal) const;
47 inline float SignedDistance(const Vec3f& p) const;
48 void Project(const Vec3f& p, Vec3f* pp) const;
49 const Vec3f& Center() const;
50
51 void
52 Center(const Vec3f& center)
53 {
54 m_center = center;
55 }
56
57 float Radius() const;
58
59 void
60 Radius(float radius)
61 {
62 m_radius = radius;
63 }
64
65 bool LeastSquaresFit(const PointCloud& pc,
68 template <class IteratorT>
69 bool LeastSquaresFit(IteratorT begin, IteratorT end);
70
71 bool
78
79 static bool Interpolate(const MiscLib::Vector<Sphere>& spheres,
80 const MiscLib::Vector<float>& weights,
81 Sphere* is);
82 void Serialize(bool binary, std::ostream* o) const;
83 static size_t SerializedSize();
84 void Serialize(FILE* o) const;
85 void Serialize(float* array) const;
86 static size_t SerializedFloatSize();
87
88 void Transform(float scale, const Vec3f& translate);
89 inline unsigned int
90 Intersect(const Vec3f& p, const Vec3f& r, float* first, float* second) const;
91
92private:
93 template <class WeightT>
94 class LevMarSimpleSphere : public WeightT
95 {
96 public:
97 enum
98 {
99 NumParams = 4
100 };
101
102 typedef float ScalarType;
103
104 template <class IteratorT>
105 ScalarType
106 Chi(const ScalarType* params,
107 IteratorT begin,
108 IteratorT end,
109 ScalarType* values,
110 ScalarType* temp) const
111 {
112 ScalarType chi = 0;
113 int size = end - begin;
114#pragma omp parallel for schedule(static) reduction(+ : chi)
115 for (int idx = 0; idx < size; ++idx)
116 {
117 float s = begin[idx][0] - params[0];
118 s *= s;
119 for (unsigned int j = 1; j < 3; ++j)
120 {
121 float ss = begin[idx][j] - params[j];
122 s += ss * ss;
123 }
124 values[idx] = WeightT::Weigh(std::sqrt(s) - params[3]);
125 chi += values[idx] * values[idx];
126 }
127 return chi;
128 }
129
130 template <class IteratorT>
131 void
132 Derivatives(const ScalarType* params,
133 IteratorT begin,
134 IteratorT end,
135 const ScalarType* values,
136 const ScalarType* temp,
137 ScalarType* matrix) const
138 {
139 int size = end - begin;
140#pragma omp parallel for schedule(static)
141 for (int idx = 0; idx < size; ++idx)
142 {
143 float s[3];
144 s[0] = begin[idx][0] - params[0];
145 float sl = s[0] * s[0];
146 for (unsigned int i = 1; i < 3; ++i)
147 {
148 s[i] = begin[idx][i] - params[i];
149 sl += s[i] * s[i];
150 }
151 sl = std::sqrt(sl);
152 matrix[idx * NumParams + 0] = -s[0] / sl;
153 matrix[idx * NumParams + 1] = -s[1] / sl;
154 matrix[idx * NumParams + 2] = -s[2] / sl;
155 matrix[idx * NumParams + 3] = -1;
156 WeightT::template DerivWeigh<NumParams>(sl - params[3], matrix + idx * NumParams);
157 }
158 }
159
160 void
161 Normalize(ScalarType*) const
162 {
163 }
164 };
165
166 template <class WeightT>
167 class LevMarSphere : public WeightT
168 {
169 public:
170 enum
171 {
172 NumParams = 7
173 };
174
175 typedef float ScalarType;
176
177 // parametrization: params[0] - params[2] = normal
178 // params[3] - params[5] = point
179 // params[6] = 1 / radius
180
181 template <class IteratorT>
182 ScalarType
183 Chi(const ScalarType* params,
184 IteratorT begin,
185 IteratorT end,
186 ScalarType* values,
187 ScalarType* temp) const
188 {
189 ScalarType chi = 0;
190 ScalarType radius = 1 / params[6];
191 Vec3f center = -radius * Vec3f(params[0], params[1], params[2]) +
192 Vec3f(params[3], params[4], params[5]);
193 int size = end - begin;
194#pragma omp parallel for schedule(static) reduction(+ : chi)
195 for (int idx = 0; idx < size; ++idx)
196 {
197 temp[idx] = (begin[idx] - center).length();
198 chi += (values[idx] = WeightT::Weigh(temp[idx] - radius)) * values[idx];
199 }
200 return chi;
201 }
202
203 template <class IteratorT>
204 void
205 Derivatives(const ScalarType* params,
206 IteratorT begin,
207 IteratorT end,
208 const ScalarType* values,
209 const ScalarType* temp,
210 ScalarType* matrix) const
211 {
212 Vec3f normal(params[0], params[1], params[2]);
213 Vec3f point(params[3], params[4], params[5]);
214 int size = end - begin;
215#pragma omp parallel for schedule(static)
216 for (int idx = 0; idx < size; ++idx)
217 {
218 ScalarType denominator = -1.f / temp[idx] * params[6];
219 matrix[idx * NumParams + 0] =
220 (matrix[idx * NumParams + 3] =
221 (point[0] - normal[0] * params[6] - begin[idx][0])) *
222 denominator;
223 matrix[idx * NumParams + 1] =
224 (matrix[idx * NumParams + 4] =
225 (point[1] - normal[1] * params[6] - begin[idx][1])) *
226 denominator;
227 matrix[idx * NumParams + 2] =
228 (matrix[idx * NumParams + 5] =
229 (point[2] - normal[2] * params[6] - begin[idx][2])) *
230 denominator;
231 matrix[idx * NumParams + 3] /= temp[idx];
232 matrix[idx * NumParams + 4] /= temp[idx];
233 matrix[idx * NumParams + 5] /= temp[idx];
234 matrix[idx * NumParams + 6] = (normal[0] * matrix[idx * NumParams + 3] +
235 normal[1] * matrix[idx * NumParams + 4] +
236 normal[2] * matrix[idx * NumParams + 5] + 1) *
237 params[6] * params[6];
238 WeightT::template DerivWeigh<NumParams>(temp[idx] - 1.f / params[6],
239 matrix + idx * NumParams);
240 }
241 }
242
243 void
244 Normalize(ScalarType* params) const
245 {
246 ScalarType len =
247 std::sqrt(params[0] * params[0] + params[1] * params[1] + params[2] * params[2]);
248 params[0] /= len;
249 params[1] /= len;
250 params[2] /= len;
251 }
252 };
253
254private:
255 Vec3f m_center;
256 float m_radius;
257};
258
259inline float
260Sphere::Distance(const Vec3f& p) const
261{
262 return abs((m_center - p).length() - m_radius);
263}
264
265inline void
266Sphere::Normal(const Vec3f& p, Vec3f* normal) const
267{
268 *normal = p - m_center;
269 normal->normalize();
270}
271
272inline float
273Sphere::DistanceAndNormal(const Vec3f& p, Vec3f* normal) const
274{
275 *normal = p - m_center;
276 float l = normal->length();
277 if (l > 0)
278 {
279 *normal /= l;
280 }
281 return abs(l - m_radius);
282}
283
284inline float
286{
287 return (m_center - p).length() - m_radius;
288}
289
290template <class IteratorT>
291bool
292Sphere::LeastSquaresFit(IteratorT begin, IteratorT end)
293{
294 LevMarSimpleSphere<LevMarLSWeight> levMarSphere;
295 float param[4];
296 for (size_t i = 0; i < 3; ++i)
297 {
298 param[i] = m_center[i];
299 }
300 param[3] = m_radius;
301 if (!LevMar(begin, end, levMarSphere, param))
302 {
303 return false;
304 }
305 for (size_t i = 0; i < 3; ++i)
306 {
307 m_center[i] = param[i];
308 }
309 m_radius = param[3];
310 return true;
311}
312
313inline unsigned int
314Sphere::Intersect(const Vec3f& p, const Vec3f& r, float* first, float* second) const
315{
316 using namespace std;
317 Vec3f kDiff = p - m_center;
318 float fA0 = kDiff.dot(kDiff) - m_radius * m_radius;
319 float fA1, fDiscr, fRoot;
320 if (fA0 <= 0)
321 {
322 // P is inside the sphere
323 fA1 = r.dot(kDiff);
324 fDiscr = fA1 * fA1 - fA0;
325 fRoot = sqrt(fDiscr);
326 *first = -fA1 + fRoot;
327 return 1;
328 }
329 // else: P is outside the sphere
330 fA1 = r.dot(kDiff);
331 if (fA1 >= 0)
332 {
333 return 0;
334 }
335 fDiscr = fA1 * fA1 - fA0;
336 if (fDiscr < 0)
337 {
338 return 0;
339 }
340 else if (fDiscr >= /* zero tolerance eps */ 1e-7f)
341 {
342 fRoot = sqrt(fDiscr);
343 *first = -fA1 - fRoot;
344 *second = -fA1 + fRoot;
345 return 2;
346 }
347 *first = -fA1;
348 return 1;
349}
350
352{
353public:
357
358 SphereAsSquaresParametrization(const Sphere& sphere, const Vec3f& planeNormal);
359 void Init(const Sphere& sphere, const Vec3f& planeNormal);
360
361 // returns < 0 if point is on lower hemisphere
362 float Parameters(const Vec3f& p, std::pair<float, float>* param) const;
363 bool InSpace(const std::pair<float, float>& param, bool lower, Vec3f* p) const;
364 bool InSpace(const std::pair<float, float>& param, bool lower, Vec3f* p, Vec3f* n) const;
365 void Transform(const GfxTL::MatrixXX<3, 3, float>& rot, const GfxTL::Vector3Df& trans);
366 void HyperplaneCoordinateSystem(Vec3f* hcs0, Vec3f* hcs1, Vec3f* hcs2) const;
367
368private:
369 void Hemisphere2Disk(const Vec3f& p, std::pair<float, float>* inDisk) const;
370 void Disk2Square(const std::pair<float, float>& inDisk,
371 std::pair<float, float>* inSquare) const;
372 void Square2Disk(const std::pair<float, float>& inSquare,
373 std::pair<float, float>* inDisk) const;
374 void Disk2Hemisphere(const std::pair<float, float>& inDisk, Vec3f* p) const;
375
376private:
377 Sphere m_sphere;
378 Vec3f m_planeNormal;
380};
381
383{
384public:
388
393
394 bool
395 InSpace(const std::pair<float, float>& param, Vec3f* p) const
396 {
397 return SphereAsSquaresParametrization::InSpace(param, false, p);
398 }
399
400 bool
401 InSpace(const std::pair<float, float>& param, Vec3f* p, Vec3f* n) const
402 {
403 return SphereAsSquaresParametrization::InSpace(param, false, p, n);
404 }
405
406 bool
407 InSpace(float u, float v, Vec3f* p) const
408 {
409 return SphereAsSquaresParametrization::InSpace(std::make_pair(u, v), false, p);
410 }
411
412 bool
413 InSpace(float u, float v, Vec3f* p, Vec3f* n) const
414 {
415 return SphereAsSquaresParametrization::InSpace(std::make_pair(u, v), false, p, n);
416 }
417};
418
420{
421public:
425
430
431 bool
432 InSpace(const std::pair<float, float>& param, Vec3f* p) const
433 {
434 return SphereAsSquaresParametrization::InSpace(param, true, p);
435 }
436
437 bool
438 InSpace(const std::pair<float, float>& param, Vec3f* p, Vec3f* n) const
439 {
440 return SphereAsSquaresParametrization::InSpace(param, true, p, n);
441 }
442
443 bool
444 InSpace(float u, float v, Vec3f* p) const
445 {
446 return SphereAsSquaresParametrization::InSpace(std::make_pair(u, v), true, p);
447 }
448
449 bool
450 InSpace(float u, float v, Vec3f* p, Vec3f* n) const
451 {
452 return SphereAsSquaresParametrization::InSpace(std::make_pair(u, v), true, p, n);
453 }
454};
455
456#endif
bool LevMar(IteratorT begin, IteratorT end, FuncT &func, typename FuncT::ScalarType *param)
#define DLL_LINKAGE
Definition basic.h:12
bool InSpace(const std::pair< float, float > &param, Vec3f *p, Vec3f *n) const
Definition Sphere.h:438
LowerSphereAsSquaresParametrization(const SphereAsSquaresParametrization &p)
Definition Sphere.h:426
bool InSpace(const std::pair< float, float > &param, Vec3f *p) const
Definition Sphere.h:432
bool InSpace(float u, float v, Vec3f *p) const
Definition Sphere.h:444
bool InSpace(float u, float v, Vec3f *p, Vec3f *n) const
Definition Sphere.h:450
bool InSpace(const std::pair< float, float > &param, bool lower, Vec3f *p) const
Definition Sphere.cpp:509
Sphere()
Definition Sphere.cpp:155
float SignedDistance(const Vec3f &p) const
Definition Sphere.h:285
void Center(const Vec3f &center)
Definition Sphere.h:52
@ RequiredSamples
Definition Sphere.h:32
float DistanceAndNormal(const Vec3f &p, Vec3f *normal) const
Definition Sphere.h:273
bool LeastSquaresFit(const PointCloud &pc, MiscLib::Vector< size_t >::const_iterator begin, MiscLib::Vector< size_t >::const_iterator end)
Definition Sphere.cpp:399
void Normal(const Vec3f &p, Vec3f *normal) const
Definition Sphere.h:266
bool Fit(const PointCloud &pc, MiscLib::Vector< size_t >::const_iterator begin, MiscLib::Vector< size_t >::const_iterator end)
Definition Sphere.h:72
float Distance(const Vec3f &p) const
Definition Sphere.h:260
void Radius(float radius)
Definition Sphere.h:60
unsigned int Intersect(const Vec3f &p, const Vec3f &r, float *first, float *second) const
Definition Sphere.h:314
bool InSpace(const std::pair< float, float > &param, Vec3f *p, Vec3f *n) const
Definition Sphere.h:401
UpperSphereAsSquaresParametrization(const SphereAsSquaresParametrization &p)
Definition Sphere.h:389
bool InSpace(const std::pair< float, float > &param, Vec3f *p) const
Definition Sphere.h:395
bool InSpace(float u, float v, Vec3f *p) const
Definition Sphere.h:407
bool InSpace(float u, float v, Vec3f *p, Vec3f *n) const
Definition Sphere.h:413
Definition basic.h:18
float length() const
Definition basic.h:135
float normalize()
Definition basic.h:141
float dot(const Vec3f &v) const
Definition basic.h:104
VectorXD< 3, float > Vec3f
Definition VectorXD.h:733
VectorXD< 3, float > Vector3Df
Definition VectorXD.h:718
double s(double t, double s0, double v0, double a0, double j)
Definition CtrlUtil.h:33