transform.cpp
Go to the documentation of this file.
1 // This code was largely copied from an early implementation by UPenn. The author
2 // does not know what the hard-coded values below mean.
3 
5 #include "quori_face/Cache.hpp"
6 
7 #include <cmath>
8 #include <complex>
9 #include <thread>
10 #include <memory>
11 #include <vector>
12 #include <cstring>
13 
14 using namespace quori_face;
15 
16 namespace
17 {
18  template<typename T>
19  inline T square(const T value)
20  {
21  return value * value;
22  }
23 
24  template<typename T>
25  inline T clamp(const T min, const T value, const T max)
26  {
27  if (value < min) return min;
28  if (value > max) return max;
29  return value;
30  }
31 
32  // Closed form solution to the transform
33  // parameters unknown
34  double mTot(const double m, const double d, const double rm, const double R, const double del)
35  {
36  const double m2 = square(m);
37  const double m3 = m2 * m;
38  const double m5 = m3 * m2;
39  const double d2 = square(d);
40  const double d3 = d2 * d;
41  const double rm2 = square(rm);
42  const double rm4 = square(rm2);
43  const double R2 = square(R);
44  const double R3 = R2 * R;
45  const double R4 = R3 * R;
46  const double del2 = square(del);
47  const double del3 = del2 * del;
48  const double del4 = del3 * del;
49  const double m2p1 = m2 + 1.0;
50  const double m2p12 = square(m2p1);
51  const double m2p13 = m2p12 * m2p1;
52  const double Rddel = R + d - del;
53  const double Rddel2 = square(Rddel);
54  const double Rddelrm = Rddel + rm;
55  const double para1 = R * rm - 2.0 * R * del - 2.0 * d * del + d * rm - 2.0 * del * rm + 2.0 * del2 + 4.0 * R2 * m2 + 2.0 * del2 * m2 + d * m2 * rm - 2.0 * del * m2 * rm + 4.0 * R * d * m2 - 6.0 * R * del * m2 + 3.0 * R * m2 * rm - 2.0 * d * del * m2;
56  const double para2 = (8 * R * del3 + 8.0 * d * del3 - 4.0 * del4 - 4.0 * R2 * del2 - 16.0 * R4 * m2 + R2 * rm2 - 4.0 * d2 * del2 - 4.0 * del4 * m2 + d2 * rm2 + 4.0 * del2 * rm2 - 32.0 * R3 * d * m2 + 24 * R * del3 * m2 + 48.0 * R3 * del * m2 + 8.0 * d * del3 * m2 - 16.0 * R2 * d2 * m2 - 52.0 * R2 * del2 * m2 + 9.0 * R2 * m2 * rm2 - 4.0 * d2 * del2 * m2 + d2 * m2 * rm2 + 4.0 * del2 * m2 * rm2 - 8.0 * R * d * del2 + 2.0 * R * d * rm2 - 4.0 * R * del * rm2 - 4.0 * d * del * rm2 - 40 * R * d * del2 * m2 + 16 * R * d2 * del * m2 + 64.0 * R2 * d * del * m2 + 6.0 * R * d * m2 * rm2 - 12.0 * R * del * m2 * rm2 - 4.0 * d * del * m2 * rm2);
57  const double para3 = 2.0 * R * d - 2.0 * R * del - 2.0 * d * del + R2 + d2 - 3.0 * R2 * m2 + d2 * m2 + 2.0 * R * d * m2 + 2.0 * R * del * m2 - 2.0 * d * del * m2;
58  const double para4 = 18.0 * R4 * m * rm2 - 36.0 * R4 * m3 * rm2 - 54.0 * R4 * m5 * rm2 + 54.0 * R2 * d2 * m * rm2 + 36 * R * d3 * m3 * rm2 + 36.0 * R3 * d * m3 * rm2 + 18 * R * d3 * m5 * rm2 - 18.0 * R3 * d * m5 * rm2 + 36.0 * R2 * del2 * m * rm2 + 36.0 * R3 * del * m3 * rm2 + 90.0 * R3 * del * m5 * rm2 + 108.0 * R2 * d2 * m3 * rm2 + 54.0 * R2 * d2 * m5 * rm2 - 36.0 * R2 * del2 * m5 * rm2 + 18 * R * d3 * m * rm2 + 54.0 * R3 * d * m * rm2 - 54.0 * R3 * del * m * rm2 + 36 * R * d * del2 * m * rm2 - 54 * R * d2 * del * m * rm2 - 108.0 * R2 * d * del * m * rm2 + 72 * R * d * del2 * m3 * rm2 - 108.0 * R * d2 * del * m3 * rm2 - 144.0 * R2 * d * del * m3 * rm2 + 36.0 * R * d * del2 * m5 * rm2 - 54 * R * d2 * del * m5 * rm2 - 36.0 * R2 * d * del * m5 * rm2;
59  const std::complex<double> para10 = (m2p13 * std::pow(para2, 3) + 108.0 * R2 * m2 * rm4 * m2p12 * Rddel2 * square(para3));
60  const std::complex<double> para11 = std::sqrt(para10);
61  const std::complex<double> para5 = std::pow((1.7320508075688 * para11 + para4), (1.0 / 3.0));
62  const std::complex<double> para6 = 4330209751607469.0 * para5;
63  const double para7 = 2.49809726143892e16 * m2p1 * para2;
64  const double para8 = 9007199254740992 * R * m * Rddelrm;
65  const std::complex<double> para9 = 36028797018963968 * R * m * Rddelrm * para5;
66  const std::complex<double> ret = std::pow(((6.0 * Rddel) / Rddelrm - (2.0 * Rddel) / Rddelrm + std::pow(para1, 2) / (4.0 * R2 * m2 * std::pow(Rddelrm, 2)) + para6 / para8 - para7 / para9), 0.5) * 0.5 - std::pow(((2.0 * Rddel) / Rddelrm - ((2.0 * (2.0 * R * del + R * rm + 2.0 * d * del + d * rm - 2.0 * del * rm - 2.0 * del2 - 4.0 * R2 * m2 - 2.0 * del2 * m2 + d * m2 * rm - 2.0 * del * m2 * rm - 4.0 * R * d * m2 + 6.0 * R * del * m2 + 3.0 * R * m2 * rm + 2.0 * d * del * m2)) / (R * m * Rddelrm) + std::pow(para1, 3.0) / (4.0 * R3 * m3 * std::pow(Rddelrm, 3)) + (6.0 * (Rddel)*para1) / (R * m * std::pow(Rddelrm, 2))) / std::pow(((6.0 * Rddel) / Rddelrm - (2.0 * Rddel) / Rddelrm + std::pow(para1, 2.0) / (4.0 * R2 * m2 * std::pow(Rddelrm, 2.0)) + para6 / para8 - para7 / para9), 0.5) + (6.0 * Rddel) / Rddelrm + std::pow(para1, 2.0) / (2.0 * R2 * m2 * std::pow(Rddelrm, 2)) - para6 / para8 + para7 / para9), 0.5) * 0.5 - para1 / (4 * R * m * Rddelrm);
67  return ret.real();
68  }
69 
70  Vector2<double> sphere2Plane(const TransformStaticParameters &static_params, const SphericalCoordinate &params)
71  {
72  double d = static_params.h + sqrt(square(static_params.R) - square(static_params.r_o));
73  double del = static_params.R - sqrt(square(static_params.R) - square(static_params.r_m));
74  double x = mTot(tan(params.theta / 2.0), d, static_params.r_m, static_params.R, del);
75  double phi = 2.0 * atan(x);
76  phi = atan(sin(phi) / (((static_params.R - del) + d) / static_params.r_m - cos(phi)));
77  const double l1 = static_params.L * tan(static_params.epsilon - phi);
78  const double l2 = static_params.L * tan(static_params.epsilon + phi);
79 
80  del = (-l1 + l2) / 2.0;
81  phi = del * sin(static_params.epsilon) / cos(phi);
82  phi = sqrt(square(del) - square(phi));
83  x = cos(params.psi - M_PI / 2.0);
84  d = sin(params.psi - M_PI / 2.0);
85  phi = sqrt(1.0 / (square(x) / square(del) + square(d) / square(phi)));
86 
87  return Vector2<double>(
88  (-l1 - l2) / 2.0 + phi * cos(params.psi - M_PI / 2.0),
89  phi * sin(params.psi - M_PI / 2.0)
90  );
91  }
92 
95 }
96 
98 {
99  return (
100  R == other.R
101  && r_m == other.r_m
102  && r_o == other.r_o
103  && h == other.h
104  && L == other.L
105  && epsilon == other.epsilon
106  && delta == other.delta
107  && screen_size == other.screen_size
108  );
109 }
110 
112 {
113  return (
114  R != other.R
115  || r_m != other.r_m
116  || r_o != other.r_o
117  || h != other.h
118  || L != other.L
119  || epsilon != other.epsilon
120  || delta != other.delta
121  || screen_size != other.screen_size
122  );
123 }
124 
126  .R = 4.0,
127  .r_m = 1.5,
128  .r_o = 2.0,
129  .h = 1.0,
130  .L = 8.4476252817457738,
131  .epsilon = 0.059068559067049511,
132  .delta = {
133  .x = -2.9,
134  .y = -1.6
135  },
136  .screen_size = {
137  .x = 1920,
138  .y = 1080
139  }
140 };
141 
143  : theta(0.0)
144  , psi(0.0)
145 {
146 }
147 
148 SphericalCoordinate::SphericalCoordinate(const double theta, const double psi)
149  : theta(theta)
150  , psi(psi)
151 {
152 }
153 
155 {
156  return {
157  .theta = theta + rhs.theta,
158  .psi = psi + rhs.psi
159  };
160 }
161 
163 {
164  theta += rhs.theta;
165  psi += rhs.psi;
166  return *this;
167 }
168 
169 const SphericalCoordinate SphericalCoordinate::CENTER(0.45 * M_PI, 1.55);
170 
172 {
173  const double x = 40.0 / 3.0;
174  const double y = 7.5;
175  const double s = 10.8 / 7.5;
176  double px1 = 898.62;
177  double py1 = 182.37;
178 
179  const auto &p1 = P1_CACHE.getOrCompute(static_params, [](const TransformStaticParameters &static_params) {
180  const static SphericalCoordinate p1_params(M_PI / 6.0, M_PI);
181  return sphere2Plane(static_params, p1_params);
182  });
183 
184  const auto &p2 = P2_CACHE.getOrCompute(static_params, [](const TransformStaticParameters &static_params) {
185  const static SphericalCoordinate p2_params(M_PI / 2.0, M_PI * 2.0 / 3.0);
186  return sphere2Plane(static_params, p2_params);
187  });
188 
189  const auto p = sphere2Plane(static_params, coord);
190  Vector2<double> a(-159.78000000000009 / (p1.x - p2.x), -248.13 / (p1.y - p2.y));
191 
192  return Vector2<double>(
193  s * (a.x * p.x + (px1 - a.x * p1.x)) + static_params.delta.x * static_params.screen_size.x / x,
194  s * (a.y * p.y + (py1 - a.y * p1.y)) + static_params.delta.y * static_params.screen_size.y / y
195  );
196 }
197 
199 {
200  const std::size_t lookup_table_size = static_params.screen_size.x * static_params.screen_size.y * 3;
201  float *const lookup_table = new float[lookup_table_size];
202  for (std::size_t i = 0; i < lookup_table_size; ++i)
203  {
204 
205  }
206  const double theta_range = max.theta - min.theta;
207  const double psi_range = max.psi - min.psi;
208 
209  const auto generate_range = [&](const std::size_t begin_y, const std::size_t end_y) {
210  for (std::size_t y = begin_y; y < end_y; ++y)
211  {
212  for (std::size_t x = 0; x < size.x; ++x)
213  {
214  const double frac_x = static_cast<double>(x) / size.x;
215  const double frac_y = static_cast<double>(y) / size.y;
216 
217  const auto t = transform(static_params, SphericalCoordinate(
218  min.theta + frac_y * theta_range,
219  min.psi + frac_x * psi_range
220  ));
221 
222  const std::size_t t_x = t.x;
223  const std::size_t t_y = t.y;
224 
225  const auto tx = clamp<std::size_t>(0, t_x, static_params.screen_size.x - 1);
226  const auto ty = clamp<std::size_t>(0, t_y, static_params.screen_size.y - 1);
227 
228  if ((tx != t_x || ty != t_y))
229  {
230  // std::cout << "clamped " << y << ", " << x <<
231  }
232 
233  const std::size_t index = (ty * static_params.screen_size.x + tx) * 3;
234 
235  lookup_table[index + 0] = frac_x;
236  lookup_table[index + 1] = frac_y;
237 
238  // Marker for pixel validity.
239  lookup_table[index + 2] = 1.0;
240  }
241  }
242  };
243 
244  const std::uint32_t num_threads = std::thread::hardware_concurrency();
245 
246  std::vector<std::thread> threads;
247 
248  for (std::uint32_t i = 0; i < num_threads; ++i)
249  {
250  const std::size_t begin_y = (size.y / num_threads) * i;
251  const std::size_t end_y = std::min((size.y / num_threads) * (i + 1), size.y);
252  threads.emplace_back(std::bind(generate_range, begin_y, end_y));
253  }
254 
255  for (auto &thread : threads) {
256  thread.join();
257  }
258 
259  return lookup_table;
260 }
quori_face::TransformStaticParameters::r_m
double r_m
Definition: transform.hpp:25
clamp
GLenum clamp
Definition: glcorearb.h:1226
index
GLuint index
Definition: glcorearb.h:762
quori_face::Vector2< double >
min
int min(int a, int b)
quori_face::Cache
A simple memoization object that eliminates repetitive computations.
Definition: Cache.hpp:20
size
GLsizeiptr size
Definition: glcorearb.h:640
y
GLint y
Definition: glcorearb.h:251
quori_face::TransformStaticParameters::DEFAULT
static const TransformStaticParameters DEFAULT
Definition: transform.hpp:57
Cache.hpp
quori_face::TransformStaticParameters::epsilon
double epsilon
Definition: transform.hpp:45
s
XmlRpcServer s
quori_face::SphericalCoordinate::SphericalCoordinate
SphericalCoordinate()
Definition: transform.cpp:142
quori_face::TransformStaticParameters::delta
Vector2< double > delta
Definition: transform.hpp:50
quori_face::Vector2::x
T x
Definition: Vector2.hpp:37
coord
GLenum coord
Definition: glcorearb.h:4096
del
ROSCPP_DECL bool del(const std::string &key)
value
GLsizei const GLfloat * value
Definition: glcorearb.h:800
quori_face::Vector2::y
T y
Definition: Vector2.hpp:38
quori_face::generateLookupTable
float * generateLookupTable(const TransformStaticParameters &static_params, const SphericalCoordinate &min, const SphericalCoordinate &max, const Vector2< std::uint32_t > &size)
Definition: transform.cpp:198
quori_face
Definition: Cache.hpp:9
quori_face::SphericalCoordinate::operator+
SphericalCoordinate operator+(const SphericalCoordinate &rhs) const
Definition: transform.cpp:154
quori_face::SphericalCoordinate::theta
double theta
Definition: transform.hpp:76
quori_face::SphericalCoordinate::CENTER
static const SphericalCoordinate CENTER
Definition: transform.hpp:86
params
GLenum const GLfloat * params
Definition: glcorearb.h:253
d
d
quori_face::SphericalCoordinate::operator+=
SphericalCoordinate & operator+=(const SphericalCoordinate &rhs)
Definition: transform.cpp:162
quori_face::SphericalCoordinate
Definition: transform.hpp:68
m
const GLfloat * m
Definition: glcorearb.h:4053
quori_face::TransformStaticParameters::operator==
bool operator==(const TransformStaticParameters &other) const
Definition: transform.cpp:97
quori_face::TransformStaticParameters::screen_size
Vector2< std::uint32_t > screen_size
Definition: transform.hpp:55
transform.hpp
x
GLint GLenum GLint x
Definition: glcorearb.h:384
quori_face::TransformStaticParameters::operator!=
bool operator!=(const TransformStaticParameters &other) const
Definition: transform.cpp:111
quori_face::TransformStaticParameters::h
double h
Definition: transform.hpp:35
quori_face::TransformStaticParameters::L
double L
Definition: transform.hpp:40
quori_face::SphericalCoordinate::psi
double psi
Definition: transform.hpp:81
quori_face::TransformStaticParameters
Definition: transform.hpp:15
quori_face::TransformStaticParameters::r_o
double r_o
Definition: transform.hpp:30
quori_face::TransformStaticParameters::R
double R
Definition: transform.hpp:20
quori_face::transform
Vector2< double > transform(const TransformStaticParameters &static_params, const SphericalCoordinate &coord)
Definition: transform.cpp:171
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1214
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:1957


quori_face
Author(s):
autogenerated on Wed Mar 2 2022 00:53:20