Commit eb119a4f8520f37c648a94435f159c025a4b2743
1 parent
9f5c0d4a
renamed fiber into centerline and removed all of the radius information from fiber.
Showing
1 changed file
with
0 additions
and
483 deletions
Show diff stats
stim/biomodels/fiber.h deleted
1 | -#ifndef STIM_FIBER_H | |
2 | -#define STIM_FIBER_H | |
3 | - | |
4 | -#include <vector> | |
5 | -#include <ANN/ANN.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 fiber{ | |
15 | - | |
16 | -protected: | |
17 | - unsigned int N; //number of points in the fiber | |
18 | - double **c; //centerline (array of double pointers) | |
19 | - | |
20 | - T* r; // array of fiber radii | |
21 | - ANNkd_tree* kdt; //kd-tree stores all points in the fiber for fast searching | |
22 | - | |
23 | - /// Initialize an empty fiber | |
24 | - void init() | |
25 | - { | |
26 | - kdt = NULL; | |
27 | - c=NULL; | |
28 | - r=NULL; | |
29 | - N=0; | |
30 | - } | |
31 | - | |
32 | - /// Initialize a fiber with N centerline points (all located at [0, 0, 0] with radius 0) | |
33 | - void init(unsigned int n) | |
34 | - { | |
35 | - | |
36 | - N = n; //set the number of points | |
37 | - kdt = NULL; | |
38 | - c = (double**) malloc(sizeof(double*) * N); //allocate the array pointer | |
39 | - | |
40 | - for(unsigned int i = 0; i < N; i++) //allocate space for each point | |
41 | - c[i] = (double*) malloc(sizeof(double) * 3); | |
42 | - | |
43 | - r = (T*) malloc(sizeof(T) * N); //allocate space for the radii | |
44 | - } | |
45 | - | |
46 | - /// Copies an existing fiber to the current fiber | |
47 | - | |
48 | - /// @param cpy stores the new copy of the fiber | |
49 | - void copy( const stim::fiber<T>& cpy ){ | |
50 | - | |
51 | - ///allocate space for the new fiber | |
52 | - init(cpy.N); | |
53 | - | |
54 | - ///copy the points | |
55 | - for(unsigned int i = 0; i < N; i++){ | |
56 | - for(unsigned int d = 0; d < 3; d++) //for each dimension | |
57 | - c[i][d] = cpy.c[i][d]; //copy the coordinate | |
58 | - | |
59 | - r[i] = cpy.r[i]; //copy the radius | |
60 | - } | |
61 | - | |
62 | - gen_kdtree(); //generate the kd tree for the new fiber | |
63 | - } | |
64 | - | |
65 | - /// generate a KD tree for points on fiber | |
66 | - void gen_kdtree() | |
67 | - { | |
68 | - int n_data = N; //create an array of data points | |
69 | - ANNpointArray pts = (ANNpointArray)c; //cast the centerline list to an ANNpointArray | |
70 | - kdt = new ANNkd_tree(pts, n_data, 3); //build a KD tree | |
71 | - } | |
72 | - | |
73 | - /// find distance between two points | |
74 | - double dist(double* p0, double* p1){ | |
75 | - | |
76 | - double sum = 0; // initialize variables | |
77 | - float v; | |
78 | - for(unsigned int d = 0; d < 3; d++) | |
79 | - { | |
80 | - v = p1[d] - p0[d]; | |
81 | - sum +=v * v; | |
82 | - | |
83 | - } | |
84 | - return sqrt(sum); | |
85 | - } | |
86 | - | |
87 | - /// This function retreives the index for the fiber point closest to q | |
88 | - | |
89 | - /// @param q is a reference point used to find the closest point on the fiber center line | |
90 | - unsigned int ann( stim::vec<double> q ){ | |
91 | - | |
92 | - ANNidxArray idx = new ANNidx[1]; //variable used to hold the nearest point | |
93 | - ANNdistArray sq_dist = new ANNdist[1]; //variable used to hold the squared distance to the nearest point | |
94 | - | |
95 | - kdt->annkSearch(q.data(), 1, idx, sq_dist); //search the KD tree for the nearest neighbor | |
96 | - | |
97 | - return *idx; | |
98 | - } | |
99 | - | |
100 | - /// Returns a stim::vec representing the point at index i | |
101 | - | |
102 | - /// @param i is an index of the desired centerline point | |
103 | - stim::vec<T> get_vec(unsigned i){ | |
104 | - stim::vec<T> r; | |
105 | - r.resize(3); | |
106 | - r[0] = c[i][0]; | |
107 | - r[1] = c[i][1]; | |
108 | - r[2] = c[i][2]; | |
109 | - | |
110 | - return r; | |
111 | - } | |
112 | - | |
113 | - | |
114 | -public: | |
115 | - | |
116 | - fiber(){ | |
117 | - init(); | |
118 | - } | |
119 | - | |
120 | - /// Copy constructor | |
121 | - fiber(const stim::fiber<T> &obj){ | |
122 | - | |
123 | - copy(obj); | |
124 | - | |
125 | - } | |
126 | - | |
127 | - //temp constructor for graph visualization | |
128 | - fiber(int n) | |
129 | - { | |
130 | - init(n); | |
131 | - } | |
132 | - | |
133 | - /// Constructor takes a list of stim::vec points, the radius at each point is set to zero | |
134 | - fiber(std::vector< stim::vec<T> > p){ | |
135 | - init(p.size()); //initialize the fiber | |
136 | - | |
137 | - //for each point, set the centerline position and radius | |
138 | - for(unsigned int i = 0; i < N; i++){ | |
139 | - | |
140 | - //set the centerline position | |
141 | - for(unsigned int d = 0; d < 3; d++) | |
142 | - c[i][d] = (double) p[i][d]; | |
143 | - | |
144 | - //set the radius | |
145 | - r[i] = 0; | |
146 | - } | |
147 | - | |
148 | - //generate a kd tree | |
149 | - gen_kdtree(); | |
150 | - } | |
151 | - | |
152 | - /// constructor takes a list of points and radii | |
153 | - fiber(std::vector< stim::vec< T > > pos, std::vector< T > radii){ | |
154 | - init(pos.size()); //initialize the fiber | |
155 | - | |
156 | - //for each point, set the centerline position and radius | |
157 | - for(unsigned int i = 0; i < N; i++){ | |
158 | - | |
159 | - //set the centerline position | |
160 | - for(unsigned int d = 0; d < 3; d++) | |
161 | - c[i][d] = (double) pos[i][d]; | |
162 | - | |
163 | - //set the radius | |
164 | - r[i] = radii[i]; | |
165 | - } | |
166 | - | |
167 | - //generate a kd tree | |
168 | - gen_kdtree(); | |
169 | - } | |
170 | - | |
171 | - /// constructor takes an array of points and radii | |
172 | - // this function is used when the radii are represented as a stim::vec, | |
173 | - // since this may be easier when importing OBJs | |
174 | - fiber(std::vector< stim::vec<T> > pos, std::vector< stim::vec<T> > radii){ | |
175 | - | |
176 | - init(pos.size()); | |
177 | - | |
178 | - //for each point, set the position and radius | |
179 | - for(unsigned int i = 0; i < N; i++){ | |
180 | - //at(i) = (double*)malloc(sizeof(double) * 3); | |
181 | - for(unsigned int d = 0; d < 3; d++) | |
182 | - c[i][d] = (double) pos[i][d]; | |
183 | - | |
184 | - r[i] = radii[i][(unsigned int)0]; | |
185 | - } | |
186 | - | |
187 | - gen_kdtree(); | |
188 | - } | |
189 | - | |
190 | - /// Assignment operation | |
191 | - fiber& operator=(const fiber &rhs){ | |
192 | - | |
193 | - if(this == &rhs) return *this; //test for and handle self-assignment | |
194 | - | |
195 | - copy(rhs); | |
196 | - } | |
197 | - | |
198 | - /// Calculate the length of the fiber and return it. | |
199 | - double length(){ | |
200 | - | |
201 | - double* p0; | |
202 | - double *p1; | |
203 | - double l = 0; //initialize the length to zero | |
204 | - | |
205 | - //for each point | |
206 | - //typename std::list< point<T> >::iterator i; //create a point iterator | |
207 | - for(unsigned int i = 0; i < N; i++){ //for each point in the fiber | |
208 | - | |
209 | - if(i == 0) //if this is the first point, just store it | |
210 | - p1 = c[0]; | |
211 | - else{ //if this is any other point | |
212 | - p0 = p1; //shift p1->p0 | |
213 | - p1 = c[i]; //set p1 to the new point | |
214 | - l += dist(p0, p1); //add the length of p1 - p0 to the running sum | |
215 | - } | |
216 | - } | |
217 | - | |
218 | - return l; //return the length | |
219 | - } | |
220 | - | |
221 | - /// Calculates the length and average radius of the fiber | |
222 | - | |
223 | - /// @param length is filled with the fiber length | |
224 | - T radius(T& length){ | |
225 | - | |
226 | - double* p0; //temporary variables to store point positions | |
227 | - double* p1; | |
228 | - T r0, r1; //temporary variables to store radii at points | |
229 | - double l; | |
230 | - T r_mean; //temporary variable to store the length and average radius of a fiber segment | |
231 | - double length_sum = 0; //initialize the length to zero | |
232 | - T radius_sum = 0; //initialize the radius sum to zero | |
233 | - | |
234 | - //for each point | |
235 | - //typename std::list< point<T> >::iterator i; //create a point iterator | |
236 | - for(unsigned int i = 0; i < N; i++){ //for each point in the fiber | |
237 | - | |
238 | - if(i == 0){ //if this is the first point, just store it | |
239 | - p1 = c[0]; | |
240 | - r1 = r[0]; | |
241 | - } | |
242 | - else{ //if this is any other point | |
243 | - p0 = p1; //shift p1->p0 and r1->r0 | |
244 | - r0 = r1; | |
245 | - p1 = c[i]; //set p1 to the new point | |
246 | - r1 = r[i]; | |
247 | - | |
248 | - l = dist(p0, p1); //calculate the length of the p0-p1 segment | |
249 | - r_mean = (r0 + r1) / 2; //calculate the average radius of the segment | |
250 | - | |
251 | - radius_sum += r_mean * (T) l; //add the radius scaled by the length to a running sum | |
252 | - length_sum += l; //add the length of p1 - p0 to the running sum | |
253 | - } | |
254 | - } | |
255 | - | |
256 | - length = length_sum; //store the total length | |
257 | - | |
258 | - //if the total length is zero, store a radius of zero | |
259 | - if(length == 0) | |
260 | - return 0; | |
261 | - else | |
262 | - return (T)(radius_sum / length); //return the average radius of the fiber | |
263 | - } | |
264 | - T average_radius() | |
265 | - { | |
266 | - T r_sum = 0.; | |
267 | - for(unsigned int i = 0; i < N; i++) | |
268 | - { | |
269 | - r_sum = r_sum + r[i]; | |
270 | - } | |
271 | - return r_sum/((T) N); | |
272 | - } | |
273 | - | |
274 | - /// Calculates the average radius of the fiber | |
275 | - T radius(){ | |
276 | - T length; | |
277 | - return radius(length); | |
278 | - } | |
279 | - | |
280 | - /// Returns the radius at index idx. | |
281 | - T radius(int idx){ | |
282 | - return r[idx]; | |
283 | - } | |
284 | - | |
285 | - /// Return the point on the fiber closest to q | |
286 | - /// @param q is the query point used to locate the nearest point on the fiber centerline | |
287 | - stim::vec<T> nearest(stim::vec<T> q){ | |
288 | - | |
289 | - stim::vec<double> temp( (double) q[0], (double) q[1], (double) q[2]); | |
290 | - | |
291 | - unsigned int idx = ann(temp); //determine the index of the nearest neighbor | |
292 | - | |
293 | - return stim::vec<T>((T) c[idx][0], (T) c[idx][1], (T) c[idx][2]); //return the nearest centerline point | |
294 | - } | |
295 | - | |
296 | - /// Return the point index on the fiber closest to q | |
297 | - /// @param q is the query point used to locate the nearest point on the fiber centerline | |
298 | - unsigned int nearest_idx(stim::vec<T> q){ | |
299 | - | |
300 | - stim::vec<double> temp((double) q[0], (double) q[1], (double) q[2]); | |
301 | - | |
302 | - unsigned int idx = ann(temp); //determine the index of the nearest neighbor | |
303 | - | |
304 | - return idx; //return the nearest centerline point index | |
305 | - } | |
306 | - | |
307 | - /// Returns the fiber centerline as an array of stim::vec points | |
308 | - std::vector< stim::vec<T> > centerline(){ | |
309 | - | |
310 | - //create an array of stim vectors | |
311 | - std::vector< stim::vec<T> > pts(N); | |
312 | - | |
313 | - //cast each point to a stim::vec, keeping only the position information | |
314 | - for(unsigned int i = 0; i < N; i++) | |
315 | - pts[i] = stim::vec<T>((T) c[i][0], (T) c[i][1], (T) c[i][2]); | |
316 | - | |
317 | - //return the centerline array | |
318 | - return pts; | |
319 | - } | |
320 | - | |
321 | - /// Returns the fiber centerline magnitudes as an array of stim::vec points | |
322 | - std::vector< stim::vec<T> > centerlinemag(){ | |
323 | - | |
324 | - //create an array of stim vectors | |
325 | - std::vector< stim::vec<T> > pts(N); | |
326 | - | |
327 | - //cast each point to a stim::vec, keeping only the position information | |
328 | - for(unsigned int i = 0; i < N; i++) | |
329 | - pts[i] = stim::vec<T>(r[i], r[i]);; | |
330 | - | |
331 | - //return the centerline array | |
332 | - return pts; | |
333 | - } | |
334 | - | |
335 | - /// Split the fiber at the specified index. If the index is an end point, only one fiber is returned | |
336 | - std::vector< stim::fiber<T> > split(unsigned int idx){ | |
337 | - | |
338 | - std::vector< stim::fiber<T> > fl; //create an array to store up to two fibers | |
339 | - | |
340 | - //if the index is an end point, only the existing fiber is returned | |
341 | - if(idx == 0 || idx == N-1){ | |
342 | - fl.resize(1); //set the size of the fiber to 1 | |
343 | - fl[0] = *this; //copy the current fiber | |
344 | - } | |
345 | - | |
346 | - //if the index is not an end point | |
347 | - else{ | |
348 | - | |
349 | - unsigned int N1 = idx + 1; //calculate the size of both fibers | |
350 | - unsigned int N2 = N - idx; | |
351 | - | |
352 | - fl.resize(2); //set the array size to 2 | |
353 | - | |
354 | - fl[0].init(N1); //set the size of each fiber | |
355 | - fl[1].init(N2); | |
356 | - | |
357 | - //copy both halves of the fiber | |
358 | - unsigned int i, d; | |
359 | - | |
360 | - //first half | |
361 | - for(i = 0; i < N1; i++){ //for each centerline point | |
362 | - for(d = 0; d < 3; d++) | |
363 | - fl[0].c[i][d] = c[i][d]; //copy each coordinate | |
364 | - fl[0].r[i] = r[i]; //copy the corresponding radius | |
365 | - } | |
366 | - | |
367 | - //second half | |
368 | - for(i = 0; i < N2; i++){ | |
369 | - for(d = 0; d < 3; d++) | |
370 | - fl[1].c[i][d] = c[idx + i][d]; | |
371 | - fl[1].r[i] = r[idx + i]; | |
372 | - } | |
373 | - } | |
374 | - | |
375 | - return fl; //return the array | |
376 | - | |
377 | - } | |
378 | - | |
379 | - /// Calculates the set of fibers resulting from a connection between the current fiber and a fiber f | |
380 | - | |
381 | - /// @param f is the fiber that will be connected to the current fiber | |
382 | - std::vector< stim::fiber<T> > connect( stim::fiber<T> &f, double dist){ | |
383 | - | |
384 | - double min_dist; | |
385 | - unsigned int idx0, idx1; | |
386 | - | |
387 | - //go through each point in the query fiber, looking for the indices for the closest points | |
388 | - for(unsigned int i = 0; i < f.n_pts(); i++){ | |
389 | - //Run through all points and find the index with the closest point, then partition the fiber and return two fibers. | |
390 | - | |
391 | - } | |
392 | - | |
393 | - | |
394 | - | |
395 | - } | |
396 | - | |
397 | - /// Outputs the fiber as a string | |
398 | - std::string str(){ | |
399 | - std::stringstream ss; | |
400 | - | |
401 | - //create an iterator for the point list | |
402 | - //typename std::list< point<T> >::iterator i; | |
403 | - for(unsigned int i = 0; i < N; i++){ | |
404 | - ss<<" [ "; | |
405 | - for(unsigned int d = 0; d < 3; d++){ | |
406 | - ss<<c[i][d]<<" "; | |
407 | - } | |
408 | - ss<<"] r = "<<r[i]<<std::endl; | |
409 | - } | |
410 | - | |
411 | - return ss.str(); | |
412 | - } | |
413 | - /// Returns the number of centerline points in the fiber | |
414 | - unsigned int size(){ | |
415 | - return N; | |
416 | - } | |
417 | - | |
418 | - | |
419 | - /// Bracket operator returns the element at index i | |
420 | - | |
421 | - /// @param i is the index of the element to be returned as a stim::vec | |
422 | - stim::vec<T> operator[](unsigned i){ | |
423 | - return get_vec(i); | |
424 | - } | |
425 | - | |
426 | - /// Back method returns the last point in the fiber | |
427 | - stim::vec<T> back(){ | |
428 | - return get_vec(N-1); | |
429 | - } | |
430 | - ////resample a fiber in the network | |
431 | - stim::fiber<T> resample(T spacing) | |
432 | - { | |
433 | - std::cout<<"fiber::resample()"<<std::endl; | |
434 | - | |
435 | - std::vector<T> v(3); //v-direction vector of the segment | |
436 | - stim::vec<T> p(3); //- intermediate point to be added | |
437 | - stim::vec<T> p1(3); // p1 - starting point of an segment on the fiber, | |
438 | - stim::vec<T> p2(3); // p2 - ending point, | |
439 | - double sum=0; //distance summation | |
440 | - std::vector<stim::vec<T> > fiberPositions = centerline(); | |
441 | - std::vector<stim::vec<T> > newPointList; // initialize list of new resampled points on the fiber | |
442 | - // for each point on the centerline (skip if it is the last point on centerline) | |
443 | - //unsigned int N = fiberPositions.size(); // number of points on the fiber | |
444 | - for(unsigned int f=0; f< N-1; f++) | |
445 | - { | |
446 | - | |
447 | - p1 = fiberPositions[f]; p2 = fiberPositions[f + 1]; v = p2 - p1; | |
448 | - for(unsigned int d = 0; d < 3; d++){ | |
449 | - sum +=v[d] * v[d];} //length of segment-distance between starting and ending point | |
450 | - | |
451 | - T lengthSegment = sqrt(sum); //find Length of the segment as distance between the starting and ending points of the segment | |
452 | - | |
453 | - if(lengthSegment >= spacing) // if length of the segment is greater than standard deviation resample | |
454 | - { | |
455 | - // repeat resampling until accumulated stepsize is equsl to length of the segment | |
456 | - for(T step=0.0; step<lengthSegment; step+=spacing) | |
457 | - { | |
458 | - // calculate the resampled point by travelling step size in the direction of normalized gradient vector | |
459 | - for(unsigned int i=0; i<3;i++) | |
460 | - { | |
461 | - p[i] = p1[i] + v[i]*(step/lengthSegment); | |
462 | - } //for each dimension | |
463 | - // add this resampled points to the new fiber list | |
464 | - newPointList.push_back(p); | |
465 | - } | |
466 | - } | |
467 | - 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 | |
468 | - newPointList.push_back(fiberPositions[f+1]); | |
469 | - } | |
470 | - newPointList.push_back(fiberPositions[N-1]); //add the last point on the fiber to the new fiber list | |
471 | - fiber newFiber(newPointList); | |
472 | - return newFiber; | |
473 | - } | |
474 | - | |
475 | -}; | |
476 | - | |
477 | - | |
478 | - | |
479 | -} //end namespace stim | |
480 | - | |
481 | - | |
482 | - | |
483 | -#endif |