PyPO User Manual
 
Loading...
Searching...
No Matches
RayTrace.h
Go to the documentation of this file.
1#include <iostream>
2#include <vector>
3#include <array>
4#include <cmath>
5#include <thread>
6
7#include "Utils.h"
8#include "Structs.h"
9#include "RTRefls.h"
10
11#define _USE_MATH_DEFINES
12
13#ifndef __RayTracer_h
14#define __RayTracer_h
15
16/*! \file RayTrace.h
17 \brief Functions for RT calculations on CPU.
18
19 Provides functions for performing PO calculations on the CPU.
20*/
21
22/**
23 * Ray-trace class.
24 *
25 * Contains methods for performing ray-traces between arbitrarily oriented and curved surfaces.
26 *
27 * @see Utils
28 * @see RTRefls
29 */
30template<class T, class U, class V>
32{
33 int numThreads;
34 int step;
35 int nTot;
36
37 V epsilon;
38
39 void joinThreads();
40
41public:
42 Utils<V> ut; /**<Utils object.*/
43 std::vector<std::thread> threadPool; /**<Vector of thread object.*/
44
45 RayTracer(int numThreads, int nTot, V epsilon, bool verbose = false);
46
47 void transfRays(T ctp, U *fr, bool inv = false);
48
49 void propagateRaysToTarget(int start, int stop,
50 T ctp, U *fr_in, U *fr_out, V t0);
51
52 void parallelRays(T ctp, U *fr_in, U *fr_out, V t0);
53};
54
55/**
56 * Constructor.
57 *
58 * Set internal parameters for ray-tracing.
59 *
60 * @param numThreads Number of computing threads to employ.
61 * @param nTot Total amount of rays in beam.
62 * @param epsilon Precision of NR method, double/float.
63 * @param verbose Whether or not to print internal state information upon construction.
64 */
65template<class T, class U, class V>
66RayTracer<T, U, V>::RayTracer(int numThreads, int nTot, V epsilon, bool verbose)
67{
68 this->numThreads = numThreads;
69 this->step = ceil(nTot / numThreads);
70 this->nTot = nTot;
71 this->threadPool.resize(numThreads);
72 this->epsilon = epsilon;
73}
74
75/**
76 * Transform to surface.
77 *
78 * Transform ray-trace frame into target surface restframe, using target surface transformation matrix.
79 *
80 * @param ctp reflparams or reflparamsf of target surface.
81 * @param fr Pointer to cframe or cframef object to be transformed.
82 * @param inv Whether or not to apply the inverse of the transformation matrix.
83 *
84 * @see reflparams
85 * @see reflparamsf
86 * @see cframe
87 * @see cframef
88 */
89template<class T, class U, class V>
90void RayTracer<T, U, V>::transfRays(T ctp, U *fr, bool inv)
91{
92 bool vec = true;
93 std::array<V, 3> inp, out;
94 for (int i=0; i<fr->size; i++)
95 {
96 inp[0] = fr->x[i];
97 inp[1] = fr->y[i];
98 inp[2] = fr->z[i];
99
100 if (inv) {ut.invmatVec4(ctp.transf, inp, out);}
101 else {ut.matVec4(ctp.transf, inp, out);}
102
103 fr->x[i] = out[0];
104 fr->y[i] = out[1];
105 fr->z[i] = out[2];
106
107 inp[0] = fr->dx[i];
108 inp[1] = fr->dy[i];
109 inp[2] = fr->dz[i];
110
111 if (inv) {ut.invmatVec4(ctp.transf, inp, out, vec);}
112 else {ut.matVec4(ctp.transf, inp, out, vec);}
113
114 fr->dx[i] = out[0];
115 fr->dy[i] = out[1];
116 fr->dz[i] = out[2];
117 }
118}
119
120/**
121 * Propagate rays to target.
122 *
123 * Propagate a frame of rays to a target surface.
124 *
125 * @param start Index of first loop iteration in parallel block.
126 * @param stop Index of last loop iteration in parallel block.
127 * @param ctp reflparams or reflparamsf object containing target surface parameters.
128 * @param fr_in Pointer to input cframe or cframef object.
129 * @param fr_out Pointer to output cframe or cframef object.
130 * @param t0 Starting guess for NR method, double/float.
131 *
132 * @see reflparams
133 * @see reflparamsf
134 * @see cframe
135 * @see cframef
136 */
137template<class T, class U, class V>
139 T ctp, U *fr_in, U *fr_out, V t0)
140{
141 int flip = 1;
142
143 if (ctp.flip)
144 {
145 flip = -1;
146 }
147
148 V (*refl_func_ptr)(V, V, V, V, V, V, V, V, V, V);
149 std::array<V, 3> (*refl_norm_ptr)(V, V, V, int, V, V, V);
150
151 if (ctp.type == 0)
152 {
153 refl_func_ptr = &RTRefls<V>::gp;
154 refl_norm_ptr = &RTRefls<V>::np;
155 }
156
157 if (ctp.type == 1)
158 {
159 refl_func_ptr = &RTRefls<V>::gh;
160 refl_norm_ptr = &RTRefls<V>::nh;
161 }
162
163 else if (ctp.type == 2)
164 {
165 refl_func_ptr = &RTRefls<V>::ge;
166 refl_norm_ptr = &RTRefls<V>::ne;
167 }
168
169 else if (ctp.type == 3)
170 {
171 refl_func_ptr = &RTRefls<V>::gpl;
172 refl_norm_ptr = &RTRefls<V>::npl;
173 }
174
175 std::array<V, 3> direct; // Store incoming ray
176 std::array<V, 3> out; // Store reflected/refracted ray
177
178 for (int i=start; i<stop; i++)
179 {
180 V _t = t0;
181 V t1 = 1e99;
182
183 V check = fabs(t1 - _t);
184 std::array<V, 3> norms;
185
186 V x = fr_in->x[i];
187 V y = fr_in->y[i];
188 V z = fr_in->z[i];
189
190 V dx = fr_in->dx[i];
191 V dy = fr_in->dy[i];
192 V dz = fr_in->dz[i];
193
194 direct = {dx, dy, dz};
195
196 while (check > epsilon)
197 {
198 t1 = refl_func_ptr(_t, x, y, z, dx, dy, dz, ctp.coeffs[0], ctp.coeffs[1], ctp.coeffs[2]);
199
200 check = fabs(t1 - _t);
201
202 _t = t1;
203 }
204
205 if ((abs(round(dx)) == 0 && abs(round(dy)) == 0 && abs(round(dz)) == 0) || std::isnan(_t))
206 {
207 fr_out->x[i] = x;
208 fr_out->y[i] = y;
209 fr_out->z[i] = z;
210
211 fr_out->dx[i] = 0; // Set at 2: since beta should be normalized, can select on 2
212 fr_out->dy[i] = 0;
213 fr_out->dz[i] = 0;
214 }
215
216 else
217 {
218 fr_out->x[i] = x + _t*dx;
219 fr_out->y[i] = y + _t*dy;
220 fr_out->z[i] = z + _t*dz;
221
222 norms = refl_norm_ptr(fr_out->x[i], fr_out->y[i], fr_out->z[i], flip, ctp.coeffs[0], ctp.coeffs[1], ctp.coeffs[2]);
223 check = (dx*norms[0] + dy*norms[1] + dz*norms[2]);
224
225 ut.snell(direct, norms, out);
226
227 fr_out->dx[i] = out[0];
228 fr_out->dy[i] = out[1];
229 fr_out->dz[i] = out[2];
230 }
231 }
232}
233
234/**
235 * Run ray-trace in parallel.
236 *
237 * Run a parallel ray-trace, depending on the type of target surface.
238 *
239 * @param ctp reflparams or reflparamsf object containing target surface parameters.
240 * @param fr_in Pointer to input cframe or cframef object.
241 * @param fr_out Pointer to output cframe or cframef object.
242 * @param t0 Starting guess for NR method, double/float.
243 *
244 * @see reflparams
245 * @see reflparamsf
246 * @see cframe
247 * @see cframef
248 */
249template <class T, class U, class V>
250void RayTracer<T, U, V>::parallelRays(T ctp, U *fr_in, U *fr_out, V t0)
251{
252 int final_step;
253
254 // Transform to reflector rest frame
255 bool inv = true;
256 transfRays(ctp, fr_in, inv);
257
258 for(int n=0; n<numThreads; n++)
259 {
260 if(n == (numThreads-1)) {final_step = nTot;}
261 else {final_step = (n+1) * step;}
262
263 threadPool[n] = std::thread(&RayTracer::propagateRaysToTarget,
264 this, n * step, final_step,
265 ctp, fr_in, fr_out, t0);
266 }
267 joinThreads();
268
269 // Transform back to real frame
270 transfRays(ctp, fr_in);
271 transfRays(ctp, fr_out);
272}
273
274template <class T, class U, class V>
276{
277 for (std::thread &t : threadPool) {if (t.joinable()) {t.join();}}
278}
279#endif
__device__ __inline__ void abs(float(&v)[3], float &out)
Definition GUtils.h:195
__device__ __inline__ void transfRays(float *x, float *y, float *z, float *dx, float *dy, float *dz, int i, bool inv=false)
Definition KernelsRTf.cu:209
Simple reflector definitions used for PyPO ray-tracer.
Structs used within PyPO.
Linear algebra functions for the CPU version of PyPO.
Definition RTRefls.h:20
Definition RayTrace.h:32
std::vector< std::thread > threadPool
Definition RayTrace.h:43
Utils< V > ut
Definition RayTrace.h:42
void parallelRays(T ctp, U *fr_in, U *fr_out, V t0)
Definition RayTrace.h:250
void transfRays(T ctp, U *fr, bool inv=false)
Definition RayTrace.h:90
void propagateRaysToTarget(int start, int stop, T ctp, U *fr_in, U *fr_out, V t0)
Definition RayTrace.h:138
RayTracer(int numThreads, int nTot, V epsilon, bool verbose=false)
Definition RayTrace.h:66
Definition Utils.h:23