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 |