Sphere.cpp
Go to the documentation of this file.
1#include "Sphere.h"
2
4#include <GfxTL/MathHelper.h>
6#ifdef DOPARALLEL
7#include <omp.h>
8#endif
9
10extern int dmat_solve(int n, int rhs_num, double a[]);
11
12void
13tetrahedron_circumsphere_3d(double tetra[3 * 4], double* r, double pc[3])
14
15//******************************************************************************
16//
17// Purpose:
18//
19// TETRAHEDRON_CIRCUMSPHERE_3D computes the circumsphere of a tetrahedron in 3D.
20//
21// Discussion:
22//
23// The circumsphere, or circumscribed sphere, of a tetrahedron is the sphere that
24// passes through the four vertices. The circumsphere is not necessarily
25// the smallest sphere that contains the tetrahedron.
26//
27// Surprisingly, the diameter of the sphere can be found by solving
28// a 3 by 3 linear system. This is because the vectors P2 - P1,
29// P3 - P1 and P4 - P1 are secants of the sphere, and each forms a
30// right triangle with the diameter through P1. Hence, the dot product of
31// P2 - P1 with that diameter is equal to the square of the length
32// of P2 - P1, and similarly for P3 - P1 and P4 - P1. This determines
33// the diameter vector originating at P1, and hence the radius and
34// center.
35//
36// Modified:
37//
38// 10 August 2005
39//
40// Author:
41//
42// John Burkardt
43//
44// Reference:
45//
46// Adrian Bowyer and John Woodwark,
47// A Programmer's Geometry,
48// Butterworths, 1983.
49//
50// Parameters:
51//
52// Input, double TETRA[3*4], the vertices of the tetrahedron.
53//
54// Output, double *R, PC[3], the coordinates of the center of the
55// circumscribed sphere, and its radius. If the linear system is
56// singular, then R = -1, PC[] = 0.
57//
58{
59#define DIM_NUM 3
60#define RHS_NUM 1
61
62 double a[DIM_NUM * (DIM_NUM + RHS_NUM)];
63 int info;
64 //
65 // Set up the linear system.
66 //
67 a[0 + 0 * 3] = tetra[0 + 1 * 3] - tetra[0 + 0 * 3];
68 a[0 + 1 * 3] = tetra[1 + 1 * 3] - tetra[1 + 0 * 3];
69 a[0 + 2 * 3] = tetra[2 + 1 * 3] - tetra[2 + 0 * 3];
70 a[0 + 3 * 3] = std::pow(tetra[0 + 1 * 3] - tetra[0 + 0 * 3], 2) +
71 std::pow(tetra[1 + 1 * 3] - tetra[1 + 0 * 3], 2) +
72 std::pow(tetra[2 + 1 * 3] - tetra[2 + 0 * 3], 2);
73
74 a[1 + 0 * 3] = tetra[0 + 2 * 3] - tetra[0 + 0 * 3];
75 a[1 + 1 * 3] = tetra[1 + 2 * 3] - tetra[1 + 0 * 3];
76 a[1 + 2 * 3] = tetra[2 + 2 * 3] - tetra[2 + 0 * 3];
77 a[1 + 3 * 3] = std::pow(tetra[0 + 2 * 3] - tetra[0 + 0 * 3], 2) +
78 std::pow(tetra[1 + 2 * 3] - tetra[1 + 0 * 3], 2) +
79 std::pow(tetra[2 + 2 * 3] - tetra[2 + 0 * 3], 2);
80
81 a[2 + 0 * 3] = tetra[0 + 3 * 3] - tetra[0 + 0 * 3];
82 a[2 + 1 * 3] = tetra[1 + 3 * 3] - tetra[1 + 0 * 3];
83 a[2 + 2 * 3] = tetra[2 + 3 * 3] - tetra[2 + 0 * 3];
84 a[2 + 3 * 3] = std::pow(tetra[0 + 3 * 3] - tetra[0 + 0 * 3], 2) +
85 std::pow(tetra[1 + 3 * 3] - tetra[1 + 0 * 3], 2) +
86 std::pow(tetra[2 + 3 * 3] - tetra[2 + 0 * 3], 2);
87 //
88 // Solve the linear system.
89 //
90 info = dmat_solve(DIM_NUM, RHS_NUM, a);
91 //
92 // If the system was singular, return a consolation prize.
93 //
94 if (info != 0)
95 {
96 *r = -1.0;
97 for (size_t i = 0; i < DIM_NUM; ++i)
98 {
99 pc[i] = 0;
100 }
101 //dvec_zero ( DIM_NUM, pc );
102 return;
103 }
104 //
105 // Compute the radius and center.
106 //
107 *r = 0.5 * std::sqrt(a[0 + 3 * 3] * a[0 + 3 * 3] + a[1 + 3 * 3] * a[1 + 3 * 3] +
108 a[2 + 3 * 3] * a[2 + 3 * 3]);
109
110 pc[0] = tetra[0 + 0 * 3] + 0.5 * a[0 + 3 * 3];
111 pc[1] = tetra[1 + 0 * 3] + 0.5 * a[1 + 3 * 3];
112 pc[2] = tetra[2 + 0 * 3] + 0.5 * a[2 + 3 * 3];
113
114 return;
115#undef DIM_NUM
116#undef RHS_NUM
117}
118
119bool
120Midpoint(const Vec3f& p1, const Vec3f& n1, const Vec3f& p2, const Vec3f& n2, Vec3f* mid)
121{
122 float d1343, d4321, d1321, d4343, d2121;
123 float numer, denom, mua, mub;
124
125 Vec3f p13 = p1 - p2;
126 // p43 = n2
127 // p21 = n1
128 d1343 = p13[0] * n2[0] + p13[1] * n2[1] + p13[2] * n2[2];
129 d4321 = n2[0] * n1[0] + n2[1] * n1[1] + n2[2] * n1[2];
130 d1321 = p13[0] * n1[0] + p13[1] * n1[1] + p13[2] * n1[2];
131 d4343 = n2[0] * n2[0] + n2[1] * n2[1] + n2[2] * n2[2];
132 d2121 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2];
133
134 denom = d2121 * d4343 - d4321 * d4321;
135 if (abs(denom) < 1e-6)
136 {
137 return false;
138 }
139 numer = d1343 * d4321 - d1321 * d4343;
140
141 mua = numer / denom;
142 mub = (d1343 + d4321 * (mua)) / d4343;
143
144 Vec3f pa, pb;
145 pa = p1 + mua * n1;
146 pb = p2 + mub * n2;
147 *mid = 0.5f * (pa + pb);
148 return true;
149}
150
151InvalidTetrahedonError::InvalidTetrahedonError() : std::runtime_error("Invalid tetrahedon")
152{
153}
154
156{
157}
158
159Sphere::Sphere(const Vec3f& center, float radius) : m_center(center), m_radius(radius)
160{
161}
162
163Sphere::Sphere(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4)
164{
165 if (!Init(p1, p2, p3, p4))
166 {
168 }
169}
170
171bool
173{
174 if (samples.size() < 4)
175 {
176 return false;
177 }
178 // get center
179 size_t c = samples.size() / 2;
180 m_center = Vec3f(0, 0, 0);
181 size_t midCount = 0;
182 for (size_t i = 0; i < c - 1; ++i)
183 for (size_t j = i + 1; j < c; ++j)
184 {
185 Vec3f mid;
186 if (!Midpoint(samples[i], samples[i + c], samples[j], samples[j + c], &mid))
187 {
188 continue;
189 }
190 m_center += mid;
191 ++midCount;
192 }
193 if (!midCount)
194 {
195 return false;
196 }
197 m_center /= midCount;
198 m_radius = 0;
199 for (size_t i = 0; i < c; ++i)
200 {
201 float d = (samples[i] - m_center).length();
202 m_radius += d;
203 }
204 m_radius /= c;
205 return true;
206}
207
208bool
209Sphere::Init(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4)
210{
211 // convert to double array
212 double tetra[4 * 3];
213 for (size_t i = 0; i < 3; ++i)
214 {
215 tetra[0 * 3 + i] = p1[i];
216 }
217 for (size_t i = 0; i < 3; ++i)
218 {
219 tetra[1 * 3 + i] = p2[i];
220 }
221 for (size_t i = 0; i < 3; ++i)
222 {
223 tetra[2 * 3 + i] = p3[i];
224 }
225 for (size_t i = 0; i < 3; ++i)
226 {
227 tetra[3 * 3 + i] = p4[i];
228 }
229 double r, pc[3];
230 tetrahedron_circumsphere_3d(tetra, &r, pc);
231 if (r < 0)
232 {
233 return false;
234 }
235 m_radius = r;
236 m_center[0] = pc[0];
237 m_center[1] = pc[1];
238 m_center[2] = pc[2];
239 return true;
240}
241
242bool
243Sphere::Init2(const Vec3f& p1, const Vec3f& p2, const Vec3f& n1, const Vec3f& n2)
244{
245 /*
246 Calculate the line segment PaPb that is the shortest route between
247 two lines P1P2 and P3P4. Calculate also the values of mua and mub where
248 Pa = P1 + mua (P2 - P1)
249 Pb = P3 + mub (P4 - P3)
250 Return FALSE if no solution exists.
251 */
252 float d1343, d4321, d1321, d4343, d2121;
253 float numer, denom, mua, mub;
254
255 Vec3f p13 = p1 - p2;
256 // p43 = n2
257 // p21 = n1
258 d1343 = p13[0] * n2[0] + p13[1] * n2[1] + p13[2] * n2[2];
259 d4321 = n2[0] * n1[0] + n2[1] * n1[1] + n2[2] * n1[2];
260 d1321 = p13[0] * n1[0] + p13[1] * n1[1] + p13[2] * n1[2];
261 d4343 = n2[0] * n2[0] + n2[1] * n2[1] + n2[2] * n2[2];
262 d2121 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2];
263
264 denom = d2121 * d4343 - d4321 * d4321;
265 if (abs(denom) < 1e-6)
266 {
267 return false;
268 }
269 numer = d1343 * d4321 - d1321 * d4343;
270
271 mua = numer / denom;
272 mub = (d1343 + d4321 * (mua)) / d4343;
273
274 Vec3f pa, pb;
275 pa = p1 + mua * n1;
276 pb = p2 + mub * n2;
277
278 // get the midpoint between pa and pb and make it the center
279 m_center = 0.5f * (pa + pb);
280 // make the radius the average of the two distances
281 float da = (p1 - m_center).length();
282 float db = (p2 - m_center).length();
283 m_radius = 0.5f * (da + db);
284 // do some plausability checks
285 // lets say the actual distance should not deviate by more than 10%
286 float dev = da / m_radius;
287 if (dev < 0.9f || dev > 1.1f)
288 {
289 return false;
290 }
291 dev = db / m_radius;
292 if (dev < 0.9f || dev > 1.1f)
293 {
294 return false;
295 }
296 // distance between pa and pb should not be greater than 10% of the radius
297 dev = (pa - pb).length() / m_radius;
298 if (dev > 0.1f)
299 {
300 return false;
301 }
302 return true;
303}
304
305bool
306Sphere::Init(bool binary, std::istream* i)
307{
308 if (binary)
309 {
310 i->read((char*)&m_center, sizeof(m_center));
311 i->read((char*)&m_radius, sizeof(m_radius));
312 }
313 else
314 {
315 for (size_t j = 0; j < 3; ++j)
316 {
317 (*i) >> m_center[j];
318 }
319 (*i) >> m_radius;
320 }
321 return true;
322}
323
324void
326{
327 fread(&m_center, sizeof(m_center), 1, i);
328 fread(&m_radius, sizeof(m_radius), 1, i);
329}
330
331void
332Sphere::Init(float* array)
333{
334 for (int i = 0; i < 3; i++)
335 {
336 m_center[i] = array[i];
337 }
338 m_radius = array[3];
339}
340
341void
342Sphere::Project(const Vec3f& p, Vec3f* pp) const
343{
344 *pp = p - m_center;
345 float l = pp->length();
346 *pp *= m_radius / l;
347 *pp += m_center;
348}
349
350const Vec3f&
352{
353 return m_center;
354}
355
356float
358{
359 return m_radius;
360}
361
362float
363SphereDistance(const float* param, const float* x)
364{
365 float s = x[0] - param[0];
366 s *= s;
367 for (unsigned int i = 1; i < 3; ++i)
368 {
369 float ss = x[i] - param[i];
370 s += ss * ss;
371 }
372 return std::sqrt(s) - param[3];
373}
374
375void
376SphereDistanceDerivatives(const float* param, const float* x, float* gradient)
377{
378 float s[3];
379 s[0] = x[0] - param[0];
380 float sl = s[0] * s[0];
381 for (unsigned int i = 1; i < 3; ++i)
382 {
383 s[i] = x[i] - param[i];
384 sl += s[i] * s[i];
385 }
386 sl = std::sqrt(sl);
387 gradient[0] = -s[0] / sl;
388 gradient[1] = -s[1] / sl;
389 gradient[2] = -s[2] / sl;
390 gradient[3] = -1;
391}
392
393void
395{
396}
397
398bool
407
408bool
410 const MiscLib::Vector<float>& weights,
411 Sphere* is)
412{
413 Vec3f center(0, 0, 0);
414 float radius = 0;
415 for (size_t i = 0; i < spheres.size(); ++i)
416 {
417 center += weights[i] * spheres[i].Center();
418 radius += weights[i] * spheres[i].Radius();
419 }
420 is->Center(center);
421 is->Radius(radius);
422 return true;
423}
424
425void
426Sphere::Serialize(bool binary, std::ostream* o) const
427{
428 if (binary)
429 {
430 o->write((const char*)&m_center, sizeof(m_center));
431 o->write((const char*)&m_radius, sizeof(m_radius));
432 }
433 else
434 {
435 (*o) << m_center[0] << " " << m_center[1] << " " << m_center[2] << " " << m_radius << " ";
436 }
437}
438
439size_t
441{
442 return sizeof(Vec3f) + sizeof(float);
443}
444
445size_t
447{
448 return 4;
449}
450
451void
452Sphere::Serialize(FILE* o) const
453{
454 fwrite(&m_center, sizeof(m_center), 1, o);
455 fwrite(&m_radius, sizeof(m_radius), 1, o);
456}
457
458void
459Sphere::Serialize(float* array) const
460{
461 for (int i = 0; i < 3; i++)
462 {
463 array[i] = m_center[i];
464 }
465 array[3] = m_radius;
466}
467
468void
469Sphere::Transform(float scale, const Vec3f& translate)
470{
471 m_center *= scale;
472 m_center += translate;
473 m_radius *= scale;
474}
475
477 const Vec3f& planeNormal) :
478 m_sphere(sphere), m_planeNormal(planeNormal), m_hcs(GfxTL::Vector3Df(planeNormal))
479{
480}
481
482void
483SphereAsSquaresParametrization::Init(const Sphere& sphere, const Vec3f& planeNormal)
484{
485 m_sphere = sphere;
486 m_planeNormal = planeNormal;
487 m_hcs.FromNormal(planeNormal[0], planeNormal[1], planeNormal[2]);
488}
489
490float
491SphereAsSquaresParametrization::Parameters(const Vec3f& p, std::pair<float, float>* param) const
492{
493 // convert to hemisphere coordinates
494 Vec3f s = p - m_sphere.Center();
495 s.normalize();
496 Vec3f hs;
497 hs[0] = s.dot(m_hcs[0].Data());
498 hs[1] = s.dot(m_hcs[1].Data());
499 hs[2] = s.dot(m_planeNormal);
500 float ret = hs[2];
501 hs[2] = abs(hs[2]);
502 std::pair<float, float> inDisk;
503 Hemisphere2Disk(hs, &inDisk);
504 Disk2Square(inDisk, param);
505 return ret;
506}
507
508bool
509SphereAsSquaresParametrization::InSpace(const std::pair<float, float>& param,
510 bool lower,
511 Vec3f* p) const
512{
513 if (param.first < -0.1 || param.first > 1.1 || param.second < -0.1 || param.second > 1.1)
514 {
515 return false;
516 }
517 std::pair<float, float> clampedParam;
518 clampedParam.first = GfxTL::Math<float>::Clamp(param.first, 0, 1);
519 clampedParam.second = GfxTL::Math<float>::Clamp(param.second, 0, 1);
520 std::pair<float, float> inDisk;
521 Square2Disk(clampedParam, &inDisk);
522 Vec3f s;
523 Disk2Hemisphere(inDisk, &s);
524 *p = Vec3f((s[0] * m_hcs[0] + s[1] * m_hcs[1] +
525 GfxTL::Vector3Df((lower ? -1 : 1) * s[2] * m_planeNormal))
526 .Data());
527 *p *= m_sphere.Radius();
528 *p += m_sphere.Center();
529 return true;
530}
531
532bool
533SphereAsSquaresParametrization::InSpace(const std::pair<float, float>& param,
534 bool lower,
535 Vec3f* p,
536 Vec3f* n) const
537{
538 if (param.first < -0.1 || param.first > 1.1 || param.second < -0.1 || param.second > 1.1)
539 {
540 return false;
541 }
542 std::pair<float, float> clampedParam;
543 clampedParam.first = GfxTL::Math<float>::Clamp(param.first, 0, 1);
544 clampedParam.second = GfxTL::Math<float>::Clamp(param.second, 0, 1);
545 std::pair<float, float> inDisk;
546 Square2Disk(clampedParam, &inDisk);
547 Vec3f s;
548 Disk2Hemisphere(inDisk, &s);
549 if (lower)
550 {
551 s[2] *= -1;
552 }
553 *n = Vec3f((s[0] * m_hcs[0] + s[1] * m_hcs[1] + GfxTL::Vector3Df(s[2] * m_planeNormal)).Data());
554 *p = m_sphere.Radius() * (*n);
555 *p += m_sphere.Center();
556 return true;
557}
558
559void
561 const GfxTL::Vector3Df& trans)
562{
563 m_sphere = Sphere(Vec3f((rot * GfxTL::Vector3Df(m_sphere.Center()) + trans).Data()),
564 m_sphere.Radius());
565 m_planeNormal = Vec3f((rot * GfxTL::Vector3Df(m_planeNormal)).Data());
566 m_hcs[0] = rot * m_hcs[0];
567 m_hcs[1] = rot * m_hcs[1];
568}
569
570void
572 Vec3f* hcs1,
573 Vec3f* hcs2) const
574{
575 hcs0->setValue(m_hcs[0]);
576 hcs1->setValue(m_hcs[1]);
577 hcs2->setValue(m_hcs[2]);
578}
579
580void
581SphereAsSquaresParametrization::Hemisphere2Disk(const Vec3f& p,
582 std::pair<float, float>* inDisk) const
583{
584 inDisk->first = std::sqrt(1 - p[2]);
585 inDisk->second = std::atan2(p[1], p[0]);
586}
587
588void
589SphereAsSquaresParametrization::Disk2Square(const std::pair<float, float>& inDisk,
590 std::pair<float, float>* inSquare) const
591{
592 float r = inDisk.first;
593 float phi = inDisk.second;
594 float a, b;
595
596 if (phi < float(-M_PI / 4.0))
597 {
598 phi += float(2 * M_PI);
599 }
600
601 if (phi < float(M_PI / 4.0))
602 {
603 a = r;
604 b = phi * a / float(M_PI / 4.0);
605 }
606 else if (phi < float(3 * M_PI / 4.0))
607 {
608 b = r;
609 a = -(phi - float(M_PI / 2.0)) * b / float(M_PI / 4.0);
610 }
611 else if (phi < float(5 * M_PI / 4.0))
612 {
613 a = -r;
614 b = (phi - float(M_PI)) * a / float(M_PI / 4.0);
615 }
616 else
617 {
618 b = -r;
619 a = -(phi - float(3 * M_PI / 2.0)) * b / float(M_PI / 4.0);
620 }
621
622 inSquare->first = (a + float(1.0)) / float(2.0);
623 inSquare->second = (b + float(1.0)) / float(2.0);
624}
625
626void
627SphereAsSquaresParametrization::Square2Disk(const std::pair<float, float>& inSquare,
628 std::pair<float, float>* inDisk) const
629{
630 float phi, r;
631 float a = 2 * inSquare.first - 1;
632 float b = 2 * inSquare.second - 1;
633
634 if (a > -b)
635 {
636 if (a > b)
637 {
638 r = a;
639 phi = float(M_PI / 4.0) * (b / a);
640 }
641 else
642 {
643 r = b;
644 phi = float(M_PI / 4.0) * (2 - (a / b));
645 }
646 }
647 else
648 {
649 if (a < b)
650 {
651 r = -a;
652 phi = float(M_PI / 4.0) * (4 + (b / a));
653 }
654 else
655 {
656 r = -b;
657 if (b != 0)
658 {
659 phi = float(M_PI / 4.0) * (6 - (a / b));
660 }
661 else
662 {
663 phi = 0;
664 }
665 }
666 }
667
668 inDisk->first = r;
669 inDisk->second = phi;
670}
671
672void
673SphereAsSquaresParametrization::Disk2Hemisphere(const std::pair<float, float>& inDisk,
674 Vec3f* p) const
675{
676 (*p)[0] = inDisk.first * std::sqrt(2 - inDisk.first * inDisk.first) * std::cos(inDisk.second);
677 (*p)[1] = inDisk.first * std::sqrt(2 - inDisk.first * inDisk.first) * std::sin(inDisk.second);
678 (*p)[2] = 1 - inDisk.first * inDisk.first;
679}
#define float
Definition 16_Level.h:22
#define M_PI
Definition MathTools.h:17
void tetrahedron_circumsphere_3d(double tetra[3 *4], double *r, double pc[3])
Definition Sphere.cpp:13
int dmat_solve(int n, int rhs_num, double a[])
Definition solve.cpp:9
void NormalizeSphereParams(float *param)
Definition Sphere.cpp:394
#define RHS_NUM
#define DIM_NUM
float SphereDistance(const float *param, const float *x)
Definition Sphere.cpp:363
void SphereDistanceDerivatives(const float *param, const float *x, float *gradient)
Definition Sphere.cpp:376
bool Midpoint(const Vec3f &p1, const Vec3f &n1, const Vec3f &p2, const Vec3f &n2, Vec3f *mid)
Definition Sphere.cpp:120
constexpr T c
static ScalarT Clamp(ScalarT s, ScalarT bottom, ScalarT top)
Definition MathHelper.h:39
size_type size() const
Definition Vector.h:215
float Parameters(const Vec3f &p, std::pair< float, float > *param) const
Definition Sphere.cpp:491
bool InSpace(const std::pair< float, float > &param, bool lower, Vec3f *p) const
Definition Sphere.cpp:509
void Init(const Sphere &sphere, const Vec3f &planeNormal)
Definition Sphere.cpp:483
void Transform(const GfxTL::MatrixXX< 3, 3, float > &rot, const GfxTL::Vector3Df &trans)
Definition Sphere.cpp:560
void HyperplaneCoordinateSystem(Vec3f *hcs0, Vec3f *hcs1, Vec3f *hcs2) const
Definition Sphere.cpp:571
static size_t SerializedFloatSize()
Definition Sphere.cpp:446
Sphere()
Definition Sphere.cpp:155
const Vec3f & Center() const
Definition Sphere.cpp:351
static bool Interpolate(const MiscLib::Vector< Sphere > &spheres, const MiscLib::Vector< float > &weights, Sphere *is)
Definition Sphere.cpp:409
static size_t SerializedSize()
Definition Sphere.cpp:440
bool LeastSquaresFit(const PointCloud &pc, MiscLib::Vector< size_t >::const_iterator begin, MiscLib::Vector< size_t >::const_iterator end)
Definition Sphere.cpp:399
void Transform(float scale, const Vec3f &translate)
Definition Sphere.cpp:469
float Radius() const
Definition Sphere.cpp:357
void Project(const Vec3f &p, Vec3f *pp) const
Definition Sphere.cpp:342
bool Init2(const Vec3f &p1, const Vec3f &p2, const Vec3f &n1, const Vec3f &n2)
Definition Sphere.cpp:243
void Serialize(bool binary, std::ostream *o) const
Definition Sphere.cpp:426
bool Init(const MiscLib::Vector< Vec3f > &samples)
Definition Sphere.cpp:172
Definition basic.h:18
Vec3f & setValue(const float v[3])
Definition basic.h:51
float length() const
Definition basic.h:135
Definition AABox.h:10
VectorXD< 3, float > Vector3Df
Definition VectorXD.h:718
IndexedIterator< IndexIteratorT, IteratorT > IndexIterate(IndexIteratorT idxIt, IteratorT it)
double a(double t, double a0, double j)
Definition CtrlUtil.h:45
This file offers overloads of toIce() and fromIce() functions for STL container types.