Commit 5eeaf94149e3255107b2bc3f48446c88acfbdf65

Authored by Pavel Govyadinov
2 parents 84583942 487a9b49

changer to the base stim/math/*, stim/grid/* and /stim/gl/* classes in order to …

…allow the new vector to function. Added general convenience push methods to the mathvec class, as well as changed a convenience constructor to a size constructor, many small fixes
@@ -67,8 +67,8 @@ void get_diff (float *result) @@ -67,8 +67,8 @@ void get_diff (float *result)
67 67
68 float valIn = tex2D(texIn, x, y)/255.0; 68 float valIn = tex2D(texIn, x, y)/255.0;
69 float valTemp = Template(x); 69 float valTemp = Template(x);
70 - //result[idx] = abs(valIn-valTemp);  
71 - result[idx] = abs(valIn); 70 + result[idx] = abs(valIn-valTemp);
  71 + //result[idx] = abs(valIn);
72 } 72 }
73 73
74 74
stim/gl/gl_spider.h
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 #include "stim/gl/gl_texture.h" 10 #include "stim/gl/gl_texture.h"
11 #include "stim/visualization/camera.h" 11 #include "stim/visualization/camera.h"
12 #include "stim/gl/error.h" 12 #include "stim/gl/error.h"
13 -#include "stim/math/vector.h" 13 +#include "stim/math/mathvec.h"
14 #include "stim/math/rect.h" 14 #include "stim/math/rect.h"
15 #include "stim/math/matrix.h" 15 #include "stim/math/matrix.h"
16 #include "stim/cuda/cost.h" 16 #include "stim/cuda/cost.h"
@@ -64,19 +64,22 @@ class gl_spider @@ -64,19 +64,22 @@ class gl_spider
64 findOptimalDirection() 64 findOptimalDirection()
65 { 65 {
66 //genTemplate(dV, 0); 66 //genTemplate(dV, 0);
  67 + cout << "Direction Before: " << d << endl;
67 setMatrix(); 68 setMatrix();
68 glCallList(dList); 69 glCallList(dList);
69 int best = getCost(); 70 int best = getCost();
70 - stim::vec<float, 4> next;  
71 - next[0] = dV[best][0]*S[0]*R[0];  
72 - next[1] = dV[best][1]*S[1]*R[1];  
73 - next[2] = dV[best][2]*S[2]*R[2];  
74 - next[3] = 1; 71 + stim::vec<float> next(
  72 + dV[best][0]*S[0]*R[0],
  73 + dV[best][1]*S[1]*R[1],
  74 + dV[best][2]*S[2]*R[2],
  75 + 1);
  76 + //next = (cT*next).norm();
75 next = (cT*next).norm(); 77 next = (cT*next).norm();
76 setPosition( p[0]+next[0]*m[0]/stepsize, 78 setPosition( p[0]+next[0]*m[0]/stepsize,
77 p[1]+next[1]*m[0]/stepsize, 79 p[1]+next[1]*m[0]/stepsize,
78 p[2]+next[2]*m[0]/stepsize); 80 p[2]+next[2]*m[0]/stepsize);
79 setDirection(next[0], next[1], next[2]); 81 setDirection(next[0], next[1], next[2]);
  82 + cout << "Direction After: " << d << endl;
80 } 83 }
81 84
82 /// Method for finding the best d for the spider. 85 /// Method for finding the best d for the spider.
@@ -88,16 +91,16 @@ class gl_spider @@ -88,16 +91,16 @@ class gl_spider
88 setMatrix(); 91 setMatrix();
89 glCallList(dList+1); 92 glCallList(dList+1);
90 int best = getCost(); 93 int best = getCost();
91 - stim::vec<float, 4> next;  
92 - next[0] = pV[best][0];  
93 - next[1] = pV[best][1];  
94 - next[2] = pV[best][2];  
95 - next[3] = 1; 94 + stim::vec<float> next(
  95 + pV[best][0],
  96 + pV[best][1],
  97 + pV[best][2],
  98 + 1);
96 next = cT*next; 99 next = cT*next;
97 - std::cout << "Optimal p:"<< next << std::endl;  
98 setPosition( next[0]*S[0]*R[0], 100 setPosition( next[0]*S[0]*R[0],
99 next[1]*S[1]*R[1], 101 next[1]*S[1]*R[1],
100 next[2]*S[2]*R[2]); 102 next[2]*S[2]*R[2]);
  103 + std::cout << "Optimal p:"<< p << std::endl;
101 } 104 }
102 105
103 /// Method for finding the best scale for the spider. 106 /// Method for finding the best scale for the spider.
@@ -109,11 +112,11 @@ class gl_spider @@ -109,11 +112,11 @@ class gl_spider
109 setMatrix(); 112 setMatrix();
110 glCallList(dList+2); 113 glCallList(dList+2);
111 int best = getCost(); 114 int best = getCost();
112 - stim::vec<float, 4> next;  
113 - next[0] = mV[best][0]*S[0]*R[0];  
114 - next[1] = mV[best][1]*S[1]*R[1];  
115 - next[2] = mV[best][2]*S[2]*R[2];  
116 - next[3] = 1; 115 + stim::vec<float> next(
  116 + mV[best][0]*S[0]*R[0],
  117 + mV[best][1]*S[1]*R[1],
  118 + mV[best][2]*S[2]*R[2],
  119 + 1);
117 next = cT*next; 120 next = cT*next;
118 std::cout << "Optimal Scale:"<< next << std::endl; 121 std::cout << "Optimal Scale:"<< next << std::endl;
119 setMagnitude(next[0]); 122 setMagnitude(next[0]);
@@ -123,7 +126,7 @@ class gl_spider @@ -123,7 +126,7 @@ class gl_spider
123 branchDetection() 126 branchDetection()
124 { 127 {
125 Bind(); 128 Bind();
126 - positionTemplate(); 129 + setMatrix();
127 glCallList(dList+3); 130 glCallList(dList+3);
128 131
129 int best = getCost(); 132 int best = getCost();
@@ -151,16 +154,17 @@ class gl_spider @@ -151,16 +154,17 @@ class gl_spider
151 void 154 void
152 genDirectionVectors(float solidAngle = M_PI) 155 genDirectionVectors(float solidAngle = M_PI)
153 { 156 {
  157 + //ofstream file;
  158 + //file.open("dvectors.txt");
154 //Set up the vectors necessary for Rectangle creation. 159 //Set up the vectors necessary for Rectangle creation.
155 vec<float> Y(1.0,0.0,0.0); 160 vec<float> Y(1.0,0.0,0.0);
156 vec<float> pos(0.0,0.0,0.0); 161 vec<float> pos(0.0,0.0,0.0);
157 vec<float> mag(1.0, 1.0, 1.0); 162 vec<float> mag(1.0, 1.0, 1.0);
158 vec<float> dir(0.0, 0.0, 1.0); 163 vec<float> dir(0.0, 0.0, 1.0);
159 164
160 - vec<float> d_s = direction.cart2sph().norm();  
161 //Set up the variable necessary for vector creation. 165 //Set up the variable necessary for vector creation.
162 vec<float> d_s = d.cart2sph().norm(); 166 vec<float> d_s = d.cart2sph().norm();
163 - vec<float> temp; 167 + vec<float> temp(0,0,0);
164 int dim = (sqrt(numSamples)-1)/2; 168 int dim = (sqrt(numSamples)-1)/2;
165 float p0 = -M_PI; 169 float p0 = -M_PI;
166 float dt = solidAngle/(2.0 * ((float)dim + 1.0)); 170 float dt = solidAngle/(2.0 * ((float)dim + 1.0));
@@ -171,7 +175,7 @@ class gl_spider @@ -171,7 +175,7 @@ class gl_spider
171 int idx = 0; 175 int idx = 0;
172 for(int i = -dim; i <= dim; i++){ 176 for(int i = -dim; i <= dim; i++){
173 for(int j = -dim; j <= dim; j++){ 177 for(int j = -dim; j <= dim; j++){
174 - 178 +
175 //Create linear index 179 //Create linear index
176 idx = (j+dim)+(i+dim)*((dim*2)+1); 180 idx = (j+dim)+(i+dim)*((dim*2)+1);
177 temp[0] = d_s[0]; //rotate vector 181 temp[0] = d_s[0]; //rotate vector
@@ -179,6 +183,7 @@ class gl_spider @@ -179,6 +183,7 @@ class gl_spider
179 temp[2] = d_s[2]+dt*(float) j; 183 temp[2] = d_s[2]+dt*(float) j;
180 184
181 temp = (temp.sph2cart()).norm(); //back to cart 185 temp = (temp.sph2cart()).norm(); //back to cart
  186 + // file << temp[0] << "," << temp[1] << "," << temp[2] << endl;
182 dV.push_back(temp); 187 dV.push_back(temp);
183 if(cos(Y.dot(temp))< 0.087){ Y[0] = 0.0; Y[1] = 1.0;} 188 if(cos(Y.dot(temp))< 0.087){ Y[0] = 0.0; Y[1] = 1.0;}
184 else{Y[0] = 1.0; Y[1] = 0.0;} 189 else{Y[0] = 1.0; Y[1] = 0.0;}
@@ -202,6 +207,8 @@ class gl_spider @@ -202,6 +207,8 @@ class gl_spider
202 void 207 void
203 genPositionVectors(float delta = 0.2) 208 genPositionVectors(float delta = 0.2)
204 { 209 {
  210 + ofstream file;
  211 + file.open("pvectors.txt");
205 //Set up the vectors necessary for Rectangle creation. 212 //Set up the vectors necessary for Rectangle creation.
206 vec<float> Y(1.0,0.0,0.0); 213 vec<float> Y(1.0,0.0,0.0);
207 vec<float> pos(0.0,0.0,0.0); 214 vec<float> pos(0.0,0.0,0.0);
@@ -209,10 +216,11 @@ class gl_spider @@ -209,10 +216,11 @@ class gl_spider
209 vec<float> dir(0.0, 0.0, 1.0); 216 vec<float> dir(0.0, 0.0, 1.0);
210 217
211 //Set up the variable necessary for vector creation. 218 //Set up the variable necessary for vector creation.
212 - vec<float> temp; 219 + vec<float> temp(0,0,0);
213 int dim = (sqrt(numSamples)-1)/2; 220 int dim = (sqrt(numSamples)-1)/2;
214 stim::rect<float> samplingPlane = 221 stim::rect<float> samplingPlane =
215 - stim::rect<float>(m[0]*delta, p, d); 222 + stim::rect<float>(p, d);
  223 + samplingPlane.scale(m[0]*delta, m[0]*delta);
216 float step = 1.0/(dim); 224 float step = 1.0/(dim);
217 225
218 //Loop over the samples, keeping the original p sample 226 //Loop over the samples, keeping the original p sample
@@ -228,6 +236,7 @@ class gl_spider @@ -228,6 +236,7 @@ class gl_spider
228 0.5+step*i, 236 0.5+step*i,
229 0.5+step*j 237 0.5+step*j
230 ); 238 );
  239 + file << temp[0] << "," << temp[1] << "," << temp[2] << endl;
231 pV.push_back(temp); 240 pV.push_back(temp);
232 hor = stim::rect<float>(mag, 241 hor = stim::rect<float>(mag,
233 temp, dir, 242 temp, dir,
@@ -262,7 +271,7 @@ class gl_spider @@ -262,7 +271,7 @@ class gl_spider
262 float max = 1.0+delta; 271 float max = 1.0+delta;
263 float step = (max-min)/(numSamples-1); 272 float step = (max-min)/(numSamples-1);
264 float factor; 273 float factor;
265 - vec<float> temp; 274 + vec<float> temp(0.0,0.0,0.0);
266 275
267 glNewList(dList+2, GL_COMPILE); 276 glNewList(dList+2, GL_COMPILE);
268 for(int i = 0; i < numSamples; i++){ 277 for(int i = 0; i < numSamples; i++){
@@ -284,7 +293,6 @@ class gl_spider @@ -284,7 +293,6 @@ class gl_spider
284 } 293 }
285 ///@param v_x x-coordinate in buffer-space, 294 ///@param v_x x-coordinate in buffer-space,
286 ///@param v_y y-coordinate in buffer-space. 295 ///@param v_y y-coordinate in buffer-space.
287 - ilVertex2f(0.0, j*10.0);  
288 ///Samples the texturespace and places a sample in the provided coordinates 296 ///Samples the texturespace and places a sample in the provided coordinates
289 ///of bufferspace. 297 ///of bufferspace.
290 void 298 void
@@ -434,7 +442,7 @@ class gl_spider @@ -434,7 +442,7 @@ class gl_spider
434 ///Based on the p of the spider in real space (arbitrary). 442 ///Based on the p of the spider in real space (arbitrary).
435 void setMatrix() 443 void setMatrix()
436 { 444 {
437 - stim::vec<float, 4> rot = getRotation(d); 445 + stim::vec<float> rot = getRotation(d);
438 glMatrixMode(GL_TEXTURE); 446 glMatrixMode(GL_TEXTURE);
439 glLoadIdentity(); 447 glLoadIdentity();
440 448
@@ -514,20 +522,30 @@ class gl_spider @@ -514,20 +522,30 @@ class gl_spider
514 gl_spider 522 gl_spider
515 (int samples = 1089) 523 (int samples = 1089)
516 { 524 {
517 - setPosition(0.0,0.0,0.0);  
518 - setDirection(0.0,0.0,1.0);  
519 - setMagnitude(1.0); 525 + p.push(0.0,0.0,0.0);
  526 + d.push(0.0,0.0,1.0);
  527 + m.push(1.0, 1.0);
  528 + S.push(1.0,1.0,1.0);
  529 + R.push(1.0,1.0,1.0);
  530 + //setPosition(0.0,0.0,0.0);
  531 + //setDirection(0.0,0.0,1.0);
  532 + //setMagnitude(1.0);
520 numSamples = samples; 533 numSamples = samples;
521 } 534 }
522 535
523 ///temporary constructor for convenience, will be removed in further updates. 536 ///temporary constructor for convenience, will be removed in further updates.
524 gl_spider 537 gl_spider
525 (float pos_x, float pos_y, float pos_z, float dir_x, float dir_y, float dir_z, 538 (float pos_x, float pos_y, float pos_z, float dir_x, float dir_y, float dir_z,
526 - float mag_x)  
527 - {  
528 - setPosition(pos_x, pos_y, pos_z);  
529 - setDirection(dir_x, dir_y, dir_z);  
530 - setMagnitude(mag_x); 539 + float mag_x, int numSamples = 1089)
  540 + {
  541 + p.push(pos_x, pos_y, pos_z);
  542 + d.push(dir_x, dir_y, dir_z);
  543 + m.push(mag_x, mag_x);
  544 + S.push(1.0,1.0,1.0);
  545 + R.push(1.0,1.0,1.0);
  546 + //setPosition(pos_x, pos_y, pos_z);
  547 + //setDirection(dir_x, dir_y, dir_z);
  548 + //setMagnitude(mag_x);
531 549
532 } 550 }
533 551
@@ -551,7 +569,7 @@ class gl_spider @@ -551,7 +569,7 @@ class gl_spider
551 GenerateFBO(20, numSamples*10); 569 GenerateFBO(20, numSamples*10);
552 setDims(0.6, 0.6, 1.0); 570 setDims(0.6, 0.6, 1.0);
553 setSize(512.0, 512.0, 426.0); 571 setSize(512.0, 512.0, 426.0);
554 - 572 + setMatrix();
555 dList = glGenLists(3); 573 dList = glGenLists(3);
556 glListBase(dList); 574 glListBase(dList);
557 Bind(); 575 Bind();
@@ -664,10 +682,10 @@ class gl_spider @@ -664,10 +682,10 @@ class gl_spider
664 ///@param dir, the vector to which we are rotating 682 ///@param dir, the vector to which we are rotating
665 ///given a vector to align to, finds the required 683 ///given a vector to align to, finds the required
666 ///axis and angle for glRotatef 684 ///axis and angle for glRotatef
667 - stim::vec<float, 4> 685 + stim::vec<float>
668 getRotation(stim::vec<float> dir) 686 getRotation(stim::vec<float> dir)
669 { 687 {
670 - stim::vec<float, 4> out; 688 + stim::vec<float> out(0,0,0,0);;
671 stim::vec<float> from(0,0,1); 689 stim::vec<float> from(0,0,1);
672 out[0] = acos(from.dot(dir))*M_PI/180; 690 out[0] = acos(from.dot(dir))*M_PI/180;
673 if(out[0] < 0.0001){ 691 if(out[0] < 0.0001){
@@ -718,7 +736,7 @@ class gl_spider @@ -718,7 +736,7 @@ class gl_spider
718 findOptimalDirection(); 736 findOptimalDirection();
719 findOptimalPosition(); 737 findOptimalPosition();
720 findOptimalScale(); 738 findOptimalScale();
721 - branchDetection(); 739 +// branchDetection();
722 Unbind(); 740 Unbind();
723 } 741 }
724 742
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 #include <fstream> 7 #include <fstream>
8 #include <cstdarg> 8 #include <cstdarg>
9 9
10 -#include "../math/vector.h" 10 +#include "../math/mathvec.h"
11 11
12 namespace stim{ 12 namespace stim{
13 13
@@ -20,8 +20,8 @@ class grid{ @@ -20,8 +20,8 @@ class grid{
20 20
21 protected: 21 protected:
22 22
23 - stim::vec<unsigned long, D> R; //elements in each dimension  
24 - stim::vec<float, D> S; 23 + stim::vec<unsigned long> R; //elements in each dimension
  24 + stim::vec<float> S;
25 T* ptr; //pointer to the data (on the GPU or CPU) 25 T* ptr; //pointer to the data (on the GPU or CPU)
26 26
27 ///Return the total number of values in the binary file 27 ///Return the total number of values in the binary file
@@ -56,7 +56,7 @@ public: @@ -56,7 +56,7 @@ public:
56 ///Constructor used to specify the grid size as a vector 56 ///Constructor used to specify the grid size as a vector
57 57
58 /// @param _R is a vector describing the grid resolution 58 /// @param _R is a vector describing the grid resolution
59 - grid( stim::vec<unsigned long, D> _R){ 59 + grid( stim::vec<unsigned long> _R){
60 60
61 //set the grid resolution 61 //set the grid resolution
62 R = _R; 62 R = _R;
@@ -65,7 +65,7 @@ public: @@ -65,7 +65,7 @@ public:
65 } 65 }
66 66
67 void 67 void
68 - setDim(stim::vec<float, D> s) 68 + setDim(stim::vec<float> s)
69 { 69 {
70 S = s; 70 S = s;
71 } 71 }
@@ -106,7 +106,7 @@ public: @@ -106,7 +106,7 @@ public:
106 /// @param filename is the name of the file containing the binary data 106 /// @param filename is the name of the file containing the binary data
107 /// @param S is the size of the binary file along each dimension 107 /// @param S is the size of the binary file along each dimension
108 /// @param header is the size of the header in bytes 108 /// @param header is the size of the header in bytes
109 - void read(std::string filename, stim::vec<unsigned long, D> S, unsigned long header = 0){ 109 + void read(std::string filename, stim::vec<unsigned long> S, unsigned long header = 0){
110 110
111 R = S; //set the sample resolution 111 R = S; //set the sample resolution
112 112
@@ -177,7 +177,7 @@ public: @@ -177,7 +177,7 @@ public:
177 result<<"]"<<std::endl; 177 result<<"]"<<std::endl;
178 178
179 //calculate the number of values to output 179 //calculate the number of values to output
180 - unsigned long nV = min(R[0], (unsigned long)10); 180 + unsigned long nV = min((unsigned long long)R[0], (unsigned long long)10);
181 181
182 for(unsigned long v = 0; v<nV; v++){ 182 for(unsigned long v = 0; v<nV; v++){
183 result<<ptr[v]; 183 result<<ptr[v];
stim/grids/image_stack.h
@@ -51,10 +51,10 @@ public: @@ -51,10 +51,10 @@ public:
51 stim::image<T> I(file_list[0].str()); 51 stim::image<T> I(file_list[0].str());
52 52
53 //set the image resolution and number of channels 53 //set the image resolution and number of channels
54 - R[0] = I.channels();  
55 - R[1] = I.width();  
56 - R[2] = I.height();  
57 - R[3] = file_list.size(); 54 + R.push(I.channels());
  55 + R.push(I.width());
  56 + R.push(I.height());
  57 + R.push(file_list.size());
58 58
59 //allocate storage space 59 //allocate storage space
60 ptr = (T*)malloc(sizeof(T) * samples()); 60 ptr = (T*)malloc(sizeof(T) * samples());
stim/math/mathvec.h 0 → 100644
  1 +#ifndef RTS_VECTOR_H
  2 +#define RTS_VECTOR_H
  3 +
  4 +#include <iostream>
  5 +#include <cmath>
  6 +#include <sstream>
  7 +#include <vector>
  8 +#include "../cuda/callable.h"
  9 +
  10 +namespace stim
  11 +{
  12 +
  13 +
  14 +
  15 +template <class T>
  16 +struct vec : public std::vector<T>
  17 +{
  18 + using std::vector<T>::size;
  19 + using std::vector<T>::at;
  20 + using std::vector<T>::resize;
  21 + using std::vector<T>::push_back;
  22 + vec(){
  23 +
  24 + }
  25 +
  26 +// //efficiency constructors, makes construction easier for 1D-4D vectors
  27 + vec(T rhs)
  28 + {
  29 + resize(1, rhs);
  30 +// cerr << " Created a vector " << endl;
  31 +// //for(int i=0; i<N; i++)
  32 +// // v[i] = rhs;
  33 + }
  34 +
  35 +// vec(int s)
  36 +// {
  37 +// resize(s,0);
  38 +// }
  39 +
  40 + vec(T x, T y)
  41 + {
  42 + push_back(x);
  43 + push_back(y);
  44 + }
  45 + vec(T x, T y, T z)
  46 + {
  47 + push_back(x);
  48 + push_back(y);
  49 + push_back(z);
  50 + }
  51 + vec(T x, T y, T z, T w)
  52 + {
  53 + push_back(x);
  54 + push_back(y);
  55 + push_back(z);
  56 + push_back(w);
  57 + }
  58 +
  59 +
  60 +
  61 + //copy constructor
  62 + vec( const vec<T>& other){
  63 + unsigned int N = other.size();
  64 + for(int i=0; i<N; i++)
  65 + push_back(other[i]);
  66 + }
  67 +
  68 + vec<T> push(T x)
  69 + {
  70 + push_back(x);
  71 + return *this;
  72 + }
  73 +
  74 + vec<T> push(T x, T y)
  75 + {
  76 + push_back(x);
  77 + push_back(y);
  78 + return *this;
  79 + }
  80 + vec<T> push(T x, T y, T z)
  81 + {
  82 + push_back(x);
  83 + push_back(y);
  84 + push_back(z);
  85 + return *this;
  86 + }
  87 + vec<T> push(T x, T y, T z, T w)
  88 + {
  89 + push_back(x);
  90 + push_back(y);
  91 + push_back(z);
  92 + push_back(w);
  93 + return *this;
  94 + }
  95 + template< typename U >
  96 + operator vec<U>(){
  97 + unsigned int N = size();
  98 + vec<U> result;
  99 + for(int i=0; i<N; i++)
  100 + result.push_back(at(i));
  101 +
  102 + return result;
  103 + }
  104 +
  105 + //template<class U>
  106 + //friend vec<U, N>::operator vec<T, N>();
  107 +
  108 + T len() const
  109 + {
  110 + unsigned int N = size();
  111 +
  112 + //compute and return the vector length
  113 + T sum_sq = (T)0;
  114 + for(int i=0; i<N; i++)
  115 + {
  116 + sum_sq += pow( at(i), 2 );
  117 + }
  118 + return sqrt(sum_sq);
  119 +
  120 + }
  121 +
  122 + vec<T> cart2sph() const
  123 + {
  124 + //convert the vector from cartesian to spherical coordinates
  125 + //x, y, z -> r, theta, phi (where theta = 0 to 2*pi)
  126 +
  127 + vec<T> sph;
  128 + sph.push_back(std::sqrt(at(0)*at(0) + at(1)*at(1) + at(2)*at(2)));
  129 + sph.push_back(std::atan2(at(1), at(0)));
  130 +
  131 + if(sph[0] == 0)
  132 + sph.push_back(0);
  133 + else
  134 + sph.push_back(std::acos(at(2) / sph[0]));
  135 +
  136 + return sph;
  137 + }
  138 +
  139 + vec<T> sph2cart() const
  140 + {
  141 + //convert the vector from cartesian to spherical coordinates
  142 + //r, theta, phi -> x, y, z (where theta = 0 to 2*pi)
  143 +
  144 + vec<T> cart;
  145 + cart.push_back(at(0) * std::cos(at(1)) * std::sin(at(2)));
  146 + cart.push_back(at(0) * std::sin(at(1)) * std::sin(at(2)));
  147 + cart.push_back(at(0) * std::cos(at(2)));
  148 +
  149 + return cart;
  150 + }
  151 +
  152 + vec<T> norm() const
  153 + {
  154 + unsigned int N = size();
  155 +
  156 + //compute and return the unit vector
  157 + vec<T> result;
  158 +
  159 + //compute the vector length
  160 + T l = len();
  161 +
  162 + //normalize
  163 + for(int i=0; i<N; i++)
  164 + {
  165 + result.push_back(at(i) / l);
  166 + }
  167 +
  168 + return result;
  169 + }
  170 +
  171 + vec<T> cross(const vec<T> rhs) const
  172 + {
  173 + vec<T> result;
  174 +
  175 + //compute the cross product (only valid for 3D vectors)
  176 + result.push_back(at(1) * rhs[2] - at(2) * rhs[1]);
  177 + result.push_back(at(2) * rhs[0] - at(0) * rhs[2]);
  178 + result.push_back(at(0) * rhs[1] - at(1) * rhs[0]);
  179 +
  180 + return result;
  181 + }
  182 +
  183 + T dot(vec<T> rhs) const
  184 + {
  185 + T result = (T)0;
  186 + unsigned int N = size();
  187 + for(int i=0; i<N; i++)
  188 + result += at(i) * rhs[i];
  189 +
  190 + return result;
  191 +
  192 + }
  193 +
  194 + //arithmetic
  195 + vec<T> operator+(vec<T> rhs) const
  196 + {
  197 + vec<T> result;
  198 +
  199 + unsigned int N = size();
  200 + for(int i=0; i<N; i++)
  201 + result.push_back(at(i) + rhs[i]);
  202 +
  203 + return result;
  204 + }
  205 + vec<T> operator+(T rhs) const
  206 + {
  207 + vec<T> result;
  208 + unsigned int N = size();
  209 + for(int i=0; i<N; i++)
  210 + result.push_back(at(i) + rhs);
  211 +
  212 + return result;
  213 + }
  214 + vec<T> operator-(vec<T> rhs) const
  215 + {
  216 + vec<T> result;
  217 +
  218 + unsigned int N = size();
  219 + for(int i=0; i<N; i++)
  220 + result.push_back(at(i) - rhs[i]);
  221 +
  222 + return result;
  223 + }
  224 + vec<T> operator*(T rhs) const
  225 + {
  226 + vec<T> result;
  227 +
  228 + unsigned int N = size();
  229 + for(int i=0; i<N; i++)
  230 + result.push_back(at(i) * rhs);
  231 +
  232 + return result;
  233 + }
  234 + vec<T> operator/(T rhs) const
  235 + {
  236 + vec<T> result;
  237 +
  238 + unsigned int N = size();
  239 + for(int i=0; i<N; i++)
  240 + result.push_back(at(i) / rhs);
  241 +
  242 + return result;
  243 + }
  244 + vec<T> operator*=(T rhs){
  245 +
  246 + unsigned int N = size();
  247 + for(int i=0; i<N; i++)
  248 + at(i) = at(i) * rhs;
  249 + return *this;
  250 + }
  251 + vec<T> operator+=(vec<T> rhs){
  252 + unsigned int N = size();
  253 + for(int i=0; i<N; i++)
  254 + at(i) += rhs[i];
  255 + return *this;
  256 + }
  257 + vec<T> & operator=(T rhs){
  258 +
  259 + unsigned int N = size();
  260 + for(int i=0; i<N; i++)
  261 + at(i) = rhs;
  262 + return *this;
  263 + }
  264 +
  265 + template<typename Y>
  266 + vec<T> & operator=(vec<Y> rhs){
  267 + unsigned int N = rhs.size();
  268 + resize(N);
  269 +
  270 + for(int i=0; i<N; i++)
  271 + at(i) = rhs[i];
  272 + return *this;
  273 + }
  274 + //unary minus
  275 + vec<T> operator-() const{
  276 + vec<T> r;
  277 +
  278 + //negate the vector
  279 + unsigned int N = size();
  280 + for(int i=0; i<N; i++)
  281 + r.push_back(-at(i));
  282 +
  283 + return r;
  284 + }
  285 +
  286 +
  287 + std::string str() const
  288 + {
  289 + std::stringstream ss;
  290 +
  291 + unsigned int N = size();
  292 +
  293 + ss<<"[";
  294 + for(int i=0; i<N; i++)
  295 + {
  296 + ss<<at(i);
  297 + if(i != N-1)
  298 + ss<<", ";
  299 + }
  300 + ss<<"]";
  301 +
  302 + return ss.str();
  303 + }
  304 +
  305 +};
  306 +
  307 +
  308 +} //end namespace rts
  309 +
  310 +template <typename T>
  311 +std::ostream& operator<<(std::ostream& os, stim::vec<T> v)
  312 +{
  313 + os<<v.str();
  314 + return os;
  315 +}
  316 +
  317 +
  318 +
  319 +template <typename T>
  320 +stim::vec<T> operator*(T lhs, stim::vec<T> rhs)
  321 +{
  322 + stim::vec<T> r;
  323 +
  324 + return rhs * lhs;
  325 +}
  326 +
  327 +//#if __GNUC__ > 3 && __GNUC_MINOR__ > 7
  328 +//template<class T, int N> using rtsVector = rts::vector<T, N>;
  329 +//#endif
  330 +
  331 +#endif
stim/math/matrix.h
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 //#include "rts/vector.h" 4 //#include "rts/vector.h"
5 #include <string.h> 5 #include <string.h>
6 #include <iostream> 6 #include <iostream>
7 -#include "vector.h" 7 +#include "mathvec.h"
8 #include "../cuda/callable.h" 8 #include "../cuda/callable.h"
9 9
10 namespace stim{ 10 namespace stim{
@@ -52,9 +52,12 @@ struct matrix @@ -52,9 +52,12 @@ struct matrix
52 52
53 53
54 template<typename Y> 54 template<typename Y>
55 - CUDA_CALLABLE vec<Y, N> operator*(vec<Y, N> rhs) 55 + CUDA_CALLABLE vec<Y> operator*(vec<Y> rhs)
56 { 56 {
57 - vec<Y, N> result; 57 + unsigned int N = rhs.size();
  58 +
  59 + vec<Y> result;
  60 + result.resize(N);
58 61
59 for(int r=0; r<N; r++) 62 for(int r=0; r<N; r++)
60 for(int c=0; c<N; c++) 63 for(int c=0; c<N; c++)
stim/math/quaternion.h
@@ -26,13 +26,13 @@ public: @@ -26,13 +26,13 @@ public:
26 26
27 CUDA_CALLABLE void CreateRotation(T theta, T ux, T uy, T uz){ 27 CUDA_CALLABLE void CreateRotation(T theta, T ux, T uy, T uz){
28 28
29 - vec<T, 3> u(ux, uy, uz); 29 + vec<T> u(ux, uy, uz);
30 CreateRotation(theta, u); 30 CreateRotation(theta, u);
31 } 31 }
32 32
33 - CUDA_CALLABLE void CreateRotation(T theta, vec<T, 3> u){ 33 + CUDA_CALLABLE void CreateRotation(T theta, vec<T> u){
34 34
35 - vec<T, 3> u_hat = u.norm(); 35 + vec<T> u_hat = u.norm();
36 36
37 //assign the given Euler rotation to this quaternion 37 //assign the given Euler rotation to this quaternion
38 w = (T)cos(theta/2); 38 w = (T)cos(theta/2);
@@ -41,7 +41,7 @@ public: @@ -41,7 +41,7 @@ public:
41 z = u_hat[2]*(T)sin(theta/2); 41 z = u_hat[2]*(T)sin(theta/2);
42 } 42 }
43 43
44 - CUDA_CALLABLE void CreateRotation(vec<T, 3> from, vec<T, 3> to){ 44 + CUDA_CALLABLE void CreateRotation(vec<T> from, vec<T> to){
45 45
46 vec<T> r = from.cross(to); //compute the rotation vector 46 vec<T> r = from.cross(to); //compute the rotation vector
47 T theta = asin(r.len()); //compute the angle of the rotation about r 47 T theta = asin(r.len()); //compute the angle of the rotation about r
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 //enable CUDA_CALLABLE macro 4 //enable CUDA_CALLABLE macro
5 #include "../cuda/callable.h" 5 #include "../cuda/callable.h"
6 -#include "../math/vector.h" 6 +#include "../math/mathvec.h"
7 #include "../math/triangle.h" 7 #include "../math/triangle.h"
8 #include "../math/quaternion.h" 8 #include "../math/quaternion.h"
9 #include <iostream> 9 #include <iostream>
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 namespace stim{ 13 namespace stim{
14 14
15 //template for a rectangle class in ND space 15 //template for a rectangle class in ND space
16 -template <class T, int N = 3> 16 +template <class T>
17 struct rect 17 struct rect
18 { 18 {
19 /* 19 /*
@@ -28,9 +28,9 @@ struct rect @@ -28,9 +28,9 @@ struct rect
28 28
29 private: 29 private:
30 30
31 - stim::vec<T, N> C;  
32 - stim::vec<T, N> X;  
33 - stim::vec<T, N> Y; 31 + stim::vec<T> C;
  32 + stim::vec<T> X;
  33 + stim::vec<T> Y;
34 34
35 CUDA_CALLABLE void scale(T factor){ 35 CUDA_CALLABLE void scale(T factor){
36 X *= factor; 36 X *= factor;
@@ -38,10 +38,10 @@ private: @@ -38,10 +38,10 @@ private:
38 } 38 }
39 39
40 40
41 - CUDA_CALLABLE void normal(vec<T, N> n){ //orient the rectangle along the specified normal 41 + CUDA_CALLABLE void normal(vec<T> n){ //orient the rectangle along the specified normal
42 42
43 n = n.norm(); //normalize, just in case 43 n = n.norm(); //normalize, just in case
44 - vec<T, N> n_current = X.cross(Y).norm(); //compute the current normal 44 + vec<T> n_current = X.cross(Y).norm(); //compute the current normal
45 quaternion<T> q; //create a quaternion 45 quaternion<T> q; //create a quaternion
46 q.CreateRotation(n_current, n); //initialize a rotation from n_current to n 46 q.CreateRotation(n_current, n); //initialize a rotation from n_current to n
47 47
@@ -51,9 +51,9 @@ private: @@ -51,9 +51,9 @@ private:
51 } 51 }
52 52
53 CUDA_CALLABLE void init(){ 53 CUDA_CALLABLE void init(){
54 - C = vec<T, N>(0, 0, 0);  
55 - X = vec<T, N>(1, 0, 0);  
56 - Y = vec<T, N>(0, 1, 0); 54 + C = vec<T>(0, 0, 0);
  55 + X = vec<T>(1, 0, 0);
  56 + Y = vec<T>(0, 1, 0);
57 } 57 }
58 58
59 public: 59 public:
@@ -69,30 +69,22 @@ public: @@ -69,30 +69,22 @@ public:
69 C[2] = z_pos; 69 C[2] = z_pos;
70 } 70 }
71 71
72 - //create a rectangle from a center point, normal, and size  
73 - CUDA_CALLABLE rect(T size, vec<T, N> c, vec<T, N> n = vec<T, N>(0, 0, 1)){  
74 - init(); //start with the default setting  
75 - C = c;  
76 - scale(size); //scale the rectangle  
77 - normal(n); //orient  
78 - }  
79 72
80 //create a rectangle from a center point, normal, and size 73 //create a rectangle from a center point, normal, and size
81 - CUDA_CALLABLE rect(vec<T,2> size, vec<T, N> c, vec<T, N> n = vec<T, N>(0, 0, 1)){ 74 + CUDA_CALLABLE rect(vec<T> c, vec<T> n = vec<T>(0, 0, 1)){
82 init(); //start with the default setting 75 init(); //start with the default setting
83 C = c; 76 C = c;
84 - scale(size); //scale the rectangle  
85 normal(n); //orient 77 normal(n); //orient
86 } 78 }
87 79
88 - CUDA_CALLABLE rect(vec<T, N> center, vec<T, N> directionX, vec<T, N> directionY ) 80 + CUDA_CALLABLE rect(vec<T> center, vec<T> directionX, vec<T> directionY )
89 { 81 {
90 C = center; 82 C = center;
91 X = directionX; 83 X = directionX;
92 Y = directionY; 84 Y = directionY;
93 } 85 }
94 86
95 - CUDA_CALLABLE rect(T size, vec<T, N> center, vec<T, N> directionX, vec<T, N> directionY ) 87 + CUDA_CALLABLE rect(T size, vec<T> center, vec<T> directionX, vec<T> directionY )
96 { 88 {
97 C = center; 89 C = center;
98 X = directionX; 90 X = directionX;
@@ -100,7 +92,7 @@ public: @@ -100,7 +92,7 @@ public:
100 scale(size); 92 scale(size);
101 } 93 }
102 94
103 - CUDA_CALLABLE rect(vec<T,N> size, vec<T, N> center, vec<T, N> directionX, vec<T, N> directionY ) 95 + CUDA_CALLABLE rect(vec<T> size, vec<T> center, vec<T> directionX, vec<T> directionY )
104 { 96 {
105 C = center; 97 C = center;
106 X = directionX; 98 X = directionX;
@@ -114,7 +106,7 @@ public: @@ -114,7 +106,7 @@ public:
114 } 106 }
115 107
116 //boolean comparison 108 //boolean comparison
117 - bool operator==(const rect<T, N> & rhs) 109 + bool operator==(const rect<T> & rhs)
118 { 110 {
119 if(C == rhs.C && X == rhs.X && Y == rhs.Y) 111 if(C == rhs.C && X == rhs.X && Y == rhs.Y)
120 return true; 112 return true;
@@ -125,24 +117,24 @@ public: @@ -125,24 +117,24 @@ public:
125 /******************************************* 117 /*******************************************
126 Return the normal for the rect 118 Return the normal for the rect
127 *******************************************/ 119 *******************************************/
128 - CUDA_CALLABLE stim::vec<T, N> n() 120 + CUDA_CALLABLE stim::vec<T> n()
129 { 121 {
130 return (X.cross(Y)).norm(); 122 return (X.cross(Y)).norm();
131 } 123 }
132 124
133 //get the world space value given the planar coordinates a, b in [0, 1] 125 //get the world space value given the planar coordinates a, b in [0, 1]
134 - CUDA_CALLABLE stim::vec<T, N> p(T a, T b) 126 + CUDA_CALLABLE stim::vec<T> p(T a, T b)
135 { 127 {
136 - stim::vec<T, N> result; 128 + stim::vec<T> result;
137 //given the two parameters a, b = [0 1], returns the position in world space 129 //given the two parameters a, b = [0 1], returns the position in world space
138 - vec<T, N> A = C - X * (T)0.5 - Y * (T)0.5; 130 + vec<T> A = C - X * (T)0.5 - Y * (T)0.5;
139 result = A + X * a + Y * b; 131 result = A + X * a + Y * b;
140 132
141 return result; 133 return result;
142 } 134 }
143 135
144 //parenthesis operator returns the world space given rectangular coordinates a and b in [0 1] 136 //parenthesis operator returns the world space given rectangular coordinates a and b in [0 1]
145 - CUDA_CALLABLE stim::vec<T, N> operator()(T a, T b) 137 + CUDA_CALLABLE stim::vec<T> operator()(T a, T b)
146 { 138 {
147 return p(a, b); 139 return p(a, b);
148 } 140 }
@@ -150,7 +142,7 @@ public: @@ -150,7 +142,7 @@ public:
150 std::string str() 142 std::string str()
151 { 143 {
152 std::stringstream ss; 144 std::stringstream ss;
153 - vec<T, N> A = C - X * (T)0.5 - Y * (T)0.5; 145 + vec<T> A = C - X * (T)0.5 - Y * (T)0.5;
154 ss<<std::left<<"B="<<std::setfill('-')<<std::setw(20)<<A + Y<<">"<<"C="<<A + Y + X<<std::endl; 146 ss<<std::left<<"B="<<std::setfill('-')<<std::setw(20)<<A + Y<<">"<<"C="<<A + Y + X<<std::endl;
155 ss<<std::setfill(' ')<<std::setw(23)<<"|"<<"|"<<std::endl<<std::setw(23)<<"|"<<"|"<<std::endl; 147 ss<<std::setfill(' ')<<std::setw(23)<<"|"<<"|"<<std::endl<<std::setw(23)<<"|"<<"|"<<std::endl;
156 ss<<std::left<<"A="<<std::setfill('-')<<std::setw(20)<<A<<">"<<"D="<<A + X; 148 ss<<std::left<<"A="<<std::setfill('-')<<std::setw(20)<<A<<">"<<"D="<<A + X;
@@ -160,12 +152,12 @@ public: @@ -160,12 +152,12 @@ public:
160 } 152 }
161 153
162 //scales the rectangle by a value rhs 154 //scales the rectangle by a value rhs
163 - CUDA_CALLABLE rect<T, N> operator*(T rhs) 155 + CUDA_CALLABLE rect<T> operator*(T rhs)
164 { 156 {
165 //scales the plane by a scalar value 157 //scales the plane by a scalar value
166 158
167 //create the new rectangle 159 //create the new rectangle
168 - rect<T, N> result = *this; 160 + rect<T> result = *this;
169 result.scale(rhs); 161 result.scale(rhs);
170 162
171 return result; 163 return result;
@@ -173,15 +165,15 @@ public: @@ -173,15 +165,15 @@ public:
173 } 165 }
174 166
175 //computes the distance between the specified point and this rectangle 167 //computes the distance between the specified point and this rectangle
176 - CUDA_CALLABLE T dist(vec<T, N> p) 168 + CUDA_CALLABLE T dist(vec<T> p)
177 { 169 {
178 //compute the distance between a point and this rect 170 //compute the distance between a point and this rect
179 171
180 - vec<T, N> A = C - X * (T)0.5 - Y * (T)0.5; 172 + vec<T> A = C - X * (T)0.5 - Y * (T)0.5;
181 173
182 //first break the rect up into two triangles 174 //first break the rect up into two triangles
183 - triangle<T, N> T0(A, A+X, A+Y);  
184 - triangle<T, N> T1(A+X+Y, A+X, A+Y); 175 + triangle<T> T0(A, A+X, A+Y);
  176 + triangle<T> T1(A+X+Y, A+X, A+Y);
185 177
186 178
187 T d0 = T0.dist(p); 179 T d0 = T0.dist(p);
@@ -193,9 +185,9 @@ public: @@ -193,9 +185,9 @@ public:
193 return d1; 185 return d1;
194 } 186 }
195 187
196 - CUDA_CALLABLE T dist_max(vec<T, N> p) 188 + CUDA_CALLABLE T dist_max(vec<T> p)
197 { 189 {
198 - vec<T, N> A = C - X * (T)0.5 - Y * (T)0.5; 190 + vec<T> A = C - X * (T)0.5 - Y * (T)0.5;
199 T da = (A - p).len(); 191 T da = (A - p).len();
200 T db = (A+X - p).len(); 192 T db = (A+X - p).len();
201 T dc = (A+Y - p).len(); 193 T dc = (A+Y - p).len();
@@ -208,7 +200,7 @@ public: @@ -208,7 +200,7 @@ public:
208 } //end namespace rts 200 } //end namespace rts
209 201
210 template <typename T, int N> 202 template <typename T, int N>
211 -std::ostream& operator<<(std::ostream& os, stim::rect<T, N> R) 203 +std::ostream& operator<<(std::ostream& os, stim::rect<T> R)
212 { 204 {
213 os<<R.str(); 205 os<<R.str();
214 return os; 206 return os;
stim/math/spharmonics.h 0 → 100644
  1 +#ifndef STIM_SPH_HARMONICS
  2 +#define STIM_SPH_HARMONICS
  3 +
  4 +
  5 +#include <boost/math/special_functions/spherical_harmonic.hpp>
  6 +#include <vector>
  7 +
  8 +#define PI 3.14159
  9 +#define WIRE_SCALE 1.001
  10 +namespace stim{
  11 +
  12 +template<class T>
  13 +class spharmonics{
  14 +
  15 +protected:
  16 +
  17 + std::vector<T> C; //list of SH coefficients
  18 +
  19 + unsigned int mcN; //number of Monte-Carlo samples
  20 +
  21 + //calculate the value of the SH basis function (l, m) at (theta, phi)
  22 + //here, theta = [0, PI], phi = [0, 2*PI]
  23 + double SH(int l, int m, double theta, double phi){
  24 + return boost::math::spherical_harmonic_r(l, m, phi, theta);
  25 + }
  26 +
  27 + unsigned int coeff_1d(unsigned int l, int m){
  28 + return pow(l + 1, 2) - (l - m) - 1;
  29 + }
  30 +
  31 +
  32 +
  33 +
  34 +public:
  35 +
  36 + void push(double c){
  37 + C.push_back(c);
  38 + }
  39 +
  40 + void resize(unsigned int n){
  41 + C.resize(n);
  42 + }
  43 +
  44 + void setc(unsigned int l, int m, T value){
  45 + unsigned int c = coeff_1d(l, m);
  46 + C[c] = value;
  47 + }
  48 +
  49 + void setc(unsigned int c, T value){
  50 + C[c] = value;
  51 + }
  52 +
  53 + /// Initialize Monte-Carlo sampling of a function using N spherical harmonics coefficients
  54 +
  55 + /// @param N is the number of spherical harmonics coefficients used to represent the user function
  56 + void mcBegin(unsigned int coefficients){
  57 + C.resize(coefficients, 0);
  58 + mcN = 0;
  59 + }
  60 +
  61 + void mcBegin(unsigned int l, int m){
  62 + unsigned int c = pow(l + 1, 2) - (l - m);
  63 + mcBegin(c);
  64 + }
  65 +
  66 + void mcSample(double theta, double phi, double val){
  67 +
  68 + int l, m;
  69 + double sh;
  70 +
  71 + l = m = 0;
  72 + for(unsigned int i = 0; i < C.size(); i++){
  73 +
  74 + sh = SH(l, m, theta, phi);
  75 + C[i] += sh * val;
  76 +
  77 + m++; //increment m
  78 +
  79 + //if we're in a new tier, increment l and set m = -l
  80 + if(m > l){
  81 + l++;
  82 + m = -l;
  83 + }
  84 + } //end for all coefficients
  85 +
  86 + //increment the number of samples
  87 + mcN++;
  88 +
  89 + } //end mcSample()
  90 +
  91 + void mcEnd(){
  92 +
  93 + //divide all coefficients by the number of samples
  94 + for(unsigned int i = 0; i < C.size(); i++)
  95 + C[i] /= mcN;
  96 + }
  97 +
  98 + /// Generates a PDF describing the probability distribution of points on a spherical surface
  99 +
  100 + /// @param sph_pts is a list of points in spherical coordinates (theta, phi) where theta = [0, 2pi] and phi = [0, pi]
  101 + /// @param l is the maximum degree of the spherical harmonic function
  102 + /// @param m is the maximum order
  103 + void pdf(std::vector<stim::vec<double>> sph_pts, unsigned int l, int m){
  104 +
  105 + mcBegin( l, m ); //begin spherical harmonic sampling
  106 +
  107 + unsigned int nP = sph_pts.size();
  108 +
  109 + for(unsigned int p = 0; p < nP; p++){
  110 + mcSample(sph_pts[p][1], sph_pts[p][2], 1.0);
  111 + }
  112 +
  113 + mcEnd();
  114 + }
  115 +
  116 + std::string str(){
  117 +
  118 + std::stringstream ss;
  119 +
  120 + int l, m;
  121 + l = m = 0;
  122 + for(unsigned int i = 0; i < C.size(); i++){
  123 +
  124 + ss<<C[i]<<'\t';
  125 +
  126 + m++; //increment m
  127 +
  128 + //if we're in a new tier, increment l and set m = -l
  129 + if(m > l){
  130 + l++;
  131 + m = -l;
  132 +
  133 + ss<<std::endl;
  134 +
  135 + }
  136 + }
  137 +
  138 + return ss.str();
  139 +
  140 +
  141 + }
  142 +
  143 + /// Returns the value of the function at the coordinate (theta, phi)
  144 +
  145 + /// @param theta = [0, 2pi]
  146 + /// @param phi = [0, pi]
  147 + double operator()(double theta, double phi){
  148 +
  149 + double fx = 0;
  150 +
  151 + int l = 0;
  152 + int m = 0;
  153 + for(unsigned int i = 0; i < C.size(); i++){
  154 + fx += C[i] * SH(l, m, theta, phi);
  155 + m++;
  156 + if(m > l){
  157 + l++;
  158 + m = -l;
  159 + }
  160 +
  161 + }
  162 +
  163 + return fx;
  164 + }
  165 +
  166 +}; //end class sph_harmonics
  167 +
  168 +
  169 +
  170 +
  171 +}
  172 +
  173 +
  174 +#endif
stim/math/triangle.h
@@ -3,12 +3,12 @@ @@ -3,12 +3,12 @@
3 3
4 //enable CUDA_CALLABLE macro 4 //enable CUDA_CALLABLE macro
5 #include "../cuda/callable.h" 5 #include "../cuda/callable.h"
6 -#include "../math/vector.h" 6 +#include "../math/mathvec.h"
7 #include <iostream> 7 #include <iostream>
8 8
9 namespace stim{ 9 namespace stim{
10 10
11 -template <class T, int N=3> 11 +template <class T>
12 struct triangle 12 struct triangle
13 { 13 {
14 /* 14 /*
@@ -23,15 +23,15 @@ struct triangle @@ -23,15 +23,15 @@ struct triangle
23 */ 23 */
24 private: 24 private:
25 25
26 - vec<T, N> A;  
27 - vec<T, N> B;  
28 - vec<T, N> C; 26 + vec<T> A;
  27 + vec<T> B;
  28 + vec<T> C;
29 29
30 - CUDA_CALLABLE vec<T, N> _p(T s, T t) 30 + CUDA_CALLABLE vec<T> _p(T s, T t)
31 { 31 {
32 //This function returns the point specified by p = A + s(B-A) + t(C-A) 32 //This function returns the point specified by p = A + s(B-A) + t(C-A)
33 - vec<T, N> E0 = B-A;  
34 - vec<T, N> E1 = C-A; 33 + vec<T> E0 = B-A;
  34 + vec<T> E1 = C-A;
35 35
36 return A + s*E0 + t*E1; 36 return A + s*E0 + t*E1;
37 } 37 }
@@ -46,26 +46,26 @@ struct triangle @@ -46,26 +46,26 @@ struct triangle
46 46
47 } 47 }
48 48
49 - CUDA_CALLABLE triangle(vec<T, N> a, vec<T, N> b, vec<T, N> c) 49 + CUDA_CALLABLE triangle(vec<T> a, vec<T> b, vec<T> c)
50 { 50 {
51 A = a; 51 A = a;
52 B = b; 52 B = b;
53 C = c; 53 C = c;
54 } 54 }
55 55
56 - CUDA_CALLABLE stim::vec<T, N> operator()(T s, T t) 56 + CUDA_CALLABLE stim::vec<T> operator()(T s, T t)
57 { 57 {
58 return _p(s, t); 58 return _p(s, t);
59 } 59 }
60 60
61 - CUDA_CALLABLE vec<T, N> nearest(vec<T, N> p) 61 + CUDA_CALLABLE vec<T> nearest(vec<T> p)
62 { 62 {
63 //comptue the distance between a point and this triangle 63 //comptue the distance between a point and this triangle
64 // This code is adapted from: http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf 64 // This code is adapted from: http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf
65 65
66 - vec<T, N> E0 = B-A;  
67 - vec<T, N> E1 = C-A;  
68 - vec<T, N> D = A - p; 66 + vec<T> E0 = B-A;
  67 + vec<T> E1 = C-A;
  68 + vec<T> D = A - p;
69 69
70 T a = E0.dot(E0); 70 T a = E0.dot(E0);
71 T b = E0.dot(E1); 71 T b = E0.dot(E1);
@@ -175,9 +175,9 @@ struct triangle @@ -175,9 +175,9 @@ struct triangle
175 175
176 } 176 }
177 177
178 - CUDA_CALLABLE T dist(vec<T, N> p) 178 + CUDA_CALLABLE T dist(vec<T> p)
179 { 179 {
180 - vec<T, N> n = nearest(p); 180 + vec<T> n = nearest(p);
181 181
182 return (p - n).len(); 182 return (p - n).len();
183 } 183 }
stim/math/vector.h deleted
1 -#ifndef RTS_VECTOR_H  
2 -#define RTS_VECTOR_H  
3 -  
4 -#include <iostream>  
5 -#include <cmath>  
6 -#include <sstream>  
7 -//#include "rts/math/point.h"  
8 -#include "../cuda/callable.h"  
9 -  
10 -  
11 -namespace stim  
12 -{  
13 -  
14 -  
15 -  
16 -template <class T, int N=3>  
17 -struct vec  
18 -{  
19 - T v[N];  
20 -  
21 - CUDA_CALLABLE vec()  
22 - {  
23 - //memset(v, 0, sizeof(T) * N);  
24 - for(int i=0; i<N; i++)  
25 - v[i] = 0;  
26 - }  
27 -  
28 - //efficiency constructor, makes construction easier for 1D-4D vectors  
29 - CUDA_CALLABLE vec(T rhs)  
30 - {  
31 - for(int i=0; i<N; i++)  
32 - v[i] = rhs;  
33 - }  
34 - CUDA_CALLABLE vec(T x, T y)  
35 - {  
36 - v[0] = x;  
37 - v[1] = y;  
38 - }  
39 - CUDA_CALLABLE vec(T x, T y, T z)  
40 - {  
41 - v[0] = x;  
42 - v[1] = y;  
43 - v[2] = z;  
44 - }  
45 - CUDA_CALLABLE vec(T x, T y, T z, T w)  
46 - {  
47 - v[0] = x;  
48 - v[1] = y;  
49 - v[2] = z;  
50 - v[3] = w;  
51 - }  
52 -  
53 - //copy constructor  
54 - CUDA_CALLABLE vec( const vec<T, N>& other){  
55 - for(int i=0; i<N; i++)  
56 - v[i] = other.v[i];  
57 - }  
58 -  
59 -  
60 - template< typename U >  
61 - CUDA_CALLABLE operator vec<U, N>(){  
62 - vec<U, N> result;  
63 - for(int i=0; i<N; i++)  
64 - result.v[i] = v[i];  
65 -  
66 - return result;  
67 - }  
68 -  
69 - //template<class U>  
70 - //friend vec<U, N>::operator vec<T, N>();  
71 -  
72 - CUDA_CALLABLE T len() const  
73 - {  
74 - //compute and return the vector length  
75 - T sum_sq = (T)0;  
76 - for(int i=0; i<N; i++)  
77 - {  
78 - sum_sq += v[i] * v[i];  
79 - }  
80 - return sqrt(sum_sq);  
81 -  
82 - }  
83 -  
84 - CUDA_CALLABLE vec<T, N> cart2sph() const  
85 - {  
86 - //convert the vector from cartesian to spherical coordinates  
87 - //x, y, z -> r, theta, phi (where theta = 0 to 2*pi)  
88 -  
89 - vec<T, N> sph;  
90 - sph[0] = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);  
91 - sph[1] = std::atan2(v[1], v[0]);  
92 - sph[2] = std::acos(v[2] / sph[0]);  
93 -  
94 - return sph;  
95 - }  
96 -  
97 - CUDA_CALLABLE vec<T, N> sph2cart() const  
98 - {  
99 - //convert the vector from cartesian to spherical coordinates  
100 - //r, theta, phi -> x, y, z (where theta = 0 to 2*pi)  
101 -  
102 - vec<T, N> cart;  
103 - cart[0] = v[0] * std::cos(v[1]) * std::sin(v[2]);  
104 - cart[1] = v[0] * std::sin(v[1]) * std::sin(v[2]);  
105 - cart[2] = v[0] * std::cos(v[2]);  
106 -  
107 - return cart;  
108 - }  
109 -  
110 - CUDA_CALLABLE vec<T, N> norm() const  
111 - {  
112 - //compute and return the vector norm  
113 - vec<T, N> result;  
114 -  
115 - //compute the vector length  
116 - T l = len();  
117 -  
118 - //normalize  
119 - for(int i=0; i<N; i++)  
120 - {  
121 - result.v[i] = v[i] / l;  
122 - }  
123 -  
124 - return result;  
125 - }  
126 -  
127 - CUDA_CALLABLE vec<T, 3> cross(const vec<T, 3> rhs) const  
128 - {  
129 - vec<T, 3> result;  
130 -  
131 - //compute the cross product (only valid for 3D vectors)  
132 - result[0] = v[1] * rhs.v[2] - v[2] * rhs.v[1];  
133 - result[1] = v[2] * rhs.v[0] - v[0] * rhs.v[2];  
134 - result[2] = v[0] * rhs.v[1] - v[1] * rhs.v[0];  
135 -  
136 - return result;  
137 - }  
138 -  
139 - CUDA_CALLABLE T dot(vec<T, N> rhs) const  
140 - {  
141 - T result = (T)0;  
142 -  
143 - for(int i=0; i<N; i++)  
144 - result += v[i] * rhs.v[i];  
145 -  
146 - return result;  
147 -  
148 - }  
149 -  
150 - //arithmetic  
151 - CUDA_CALLABLE vec<T, N> operator+(vec<T, N> rhs) const  
152 - {  
153 - vec<T, N> result;  
154 -  
155 - for(int i=0; i<N; i++)  
156 - result.v[i] = v[i] + rhs.v[i];  
157 -  
158 - return result;  
159 - }  
160 - CUDA_CALLABLE vec<T, N> operator+(T rhs) const  
161 - {  
162 - vec<T, N> result;  
163 -  
164 - for(int i=0; i<N; i++)  
165 - result.v[i] = v[i] + rhs;  
166 -  
167 - return result;  
168 - }  
169 - CUDA_CALLABLE vec<T, N> operator-(vec<T, N> rhs) const  
170 - {  
171 - vec<T, N> result;  
172 -  
173 - for(int i=0; i<N; i++)  
174 - result.v[i] = v[i] - rhs.v[i];  
175 -  
176 - return result;  
177 - }  
178 - CUDA_CALLABLE vec<T, N> operator*(T rhs) const  
179 - {  
180 - vec<T, N> result;  
181 -  
182 - for(int i=0; i<N; i++)  
183 - result.v[i] = v[i] * rhs;  
184 -  
185 - return result;  
186 - }  
187 - CUDA_CALLABLE vec<T, N> operator/(T rhs) const  
188 - {  
189 - vec<T, N> result;  
190 -  
191 - for(int i=0; i<N; i++)  
192 - result.v[i] = v[i] / rhs;  
193 -  
194 - return result;  
195 - }  
196 - CUDA_CALLABLE vec<T, N> operator*=(T rhs){  
197 - for(int i=0; i<N; i++)  
198 - v[i] = v[i] * rhs;  
199 - return *this;  
200 - }  
201 - CUDA_CALLABLE vec<T, N> & operator=(T rhs){  
202 - for(int i=0; i<N; i++)  
203 - v[i] = rhs;  
204 - return *this;  
205 - }  
206 - template<typename Y>  
207 - CUDA_CALLABLE vec<T, N> & operator=(vec<Y, N> rhs){  
208 - for(int i=0; i<N; i++)  
209 - v[i] = rhs.v[i];  
210 - return *this;  
211 - }  
212 - //unary minus  
213 - CUDA_CALLABLE vec<T, N> operator-() const{  
214 - vec<T, N> r;  
215 -  
216 - //negate the vector  
217 - for(int i=0; i<N; i++)  
218 - r.v[i] = -v[i];  
219 -  
220 - return r;  
221 - }  
222 -  
223 - CUDA_CALLABLE bool operator==(vec<T, N> rhs) const  
224 - {  
225 - if ( (rhs.v[0] == v[0]) && (rhs.v[1] == v[1]) && (rhs.v[2] == v[2]) )  
226 - return true;  
227 -  
228 - return false;  
229 - }  
230 -  
231 - std::string str() const  
232 - {  
233 - std::stringstream ss;  
234 -  
235 - ss<<"[";  
236 - for(int i=0; i<N; i++)  
237 - {  
238 - ss<<v[i];  
239 - if(i != N-1)  
240 - ss<<", ";  
241 - }  
242 - ss<<"]";  
243 -  
244 - return ss.str();  
245 - }  
246 -  
247 - //bracket operator - allows assignment to the vector  
248 - CUDA_CALLABLE T& operator[](const unsigned int i)  
249 - {  
250 - return v[i];  
251 - }  
252 -  
253 -};  
254 -  
255 -  
256 -} //end namespace rts  
257 -  
258 -template <typename T, int N>  
259 -std::ostream& operator<<(std::ostream& os, stim::vec<T, N> v)  
260 -{  
261 - os<<v.str();  
262 - return os;  
263 -}  
264 -  
265 -  
266 -  
267 -template <typename T, int N>  
268 -CUDA_CALLABLE stim::vec<T, N> operator*(T lhs, stim::vec<T, N> rhs)  
269 -{  
270 - stim::vec<T, N> r;  
271 -  
272 - return rhs * lhs;  
273 -}  
274 -  
275 -//#if __GNUC__ > 3 && __GNUC_MINOR__ > 7  
276 -//template<class T, int N> using rtsVector = rts::vector<T, N>;  
277 -//#endif  
278 -  
279 -#endif  
stim/visualization/camera.h
1 -#include "../math/vector.h" 1 +#include "../math/mathvec.h"
2 #include "../math/quaternion.h" 2 #include "../math/quaternion.h"
3 #include "../math/matrix.h" 3 #include "../math/matrix.h"
4 4
@@ -11,32 +11,32 @@ namespace stim{ @@ -11,32 +11,32 @@ namespace stim{
11 11
12 class camera 12 class camera
13 { 13 {
14 - vec<float, 3> d; //direction that the camera is pointing  
15 - vec<float, 3> p; //position of the camera  
16 - vec<float, 3> up; //"up" direction 14 + vec<float> d; //direction that the camera is pointing
  15 + vec<float> p; //position of the camera
  16 + vec<float> up; //"up" direction
17 float focus; //focal length of the camera 17 float focus; //focal length of the camera
18 float fov; 18 float fov;
19 19
20 //private function makes sure that the up vector is orthogonal to the direction vector and both are normalized 20 //private function makes sure that the up vector is orthogonal to the direction vector and both are normalized
21 void stabalize() 21 void stabalize()
22 { 22 {
23 - vec<float, 3> side = up.cross(d); 23 + vec<float> side = up.cross(d);
24 up = d.cross(side); 24 up = d.cross(side);
25 up = up.norm(); 25 up = up.norm();
26 d = d.norm(); 26 d = d.norm();
27 } 27 }
28 28
29 public: 29 public:
30 - void setPosition(vec<float, 3> pos) 30 + void setPosition(vec<float> pos)
31 { 31 {
32 p = pos; 32 p = pos;
33 } 33 }
34 - void setPosition(float x, float y, float z){setPosition(vec<float, 3>(x, y, z));} 34 + void setPosition(float x, float y, float z){setPosition(vec<float>(x, y, z));}
35 35
36 void setFocalDistance(float distance){focus = distance;} 36 void setFocalDistance(float distance){focus = distance;}
37 void setFOV(float field_of_view){fov = field_of_view;} 37 void setFOV(float field_of_view){fov = field_of_view;}
38 38
39 - void LookAt(vec<float, 3> pos) 39 + void LookAt(vec<float> pos)
40 { 40 {
41 //find the new direction 41 //find the new direction
42 d = pos - p; 42 d = pos - p;
@@ -47,22 +47,22 @@ public: @@ -47,22 +47,22 @@ public:
47 //stabalize the camera 47 //stabalize the camera
48 stabalize(); 48 stabalize();
49 } 49 }
50 - void LookAt(float px, float py, float pz){LookAt(vec<float, 3>(px, py, pz));}  
51 - void LookAt(vec<float, 3> pos, vec<float, 3> new_up){up = new_up; LookAt(pos);}  
52 - void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(vec<float, 3>(px, py, pz), vec<float, 3>(ux, uy, uz));} 50 + void LookAt(float px, float py, float pz){LookAt(vec<float>(px, py, pz));}
  51 + void LookAt(vec<float> pos, vec<float> new_up){up = new_up; LookAt(pos);}
  52 + void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(vec<float>(px, py, pz), vec<float>(ux, uy, uz));}
53 void LookAtDolly(float lx, float ly, float lz) 53 void LookAtDolly(float lx, float ly, float lz)
54 { 54 {
55 //find the current focus point 55 //find the current focus point
56 - vec<float, 3> f = p + focus*d;  
57 - vec<float, 3> T = vec<float, 3>(lx, ly, lz) - f; 56 + vec<float> f = p + focus*d;
  57 + vec<float> T = vec<float>(lx, ly, lz) - f;
58 p = p + T; 58 p = p + T;
59 } 59 }
60 60
61 - void Dolly(vec<float, 3> direction) 61 + void Dolly(vec<float> direction)
62 { 62 {
63 p = p+direction; 63 p = p+direction;
64 } 64 }
65 - void Dolly(float x, float y, float z){Dolly(vec<float, 3>(x, y, z));} 65 + void Dolly(float x, float y, float z){Dolly(vec<float>(x, y, z));}
66 void Push(float delta) 66 void Push(float delta)
67 { 67 {
68 if(delta > focus) 68 if(delta > focus)
@@ -80,7 +80,7 @@ public: @@ -80,7 +80,7 @@ public:
80 qx.CreateRotation(theta_x, up[0], up[1], up[2]); 80 qx.CreateRotation(theta_x, up[0], up[1], up[2]);
81 81
82 //y rotation is around the side axis 82 //y rotation is around the side axis
83 - vec<float, 3> side = up.cross(d); 83 + vec<float> side = up.cross(d);
84 quaternion<float> qy; 84 quaternion<float> qy;
85 qy.CreateRotation(theta_y, side[0], side[1], side[2]); 85 qy.CreateRotation(theta_y, side[0], side[1], side[2]);
86 86
@@ -118,28 +118,28 @@ public: @@ -118,28 +118,28 @@ public:
118 void OrbitFocus(float theta_x, float theta_y) 118 void OrbitFocus(float theta_x, float theta_y)
119 { 119 {
120 //find the focal point 120 //find the focal point
121 - vec<float, 3> focal_point = p + focus*d; 121 + vec<float> focal_point = p + focus*d;
122 122
123 //center the coordinate system on the focal point 123 //center the coordinate system on the focal point
124 - vec<float, 3> centered = p - (focal_point - vec<float, 3>(0, 0, 0)); 124 + vec<float> centered = p - (focal_point - vec<float>(0, 0, 0));
125 125
126 //create the x rotation (around the up vector) 126 //create the x rotation (around the up vector)
127 quaternion<float> qx; 127 quaternion<float> qx;
128 qx.CreateRotation(theta_x, up[0], up[1], up[2]); 128 qx.CreateRotation(theta_x, up[0], up[1], up[2]);
129 - centered = vec<float, 3>(0, 0, 0) + qx.toMatrix3()*(centered - vec<float, 3>(0, 0, 0)); 129 + centered = vec<float>(0, 0, 0) + qx.toMatrix3()*(centered - vec<float>(0, 0, 0));
130 130
131 //get a side vector for theta_y rotation 131 //get a side vector for theta_y rotation
132 - vec<float, 3> side = up.cross((vec<float, 3>(0, 0, 0) - centered).norm()); 132 + vec<float> side = up.cross((vec<float>(0, 0, 0) - centered).norm());
133 133
134 quaternion<float> qy; 134 quaternion<float> qy;
135 qy.CreateRotation(theta_y, side[0], side[1], side[2]); 135 qy.CreateRotation(theta_y, side[0], side[1], side[2]);
136 - centered = vec<float, 3>(0, 0, 0) + qy.toMatrix3()*(centered - vec<float, 3>(0, 0, 0)); 136 + centered = vec<float>(0, 0, 0) + qy.toMatrix3()*(centered - vec<float>(0, 0, 0));
137 137
138 //perform the rotation on the centered camera position 138 //perform the rotation on the centered camera position
139 //centered = final.toMatrix()*centered; 139 //centered = final.toMatrix()*centered;
140 140
141 //re-position the camera 141 //re-position the camera
142 - p = centered + (focal_point - vec<float, 3>(0, 0, 0)); 142 + p = centered + (focal_point - vec<float>(0, 0, 0));
143 143
144 //make sure we are looking at the focal point 144 //make sure we are looking at the focal point
145 LookAt(focal_point); 145 LookAt(focal_point);
@@ -151,21 +151,21 @@ public: @@ -151,21 +151,21 @@ public:
151 151
152 void Slide(float u, float v) 152 void Slide(float u, float v)
153 { 153 {
154 - vec<float, 3> V = up.norm();  
155 - vec<float, 3> U = up.cross(d).norm(); 154 + vec<float> V = up.norm();
  155 + vec<float> U = up.cross(d).norm();
156 156
157 p = p + (V * v) + (U * u); 157 p = p + (V * v) + (U * u);
158 } 158 }
159 159
160 //accessor methods 160 //accessor methods
161 - vec<float, 3> getPosition(){return p;}  
162 - vec<float, 3> getUp(){return up;}  
163 - vec<float, 3> getDirection(){return d;}  
164 - vec<float, 3> getLookAt(){return p + focus*d;} 161 + vec<float> getPosition(){return p;}
  162 + vec<float> getUp(){return up;}
  163 + vec<float> getDirection(){return d;}
  164 + vec<float> getLookAt(){return p + focus*d;}
165 float getFOV(){return fov;} 165 float getFOV(){return fov;}
166 166
167 //output the camera settings 167 //output the camera settings
168 - const void print(std::ostream& output) 168 + void print(std::ostream& output)
169 { 169 {
170 output<<"Position: "<<p.str()<<std::endl; 170 output<<"Position: "<<p.str()<<std::endl;
171 171
@@ -182,9 +182,9 @@ public: @@ -182,9 +182,9 @@ public:
182 //constructor 182 //constructor
183 camera() 183 camera()
184 { 184 {
185 - p = vec<float, 3>(0, 0, 0);  
186 - d = vec<float, 3>(0, 0, 1);  
187 - up = vec<float, 3>(0, 1, 0); 185 + p = vec<float>(0, 0, 0);
  186 + d = vec<float>(0, 0, 1);
  187 + up = vec<float>(0, 1, 0);
188 focus = 1; 188 focus = 1;
189 189
190 } 190 }
stim/visualization/sph_harmonics.h renamed to stim/visualization/gl_spharmonics.h
1 -#ifndef STIM_SPH_HARMONICS  
2 -#define STIM_SPH_HARMONICS 1 +#ifndef STIM_GL_SPHARMONICS_H
  2 +#define STIM_GL_SPHARMONICS_H
3 3
4 #include <GL/gl.h> 4 #include <GL/gl.h>
5 5
6 #include <stim/gl/error.h> 6 #include <stim/gl/error.h>
7 #include <stim/visualization/colormap.h> 7 #include <stim/visualization/colormap.h>
8 -#include <vector> 8 +#include <stim/math/spharmonics.h>
9 9
10 -#define PI 3.14159  
11 -#define WIRE_SCALE 1.001  
12 namespace stim{ 10 namespace stim{
13 11
14 - class sph_harmonics{ 12 +
  13 +template <typename T>
  14 +class gl_spharmonics : public spharmonics<T>{
15 15
16 - private: 16 +protected:
  17 +
  18 + T* func; //stores the raw function data (samples at each point)
17 19
18 - double* func; //stores the raw function data (samples at each point) 20 + GLuint color_tex; //texture map that acts as a colormap for the spherical function
  21 +
  22 + unsigned int N; //resolution of the spherical grid
19 23
20 - GLuint color_tex; //texture map that acts as a colormap for the spherical function  
21 -  
22 - unsigned int N; //resolution of the spherical grid 24 + void gen_function(){
23 25
24 - std::vector<double> C; //list of SH coefficients 26 + //initialize the function to zero
  27 + memset(func, 0, sizeof(double) * N * N);
25 28
  29 + double theta, phi;
  30 + double result;
  31 + int l, m;
26 32
27 - //evaluates an associated Legendre polynomial (-l <= m <= l)  
28 - double P(int l,int m,double x)  
29 - {  
30 - // evaluate an Associated Legendre Polynomial P(l,m,x) at x  
31 - double pmm = 1.0;  
32 - if(m>0) {  
33 - double somx2 = sqrt((1.0-x)*(1.0+x));  
34 - double fact = 1.0;  
35 - for(int i=1; i<=m; i++) {  
36 - pmm *= (-fact) * somx2;  
37 - fact += 2.0;  
38 - }  
39 - }  
40 - if(l==m) return pmm;  
41 - double pmmp1 = x * (2.0*m+1.0) * pmm;  
42 - if(l==m+1) return pmmp1;  
43 - double pll = 0.0;  
44 - for(int ll=m+2; ll<=l; ++ll) {  
45 - pll = ( (2.0*ll-1.0)*x*pmmp1-(ll+m-1.0)*pmm ) / (ll-m);  
46 - pmm = pmmp1;  
47 - pmmp1 = pll;  
48 - }  
49 - return pll;  
50 - }  
51 33
52 - //recursively calculate a factorial given a positive integer n  
53 - unsigned int factorial(unsigned int n) {  
54 - if (n == 0)  
55 - return 1;  
56 - return n * factorial(n - 1);  
57 - }  
58 -  
59 - //calculate the SH scaling constant  
60 - double K(int l, int m){ 34 + l = m = 0;
  35 + //for each coefficient
  36 + for(unsigned int c = 0; c < C.size(); c++){
61 37
62 - // renormalisation constant for SH function  
63 - double temp = ((2.0*l+1.0)*factorial(l-m)) / (4.0*PI*factorial(l+m));  
64 - return sqrt(temp);  
65 - } 38 + //iterate through the entire 2D grid representing the function
  39 + for(unsigned int xi = 0; xi < N; xi++){
  40 + for(unsigned int yi = 0; yi < N; yi++){
66 41
67 - //calculate the value of the SH basis function (l, m) at (theta, phi)  
68 - //here, theta = [0, PI], phi = [0, 2*PI]  
69 - double SH(int l, int m, double theta, double phi){  
70 - // return a point sample of a Spherical Harmonic basis function  
71 - // l is the band, range [0..N]  
72 - // m in the range [-l..l]  
73 - // theta in the range [0..Pi]  
74 - // phi in the range [0..2*Pi]  
75 - const double sqrt2 = sqrt(2.0);  
76 - if(m==0) return K(l,0)*P(l,m,cos(theta));  
77 - else if(m>0) return sqrt2*K(l,m)*cos(m*phi)*P(l,m,cos(theta));  
78 - else return sqrt2*K(l,-m)*sin(-m*phi)*P(l,-m,cos(theta));  
79 - } 42 + //get the spherical coordinates for each grid point
  43 + theta = (2 * PI) * ((double)xi / (N-1));
  44 + phi = PI * ((double)yi / (N-1));
80 45
81 - void gen_function(){ 46 + //sum the contribution of the current spherical harmonic based on the coefficient
  47 + result = C[c] * SH(l, m, theta, phi);
82 48
83 - //initialize the function to zero  
84 - memset(func, 0, sizeof(double) * N * N);  
85 -  
86 - double theta, phi;  
87 - double result;  
88 - int l, m;  
89 -  
90 - l = m = 0;  
91 - for(unsigned int c = 0; c < C.size(); c++){  
92 -  
93 -  
94 - for(unsigned int xi = 0; xi < N; xi++)  
95 - for(unsigned int yi = 0; yi < N; yi++){  
96 -  
97 - theta = (2 * PI) * ((double)xi / (N-1));  
98 - phi = PI * ((double)yi / (N-1));  
99 - result = C[c] * SH(l, m, phi, theta); //phi and theta are reversed here (damn physicists)  
100 - func[yi * N + xi] += result;  
101 - }  
102 -  
103 - m++; //increment m  
104 -  
105 - //if we're in a new tier, increment l and set m = -l  
106 - if(m > l){  
107 - l++;  
108 - m = -l; 49 + //store the result in a 2D array (which will later be used as a texture map)
  50 + func[yi * N + xi] += result;
109 } 51 }
110 } 52 }
111 - }  
112 -  
113 - void gl_prep_draw(){  
114 53
115 - //enable depth testing  
116 - //this has to be used instead of culling because the sphere can have negative values  
117 - glEnable(GL_DEPTH_TEST);  
118 - glDepthMask(GL_TRUE);  
119 - glEnable(GL_TEXTURE_2D); //enable 2D texture mapping 54 + //keep track of m and l here
  55 + m++; //increment m
  56 + //if we're in a new tier, increment l and set m = -l
  57 + if(m > l){
  58 + l++;
  59 + m = -l;
  60 + }
120 } 61 }
  62 + }
121 63
122 - //draw a texture mapped sphere representing the function surface  
123 - void gl_draw_sphere() {  
124 -  
125 - //PI is used to convert from spherical to cartesian coordinates  
126 - //const double PI = 3.14159;  
127 -  
128 - //bind the 2D texture representing the color map  
129 - glBindTexture(GL_TEXTURE_2D, color_tex);  
130 -  
131 - //Draw the Sphere  
132 - int i, j;  
133 -  
134 - for(i = 1; i <= N-1; i++) {  
135 - double phi0 = PI * ((double) (i - 1) / (N-1));  
136 - double phi1 = PI * ((double) i / (N-1));  
137 -  
138 - glBegin(GL_QUAD_STRIP);  
139 - for(j = 0; j <= N; j++) {  
140 -  
141 - //calculate the indices into the function array  
142 - int phi0_i = i-1;  
143 - int phi1_i = i;  
144 - int theta_i = j;  
145 - if(theta_i == N)  
146 - theta_i = 0;  
147 -  
148 - double v0 = func[phi0_i * N + theta_i];  
149 - double v1 = func[phi1_i * N + theta_i];  
150 -  
151 - v0 = fabs(v0);  
152 - v1 = fabs(v1);  
153 -  
154 -  
155 - double theta = 2 * PI * (double) (j - 1) / N;  
156 - double x0 = v0 * cos(theta) * sin(phi0);  
157 - double y0 = v0 * sin(theta) * sin(phi0);  
158 - double z0 = v0 * cos(phi0);  
159 -  
160 - double x1 = v1 * cos(theta) * sin(phi1);  
161 - double y1 = v1 * sin(theta) * sin(phi1);  
162 - double z1 = v1 * cos(phi1);  
163 -  
164 - glTexCoord2f(theta / (2 * PI), phi0 / PI);  
165 - glVertex3f(x0, y0, z0);  
166 -  
167 - glTexCoord2f(theta / (2 * PI), phi1 / PI);  
168 - glVertex3f(x1, y1, z1);  
169 - }  
170 - glEnd();  
171 - }  
172 - } 64 + void gl_prep_draw(){
173 65
174 - //draw a wire frame sphere representing the function surface  
175 - void gl_draw_wireframe() { 66 + //enable depth testing
  67 + //this has to be used instead of culling because the sphere can have negative values
  68 + glEnable(GL_DEPTH_TEST);
  69 + glDepthMask(GL_TRUE);
  70 + glEnable(GL_TEXTURE_2D); //enable 2D texture mapping
  71 + }
176 72
177 - //PI is used to convert from spherical to cartesian coordinates  
178 - //const double PI = 3.14159; 73 + //draw a texture mapped sphere representing the function surface
  74 + void gl_draw_sphere() {
179 75
180 - //bind the 2D texture representing the color map  
181 - glDisable(GL_TEXTURE_2D);  
182 - glColor3f(0.0f, 0.0f, 0.0f); 76 + //bind the 2D texture representing the color map
  77 + glBindTexture(GL_TEXTURE_2D, color_tex);
183 78
184 - //Draw the Sphere  
185 - int i, j; 79 + //Draw the Sphere
  80 + int i, j;
186 81
187 - for(i = 1; i <= N-1; i++) {  
188 - double phi0 = PI * ((double) (i - 1) / (N-1));  
189 - double phi1 = PI * ((double) i / (N-1)); 82 + for(i = 1; i <= N-1; i++) {
  83 + double phi0 = PI * ((double) (i - 1) / (N-1));
  84 + double phi1 = PI * ((double) i / (N-1));
190 85
191 - glBegin(GL_LINE_STRIP);  
192 - for(j = 0; j <= N; j++) { 86 + glBegin(GL_QUAD_STRIP);
  87 + for(j = 0; j <= N; j++) {
193 88
194 - //calculate the indices into the function array  
195 - int phi0_i = i-1;  
196 - int phi1_i = i;  
197 - int theta_i = j;  
198 - if(theta_i == N)  
199 - theta_i = 0; 89 + //calculate the indices into the function array
  90 + int phi0_i = i-1;
  91 + int phi1_i = i;
  92 + int theta_i = j;
  93 + if(theta_i == N)
  94 + theta_i = 0;
200 95
201 - double v0 = func[phi0_i * N + theta_i];  
202 - double v1 = func[phi1_i * N + theta_i]; 96 + double v0 = func[phi0_i * N + theta_i];
  97 + double v1 = func[phi1_i * N + theta_i];
203 98
204 - v0 = fabs(v0);  
205 - v1 = fabs(v1); 99 + v0 = fabs(v0);
  100 + v1 = fabs(v1);
206 101
207 102
208 - double theta = 2 * PI * (double) (j - 1) / N;  
209 - double x0 = WIRE_SCALE * v0 * cos(theta) * sin(phi0);  
210 - double y0 = WIRE_SCALE * v0 * sin(theta) * sin(phi0);  
211 - double z0 = WIRE_SCALE * v0 * cos(phi0); 103 + double theta = 2 * PI * (double) (j - 1) / N;
  104 + double x0 = v0 * cos(theta) * sin(phi0);
  105 + double y0 = v0 * sin(theta) * sin(phi0);
  106 + double z0 = v0 * cos(phi0);
212 107
213 - double x1 = WIRE_SCALE * v1 * cos(theta) * sin(phi1);  
214 - double y1 = WIRE_SCALE * v1 * sin(theta) * sin(phi1);  
215 - double z1 = WIRE_SCALE * v1 * cos(phi1); 108 + double x1 = v1 * cos(theta) * sin(phi1);
  109 + double y1 = v1 * sin(theta) * sin(phi1);
  110 + double z1 = v1 * cos(phi1);
216 111
217 - glTexCoord2f(theta / (2 * PI), phi0 / PI);  
218 - glVertex3f(x0, y0, z0); 112 + glTexCoord2f(theta / (2 * PI), phi0 / PI);
  113 + glVertex3f(x0, y0, z0);
219 114
220 - glTexCoord2f(theta / (2 * PI), phi1 / PI);  
221 - glVertex3f(x1, y1, z1);  
222 - }  
223 - glEnd();  
224 - }  
225 - } 115 + glTexCoord2f(theta / (2 * PI), phi1 / PI);
  116 + glVertex3f(x1, y1, z1);
  117 + }
  118 + glEnd();
  119 + }
  120 + }
226 121
227 - void init(unsigned int n){ 122 + void gl_init(unsigned int n){
228 123
229 - //set the sphere resolution  
230 - N = n; 124 + //set the sphere resolution
  125 + N = n;
231 126
232 - //allocate space for the color map  
233 - unsigned int bytes = N * N * sizeof(unsigned char) * 3;  
234 - unsigned char* color_image;  
235 - color_image = (unsigned char*) malloc(bytes); 127 + //allocate space for the color map
  128 + unsigned int bytes = N * N * sizeof(unsigned char) * 3;
  129 + unsigned char* color_image;
  130 + color_image = (unsigned char*) malloc(bytes);
236 131
237 - //allocate space for the function  
238 - func = (double*) malloc(N * N * sizeof(double)); 132 + //allocate space for the function
  133 + func = (double*) malloc(N * N * sizeof(double));
239 134
240 - //generate a function (temporary)  
241 - gen_function(); 135 + //generate a functional representation that will be used for the texture map and vertices
  136 + gen_function();
242 137
243 - //generate a colormap from the function  
244 - stim::cpu2cpu<double>(func, color_image, N*N, stim::cmBrewer); 138 + //generate a colormap from the function
  139 + stim::cpu2cpu<double>(func, color_image, N*N, stim::cmBrewer);
245 140
246 - //prep everything for drawing  
247 - gl_prep_draw(); 141 + //prep everything for drawing
  142 + gl_prep_draw();
248 143
249 - //generate an OpenGL texture map in the current context  
250 - glGenTextures(1, &color_tex);  
251 - //bind the texture  
252 - glBindTexture(GL_TEXTURE_2D, color_tex); 144 + //generate an OpenGL texture map in the current context
  145 + glGenTextures(1, &color_tex);
  146 + //bind the texture
  147 + glBindTexture(GL_TEXTURE_2D, color_tex);
253 148
254 - //copy the color data from the buffer to the GPU  
255 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, N, N, 0, GL_RGB, GL_UNSIGNED_BYTE, color_image); 149 + //copy the color data from the buffer to the GPU
  150 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, N, N, 0, GL_RGB, GL_UNSIGNED_BYTE, color_image);
256 151
257 - //initialize all of the texture parameters  
258 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);  
259 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);  
260 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
261 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  
262 - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 152 + //initialize all of the texture parameters
  153 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  154 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  155 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  156 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  157 + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
263 158
264 - //free the buffer  
265 - free(color_image);  
266 - }  
267 -  
268 -  
269 - public: 159 + //free the buffer
  160 + free(color_image);
  161 + }
270 162
271 - void glRender(){  
272 - //set all OpenGL parameters required for drawing  
273 - gl_prep_draw();  
274 -  
275 - //draw the sphere  
276 - gl_draw_sphere();  
277 - //gl_draw_wireframe();  
278 -  
279 - }  
280 -  
281 - void glInit(unsigned int n){  
282 - init(n);  
283 - }  
284 -  
285 - void push(double c){  
286 - C.push_back(c);  
287 - } 163 +public:
288 164
  165 + void glRender(){
  166 + //set all OpenGL parameters required for drawing
  167 + gl_prep_draw();
289 168
  169 + //draw the sphere
  170 + gl_draw_sphere();
  171 + }
290 172
  173 + void glInit(unsigned int n = 256){
  174 + gl_init(n);
  175 + gen_function();
  176 + }
291 177
292 178
293 - }; //end class sph_harmonics 179 +}; //end gl_spharmonics
294 180
295 181
  182 +}; //end namespace stim
296 183
297 184
298 -}  
299 185
300 186
301 -#endif 187 +#endif
302 \ No newline at end of file 188 \ No newline at end of file
stim/visualization/obj.h
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include <fstream> 6 #include <fstream>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <stim/parser/parser.h> 8 #include <stim/parser/parser.h>
  9 +#include <stim/math/mathvec.h>
9 10
10 namespace stim{ 11 namespace stim{
11 12
@@ -34,37 +35,14 @@ protected: @@ -34,37 +35,14 @@ protected:
34 35
35 enum token_type { OBJ_INVALID, OBJ_V, OBJ_VT, OBJ_VN, OBJ_P, OBJ_L, OBJ_F }; 36 enum token_type { OBJ_INVALID, OBJ_V, OBJ_VT, OBJ_VN, OBJ_P, OBJ_L, OBJ_F };
36 37
37 - struct vertex : public std::vector<T>{ 38 + struct vertex : public stim::vec<T>{
38 39
39 - using std::vector<T>::push_back;  
40 - using std::vector<T>::size;  
41 - using std::vector<T>::at; 40 + using vec<T>::push_back;
  41 + using vec<T>::size;
  42 + using vec<T>::at;
42 43
43 vertex(){} 44 vertex(){}
44 45
45 - //constructors for quickly building vertices with arbitrary numbers of components  
46 - vertex(T x){  
47 - push_back(x);  
48 - }  
49 -  
50 - vertex(T x, T y){  
51 - push_back(x);  
52 - push_back(y);  
53 - }  
54 -  
55 - vertex(T x, T y, T z){  
56 - push_back(x);  
57 - push_back(y);  
58 - push_back(z);  
59 - }  
60 -  
61 - vertex(T x, T y, T z, T w){  
62 - push_back(x);  
63 - push_back(y);  
64 - push_back(z);  
65 - push_back(w);  
66 - }  
67 -  
68 //constructor creates a vertex from a line string 46 //constructor creates a vertex from a line string
69 vertex(std::string line){ 47 vertex(std::string line){
70 48
@@ -305,6 +283,11 @@ protected: @@ -305,6 +283,11 @@ protected:
305 } 283 }
306 284
307 public: 285 public:
  286 + /// Constructor loads a Wavefront OBJ file
  287 + obj(std::string filename){
  288 + load(filename);
  289 + }
  290 +
308 //functions for setting the texture coordinate for the next vertex 291 //functions for setting the texture coordinate for the next vertex
309 void TexCoord(T x){ update_vt(vertex(x));} 292 void TexCoord(T x){ update_vt(vertex(x));}
310 void TexCoord(T x, T y){ update_vt(vertex(x, y));} 293 void TexCoord(T x, T y){ update_vt(vertex(x, y));}
@@ -504,6 +487,47 @@ public: @@ -504,6 +487,47 @@ public:
504 487
505 } 488 }
506 489
  490 + /// Return the number of position vertices in the OBJ model
  491 + unsigned int numV(){
  492 + return V.size();
  493 + }
  494 +
  495 + /// Retrieve the vertex stored in index i
  496 +
  497 + /// @param i is the desired vertex index
  498 + stim::vec<T> getV(unsigned int i){
  499 +
  500 + stim::vec<T> v = V[i];
  501 + return v;
  502 + }
  503 +
  504 + stim::vec<T> centroid(){
  505 +
  506 + //get the number of coordinates
  507 + unsigned int N = V[0].size();
  508 +
  509 + //allocate space for the minimum and maximum coordinate points (bounding box corners)
  510 + stim::vec<float> vmin, vmax;
  511 + vmin.resize(N);
  512 + vmax.resize(N);
  513 +
  514 + //find the minimum and maximum value for each coordinate
  515 + unsigned int NV = V.size();
  516 + for(unsigned int v = 0; v < NV; v++)
  517 + for(unsigned int i = 0; i < N; i++){
  518 +
  519 + if(V[v][i] < vmin[i])
  520 + vmin[i] = V[v][i];
  521 + if(V[v][i] > vmax[i])
  522 + vmax[i] = V[v][i];
  523 + }
  524 +
  525 + //find the centroid using the min and max points
  526 + stim::vec<T> c = vmin * 0.5 + vmax * 0.5;
  527 +
  528 + return c;
  529 + }
  530 +
507 531
508 }; 532 };
509 533