Commit 9c97e1269d19a12411c904106718e478b1324efd

Authored by David Mayerich
1 parent 58ee2b21

added an axis-aligned bounding box class, as well as classes for rendering networks

stim/biomodels/network.h
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 #define STIM_NETWORK_H 2 #define STIM_NETWORK_H
3 3
4 #include <stdlib.h> 4 #include <stdlib.h>
5 -#include <assert.h> 5 +#include <assert.h>
6 #include <sstream> 6 #include <sstream>
7 #include <fstream> 7 #include <fstream>
8 #include <algorithm> 8 #include <algorithm>
@@ -50,7 +50,7 @@ class network{ @@ -50,7 +50,7 @@ class network{
50 50
51 return e; //return the new edge 51 return e; //return the new edge
52 } 52 }
53 - 53 +
54 /// Output the edge information as a string 54 /// Output the edge information as a string
55 std::string str(){ 55 std::string str(){
56 std::stringstream ss; 56 std::stringstream ss;
@@ -58,8 +58,8 @@ class network{ @@ -58,8 +58,8 @@ class network{
58 return ss.str(); 58 return ss.str();
59 } 59 }
60 60
61 - };  
62 - 61 + };
  62 +
63 ///Node class that stores the physical position of the node as well as the edges it is connected to (edges that connect to it), As well as any additional data necessary. 63 ///Node class that stores the physical position of the node as well as the edges it is connected to (edges that connect to it), As well as any additional data necessary.
64 class vertex : public stim::vec<T> 64 class vertex : public stim::vec<T>
65 { 65 {
@@ -89,15 +89,15 @@ class network{ @@ -89,15 +89,15 @@ class network{
89 89
90 return ss.str(); 90 return ss.str();
91 } 91 }
92 - 92 +
93 }; 93 };
94 94
95 - private: 95 +protected:
96 96
97 std::vector<edge> E; //list of edges 97 std::vector<edge> E; //list of edges
98 std::vector<vertex> V; //list of vertices. 98 std::vector<vertex> V; //list of vertices.
99 -  
100 - public: 99 +
  100 +public:
101 101
102 ///Returns the number of edges in the network. 102 ///Returns the number of edges in the network.
103 unsigned int edges(){ 103 unsigned int edges(){
@@ -134,7 +134,7 @@ class network{ @@ -134,7 +134,7 @@ class network{
134 134
135 //get the first and last vertex IDs for the line 135 //get the first and last vertex IDs for the line
136 std::vector< unsigned > id; //create an array to store the centerline point IDs 136 std::vector< unsigned > id; //create an array to store the centerline point IDs
137 - O.getLinei(l, id); //get the list of point IDs for the line 137 + O.getLinei(l, id); //get the list of point IDs for the line
138 i[0] = id.front(); //get the OBJ ID for the first element of the line 138 i[0] = id.front(); //get the OBJ ID for the first element of the line
139 i[1] = id.back(); //get the OBJ ID for the last element of the line 139 i[1] = id.back(); //get the OBJ ID for the last element of the line
140 140
@@ -169,7 +169,7 @@ class network{ @@ -169,7 +169,7 @@ class network{
169 V[it_idx].e[1].push_back(E.size()); //add the current edge as incoming 169 V[it_idx].e[1].push_back(E.size()); //add the current edge as incoming
170 new_edge.v[1] = it_idx; 170 new_edge.v[1] = it_idx;
171 } 171 }
172 - 172 +
173 E.push_back(new_edge); //push the edge to the list 173 E.push_back(new_edge); //push the edge to the list
174 174
175 } 175 }
@@ -193,6 +193,7 @@ class network{ @@ -193,6 +193,7 @@ class network{
193 } 193 }
194 194
195 /// This function resamples all fibers in a network given a desired minimum spacing 195 /// This function resamples all fibers in a network given a desired minimum spacing
  196 + /// @param spacing is the minimum distance between two points on the network
196 stim::network<T> resample(T spacing){ 197 stim::network<T> resample(T spacing){
197 stim::network<T> n; //create a new network that will be an exact copy, with resampled fibers 198 stim::network<T> n; //create a new network that will be an exact copy, with resampled fibers
198 n.V = V; //copy all vertices 199 n.V = V; //copy all vertices
@@ -209,7 +210,7 @@ class network{ @@ -209,7 +210,7 @@ class network{
209 210
210 211
211 212
212 - // total number of points on all fibers after resampling -- function used only on a resampled network 213 + /// Calculate the total number of points on all edges.
213 unsigned total_points(){ 214 unsigned total_points(){
214 unsigned n = 0; 215 unsigned n = 0;
215 for(unsigned e = 0; e < E.size(); e++) 216 for(unsigned e = 0; e < E.size(); e++)
@@ -227,28 +228,50 @@ class network{ @@ -227,28 +228,50 @@ class network{
227 a[2] = b[2]; 228 a[2] = b[2];
228 } 229 }
229 230
  231 + /// Calculate the average magnitude across the entire network.
  232 + /// @param m is the magnitude value to use. The default is 0 (usually radius).
  233 + T average(unsigned m = 0){
  234 +
  235 + T M, L; //allocate space for the total magnitude and length
  236 + M = L = 0; //initialize both the initial magnitude and length to zero
  237 + for(unsigned e = 0; e < E.size(); e++){ //for each edge in the network
  238 + M += E[e].integrate(m); //get the integrated magnitude
  239 + L += E[e].length(); //get the edge length
  240 + }
230 241
231 - /// This function compares two networks and returns a metric  
232 - float compare(stim::network<T> A, float sigma){ 242 + return M / L; //return the average magnitude
  243 + }
  244 +
  245 + /// This function compares two networks and returns the percentage of the current network that is missing from A.
  246 +
  247 + /// @param A is the network to compare to - the field is generated for A
  248 + /// @param sigma is the user-defined tolerance value - smaller values provide a stricter comparison
  249 + stim::network<T> compare(stim::network<T> A, float sigma){
  250 +
  251 + stim::network<T> R; //generate a network storing the result of the comparison
  252 + R = (*this); //initialize the result with the current network
  253 +
  254 + //generate a KD-tree for network A
233 float metric = 0.0; // initialize metric to be returned after comparing the networks 255 float metric = 0.0; // initialize metric to be returned after comparing the networks
234 ANNkd_tree* kdt; // initialize a pointer to a kd tree 256 ANNkd_tree* kdt; // initialize a pointer to a kd tree
235 double **c; // centerline (array of double pointers) - points on kdtree must be double 257 double **c; // centerline (array of double pointers) - points on kdtree must be double
236 - unsigned int n_data = total_points(); // set the number of points 258 + unsigned int n_data = A.total_points(); // set the number of points
237 c = (double**) malloc(sizeof(double*) * n_data); // allocate the array pointer 259 c = (double**) malloc(sizeof(double*) * n_data); // allocate the array pointer
238 for(unsigned int i = 0; i < n_data; i++) // allocate space for each point of 3 dimensions 260 for(unsigned int i = 0; i < n_data; i++) // allocate space for each point of 3 dimensions
239 c[i] = (double*) malloc(sizeof(double) * 3); 261 c[i] = (double*) malloc(sizeof(double) * 3);
240 - //std::vector<stim::vec<T> > pointsVector = points_afterResampling(); //get vertices in the network after resampling 262 +
241 unsigned t = 0; 263 unsigned t = 0;
242 - for(unsigned e = 0; e < E.size(); e++){ //for each edge in the network  
243 - for(unsigned p = 0; p < E[e].size(); p++){ //for each point in the edge 264 + for(unsigned e = 0; e < A.E.size(); e++){ //for each edge in the network
  265 + for(unsigned p = 0; p < A.E[e].size(); p++){ //for each point in the edge
244 for(unsigned d = 0; d < 3; d++){ //for each coordinate 266 for(unsigned d = 0; d < 3; d++){ //for each coordinate
245 267
246 - c[t][d] = E[e][p][d]; 268 + c[t][d] = A.E[e][p][d];
247 } 269 }
248 t++; 270 t++;
249 } 271 }
250 } 272 }
251 273
  274 + //compare each point in the current network to the field produced by A
252 ANNpointArray pts = (ANNpointArray)c; // create an array of data points of type double 275 ANNpointArray pts = (ANNpointArray)c; // create an array of data points of type double
253 kdt = new ANNkd_tree(pts, n_data, 3); // build a KD tree using the annpointarray 276 kdt = new ANNkd_tree(pts, n_data, 3); // build a KD tree using the annpointarray
254 double eps = 0; // error bound 277 double eps = 0; // error bound
@@ -261,33 +284,24 @@ class network{ @@ -261,33 +284,24 @@ class network{
261 float l; //stores the segment length 284 float l; //stores the segment length
262 float L = 0; //stores the total network length 285 float L = 0; //stores the total network length
263 ANNpoint queryPt = annAllocPt(3); 286 ANNpoint queryPt = annAllocPt(3);
264 - for(unsigned e = 0; e < A.E.size(); e++){ //for each edge in A  
265 - M = 0; //total metric value for the fiber  
266 - p0 = A.E[e][0]; //get the first point in the edge  
267 - stim2ann(queryPt, p0);  
268 - kdt->annkSearch( queryPt, 1, nnIdx, dists, eps); //find the distance between A and the current network  
269 - m0 = 1.0f - gaussianFunction(dists[0], sigma); //calculate the metric value based on the distance 287 + for(unsigned e = 0; e < R.E.size(); e++){ //for each edge in A
  288 + R.E[e].add_mag(0); //add a new magnitude for the metric
270 289
271 - for(unsigned p = 1; p < A.E[e].size(); p++){ //for each point in the edge 290 + for(unsigned p = 0; p < R.E[e].size(); p++){ //for each point in the edge
272 291
273 - p1 = A.E[e][p]; //get the next point in the edge 292 + p1 = R.E[e][p]; //get the next point in the edge
274 stim2ann(queryPt, p1); 293 stim2ann(queryPt, p1);
275 kdt->annkSearch( queryPt, 1, nnIdx, dists, eps); //find the distance between A and the current network 294 kdt->annkSearch( queryPt, 1, nnIdx, dists, eps); //find the distance between A and the current network
276 m1 = 1.0f - gaussianFunction(dists[0], sigma); //calculate the metric value based on the distance 295 m1 = 1.0f - gaussianFunction(dists[0], sigma); //calculate the metric value based on the distance
  296 + R.E[e].set_mag(m1, p, 1); //set the error for the second point in the segment
277 297
278 - //average the metric and scale  
279 - l = (p1 - p0).len(); //calculate the length of the segment  
280 - L += l; //add the length of this segment to the total network length  
281 - M += (m0 + m1)/2 * l; //scale the metric based on segment length  
282 -  
283 - //swap points  
284 - p0 = p1;  
285 - m0 = m1;  
286 } 298 }
287 } 299 }
288 300
289 - return M/L; 301 + return R; //return the resulting network
290 } 302 }
  303 +
  304 +
291 }; //end stim::network class 305 }; //end stim::network class
292 }; //end stim namespace 306 }; //end stim namespace
293 #endif 307 #endif
stim/parser/arguments.h
@@ -239,35 +239,29 @@ namespace stim{ @@ -239,35 +239,29 @@ namespace stim{
239 239
240 /**The arglist class implements command line arguments. 240 /**The arglist class implements command line arguments.
241 Example: 241 Example:
242 -  
243 - 1) Create an arglist instance:  
244 -  
245 - stim::arglist args;  
246 242
247 - 2) Test to see if ANSI output is supported (arguments will use color if it is). Generally, Windows consoles don't support ANSI. 243 + 1) Create an arglist instance:
248 244
249 - #ifdef _WIN32  
250 - args.set_ansi(false);  
251 - #endif 245 + stim::arglist args;
252 246
253 - 3) Add arguments: 247 + 2) Add arguments:
254 248
255 args.add("help", "prints this help"); 249 args.add("help", "prints this help");
256 args.add("foo", "foo takes a single integer value", "", "[intval]"); 250 args.add("foo", "foo takes a single integer value", "", "[intval]");
257 args.add("bar", "bar takes two floating point values", "", "[value1], [value2]"); 251 args.add("bar", "bar takes two floating point values", "", "[value1], [value2]");
258 252
259 - 4) Parse the command line: 253 + 3) Parse the command line:
260 254
261 args.parse(argc, argv); 255 args.parse(argc, argv);
262 256
263 - 5) You generally want to immediately test for help and output available arguments: 257 + 4) You generally want to immediately test for help and output available arguments:
264 258
265 if(args["help"].is_set()) 259 if(args["help"].is_set())
266 std::cout<<args.str(); 260 std::cout<<args.str();
267 261
268 -  
269 262
270 - 6) Retrieve values: 263 +
  264 + 5) Retrieve values:
271 265
272 int foo; 266 int foo;
273 float bar1, bar2; 267 float bar1, bar2;
@@ -300,7 +294,15 @@ namespace stim{ @@ -300,7 +294,15 @@ namespace stim{
300 294
301 arglist(){ 295 arglist(){
302 col_width = 0; 296 col_width = 0;
303 - ansi = true; 297 +
  298 + ansi = true;
  299 +
  300 + //set ansi to false by default if this is a Windows system
  301 + // (console doesn't support ANSI colors)
  302 + #ifdef _WIN32
  303 + ansi=false;
  304 + #endif
  305 +
304 } 306 }
305 307
306 ///Sets ANSI support (default is on), which allows colored values in the help output. 308 ///Sets ANSI support (default is on), which allows colored values in the help output.
stim/visualization/aabb.h 0 → 100644
  1 +#ifndef STIM_AABB
  2 +#define STIM_AABB
  3 +
  4 +namespace stim{
  5 +
  6 +
  7 +/// This class describes a structure for an axis-aligned bounding box
  8 +template< typename T >
  9 +class aabb{
  10 +
  11 +public:
  12 + bool set; //has the bounding box been set to include any points?
  13 + stim::vec<T> A; //minimum point in the bounding box
  14 + stim::vec<T> B; //maximum point in the bounding box
  15 +
  16 + aabb(){ //constructor generates an empty bounding box
  17 + set = false;
  18 + }
  19 +
  20 +
  21 + /// Test if a point is inside of the bounding box and returns true if it is.
  22 +
  23 + /// @param p is the point to be tested
  24 + bool test(stim::vec<T> p){
  25 +
  26 + for(unsigned d = 0; d < p.size(); p++){ //for each dimension
  27 + if(p[d] < A[d]) return false; //if the point is less than the minimum bound, return false
  28 + if(p[d] > B[d]) return false; //if the point is greater than the max bound, return false
  29 + }
  30 + return true;
  31 + }
  32 +
  33 + /// Expand the bounding box to include the specified point.
  34 +
  35 + /// @param p is the point to be included
  36 + void expand(stim::vec<T> p){
  37 +
  38 + if(!set){ //if the bounding box is empty, fill it with the current point
  39 + A = B = p;
  40 + set = true;
  41 + }
  42 +
  43 + for(unsigned d = 0; d < p.size(); d++){ //for each dimension
  44 + if(p[d] < A[d]) A[d] = p[d]; //expand the bounding box as necessary
  45 + if(p[d] > B[d]) B[d] = p[d];
  46 + }
  47 + }
  48 +
  49 + /// Return the center point of the bounding box as a stim::vec
  50 + stim::vec<T> center(){
  51 + return (B + A) * 0.5;
  52 + }
  53 +
  54 + /// Return the size of the bounding box as a stim::vec
  55 + stim::vec<T> size(){
  56 + return (B - A);
  57 + }
  58 +
  59 + /// Generate a string for the bounding box
  60 + std::string str(){
  61 + std::stringstream ss;
  62 + ss<<A.str()<<"----->"<<B.str();
  63 + return ss.str();
  64 + }
  65 +
  66 +
  67 +}; //end stim::aabb
  68 +
  69 +
  70 +}; //end namespace stim
  71 +
  72 +#endif
0 \ No newline at end of file 73 \ No newline at end of file
stim/visualization/camera.h
@@ -188,6 +188,13 @@ public: @@ -188,6 +188,13 @@ public:
188 focus = 1; 188 focus = 1;
189 189
190 } 190 }
  191 +
  192 + /// Outputs the camera information as a string
  193 + std::string str(){
  194 + std::stringstream ss;
  195 + ss<<p.str()<<"----->"<<(p + d * focus).str();
  196 + return ss.str();
  197 + }
191 }; 198 };
192 199
193 } 200 }
stim/visualization/cylinder.h
@@ -15,45 +15,38 @@ class cylinder @@ -15,45 +15,38 @@ class cylinder
15 std::vector< stim::vec<T> > pos; //positions of the cylinder. 15 std::vector< stim::vec<T> > pos; //positions of the cylinder.
16 std::vector< stim::vec<T> > mags; //radii at each position 16 std::vector< stim::vec<T> > mags; //radii at each position
17 std::vector< T > L; //length of the cylinder at each position. 17 std::vector< T > L; //length of the cylinder at each position.
18 -  
19 - ///default init 18 +
  19 + ///default init
20 void 20 void
21 - init()  
22 - { 21 + init(){
23 22
24 } 23 }
25 24
26 ///inits the cylinder from a list of points (inP) and radii (inM) 25 ///inits the cylinder from a list of points (inP) and radii (inM)
27 void 26 void
28 - init(std::vector<stim::vec<T> > inP, std::vector<stim::vec<T> > inM)  
29 - { 27 + init(std::vector<stim::vec<T> > inP, std::vector<stim::vec<T> > inM){
30 pos = inP; 28 pos = inP;
31 mags = inM; 29 mags = inM;
32 30
33 //calculate each L. 31 //calculate each L.
34 L.resize(pos.size()-1); 32 L.resize(pos.size()-1);
35 T temp = (T)0; 33 T temp = (T)0;
36 - for(int i = 0; i < L.size()-1; i++) 34 + for(int i = 0; i < L.size(); i++)
37 { 35 {
38 temp += (pos[i] - pos[i+1]).len(); 36 temp += (pos[i] - pos[i+1]).len();
39 L[i] = temp; 37 L[i] = temp;
40 } 38 }
41 } 39 }
42 - 40 +
43 ///returns the direction vector at point idx. 41 ///returns the direction vector at point idx.
44 stim::vec<T> 42 stim::vec<T>
45 - d(int idx)  
46 - { 43 + d(int idx){
47 return (pos[idx] - pos[idx+1]).norm(); 44 return (pos[idx] - pos[idx+1]).norm();
48 -  
49 } 45 }
50 46
51 -  
52 -  
53 ///returns the total length of the line at index j. 47 ///returns the total length of the line at index j.
54 T 48 T
55 - getl(int j)  
56 - { 49 + getl(int j){
57 for(int i = 0; i < j-1; ++i) 50 for(int i = 0; i < j-1; ++i)
58 { 51 {
59 temp += (pos[i] - pos[i+1]).len(); 52 temp += (pos[i] - pos[i+1]).len();
@@ -64,8 +57,7 @@ class cylinder @@ -64,8 +57,7 @@ class cylinder
64 ///finds the index of the point closest to the length l on the lower bound. 57 ///finds the index of the point closest to the length l on the lower bound.
65 ///binary search. 58 ///binary search.
66 int 59 int
67 - findIdx(T l)  
68 - { 60 + findIdx(T l){
69 int i = pos.size()/2; 61 int i = pos.size()/2;
70 while(i > 0 && i < pos.size()) 62 while(i > 0 && i < pos.size())
71 { 63 {
@@ -85,18 +77,29 @@ class cylinder @@ -85,18 +77,29 @@ class cylinder
85 return i; 77 return i;
86 } 78 }
87 79
88 - public:  
89 - ///default constructor  
90 - cylinder()  
91 - { 80 + //initializes the length array given the current set of positions
  81 + void init_length(){
  82 + vec<T> p0, p1;
  83 + p0 = pos[0]; //initialize the first point in the segment to the first point in the cylinder
  84 + T l; //allocate space for the segment length
  85 + for(unsigned p = 1; p < pos.size(); p++){ //for each point in the cylinder
  86 + p1 = pos[p]; //get the second point in the segment
  87 + l = (p1 - p0).len(); //calculate the length of the segment
  88 +
  89 + if(p == 1) L[0] = l; //set the length for the first segment
  90 + else L[p-1] = L[p-2] + l; //calculate and set the running length for each additional segment
  91 + }
92 92
93 } 93 }
94 94
  95 + public:
  96 + ///default constructor
  97 + cylinder(){}
  98 +
95 ///constructor to create a cylinder from a set of points, radii, and the number of sides for the cylinder. 99 ///constructor to create a cylinder from a set of points, radii, and the number of sides for the cylinder.
96 ///@param inP: Vector of stim vecs composing the points of the centerline. 100 ///@param inP: Vector of stim vecs composing the points of the centerline.
97 ///@param inM: Vector of stim vecs composing the radii of the centerline. 101 ///@param inM: Vector of stim vecs composing the radii of the centerline.
98 - cylinder(std::vector<stim::vec<T> > inP, std::vector<stim::vec<T> > inM)  
99 - { 102 + cylinder(std::vector<stim::vec<T> > inP, std::vector<stim::vec<T> > inM){
100 init(inP, inM); 103 init(inP, inM);
101 } 104 }
102 105
@@ -104,7 +107,11 @@ class cylinder @@ -104,7 +107,11 @@ class cylinder
104 ///@param inP: Vector of stim vecs composing the points of the centerline 107 ///@param inP: Vector of stim vecs composing the points of the centerline
105 cylinder(std::vector< stim::vec<T> > inP){ 108 cylinder(std::vector< stim::vec<T> > inP){
106 std::vector< stim::vec<T> > inM; //create an array of arbitrary magnitudes 109 std::vector< stim::vec<T> > inM; //create an array of arbitrary magnitudes
107 - inM.resize(inP.size(), 0); //initialize the magnitude values to zero 110 +
  111 + stim::vec<T> zero;
  112 + zero.push_back(0);
  113 +
  114 + inM.resize(inP.size(), zero); //initialize the magnitude values to zero
108 init(inP, inM); 115 init(inP, inM);
109 } 116 }
110 117
@@ -120,8 +127,7 @@ class cylinder @@ -120,8 +127,7 @@ class cylinder
120 ///interpolates the position along the line. 127 ///interpolates the position along the line.
121 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). 128 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1).
122 stim::vec<T> 129 stim::vec<T>
123 - p(T pvalue)  
124 - { 130 + p(T pvalue){
125 if(pvalue < 0.0 || pvalue > 1.0) 131 if(pvalue < 0.0 || pvalue > 1.0)
126 return; 132 return;
127 T l = pvalue*L[L.size()-1]; 133 T l = pvalue*L[L.size()-1];
@@ -134,8 +140,7 @@ class cylinder @@ -134,8 +140,7 @@ class cylinder
134 ///@param l: the location of the in the cylinder. 140 ///@param l: the location of the in the cylinder.
135 ///@param idx: integer location of the point closest to l but prior to it. 141 ///@param idx: integer location of the point closest to l but prior to it.
136 stim::vec<T> 142 stim::vec<T>
137 - p(T l, int idx)  
138 - { 143 + p(T l, int idx){
139 return (pos[idx] + (pos[idx+1]-pos[idx])*((l-L[idx])/(L[idx+1]- L[idx]))); 144 return (pos[idx] + (pos[idx+1]-pos[idx])*((l-L[idx])/(L[idx+1]- L[idx])));
140 } 145 }
141 146
@@ -143,8 +148,7 @@ class cylinder @@ -143,8 +148,7 @@ class cylinder
143 ///interpolates the radius along the line. 148 ///interpolates the radius along the line.
144 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1). 149 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1).
145 T 150 T
146 - r(T pvalue)  
147 - { 151 + r(T pvalue){
148 if(pvalue < 0.0 || pvalue > 1.0) 152 if(pvalue < 0.0 || pvalue > 1.0)
149 return; 153 return;
150 T l = pvalue*L[L.size()-1]; 154 T l = pvalue*L[L.size()-1];
@@ -157,11 +161,33 @@ class cylinder @@ -157,11 +161,33 @@ class cylinder
157 ///@param l: the location of the in the cylinder. 161 ///@param l: the location of the in the cylinder.
158 ///@param idx: integer location of the point closest to l but prior to it. 162 ///@param idx: integer location of the point closest to l but prior to it.
159 T 163 T
160 - r(T l, int idx)  
161 - { 164 + r(T l, int idx){
162 return (mags[idx] + (mags[idx+1]-mags[idx])*((l-L[idx])/(L[idx+1]- L[idx]))); 165 return (mags[idx] + (mags[idx+1]-mags[idx])*((l-L[idx])/(L[idx+1]- L[idx])));
163 } 166 }
164 167
  168 + /// Returns the magnitude at the given index
  169 + /// @param i is the index of the desired point
  170 + /// @param m is the index of the magnitude value
  171 + T ri(unsigned i, unsigned m = 0){
  172 + return mags[i][m];
  173 + }
  174 +
  175 + /// Adds a new magnitude value to all points
  176 + /// @param m is the starting value for the new magnitude
  177 + void add_mag(T m = 0){
  178 + for(unsigned int p = 0; p < pos.size(); p++)
  179 + mags[p].push_back(m);
  180 + }
  181 +
  182 + /// Sets a magnitude value
  183 + /// @param val is the new value for the magnitude
  184 + /// @param p is the point index for the magnitude to be set
  185 + /// @param m is the index for the magnitude
  186 + void set_mag(T val, unsigned p, unsigned m = 0){
  187 + mags[p][m] = val;
  188 + }
  189 +
  190 +
165 191
166 ///returns the position of the point with a given pvalue and theta on the surface 192 ///returns the position of the point with a given pvalue and theta on the surface
167 ///in x, y, z coordinates. Theta is in degrees from 0 to 360. 193 ///in x, y, z coordinates. Theta is in degrees from 0 to 360.
@@ -174,7 +200,7 @@ class cylinder @@ -174,7 +200,7 @@ class cylinder
174 return; 200 return;
175 T l = pvalue*L[L.size()-1]; 201 T l = pvalue*L[L.size()-1];
176 int idx = findIdx(l); 202 int idx = findIdx(l);
177 - stim::vec<T> ps = p(l, idx); 203 + stim::vec<T> ps = p(l, idx);
178 T m = r(l, idx); 204 T m = r(l, idx);
179 stim::vec<T> dr = d(idx); 205 stim::vec<T> dr = d(idx);
180 s = stim::circle<T>(ps, m, dr); 206 s = stim::circle<T>(ps, m, dr);
@@ -182,7 +208,7 @@ class cylinder @@ -182,7 +208,7 @@ class cylinder
182 } 208 }
183 209
184 ///returns a vector of points necessary to create a circle at every position in the fiber. 210 ///returns a vector of points necessary to create a circle at every position in the fiber.
185 - ///@param sides: the number of sides of each circle. 211 + ///@param sides: the number of sides of each circle.
186 std::vector<std::vector<vec<T> > > 212 std::vector<std::vector<vec<T> > >
187 getPoints(int sides) 213 getPoints(int sides)
188 { 214 {
@@ -210,9 +236,7 @@ class cylinder @@ -210,9 +236,7 @@ class cylinder
210 /// Allows a point on the centerline to be accessed using bracket notation 236 /// Allows a point on the centerline to be accessed using bracket notation
211 237
212 vec<T> operator[](unsigned int i){ 238 vec<T> operator[](unsigned int i){
213 -  
214 return pos[i]; 239 return pos[i];
215 -  
216 } 240 }
217 241
218 /// Returns the total length of the cylinder centerline 242 /// Returns the total length of the cylinder centerline
@@ -220,13 +244,51 @@ class cylinder @@ -220,13 +244,51 @@ class cylinder
220 return L.back(); 244 return L.back();
221 } 245 }
222 246
  247 + /// Integrates a magnitude value along the cylinder.
  248 + /// @param m is the magnitude value to be integrated (this is usually the radius)
  249 + T integrate(unsigned m = 0){
  250 +
  251 + T M = 0; //initialize the integral to zero
  252 + T m0, m1; //allocate space for both magnitudes in a single segment
  253 +
  254 + //vec<T> p0, p1; //allocate space for both points in a single segment
  255 +
  256 + m0 = mags[0][m]; //initialize the first point and magnitude to the first point in the cylinder
  257 + //p0 = pos[0];
  258 +
  259 + T len = L[0]; //allocate space for the segment length
  260 +
  261 + //for every consecutive point in the cylinder
  262 + for(unsigned p = 1; p < pos.size(); p++){
  263 +
  264 + //p1 = pos[p]; //get the position and magnitude for the next point
  265 + m1 = mags[p][m];
  266 +
  267 + if(p > 1) len = (L[p-1] - L[p-2]); //calculate the segment length using the L array
  268 +
  269 + //add the average magnitude, weighted by the segment length
  270 + M += (m0 + m1)/2.0 * len;
  271 +
  272 + m0 = m1; //move to the next segment by shifting points
  273 + }
  274 + return M; //return the integral
  275 + }
  276 +
  277 + /// Averages a magnitude value across the cylinder
  278 + /// @param m is the magnitude value to be averaged (this is usually the radius)
  279 + T average(unsigned m = 0){
  280 +
  281 + //return the average magnitude
  282 + return integrate(m) / L.back();
  283 + }
  284 +
223 /// Resamples the cylinder to provide a maximum distance of "spacing" between centerline points. All current 285 /// Resamples the cylinder to provide a maximum distance of "spacing" between centerline points. All current
224 /// centerline points are guaranteed to exist in the new cylinder 286 /// centerline points are guaranteed to exist in the new cylinder
225 /// @param spacing is the maximum spacing allowed between sample points 287 /// @param spacing is the maximum spacing allowed between sample points
226 cylinder<T> resample(T spacing){ 288 cylinder<T> resample(T spacing){
227 289
228 std::vector< vec<T> > result; 290 std::vector< vec<T> > result;
229 - 291 +
230 vec<T> p0 = pos[0]; //initialize p0 to the first point on the centerline 292 vec<T> p0 = pos[0]; //initialize p0 to the first point on the centerline
231 vec<T> p1; 293 vec<T> p1;
232 unsigned N = size(); //number of points in the current centerline 294 unsigned N = size(); //number of points in the current centerline
@@ -238,7 +300,7 @@ class cylinder @@ -238,7 +300,7 @@ class cylinder
238 vec<T> v = p1 - p0; //calculate the vector between these two points 300 vec<T> v = p1 - p0; //calculate the vector between these two points
239 T d = v.len(); //calculate the distance between these two points (length of the line segment) 301 T d = v.len(); //calculate the distance between these two points (length of the line segment)
240 302
241 - unsigned nsteps = d / spacing; //calculate the number of steps to take along the segment to meet the spacing criteria 303 + unsigned nsteps = d / spacing+1; //calculate the number of steps to take along the segment to meet the spacing criteria
242 T stepsize = 1.0 / nsteps; //calculate the parametric step size between new centerline points 304 T stepsize = 1.0 / nsteps; //calculate the parametric step size between new centerline points
243 305
244 //for each step along the line segment 306 //for each step along the line segment
@@ -251,11 +313,11 @@ class cylinder @@ -251,11 +313,11 @@ class cylinder
251 } 313 }
252 314
253 result.push_back(pos[size() - 1]); //push the last point in the centerline 315 result.push_back(pos[size() - 1]); //push the last point in the centerline
254 - 316 +
255 return cylinder<T>(result); 317 return cylinder<T>(result);
256 318
257 } 319 }
258 - 320 +
259 }; 321 };
260 322
261 } 323 }
stim/visualization/gl_aabb.h 0 → 100644
  1 +#ifndef STIM_GL_AABB
  2 +#define STIM_GL_AABB
  3 +
  4 +#include "aabb.h"
  5 +#include "GL/gl.h"
  6 +
  7 +namespace stim{
  8 +
  9 +template <typename T>
  10 +class gl_aabb : public aabb<T>{
  11 +
  12 +public:
  13 +
  14 + //default constructor
  15 + gl_aabb() : stim::aabb<T>(){}
  16 +
  17 + //constructor takes an AABB
  18 + gl_aabb(stim::aabb<T> b) : stim::aabb<T>(b){}
  19 +
  20 +
  21 + /// Specifies vertices of the bounding box using CW winding. Use GL_LINE_LOOP for wireframe or GL_QUADS for a solid.
  22 + void glPointsCW(){
  23 +
  24 + //front plane (in A[2])
  25 + glVertex3f(A[0], A[1], A[2]);
  26 + glVertex3f(A[0], B[1], A[2]);
  27 + glVertex3f(B[0], B[1], A[2]);
  28 + glVertex3f(B[0], A[1], A[2]);
  29 +
  30 + //back plane (in B[2])
  31 + glVertex3f(B[0], B[1], B[2]);
  32 + glVertex3f(A[0], B[1], B[2]);
  33 + glVertex3f(A[0], A[1], B[2]);
  34 + glVertex3f(B[0], A[1], B[2]);
  35 + }
  36 +
  37 +
  38 +}; //end stim::gl_aabb
  39 +
  40 +
  41 +}; //end namespace stim
  42 +
  43 +#endif
0 \ No newline at end of file 44 \ No newline at end of file
stim/visualization/gl_network.h 0 → 100644
  1 +#ifndef STIM_GL_NETWORK
  2 +#define STIM_GL_NETWORK
  3 +
  4 +#include <stim/biomodels/network.h>
  5 +#include "aabb.h"
  6 +
  7 +namespace stim{
  8 +
  9 +template <typename T>
  10 +class gl_network : public stim::network<T>{
  11 +
  12 +protected:
  13 + using stim::network<T>::E;
  14 + using stim::network<T>::V;
  15 +
  16 +public:
  17 +
  18 + /// Default constructor
  19 + gl_network() : stim::network<T>(){}
  20 +
  21 + /// Constructor creates a gl_network from a stim::network
  22 + gl_network(stim::network<T> N) : stim::network<T>(N){}
  23 +
  24 + /// Fills the parameters with the minimum and maximum spatial positions in the network,
  25 + /// specifying a bounding box for the network geometry
  26 + aabb<T> boundingbox(){
  27 +
  28 + aabb<T> bb; //create a bounding box
  29 +
  30 + //loop through every edge
  31 + for(unsigned e = 0; e < E.size(); e++){
  32 + //loop through every point
  33 + for(unsigned p = 0; p < E[e].size(); p++)
  34 + bb.expand(E[e][p]); //expand the bounding box to include the point
  35 + }
  36 +
  37 + return bb; //return the bounding box
  38 + }
  39 +
  40 + /// Render the network centerline as a series of line strips.
  41 + void glCenterline(){
  42 +
  43 + for(unsigned e = 0; e < E.size(); e++){ //for each edge in the network
  44 + glBegin(GL_LINE_STRIP);
  45 + for(unsigned p = 0; p < E[e].size(); p++){ //for each point on that edge
  46 + glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);
  47 + glTexCoord1f(E[e].ri(p));
  48 + }
  49 + glEnd();
  50 + }
  51 +
  52 + }
  53 +
  54 +}; //end stim::gl_network class
  55 +}; //end stim namespace
  56 +
  57 +
  58 +
  59 +#endif
0 \ No newline at end of file 60 \ No newline at end of file
stim/visualization/glnetwork.h renamed to stim/visualization/glnetwork-dep.h