LowStretchSphereParametrization.h
Go to the documentation of this file.
1#ifndef LOWSTRETCHSPHEREPARAMETRIZATION_HEADER
2#define LOWSTRETCHSPHEREPARAMETRIZATION_HEADER
3#include <utility>
4
5#include "Sphere.h"
6#include "basic.h"
7#include <GfxTL/AABox.h>
8#include <GfxTL/Frame.h>
9#include <GfxTL/MathHelper.h>
10#include <GfxTL/VectorXD.h>
11#include <MiscLib/Vector.h>
12
14{
15public:
17 void Shape(const Sphere& sphere);
18
19 const Sphere&
20 Shape() const
21 {
22 return *m_sphere;
23 }
24
25 inline void Parameters(const Vec3f& p, std::pair<float, float>* param) const;
26 inline bool InSpace(float u, float v, Vec3f* p) const;
27 inline bool InSpace(float u, float v, Vec3f* p, Vec3f* n) const;
28
29 void
31 float epsilon,
32 bool* uwrap,
33 bool* vwrap) const
34 {
35 *uwrap = false;
36 *vwrap = false;
37 }
38
40 float epsilon,
41 size_t uextent,
42 size_t vextent,
43 MiscLib::Vector<int>* componentImg,
44 MiscLib::Vector<std::pair<int, size_t>>* labels) const;
45 template <class IteratorT>
46 void Optimize(IteratorT begin, IteratorT end, float epsilon);
47 static size_t SerializedSize();
48 void Serialize(std::ostream* o, bool binary) const;
49 void Deserialize(std::istream* i, bool binary);
50
51private:
52 const Sphere* m_sphere;
54};
55
56void
57LowStretchSphereParametrization::Parameters(const Vec3f& p, std::pair<float, float>* param) const
58{
59 Vec3f s = p - m_sphere->Center();
60 float slength = s.length();
62 m_frame.ToLocal(*((GfxTL::Vector3Df*)&s), &l);
63 if (slength > 0)
64 {
65 l[2] /= slength;
66 }
67 l[2] = GfxTL::Math<float>::Clamp(l[2], -1, 1);
68 float radius = std::sqrt(1.f - l[2] * l[2]) * m_sphere->Radius();
69 param->first = std::acos(l[2]) * m_sphere->Radius();
70 param->second = std::atan2(l[1], l[0]) * radius;
71}
72
73bool
75{
76 float uangle = u / m_sphere->Radius();
77 float cosu = std::cos(uangle);
78 float sinu = std::sin(uangle);
79 float radius = sinu * m_sphere->Radius();
80 float vangle = v / radius;
81 float sinv = std::sin(vangle);
82 float cosv = std::cos(vangle);
84 m_frame.ToGlobal(GfxTL::Vector3Df(sinu * cosv, sinu * sinv, cosu), &g);
85 *p = m_sphere->Radius() * Vec3f(g) + m_sphere->Center();
86 return true;
87}
88
89bool
91{
92 float uangle = u / m_sphere->Radius();
93 float cosu = std::cos(uangle);
94 float sinu = std::sin(uangle);
95 float radius = sinu * m_sphere->Radius();
96 float vangle = v / radius;
97 float sinv = std::sin(vangle);
98 float cosv = std::cos(vangle);
100 m_frame.ToGlobal(GfxTL::Vector3Df(sinu * cosv, sinu * sinv, cosu), &g);
101 *n = Vec3f(g);
102 *p = m_sphere->Radius() * (*n) + m_sphere->Center();
103 return true;
104}
105
106template <class IteratorT>
107void
108LowStretchSphereParametrization::Optimize(IteratorT begin, IteratorT end, float epsilon)
109{
110 // tries to find a rotation of the parametrization that does not cut
111 // the points
112
113 // pull the center of the points onto the equator
114 float minUangle = float(M_PI), maxUangle = 0;
115 if (end - begin <= 1)
116 {
117 return;
118 }
119 for (IteratorT i = begin; i != end; ++i)
120 {
121 Vec3f s = *i - m_sphere->Center();
122 float slength = s.length();
123 float h = m_frame.Height(*((GfxTL::Vector3Df*)&s));
124 if (slength > 0)
125 {
126 h /= slength;
127 }
128 h = GfxTL::Math<float>::Clamp(h, -1, 1);
129 float uangle = std::acos(h);
130 if (minUangle > uangle)
131 {
132 minUangle = uangle;
133 }
134 if (maxUangle < uangle)
135 {
136 maxUangle = uangle;
137 }
138 }
139 float centerUangle = (minUangle + maxUangle) / 2;
140 // centerUangle should be located at 90 degrees
142 q.RotationRad(
143 -2 * (centerUangle - float(M_PI / 2)), m_frame[0][0], m_frame[0][1], m_frame[0][2]);
144 GfxTL::Vector3Df newNormal;
145 q.Rotate(m_frame[2], &newNormal);
146 m_frame.FromNormal(newNormal);
147
148 // a rotation around the normal is searched
149 // for this find all the angles and then extract the largest gap
151 for (IteratorT i = begin; i != end; ++i)
152 {
153 Vec3f s = *i - m_sphere->Center();
154 float slength = s.length();
156 m_frame.ToLocal(*((GfxTL::Vector3Df*)&s), &l);
157 if (slength > 0)
158 {
159 l[2] /= slength;
160 }
161 l[2] = GfxTL::Math<float>::Clamp(l[2], -1, 1);
162 float uangle = std::acos(l[2]);
163 if (uangle * m_sphere->Radius() < float(M_PI) * m_sphere->Radius() - 2 * epsilon &&
164 uangle * m_sphere->Radius() > float(-M_PI) * m_sphere->Radius() + 2 * epsilon)
165 {
166 vangles.push_back(std::atan2(l[1], l[0]));
167 }
168 }
169 std::sort(vangles.begin(), vangles.end());
170 // try to find a large gap
171 float maxGap = vangles.front() + 2 * float(M_PI) - vangles.back();
172 float lower = vangles.back(), upper = vangles.front() + 2 * float(M_PI);
173 for (size_t i = 1; i < vangles.size(); ++i)
174 {
175 float gap = vangles[i] - vangles[i - 1];
176 if (gap > maxGap)
177 {
178 maxGap = gap;
179 lower = vangles[i - 1];
180 upper = vangles[i];
181 }
182 }
183 // reparameterize by rotating the frame on the normal such that x direction
184 // coincides with the gap
185 float rotationAngle = (lower + upper) / 2;
186 m_frame.RotateOnNormal(rotationAngle + float(M_PI));
187}
188
189#endif
#define float
Definition 16_Level.h:22
#define M_PI
Definition MathTools.h:17
static ScalarT Clamp(ScalarT s, ScalarT bottom, ScalarT top)
Definition MathHelper.h:39
void WrapComponents(const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, size_t uextent, size_t vextent, MiscLib::Vector< int > *componentImg, MiscLib::Vector< std::pair< int, size_t > > *labels) const
void Deserialize(std::istream *i, bool binary)
void Serialize(std::ostream *o, bool binary) const
void WrapBitmap(const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, bool *uwrap, bool *vwrap) const
void Optimize(IteratorT begin, IteratorT end, float epsilon)
bool InSpace(float u, float v, Vec3f *p) const
void Parameters(const Vec3f &p, std::pair< float, float > *param) const
size_type size() const
Definition Vector.h:215
void push_back(const T &v)
Definition Vector.h:354
Definition basic.h:18
#define q
VectorXD< 3, float > Vector3Df
Definition VectorXD.h:718