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 2 #define STIM_NETWORK_H
3 3  
4 4 #include <stdlib.h>
5   -#include <assert.h>
  5 +#include <assert.h>
6 6 #include <sstream>
7 7 #include <fstream>
8 8 #include <algorithm>
... ... @@ -50,7 +50,7 @@ class network{
50 50  
51 51 return e; //return the new edge
52 52 }
53   -
  53 +
54 54 /// Output the edge information as a string
55 55 std::string str(){
56 56 std::stringstream ss;
... ... @@ -58,8 +58,8 @@ class network{
58 58 return ss.str();
59 59 }
60 60  
61   - };
62   -
  61 + };
  62 +
63 63 ///Node class that stores the physical position of the node as well as the edges it is connected to (edges that connect to it), As well as any additional data necessary.
64 64 class vertex : public stim::vec<T>
65 65 {
... ... @@ -89,15 +89,15 @@ class network{
89 89  
90 90 return ss.str();
91 91 }
92   -
  92 +
93 93 };
94 94  
95   - private:
  95 +protected:
96 96  
97 97 std::vector<edge> E; //list of edges
98 98 std::vector<vertex> V; //list of vertices.
99   -
100   - public:
  99 +
  100 +public:
101 101  
102 102 ///Returns the number of edges in the network.
103 103 unsigned int edges(){
... ... @@ -134,7 +134,7 @@ class network{
134 134  
135 135 //get the first and last vertex IDs for the line
136 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 138 i[0] = id.front(); //get the OBJ ID for the first element of the line
139 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 169 V[it_idx].e[1].push_back(E.size()); //add the current edge as incoming
170 170 new_edge.v[1] = it_idx;
171 171 }
172   -
  172 +
173 173 E.push_back(new_edge); //push the edge to the list
174 174  
175 175 }
... ... @@ -193,6 +193,7 @@ class network{
193 193 }
194 194  
195 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 197 stim::network<T> resample(T spacing){
197 198 stim::network<T> n; //create a new network that will be an exact copy, with resampled fibers
198 199 n.V = V; //copy all vertices
... ... @@ -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 214 unsigned total_points(){
214 215 unsigned n = 0;
215 216 for(unsigned e = 0; e < E.size(); e++)
... ... @@ -227,28 +228,50 @@ class network{
227 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 255 float metric = 0.0; // initialize metric to be returned after comparing the networks
234 256 ANNkd_tree* kdt; // initialize a pointer to a kd tree
235 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 259 c = (double**) malloc(sizeof(double*) * n_data); // allocate the array pointer
238 260 for(unsigned int i = 0; i < n_data; i++) // allocate space for each point of 3 dimensions
239 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 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 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 270 t++;
249 271 }
250 272 }
251 273  
  274 + //compare each point in the current network to the field produced by A
252 275 ANNpointArray pts = (ANNpointArray)c; // create an array of data points of type double
253 276 kdt = new ANNkd_tree(pts, n_data, 3); // build a KD tree using the annpointarray
254 277 double eps = 0; // error bound
... ... @@ -261,33 +284,24 @@ class network{
261 284 float l; //stores the segment length
262 285 float L = 0; //stores the total network length
263 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 293 stim2ann(queryPt, p1);
275 294 kdt->annkSearch( queryPt, 1, nnIdx, dists, eps); //find the distance between A and the current network
276 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 305 }; //end stim::network class
292 306 }; //end stim namespace
293 307 #endif
... ...
stim/parser/arguments.h
... ... @@ -239,35 +239,29 @@ namespace stim{
239 239  
240 240 /**The arglist class implements command line arguments.
241 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 249 args.add("help", "prints this help");
256 250 args.add("foo", "foo takes a single integer value", "", "[intval]");
257 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 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 259 if(args["help"].is_set())
266 260 std::cout<<args.str();
267 261  
268   -
269 262  
270   - 6) Retrieve values:
  263 +
  264 + 5) Retrieve values:
271 265  
272 266 int foo;
273 267 float bar1, bar2;
... ... @@ -300,7 +294,15 @@ namespace stim{
300 294  
301 295 arglist(){
302 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 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 73 \ No newline at end of file
... ...
stim/visualization/camera.h
... ... @@ -188,6 +188,13 @@ public:
188 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 15 std::vector< stim::vec<T> > pos; //positions of the cylinder.
16 16 std::vector< stim::vec<T> > mags; //radii at each position
17 17 std::vector< T > L; //length of the cylinder at each position.
18   -
19   - ///default init
  18 +
  19 + ///default init
20 20 void
21   - init()
22   - {
  21 + init(){
23 22  
24 23 }
25 24  
26 25 ///inits the cylinder from a list of points (inP) and radii (inM)
27 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 28 pos = inP;
31 29 mags = inM;
32 30  
33 31 //calculate each L.
34 32 L.resize(pos.size()-1);
35 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 36 temp += (pos[i] - pos[i+1]).len();
39 37 L[i] = temp;
40 38 }
41 39 }
42   -
  40 +
43 41 ///returns the direction vector at point idx.
44 42 stim::vec<T>
45   - d(int idx)
46   - {
  43 + d(int idx){
47 44 return (pos[idx] - pos[idx+1]).norm();
48   -
49 45 }
50 46  
51   -
52   -
53 47 ///returns the total length of the line at index j.
54 48 T
55   - getl(int j)
56   - {
  49 + getl(int j){
57 50 for(int i = 0; i < j-1; ++i)
58 51 {
59 52 temp += (pos[i] - pos[i+1]).len();
... ... @@ -64,8 +57,7 @@ class cylinder
64 57 ///finds the index of the point closest to the length l on the lower bound.
65 58 ///binary search.
66 59 int
67   - findIdx(T l)
68   - {
  60 + findIdx(T l){
69 61 int i = pos.size()/2;
70 62 while(i > 0 && i < pos.size())
71 63 {
... ... @@ -85,18 +77,29 @@ class cylinder
85 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 99 ///constructor to create a cylinder from a set of points, radii, and the number of sides for the cylinder.
96 100 ///@param inP: Vector of stim vecs composing the points of the centerline.
97 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 103 init(inP, inM);
101 104 }
102 105  
... ... @@ -104,7 +107,11 @@ class cylinder
104 107 ///@param inP: Vector of stim vecs composing the points of the centerline
105 108 cylinder(std::vector< stim::vec<T> > inP){
106 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 115 init(inP, inM);
109 116 }
110 117  
... ... @@ -120,8 +127,7 @@ class cylinder
120 127 ///interpolates the position along the line.
121 128 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1).
122 129 stim::vec<T>
123   - p(T pvalue)
124   - {
  130 + p(T pvalue){
125 131 if(pvalue < 0.0 || pvalue > 1.0)
126 132 return;
127 133 T l = pvalue*L[L.size()-1];
... ... @@ -134,8 +140,7 @@ class cylinder
134 140 ///@param l: the location of the in the cylinder.
135 141 ///@param idx: integer location of the point closest to l but prior to it.
136 142 stim::vec<T>
137   - p(T l, int idx)
138   - {
  143 + p(T l, int idx){
139 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 148 ///interpolates the radius along the line.
144 149 ///@param pvalue: the location of the in the cylinder, from 0 (beginning to 1).
145 150 T
146   - r(T pvalue)
147   - {
  151 + r(T pvalue){
148 152 if(pvalue < 0.0 || pvalue > 1.0)
149 153 return;
150 154 T l = pvalue*L[L.size()-1];
... ... @@ -157,11 +161,33 @@ class cylinder
157 161 ///@param l: the location of the in the cylinder.
158 162 ///@param idx: integer location of the point closest to l but prior to it.
159 163 T
160   - r(T l, int idx)
161   - {
  164 + r(T l, int idx){
162 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 192 ///returns the position of the point with a given pvalue and theta on the surface
167 193 ///in x, y, z coordinates. Theta is in degrees from 0 to 360.
... ... @@ -174,7 +200,7 @@ class cylinder
174 200 return;
175 201 T l = pvalue*L[L.size()-1];
176 202 int idx = findIdx(l);
177   - stim::vec<T> ps = p(l, idx);
  203 + stim::vec<T> ps = p(l, idx);
178 204 T m = r(l, idx);
179 205 stim::vec<T> dr = d(idx);
180 206 s = stim::circle<T>(ps, m, dr);
... ... @@ -182,7 +208,7 @@ class cylinder
182 208 }
183 209  
184 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 212 std::vector<std::vector<vec<T> > >
187 213 getPoints(int sides)
188 214 {
... ... @@ -210,9 +236,7 @@ class cylinder
210 236 /// Allows a point on the centerline to be accessed using bracket notation
211 237  
212 238 vec<T> operator[](unsigned int i){
213   -
214 239 return pos[i];
215   -
216 240 }
217 241  
218 242 /// Returns the total length of the cylinder centerline
... ... @@ -220,13 +244,51 @@ class cylinder
220 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 285 /// Resamples the cylinder to provide a maximum distance of "spacing" between centerline points. All current
224 286 /// centerline points are guaranteed to exist in the new cylinder
225 287 /// @param spacing is the maximum spacing allowed between sample points
226 288 cylinder<T> resample(T spacing){
227 289  
228 290 std::vector< vec<T> > result;
229   -
  291 +
230 292 vec<T> p0 = pos[0]; //initialize p0 to the first point on the centerline
231 293 vec<T> p1;
232 294 unsigned N = size(); //number of points in the current centerline
... ... @@ -238,7 +300,7 @@ class cylinder
238 300 vec<T> v = p1 - p0; //calculate the vector between these two points
239 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 304 T stepsize = 1.0 / nsteps; //calculate the parametric step size between new centerline points
243 305  
244 306 //for each step along the line segment
... ... @@ -251,11 +313,11 @@ class cylinder
251 313 }
252 314  
253 315 result.push_back(pos[size() - 1]); //push the last point in the centerline
254   -
  316 +
255 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 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 60 \ No newline at end of file
... ...
stim/visualization/glnetwork.h renamed to stim/visualization/glnetwork-dep.h