Commit e21d10516d537afb3393cedd88cbd55697420722
1 parent
df171bd2
cylinder can build OBJ objects, simplified class hierarchy
Showing
6 changed files
with
1300 additions
and
352 deletions
Show diff stats
stim/biomodels/centerline.h
... | ... | @@ -3,7 +3,6 @@ |
3 | 3 | |
4 | 4 | #include <vector> |
5 | 5 | #include <stim/math/vec3.h> |
6 | -//#include <ANN/ANN.h> | |
7 | 6 | |
8 | 7 | namespace stim{ |
9 | 8 | |
... | ... | @@ -12,195 +11,123 @@ namespace stim{ |
12 | 11 | * class to describe an interconnected (often biological) network. |
13 | 12 | */ |
14 | 13 | template<typename T> |
15 | -class centerline{ | |
14 | +class centerline : public std::vector< stim::vec3<T> >{ | |
16 | 15 | |
17 | 16 | protected: |
18 | - unsigned int N; //number of points in the fiber | |
19 | - double **c; //centerline (array of double pointers) | |
20 | -// ANNkd_tree* kdt; //kd-tree stores all points in the fiber for fast searching | |
21 | 17 | |
22 | - /// Initialize an empty fiber | |
23 | - void init() | |
24 | - { | |
25 | - N=0; | |
26 | - c=NULL; | |
27 | -// kdt = NULL; | |
28 | - } | |
29 | - | |
30 | - /// Initialize a fiber with N centerline points (all located at [0, 0, 0] with radius 0) | |
31 | - void init(unsigned int n) | |
32 | - { | |
18 | + std::vector<T> L; //stores the integrated length along the fiber (used for parameterization) | |
33 | 19 | |
34 | - N = n; //set the number of points | |
35 | -// kdt = NULL; | |
36 | - c = (double**) malloc(sizeof(double*) * N); //allocate the array pointer | |
20 | + ///Return the normalized direction vector at point i (average of the incoming and outgoing directions) | |
21 | + vec3<T> d(size_t i) { | |
22 | + if (size() <= 1) return vec3<T>(0, 0, 0); //if there is insufficient information to calculate the direction, return a null vector | |
23 | + if (size() == 2) return (at(1) - at(0)).norm(); //if there are only two points, the direction vector at both is the direction of the line segment | |
24 | + if (i == 0) return (at(1) - at(0)).norm(); //the first direction vector is oriented towards the first line segment | |
25 | + if (i == size() - 1) return at(size() - 1) - at(size() - 2); //the last direction vector is oriented towards the last line segment | |
37 | 26 | |
38 | - for(unsigned int i = 0; i < N; i++) //allocate space for each point | |
39 | - c[i] = (double*) malloc(sizeof(double) * 3); | |
27 | + //all other direction vectors are the average direction of the two joined line segments | |
28 | + return ((at(i) - at(i - 1)).norm() + (at(i + 1) - at(i)).norm()).norm(); | |
40 | 29 | } |
41 | - | |
42 | - /// Copies an existing fiber to the current fiber | |
43 | - | |
44 | - /// @param cpy stores the new copy of the fiber | |
45 | - void copy( const stim::centerline<T>& cpy, bool kd = 0){ | |
46 | - | |
47 | - ///allocate space for the new fiber | |
48 | - init(cpy.N); | |
49 | - | |
50 | - ///copy the points | |
51 | - for(unsigned int i = 0; i < N; i++){ | |
52 | - for(unsigned int d = 0; d < 3; d++) //for each dimension | |
53 | - c[i][d] = cpy.c[i][d]; //copy the coordinate | |
30 | + //initializes the integrated length vector to make parameterization easier, starting with index idx (all previous indices are assumed to be correct) | |
31 | + void update_L(size_t start = 0) { | |
32 | + L.resize(size()); //allocate space for the L array | |
33 | + if (start == 0) { | |
34 | + L[0] = 0; //initialize the length value for the first point to zero (0) | |
35 | + start++; | |
54 | 36 | } |
55 | -// if(kd) | |
56 | -// gen_kdtree(); //generate the kd tree for the new fiber | |
57 | - } | |
58 | 37 | |
59 | - /// generate a KD tree for points on fiber | |
60 | -// void gen_kdtree() | |
61 | -// { | |
62 | -// int n_data = N; //create an array of data points | |
63 | -// ANNpointArray pts = (ANNpointArray)c; //cast the centerline list to an ANNpointArray | |
64 | -// kdt = new ANNkd_tree(pts, n_data, 3); //build a KD tree | |
65 | -// } | |
66 | - | |
67 | - /// find distance between two points | |
68 | - double dist(double* p0, double* p1){ | |
69 | - | |
70 | - double sum = 0; // initialize variables | |
71 | - float v; | |
72 | - for(unsigned int d = 0; d < 3; d++) | |
73 | - { | |
74 | - v = p1[d] - p0[d]; | |
75 | - sum +=v * v; | |
38 | + stim::vec3<T> d; | |
39 | + for (size_t i = start; i < size(); i++) { //for each line segment in the centerline | |
40 | + d = at(i) - at(i - 1); | |
41 | + L[i] = L[i - 1] + d.len(); //calculate the running length total | |
76 | 42 | } |
77 | - return sqrt(sum); | |
78 | 43 | } |
79 | 44 | |
80 | - /// This function retreives the index for the fiber point closest to q | |
81 | - | |
82 | - /// @param q is a reference point used to find the closest point on the fiber center line | |
83 | -// unsigned int ann( stim::vec<double> q ){ | |
84 | -// ANNidxArray idx = new ANNidx[1]; //variable used to hold the nearest point | |
85 | -// ANNdistArray sq_dist = new ANNdist[1]; //variable used to hold the squared distance to the nearest point | |
86 | -// kdt->annkSearch(q.data(), 1, idx, sq_dist); //search the KD tree for the nearest neighbor | |
87 | -// return *idx; | |
88 | -// } | |
45 | + void init() { | |
46 | + if (size() == 0) return; //return if there aren't any points | |
47 | + update_L(); | |
48 | + } | |
89 | 49 | |
90 | 50 | /// Returns a stim::vec representing the point at index i |
91 | 51 | |
92 | 52 | /// @param i is an index of the desired centerline point |
93 | 53 | stim::vec<T> get_vec(unsigned i){ |
94 | - stim::vec3<T> r; | |
95 | - r.resize(3); | |
96 | - r[0] = c[i][0]; | |
97 | - r[1] = c[i][1]; | |
98 | - r[2] = c[i][2]; | |
54 | + return std::vector< stim::vec3<T> >::at(i); | |
55 | + } | |
56 | + | |
57 | + ///finds the index of the point closest to the length l on the lower bound. | |
58 | + ///binary search. | |
59 | + size_t findIdx(T l) { | |
60 | + size_t i = L.size() / 2; | |
61 | + size_t max = L.size() - 1; | |
62 | + size_t min = 0; | |
63 | + while (i > 0 && i < L.size() - 1){ | |
64 | + if (l < L[i]) { | |
65 | + max = i; | |
66 | + i = min + (max - min) / 2; | |
67 | + } | |
68 | + else if (L[i] <= l && L[i + 1] >= l) { | |
69 | + break; | |
70 | + } | |
71 | + else { | |
72 | + min = i; | |
73 | + i = min + (max - min) / 2; | |
74 | + } | |
75 | + } | |
76 | + return i; | |
77 | + } | |
99 | 78 | |
100 | - return r; | |
79 | + ///Returns a position vector at the given length into the fiber (based on the pvalue). | |
80 | + ///Interpolates the radius along the line. | |
81 | + ///@param l: the location of the in the cylinder. | |
82 | + ///@param idx: integer location of the point closest to l but prior to it. | |
83 | + stim::vec3<T> p(T l, int idx) { | |
84 | + T rat = (l - L[idx]) / (L[idx + 1] - L[idx]); | |
85 | + stim::vec3<T> v1 = at(idx); | |
86 | + stim::vec3<T> v2 = at(idx + 1); | |
87 | + return(v1 + (v2 - v1)*rat); | |
101 | 88 | } |
102 | 89 | |
103 | 90 | |
104 | 91 | public: |
105 | 92 | |
106 | - centerline(){ | |
107 | - init(); | |
108 | - } | |
93 | + using std::vector< stim::vec3<T> >::at; | |
94 | + using std::vector< stim::vec3<T> >::size; | |
109 | 95 | |
110 | - /// Copy constructor | |
111 | - centerline(const stim::centerline<T> &obj){ | |
112 | - copy(obj); | |
96 | + centerline() : std::vector< stim::vec3<T> >() { | |
97 | + init(); | |
113 | 98 | } |
114 | - | |
115 | - //temp constructor for graph visualization | |
116 | - centerline(int n) | |
117 | - { | |
118 | - init(n); | |
99 | + centerline(size_t n) : std::vector< stim::vec3<T> >(n){ | |
100 | + init(); | |
119 | 101 | } |
120 | 102 | |
121 | - /// Constructor takes a list of stim::vec points, the radius at each point is set to zero | |
122 | - centerline(std::vector< stim::vec<T> > p, bool kd = 0){ | |
123 | - init(p.size()); //initialize the fiber | |
124 | - | |
125 | - //for each point, set the centerline position and radius | |
126 | - for(unsigned int i = 0; i < N; i++){ | |
127 | - | |
128 | - //set the centerline position | |
129 | - for(unsigned int d = 0; d < 3; d++) | |
130 | - c[i][d] = (double) p[i][d]; | |
131 | - | |
132 | - //set the radius | |
133 | - } | |
134 | - //generate a kd tree | |
135 | -// if(kd) | |
136 | -// gen_kdtree(); | |
103 | + //overload the push_back function to update the length vector | |
104 | + void push_back(stim::vec3<T> p) { | |
105 | + std::vector< stim::vec3<T> >::push_back(p); | |
106 | + update_L(size() - 1); | |
137 | 107 | } |
138 | 108 | |
139 | - /// constructor takes a list of points | |
140 | - centerline(std::vector< stim::vec3< T > > pos, bool kd = 0){ | |
141 | - init(pos.size()); //initialize the fiber | |
109 | + ///Returns a position vector at the given p-value (p value ranges from 0 to 1). | |
110 | + ///interpolates the position along the line. | |
111 | + ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). | |
112 | + stim::vec3<T> p(T pvalue) { | |
113 | + if (pvalue <= 0.0) return at(0); //return the first element | |
114 | + if (pvalue >= 1.0) return back(); //return the last element | |
142 | 115 | |
143 | - //for each point, set the centerline position and radius | |
144 | - for(unsigned int i = 0; i < N; i++){ | |
145 | - //set the centerline position | |
146 | - for(unsigned int d = 0; d < 3; d++) | |
147 | - c[i][d] = (double) pos[i][d]; | |
148 | - //set the radius | |
149 | - } | |
150 | - | |
151 | - //generate a kd tree | |
152 | - //if(kd) | |
153 | - // gen_kdtree(); | |
116 | + T l = pvalue*L[L.size() - 1]; | |
117 | + int idx = findIdx(l); | |
118 | + return p(l, idx); | |
154 | 119 | } |
155 | 120 | |
156 | - /// Assignment operation | |
157 | - centerline& operator=(const centerline &rhs){ | |
158 | - if(this == &rhs) return *this; //test for and handle self-assignment | |
159 | - copy(rhs); | |
160 | - return *this; | |
161 | - } | |
162 | - | |
163 | - | |
164 | - /// Return the point on the fiber closest to q | |
165 | - /// @param q is the query point used to locate the nearest point on the fiber centerline | |
166 | -// stim::vec<T> nearest(stim::vec<T> q){ | |
167 | -// | |
168 | -// stim::vec<double> temp( (double) q[0], (double) q[1], (double) q[2]); | |
169 | -// | |
170 | -// unsigned int idx = ann(temp); //determine the index of the nearest neighbor | |
171 | -// | |
172 | -// return stim::vec<T>((T) c[idx][0], (T) c[idx][1], (T) c[idx][2]); //return the nearest centerline point | |
173 | -// } | |
174 | - | |
175 | - /// Return the point index on the fiber closest to q | |
176 | - /// @param q is the query point used to locate the nearest point on the fiber centerline | |
177 | -// unsigned int nearest_idx(stim::vec<T> q){ | |
178 | -// | |
179 | -// stim::vec<double> temp((double) q[0], (double) q[1], (double) q[2]); | |
180 | -// | |
181 | -// unsigned int idx = ann(temp); //determine the index of the nearest neighbor | |
182 | -// | |
183 | -// return idx; //return the nearest centerline point index | |
184 | -// } | |
185 | - | |
186 | - /// Returns the fiber centerline as an array of stim::vec points | |
187 | - std::vector< stim::vec<T> > get_centerline(){ | |
188 | - | |
189 | - //create an array of stim vectors | |
190 | - std::vector< stim::vec3<T> > pts(N); | |
191 | - | |
192 | - //cast each point to a stim::vec, keeping only the position information | |
193 | - for(unsigned int i = 0; i < N; i++) | |
194 | - pts[i] = stim::vec3<T>((T) c[i][0], (T) c[i][1], (T) c[i][2]); | |
195 | - | |
196 | - //return the centerline array | |
197 | - return pts; | |
121 | + ///Return the length of the entire centerline | |
122 | + T length() { | |
123 | + return L.back(); | |
198 | 124 | } |
199 | 125 | |
200 | 126 | /// Split the fiber at the specified index. If the index is an end point, only one fiber is returned |
201 | 127 | std::vector< stim::centerline<T> > split(unsigned int idx){ |
202 | 128 | |
203 | - std::vector< stim::centerline<T> > fl; //create an array to store up to two fibers | |
129 | + std::vector< stim::centerline<T> > fl; //create an array to store up to two fibers | |
130 | + size_t N = size(); | |
204 | 131 | |
205 | 132 | //if the index is an end point, only the existing fiber is returned |
206 | 133 | if(idx == 0 || idx == N-1){ |
... | ... | @@ -216,123 +143,84 @@ public: |
216 | 143 | |
217 | 144 | fl.resize(2); //set the array size to 2 |
218 | 145 | |
219 | - fl[0].init(N1); //set the size of each fiber | |
220 | - fl[1].init(N2); | |
146 | + fl[0] = stim::centerline<T>(N1); //set the size of each fiber | |
147 | + fl[1] = stim::centerline<T>(N2); | |
221 | 148 | |
222 | 149 | //copy both halves of the fiber |
223 | 150 | unsigned int i, d; |
224 | 151 | |
225 | 152 | //first half |
226 | - for(i = 0; i < N1; i++){ //for each centerline point | |
227 | - for(d = 0; d < 3; d++) | |
228 | - fl[0].c[i][d] = c[i][d]; //copy each coordinate | |
229 | - } | |
153 | + for(i = 0; i < N1; i++) //for each centerline point | |
154 | + fl[0][i] = std::vector< stim::vec3<T> >::at(i); | |
155 | + fl[0].init(); //initialize the length vector | |
230 | 156 | |
231 | 157 | //second half |
232 | - for(i = 0; i < N2; i++){ | |
233 | - for(d = 0; d < 3; d++) | |
234 | - fl[1].c[i][d] = c[idx + i][d]; | |
235 | - | |
236 | - } | |
158 | + for(i = 0; i < N2; i++) | |
159 | + fl[1][i] = std::vector< stim::vec3<T> >::at(idx+i); | |
160 | + fl[1].init(); //initialize the length vector | |
237 | 161 | } |
238 | 162 | |
239 | 163 | return fl; //return the array |
240 | 164 | |
241 | 165 | } |
242 | 166 | |
243 | - /// Calculates the set of fibers resulting from a connection between the current fiber and a fiber f | |
244 | - | |
245 | - /// @param f is the fiber that will be connected to the current fiber | |
246 | -/* std::vector< stim::centerline<T> > connect( stim::centerline<T> &f, double dist){ | |
247 | - | |
248 | - double min_dist; | |
249 | - unsigned int idx0, idx1; | |
250 | - | |
251 | - //go through each point in the query fiber, looking for the indices for the closest points | |
252 | - for(unsigned int i = 0; i < f.n_pts(); i++){ | |
253 | - //Run through all points and find the index with the closest point, then partition the fiber and return two fibers. | |
254 | - | |
255 | - } | |
256 | - | |
257 | - | |
258 | - | |
259 | - } | |
260 | -*/ | |
261 | 167 | /// Outputs the fiber as a string |
262 | 168 | std::string str(){ |
263 | 169 | std::stringstream ss; |
264 | - | |
265 | - //create an iterator for the point list | |
266 | - //typename std::list< point<T> >::iterator i; | |
267 | - for(unsigned int i = 0; i < N; i++){ | |
268 | - ss<<" [ "; | |
269 | - for(unsigned int d = 0; d < 3; d++){ | |
270 | - ss<<c[i][d]<<" "; | |
271 | - } | |
272 | - } | |
170 | + size_t N = std::vector< stim::vec3<T> >::size(); | |
171 | + ss << "---------[" << N << "]---------" << std::endl; | |
172 | + for (size_t i = 0; i < N; i++) | |
173 | + ss << std::vector< stim::vec3<T> >::at(i) << std::endl; | |
174 | + ss << "--------------------" << std::endl; | |
273 | 175 | |
274 | 176 | return ss.str(); |
275 | 177 | } |
276 | - /// Returns the number of centerline points in the fiber | |
277 | - unsigned int size(){ | |
278 | - return N; | |
279 | - } | |
280 | - | |
281 | - | |
282 | - /// Bracket operator returns the element at index i | |
283 | - | |
284 | - /// @param i is the index of the element to be returned as a stim::vec | |
285 | - stim::vec<T> operator[](unsigned i){ | |
286 | - return get_vec(i); | |
287 | - } | |
288 | 178 | |
289 | 179 | /// Back method returns the last point in the fiber |
290 | - stim::vec<T> back(){ | |
291 | - return get_vec(N-1); | |
180 | + stim::vec3<T> back(){ | |
181 | + return std::vector< stim::vec3<T> >::back(); | |
292 | 182 | } |
183 | + | |
293 | 184 | ////resample a fiber in the network |
294 | 185 | stim::centerline<T> resample(T spacing) |
295 | 186 | { |
296 | 187 | std::cout<<"fiber::resample()"<<std::endl; |
297 | 188 | |
298 | - std::vector<T> v(3); //v-direction vector of the segment | |
299 | - stim::vec<T> p(3); //- intermediate point to be added | |
300 | - stim::vec<T> p1(3); // p1 - starting point of an segment on the fiber, | |
301 | - stim::vec<T> p2(3); // p2 - ending point, | |
189 | + stim::vec3<T> v; //v-direction vector of the segment | |
190 | + stim::vec3<T> p; //- intermediate point to be added | |
191 | + stim::vec3<T> p1; // p1 - starting point of an segment on the fiber, | |
192 | + stim::vec3<T> p2; // p2 - ending point, | |
302 | 193 | double sum=0; //distance summation |
303 | - std::vector<stim::vec<T> > fiberPositions = centerline(); | |
304 | - std::vector<stim::vec<T> > newPointList; // initialize list of new resampled points on the fiber | |
194 | + | |
195 | + size_t N = size(); | |
196 | + | |
197 | + centerline<T> new_c; // initialize list of new resampled points on the fiber | |
305 | 198 | // for each point on the centerline (skip if it is the last point on centerline) |
306 | - //unsigned int N = fiberPositions.size(); // number of points on the fiber | |
307 | 199 | for(unsigned int f=0; f< N-1; f++) |
308 | - { | |
200 | + { | |
201 | + p1 = at(f); | |
202 | + p2 = at(f+1); | |
203 | + v = p2 - p1; | |
309 | 204 | |
310 | - p1 = fiberPositions[f]; p2 = fiberPositions[f + 1]; v = p2 - p1; | |
311 | - for(unsigned int d = 0; d < 3; d++){ | |
312 | - sum +=v[d] * v[d];} //length of segment-distance between starting and ending point | |
313 | - | |
314 | - T lengthSegment = sqrt(sum); //find Length of the segment as distance between the starting and ending points of the segment | |
315 | - | |
316 | - if(lengthSegment >= spacing) // if length of the segment is greater than standard deviation resample | |
317 | - { | |
318 | - // repeat resampling until accumulated stepsize is equsl to length of the segment | |
319 | - for(T step=0.0; step<lengthSegment; step+=spacing) | |
320 | - { | |
321 | - // calculate the resampled point by travelling step size in the direction of normalized gradient vector | |
322 | - for(unsigned int i=0; i<3;i++) | |
323 | - { | |
324 | - p[i] = p1[i] + v[i]*(step/lengthSegment); | |
325 | - } //for each dimension | |
326 | - // add this resampled points to the new fiber list | |
327 | - newPointList.push_back(p); | |
328 | - } | |
205 | + T lengthSegment = v.len(); //find Length of the segment as distance between the starting and ending points of the segment | |
206 | + | |
207 | + if(lengthSegment >= spacing){ // if length of the segment is greater than standard deviation resample | |
208 | + | |
209 | + // repeat resampling until accumulated stepsize is equsl to length of the segment | |
210 | + for(T step=0.0; step<lengthSegment; step+=spacing){ | |
211 | + // calculate the resampled point by travelling step size in the direction of normalized gradient vector | |
212 | + p = p1 + v * (step / lengthSegment); | |
213 | + | |
214 | + // add this resampled points to the new fiber list | |
215 | + new_c.push_back(p); | |
329 | 216 | } |
330 | - else // length of the segment is now less than standard deviation, push the ending point of the segment and proceed to the next point in the fiber | |
331 | - newPointList.push_back(fiberPositions[f+1]); | |
332 | 217 | } |
333 | - newPointList.push_back(fiberPositions[N-1]); //add the last point on the fiber to the new fiber list | |
334 | - centerline newFiber(newPointList); | |
335 | - return newFiber; | |
218 | + else // length of the segment is now less than standard deviation, push the ending point of the segment and proceed to the next point in the fiber | |
219 | + new_c.push_back(at(f+1)); | |
220 | + } | |
221 | + new_c.push_back(at(N-1)); //add the last point on the fiber to the new fiber list | |
222 | + //centerline newFiber(newPointList); | |
223 | + return new_c; | |
336 | 224 | } |
337 | 225 | |
338 | 226 | }; | ... | ... |
1 | +#ifndef STIM_CENTERLINE_H | |
2 | +#define STIM_CENTERLINE_H | |
3 | + | |
4 | +#include <vector> | |
5 | +#include <stim/math/vec3.h> | |
6 | + | |
7 | +namespace stim{ | |
8 | + | |
9 | +/** This class stores information about a single fiber represented as a set of geometric points | |
10 | + * between two branch or end points. This class is used as a fundamental component of the stim::network | |
11 | + * class to describe an interconnected (often biological) network. | |
12 | + */ | |
13 | +template<typename T> | |
14 | +class centerline{ | |
15 | + | |
16 | +protected: | |
17 | + unsigned int N; //number of points in the fiber | |
18 | + double **c; //centerline (array of double pointers) | |
19 | + | |
20 | + /// Initialize an empty fiber | |
21 | + void init(){ | |
22 | + N=0; | |
23 | + c=NULL; | |
24 | + } | |
25 | + | |
26 | + /// Initialize a fiber with N centerline points (all located at [0, 0, 0] with radius 0) | |
27 | + void init(unsigned int n){ | |
28 | + | |
29 | + N = n; //set the number of points | |
30 | + c = (double**) malloc(sizeof(double*) * N); //allocate the array pointer | |
31 | + | |
32 | + for(unsigned int i = 0; i < N; i++) //allocate space for each point | |
33 | + c[i] = (double*) malloc(sizeof(double) * 3); | |
34 | + } | |
35 | + | |
36 | + /// Copies an existing fiber to the current fiber | |
37 | + | |
38 | + /// @param cpy stores the new copy of the fiber | |
39 | + void copy( const stim::centerline<T>& cpy, bool kd = 0){ | |
40 | + | |
41 | + ///allocate space for the new fiber | |
42 | + init(cpy.N); | |
43 | + | |
44 | + ///copy the points | |
45 | + for(unsigned int i = 0; i < N; i++){ | |
46 | + for(unsigned int d = 0; d < 3; d++) //for each dimension | |
47 | + c[i][d] = cpy.c[i][d]; //copy the coordinate | |
48 | + } | |
49 | + } | |
50 | + | |
51 | + /// find distance between two points | |
52 | + double dist(double* p0, double* p1){ | |
53 | + | |
54 | + double sum = 0; // initialize variables | |
55 | + float v; | |
56 | + for(unsigned int d = 0; d < 3; d++) | |
57 | + { | |
58 | + v = p1[d] - p0[d]; | |
59 | + sum +=v * v; | |
60 | + } | |
61 | + return sqrt(sum); | |
62 | + } | |
63 | + | |
64 | + /// Returns a stim::vec representing the point at index i | |
65 | + | |
66 | + /// @param i is an index of the desired centerline point | |
67 | + stim::vec<T> get_vec(unsigned i){ | |
68 | + stim::vec3<T> r; | |
69 | + r.resize(3); | |
70 | + r[0] = c[i][0]; | |
71 | + r[1] = c[i][1]; | |
72 | + r[2] = c[i][2]; | |
73 | + | |
74 | + return r; | |
75 | + } | |
76 | + | |
77 | + | |
78 | +public: | |
79 | + | |
80 | + centerline(){ | |
81 | + init(); | |
82 | + } | |
83 | + | |
84 | + /// Copy constructor | |
85 | + centerline(const stim::centerline<T> &obj){ | |
86 | + copy(obj); | |
87 | + } | |
88 | + | |
89 | + //initialize a centerline with n points | |
90 | + centerline(int n){ | |
91 | + init(n); | |
92 | + } | |
93 | + | |
94 | + /// Constructor takes a list of stim::vec points, the radius at each point is set to zero | |
95 | + centerline(std::vector< stim::vec<T> > p, bool kd = 0){ | |
96 | + init(p.size()); //initialize the fiber | |
97 | + | |
98 | + //for each point, set the centerline position and radius | |
99 | + for(unsigned int i = 0; i < N; i++){ | |
100 | + | |
101 | + //set the centerline position | |
102 | + for(unsigned int d = 0; d < 3; d++) | |
103 | + c[i][d] = (double) p[i][d]; | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + /// constructor takes a list of points | |
108 | + centerline(std::vector< stim::vec3< T > > pos, bool kd = 0){ | |
109 | + init(pos.size()); //initialize the fiber | |
110 | + | |
111 | + //for each point, set the centerline position and radius | |
112 | + for(unsigned int i = 0; i < N; i++){ | |
113 | + //set the centerline position | |
114 | + for(unsigned int d = 0; d < 3; d++) | |
115 | + c[i][d] = (double) pos[i][d]; | |
116 | + } | |
117 | + } | |
118 | + | |
119 | + /// Assignment operation | |
120 | + centerline& operator=(const centerline &rhs){ | |
121 | + if(this == &rhs) return *this; //test for and handle self-assignment | |
122 | + copy(rhs); | |
123 | + return *this; | |
124 | + } | |
125 | + | |
126 | + | |
127 | + /// Returns the fiber centerline as an array of stim::vec points | |
128 | + std::vector< stim::vec<T> > get_centerline(){ | |
129 | + | |
130 | + //create an array of stim vectors | |
131 | + std::vector< stim::vec3<T> > pts(N); | |
132 | + | |
133 | + //cast each point to a stim::vec, keeping only the position information | |
134 | + for(unsigned int i = 0; i < N; i++) | |
135 | + pts[i] = stim::vec3<T>((T) c[i][0], (T) c[i][1], (T) c[i][2]); | |
136 | + | |
137 | + //return the centerline array | |
138 | + return pts; | |
139 | + } | |
140 | + | |
141 | + /// Split the fiber at the specified index. If the index is an end point, only one fiber is returned | |
142 | + std::vector< stim::centerline<T> > split(unsigned int idx){ | |
143 | + | |
144 | + std::vector< stim::centerline<T> > fl; //create an array to store up to two fibers | |
145 | + | |
146 | + //if the index is an end point, only the existing fiber is returned | |
147 | + if(idx == 0 || idx == N-1){ | |
148 | + fl.resize(1); //set the size of the fiber to 1 | |
149 | + fl[0] = *this; //copy the current fiber | |
150 | + } | |
151 | + | |
152 | + //if the index is not an end point | |
153 | + else{ | |
154 | + | |
155 | + unsigned int N1 = idx + 1; //calculate the size of both fibers | |
156 | + unsigned int N2 = N - idx; | |
157 | + | |
158 | + fl.resize(2); //set the array size to 2 | |
159 | + | |
160 | + fl[0].init(N1); //set the size of each fiber | |
161 | + fl[1].init(N2); | |
162 | + | |
163 | + //copy both halves of the fiber | |
164 | + unsigned int i, d; | |
165 | + | |
166 | + //first half | |
167 | + for(i = 0; i < N1; i++){ //for each centerline point | |
168 | + for(d = 0; d < 3; d++) | |
169 | + fl[0].c[i][d] = c[i][d]; //copy each coordinate | |
170 | + } | |
171 | + | |
172 | + //second half | |
173 | + for(i = 0; i < N2; i++){ | |
174 | + for(d = 0; d < 3; d++) | |
175 | + fl[1].c[i][d] = c[idx + i][d]; | |
176 | + | |
177 | + } | |
178 | + } | |
179 | + | |
180 | + return fl; //return the array | |
181 | + | |
182 | + } | |
183 | + | |
184 | + /// Outputs the fiber as a string | |
185 | + std::string str(){ | |
186 | + std::stringstream ss; | |
187 | + | |
188 | + //create an iterator for the point list | |
189 | + //typename std::list< point<T> >::iterator i; | |
190 | + for(unsigned int i = 0; i < N; i++){ | |
191 | + ss<<" [ "; | |
192 | + for(unsigned int d = 0; d < 3; d++){ | |
193 | + ss<<c[i][d]<<" "; | |
194 | + } | |
195 | + } | |
196 | + | |
197 | + return ss.str(); | |
198 | + } | |
199 | + /// Returns the number of centerline points in the fiber | |
200 | + unsigned int size(){ | |
201 | + return N; | |
202 | + } | |
203 | + | |
204 | + | |
205 | + /// Bracket operator returns the element at index i | |
206 | + | |
207 | + /// @param i is the index of the element to be returned as a stim::vec | |
208 | + stim::vec<T> operator[](unsigned i){ | |
209 | + return get_vec(i); | |
210 | + } | |
211 | + | |
212 | + /// Back method returns the last point in the fiber | |
213 | + stim::vec<T> back(){ | |
214 | + return get_vec(N-1); | |
215 | + } | |
216 | + ////resample a fiber in the network | |
217 | + stim::centerline<T> resample(T spacing) | |
218 | + { | |
219 | + std::cout<<"fiber::resample()"<<std::endl; | |
220 | + | |
221 | + std::vector<T> v(3); //v-direction vector of the segment | |
222 | + stim::vec<T> p(3); //- intermediate point to be added | |
223 | + stim::vec<T> p1(3); // p1 - starting point of an segment on the fiber, | |
224 | + stim::vec<T> p2(3); // p2 - ending point, | |
225 | + double sum=0; //distance summation | |
226 | + std::vector<stim::vec<T> > fiberPositions = centerline(); | |
227 | + std::vector<stim::vec<T> > newPointList; // initialize list of new resampled points on the fiber | |
228 | + // for each point on the centerline (skip if it is the last point on centerline) | |
229 | + for(unsigned int f=0; f< N-1; f++) | |
230 | + { | |
231 | + | |
232 | + p1 = fiberPositions[f]; p2 = fiberPositions[f + 1]; v = p2 - p1; | |
233 | + for(unsigned int d = 0; d < 3; d++){ | |
234 | + sum +=v[d] * v[d];} //length of segment-distance between starting and ending point | |
235 | + | |
236 | + T lengthSegment = sqrt(sum); //find Length of the segment as distance between the starting and ending points of the segment | |
237 | + | |
238 | + if(lengthSegment >= spacing) // if length of the segment is greater than standard deviation resample | |
239 | + { | |
240 | + // repeat resampling until accumulated stepsize is equsl to length of the segment | |
241 | + for(T step=0.0; step<lengthSegment; step+=spacing) | |
242 | + { | |
243 | + // calculate the resampled point by travelling step size in the direction of normalized gradient vector | |
244 | + for(unsigned int i=0; i<3;i++) | |
245 | + { | |
246 | + p[i] = p1[i] + v[i]*(step/lengthSegment); | |
247 | + } //for each dimension | |
248 | + // add this resampled points to the new fiber list | |
249 | + newPointList.push_back(p); | |
250 | + } | |
251 | + } | |
252 | + else // length of the segment is now less than standard deviation, push the ending point of the segment and proceed to the next point in the fiber | |
253 | + newPointList.push_back(fiberPositions[f+1]); | |
254 | + } | |
255 | + newPointList.push_back(fiberPositions[N-1]); //add the last point on the fiber to the new fiber list | |
256 | + centerline newFiber(newPointList); | |
257 | + return newFiber; | |
258 | + } | |
259 | + | |
260 | +}; | |
261 | + | |
262 | + | |
263 | + | |
264 | +} //end namespace stim | |
265 | + | |
266 | + | |
267 | + | |
268 | +#endif | ... | ... |
stim/math/circle.h
... | ... | @@ -18,13 +18,14 @@ class circle : plane<T> |
18 | 18 | |
19 | 19 | private: |
20 | 20 | |
21 | - stim::vec3<T> Y; | |
21 | + //stim::vec3<T> Y; | |
22 | + T R; //radius of the circle | |
22 | 23 | |
23 | - CUDA_CALLABLE void | |
24 | + /*CUDA_CALLABLE void | |
24 | 25 | init() |
25 | 26 | { |
26 | 27 | Y = U.cross(N).norm(); |
27 | - } | |
28 | + }*/ | |
28 | 29 | |
29 | 30 | public: |
30 | 31 | using stim::plane<T>::n; |
... | ... | @@ -42,26 +43,28 @@ public: |
42 | 43 | init(); |
43 | 44 | } |
44 | 45 | |
45 | - ///create a rectangle given a size and position in Z space. | |
46 | + ///create a circle given a size and position in Z space. | |
46 | 47 | ///@param size: size of the rectangle in ND space. |
47 | 48 | ///@param z_pos z coordinate of the rectangle. |
48 | 49 | CUDA_CALLABLE |
49 | - circle(T size, T z_pos = (T)0) : plane<T>() | |
50 | + circle(T radius, T z_pos = (T)0) : plane<T>(z_pos) | |
50 | 51 | { |
51 | - center(stim::vec3<T>(0,0,z_pos)); | |
52 | - scale(size); | |
53 | - init(); | |
52 | + //center(stim::vec3<T>(0, 0, z_pos)); | |
53 | + //scale(size); | |
54 | + //init(); | |
55 | + R = radius; | |
54 | 56 | } |
55 | 57 | |
56 | 58 | ///create a rectangle from a center point, normal |
57 | 59 | ///@param c: x,y,z location of the center. |
58 | 60 | ///@param n: x,y,z direction of the normal. |
59 | 61 | CUDA_CALLABLE |
60 | - circle(vec3<T> c, vec3<T> n = vec3<T>(0,0,1)) : plane<T>() | |
62 | + circle(vec3<T> c, vec3<T> n = vec3<T>(0,0,1)) : plane<T>(n, c) | |
61 | 63 | { |
62 | - center(c); | |
63 | - normal(n); | |
64 | - init(); | |
64 | + //center(c); | |
65 | + //normal(n); | |
66 | + //init(); | |
67 | + R = (T)1; | |
65 | 68 | } |
66 | 69 | |
67 | 70 | /*///create a rectangle from a center point, normal, and size |
... | ... | @@ -84,14 +87,18 @@ public: |
84 | 87 | ///@param n: x,y,z direction of the normal. |
85 | 88 | ///@param u: x,y,z direction for the zero vector (from where the rotation starts) |
86 | 89 | CUDA_CALLABLE |
87 | - circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1), vec3<T> u = vec3<T>(1, 0, 0)) : plane<T>() | |
90 | + circle(vec3<T> c, T r, vec3<T> n = vec3<T>(0,0,1), vec3<T> u = vec3<T>(1, 0, 0)) : plane<T>() | |
88 | 91 | { |
89 | - init(); | |
92 | + P = c; | |
93 | + N = n; | |
90 | 94 | setU(u); |
95 | + R = r; | |
96 | + //init(); | |
97 | + //setU(u); | |
91 | 98 | // U = u; |
92 | - center(c); | |
93 | - normal(n); | |
94 | - scale(s); | |
99 | + //center(c); | |
100 | + //normal(n); | |
101 | + //scale(s); | |
95 | 102 | } |
96 | 103 | |
97 | 104 | ///scales the circle by a certain factor |
... | ... | @@ -99,23 +106,23 @@ public: |
99 | 106 | CUDA_CALLABLE |
100 | 107 | void scale(T factor) |
101 | 108 | { |
102 | - U *= factor; | |
103 | - Y *= factor; | |
109 | + //U *= factor; | |
110 | + //Y *= factor; | |
111 | + R *= factor; | |
104 | 112 | } |
105 | 113 | |
106 | 114 | ///sets the normal for the cirlce |
107 | 115 | ///@param n: x,y,z direction of the normal. |
108 | 116 | CUDA_CALLABLE void |
109 | - normal(vec3<T> n) | |
110 | - { | |
111 | - rotate(n, Y); | |
117 | + normal(vec3<T> n){ | |
118 | + rotate(n); | |
112 | 119 | } |
113 | 120 | |
114 | 121 | ///sets the center of the circle. |
115 | 122 | ///@param n: x,y,z location of the center. |
116 | 123 | CUDA_CALLABLE void |
117 | 124 | center(vec3<T> p){ |
118 | - this->P = p; | |
125 | + P = p; | |
119 | 126 | } |
120 | 127 | |
121 | 128 | ///boolean comparison |
... | ... | @@ -128,57 +135,63 @@ public: |
128 | 135 | return false; |
129 | 136 | } |
130 | 137 | |
138 | + //returns the point in world space corresponding to the polar coordinate (r, theta) | |
139 | + CUDA_CALLABLE stim::vec3<T> | |
140 | + p(T r, T theta) { | |
141 | + T u = r * cos(theta); //calculate the coordinates in the planar space defined by the circle | |
142 | + T v = r * sin(theta); | |
143 | + | |
144 | + vec3<T> V = U.cross(N); //calculate the orthogonal vector V | |
145 | + return P + U * u + V * v; //calculate the cartesian coordinate of the specified point | |
146 | + } | |
147 | + | |
148 | + //returns the point in world space corresponding to the value theta at radius R | |
149 | + CUDA_CALLABLE stim::vec3<T> | |
150 | + p(T theta) { | |
151 | + return p(R, theta); | |
152 | + } | |
153 | + | |
154 | + //get the world space value given the polar coordinates (r, theta) | |
155 | + | |
131 | 156 | ///get the world space value given the planar coordinates a, b in [0, 1] |
132 | - CUDA_CALLABLE stim::vec3<T> p(T a, T b) | |
157 | + /*CUDA_CALLABLE stim::vec3<T> p(T a, T b) | |
133 | 158 | { |
134 | 159 | stim::vec3<T> result; |
135 | 160 | |
136 | 161 | vec3<T> A = this->P - this->U * (T)0.5 - Y * (T)0.5; |
137 | 162 | result = A + this->U * a + Y * b; |
138 | 163 | return result; |
139 | - } | |
164 | + }*/ | |
140 | 165 | |
141 | 166 | ///parenthesis operator returns the world space given rectangular coordinates a and b in [0 1] |
142 | - CUDA_CALLABLE stim::vec3<T> operator()(T a, T b) | |
167 | + CUDA_CALLABLE stim::vec3<T> operator()(T r, T theta) | |
143 | 168 | { |
144 | - return p(a,b); | |
169 | + return p(r, theta); | |
170 | + } | |
171 | + | |
172 | + //parenthesis operator returns the world space coordinate at the edge of the circle given theta | |
173 | + CUDA_CALLABLE stim::vec3<T> operator()(T theta) { | |
174 | + return p(theta); | |
145 | 175 | } |
146 | 176 | |
147 | 177 | ///returns a vector with the points on the initialized circle. |
148 | 178 | ///connecting the points results in a circle. |
149 | 179 | ///@param n: integer for the number of points representing the circle. |
150 | - std::vector<stim::vec3<T> > | |
151 | - getPoints(int n) | |
152 | - { | |
153 | - std::vector<stim::vec3<T> > result; | |
154 | - stim::vec3<T> point; | |
155 | - T x,y; | |
156 | - float step = 360.0/(float) n; | |
157 | - for(float j = 0; j <= 360.0; j += step) | |
158 | - { | |
159 | - y = 0.5*cos(j*stim::TAU/360.0)+0.5; | |
160 | - x = 0.5*sin(j*stim::TAU/360.0)+0.5; | |
161 | - result.push_back(p(x,y)); | |
162 | - } | |
180 | + std::vector< stim::vec3<T> > points(unsigned n) { | |
181 | + std::vector< stim::vec3<T> > result(n); //initialize a vector of n points | |
182 | + | |
183 | + float dt = stim::TAU / n; | |
184 | + for (unsigned i = 0; i < n; i++) | |
185 | + result[i] = p(i * dt); //calculate a point on the edge of the circle | |
163 | 186 | return result; |
164 | 187 | } |
165 | 188 | |
166 | - ///returns a vector with the points on the initialized circle. | |
167 | - ///connecting the points results in a circle. | |
168 | - ///@param n: integer for the number of points representing the circle. | |
169 | - CUDA_CALLABLE stim::vec3<T> | |
170 | - p(T theta) | |
171 | - { | |
172 | - T x,y; | |
173 | - y = 0.5*cos(theta*STIM_TAU/360.0)+0.5; | |
174 | - x = 0.5*sin(theta*STIM_TAU/360.0)+0.5; | |
175 | - return p(x,y); | |
176 | - } | |
189 | + | |
177 | 190 | |
178 | 191 | std::string str() const |
179 | 192 | { |
180 | 193 | std::stringstream ss; |
181 | - ss << "(P=" << P.str() << ", N=" << N.str() << ", U=" << U.str() << ", Y=" << Y.str(); | |
194 | + ss << "r = "<<R<<" (P=" << P.str() << ", N=" << N.str() << ", U=" << U.str() << ")"; | |
182 | 195 | return ss.str(); |
183 | 196 | } |
184 | 197 | ... | ... |
1 | +#ifndef STIM_CIRCLE_H | |
2 | +#define STIM_CIRCLE_H | |
3 | + | |
4 | +#include <stim/cuda/cudatools/callable.h> | |
5 | +#include <stim/math/plane.h> | |
6 | +#include <stim/math/vector.h> | |
7 | +#include <stim/math/triangle.h> | |
8 | +#include <stim/math/constants.h> | |
9 | +#include <assert.h> | |
10 | +#include <algorithm> | |
11 | +#include <iostream> | |
12 | + | |
13 | +namespace stim{ | |
14 | + | |
15 | +template <typename T> | |
16 | +class circle : plane<T> | |
17 | +{ | |
18 | + | |
19 | +private: | |
20 | + | |
21 | + stim::vec3<T> Y; | |
22 | + | |
23 | + CUDA_CALLABLE void | |
24 | + init() | |
25 | + { | |
26 | + Y = U.cross(N).norm(); | |
27 | + } | |
28 | + | |
29 | +public: | |
30 | + using stim::plane<T>::n; | |
31 | + using stim::plane<T>::P; | |
32 | + using stim::plane<T>::N; | |
33 | + using stim::plane<T>::U; | |
34 | + using stim::plane<T>::rotate; | |
35 | + using stim::plane<T>::setU; | |
36 | + | |
37 | + ///base constructor | |
38 | + ///@param th value of the angle of the starting point from 0 to 360. | |
39 | + CUDA_CALLABLE | |
40 | + circle() : plane<T>() | |
41 | + { | |
42 | + init(); | |
43 | + } | |
44 | + | |
45 | + ///create a rectangle given a size and position in Z space. | |
46 | + ///@param size: size of the rectangle in ND space. | |
47 | + ///@param z_pos z coordinate of the rectangle. | |
48 | + CUDA_CALLABLE | |
49 | + circle(T size, T z_pos = (T)0) : plane<T>() | |
50 | + { | |
51 | + center(stim::vec3<T>(0,0,z_pos)); | |
52 | + scale(size); | |
53 | + init(); | |
54 | + } | |
55 | + | |
56 | + ///create a rectangle from a center point, normal | |
57 | + ///@param c: x,y,z location of the center. | |
58 | + ///@param n: x,y,z direction of the normal. | |
59 | + CUDA_CALLABLE | |
60 | + circle(vec3<T> c, vec3<T> n = vec3<T>(0,0,1)) : plane<T>() | |
61 | + { | |
62 | + center(c); | |
63 | + normal(n); | |
64 | + init(); | |
65 | + } | |
66 | + | |
67 | + /*///create a rectangle from a center point, normal, and size | |
68 | + ///@param c: x,y,z location of the center. | |
69 | + ///@param s: size of the rectangle. | |
70 | + ///@param n: x,y,z direction of the normal. | |
71 | + CUDA_CALLABLE | |
72 | + circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1)) : plane<T>() | |
73 | + { | |
74 | + init(); | |
75 | + center(c); | |
76 | + rotate(n, U, Y); | |
77 | + scale(s); | |
78 | + } | |
79 | + */ | |
80 | + | |
81 | + ///create a rectangle from a center point, normal, and size | |
82 | + ///@param c: x,y,z location of the center. | |
83 | + ///@param s: size of the rectangle. | |
84 | + ///@param n: x,y,z direction of the normal. | |
85 | + ///@param u: x,y,z direction for the zero vector (from where the rotation starts) | |
86 | + CUDA_CALLABLE | |
87 | + circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1), vec3<T> u = vec3<T>(1, 0, 0)) : plane<T>() | |
88 | + { | |
89 | + init(); | |
90 | + setU(u); | |
91 | +// U = u; | |
92 | + center(c); | |
93 | + normal(n); | |
94 | + scale(s); | |
95 | + } | |
96 | + | |
97 | + ///scales the circle by a certain factor | |
98 | + ///@param factor: the factor by which the dimensions of the shape are scaled. | |
99 | + CUDA_CALLABLE | |
100 | + void scale(T factor) | |
101 | + { | |
102 | + U *= factor; | |
103 | + Y *= factor; | |
104 | + } | |
105 | + | |
106 | + ///sets the normal for the cirlce | |
107 | + ///@param n: x,y,z direction of the normal. | |
108 | + CUDA_CALLABLE void | |
109 | + normal(vec3<T> n) | |
110 | + { | |
111 | + rotate(n, Y); | |
112 | + } | |
113 | + | |
114 | + ///sets the center of the circle. | |
115 | + ///@param n: x,y,z location of the center. | |
116 | + CUDA_CALLABLE void | |
117 | + center(vec3<T> p){ | |
118 | + this->P = p; | |
119 | + } | |
120 | + | |
121 | + ///boolean comparison | |
122 | + bool | |
123 | + operator==(const circle<T> & rhs) | |
124 | + { | |
125 | + if(P == rhs.P && U == rhs.U && Y == rhs.Y) | |
126 | + return true; | |
127 | + else | |
128 | + return false; | |
129 | + } | |
130 | + | |
131 | + ///get the world space value given the planar coordinates a, b in [0, 1] | |
132 | + CUDA_CALLABLE stim::vec3<T> p(T a, T b) | |
133 | + { | |
134 | + stim::vec3<T> result; | |
135 | + | |
136 | + vec3<T> A = this->P - this->U * (T)0.5 - Y * (T)0.5; | |
137 | + result = A + this->U * a + Y * b; | |
138 | + return result; | |
139 | + } | |
140 | + | |
141 | + ///parenthesis operator returns the world space given rectangular coordinates a and b in [0 1] | |
142 | + CUDA_CALLABLE stim::vec3<T> operator()(T a, T b) | |
143 | + { | |
144 | + return p(a,b); | |
145 | + } | |
146 | + | |
147 | + ///returns a vector with the points on the initialized circle. | |
148 | + ///connecting the points results in a circle. | |
149 | + ///@param n: integer for the number of points representing the circle. | |
150 | + std::vector<stim::vec3<T> > | |
151 | + getPoints(int n) | |
152 | + { | |
153 | + std::vector<stim::vec3<T> > result; | |
154 | + stim::vec3<T> point; | |
155 | + T x,y; | |
156 | + float step = 360.0/(float) n; | |
157 | + for(float j = 0; j <= 360.0; j += step) | |
158 | + { | |
159 | + y = 0.5*cos(j*stim::TAU/360.0)+0.5; | |
160 | + x = 0.5*sin(j*stim::TAU/360.0)+0.5; | |
161 | + result.push_back(p(x,y)); | |
162 | + } | |
163 | + return result; | |
164 | + } | |
165 | + | |
166 | + ///returns a vector with the points on the initialized circle. | |
167 | + ///connecting the points results in a circle. | |
168 | + ///@param n: integer for the number of points representing the circle. | |
169 | + CUDA_CALLABLE stim::vec3<T> | |
170 | + p(T theta) | |
171 | + { | |
172 | + T x,y; | |
173 | + y = 0.5*cos(theta*STIM_TAU/360.0)+0.5; | |
174 | + x = 0.5*sin(theta*STIM_TAU/360.0)+0.5; | |
175 | + return p(x,y); | |
176 | + } | |
177 | + | |
178 | + std::string str() const | |
179 | + { | |
180 | + std::stringstream ss; | |
181 | + ss << "(P=" << P.str() << ", N=" << N.str() << ", U=" << U.str() << ", Y=" << Y.str(); | |
182 | + return ss.str(); | |
183 | + } | |
184 | + | |
185 | +}; | |
186 | +} | |
187 | +#endif | ... | ... |
stim/visualization/cylinder.h
... | ... | @@ -3,56 +3,163 @@ |
3 | 3 | #include <iostream> |
4 | 4 | #include <stim/math/circle.h> |
5 | 5 | #include <stim/biomodels/centerline.h> |
6 | +#include <stim/visualization/obj.h> | |
6 | 7 | |
7 | -/* | |
8 | - | |
9 | -*/ | |
10 | 8 | |
11 | 9 | namespace stim |
12 | 10 | { |
13 | 11 | template<typename T> |
14 | -class cylinder | |
15 | - : public centerline<T> | |
16 | -{ | |
17 | - private: | |
18 | - stim::circle<T> s; //an arbitrary circle | |
19 | - std::vector<stim::circle<T> > e; //an array of circles that store the centerline | |
20 | - | |
21 | - std::vector<stim::vec3<T> > norms; | |
22 | - std::vector<stim::vec<T> > Us; | |
23 | - std::vector<stim::vec<T> > mags; //stores a list of magnitudes for each point in the centerline (assuming mags[0] is the radius) | |
24 | - std::vector< T > L; //length of the cylinder at each position (pre-integration) | |
25 | - | |
26 | - | |
27 | - using stim::centerline<T>::c; | |
28 | - using stim::centerline<T>::N; | |
12 | +class cylinder : public centerline<T> { | |
13 | +protected: | |
14 | + //stim::circle<T> s; //an arbitrary circle | |
15 | + //std::vector<stim::circle<T> > e; //an array of circles that store the centerline | |
16 | + | |
17 | + //std::vector<stim::vec3<T> > norms; | |
18 | + std::vector< stim::vec3<T> > U; //stores the array of U vectors defining the Frenet frame | |
19 | + std::vector< std::vector<T> > M; //stores a list of magnitudes for each point in the centerline (assuming mags[0] is the radius) | |
20 | + //std::vector< T > L; //length of the cylinder at each position (pre-integration) | |
21 | + | |
22 | + | |
23 | + //using stim::centerline<T>::c; | |
24 | + //using stim::centerline<T>::N; | |
25 | + using stim::centerline<T>::size; | |
26 | + using stim::centerline<T>::at; | |
27 | + using stim::centerline<T>::findIdx; | |
29 | 28 | |
30 | - ///default init | |
31 | - void | |
32 | - init() | |
33 | - { | |
34 | - | |
29 | + //calculates the U values for each point to initialize the frenet frame | |
30 | + // this function assumes that the centerline has already been set | |
31 | + void init() { | |
32 | + U.resize(size()); //allocate space for the frenet frame vectors | |
33 | + | |
34 | + stim::circle<T> c; //create a circle | |
35 | + stim::vec3<T> d0, d1; | |
36 | + for (size_t i = 0; i < size() - 1; i++) { //for each line segment in the centerline | |
37 | + c.rotate(d(i)); //rotate the circle to match that normal | |
38 | + U[i] = c.U; //save the U vector from the circle | |
35 | 39 | } |
36 | - | |
37 | - ///Calculate the physical length of the fiber at each point in the fiber. | |
38 | - void | |
39 | - calculateL() | |
40 | - { | |
41 | -/* L.resize(inP.size()); | |
42 | - T temp = (T)0; | |
43 | - L[0] = 0; | |
44 | - for(size_t i = 1; i < L.size(); i++) | |
45 | - { | |
46 | - temp += (inP[i-1] - inP[i]).len(); | |
47 | - L[i] = temp; | |
40 | + U[size() - 1] = c.U; //for the last point, duplicate the final frenet frame vector | |
41 | + } | |
42 | + | |
43 | + ///adds a magnitude to each point in the cylinder | |
44 | + void add_mag(T val = 0) { | |
45 | + if (M.size() == 0) M.resize(size()); //if the magnitude vector isn't initialized, resize it to match the centerline | |
46 | + for (size_t i = 0; i < size(); i++) //for each point | |
47 | + M[i].push_back(val); //add this value to the magnitude vector at each point | |
48 | + } | |
49 | + | |
50 | + //adds a magnitude based on a list of magnitudes for each point | |
51 | + void add_mag(std::vector<T> val) { | |
52 | + if (M.size() == 0) M.resize(size()); //if the magnitude vector isn't initialized, resize it to match the centerline | |
53 | + for (size_t i = 0; i < size(); i++) //for each point | |
54 | + M[i].push_back(val[i]); //add this value to the magnitude vector at each point | |
55 | + } | |
56 | + | |
57 | +public: | |
58 | + std::string str() { | |
59 | + std::stringstream ss; | |
60 | + size_t N = std::vector< stim::vec3<T> >::size(); | |
61 | + ss << "---------[" << N << "]---------" << std::endl; | |
62 | + for (size_t i = 0; i < N; i++) | |
63 | + ss << std::vector< stim::vec3<T> >::at(i) << " r = "<< M[i][0]<<" u = "<<U[i]<<std::endl; | |
64 | + ss << "--------------------" << std::endl; | |
65 | + | |
66 | + return ss.str(); | |
67 | + } | |
68 | + | |
69 | + cylinder(centerline& c, T r = 0) : centerline(c) { | |
70 | + init(); | |
71 | + add_mag(r); | |
72 | + } | |
73 | + | |
74 | + //initialize a cylinder with a list of points and magnitude values | |
75 | + cylinder(centerline& c, std::vector<T> r) : centerline(c){ | |
76 | + init(); | |
77 | + add_mag(r); | |
78 | + } | |
79 | + | |
80 | + ///Returns magnitude i at the given length into the fiber (based on the pvalue). | |
81 | + ///Interpolates the position along the line. | |
82 | + ///@param l: the location of the in the cylinder. | |
83 | + ///@param idx: integer location of the point closest to l but prior to it. | |
84 | + T m(T l, int idx, size_t i = 0) { | |
85 | + T a = (l - L[idx]) / (L[idx + 1] - L[idx]); | |
86 | + T v2 = (M[idx][i] + (M[idx + 1][i] - M[idx][i])*a); | |
87 | + | |
88 | + return v2; | |
89 | + } | |
90 | + | |
91 | + ///Returns the ith magnitude at the given p-value (p value ranges from 0 to 1). | |
92 | + ///interpolates the radius along the line. | |
93 | + ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). | |
94 | + T m(T pvalue, size_t i = 0) { | |
95 | + if (pvalue <= 0.0) return M[0][i]; | |
96 | + if (pvalue >= 1.0) return M[size() - 1][i]; | |
97 | + | |
98 | + T l = pvalue*L[L.size() - 1]; | |
99 | + int idx = findIdx(l); | |
100 | + return m(l, idx, i); | |
101 | + } | |
102 | + | |
103 | + ///Returns a circle representing the cylinder cross section at point i | |
104 | + stim::circle<T> circ(size_t i, size_t m = 0) { | |
105 | + return stim::circle<T>(at(i), M[i][m], d(i), U[i]); | |
106 | + } | |
107 | + | |
108 | + ///Returns an OBJ object representing the cylinder with a radial tesselation value of N using magnitude m | |
109 | + stim::obj<T> OBJ(size_t N, size_t m = 0) { | |
110 | + stim::obj<T> out; //create an OBJ object | |
111 | + stim::circle<T> c0, c1; | |
112 | + std::vector< stim::vec3<T> > p0, p1; //allocate space for the point sets representing the circles bounding each cylinder segment | |
113 | + T u0, u1, v0, v1; //allocate variables to store running texture coordinates | |
114 | + for (size_t i = 1; i < size(); i++) { //for each line segment in the cylinder | |
115 | + c0 = circ(i - 1); //get the two circles bounding the line segment | |
116 | + c1 = circ(i); | |
117 | + | |
118 | + p0 = c0.points(N); //get t points for each of the end caps | |
119 | + p1 = c1.points(N); | |
120 | + | |
121 | + u0 = L[i - 1] / length(); //calculate the texture coordinate (u, v) where u runs along the cylinder length | |
122 | + u1 = L[i] / length(); | |
123 | + | |
124 | + for (size_t n = 1; n < N; n++) { //for each point in the circle | |
125 | + v0 = (double)(n-1) / (double)(N - 1); //v texture coordinate runs around the cylinder | |
126 | + v1 = (double)(n) / (double)(N - 1); | |
127 | + out.Begin(OBJ_FACE); //start a face (quad) | |
128 | + out.TexCoord(u0, v0); | |
129 | + out.Vertex(p0[n - 1][0], p0[n - 1][1], p0[n - 1][2]); //output the points composing a strip of quads wrapping the cylinder segment | |
130 | + out.TexCoord(u1, v0); | |
131 | + out.Vertex(p1[n - 1][0], p1[n - 1][1], p1[n - 1][2]); | |
132 | + | |
133 | + out.TexCoord(u0, v1); | |
134 | + out.Vertex(p1[n][0], p1[n][1], p1[n][2]); | |
135 | + out.TexCoord(u1, v1); | |
136 | + out.Vertex(p0[n][0], p0[n][1], p0[n][2]); | |
137 | + out.End(); | |
48 | 138 | } |
49 | -*/ } | |
139 | + v0 = (double)(N - 2) / (double)(N - 1); //v texture coordinate runs around the cylinder | |
140 | + v1 = 1.0; | |
141 | + out.Begin(OBJ_FACE); | |
142 | + out.TexCoord(u0, v0); | |
143 | + out.Vertex(p0[N - 1][0], p0[N - 1][1], p0[N - 1][2]); //output the points composing a strip of quads wrapping the cylinder segment | |
144 | + out.TexCoord(u1, v0); | |
145 | + out.Vertex(p1[N - 1][0], p1[N - 1][1], p1[N - 1][2]); | |
146 | + | |
147 | + out.TexCoord(u0, v1); | |
148 | + out.Vertex(p1[0][0], p1[0][1], p1[0][2]); | |
149 | + out.TexCoord(u1, v1); | |
150 | + out.Vertex(p0[0][0], p0[0][1], p0[0][2]); | |
151 | + out.End(); | |
152 | + } | |
153 | + return out; | |
154 | + } | |
50 | 155 | |
51 | - ///inits the cylinder from a list of points (std::vector of stim::vec3 --inP) and radii (inM) | |
156 | + | |
157 | + /* | |
158 | + ///inits the cylinder from a list of points (std::vector of stim::vec3 --inP) and magnitudes (inM) | |
52 | 159 | void |
53 | - init(std::vector<stim::vec3<T> > inP, std::vector<stim::vec<T> > inM) | |
54 | - { | |
55 | - mags = inM; | |
160 | + init(centerline inP, std::vector< std::vector<T> > inM) { | |
161 | + M = inM; //the magnitude vector can be copied directly | |
162 | + (*this) = inP; //the centerline can be copied to this class directly | |
56 | 163 | stim::vec3<float> v1; |
57 | 164 | stim::vec3<float> v2; |
58 | 165 | e.resize(inP.size()); |
... | ... | @@ -246,13 +353,18 @@ class cylinder |
246 | 353 | init(inP, inM); |
247 | 354 | } |
248 | 355 | |
356 | + //assignment operator creates a cylinder from a centerline (default radius is zero) | |
357 | + cylinder& operator=(stim::centerline<T> c) { | |
358 | + init(c); | |
359 | + } | |
360 | + | |
249 | 361 | ///Returns the number of points on the cylinder centerline |
250 | 362 | |
251 | 363 | unsigned int size(){ |
252 | 364 | return N; |
253 | 365 | } |
254 | 366 | |
255 | - | |
367 | + | |
256 | 368 | ///Returns a position vector at the given p-value (p value ranges from 0 to 1). |
257 | 369 | ///interpolates the position along the line. |
258 | 370 | ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). |
... | ... | @@ -266,22 +378,7 @@ class cylinder |
266 | 378 | T l = pvalue*L[L.size()-1]; |
267 | 379 | int idx = findIdx(l); |
268 | 380 | return (p(l,idx)); |
269 | -/* T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
270 | - stim::vec3<T> v1( | |
271 | - c[idx][0], | |
272 | - c[idx][1], | |
273 | - c[idx][2] | |
274 | - ); | |
275 | - | |
276 | - stim::vec3<T> v2( | |
277 | - c[idx+1][0], | |
278 | - c[idx+1][1], | |
279 | - c[idx+1][2] | |
280 | - ); | |
281 | - | |
282 | -// return( e[idx].P + (e[idx+1].P-e[idx].P)*rat); | |
283 | - return( v1 + (v2 - v1)*rat); | |
284 | -*/ } | |
381 | + } | |
285 | 382 | |
286 | 383 | ///Returns a position vector at the given length into the fiber (based on the pvalue). |
287 | 384 | ///Interpolates the radius along the line. |
... | ... | @@ -321,10 +418,7 @@ class cylinder |
321 | 418 | T l = pvalue*L[L.size()-1]; |
322 | 419 | int idx = findIdx(l); |
323 | 420 | return (r(l,idx)); |
324 | -/* T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
325 | -// return (mags[idx][0] + (mags[idx+1][0]-mags[idx][0])*rat); | |
326 | - return (e[idx].U.len() + (e[idx+1].U.len() - e[idx].U.len())*rat); | |
327 | -*/ } | |
421 | + } | |
328 | 422 | |
329 | 423 | ///Returns a radius at the given length into the fiber (based on the pvalue). |
330 | 424 | ///Interpolates the position along the line. |
... | ... | @@ -506,7 +600,7 @@ class cylinder |
506 | 600 | |
507 | 601 | return cylinder<T>(result); |
508 | 602 | |
509 | - } | |
603 | + }*/ | |
510 | 604 | |
511 | 605 | |
512 | 606 | }; | ... | ... |
1 | +#ifndef STIM_CYLINDER_H | |
2 | +#define STIM_CYLINDER_H | |
3 | +#include <iostream> | |
4 | +#include <stim/math/circle.h> | |
5 | +#include <stim/biomodels/centerline.h> | |
6 | + | |
7 | + | |
8 | +namespace stim | |
9 | +{ | |
10 | +template<typename T> | |
11 | +class cylinder | |
12 | + : public centerline<T> | |
13 | +{ | |
14 | + private: | |
15 | + stim::circle<T> s; //an arbitrary circle | |
16 | + std::vector<stim::circle<T> > e; //an array of circles that store the centerline | |
17 | + | |
18 | + std::vector<stim::vec3<T> > norms; | |
19 | + std::vector<stim::vec<T> > Us; | |
20 | + std::vector<stim::vec<T> > mags; //stores a list of magnitudes for each point in the centerline (assuming mags[0] is the radius) | |
21 | + std::vector< T > L; //length of the cylinder at each position (pre-integration) | |
22 | + | |
23 | + | |
24 | + using stim::centerline<T>::c; | |
25 | + using stim::centerline<T>::N; | |
26 | + | |
27 | + ///default init | |
28 | + void | |
29 | + init() | |
30 | + { | |
31 | + | |
32 | + } | |
33 | + | |
34 | + ///inits the cylinder from a list of points (std::vector of stim::vec3 --inP) and radii (inM) | |
35 | + void | |
36 | + init(std::vector<stim::vec3<T> > inP, std::vector<stim::vec<T> > inM) | |
37 | + { | |
38 | + mags = inM; | |
39 | + stim::vec3<float> v1; | |
40 | + stim::vec3<float> v2; | |
41 | + e.resize(inP.size()); | |
42 | + | |
43 | + norms.resize(inP.size()); | |
44 | + Us.resize(inP.size()); | |
45 | + | |
46 | + if(inP.size() < 2) | |
47 | + return; | |
48 | + | |
49 | + //calculate each L. | |
50 | + L.resize(inP.size()); //the number of precomputed lengths will equal the number of points | |
51 | + T temp = (T)0; //length up to that point | |
52 | + L[0] = temp; | |
53 | + for(size_t i = 1; i < L.size(); i++) | |
54 | + { | |
55 | + temp += (inP[i-1] - inP[i]).len(); | |
56 | + L[i] = temp; | |
57 | + } | |
58 | + | |
59 | + stim::vec3<T> dr = (inP[1] - inP[0]).norm(); | |
60 | + s = stim::circle<T>(inP[0], inM[0][0], dr, stim::vec3<T>(1,0,0)); | |
61 | + norms[0] = s.N; | |
62 | + e[0] = s; | |
63 | + Us[0] = e[0].U; | |
64 | + for(size_t i = 1; i < inP.size()-1; i++) | |
65 | + { | |
66 | + s.center(inP[i]); | |
67 | + v1 = (inP[i] - inP[i-1]).norm(); | |
68 | + v2 = (inP[i+1] - inP[i]).norm(); | |
69 | + dr = (v1+v2).norm(); | |
70 | + s.normal(dr); | |
71 | + | |
72 | + norms[i] = s.N; | |
73 | + | |
74 | + s.scale(inM[i][0]/inM[i-1][0]); | |
75 | + e[i] = s; | |
76 | + Us[i] = e[i].U; | |
77 | + } | |
78 | + | |
79 | + int j = inP.size()-1; | |
80 | + s.center(inP[j]); | |
81 | + dr = (inP[j] - inP[j-1]).norm(); | |
82 | + s.normal(dr); | |
83 | + | |
84 | + norms[j] = s.N; | |
85 | + | |
86 | + s.scale(inM[j][0]/inM[j-1][0]); | |
87 | + e[j] = s; | |
88 | + Us[j] = e[j].U; | |
89 | + } | |
90 | + | |
91 | + ///returns the direction vector at point idx. | |
92 | + stim::vec3<T> | |
93 | + d(int idx) | |
94 | + { | |
95 | + if(idx == 0) | |
96 | + { | |
97 | + stim::vec3<T> temp( | |
98 | + c[idx+1][0]-c[idx][0], | |
99 | + c[idx+1][1]-c[idx][1], | |
100 | + c[idx+1][2]-c[idx][2] | |
101 | + ); | |
102 | +// return (e[idx+1].P - e[idx].P).norm(); | |
103 | + return (temp.norm()); | |
104 | + } | |
105 | + else if(idx == N-1) | |
106 | + { | |
107 | + stim::vec3<T> temp( | |
108 | + c[idx][0]-c[idx+1][0], | |
109 | + c[idx][1]-c[idx+1][1], | |
110 | + c[idx][2]-c[idx+1][2] | |
111 | + ); | |
112 | + // return (e[idx].P - e[idx-1].P).norm(); | |
113 | + return (temp.norm()); | |
114 | + } | |
115 | + else | |
116 | + { | |
117 | +// return (e[idx+1].P - e[idx].P).norm(); | |
118 | +// stim::vec3<float> v1 = (e[idx].P-e[idx-1].P).norm(); | |
119 | + stim::vec3<T> v1( | |
120 | + c[idx][0]-c[idx-1][0], | |
121 | + c[idx][1]-c[idx-1][1], | |
122 | + c[idx][2]-c[idx-1][2] | |
123 | + ); | |
124 | + | |
125 | +// stim::vec3<float> v2 = (e[idx+1].P-e[idx].P).norm(); | |
126 | + stim::vec3<T> v2( | |
127 | + c[idx+1][0]-c[idx][0], | |
128 | + c[idx+1][1]-c[idx][1], | |
129 | + c[idx+1][2]-c[idx][2] | |
130 | + ); | |
131 | + | |
132 | + return (v1.norm()+v2.norm()).norm(); | |
133 | + } | |
134 | + // return e[idx].N; | |
135 | + | |
136 | + } | |
137 | + | |
138 | + stim::vec3<T> | |
139 | + d(T l, int idx) | |
140 | + { | |
141 | + if(idx == 0 || idx == N-1) | |
142 | + { | |
143 | + return norms[idx]; | |
144 | +// return e[idx].N; | |
145 | + } | |
146 | + else | |
147 | + { | |
148 | + | |
149 | + T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
150 | + return( norms[idx] + (norms[idx+1] - norms[idx])*rat); | |
151 | +// return( e[idx].N + (e[idx+1].N - e[idx].N)*rat); | |
152 | + } | |
153 | + } | |
154 | + | |
155 | + | |
156 | + ///finds the index of the point closest to the length l on the lower bound. | |
157 | + ///binary search. | |
158 | + int | |
159 | + findIdx(T l) | |
160 | + { | |
161 | + unsigned int i = L.size()/2; | |
162 | + unsigned int max = L.size()-1; | |
163 | + unsigned int min = 0; | |
164 | + while(i > 0 && i < L.size()-1) | |
165 | + { | |
166 | +// std::cerr << "Trying " << i << std::endl; | |
167 | +// std::cerr << "l is " << l << ", L[" << i << "]" << L[i] << std::endl; | |
168 | + if(l < L[i]) | |
169 | + { | |
170 | + max = i; | |
171 | + i = min+(max-min)/2; | |
172 | + } | |
173 | + else if(L[i] <= l && L[i+1] >= l) | |
174 | + { | |
175 | + break; | |
176 | + } | |
177 | + else | |
178 | + { | |
179 | + min = i; | |
180 | + i = min+(max-min)/2; | |
181 | + } | |
182 | + } | |
183 | + return i; | |
184 | + } | |
185 | + | |
186 | + public: | |
187 | + ///default constructor | |
188 | + cylinder() | |
189 | + // : centerline<T>() | |
190 | + { | |
191 | + | |
192 | + } | |
193 | + | |
194 | + ///constructor to create a cylinder from a set of points, radii, and the number of sides for the cylinder. | |
195 | + ///@param inP: Vector of stim vec3 composing the points of the centerline. | |
196 | + ///@param inM: Vector of stim vecs composing the radii of the centerline. | |
197 | + cylinder(std::vector<stim::vec3<T> > inP, std::vector<stim::vec<T> > inM) | |
198 | + : centerline<T>(inP) | |
199 | + { | |
200 | + init(inP, inM); | |
201 | + } | |
202 | + | |
203 | + ///constructor to create a cylinder from a set of points, radii, and the number of sides for the cylinder. | |
204 | + ///@param inP: Vector of stim vec3 composing the points of the centerline. | |
205 | + ///@param inM: Vector of stim vecs composing the radii of the centerline. | |
206 | + cylinder(std::vector<stim::vec3<T> > inP, std::vector< T > inM) | |
207 | + : centerline<T>(inP) | |
208 | + { | |
209 | + std::vector<stim::vec<T> > temp; | |
210 | + stim::vec<T> zero(0.0,0.0); | |
211 | + temp.resize(inM.size(), zero); | |
212 | + for(int i = 0; i < inM.size(); i++) | |
213 | + temp[i][0] = inM[i]; | |
214 | + init(inP, temp); | |
215 | + } | |
216 | + | |
217 | + | |
218 | + ///Constructor defines a cylinder with centerline inP and magnitudes of zero | |
219 | + ///@param inP: Vector of stim vec3 composing the points of the centerline | |
220 | + cylinder(std::vector< stim::vec3<T> > inP) | |
221 | + : centerline<T>(inP) | |
222 | + { | |
223 | + std::vector< stim::vec<T> > inM; //create an array of arbitrary magnitudes | |
224 | + | |
225 | + stim::vec<T> zero; | |
226 | + zero.push_back(0); | |
227 | + | |
228 | + inM.resize(inP.size(), zero); //initialize the magnitude values to zero | |
229 | + init(inP, inM); | |
230 | + } | |
231 | + | |
232 | + ///Returns the number of points on the cylinder centerline | |
233 | + | |
234 | + unsigned int size(){ | |
235 | + return N; | |
236 | + } | |
237 | + | |
238 | + | |
239 | + ///Returns a position vector at the given p-value (p value ranges from 0 to 1). | |
240 | + ///interpolates the position along the line. | |
241 | + ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). | |
242 | + stim::vec3<T> | |
243 | + p(T pvalue) | |
244 | + { | |
245 | + if(pvalue < 0.0 || pvalue > 1.0) | |
246 | + { | |
247 | + return stim::vec3<float>(-1,-1,-1); | |
248 | + } | |
249 | + T l = pvalue*L[L.size()-1]; | |
250 | + int idx = findIdx(l); | |
251 | + return (p(l,idx)); | |
252 | +/* T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
253 | + stim::vec3<T> v1( | |
254 | + c[idx][0], | |
255 | + c[idx][1], | |
256 | + c[idx][2] | |
257 | + ); | |
258 | + | |
259 | + stim::vec3<T> v2( | |
260 | + c[idx+1][0], | |
261 | + c[idx+1][1], | |
262 | + c[idx+1][2] | |
263 | + ); | |
264 | + | |
265 | +// return( e[idx].P + (e[idx+1].P-e[idx].P)*rat); | |
266 | + return( v1 + (v2 - v1)*rat); | |
267 | +*/ } | |
268 | + | |
269 | + ///Returns a position vector at the given length into the fiber (based on the pvalue). | |
270 | + ///Interpolates the radius along the line. | |
271 | + ///@param l: the location of the in the cylinder. | |
272 | + ///@param idx: integer location of the point closest to l but prior to it. | |
273 | + stim::vec3<T> | |
274 | + p(T l, int idx) | |
275 | + { | |
276 | + T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
277 | + stim::vec3<T> v1( | |
278 | + c[idx][0], | |
279 | + c[idx][1], | |
280 | + c[idx][2] | |
281 | + ); | |
282 | + | |
283 | + stim::vec3<T> v2( | |
284 | + c[idx+1][0], | |
285 | + c[idx+1][1], | |
286 | + c[idx+1][2] | |
287 | + ); | |
288 | +// return( e[idx].P + (e[idx+1].P-e[idx].P)*rat); | |
289 | + return( v1 + (v2-v1)*rat); | |
290 | +// return( | |
291 | +// return (pos[idx] + (pos[idx+1]-pos[idx])*((l-L[idx])/(L[idx+1]- L[idx]))); | |
292 | + } | |
293 | + | |
294 | + ///Returns a radius at the given p-value (p value ranges from 0 to 1). | |
295 | + ///interpolates the radius along the line. | |
296 | + ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). | |
297 | + T | |
298 | + r(T pvalue) | |
299 | + { | |
300 | + if(pvalue < 0.0 || pvalue > 1.0){ | |
301 | + std::cerr<<"Error, value "<<pvalue<<" is outside of [0 1]."<<std::endl; | |
302 | + exit(1); | |
303 | + } | |
304 | + T l = pvalue*L[L.size()-1]; | |
305 | + int idx = findIdx(l); | |
306 | + return (r(l,idx)); | |
307 | +/* T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
308 | +// return (mags[idx][0] + (mags[idx+1][0]-mags[idx][0])*rat); | |
309 | + return (e[idx].U.len() + (e[idx+1].U.len() - e[idx].U.len())*rat); | |
310 | +*/ } | |
311 | + | |
312 | + ///Returns a radius at the given length into the fiber (based on the pvalue). | |
313 | + ///Interpolates the position along the line. | |
314 | + ///@param l: the location of the in the cylinder. | |
315 | + ///@param idx: integer location of the point closest to l but prior to it. | |
316 | + T | |
317 | + r(T l, int idx) | |
318 | + { | |
319 | + T rat = (l-L[idx])/(L[idx+1]-L[idx]); | |
320 | + T v1 = (e[idx].U.len() + (e[idx+1].U.len() - e[idx].U.len())*rat); | |
321 | + T v3 = (Us[idx].len() + (Us[idx+1].len() - Us[idx].len())*rat); | |
322 | + T v2 = (mags[idx][0] + (mags[idx+1][0]-mags[idx][0])*rat); | |
323 | +// std::cout << (float)v1 = (float) v2 << std::endl; | |
324 | + if(abs(v3 - v1) >= 10e-6) | |
325 | + { | |
326 | + std::cout << "-------------------------" << std::endl; | |
327 | + std::cout << e[idx].str() << std::endl << std::endl; | |
328 | + std::cout << Us[idx].str() << std::endl; | |
329 | + std::cout << (float)v1 - (float) v2 << std::endl; | |
330 | + std::cout << "failed" << std::endl; | |
331 | + } | |
332 | +// std::cout << e[idx].U.len() << " " << mags[idx][0] << std::endl; | |
333 | +// std::cout << v2 << std::endl; | |
334 | + return(v2); | |
335 | +// return (mags[idx][0] + (mags[idx+1][0]-mags[idx][0])*rat); | |
336 | + // ( | |
337 | + } | |
338 | + | |
339 | + /// Returns the magnitude at the given index | |
340 | + /// @param i is the index of the desired point | |
341 | + /// @param m is the index of the magnitude value | |
342 | + T ri(unsigned i, unsigned m = 0){ | |
343 | + return mags[i][m]; | |
344 | + } | |
345 | + | |
346 | + /// Adds a new magnitude value to all points | |
347 | + /// @param m is the starting value for the new magnitude | |
348 | + void add_mag(T m = 0){ | |
349 | + for(unsigned int p = 0; p < N; p++) | |
350 | + mags[p].push_back(m); | |
351 | + } | |
352 | + | |
353 | + /// Sets a magnitude value | |
354 | + /// @param val is the new value for the magnitude | |
355 | + /// @param p is the point index for the magnitude to be set | |
356 | + /// @param m is the index for the magnitude | |
357 | + void set_mag(T val, unsigned p, unsigned m = 0){ | |
358 | + mags[p][m] = val; | |
359 | + } | |
360 | + | |
361 | + /// Returns the number of magnitude values at each point | |
362 | + unsigned nmags(){ | |
363 | + return mags[0].size(); | |
364 | + } | |
365 | + | |
366 | + ///returns the position of the point with a given pvalue and theta on the surface | |
367 | + ///in x, y, z coordinates. Theta is in degrees from 0 to 360. | |
368 | + ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). | |
369 | + ///@param theta: the angle to the point of a circle. | |
370 | + stim::vec3<T> | |
371 | + surf(T pvalue, T theta) | |
372 | + { | |
373 | + if(pvalue < 0.0 || pvalue > 1.0) | |
374 | + { | |
375 | + return stim::vec3<float>(-1,-1,-1); | |
376 |