50 bool Init(
const Vec3f& p1,
56 bool Init(
bool binary, std::istream* i);
58 void Init(
float* array);
59 inline float Distance(
const Vec3f& p)
const;
61 inline float DistanceAndNormal(
const Vec3f& p,
Vec3f*
n)
const;
62 inline float SignedDistance(
const Vec3f& p)
const;
63 inline float SignedDistanceAndNormal(
const Vec3f& p,
Vec3f*
n)
const;
67 inline float Height(
const Vec3f& p)
const;
68 inline float Angle()
const;
70 inline const Vec3f& AxisDirection()
const;
78 inline const Vec3f AngularDirection()
const;
80 void RotateAngularDirection(
float radians);
81 inline float RadiusAtLength(
float length)
const;
85 template <
class IteratorT>
86 bool LeastSquaresFit(IteratorT begin, IteratorT end);
93 return LeastSquaresFit(
pc, begin, end);
99 void Serialize(
bool binary, std::ostream* o)
const;
100 static size_t SerializedSize();
101 void Serialize(FILE* o)
const;
102 void Serialize(
float* array)
const;
103 static size_t SerializedFloatSize();
104 void Transform(
float scale,
const Vec3f& translate);
107 Intersect(
const Vec3f& p,
const Vec3f& r,
float lambda[2],
Vec3f interPts[2])
const;
110 template <
class WeightT>
111 class LevMarCone :
public WeightT
119 typedef float ScalarType;
121 template <
class IteratorT>
123 Chi(
const ScalarType* params,
127 ScalarType* temp)
const
130 ScalarType cosPhi = std::cos(params[6]);
131 ScalarType sinPhi = std::sin(params[6]);
132 int size = end - begin;
133 #pragma omp parallel for schedule(static) reduction(+ : chi)
134 for (
int idx = 0; idx < size; ++idx)
137 for (
unsigned int j = 0; j < 3; ++j)
139 s[j] = begin[idx][j] - params[j];
141 ScalarType g =
abs(
s[0] * params[3] +
s[1] * params[4] +
s[2] * params[5]);
142 ScalarType f =
s.sqrLength() - (g * g);
152 chi += (
values[idx] = WeightT::Weigh(cosPhi * f - sinPhi * g)) *
values[idx];
157 template <
class IteratorT>
159 Derivatives(
const ScalarType* params,
163 const ScalarType* temp,
164 ScalarType* matrix)
const
166 ScalarType sinPhi = -std::sin(params[6]);
167 ScalarType cosPhi = std::cos(params[6]);
168 int size = end - begin;
169 #pragma omp parallel for schedule(static)
170 for (
int idx = 0; idx < size; ++idx)
173 for (
unsigned int j = 0; j < 3; ++j)
175 s[j] = begin[idx][j] - params[j];
177 ScalarType g =
abs(
s[0] * params[3] +
s[1] * params[4] +
s[2] * params[5]);
178 ScalarType ggradient[6];
179 for (
unsigned int j = 0; j < 3; ++j)
181 ggradient[j] = -params[j + 3];
183 for (
unsigned int j = 0; j < 3; ++j)
185 ggradient[j + 3] =
s[j] - params[j + 3] * g;
187 ScalarType fgradient[6];
188 if (temp[idx] < 1e-6)
190 fgradient[0] =
std::sqrt(1 - params[3] * params[3]);
191 fgradient[1] =
std::sqrt(1 - params[4] * params[4]);
192 fgradient[2] =
std::sqrt(1 - params[5] * params[5]);
196 fgradient[0] = (params[3] * g -
s[0]) / temp[idx];
197 fgradient[1] = (params[4] * g -
s[1]) / temp[idx];
198 fgradient[2] = (params[5] * g -
s[2]) / temp[idx];
200 fgradient[3] = g * fgradient[0];
201 fgradient[4] = g * fgradient[1];
202 fgradient[5] = g * fgradient[2];
203 for (
unsigned int j = 0; j < 6; ++j)
204 matrix[idx * NumParams + j] = cosPhi * fgradient[j] + sinPhi * ggradient[j];
205 matrix[idx * NumParams + 6] = temp[idx] * sinPhi - g * cosPhi;
206 WeightT::template DerivWeigh<NumParams>(cosPhi * temp[idx] + sinPhi * g,
207 matrix + idx * NumParams);
212 Normalize(
float* params)
const
216 std::sqrt(params[3] * params[3] + params[4] * params[4] + params[5] * params[5]);
217 for (
unsigned int i = 3; i < 6; ++i)
222 params[6] -= std::floor(params[6] / (2 * ScalarType(
M_PI))) *
223 (2 * ScalarType(
M_PI));
224 if (params[6] >
M_PI)
226 params[6] -= std::floor(params[6] / ScalarType(
M_PI)) *
228 for (
unsigned int i = 3; i < 6; ++i)
233 if (params[6] > ScalarType(
M_PI) / 2)
235 params[6] = ScalarType(
M_PI) - params[6];
248 float m_angularRotatedRadians;
256 float g =
s.dot(m_axisDir);
259 float sqrS =
s.sqrLength();
260 float f = sqrS - (g * g);
269 float da = m_n2d[0] * f;
270 float db = m_n2d[1] * g;
271 if (g < 0 && da - db < 0)
282 Vec3f pln =
s.cross(m_axisDir);
286 *
n = m_normal[0] * plx + m_normalY;
294 float g =
s.dot(m_axisDir);
297 float sqrS =
s.sqrLength();
298 float f = sqrS - (g * g);
307 float da = m_n2d[0] * f;
308 float db = m_n2d[1] * g;
310 if (g < 0 && da - db < 0)
319 Vec3f plx =
s - g * m_axisDir;
321 *
n = m_normal[0] * plx + m_normalY;
330 float g =
s.dot(m_axisDir);
333 float sqrS =
s.sqrLength();
334 float f = sqrS - (g * g);
343 float da = m_n2d[0] * f;
344 float db = m_n2d[1] * g;
345 if (g < 0 && da - db < 0)
357 float g =
s.dot(m_axisDir);
360 float sqrS =
s.sqrLength();
361 float f = sqrS - (g * g);
370 float da = m_n2d[0] * f;
371 float db = m_n2d[1] * g;
373 if (g < 0 && da - db < 0)
382 Vec3f plx =
s - g * m_axisDir;
384 *
n = m_normal[0] * plx + m_normalY;
409 return Vec3f(m_hcs[0].Data());
415 return std::sin(m_angle) *
abs(length);
422 return m_axisDir.
dot(
s);
425 template <
class IteratorT>
430 for (
unsigned int i = 0; i < 3; ++i)
432 param[i] = m_center[i];
434 for (
unsigned int i = 0; i < 3; ++i)
436 param[i + 3] = m_axisDir[i];
439 LevMarCone<LevMarLSWeight> levMarCone;
440 if (!
LevMar(begin, end, levMarCone, param))
444 if (param[6] < 1e-6 || param[6] >
float(
M_PI) / 2 - 1e-6)
448 for (
unsigned int i = 0; i < 3; ++i)
450 m_center[i] = param[i];
452 for (
unsigned int i = 0; i < 3; ++i)
454 m_axisDir[i] = param[i + 3];
457 m_normal =
Vec3f(std::cos(-m_angle), std::sin(-m_angle), 0);
458 m_normalY = m_normal[1] * m_axisDir;
459 m_n2d[0] = std::cos(m_angle);
460 m_n2d[1] = -std::sin(m_angle);
461 m_hcs.FromNormal(m_axisDir);
462 m_angularRotatedRadians = 0;
469 intptr_t size = end - begin;
470 #ifndef _WIN64 // for some reason the Microsoft x64 compiler crashes at the next line
471 #pragma omp parallel for schedule(static) reduction(+ : heightSum)
473 for (intptr_t i = 0; i < size; ++i)
475 heightSum +=
Height(begin[i]);
480 m_hcs.FromNormal(m_axisDir);
502 float fAdD = m_axisDir.dot(r);
503 float tmp, fCosSqr = (tmp = cos(m_angle)) * tmp;
504 Vec3f kE = p - m_center;
505 float fAdE = m_axisDir.
dot(kE);
506 float fDdE = r.
dot(kE);
507 float fEdE = kE.
dot(kE);
508 float fC2 = fAdD * fAdD - fCosSqr;
509 float fC1 = fAdD * fAdE - fCosSqr * fDdE;
510 float fC0 = fAdE * fAdE - fCosSqr * fEdE;
514 unsigned int interCount = 0;
515 if (
abs(fC2) >= 1e-7)
518 float fDiscr = fC1 * fC1 - fC0 * fC2;
519 if (fDiscr < (
float)0.0)
525 else if (fDiscr > 1e-7)
531 float fRoot =
sqrt(fDiscr);
532 float fInvC2 = ((
float)1.0) / fC2;
535 float fT = (-fC1 - fRoot) * fInvC2;
538 interPts[interCount] = p + fT * r;
539 kE = interPts[interCount] - m_center;
540 fdot = kE.
dot(m_axisDir);
541 if (fdot > (
float)0.0)
543 lambda[interCount] = fT;
548 fT = (-fC1 + fRoot) * fInvC2;
551 interPts[interCount] = p + fT * r;
552 kE = interPts[interCount] - m_center;
553 fdot = kE.
dot(m_axisDir);
554 if (fdot > (
float)0.0)
556 lambda[interCount] = fT;
561 else if (fC1 / fC2 < 0)
564 interPts[0] = p - (fC1 / fC2) * r;
565 lambda[0] = -(fC1 / fC2);
566 kE = interPts[0] - m_center;
577 else if (
abs(fC1) >= 1e-7)
580 lambda[0] = -(((
float)0.5) * fC0 / fC1);
585 interPts[0] = p + lambda[0] * r;
586 kE = interPts[0] - m_center;
587 fdot = kE.
dot(m_axisDir);
588 if (fdot > (
float)0.0)
597 else if (
abs(fC0) >= 1e-7)
607 lambda[0] = (m_center - p).
dot(r);
608 interPts[0] = m_center;