Commit 03c403facb572c7df53e36dd20ef6b73ea1290e3
Merge branch 'master' of git.stim.ee.uh.edu:codebase/stimlib
Showing
40 changed files
with
3697 additions
and
1625 deletions
Show diff stats
stim/biomodels/network.h
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | #include <algorithm> |
9 | 9 | #include <string.h> |
10 | 10 | #include <math.h> |
11 | -#include <stim/math/vector.h> | |
11 | +#include <stim/math/vec3.h> | |
12 | 12 | #include <stim/visualization/obj.h> |
13 | 13 | #include <stim/visualization/cylinder.h> |
14 | 14 | #include <ANN/ANN.h> |
... | ... | @@ -37,7 +37,7 @@ class network{ |
37 | 37 | /// Constructor - creates an edge from a list of points by calling the stim::fiber constructor |
38 | 38 | |
39 | 39 | ///@param p is an array of positions in space |
40 | - edge(std::vector< stim::vec<T> > p) : cylinder<T>(p){} | |
40 | + edge(std::vector< stim::vec3<T> > p) : cylinder<T>(p){} | |
41 | 41 | |
42 | 42 | /// Copy constructor creates an edge from a fiber |
43 | 43 | edge(stim::cylinder<T> f) : cylinder<T>(f) {} |
... | ... | @@ -61,20 +61,20 @@ class network{ |
61 | 61 | }; |
62 | 62 | |
63 | 63 | ///Node class that stores the physical position of the node as well as the edges it is connected to (edges that connect to it), As well as any additional data necessary. |
64 | - class vertex : public stim::vec<T> | |
64 | + class vertex : public stim::vec3<T> | |
65 | 65 | { |
66 | 66 | public: |
67 | 67 | //std::vector<unsigned int> edges; //indices of edges connected to this node. |
68 | 68 | std::vector<unsigned int> e[2]; //indices of edges going out (e[0]) and coming in (e[1]) |
69 | - //stim::vec<T> p; //position of this node in physical space. | |
69 | + //stim::vec3<T> p; //position of this node in physical space. | |
70 | 70 | |
71 | 71 | //constructor takes a stim::vec |
72 | - vertex(stim::vec<T> p) : stim::vec<T>(p){} | |
72 | + vertex(stim::vec3<T> p) : stim::vec3<T>(p){} | |
73 | 73 | |
74 | 74 | /// Output the vertex information as a string |
75 | 75 | std::string str(){ |
76 | 76 | std::stringstream ss; |
77 | - ss<<"\t(x, y, z) = "<<stim::vec<T>::str(); | |
77 | + ss<<"\t(x, y, z) = "<<stim::vec3<T>::str(); | |
78 | 78 | |
79 | 79 | if(e[0].size() > 0){ |
80 | 80 | ss<<"\t> "; |
... | ... | @@ -129,7 +129,11 @@ public: |
129 | 129 | std::vector< stim::vec<T> > c; //allocate an array of points for the vessel centerline |
130 | 130 | O.getLine(l, c); //get the fiber centerline |
131 | 131 | |
132 | - edge new_edge = c; //create an edge from the given centerline | |
132 | + std::vector< stim::vec3<T> > c3(c.size()); | |
133 | + for(size_t j = 0; j < c.size(); j++) | |
134 | + c3[j] = c[j]; | |
135 | + | |
136 | + edge new_edge = c3; //create an edge from the given centerline | |
133 | 137 | unsigned int I = new_edge.size(); //calculate the number of points on the centerline |
134 | 138 | |
135 | 139 | //get the first and last vertex IDs for the line |
... | ... | @@ -222,7 +226,7 @@ public: |
222 | 226 | float gaussianFunction(float x, float std=25){ return exp(-x/(2*std*std));} // by default std = 25 |
223 | 227 | |
224 | 228 | // stim 3d vector to annpoint of 3 dimensions |
225 | - void stim2ann(ANNpoint &a, stim::vec<T> b){ | |
229 | + void stim2ann(ANNpoint &a, stim::vec3<T> b){ | |
226 | 230 | a[0] = b[0]; |
227 | 231 | a[1] = b[1]; |
228 | 232 | a[2] = b[2]; |
... | ... | @@ -278,10 +282,9 @@ public: |
278 | 282 | ANNdistArray dists = new ANNdist[1]; // near neighbor distances |
279 | 283 | ANNidxArray nnIdx = new ANNidx[1]; // near neighbor indices // allocate near neigh indices |
280 | 284 | |
281 | - stim::vec<T> p0, p1; | |
282 | - float m0, m1; | |
285 | + stim::vec3<T> p0, p1; | |
286 | + float m1; | |
283 | 287 | float M = 0; //stores the total metric value |
284 | - float l; //stores the segment length | |
285 | 288 | float L = 0; //stores the total network length |
286 | 289 | ANNpoint queryPt = annAllocPt(3); |
287 | 290 | for(unsigned e = 0; e < R.E.size(); e++){ //for each edge in A |
... | ... | @@ -292,7 +295,7 @@ public: |
292 | 295 | p1 = R.E[e][p]; //get the next point in the edge |
293 | 296 | stim2ann(queryPt, p1); |
294 | 297 | kdt->annkSearch( queryPt, 1, nnIdx, dists, eps); //find the distance between A and the current network |
295 | - m1 = 1.0f - gaussianFunction(dists[0], sigma); //calculate the metric value based on the distance | |
298 | + m1 = 1.0f - gaussianFunction((float)dists[0], sigma); //calculate the metric value based on the distance | |
296 | 299 | R.E[e].set_mag(m1, p, 1); //set the error for the second point in the segment |
297 | 300 | |
298 | 301 | } | ... | ... |
stim/cuda/cudatools/callable.h
stim/cuda/cudatools/devices.h
... | ... | @@ -15,7 +15,7 @@ int maxThreadsPerBlock() |
15 | 15 | } |
16 | 16 | |
17 | 17 | extern "C" |
18 | -int sharedMemPerBlock() | |
18 | +size_t sharedMemPerBlock() | |
19 | 19 | { |
20 | 20 | int device; |
21 | 21 | cudaGetDevice(&device); //get the id of the current device |
... | ... | @@ -23,6 +23,16 @@ int sharedMemPerBlock() |
23 | 23 | cudaGetDeviceProperties(&props, device); |
24 | 24 | return props.sharedMemPerBlock; |
25 | 25 | } |
26 | + | |
27 | +extern "C" | |
28 | +size_t constMem() | |
29 | +{ | |
30 | + int device; | |
31 | + cudaGetDevice(&device); //get the id of the current device | |
32 | + cudaDeviceProp props; //device property structure | |
33 | + cudaGetDeviceProperties(&props, device); | |
34 | + return props.totalConstMem; | |
35 | +} | |
26 | 36 | } //end namespace rts |
27 | 37 | |
28 | 38 | #endif | ... | ... |
stim/cuda/sharedmem.cuh
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | namespace stim{ |
6 | 6 | namespace cuda{ |
7 | 7 | |
8 | - // Copies values from global memory to shared memory, optimizing threads | |
8 | + // Copies values from texture memory to shared memory, optimizing threads | |
9 | 9 | template<typename T> |
10 | 10 | __device__ void sharedMemcpy_tex2D(T* dest, cudaTextureObject_t src, |
11 | 11 | unsigned int x, unsigned int y, unsigned int X, unsigned int Y, |
... | ... | @@ -35,6 +35,19 @@ namespace stim{ |
35 | 35 | } |
36 | 36 | } |
37 | 37 | |
38 | + // Copies values from global memory to shared memory, optimizing threads | |
39 | + template<typename T> | |
40 | + __device__ void sharedMemcpy(T* dest, T* src, size_t N, size_t tid, size_t nt){ | |
41 | + | |
42 | + size_t I = N / nt + 1; //calculate the number of iterations required to make the copy | |
43 | + size_t xi = tid; //initialize the source and destination index to the thread ID | |
44 | + for(size_t i = 0; i < I; i++){ //for each iteration | |
45 | + if(xi < N) //if the index is within the copy region | |
46 | + dest[xi] = src[xi]; //perform the copy | |
47 | + xi += nt; | |
48 | + } | |
49 | + } | |
50 | + | |
38 | 51 | |
39 | 52 | } |
40 | 53 | } | ... | ... |
stim/envi/bil.h
... | ... | @@ -884,7 +884,7 @@ public: |
884 | 884 | /// using the following indexing: i = p*B + b |
885 | 885 | /// @param matrix is the destination for the pixel data |
886 | 886 | /// @param mask is the mask |
887 | - bool sift(T* matrix, unsigned char* mask = NULL){ | |
887 | + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){ | |
888 | 888 | size_t Lbytes = sizeof(T) * X(); |
889 | 889 | T* line = (T*) malloc( Lbytes ); //allocate space for a line |
890 | 890 | |
... | ... | @@ -903,6 +903,7 @@ public: |
903 | 903 | pl++; //increment the pixel pointer |
904 | 904 | } |
905 | 905 | } |
906 | + if(PROGRESS) progress = (double)( (y+1)*Z() + 1) / (double)(Y() * Z()) * 100; | |
906 | 907 | } |
907 | 908 | p += pl; //add the line increment to the running pixel index |
908 | 909 | } | ... | ... |
stim/envi/bip.h
... | ... | @@ -817,7 +817,7 @@ public: |
817 | 817 | /// using the following indexing: i = p*B + b |
818 | 818 | /// @param matrix is the destination for the pixel data |
819 | 819 | /// @param mask is the mask |
820 | - bool sift(T* matrix, unsigned char* mask = NULL){ | |
820 | + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){ | |
821 | 821 | size_t Bbytes = sizeof(T) * Z(); |
822 | 822 | size_t XY = X() * Y(); |
823 | 823 | T* band = (T*) malloc( Bbytes ); //allocate space for a line |
... | ... | @@ -836,6 +836,7 @@ public: |
836 | 836 | } |
837 | 837 | else |
838 | 838 | file.seekg(Bbytes, std::ios::cur); //otherwise skip this band |
839 | + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100; | |
839 | 840 | } |
840 | 841 | return true; |
841 | 842 | } | ... | ... |
stim/envi/bsq.h
... | ... | @@ -809,7 +809,7 @@ public: |
809 | 809 | /// using the following indexing: i = p*B + b |
810 | 810 | /// @param matrix is the destination for the pixel data |
811 | 811 | /// @param mask is the mask |
812 | - bool sift(T* matrix, unsigned char* mask = NULL){ | |
812 | + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){ | |
813 | 813 | unsigned long long XY = X() * Y(); //Number of XY pixels |
814 | 814 | unsigned long long L = XY * sizeof(T); //size of XY plane (in bytes) |
815 | 815 | |
... | ... | @@ -827,9 +827,8 @@ public: |
827 | 827 | if(mask == NULL || mask[xy] != 0){ //if the pixel is valid |
828 | 828 | matrix[i*Z() + b] = band_image[xy]; //copy it to the appropriate point in the values[] array |
829 | 829 | i++; |
830 | - //std::cout<<i<<std::endl; | |
831 | 830 | } |
832 | - | |
831 | + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100; | |
833 | 832 | } |
834 | 833 | } |
835 | 834 | ... | ... |
stim/envi/envi.h
... | ... | @@ -670,13 +670,13 @@ public: |
670 | 670 | /// using the following indexing: i = b*P + p |
671 | 671 | /// @param matrix is the destination for the pixel data |
672 | 672 | /// @param p is the mask |
673 | - bool sift(void* matrix, unsigned char* p = NULL){ | |
673 | + bool sift(void* matrix, unsigned char* p = NULL, bool PROGRESS = false){ | |
674 | 674 | |
675 | 675 | if (header.interleave == envi_header::BSQ){ //if the infile is bsq file |
676 | 676 | if (header.data_type == envi_header::float32) |
677 | - return ((bsq<float>*)file)->sift((float*)matrix, p); | |
677 | + return ((bsq<float>*)file)->sift((float*)matrix, p, PROGRESS); | |
678 | 678 | else if (header.data_type == envi_header::float64) |
679 | - return ((bsq<double>*)file)->sift((double*)matrix, p); | |
679 | + return ((bsq<double>*)file)->sift((double*)matrix, p, PROGRESS); | |
680 | 680 | else{ |
681 | 681 | std::cout << "ERROR: unidentified data type" << std::endl; |
682 | 682 | exit(1); |
... | ... | @@ -685,9 +685,9 @@ public: |
685 | 685 | |
686 | 686 | if (header.interleave == envi_header::BIP){ |
687 | 687 | if (header.data_type == envi_header::float32) |
688 | - return ((bip<float>*)file)->sift((float*)matrix, p); | |
688 | + return ((bip<float>*)file)->sift((float*)matrix, p, PROGRESS); | |
689 | 689 | else if (header.data_type == envi_header::float64) |
690 | - return ((bip<double>*)file)->sift((double*)matrix, p); | |
690 | + return ((bip<double>*)file)->sift((double*)matrix, p, PROGRESS); | |
691 | 691 | else{ |
692 | 692 | std::cout << "ERROR: unidentified data type" << std::endl; |
693 | 693 | exit(1); |
... | ... | @@ -695,9 +695,9 @@ public: |
695 | 695 | } |
696 | 696 | if (header.interleave == envi_header::BIL){ |
697 | 697 | if (header.data_type == envi_header::float32) |
698 | - return ((bil<float>*)file)->sift((float*)matrix, p); | |
698 | + return ((bil<float>*)file)->sift((float*)matrix, p, PROGRESS); | |
699 | 699 | else if (header.data_type == envi_header::float64) |
700 | - return ((bil<double>*)file)->sift((double*)matrix, p); | |
700 | + return ((bil<double>*)file)->sift((double*)matrix, p, PROGRESS); | |
701 | 701 | else{ |
702 | 702 | std::cout << "ERROR: unidentified data type" << std::endl; |
703 | 703 | exit(1); | ... | ... |
stim/image/image.h
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | #include <vector> |
7 | 7 | #include <iostream> |
8 | 8 | #include <limits> |
9 | +#include <typeinfo> | |
9 | 10 | |
10 | 11 | namespace stim{ |
11 | 12 | /// This static class provides the STIM interface for loading, saving, and storing 2D images. |
... | ... | @@ -24,8 +25,6 @@ class image{ |
24 | 25 | size_t Y() const { return R[2]; } |
25 | 26 | size_t C() const { return R[0]; } |
26 | 27 | |
27 | - size_t bytes(){ return size() * sizeof(T); } | |
28 | - | |
29 | 28 | void init(){ //initializes all variables, assumes no memory is allocated |
30 | 29 | memset(R, 0, sizeof(size_t) * 3); //set the resolution and number of channels to zero |
31 | 30 | img = NULL; |
... | ... | @@ -33,7 +32,6 @@ class image{ |
33 | 32 | |
34 | 33 | void unalloc(){ //frees any resources associated with the image |
35 | 34 | if(img) free(img); //if memory has been allocated, free it |
36 | - img=NULL; | |
37 | 35 | } |
38 | 36 | |
39 | 37 | |
... | ... | @@ -44,16 +42,15 @@ class image{ |
44 | 42 | |
45 | 43 | void allocate(){ |
46 | 44 | unalloc(); |
47 | - img = (T*) malloc( bytes() ); //allocate memory | |
48 | - memset(img, 0, bytes()); | |
45 | + img = (T*) malloc( sizeof(T) * R[0] * R[1] * R[2] ); //allocate memory | |
49 | 46 | } |
50 | 47 | |
51 | 48 | void allocate(size_t x, size_t y, size_t c){ //allocate memory based on the resolution |
52 | - unalloc(); | |
53 | 49 | R[0] = c; R[1] = x; R[2] = y; //set the resolution |
54 | 50 | allocate(); //allocate memory |
55 | 51 | } |
56 | 52 | |
53 | + size_t bytes(){ return size() * sizeof(T); } | |
57 | 54 | |
58 | 55 | size_t idx(size_t x, size_t y, size_t c = 0){ |
59 | 56 | return y * C() * X() + x * C() + c; |
... | ... | @@ -61,13 +58,23 @@ class image{ |
61 | 58 | |
62 | 59 | |
63 | 60 | int cv_type(){ |
64 | - if(std::is_same<T, unsigned char>::value) return CV_MAKETYPE(CV_8U, (int)C()); | |
65 | - if(std::is_same<T, char>::value) return CV_MAKETYPE(CV_8S, (int)C()); | |
66 | - if(std::is_same<T, unsigned short>::value) return CV_MAKETYPE(CV_16U, (int)C()); | |
67 | - if(std::is_same<T, short>::value) return CV_MAKETYPE(CV_16S, (int)C()); | |
68 | - if(std::is_same<T, int>::value) return CV_MAKETYPE(CV_32S, (int)C()); | |
69 | - if(std::is_same<T, float>::value) return CV_MAKETYPE(CV_32F, (int)C()); | |
70 | - if(std::is_same<T, double>::value) return CV_MAKETYPE(CV_64F, (int)C()); | |
61 | + // The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution | |
62 | + | |
63 | + //if(std::is_same<T, unsigned char>::value) return CV_MAKETYPE(CV_8U, (int)C()); | |
64 | + //if(std::is_same<T, char>::value) return CV_MAKETYPE(CV_8S, (int)C()); | |
65 | + //if(std::is_same<T, unsigned short>::value) return CV_MAKETYPE(CV_16U, (int)C()); | |
66 | + //if(std::is_same<T, short>::value) return CV_MAKETYPE(CV_16S, (int)C()); | |
67 | + //if(std::is_same<T, int>::value) return CV_MAKETYPE(CV_32S, (int)C()); | |
68 | + //if(std::is_same<T, float>::value) return CV_MAKETYPE(CV_32F, (int)C()); | |
69 | + //if(std::is_same<T, double>::value) return CV_MAKETYPE(CV_64F, (int)C()); | |
70 | + | |
71 | + if(typeid(T) == typeid(unsigned char)) return CV_MAKETYPE(CV_8U, (int)C()); | |
72 | + if(typeid(T) == typeid(char)) return CV_MAKETYPE(CV_8S, (int)C()); | |
73 | + if(typeid(T) == typeid(unsigned short)) return CV_MAKETYPE(CV_16U, (int)C()); | |
74 | + if(typeid(T) == typeid(short)) return CV_MAKETYPE(CV_16S, (int)C()); | |
75 | + if(typeid(T) == typeid(int)) return CV_MAKETYPE(CV_32S, (int)C()); | |
76 | + if(typeid(T) == typeid(float)) return CV_MAKETYPE(CV_32F, (int)C()); | |
77 | + if(typeid(T) == typeid(double)) return CV_MAKETYPE(CV_64F, (int)C()); | |
71 | 78 | |
72 | 79 | std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl; |
73 | 80 | exit(1); |
... | ... | @@ -75,15 +82,26 @@ class image{ |
75 | 82 | |
76 | 83 | /// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images) |
77 | 84 | T white(){ |
78 | - if(std::is_same<T, unsigned char>::value) return UCHAR_MAX; | |
79 | - if(std::is_same<T, unsigned short>::value) return SHRT_MAX; | |
80 | - if(std::is_same<T, unsigned>::value) return UINT_MAX; | |
81 | - if(std::is_same<T, unsigned long>::value) return ULONG_MAX; | |
82 | - if(std::is_same<T, unsigned long long>::value) return ULLONG_MAX; | |
83 | - if(std::is_same<T, float>::value) return 1.0f; | |
84 | - if(std::is_same<T, double>::value) return 1.0; | |
85 | + // The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution | |
86 | + | |
87 | + //if(std::is_same<T, unsigned char>::value) return UCHAR_MAX; | |
88 | + //if(std::is_same<T, unsigned short>::value) return SHRT_MAX; | |
89 | + //if(std::is_same<T, unsigned>::value) return UINT_MAX; | |
90 | + //if(std::is_same<T, unsigned long>::value) return ULONG_MAX; | |
91 | + //if(std::is_same<T, unsigned long long>::value) return ULLONG_MAX; | |
92 | + //if(std::is_same<T, float>::value) return 1.0f; | |
93 | + //if(std::is_same<T, double>::value) return 1.0; | |
94 | + | |
95 | + if(typeid(T) == typeid(unsigned char)) return UCHAR_MAX; | |
96 | + if(typeid(T) == typeid(unsigned short)) return SHRT_MAX; | |
97 | + if(typeid(T) == typeid(unsigned)) return UINT_MAX; | |
98 | + if(typeid(T) == typeid(unsigned long)) return ULONG_MAX; | |
99 | + if(typeid(T) == typeid(unsigned long long)) return ULLONG_MAX; | |
100 | + if(typeid(T) == typeid(float)) return 1.0f; | |
101 | + if(typeid(T) == typeid(double)) return 1.0; | |
85 | 102 | |
86 | 103 | std::cout<<"ERROR in stim::image::white - no white value known for this data type"<<std::endl; |
104 | + exit(1); | |
87 | 105 | |
88 | 106 | } |
89 | 107 | |
... | ... | @@ -91,9 +109,7 @@ class image{ |
91 | 109 | public: |
92 | 110 | |
93 | 111 | /// Default constructor - creates an empty image object |
94 | - image(){ | |
95 | - init(); //initialize all variables to zero, don't allocate any memory | |
96 | - } | |
112 | + image(){ init(); } //initialize all variables to zero, don't allocate any memory | |
97 | 113 | |
98 | 114 | /// Constructor with a filename - loads the specified file |
99 | 115 | image(std::string filename){ //constructor initialize the image with an image file |
... | ... | @@ -115,7 +131,7 @@ public: |
115 | 131 | } |
116 | 132 | |
117 | 133 | /// Copy constructor - duplicates an image object |
118 | - image(const stim::image<T> &I){ | |
134 | + image(const stim::image<T>& I){ | |
119 | 135 | init(); |
120 | 136 | allocate(I.X(), I.Y(), I.C()); |
121 | 137 | memcpy(img, I.img, bytes()); |
... | ... | @@ -127,6 +143,7 @@ public: |
127 | 143 | } |
128 | 144 | |
129 | 145 | stim::image<T>& operator=(const stim::image<T>& I){ |
146 | + init(); | |
130 | 147 | if(&I == this) //handle self-assignment |
131 | 148 | return *this; |
132 | 149 | allocate(I.X(), I.Y(), I.C()); |
... | ... | @@ -139,22 +156,15 @@ public: |
139 | 156 | |
140 | 157 | cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); //use OpenCV to open the image file |
141 | 158 | if(!cvImage.data){ |
142 | - std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<" ["<<__FILE__<<" (line "<<__LINE__<<")]"<<std::endl; | |
159 | + std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl; | |
143 | 160 | exit(1); |
144 | 161 | } |
145 | 162 | allocate(cvImage.cols, cvImage.rows, cvImage.channels()); //allocate space for the image |
146 | - T* cv_ptr = (T*) cvImage.data; | |
147 | - if(C() == 1) | |
148 | - { | |
149 | - //if this is a single-color image, just copy the data | |
150 | - memcpy(img, cv_ptr, bytes()); | |
151 | - } | |
152 | - if(C() == 3) | |
153 | - { //if this is a 3-color image, OpenCV uses BGR interleaving | |
163 | + T* cv_ptr = (T*)cvImage.data; | |
164 | + if(C() == 1) //if this is a single-color image, just copy the data | |
165 | + memcpy(img, cv_ptr, bytes()); | |
166 | + if(C() == 3) //if this is a 3-color image, OpenCV uses BGR interleaving | |
154 | 167 | set_interleaved_bgr(cv_ptr, X(), Y()); |
155 | - } | |
156 | - | |
157 | - cvImage.release(); | |
158 | 168 | } |
159 | 169 | |
160 | 170 | //save a file |
... | ... | @@ -168,18 +178,16 @@ public: |
168 | 178 | get_interleaved_bgr(buffer); |
169 | 179 | cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer); |
170 | 180 | cv::imwrite(filename, cvImage); |
171 | - cvImage.release(); | |
172 | - free(buffer); | |
173 | 181 | } |
174 | 182 | |
175 | 183 | //create an image from an interleaved buffer |
176 | - void set_interleaved_rgb(T* buffer, size_t width, size_t height, size_t channels = 3){ | |
177 | - allocate(width, height, channels); | |
184 | + void set_interleaved_rgb(T* buffer, size_t width, size_t height){ | |
185 | + allocate(width, height, 3); | |
178 | 186 | memcpy(img, buffer, bytes()); |
179 | 187 | } |
180 | 188 | |
181 | - void set_interleaved_bgr(T* buffer, size_t width, size_t height, size_t channels = 3){ | |
182 | - allocate(width, height, channels); | |
189 | + void set_interleaved_bgr(T* buffer, size_t width, size_t height){ | |
190 | + allocate(width, height, 3); | |
183 | 191 | for(size_t c = 0; c < C(); c++){ //copy directly |
184 | 192 | for(size_t y = 0; y < Y(); y++){ |
185 | 193 | for(size_t x = 0; x < X(); x++){ |
... | ... | @@ -359,34 +367,6 @@ public: |
359 | 367 | |
360 | 368 | return r; //return the inverted image |
361 | 369 | } |
362 | - | |
363 | - /// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value | |
364 | - image<T> invert(){ | |
365 | - size_t N = size(); //calculate the total number of values in the image | |
366 | - image<T> r(X(), Y(), C()); //allocate space for the resulting image | |
367 | - T white_val = maxv(); | |
368 | - for(size_t n = 0; n < N; n++) | |
369 | - r.img[n] = white_val - img[n]; //perform the inversion | |
370 | - | |
371 | - return r; //return the inverted image | |
372 | - } | |
373 | - | |
374 | - ///crops the image from x1 to x0 and y1 to y0 and returns a new (smaller) image. | |
375 | - image<T> crop(int x0, int x1, int y0, int y1) | |
376 | - { | |
377 | - | |
378 | - image<T> ret(x1-x0, y1-y0, C()); | |
379 | - int newWidth = x1-x0; | |
380 | - int destidx, srcidx; | |
381 | - ///for each row, cut what amount of data from the original and put it into the new copy. | |
382 | - for(int i = 0; i < (y1-y0); i++) | |
383 | - { | |
384 | - destidx = i*newWidth*C(); ///destination index one per each row | |
385 | - srcidx = ((i+(y0))*X()+x0)*C(); ///source index, one per each row. | |
386 | - memcpy(&ret.img[destidx], &img[srcidx], sizeof(T)*newWidth*C()); | |
387 | - } | |
388 | - return ret; | |
389 | - } | |
390 | 370 | |
391 | 371 | image<T> srgb2lab(){ |
392 | 372 | std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl; |
... | ... | @@ -405,7 +385,6 @@ public: |
405 | 385 | exit(1); |
406 | 386 | } |
407 | 387 | |
408 | - | |
409 | 388 | // leila's code for non_interleaving data in 3D |
410 | 389 | //create an data set from an interleaved buffer |
411 | 390 | void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){ | ... | ... |
stim/math/bessel.h
... | ... | @@ -17,6 +17,11 @@ static complex<double> czero(0.0,0.0); |
17 | 17 | template< typename P > |
18 | 18 | P gamma(P x) |
19 | 19 | { |
20 | + const P EPS = numeric_limits<P>::epsilon(); | |
21 | + const P FPMIN_MAG = numeric_limits<P>::min(); | |
22 | + const P FPMIN = numeric_limits<P>::lowest(); | |
23 | + const P FPMAX = numeric_limits<P>::max(); | |
24 | + | |
20 | 25 | int i,k,m; |
21 | 26 | P ga,gr,r,z; |
22 | 27 | |
... | ... | @@ -47,7 +52,7 @@ P gamma(P x) |
47 | 52 | -0.54e-14, |
48 | 53 | 0.14e-14}; |
49 | 54 | |
50 | - if (x > 171.0) return 1e308; // This value is an overflow flag. | |
55 | + if (x > 171.0) return FPMAX; // This value is an overflow flag. | |
51 | 56 | if (x == (int)x) { |
52 | 57 | if (x > 0.0) { |
53 | 58 | ga = 1.0; // use factorial |
... | ... | @@ -56,7 +61,7 @@ P gamma(P x) |
56 | 61 | } |
57 | 62 | } |
58 | 63 | else |
59 | - ga = 1e308; | |
64 | + ga = FPMAX; | |
60 | 65 | } |
61 | 66 | else { |
62 | 67 | if (fabs(x) > 1.0) { |
... | ... | @@ -89,6 +94,11 @@ template<typename P> |
89 | 94 | int bessjy01a(P x,P &j0,P &j1,P &y0,P &y1, |
90 | 95 | P &j0p,P &j1p,P &y0p,P &y1p) |
91 | 96 | { |
97 | + const P EPS = numeric_limits<P>::epsilon(); | |
98 | + const P FPMIN_MAG = numeric_limits<P>::min(); | |
99 | + const P FPMIN = numeric_limits<P>::lowest(); | |
100 | + const P FPMAX = numeric_limits<P>::max(); | |
101 | + | |
92 | 102 | P x2,r,ec,w0,w1,r0,r1,cs0,cs1; |
93 | 103 | P cu,p0,q0,p1,q1,t1,t2; |
94 | 104 | int k,kz; |
... | ... | @@ -157,12 +167,12 @@ int bessjy01a(P x,P &j0,P &j1,P &y0,P &y1, |
157 | 167 | if (x == 0.0) { |
158 | 168 | j0 = 1.0; |
159 | 169 | j1 = 0.0; |
160 | - y0 = -1e308; | |
161 | - y1 = -1e308; | |
170 | + y0 = -FPMIN; | |
171 | + y1 = -FPMIN; | |
162 | 172 | j0p = 0.0; |
163 | 173 | j1p = 0.5; |
164 | - y0p = 1e308; | |
165 | - y1p = 1e308; | |
174 | + y0p = FPMAX; | |
175 | + y1p = FPMAX; | |
166 | 176 | return 0; |
167 | 177 | } |
168 | 178 | x2 = x*x; |
... | ... | @@ -329,7 +339,7 @@ int msta1(P x,int mp) |
329 | 339 | for (i=0;i<20;i++) { |
330 | 340 | nn = (int)(n1-(n1-n0)/(1.0-f0/f1)); |
331 | 341 | f = 0.5*log10(6.28*nn)-nn*log10(1.36*a0/nn)-mp; |
332 | - if (abs(nn-n1) < 1) break; | |
342 | + if (std::abs(nn-n1) < 1) break; | |
333 | 343 | n0 = n1; |
334 | 344 | f0 = f1; |
335 | 345 | n1 = nn; |
... | ... | @@ -361,7 +371,7 @@ int msta2(P x,int n,int mp) |
361 | 371 | for (i=0;i<20;i++) { |
362 | 372 | nn = (int)(n1-(n1-n0)/(1.0-f0/f1)); |
363 | 373 | f = 0.5*log10(6.28*nn)-nn*log10(1.36*a0/nn)-obj; |
364 | - if (abs(nn-n1) < 1) break; | |
374 | + if (std::abs(nn-n1) < 1) break; | |
365 | 375 | n0 = n1; |
366 | 376 | f0 = f1; |
367 | 377 | n1 = nn; |
... | ... | @@ -596,21 +606,26 @@ int bessjyv(P v,P x,P &vm,P *jv,P *yv, |
596 | 606 | P b,ec,w0,w1,bju0,bju1,pv0,pv1,byvk; |
597 | 607 | int j,k,l,m,n,kz; |
598 | 608 | |
609 | + const P EPS = numeric_limits<P>::epsilon(); | |
610 | + const P FPMIN_MAG = numeric_limits<P>::min(); | |
611 | + const P FPMIN = numeric_limits<P>::lowest(); | |
612 | + const P FPMAX = numeric_limits<P>::max(); | |
613 | + | |
599 | 614 | x2 = x*x; |
600 | 615 | n = (int)v; |
601 | 616 | v0 = v-n; |
602 | 617 | if ((x < 0.0) || (v < 0.0)) return 1; |
603 | - if (x < 1e-15) { | |
618 | + if (x < EPS) { | |
604 | 619 | for (k=0;k<=n;k++) { |
605 | 620 | jv[k] = 0.0; |
606 | - yv[k] = -1e308; | |
621 | + yv[k] = FPMIN; | |
607 | 622 | djv[k] = 0.0; |
608 | - dyv[k] = 1e308; | |
623 | + dyv[k] = FPMAX; | |
609 | 624 | if (v0 == 0.0) { |
610 | 625 | jv[0] = 1.0; |
611 | 626 | djv[1] = 0.5; |
612 | 627 | } |
613 | - else djv[0] = 1e308; | |
628 | + else djv[0] = FPMAX; | |
614 | 629 | } |
615 | 630 | vm = v; |
616 | 631 | return 0; |
... | ... | @@ -623,7 +638,7 @@ int bessjyv(P v,P x,P &vm,P *jv,P *yv, |
623 | 638 | for (k=1;k<=40;k++) { |
624 | 639 | r *= -0.25*x2/(k*(k+vl)); |
625 | 640 | bjvl += r; |
626 | - if (fabs(r) < fabs(bjvl)*1e-15) break; | |
641 | + if (fabs(r) < fabs(bjvl)*EPS) break; | |
627 | 642 | } |
628 | 643 | vg = 1.0 + vl; |
629 | 644 | a = pow(0.5*x,vl)/gamma(vg); |
... | ... | @@ -686,7 +701,7 @@ int bessjyv(P v,P x,P &vm,P *jv,P *yv, |
686 | 701 | if (m < n) n = m; |
687 | 702 | else m = msta2(x,n,15); |
688 | 703 | f2 = 0.0; |
689 | - f1 = 1.0e-100; | |
704 | + f1 = FPMIN_MAG; | |
690 | 705 | for (k=m;k>=0;k--) { |
691 | 706 | f = 2.0*(v0+k+1.0)*f1/x-f2; |
692 | 707 | if (k <= n) jv[k] = f; |
... | ... | @@ -763,20 +778,26 @@ int bessjyv(P v,P x,P &vm,P *jv,P *yv, |
763 | 778 | |
764 | 779 | template<typename P> |
765 | 780 | int bessjyv_sph(int v, P z, P &vm, P* cjv, |
766 | - P* cyv, P* cjvp, P* cyvp) | |
767 | -{ | |
781 | + P* cyv, P* cjvp, P* cyvp){ | |
782 | + | |
768 | 783 | //first, compute the bessel functions of fractional order |
769 | - bessjyv(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
784 | + bessjyv<P>(v + (P)0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
785 | + | |
786 | + if(z == 0){ //handle degenerate case of z = 0 | |
787 | + memset(cjv, 0, sizeof(P) * (v+1)); | |
788 | + cjv[0] = 1; | |
789 | + } | |
770 | 790 | |
771 | 791 | //iterate through each and scale |
772 | - for(int n = 0; n<=v; n++) | |
773 | - { | |
792 | + for(int n = 0; n<=v; n++){ | |
774 | 793 | |
775 | - cjv[n] = cjv[n] * sqrt(rtsPI/(z * 2.0)); | |
776 | - cyv[n] = cyv[n] * sqrt(rtsPI/(z * 2.0)); | |
794 | + if(z != 0){ //handle degenerate case of z = 0 | |
795 | + cjv[n] = cjv[n] * sqrt(stim::PI/(z * 2.0)); | |
796 | + cyv[n] = cyv[n] * sqrt(stim::PI/(z * 2.0)); | |
797 | + } | |
777 | 798 | |
778 | - cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(rtsPI / (z * 2.0)); | |
779 | - cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(rtsPI / (z * 2.0)); | |
799 | + cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(stim::PI / (z * 2.0)); | |
800 | + cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(stim::PI / (z * 2.0)); | |
780 | 801 | } |
781 | 802 | |
782 | 803 | return 0; |
... | ... | @@ -1237,7 +1258,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1237 | 1258 | P a0,v0,pv0,pv1,vl,ga,gb,vg,vv,w0,w1,ya0,yak,ya1,wa; |
1238 | 1259 | int j,n,k,kz,l,lb,lb0,m; |
1239 | 1260 | |
1240 | - a0 = abs(z); | |
1261 | + a0 = ::abs(z); | |
1241 | 1262 | z1 = z; |
1242 | 1263 | z2 = z*z; |
1243 | 1264 | n = (int)v; |
... | ... | @@ -1265,7 +1286,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1265 | 1286 | vm = v; |
1266 | 1287 | return 0; |
1267 | 1288 | } |
1268 | - if (real(z1) < 0.0) z1 = -z; | |
1289 | + if (::real(z1) < 0.0) z1 = -z; | |
1269 | 1290 | if (a0 <= 12.0) { |
1270 | 1291 | for (l=0;l<2;l++) { |
1271 | 1292 | vl = v0+l; |
... | ... | @@ -1274,7 +1295,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1274 | 1295 | for (k=1;k<=40;k++) { |
1275 | 1296 | cr *= -0.25*z2/(k*(k+vl)); |
1276 | 1297 | cjvl += cr; |
1277 | - if (abs(cr) < abs(cjvl)*eps) break; | |
1298 | + if (::abs(cr) < ::abs(cjvl)*eps) break; | |
1278 | 1299 | } |
1279 | 1300 | vg = 1.0 + vl; |
1280 | 1301 | ga = gamma(vg); |
... | ... | @@ -1327,7 +1348,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1327 | 1348 | for (k=1;k<=40;k++) { |
1328 | 1349 | cr *= -0.25*z2/(k*(k-vl)); |
1329 | 1350 | cjvl += cr; |
1330 | - if (abs(cr) < abs(cjvl)*eps) break; | |
1351 | + if (::abs(cr) < ::abs(cjvl)*eps) break; | |
1331 | 1352 | } |
1332 | 1353 | vg = 1.0-vl; |
1333 | 1354 | gb = gamma(vg); |
... | ... | @@ -1360,16 +1381,16 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1360 | 1381 | cyv1 = M_2_PI*(cec*cjv1-1.0/z1-0.25*z1*cs1); |
1361 | 1382 | } |
1362 | 1383 | } |
1363 | - if (real(z) < 0.0) { | |
1384 | + if (::real(z) < 0.0) { | |
1364 | 1385 | cfac0 = exp(pv0*cii); |
1365 | 1386 | cfac1 = exp(pv1*cii); |
1366 | - if (imag(z) < 0.0) { | |
1387 | + if (::imag(z) < 0.0) { | |
1367 | 1388 | cyv0 = cfac0*cyv0-(P)2.0*(complex<P>)cii*cos(pv0)*cjv0; |
1368 | 1389 | cyv1 = cfac1*cyv1-(P)2.0*(complex<P>)cii*cos(pv1)*cjv1; |
1369 | 1390 | cjv0 /= cfac0; |
1370 | 1391 | cjv1 /= cfac1; |
1371 | 1392 | } |
1372 | - else if (imag(z) > 0.0) { | |
1393 | + else if (::imag(z) > 0.0) { | |
1373 | 1394 | cyv0 = cyv0/cfac0+(P)2.0*(complex<P>)cii*cos(pv0)*cjv0; |
1374 | 1395 | cyv1 = cyv1/cfac1+(P)2.0*(complex<P>)cii*cos(pv1)*cjv1; |
1375 | 1396 | cjv0 *= cfac0; |
... | ... | @@ -1400,7 +1421,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1400 | 1421 | cf2 = cf1; |
1401 | 1422 | cf1 = cf; |
1402 | 1423 | } |
1403 | - if (abs(cjv0) > abs(cjv1)) cs = cjv0/cf; | |
1424 | + if (::abs(cjv0) > ::abs(cjv1)) cs = cjv0/cf; | |
1404 | 1425 | else cs = cjv1/cf2; |
1405 | 1426 | for (k=0;k<=n;k++) { |
1406 | 1427 | cjv[k] *= cs; |
... | ... | @@ -1412,21 +1433,21 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1412 | 1433 | } |
1413 | 1434 | cyv[0] = cyv0; |
1414 | 1435 | cyv[1] = cyv1; |
1415 | - ya0 = abs(cyv0); | |
1436 | + ya0 = ::abs(cyv0); | |
1416 | 1437 | lb = 0; |
1417 | 1438 | cg0 = cyv0; |
1418 | 1439 | cg1 = cyv1; |
1419 | 1440 | for (k=2;k<=n;k++) { |
1420 | 1441 | cyk = 2.0*(v0+k-1.0)*cg1/z-cg0; |
1421 | - yak = abs(cyk); | |
1422 | - ya1 = abs(cg0); | |
1442 | + yak = ::abs(cyk); | |
1443 | + ya1 = ::abs(cg0); | |
1423 | 1444 | if ((yak < ya0) && (yak< ya1)) lb = k; |
1424 | 1445 | cyv[k] = cyk; |
1425 | 1446 | cg0 = cg1; |
1426 | 1447 | cg1 = cyk; |
1427 | 1448 | } |
1428 | 1449 | lb0 = 0; |
1429 | - if ((lb > 4) && (imag(z) != 0.0)) { | |
1450 | + if ((lb > 4) && (::imag(z) != 0.0)) { | |
1430 | 1451 | while(lb != lb0) { |
1431 | 1452 | ch2 = cone; |
1432 | 1453 | ch1 = czero; |
... | ... | @@ -1449,7 +1470,7 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1449 | 1470 | cp21 = ch2; |
1450 | 1471 | if (lb == n) |
1451 | 1472 | cjv[lb+1] = 2.0*(lb+v0)*cjv[lb]/z-cjv[lb-1]; |
1452 | - if (abs(cjv[0]) > abs(cjv[1])) { | |
1473 | + if (::abs(cjv[0]) > ::abs(cjv[1])) { | |
1453 | 1474 | cyv[lb+1] = (cjv[lb+1]*cyv0-2.0*cp11/(M_PI*z))/cjv[0]; |
1454 | 1475 | cyv[lb] = (cjv[lb]*cyv0+2.0*cp12/(M_PI*z))/cjv[0]; |
1455 | 1476 | } |
... | ... | @@ -1474,8 +1495,8 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1474 | 1495 | cyl2 = cylk; |
1475 | 1496 | } |
1476 | 1497 | for (k=2;k<=n;k++) { |
1477 | - wa = abs(cyv[k]); | |
1478 | - if (wa < abs(cyv[k-1])) lb = k; | |
1498 | + wa = ::abs(cyv[k]); | |
1499 | + if (wa < ::abs(cyv[k-1])) lb = k; | |
1479 | 1500 | } |
1480 | 1501 | } |
1481 | 1502 | } |
... | ... | @@ -1494,15 +1515,21 @@ int cbessjyva_sph(int v,complex<P> z,P &vm,complex<P>*cjv, |
1494 | 1515 | //first, compute the bessel functions of fractional order |
1495 | 1516 | cbessjyva<P>(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); |
1496 | 1517 | |
1518 | + if(z == 0){ //handle degenerate case of z = 0 | |
1519 | + memset(cjv, 0, sizeof(P) * (v+1)); | |
1520 | + cjv[0] = 1; | |
1521 | + } | |
1522 | + | |
1497 | 1523 | //iterate through each and scale |
1498 | 1524 | for(int n = 0; n<=v; n++) |
1499 | 1525 | { |
1526 | + if(z != 0){ //handle degenerate case of z = 0 | |
1527 | + cjv[n] = cjv[n] * sqrt(stim::PI/(z * 2.0)); | |
1528 | + cyv[n] = cyv[n] * sqrt(stim::PI/(z * 2.0)); | |
1529 | + } | |
1500 | 1530 | |
1501 | - cjv[n] = cjv[n] * sqrt(rtsPI/(z * 2.0)); | |
1502 | - cyv[n] = cyv[n] * sqrt(rtsPI/(z * 2.0)); | |
1503 | - | |
1504 | - cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(rtsPI / (z * 2.0)); | |
1505 | - cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(rtsPI / (z * 2.0)); | |
1531 | + cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(stim::PI / (z * 2.0)); | |
1532 | + cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(stim::PI / (z * 2.0)); | |
1506 | 1533 | } |
1507 | 1534 | |
1508 | 1535 | return 0; | ... | ... |
stim/math/circle.h
... | ... | @@ -17,7 +17,7 @@ class circle : plane<T> |
17 | 17 | |
18 | 18 | private: |
19 | 19 | |
20 | - stim::vec<T> Y; | |
20 | + stim::vec3<T> Y; | |
21 | 21 | |
22 | 22 | CUDA_CALLABLE void |
23 | 23 | init() |
... | ... | @@ -48,7 +48,7 @@ public: |
48 | 48 | circle(T size, T z_pos = (T)0) : plane<T>() |
49 | 49 | { |
50 | 50 | init(); |
51 | - center(stim::vec<T>(0,0,z_pos)); | |
51 | + center(stim::vec3<T>(0,0,z_pos)); | |
52 | 52 | scale(size); |
53 | 53 | } |
54 | 54 | |
... | ... | @@ -56,7 +56,7 @@ public: |
56 | 56 | ///@param c: x,y,z location of the center. |
57 | 57 | ///@param n: x,y,z direction of the normal. |
58 | 58 | CUDA_CALLABLE |
59 | - circle(vec<T> c, vec<T> n = vec<T>(0,0,1)) : plane<T>() | |
59 | + circle(vec3<T> c, vec3<T> n = vec3<T>(0,0,1)) : plane<T>() | |
60 | 60 | { |
61 | 61 | center(c); |
62 | 62 | normal(n); |
... | ... | @@ -68,7 +68,7 @@ public: |
68 | 68 | ///@param s: size of the rectangle. |
69 | 69 | ///@param n: x,y,z direction of the normal. |
70 | 70 | CUDA_CALLABLE |
71 | - circle(vec<T> c, T s, vec<T> n = vec<T>(0,0,1)) : plane<T>() | |
71 | + circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1)) : plane<T>() | |
72 | 72 | { |
73 | 73 | init(); |
74 | 74 | center(c); |
... | ... | @@ -82,7 +82,7 @@ public: |
82 | 82 | ///@param n: x,y,z direction of the normal. |
83 | 83 | ///@param u: x,y,z direction for the zero vector (from where the rotation starts) |
84 | 84 | CUDA_CALLABLE |
85 | - circle(vec<T> c, T s, vec<T> n = vec<T>(0,0,1), vec<T> u = vec<T>(1, 0, 0)) : plane<T>() | |
85 | + circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1), vec3<T> u = vec3<T>(1, 0, 0)) : plane<T>() | |
86 | 86 | { |
87 | 87 | init(); |
88 | 88 | setU(u); |
... | ... | @@ -103,16 +103,15 @@ public: |
103 | 103 | ///sets the normal for the cirlce |
104 | 104 | ///@param n: x,y,z direction of the normal. |
105 | 105 | CUDA_CALLABLE void |
106 | - normal(vec<T> n) | |
106 | + normal(vec3<T> n) | |
107 | 107 | { |
108 | 108 | rotate(n, Y); |
109 | 109 | } |
110 | 110 | |
111 | 111 | ///sets the center of the circle. |
112 | 112 | ///@param n: x,y,z location of the center. |
113 | - CUDA_CALLABLE T | |
114 | - center(vec<T> p) | |
115 | - { | |
113 | + CUDA_CALLABLE void | |
114 | + center(vec3<T> p){ | |
116 | 115 | this->P = p; |
117 | 116 | } |
118 | 117 | |
... | ... | @@ -127,17 +126,17 @@ public: |
127 | 126 | } |
128 | 127 | |
129 | 128 | ///get the world space value given the planar coordinates a, b in [0, 1] |
130 | - CUDA_CALLABLE stim::vec<T> p(T a, T b) | |
129 | + CUDA_CALLABLE stim::vec3<T> p(T a, T b) | |
131 | 130 | { |
132 | - stim::vec<T> result; | |
131 | + stim::vec3<T> result; | |
133 | 132 | |
134 | - vec<T> A = this->P - this->U * (T)0.5 - Y * (T)0.5; | |
133 | + vec3<T> A = this->P - this->U * (T)0.5 - Y * (T)0.5; | |
135 | 134 | result = A + this->U * a + Y * b; |
136 | 135 | return result; |
137 | 136 | } |
138 | 137 | |
139 | 138 | ///parenthesis operator returns the world space given rectangular coordinates a and b in [0 1] |
140 | - CUDA_CALLABLE stim::vec<T> operator()(T a, T b) | |
139 | + CUDA_CALLABLE stim::vec3<T> operator()(T a, T b) | |
141 | 140 | { |
142 | 141 | return p(a,b); |
143 | 142 | } |
... | ... | @@ -145,11 +144,11 @@ public: |
145 | 144 | ///returns a vector with the points on the initialized circle. |
146 | 145 | ///connecting the points results in a circle. |
147 | 146 | ///@param n: integer for the number of points representing the circle. |
148 | - std::vector<stim::vec<T> > | |
147 | + std::vector<stim::vec3<T> > | |
149 | 148 | getPoints(int n) |
150 | 149 | { |
151 | - std::vector<stim::vec<T> > result; | |
152 | - stim::vec<T> point; | |
150 | + std::vector<stim::vec3<T> > result; | |
151 | + stim::vec3<T> point; | |
153 | 152 | T x,y; |
154 | 153 | float step = 360.0/(float) n; |
155 | 154 | for(float j = 0; j <= 360.0; j += step) |
... | ... | @@ -164,7 +163,7 @@ public: |
164 | 163 | ///returns a vector with the points on the initialized circle. |
165 | 164 | ///connecting the points results in a circle. |
166 | 165 | ///@param n: integer for the number of points representing the circle. |
167 | - stim::vec<T> | |
166 | + stim::vec3<T> | |
168 | 167 | p(T theta) |
169 | 168 | { |
170 | 169 | T x,y; | ... | ... |
stim/math/complex.h
1 | -/*RTS Complex number class. This class is CUDA compatible, | |
2 | -and can therefore be used in CUDA code and on CUDA devices. | |
3 | -*/ | |
1 | +/// CUDA compatible complex number class | |
4 | 2 | |
5 | -#ifndef RTS_COMPLEX | |
6 | -#define RTS_COMPLEX | |
3 | +#ifndef STIM_COMPLEX | |
4 | +#define STIM_COMPLEX | |
7 | 5 | |
8 | -#include "../cuda/callable.h" | |
6 | +#include "../cuda/cudatools/callable.h" | |
9 | 7 | #include <cmath> |
10 | 8 | #include <string> |
11 | 9 | #include <sstream> |
... | ... | @@ -13,6 +11,7 @@ and can therefore be used in CUDA code and on CUDA devices. |
13 | 11 | |
14 | 12 | namespace stim |
15 | 13 | { |
14 | + enum complexComponentType {complexReal, complexImaginary, complexMag}; | |
16 | 15 | |
17 | 16 | template <class T> |
18 | 17 | struct complex |
... | ... | @@ -230,12 +229,6 @@ struct complex |
230 | 229 | return result; |
231 | 230 | } |
232 | 231 | |
233 | - /*CUDA_CALLABLE complex<T> pow(int y) | |
234 | - { | |
235 | - | |
236 | - return pow((double)y); | |
237 | - }*/ | |
238 | - | |
239 | 232 | CUDA_CALLABLE complex<T> pow(T y) |
240 | 233 | { |
241 | 234 | complex<T> result; |
... | ... | @@ -328,8 +321,31 @@ struct complex |
328 | 321 | return *this; |
329 | 322 | } |
330 | 323 | |
324 | + | |
325 | + | |
331 | 326 | }; |
332 | 327 | |
328 | +/// Cast an array of complex values to an array of real values | |
329 | +template<typename T> | |
330 | +static void real(T* r, complex<T>* c, size_t n){ | |
331 | + for(size_t i = 0; i < n; i++) | |
332 | + r[i] = c[i].real(); | |
333 | +} | |
334 | + | |
335 | +/// Cast an array of complex values to an array of real values | |
336 | +template<typename T> | |
337 | +static void imag(T* r, complex<T>* c, size_t n){ | |
338 | + for(size_t i = 0; i < n; i++) | |
339 | + r[i] = c[i].imag(); | |
340 | +} | |
341 | + | |
342 | +/// Calculate the magnitude of an array of complex values | |
343 | +template<typename T> | |
344 | +static void abs(T* m, complex<T>* c, size_t n){ | |
345 | + for(size_t i = 0; i < n; i++) | |
346 | + m[i] = c[i].abs(); | |
347 | +} | |
348 | + | |
333 | 349 | } //end RTS namespace |
334 | 350 | |
335 | 351 | //addition |
... | ... | @@ -432,17 +448,6 @@ CUDA_CALLABLE static T imag(stim::complex<T> a) |
432 | 448 | return a.i; |
433 | 449 | } |
434 | 450 | |
435 | -//trigonometric functions | |
436 | -//template<class A> | |
437 | -/*CUDA_CALLABLE static stim::complex<float> sinf(const stim::complex<float> x) | |
438 | -{ | |
439 | - stim::complex<float> result; | |
440 | - result.r = sinf(x.r) * coshf(x.i); | |
441 | - result.i = cosf(x.r) * sinhf(x.i); | |
442 | - | |
443 | - return result; | |
444 | -}*/ | |
445 | - | |
446 | 451 | template<class A> |
447 | 452 | CUDA_CALLABLE stim::complex<A> sin(const stim::complex<A> x) |
448 | 453 | { |
... | ... | @@ -453,17 +458,6 @@ CUDA_CALLABLE stim::complex<A> sin(const stim::complex<A> x) |
453 | 458 | return result; |
454 | 459 | } |
455 | 460 | |
456 | -//floating point template | |
457 | -//template<class A> | |
458 | -/*CUDA_CALLABLE static stim::complex<float> cosf(const stim::complex<float> x) | |
459 | -{ | |
460 | - stim::complex<float> result; | |
461 | - result.r = cosf(x.r) * coshf(x.i); | |
462 | - result.i = -(sinf(x.r) * sinhf(x.i)); | |
463 | - | |
464 | - return result; | |
465 | -}*/ | |
466 | - | |
467 | 461 | template<class A> |
468 | 462 | CUDA_CALLABLE stim::complex<A> cos(const stim::complex<A> x) |
469 | 463 | { |
... | ... | @@ -496,10 +490,4 @@ std::istream& operator>>(std::istream& is, stim::complex<A>& x) |
496 | 490 | return is; //return the stream |
497 | 491 | } |
498 | 492 | |
499 | -//#if __GNUC__ > 3 && __GNUC_MINOR__ > 7 | |
500 | -//template<class T> using rtsComplex = stim::complex<T>; | |
501 | -//#endif | |
502 | - | |
503 | - | |
504 | - | |
505 | 493 | #endif | ... | ... |
stim/math/constants.h
1 | -#ifndef RTS_CONSTANTS_H | |
2 | -#define RTS_CONSTANTS_H | |
1 | +#ifndef STIM_CONSTANTS_H | |
2 | +#define STIM_CONSTANTS_H | |
3 | 3 | |
4 | -#define stimPI 3.14159 | |
5 | -#define stimTAU 2 * rtsPI | |
4 | +#include "stim/cuda/cudatools/callable.h" | |
5 | +namespace stim{ | |
6 | + const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862; | |
7 | + const double TAU = 2 * stim::PI; | |
8 | +} | |
6 | 9 | |
7 | 10 | #endif | ... | ... |
1 | +#ifndef STIM_FFT_H | |
2 | +#define STIM_FFT_H | |
3 | + | |
4 | +namespace stim{ | |
5 | + | |
6 | + template<class T> | |
7 | + void circshift(T *out, const T *in, size_t xdim, size_t ydim, size_t xshift, size_t yshift){ | |
8 | + size_t i, j, ii, jj; | |
9 | + for (i =0; i < xdim; i++) { | |
10 | + ii = (i + xshift) % xdim; | |
11 | + for (j = 0; j < ydim; j++) { | |
12 | + jj = (j + yshift) % ydim; | |
13 | + out[ii * ydim + jj] = in[i * ydim + j]; | |
14 | + } | |
15 | + } | |
16 | + } | |
17 | + | |
18 | + template<typename T> | |
19 | + void cpu_fftshift(T* out, T* in, size_t xdim, size_t ydim){ | |
20 | + circshift(out, in, xdim, ydim, xdim/2, ydim/2); | |
21 | + } | |
22 | + | |
23 | + template<typename T> | |
24 | + void cpu_ifftshift(T* out, T* in, size_t xdim, size_t ydim){ | |
25 | + circshift(out, in, xdim, ydim, xdim/2, ydim/2); | |
26 | + } | |
27 | + | |
28 | + | |
29 | +} | |
30 | + | |
31 | +#endif | |
0 | 32 | \ No newline at end of file | ... | ... |
stim/math/legendre.h
1 | 1 | #ifndef RTS_LEGENDRE_H |
2 | 2 | #define RTS_LEGENDRE_H |
3 | 3 | |
4 | -#include "rts/cuda/callable.h" | |
4 | +#include "../cuda/cudatools/callable.h" | |
5 | 5 | |
6 | 6 | namespace stim{ |
7 | 7 | |
... | ... | @@ -24,9 +24,11 @@ CUDA_CALLABLE void shift_legendre(int n, T x, T& P0, T& P1) |
24 | 24 | P1 = Pnew; |
25 | 25 | } |
26 | 26 | |
27 | +/// Iteratively evaluates the Legendre polynomials for orders l = [0 n] | |
27 | 28 | template <typename T> |
28 | 29 | CUDA_CALLABLE void legendre(int n, T x, T* P) |
29 | 30 | { |
31 | + if(n < 0) return; | |
30 | 32 | P[0] = 1; |
31 | 33 | |
32 | 34 | if(n >= 1) | ... | ... |
stim/math/matrix.h
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | #include <string.h> |
6 | 6 | #include <iostream> |
7 | 7 | #include <stim/math/vector.h> |
8 | +#include <stim/math/vec3.h> | |
8 | 9 | #include <stim/cuda/cudatools/callable.h> |
9 | 10 | |
10 | 11 | namespace stim{ |
... | ... | @@ -50,10 +51,8 @@ struct matrix |
50 | 51 | return *this; |
51 | 52 | } |
52 | 53 | |
53 | - | |
54 | 54 | template<typename Y> |
55 | - CUDA_CALLABLE vec<Y> operator*(vec<Y> rhs) | |
56 | - { | |
55 | + vec<Y> operator*(vec<Y> rhs){ | |
57 | 56 | unsigned int N = rhs.size(); |
58 | 57 | |
59 | 58 | vec<Y> result; |
... | ... | @@ -66,6 +65,16 @@ struct matrix |
66 | 65 | return result; |
67 | 66 | } |
68 | 67 | |
68 | + template<typename Y> | |
69 | + CUDA_CALLABLE vec3<Y> operator*(vec3<Y> rhs){ | |
70 | + vec3<Y> result = 0; | |
71 | + for(int r=0; r<3; r++) | |
72 | + for(int c=0; c<3; c++) | |
73 | + result[r] += (*this)(r, c) * rhs[c]; | |
74 | + | |
75 | + return result; | |
76 | + } | |
77 | + | |
69 | 78 | std::string toStr() |
70 | 79 | { |
71 | 80 | std::stringstream ss; |
... | ... | @@ -82,10 +91,6 @@ struct matrix |
82 | 91 | |
83 | 92 | return ss.str(); |
84 | 93 | } |
85 | - | |
86 | - | |
87 | - | |
88 | - | |
89 | 94 | }; |
90 | 95 | |
91 | 96 | } //end namespace rts | ... | ... |
1 | +#ifndef STIM_MESHGRID_H | |
2 | +#define STIM_MESHGRID_H | |
3 | + | |
4 | +namespace stim{ | |
5 | + | |
6 | + /// Create a 2D grid based on a pair of vectors representing the grid spacing (see Matlab) | |
7 | + /// @param X is an [nx x ny] array that will store the X coordinates for each 2D point | |
8 | + /// @param Y is an [nx x ny] array that will store the Y coordinates for each 2D point | |
9 | + /// @param x is an [nx] array that provides the positions of grid points in the x direction | |
10 | + /// @param nx is the number of grid points in the x direction | |
11 | + /// @param y is an [ny] array that provides the positions of grid points in the y direction | |
12 | + /// @param ny is the number of grid points in the y direction | |
13 | + template<typename T> | |
14 | + void meshgrid(T* X, T* Y, T* x, size_t nx, T* y, size_t ny){ | |
15 | + size_t xi, yi; //allocate index variables | |
16 | + for(yi = 0; yi < ny; yi++){ //iterate through each column | |
17 | + for(xi = 0; xi < nx; xi++){ //iterate through each row | |
18 | + X[yi * nx + xi] = x[xi]; | |
19 | + Y[yi * nx + xi] = y[yi]; | |
20 | + } | |
21 | + } | |
22 | + } | |
23 | + | |
24 | + /// Creates an array of n equally spaced values in the range [xmin xmax] | |
25 | + /// @param X is an array of length n that stores the values | |
26 | + /// @param xmin is the start point of the array | |
27 | + /// @param xmax is the end point of the array | |
28 | + /// @param n is the number of points in the array | |
29 | + template<typename T> | |
30 | + void linspace(T* X, T xmin, T xmax, size_t n){ | |
31 | + T alpha; | |
32 | + for(size_t i = 0; i < n; i++){ | |
33 | + alpha = (T)i / (T)n; | |
34 | + X[i] = (1 - alpha) * xmin + alpha * xmax; | |
35 | + } | |
36 | + } | |
37 | + | |
38 | + | |
39 | +} | |
40 | + | |
41 | + | |
42 | +#endif | |
0 | 43 | \ No newline at end of file | ... | ... |
stim/math/plane.h
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | #define STIM_PLANE_H |
3 | 3 | |
4 | 4 | #include <iostream> |
5 | -#include <stim/math/vector.h> | |
5 | +#include <stim/math/vec3.h> | |
6 | 6 | #include <stim/cuda/cudatools/callable.h> |
7 | 7 | #include <stim/math/quaternion.h> |
8 | 8 | |
... | ... | @@ -22,17 +22,17 @@ template <typename T> |
22 | 22 | class plane |
23 | 23 | { |
24 | 24 | protected: |
25 | - stim::vec<T> P; | |
26 | - stim::vec<T> N; | |
27 | - stim::vec<T> U; | |
25 | + stim::vec3<T> P; | |
26 | + stim::vec3<T> N; | |
27 | + stim::vec3<T> U; | |
28 | 28 | |
29 | 29 | ///Initializes the plane with standard coordinates. |
30 | 30 | /// |
31 | 31 | CUDA_CALLABLE void init() |
32 | 32 | { |
33 | - P = stim::vec<T>(0, 0, 0); | |
34 | - N = stim::vec<T>(0, 0, 1); | |
35 | - U = stim::vec<T>(1, 0, 0); | |
33 | + P = stim::vec3<T>(0, 0, 0); | |
34 | + N = stim::vec3<T>(0, 0, 1); | |
35 | + U = stim::vec3<T>(1, 0, 0); | |
36 | 36 | } |
37 | 37 | |
38 | 38 | public: |
... | ... | @@ -42,7 +42,7 @@ class plane |
42 | 42 | init(); |
43 | 43 | } |
44 | 44 | |
45 | - CUDA_CALLABLE plane(vec<T> n, vec<T> p = vec<T>(0, 0, 0)) | |
45 | + CUDA_CALLABLE plane(vec3<T> n, vec3<T> p = vec3<T>(0, 0, 0)) | |
46 | 46 | { |
47 | 47 | init(); |
48 | 48 | P = p; |
... | ... | @@ -56,11 +56,11 @@ class plane |
56 | 56 | } |
57 | 57 | |
58 | 58 | //create a plane from three points (a triangle) |
59 | - CUDA_CALLABLE plane(vec<T> a, vec<T> b, vec<T> c) | |
59 | + CUDA_CALLABLE plane(vec3<T> a, vec3<T> b, vec3<T> c) | |
60 | 60 | { |
61 | 61 | init(); |
62 | 62 | P = c; |
63 | - stim::vec<T> n = (c - a).cross(b - a); | |
63 | + stim::vec3<T> n = (c - a).cross(b - a); | |
64 | 64 | try |
65 | 65 | { |
66 | 66 | if(n.len() != 0) |
... | ... | @@ -84,17 +84,17 @@ class plane |
84 | 84 | |
85 | 85 | } |
86 | 86 | |
87 | - CUDA_CALLABLE vec<T> n() | |
87 | + CUDA_CALLABLE vec3<T> n() | |
88 | 88 | { |
89 | 89 | return N; |
90 | 90 | } |
91 | 91 | |
92 | - CUDA_CALLABLE vec<T> p() | |
92 | + CUDA_CALLABLE vec3<T> p() | |
93 | 93 | { |
94 | 94 | return P; |
95 | 95 | } |
96 | 96 | |
97 | - CUDA_CALLABLE vec<T> u() | |
97 | + CUDA_CALLABLE vec3<T> u() | |
98 | 98 | { |
99 | 99 | return U; |
100 | 100 | } |
... | ... | @@ -107,7 +107,7 @@ class plane |
107 | 107 | } |
108 | 108 | |
109 | 109 | //determines how a vector v intersects the plane (1 = intersects front, 0 = within plane, -1 = intersects back) |
110 | - CUDA_CALLABLE int face(vec<T> v){ | |
110 | + CUDA_CALLABLE int face(vec3<T> v){ | |
111 | 111 | |
112 | 112 | T dprod = v.dot(N); //get the dot product between v and N |
113 | 113 | |
... | ... | @@ -121,46 +121,46 @@ class plane |
121 | 121 | } |
122 | 122 | |
123 | 123 | //determine on which side of the plane a point lies (1 = front, 0 = on the plane, -1 = bac k) |
124 | - CUDA_CALLABLE int side(vec<T> p){ | |
124 | + CUDA_CALLABLE int side(vec3<T> p){ | |
125 | 125 | |
126 | - vec<T> v = p - P; //get the vector from P to the query point p | |
126 | + vec3<T> v = p - P; //get the vector from P to the query point p | |
127 | 127 | |
128 | 128 | return face(v); |
129 | 129 | } |
130 | 130 | |
131 | 131 | //compute the component of v that is perpendicular to the plane |
132 | - CUDA_CALLABLE vec<T> perpendicular(vec<T> v){ | |
132 | + CUDA_CALLABLE vec3<T> perpendicular(vec3<T> v){ | |
133 | 133 | return N * v.dot(N); |
134 | 134 | } |
135 | 135 | |
136 | 136 | //compute the projection of v in the plane |
137 | - CUDA_CALLABLE vec<T> parallel(vec<T> v){ | |
137 | + CUDA_CALLABLE vec3<T> parallel(vec3<T> v){ | |
138 | 138 | return v - perpendicular(v); |
139 | 139 | } |
140 | 140 | |
141 | - CUDA_CALLABLE void setU(vec<T> v) | |
141 | + CUDA_CALLABLE void setU(vec3<T> v) | |
142 | 142 | { |
143 | 143 | U = (parallel(v.norm())).norm(); |
144 | 144 | } |
145 | 145 | |
146 | - CUDA_CALLABLE void decompose(vec<T> v, vec<T>& para, vec<T>& perp){ | |
146 | + CUDA_CALLABLE void decompose(vec3<T> v, vec3<T>& para, vec3<T>& perp){ | |
147 | 147 | perp = N * v.dot(N); |
148 | 148 | para = v - perp; |
149 | 149 | } |
150 | 150 | |
151 | 151 | //get both the parallel and perpendicular components of a vector v w.r.t. the plane |
152 | - CUDA_CALLABLE void project(vec<T> v, vec<T> &v_par, vec<T> &v_perp){ | |
152 | + CUDA_CALLABLE void project(vec3<T> v, vec3<T> &v_par, vec3<T> &v_perp){ | |
153 | 153 | |
154 | 154 | v_perp = v.dot(N); |
155 | 155 | v_par = v - v_perp; |
156 | 156 | } |
157 | 157 | |
158 | 158 | //compute the reflection of v off of the plane |
159 | - CUDA_CALLABLE vec<T> reflect(vec<T> v){ | |
159 | + CUDA_CALLABLE vec3<T> reflect(vec3<T> v){ | |
160 | 160 | |
161 | 161 | //compute the reflection using N_prime as the plane normal |
162 | - vec<T> par = parallel(v); | |
163 | - vec<T> r = (-v) + par * 2; | |
162 | + vec3<T> par = parallel(v); | |
163 | + vec3<T> r = (-v) + par * 2; | |
164 | 164 | return r; |
165 | 165 | |
166 | 166 | } |
... | ... | @@ -184,7 +184,7 @@ class plane |
184 | 184 | } |
185 | 185 | |
186 | 186 | |
187 | - CUDA_CALLABLE void rotate(vec<T> n) | |
187 | + CUDA_CALLABLE void rotate(vec3<T> n) | |
188 | 188 | { |
189 | 189 | quaternion<T> q; |
190 | 190 | q.CreateRotation(N, n); |
... | ... | @@ -194,7 +194,7 @@ class plane |
194 | 194 | |
195 | 195 | } |
196 | 196 | |
197 | - CUDA_CALLABLE void rotate(vec<T> n, vec<T> &Y) | |
197 | + CUDA_CALLABLE void rotate(vec3<T> n, vec3<T> &Y) | |
198 | 198 | { |
199 | 199 | quaternion<T> q; |
200 | 200 | q.CreateRotation(N, n); |
... | ... | @@ -205,7 +205,7 @@ class plane |
205 | 205 | |
206 | 206 | } |
207 | 207 | |
208 | - CUDA_CALLABLE void rotate(vec<T> n, vec<T> &X, vec<T> &Y) | |
208 | + CUDA_CALLABLE void rotate(vec3<T> n, vec3<T> &X, vec3<T> &Y) | |
209 | 209 | { |
210 | 210 | quaternion<T> q; |
211 | 211 | q.CreateRotation(N, n); | ... | ... |
stim/math/plane_old.h deleted
1 | -#ifndef RTS_PLANE_H | |
2 | -#define RTS_PLANE_H | |
3 | - | |
4 | -#include <iostream> | |
5 | -#include <stim/math/vector.h> | |
6 | -#include "rts/cuda/callable.h" | |
7 | - | |
8 | - | |
9 | -namespace stim{ | |
10 | -template <typename T, int D> class plane; | |
11 | -} | |
12 | - | |
13 | -template <typename T, int D> | |
14 | -CUDA_CALLABLE stim::plane<T, D> operator-(stim::plane<T, D> v); | |
15 | - | |
16 | -namespace stim{ | |
17 | - | |
18 | -template <class T, int D = 3> | |
19 | -class plane{ | |
20 | - | |
21 | - //a plane is defined by a point and a normal | |
22 | - | |
23 | -private: | |
24 | - | |
25 | - vec<T, D> P; //point on the plane | |
26 | - vec<T, D> N; //plane normal | |
27 | - | |
28 | - CUDA_CALLABLE void init(){ | |
29 | - P = vec<T, D>(0, 0, 0); | |
30 | - N = vec<T, D>(0, 0, 1); | |
31 | - } | |
32 | - | |
33 | - | |
34 | -public: | |
35 | - | |
36 | - //default constructor | |
37 | - CUDA_CALLABLE plane(){ | |
38 | - init(); | |
39 | - } | |
40 | - | |
41 | - CUDA_CALLABLE plane(vec<T, D> n, vec<T, D> p = vec<T, D>(0, 0, 0)){ | |
42 | - P = p; | |
43 | - N = n.norm(); | |
44 | - } | |
45 | - | |
46 | - CUDA_CALLABLE plane(T z_pos){ | |
47 | - init(); | |
48 | - P[2] = z_pos; | |
49 | - } | |
50 | - | |
51 | - //create a plane from three points (a triangle) | |
52 | - CUDA_CALLABLE plane(vec<T, D> a, vec<T, D> b, vec<T, D> c){ | |
53 | - P = c; | |
54 | - N = (c - a).cross(b - a); | |
55 | - if(N.len() == 0) //handle the degenerate case when two vectors are the same, N = 0 | |
56 | - N = 0; | |
57 | - else | |
58 | - N = N.norm(); | |
59 | - } | |
60 | - | |
61 | - template< typename U > | |
62 | - CUDA_CALLABLE operator plane<U, D>(){ | |
63 | - | |
64 | - plane<U, D> result(N, P); | |
65 | - return result; | |
66 | - } | |
67 | - | |
68 | - CUDA_CALLABLE vec<T, D> norm(){ | |
69 | - return N; | |
70 | - } | |
71 | - | |
72 | - CUDA_CALLABLE vec<T, D> p(){ | |
73 | - return P; | |
74 | - } | |
75 | - | |
76 | - //flip the plane front-to-back | |
77 | - CUDA_CALLABLE plane<T, D> flip(){ | |
78 | - plane<T, D> result = *this; | |
79 | - result.N = -result.N; | |
80 | - return result; | |
81 | - } | |
82 | - | |
83 | - //determines how a vector v intersects the plane (1 = intersects front, 0 = within plane, -1 = intersects back) | |
84 | - CUDA_CALLABLE int face(vec<T, D> v){ | |
85 | - | |
86 | - T dprod = v.dot(N); //get the dot product between v and N | |
87 | - | |
88 | - //conditional returns the appropriate value | |
89 | - if(dprod < 0) | |
90 | - return 1; | |
91 | - else if(dprod > 0) | |
92 | - return -1; | |
93 | - else | |
94 | - return 0; | |
95 | - } | |
96 | - | |
97 | - //determine on which side of the plane a point lies (1 = front, 0 = on the plane, -1 = back) | |
98 | - CUDA_CALLABLE int side(vec<T, D> p){ | |
99 | - | |
100 | - vec<T, D> v = p - P; //get the vector from P to the query point p | |
101 | - | |
102 | - return face(v); | |
103 | - } | |
104 | - | |
105 | - //compute the component of v that is perpendicular to the plane | |
106 | - CUDA_CALLABLE vec<T, D> perpendicular(vec<T, D> v){ | |
107 | - return N * v.dot(N); | |
108 | - } | |
109 | - | |
110 | - //compute the projection of v in the plane | |
111 | - CUDA_CALLABLE vec<T, D> parallel(vec<T, D> v){ | |
112 | - return v - perpendicular(v); | |
113 | - } | |
114 | - | |
115 | - CUDA_CALLABLE void decompose(vec<T, D> v, vec<T, D>& para, vec<T, D>& perp){ | |
116 | - perp = N * v.dot(N); | |
117 | - para = v - perp; | |
118 | - } | |
119 | - | |
120 | - //get both the parallel and perpendicular components of a vector v w.r.t. the plane | |
121 | - CUDA_CALLABLE void project(vec<T, D> v, vec<T, D> &v_par, vec<T, D> &v_perp){ | |
122 | - | |
123 | - v_perp = v.dot(N); | |
124 | - v_par = v - v_perp; | |
125 | - } | |
126 | - | |
127 | - //compute the reflection of v off of the plane | |
128 | - CUDA_CALLABLE vec<T, D> reflect(vec<T, D> v){ | |
129 | - | |
130 | - //compute the reflection using N_prime as the plane normal | |
131 | - vec<T, D> par = parallel(v); | |
132 | - vec<T, D> r = (-v) + par * 2; | |
133 | - | |
134 | - /*std::cout<<"----------------REFLECT-----------------------------"<<std::endl; | |
135 | - std::cout<<str()<<std::endl; | |
136 | - std::cout<<"v: "<<v<<std::endl; | |
137 | - std::cout<<"r: "<<r<<std::endl; | |
138 | - std::cout<<"Perpendicular: "<<perpendicular(v)<<std::endl; | |
139 | - std::cout<<"Parallel: "<<par<<std::endl;*/ | |
140 | - return r; | |
141 | - | |
142 | - } | |
143 | - | |
144 | - CUDA_CALLABLE rts::plane<T, D> operator-() | |
145 | - { | |
146 | - rts::plane<T, D> p = *this; | |
147 | - | |
148 | - //negate the normal vector | |
149 | - p.N = -p.N; | |
150 | - | |
151 | - return p; | |
152 | - } | |
153 | - | |
154 | - //output a string | |
155 | - std::string str(){ | |
156 | - std::stringstream ss; | |
157 | - ss<<"P: "<<P<<std::endl; | |
158 | - ss<<"N: "<<N; | |
159 | - return ss.str(); | |
160 | - } | |
161 | - | |
162 | - ///////Friendship | |
163 | - //friend CUDA_CALLABLE rts::plane<T, D> operator- <> (rts::plane<T, D> v); | |
164 | - | |
165 | - | |
166 | - | |
167 | -}; | |
168 | - | |
169 | -} | |
170 | - | |
171 | -//arithmetic operators | |
172 | - | |
173 | -//negative operator flips the plane (front to back) | |
174 | -//template <typename T, int D> | |
175 | - | |
176 | - | |
177 | - | |
178 | - | |
179 | -#endif |
stim/math/quad.h deleted
1 | -#ifndef RTS_QUAD_H | |
2 | -#define RTS_QUAD_H | |
3 | - | |
4 | -//enable CUDA_CALLABLE macro | |
5 | -#include <stim/cuda/callable.h> | |
6 | -#include <stim/math/vector.h> | |
7 | -#include <stim/math/triangle.h> | |
8 | -#include <stim/math/quaternion.h> | |
9 | -#include <iostream> | |
10 | -#include <iomanip> | |
11 | -#include <algorithm> | |
12 | - | |
13 | -namespace stim{ | |
14 | - | |
15 | -//template for a quadangle class in ND space | |
16 | -template <class T, int N = 3> | |
17 | -struct quad | |
18 | -{ | |
19 | - /* | |
20 | - B------------------>C | |
21 | - ^ ^ | |
22 | - | | | |
23 | - Y | | |
24 | - | | | |
25 | - | | | |
26 | - A---------X-------->O | |
27 | - */ | |
28 | - | |
29 | - /*T A[N]; | |
30 | - T B[N]; | |
31 | - T C[N];*/ | |
32 | - | |
33 | - rts::vec<T, N> A; | |
34 | - rts::vec<T, N> X; | |
35 | - rts::vec<T, N> Y; | |
36 | - | |
37 | - | |
38 | - CUDA_CALLABLE quad() | |
39 | - { | |
40 | - | |
41 | - } | |
42 | - | |
43 | - CUDA_CALLABLE quad(vec<T, N> a, vec<T, N> b, vec<T, N> c) | |
44 | - { | |
45 | - | |
46 | - A = a; | |
47 | - Y = b - a; | |
48 | - X = c - a - Y; | |
49 | - | |
50 | - } | |
51 | - | |
52 | - /******************************************************************* | |
53 | - Constructor - create a quad from a position, normal, and rotation | |
54 | - *******************************************************************/ | |
55 | - CUDA_CALLABLE quad(rts::vec<T, N> c, rts::vec<T, N> normal, T width, T height, T theta) | |
56 | - { | |
57 | - | |
58 | - //compute the X direction - start along world-space X | |
59 | - Y = rts::vec<T, N>(0, 1, 0); | |
60 | - if(Y == normal) | |
61 | - Y = rts::vec<T, N>(0, 0, 1); | |
62 | - | |
63 | - X = Y.cross(normal).norm(); | |
64 | - | |
65 | - std::cout<<X<<std::endl; | |
66 | - | |
67 | - //rotate the X axis by theta radians | |
68 | - rts::quaternion<T> q; | |
69 | - q.CreateRotation(theta, normal); | |
70 | - X = q.toMatrix3() * X; | |
71 | - Y = normal.cross(X); | |
72 | - | |
73 | - //normalize everything | |
74 | - X = X.norm(); | |
75 | - Y = Y.norm(); | |
76 | - | |
77 | - //scale to match the quad width and height | |
78 | - X = X * width; | |
79 | - Y = Y * height; | |
80 | - | |
81 | - //set the corner of the plane | |
82 | - A = c - X * 0.5f - Y * 0.5f; | |
83 | - | |
84 | - std::cout<<X<<std::endl; | |
85 | - } | |
86 | - | |
87 | - //boolean comparison | |
88 | - bool operator==(const quad<T, N> & rhs) | |
89 | - { | |
90 | - if(A == rhs.A && X == rhs.X && Y == rhs.Y) | |
91 | - return true; | |
92 | - else | |
93 | - return false; | |
94 | - } | |
95 | - | |
96 | - /******************************************* | |
97 | - Return the normal for the quad | |
98 | - *******************************************/ | |
99 | - CUDA_CALLABLE rts::vec<T, N> n() | |
100 | - { | |
101 | - return (X.cross(Y)).norm(); | |
102 | - } | |
103 | - | |
104 | - CUDA_CALLABLE rts::vec<T, N> p(T a, T b) | |
105 | - { | |
106 | - rts::vec<T, N> result; | |
107 | - //given the two parameters a, b = [0 1], returns the position in world space | |
108 | - result = A + X * a + Y * b; | |
109 | - | |
110 | - return result; | |
111 | - } | |
112 | - | |
113 | - CUDA_CALLABLE rts::vec<T, N> operator()(T a, T b) | |
114 | - { | |
115 | - return p(a, b); | |
116 | - } | |
117 | - | |
118 | - std::string str() | |
119 | - { | |
120 | - std::stringstream ss; | |
121 | - | |
122 | - ss<<std::left<<"B="<<setfill('-')<<setw(20)<<A + Y<<">"<<"C="<<A + Y + X<<std::endl; | |
123 | - ss<<setfill(' ')<<setw(23)<<"|"<<"|"<<std::endl<<setw(23)<<"|"<<"|"<<std::endl; | |
124 | - ss<<std::left<<"A="<<setfill('-')<<setw(20)<<A<<">"<<"D="<<A + X; | |
125 | - | |
126 | - return ss.str(); | |
127 | - | |
128 | - } | |
129 | - | |
130 | - CUDA_CALLABLE quad<T, N> operator*(T rhs) | |
131 | - { | |
132 | - //scales the plane by a scalar value | |
133 | - | |
134 | - //compute the center point | |
135 | - rts::vec<T, N> c = A + X*0.5f + Y*0.5f; | |
136 | - | |
137 | - //create the new quadangle | |
138 | - quad<T, N> result; | |
139 | - result.X = X * rhs; | |
140 | - result.Y = Y * rhs; | |
141 | - result.A = c - result.X*0.5f - result.Y*0.5f; | |
142 | - | |
143 | - return result; | |
144 | - | |
145 | - } | |
146 | - | |
147 | - CUDA_CALLABLE T dist(vec<T, N> p) | |
148 | - { | |
149 | - //compute the distance between a point and this quad | |
150 | - | |
151 | - //first break the quad up into two triangles | |
152 | - triangle<T, N> T0(A, A+X, A+Y); | |
153 | - triangle<T, N> T1(A+X+Y, A+X, A+Y); | |
154 | - | |
155 | - | |
156 | - T d0 = T0.dist(p); | |
157 | - T d1 = T1.dist(p); | |
158 | - | |
159 | - if(d0 < d1) | |
160 | - return d0; | |
161 | - else | |
162 | - return d1; | |
163 | - } | |
164 | - | |
165 | - CUDA_CALLABLE T dist_max(vec<T, N> p) | |
166 | - { | |
167 | - T da = (A - p).len(); | |
168 | - T db = (A+X - p).len(); | |
169 | - T dc = (A+Y - p).len(); | |
170 | - T dd = (A+X+Y - p).len(); | |
171 | - | |
172 | - return std::max( da, std::max(db, std::max(dc, dd) ) ); | |
173 | - } | |
174 | -}; | |
175 | - | |
176 | -} //end namespace rts | |
177 | - | |
178 | -template <typename T, int N> | |
179 | -std::ostream& operator<<(std::ostream& os, rts::quad<T, N> R) | |
180 | -{ | |
181 | - os<<R.str(); | |
182 | - return os; | |
183 | -} | |
184 | - | |
185 | - | |
186 | -#endif |
stim/math/quaternion.h
... | ... | @@ -26,13 +26,13 @@ public: |
26 | 26 | |
27 | 27 | CUDA_CALLABLE void CreateRotation(T theta, T ux, T uy, T uz){ |
28 | 28 | |
29 | - vec<T> u(ux, uy, uz); | |
29 | + vec3<T> u(ux, uy, uz); | |
30 | 30 | CreateRotation(theta, u); |
31 | 31 | } |
32 | 32 | |
33 | - CUDA_CALLABLE void CreateRotation(T theta, vec<T> u){ | |
33 | + CUDA_CALLABLE void CreateRotation(T theta, vec3<T> u){ | |
34 | 34 | |
35 | - vec<T> u_hat = u.norm(); | |
35 | + vec3<T> u_hat = u.norm(); | |
36 | 36 | |
37 | 37 | //assign the given Euler rotation to this quaternion |
38 | 38 | w = (T)cos(theta/2); |
... | ... | @@ -41,9 +41,11 @@ public: |
41 | 41 | z = u_hat[2]*(T)sin(theta/2); |
42 | 42 | } |
43 | 43 | |
44 | - void CreateRotation(vec<T> from, vec<T> to){ | |
44 | + CUDA_CALLABLE void CreateRotation(vec3<T> from, vec3<T> to){ | |
45 | 45 | |
46 | - vec<T> r = from.cross(to); //compute the rotation vector | |
46 | + from = from.norm(); | |
47 | + to = to.norm(); | |
48 | + vec3<T> r = from.cross(to); //compute the rotation vector | |
47 | 49 | T theta = asin(r.len()); //compute the angle of the rotation about r |
48 | 50 | //deal with a zero vector (both k and kn point in the same direction) |
49 | 51 | if(theta == (T)0){ | ... | ... |
stim/math/rect.h
... | ... | @@ -28,13 +28,10 @@ class rect : plane <T> |
28 | 28 | O---------X---------> |
29 | 29 | */ |
30 | 30 | |
31 | -private: | |
32 | - | |
33 | - stim::vec<T> X; | |
34 | - stim::vec<T> Y; | |
35 | - | |
36 | - | |
31 | +protected: | |
37 | 32 | |
33 | + stim::vec3<T> X; | |
34 | + stim::vec3<T> Y; | |
38 | 35 | |
39 | 36 | public: |
40 | 37 | |
... | ... | @@ -65,7 +62,7 @@ public: |
65 | 62 | ///create a rectangle from a center point, normal |
66 | 63 | ///@param c: x,y,z location of the center. |
67 | 64 | ///@param n: x,y,z direction of the normal. |
68 | - CUDA_CALLABLE rect(vec<T> c, vec<T> n = vec<T>(0, 0, 1)) | |
65 | + CUDA_CALLABLE rect(vec3<T> c, vec3<T> n = vec3<T>(0, 0, 1)) | |
69 | 66 | : plane<T>() |
70 | 67 |