13 template<
class InIteratorT,
class OutIteratorT >
14 static void SpinImage(
const Vec3f& axisPos,
const Vec3f& axisDir,
15 InIteratorT begin, InIteratorT end, OutIteratorT out)
17 for (; begin != end; ++begin)
19 Vec3f s = *begin - axisPos;
21 spin[1] =
s.dot(axisDir);
22 spin[0] = (
s - spin[1] * axisDir).length();
27 template<
class InIteratorT >
28 static bool CircleFrom3Points(InIteratorT i,
float* r,
38 + std::pow(i[1][1] - i[0][1], 2));
39 b =
std::sqrt(std::pow(i[2][0] - i[1][0], 2)
40 + std::pow(i[2][1] - i[1][1], 2));
42 + std::pow(i[0][1] - i[2][1], 2));
44 bot = (
a + b +
c) * (-
a + b +
c) * (
a - b +
c) * (
a + b -
c);
53 top1 = (i[1][1] - i[0][1]) *
c *
c - (i[2][1] - i[0][1]) *
a *
a;
54 top2 = (i[1][0] - i[0][0]) *
c *
c - (i[2][0] - i[0][0]) *
a *
a;
55 bot = (i[1][1] - i[0][1]) * (i[2][0] - i[0][0])
56 - (i[2][1] - i[0][1]) * (i[1][0] - i[0][0]);
58 (*center)[0] = i[0][0] + 0.5f * top1 / bot;
59 (*center)[1] = i[0][1] - 0.5f * top2 / bot;
66 if (samples.
size() < 8)
80 size_t k = samples.
size() >> 1;
83 for (
size_t i = 0; i < samples.
size(); ++i)
87 double a01 = n0xn1 * dsamples[k + 2];
88 double b01 = n0xn1 * dsamples[k + 3];
89 double a0 = ((dsamples[2] - dsamples[1])
90 % dsamples[k]) * dsamples[k + 2];
91 double a1 = ((dsamples[0] - dsamples[2])
92 % dsamples[k + 1]) * dsamples[k + 2];
93 double a = ((dsamples[0] - dsamples[2])
94 % (dsamples[1] - dsamples[0])) * dsamples[k + 2];
95 double b0 = ((dsamples[3] - dsamples[1])
96 % dsamples[k]) * dsamples[k + 3];
97 double b1 = ((dsamples[0] - dsamples[3])
98 % dsamples[k + 1]) * dsamples[k + 3];
99 double b = ((dsamples[0] - dsamples[3])
100 % (dsamples[1] - dsamples[0])) * dsamples[k + 3];
101 double cc = b01 / a01;
102 double ccc = b0 - a0 * cc;
103 double c = -(b1 - a1 * cc) / ccc;
104 double d = (-b +
a * cc) / ccc;
105 double p = (a0 *
c + a1 + a01 * d) / (2 * a01 *
c);
106 double q = (
a + a0 * d) / (a01 *
c);
107 double rt = p * p -
q;
118 double s1 =
c * t1 + d;
119 double s2 =
c * t2 + d;
121 Vec3f pos1 = samples[0] + s1 * samples[k];
122 Vec3f normal1 = pos1 - (samples[1] + t1 * samples[k + 1]);
124 Vec3f pos2 = samples[0] + s2 * samples[k];
125 Vec3f normal2 = pos2 - (samples[1] + t2 * samples[k + 1]);
130 SpinImage(pos1, normal1, samples.begin(), samples.begin() + k,
131 std::back_inserter(spin1));
132 SpinImage(pos2, normal2, samples.begin(), samples.begin() + k,
133 std::back_inserter(spin2));
134 float minorRadius1, majorRadius1, minorRadius2, majorRadius2,
135 distSum1 = std::numeric_limits< float >::infinity(),
136 distSum2 = std::numeric_limits< float >::infinity(),
139 if (CircleFrom3Points(spin1.
begin(), &minorRadius1, &minorCenter1))
141 majorRadius1 = minorCenter1[0];
144 for (
size_t i = 3; i < spin1.
size(); ++i)
145 distSum1 += (tmp = ((spin1[i] - minorCenter1).Length()
146 - minorRadius1)) * tmp;
148 if (CircleFrom3Points(spin2.
begin(), &minorRadius2, &minorCenter2))
150 majorRadius2 = minorCenter2[0];
153 for (
size_t i = 3; i < spin2.
size(); ++i)
154 distSum2 += (tmp = ((spin2[i] - minorCenter2).Length()
155 - minorRadius2)) * tmp;
157 if (distSum1 != std::numeric_limits< float >::infinity()
158 && distSum1 < distSum2)
161 m_rminor = minorRadius1;
162 m_rmajor = majorRadius1;
163 m_center = pos1 + minorCenter1[1] * m_normal;
165 else if (distSum2 != std::numeric_limits< float >::infinity())
168 m_rminor = minorRadius2;
169 m_rmajor = majorRadius2;
170 m_center = pos2 + minorCenter2[1] * m_normal;
176 m_appleShaped = m_rmajor < m_rminor;
177 ComputeAppleParams();
183 if (samples.
size() < 8)
197 size_t k = samples.
size() >> 1;
200 for (
size_t i = 0; i < samples.
size(); ++i)
205 Vec3f pos1, normal1, pos2, normal2;
206 for (
size_t w = 0; w < k; ++w)
208 for (
size_t x = 0; x < k; ++x)
211 for (
size_t y = 0; y < k; ++y)
213 for (
size_t z = 0; z < k; ++z)
215 double a01 = n0xn1 * dsamples[k + y];
216 double b01 = n0xn1 * dsamples[k + z];
222 double a0 = ((dsamples[y] - dsamples[x])
223 % dsamples[k + w]) * dsamples[k + y];
224 double a1 = ((dsamples[w] - dsamples[y])
225 % dsamples[k + x]) * dsamples[k + y];
226 double a = ((dsamples[w] - dsamples[y])
227 % (dsamples[x] - dsamples[w])) * dsamples[k + y];
228 double b0 = ((dsamples[z] - dsamples[x])
229 % dsamples[k + w]) * dsamples[k + z];
230 double b1 = ((dsamples[w] - dsamples[z])
231 % dsamples[k + x]) * dsamples[k + z];
232 double b = ((dsamples[w] - dsamples[z])
233 % (dsamples[x] - dsamples[w])) * dsamples[k + z];
234 double cc = b01 / a01;
235 double ccc = b0 - a0 * cc;
236 double c = -(b1 - a1 * cc) / ccc;
237 double d = (-b +
a * cc) / ccc;
238 double p = (a0 *
c + a1 + a01 * d) / (2 * a01 *
c);
239 double q = (
a + a0 * d) / (a01 *
c);
240 double rt = p * p -
q;
251 double s1 =
c * t1 + d;
252 double s2 =
c * t2 + d;
253 pos1 = samples[w] + s1 * samples[k + w];
254 normal1 = pos1 - (samples[x] + t1 * samples[k + x]);
256 pos2 = samples[w] + s2 * samples[k + w];
257 normal2 = pos2 - (samples[x] + t2 * samples[k + x]);
269 SpinImage(pos1, normal1, samples.
begin(), samples.
begin() + k,
270 std::back_inserter(spin1));
271 SpinImage(pos2, normal2, samples.
begin(), samples.
begin() + k,
272 std::back_inserter(spin2));
273 float minorRadius1, majorRadius1, minorRadius2, majorRadius2,
274 distSum1 = std::numeric_limits< float >::infinity(),
275 distSum2 = std::numeric_limits< float >::infinity(),
278 if (CircleFrom3Points(spin1.
begin(), &minorRadius1, &minorCenter1))
280 majorRadius1 = minorCenter1[0];
283 for (
size_t i = 3; i < spin1.
size(); ++i)
284 distSum1 += (tmp = ((spin1[i] - minorCenter1).Length()
285 - minorRadius1)) * tmp;
287 if (CircleFrom3Points(spin2.
begin(), &minorRadius2, &minorCenter2))
289 majorRadius2 = minorCenter2[0];
292 for (
size_t i = 3; i < spin2.
size(); ++i)
293 distSum2 += (tmp = ((spin2[i] - minorCenter2).Length()
294 - minorRadius2)) * tmp;
296 if (distSum1 != std::numeric_limits< float >::infinity()
297 && distSum1 < distSum2)
300 m_rminor = minorRadius1;
301 m_rmajor = majorRadius1;
302 m_center = pos1 + minorCenter1[1] * m_normal;
304 else if (distSum2 != std::numeric_limits< float >::infinity())
307 m_rminor = minorRadius2;
308 m_rmajor = majorRadius2;
309 m_center = pos2 + minorCenter2[1] * m_normal;
315 m_appleShaped = m_rmajor < m_rminor;
316 ComputeAppleParams();
324 i->read((
char*)&m_normal,
sizeof(m_center));
325 i->read((
char*)&m_center,
sizeof(m_center));
326 i->read((
char*)&m_rminor,
sizeof(m_rminor));
327 i->read((
char*)&m_rmajor,
sizeof(m_rmajor));
331 for (
size_t j = 0; j < 3; ++j)
335 for (
size_t j = 0; j < 3; ++j)
342 m_appleShaped = m_rmajor < m_rminor;
343 ComputeAppleParams();
350 fread(&m_normal,
sizeof(m_normal), 1, i);
351 fread(&m_center,
sizeof(m_center), 1, i);
352 fread(&m_rminor,
sizeof(m_rminor), 1, i);
353 fread(&m_rmajor,
sizeof(m_rmajor), 1, i);
354 fread(&rot,
sizeof(rot), 1, i);
355 m_appleShaped = m_rmajor < m_rminor;
356 ComputeAppleParams();
361 for (
int i = 0; i < 3; i++)
363 m_normal[i] = array[i];
364 m_center[i] = array[i + 3];
368 m_appleShaped = m_rmajor < m_rminor;
369 ComputeAppleParams();
376 m_center += translate;
382 s[0] = x[0] - param[0];
383 s[1] = x[1] - param[1];
384 s[2] = x[2] - param[2];
385 float g =
s[0] * param[3] +
s[1] * param[4] +
s[2] * param[5];
386 float f = param[5] *
s[1] - param[4] *
s[2];
388 float v = param[3] *
s[2] - param[5] *
s[0];
390 v = param[4] *
s[0] - param[3] *
s[1];
394 return std::sqrt(g * g + ((tmp = (f - param[6])) * tmp)) - param[7];
401 s[0] = x[0] - param[0];
402 s[1] = x[1] - param[1];
403 s[2] = x[2] - param[2];
404 float g =
s[0] * param[3] +
s[1] * param[4] +
s[2] * param[5];
405 float f = param[5] *
s[1] - param[4] *
s[2];
407 float v = param[3] *
s[2] - param[5] *
s[0];
409 v = param[4] *
s[0] - param[3] *
s[1];
416 dg[3] =
s[0] - param[3] * g;
417 dg[4] =
s[1] - param[4] * g;
418 dg[5] =
s[2] - param[5] * g;
420 df[0] = (param[3] * g -
s[0]) / f;
421 df[1] = (param[4] * g -
s[1]) / f;
422 df[2] = (param[5] * g -
s[2]) / f;
427 float d =
std::sqrt(g * g + ((tmp = (f - param[6])) * tmp)) - param[7];
428 float dr = d + param[7];
429 float fr = f - param[6];
430 for (
unsigned int i = 0; i < 6; ++i)
432 gradient[i] = (g * dg[i] + fr * df[i]) / dr;
434 gradient[6] = -fr * dr;
440 float l =
std::sqrt(param[3] * param[3] + param[4] * param[4]
441 + param[5] * param[5]);
442 for (
unsigned int i = 3; i < 6; ++i)
448 template<
class WeightT >
456 template<
class IteratorT >
461 int size = end - begin;
462 #pragma omp parallel for schedule(static) reduction(+:chi)
463 for (
int idx = 0; idx < size; ++idx)
466 s[0] = begin[idx][0] - params[0];
467 s[1] = begin[idx][1] - params[1];
468 s[2] = begin[idx][2] - params[2];
469 ScalarType g =
s[0] * params[3] +
s[1] * params[4] +
s[2] * params[5];
474 v = params[4] *
s[0] - params[3] *
s[1];
479 chi += (
values[idx] = WeightT::Weigh(
480 std::sqrt(g * g + ((tmp = (f - params[6])) * tmp)) - params[7]))
486 template<
class IteratorT >
490 int size = end - begin;
491 #pragma omp parallel for schedule(static)
492 for (
int idx = 0; idx < size; ++idx)
495 s[0] = begin[idx][0] - params[0];
496 s[1] = begin[idx][1] - params[1];
497 s[2] = begin[idx][2] - params[2];
504 dg[3] =
s[0] - params[3] * g;
505 dg[4] =
s[1] - params[4] * g;
506 dg[5] =
s[2] - params[5] * g;
508 df[0] = (params[3] * g -
s[0]) / temp[idx];
509 df[1] = (params[4] * g -
s[1]) / temp[idx];
510 df[2] = (params[5] * g -
s[2]) / temp[idx];
518 for (
unsigned int j = 0; j < 6; ++j)
520 matrix[idx *
NumParams + j] = (g * dg[j] + fr * df[j]) / dr;
524 WeightT::template DerivWeigh< NumParams >(d, matrix + idx *
NumParams);
531 + params[5] * params[5]);
532 for (
unsigned int i = 3; i < 6; ++i)
544 for (
size_t i = 0; i < 3; ++i)
546 param[i] = m_center[i];
548 for (
size_t i = 0; i < 3; ++i)
550 param[i + 3] = m_normal[i];
560 for (
size_t i = 0; i < 3; ++i)
562 m_center[i] = param[i];
564 for (
size_t i = 0; i < 3; ++i)
566 m_normal[i] = param[i + 3];
570 m_appleShaped = m_rmajor < m_rminor;
571 ComputeAppleParams();
579 o->write((
const char*)&m_normal,
sizeof(m_normal));
580 o->write((
const char*)&m_center,
sizeof(m_center));
581 o->write((
const char*)&m_rminor,
sizeof(m_rminor));
582 o->write((
const char*)&m_rmajor,
sizeof(m_rmajor));
586 (*o) << m_normal[0] <<
" " << m_normal[1] <<
" " << m_normal[2] <<
" "
587 << m_center[0] <<
" " << m_center[1] <<
" " << m_center[2] <<
" "
588 << m_rminor <<
" " << m_rmajor <<
" ";
602 fwrite(&m_normal,
sizeof(m_normal), 1, o);
603 fwrite(&m_center,
sizeof(m_center), 1, o);
604 fwrite(&m_rminor,
sizeof(m_rminor), 1, o);
605 fwrite(&m_rmajor,
sizeof(m_rmajor), 1, o);
615 for (
int i = 0; i < 3; i++)
617 array[i] = m_normal[i];
618 array[i + 3] = m_center[i];
625 void Torus::ComputeAppleParams()
629 m_cutOffAngle =
M_PI;
633 m_cutOffAngle = std::acos((2 * m_rmajor - m_rminor) / m_rminor) +
M_PI / 2.f;
634 m_appleHeight = std::sin(m_cutOffAngle) * m_rminor;