Commit 2b28db3e764ab147540b5bd987c965de4c3f049b

Authored by Jiaming Guo
1 parent 5bd6c411

better render

stim/biomodels/network.h
@@ -395,31 +395,40 @@ public: @@ -395,31 +395,40 @@ public:
395 stim::swc<T> S; // create swc variable 395 stim::swc<T> S; // create swc variable
396 S.load(filename); // load the node information 396 S.load(filename); // load the node information
397 S.create_tree(); // link those node according to their linking relationships as a tree 397 S.create_tree(); // link those node according to their linking relationships as a tree
  398 + S.resample();
398 399
399 //NT.push_back(S.node[0].type); // set the neuronal_type value to the first vertex in the network 400 //NT.push_back(S.node[0].type); // set the neuronal_type value to the first vertex in the network
400 std::vector<unsigned> id2vert; // this list stores the SWC vertex ID associated with each network vertex 401 std::vector<unsigned> id2vert; // this list stores the SWC vertex ID associated with each network vertex
401 unsigned i[2]; // temporary, IDs associated with the first and last points 402 unsigned i[2]; // temporary, IDs associated with the first and last points
402 - for (unsigned int l = 1; l < S.numL(); l++) { // for every node starts from second one 403 +
  404 + for (unsigned int l = 0; l < S.numE(); l++) { // for every edge
403 //NT.push_back(S.node[l].type); 405 //NT.push_back(S.node[l].type);
404 - stim::centerline<T> c3(2); // every fiber contains two vertices  
405 - int p_idx = S.node[l].parent_idx - 1; // get the parent node loop idx of current node  
406 - c3[0] = S.node[p_idx].point; // store the begin vertex  
407 - c3[1] = S.node[l].point; // store the end vertex 406 +
  407 + std::vector< stim::vec3<T> > c;
  408 + S.get_points(l, c);
  409 +
  410 + stim::centerline<T> c3(c.size()); // new fiber
  411 +
  412 + for (unsigned j = 0; j < c.size(); j++)
  413 + c3[j] = c[j]; // copy the points
408 414
409 c3.update(); // update the L information 415 c3.update(); // update the L information
410 416
411 stim::cylinder<T> C3(c3); // create a new cylinder in order to copy the origin radius information 417 stim::cylinder<T> C3(c3); // create a new cylinder in order to copy the origin radius information
412 // upadate the R information 418 // upadate the R information
413 std::vector<T> radius; 419 std::vector<T> radius;
414 - radius.push_back(S.node[p_idx].radius);  
415 - radius.push_back(S.node[l].radius); 420 + S.get_radius(l, radius);
  421 +
416 C3.copy_r(radius); 422 C3.copy_r(radius);
417 423
418 - edge new_edge(C3); // contains two points 424 + edge new_edge(C3); // new edge
  425 +
  426 + //create an edge from the given centerline
  427 + unsigned int I = new_edge.size(); //calculate the number of points on the centerline
419 428
420 //get the first and last vertex IDs for the line 429 //get the first and last vertex IDs for the line
421 - i[0] = S.node[p_idx].idx; //get the SWC ID for the start point  
422 - i[1] = S.node[l].idx; //get the SWC ID for the end point 430 + i[0] = S.E[l].front();
  431 + i[1] = S.E[l].back();
423 432
424 std::vector<unsigned>::iterator it; //create an iterator for searching the id2vert array 433 std::vector<unsigned>::iterator it; //create an iterator for searching the id2vert array
425 unsigned it_idx; //create an integer for the id2vert entry index 434 unsigned it_idx; //create an integer for the id2vert entry index
@@ -441,7 +450,7 @@ public: @@ -441,7 +450,7 @@ public:
441 450
442 it = find(id2vert.begin(), id2vert.end(), i[1]); //look for the second ID 451 it = find(id2vert.begin(), id2vert.end(), i[1]); //look for the second ID
443 if (it == id2vert.end()) { //if i[1] hasn't already been used 452 if (it == id2vert.end()) { //if i[1] hasn't already been used
444 - vertex new_vertex = new_edge[1]; //create a new vertex, assign it a position 453 + vertex new_vertex = new_edge[I - 1]; //create a new vertex, assign it a position
445 new_vertex.e[1].push_back(E.size()); //add the current edge as incoming 454 new_vertex.e[1].push_back(E.size()); //add the current edge as incoming
446 new_edge.v[1] = V.size(); //add the new vertex to the edge 455 new_edge.v[1] = V.size(); //add the new vertex to the edge
447 V.push_back(new_vertex); //add the new vertex to the vertex list 456 V.push_back(new_vertex); //add the new vertex to the vertex list
@@ -620,8 +629,6 @@ public: @@ -620,8 +629,6 @@ public:
620 kdt.create(c, n_data, MaxTreeLevels); 629 kdt.create(c, n_data, MaxTreeLevels);
621 630
622 for(unsigned e = 0; e < R.E.size(); e++){ //for each edge in A 631 for(unsigned e = 0; e < R.E.size(); e++){ //for each edge in A
623 - R.E[e].add_mag(0); //add a new magnitude for the metric  
624 - size_t errormag_id = R.E[e].nmags() - 1;  
625 632
626 size_t n = R.E[e].size(); // the number of points in current edge 633 size_t n = R.E[e].size(); // the number of points in current edge
627 T* query = new T[3 * n]; 634 T* query = new T[3 * n];
@@ -634,8 +641,8 @@ public: @@ -634,8 +641,8 @@ public:
634 kdt.cpu_search(queryPt, n, nnIdx, dists); //find the distance between A and the current network 641 kdt.cpu_search(queryPt, n, nnIdx, dists); //find the distance between A and the current network
635 642
636 for(unsigned p = 0; p < R.E[e].size(); p++){ 643 for(unsigned p = 0; p < R.E[e].size(); p++){
637 - m1[p] = 1.0f - gaussianFunction((T)dists[p], sigma); //calculate the metric value based on the distance  
638 - R.E[e].set_mag(errormag_id, p, m1[p]); //set the error for the second point in the segment 644 + m1[p] = 1.0f - gaussianFunction((T)dists[p], sigma); //calculate the metric value based on the distance
  645 + R.E[e].set_r(p, m1[p]); //set the error for the second point in the segment
639 } 646 }
640 } 647 }
641 #endif 648 #endif
@@ -746,10 +753,8 @@ public: @@ -746,10 +753,8 @@ public:
746 edge_point_num[ee] = B.E[ee].size(); 753 edge_point_num[ee] = B.E[ee].size();
747 754
748 for(unsigned e = 0; e < A.E.size(); e++){ //for each edge in A 755 for(unsigned e = 0; e < A.E.size(); e++){ //for each edge in A
749 - A.E[e].add_mag(0); //add a new magnitude for the metric  
750 - size_t errormag_id = A.E[e].nmags() - 1;  
751 -  
752 - size_t n = A.E[e].size(); // the number of edges in A 756 +
  757 + size_t n = A.E[e].size(); //the number of edges in A
753 758
754 T* queryPt = new T[3 * n]; 759 T* queryPt = new T[3 * n];
755 T* m1 = new T[n]; 760 T* m1 = new T[n];
@@ -761,7 +766,7 @@ public: @@ -761,7 +766,7 @@ public:
761 766
762 for(unsigned p = 0; p < A.E[e].size(); p++){ 767 for(unsigned p = 0; p < A.E[e].size(); p++){
763 m1[p] = 1.0f - gaussianFunction((T)dists[p], sigma); //calculate the metric value based on the distance 768 m1[p] = 1.0f - gaussianFunction((T)dists[p], sigma); //calculate the metric value based on the distance
764 - A.E[e].set_mag(errormag_id, p, m1[p]); //set the error for the second point in the segment 769 + A.E[e].set_r(p, m1[p]); //set the error for the second point in the segment
765 770
766 unsigned id = 0; //mapping edge's idx 771 unsigned id = 0; //mapping edge's idx
767 size_t num = 0; //total number of points before #th edge 772 size_t num = 0; //total number of points before #th edge
@@ -909,9 +914,8 @@ public: @@ -909,9 +914,8 @@ public:
909 914
910 for(unsigned e = 0; e < R.E.size(); e++){ // for each edge in A 915 for(unsigned e = 0; e < R.E.size(); e++){ // for each edge in A
911 T M; // the sum of metrics of current edge 916 T M; // the sum of metrics of current edge
912 - unsigned errormag_id = R.E[e].nmags() - 1;  
913 for(unsigned p = 0; p < R.E[e].size(); p++) 917 for(unsigned p = 0; p < R.E[e].size(); p++)
914 - M += A.E[e].m(p, errormag_id); 918 + M += A.E[e].r(p);
915 M = M / A.E[e].size(); 919 M = M / A.E[e].size();
916 if(M > threshold) 920 if(M > threshold)
917 C[e] = (unsigned)-1; 921 C[e] = (unsigned)-1;
stim/visualization/gl_network.h
@@ -115,6 +115,8 @@ public: @@ -115,6 +115,8 @@ public:
115 if (!glIsList(dlist)) { // if dlist isn't a display list, create it 115 if (!glIsList(dlist)) { // if dlist isn't a display list, create it
116 dlist = glGenLists(1); // generate a display list 116 dlist = glGenLists(1); // generate a display list
117 glNewList(dlist, GL_COMPILE); // start a new display list 117 glNewList(dlist, GL_COMPILE); // start a new display list
  118 + glEnable(GL_COLOR_MATERIAL);
  119 + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
118 for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network 120 for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network
119 for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge 121 for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge
120 stim::circle<T> C1 = E[e].circ(p - 1); 122 stim::circle<T> C1 = E[e].circ(p - 1);
@@ -125,7 +127,7 @@ public: @@ -125,7 +127,7 @@ public:
125 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20); 127 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);
126 glBegin(GL_QUAD_STRIP); 128 glBegin(GL_QUAD_STRIP);
127 for (unsigned i = 0; i < Cp1.size(); i++) { // for every point on the circle(+1 means closing the circle) 129 for (unsigned i = 0; i < Cp1.size(); i++) { // for every point on the circle(+1 means closing the circle)
128 - glTexCoord1f(E[e].r(p-1)); 130 + glTexCoord1f(E[e].r(p - 1));
129 glVertex3f(Cp1[i][0], Cp1[i][1], Cp1[i][2]); 131 glVertex3f(Cp1[i][0], Cp1[i][1], Cp1[i][2]);
130 glTexCoord1f(E[e].r(p)); 132 glTexCoord1f(E[e].r(p));
131 glVertex3f(Cp2[i][0], Cp2[i][1], Cp2[i][2]); 133 glVertex3f(Cp2[i][0], Cp2[i][1], Cp2[i][2]);
@@ -150,77 +152,67 @@ public: @@ -150,77 +152,67 @@ public:
150 glCallList(dlist); // render the display list 152 glCallList(dlist); // render the display list
151 } 153 }
152 154
153 - ///render the GT network cylinder as series of tubes  
154 - ///@param dlist1 is the display list  
155 - ///@param map is the mapping relationship between two networks  
156 - ///@param colormap is the random generated color set for render  
157 - void glRandColorCylinder1(GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap, float sigma, float radius) { 155 + ///render a T as a adjoint network of GT in transparancy(darkgreen, overlaid)
  156 + void glAdjointCylinder(float sigma, float radius) {
158 157
159 - if (radius != sigma) // if render radius was changed by user, create a new display list  
160 - glDeleteLists(dlist1, 1);  
161 - if (!glIsList(dlist1)) { // if dlist1 isn't a display list, create it  
162 - dlist1 = glGenLists(1); // generate a display list  
163 - glNewList(dlist1, GL_COMPILE); // start a new display list  
164 - for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network  
165 - if (map[e] != unsigned(-1)) {  
166 - glColor3f(colormap[e * 3 + 0], colormap[e * 3 + 1], colormap[e * 3 + 2]);  
167 - for (unsigned p = 1; p < E[e].size(); p++) {// for each point on that edge  
168 - stim::circle<T> C1 = E[e].circ(p - 1);  
169 - stim::circle<T> C2 = E[e].circ(p);  
170 - C1.set_R(2*radius); // scale the circle to the same  
171 - C2.set_R(2*radius);  
172 - std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20);  
173 - std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);  
174 - renderCylinder(Cp1, Cp2);  
175 - }  
176 - }  
177 - else {  
178 - glColor3f(1.0f, 1.0f, 1.0f); // white color for the un-mapping edges  
179 - for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge  
180 - stim::circle<T> C1 = E[e].circ(p - 1);  
181 - stim::circle<T> C2 = E[e].circ(p);  
182 - C1.set_R(2*radius); // scale the circle to the same  
183 - C2.set_R(2*radius);  
184 - std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20);  
185 - std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);  
186 - renderCylinder(Cp1, Cp2); 158 + if (radius != sigma) // if render radius was changed by user, create a new display list
  159 + glDeleteLists(dlist+4, 1);
  160 + if (!glIsList(dlist+4)) {
  161 + glNewList(dlist+4, GL_COMPILE);
  162 + for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network
  163 + for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge
  164 + stim::circle<T> C1 = E[e].circ(p - 1);
  165 + stim::circle<T> C2 = E[e].circ(p);
  166 + C1.set_R(2 * radius); // scale the circle to the same
  167 + C2.set_R(2 * radius);
  168 + std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20);
  169 + std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);
  170 + glBegin(GL_QUAD_STRIP);
  171 + for (unsigned i = 0; i < Cp1.size(); i++) { // for every point on the circle(+1 means closing the circle)
  172 + glVertex3f(Cp1[i][0], Cp1[i][1], Cp1[i][2]);
  173 + glVertex3f(Cp2[i][0], Cp2[i][1], Cp2[i][2]);
187 } 174 }
188 - } 175 + glEnd();
  176 + } // set the texture coordinate based on the specified magnitude index
189 } 177 }
190 - for (unsigned v = 0; v < V.size(); v++) {  
191 - size_t num_edge = V[v].e[0].size() + V[v].e[1].size();  
192 - if (num_edge > 1) { // if it is the joint vertex  
193 - glColor3f(0.3, 0.3, 0.3); // gray color  
194 - renderBall(V[v][0], V[v][1], V[v][2], 3*radius, 20); 178 + for (unsigned n = 0; n < V.size(); n++) {
  179 + size_t num = V[n].e[0].size(); // store the number of outgoing edge of that vertex
  180 + if (num != 0) { // if it has outgoing edge
  181 + unsigned idx = V[n].e[0][0]; // find the index of first outgoing edge of that vertex
195 } 182 }
196 - else { // if it is the terminal vertex  
197 - glColor3f(0.6, 0.6, 0.6); // more white gray  
198 - renderBall(V[v][0], V[v][1], V[v][2], 3*radius, 20); 183 + else {
  184 + unsigned idx = V[n].e[1][0]; // find the index of first incoming edge of that vertex
199 } 185 }
  186 + renderBall(V[n][0], V[n][1], V[n][2], 2 * radius, 20);
200 } 187 }
201 glEndList(); 188 glEndList();
202 } 189 }
203 - glCallList(dlist1); 190 + glCallList(dlist+4);
204 } 191 }
205 192
206 - ///render the T network cylinder as series of tubes  
207 - ///@param dlist2 is the display list 193 + ///render the network cylinder as series of tubes
  194 + ///@param I is a indicator: 0 -> GT, 1 -> T
208 ///@param map is the mapping relationship between two networks 195 ///@param map is the mapping relationship between two networks
209 ///@param colormap is the random generated color set for render 196 ///@param colormap is the random generated color set for render
210 - void glRandColorCylinder2(GLuint &dlist2, std::vector<unsigned> map, std::vector<T> colormap, float sigma, float radius) { 197 + void glRandColorCylinder(int I, std::vector<unsigned> map, std::vector<T> colormap, float sigma, float radius) {
211 198
212 - if (radius != sigma) // if render radius was changed by user, create a new display list  
213 - glDeleteLists(dlist2, 1);  
214 - if (!glIsList(dlist2)) {  
215 - dlist2 = glGenLists(1);  
216 - glNewList(dlist2, GL_COMPILE);  
217 - for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network 199 + if (radius != sigma) // if render radius was changed by user, create a new display list
  200 + glDeleteLists(dlist+2, 1);
  201 + if (!glIsList(dlist+2)) { // if dlist isn't a display list, create it
  202 + glNewList(dlist+2, GL_COMPILE); // start a new display list
  203 + glEnable(GL_COLOR_MATERIAL);
  204 + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  205 + for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network
218 if (map[e] != unsigned(-1)) { 206 if (map[e] != unsigned(-1)) {
219 - glColor3f(colormap[map[e] * 3 + 0], colormap[map[e] * 3 + 1], colormap[map[e] * 3 + 2]);  
220 - for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge(except last one) 207 + if(I == 0) // if it is to render GT
  208 + glColor3f(colormap[e * 3 + 0], colormap[e * 3 + 1], colormap[e * 3 + 2]);
  209 + else // if it is to render T
  210 + glColor3f(colormap[map[e] * 3 + 0], colormap[map[e] * 3 + 1], colormap[map[e] * 3 + 2]);
  211 +
  212 + for (unsigned p = 1; p < E[e].size(); p++) {// for each point on that edge
221 stim::circle<T> C1 = E[e].circ(p - 1); 213 stim::circle<T> C1 = E[e].circ(p - 1);
222 stim::circle<T> C2 = E[e].circ(p); 214 stim::circle<T> C2 = E[e].circ(p);
223 - C1.set_R(2*radius); // scale the circle to the same 215 + C1.set_R(2*radius); // scale the circle to the same
224 C2.set_R(2*radius); 216 C2.set_R(2*radius);
225 std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20); 217 std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20);
226 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20); 218 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);
@@ -252,52 +244,27 @@ public: @@ -252,52 +244,27 @@ public:
252 } 244 }
253 } 245 }
254 glEndList(); 246 glEndList();
  247 + glDisable(GL_COLOR_MATERIAL);
255 } 248 }
256 - glCallList(dlist2); 249 + glCallList(dlist+2);
257 } 250 }
258 251
259 - /// Render the GT network centerline as a series of line strips in random different color 252 + ///render the network centerline as a series of line strips in random different color
  253 + ///@param I is a indicator: 0 -> GT, 1 -> T
260 ///@param dlist1 is the display list 254 ///@param dlist1 is the display list
261 ///@param map is the mapping relationship between two networks 255 ///@param map is the mapping relationship between two networks
262 ///@param colormap is the random generated color set for render 256 ///@param colormap is the random generated color set for render
263 - void glRandColorCenterline1(GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap) { 257 + void glRandColorCenterline(int I, GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap) {
264 if (!glIsList(dlist1)) { 258 if (!glIsList(dlist1)) {
265 dlist1 = glGenLists(1); 259 dlist1 = glGenLists(1);
266 glNewList(dlist1, GL_COMPILE); 260 glNewList(dlist1, GL_COMPILE);
267 for (unsigned e = 0; e < E.size(); e++) { 261 for (unsigned e = 0; e < E.size(); e++) {
268 - if (map[e] != unsigned(-1)) { // if it has corresponding edge in another network  
269 - glColor3f(colormap[e * 3 + 0], colormap[e * 3 + 1], colormap[e * 3 + 2]);  
270 - glBegin(GL_LINE_STRIP);  
271 - for (unsigned p = 0; p < E[e].size(); p++) {  
272 - glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);  
273 - }  
274 - glEnd();  
275 - }  
276 - else {  
277 - glColor3f(1.0, 1.0, 1.0); // white color  
278 - glBegin(GL_LINE_STRIP);  
279 - for (unsigned p = 0; p < E[e].size(); p++) {  
280 - glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);  
281 - }  
282 - glEnd();  
283 - }  
284 - }  
285 - glEndList();  
286 - }  
287 - glCallList(dlist1);  
288 - } 262 + if (map[e] != unsigned(-1)) { // if it has corresponding edge in another network
  263 + if (I == 0) // if it is to render GT
  264 + glColor3f(colormap[e * 3 + 0], colormap[e * 3 + 1], colormap[e * 3 + 2]);
  265 + else // if it is to render T
  266 + glColor3f(colormap[map[e] * 3 + 0], colormap[map[e] * 3 + 1], colormap[map[e] * 3 + 2]);
289 267
290 - /// Render the T network centerline as a series of line strips in random different color  
291 - ///@param dlist2 is the display list  
292 - ///@param map is the mapping relationship between two networks  
293 - ///@param colormap is the random generated color set for render  
294 - void glRandColorCenterline2(GLuint &dlist2, std::vector<unsigned> map, std::vector<T> colormap) {  
295 - if (!glIsList(dlist2)) {  
296 - dlist2 = glGenLists(1);  
297 - glNewList(dlist2, GL_COMPILE);  
298 - for (unsigned e = 0; e < E.size(); e++) {  
299 - if (map[e] != unsigned(-1)) { // if it has corresponding edge in another network  
300 - glColor3f(colormap[map[e] * 3 + 0], colormap[map[e] * 3 + 1], colormap[map[e] * 3 + 2]);  
301 glBegin(GL_LINE_STRIP); 268 glBegin(GL_LINE_STRIP);
302 for (unsigned p = 0; p < E[e].size(); p++) { 269 for (unsigned p = 0; p < E[e].size(); p++) {
303 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]); 270 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);
@@ -305,7 +272,7 @@ public: @@ -305,7 +272,7 @@ public:
305 glEnd(); 272 glEnd();
306 } 273 }
307 else { 274 else {
308 - glColor3f(1.0, 1.0, 1.0); // white color 275 + glColor3f(1.0, 1.0, 1.0); // white color
309 glBegin(GL_LINE_STRIP); 276 glBegin(GL_LINE_STRIP);
310 for (unsigned p = 0; p < E[e].size(); p++) { 277 for (unsigned p = 0; p < E[e].size(); p++) {
311 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]); 278 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);
@@ -315,7 +282,7 @@ public: @@ -315,7 +282,7 @@ public:
315 } 282 }
316 glEndList(); 283 glEndList();
317 } 284 }
318 - glCallList(dlist2); 285 + glCallList(dlist1);
319 } 286 }
320 287
321 //void glRandColorCenterlineGT(GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap){ 288 //void glRandColorCenterlineGT(GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap){
stim/visualization/swc.h
@@ -86,6 +86,8 @@ namespace stim { @@ -86,6 +86,8 @@ namespace stim {
86 class swc { 86 class swc {
87 public: 87 public:
88 std::vector< typename swc_tree::swc_node<T> > node; 88 std::vector< typename swc_tree::swc_node<T> > node;
  89 + std::vector< std::vector<int> > E; // list of nodes
  90 +
89 swc() {}; // default constructor 91 swc() {}; // default constructor
90 92
91 // load the swc as tree nodes 93 // load the swc as tree nodes
@@ -170,11 +172,104 @@ namespace stim { @@ -170,11 +172,104 @@ namespace stim {
170 } 172 }
171 } 173 }
172 174
  175 + // create a new edge
  176 + void create_up(std::vector<int>& edge,swc_tree::swc_node<T> cur_node, int target) {
  177 + while (cur_node.parent_idx != target) {
  178 + edge.push_back(cur_node.idx);
  179 + cur_node = node[cur_node.parent_idx - 1]; // move to next node
  180 + }
  181 + edge.push_back(cur_node.idx); // push back the start/end vertex of current edge
  182 +
  183 + std::reverse(edge.begin(), edge.end()); // follow the original flow direction
  184 + }
  185 + void create_down(std::vector<int>& edge, swc_tree::swc_node<T> cur_node, int j) {
  186 + while (cur_node.son_idx.size() != 0) {
  187 + edge.push_back(cur_node.idx);
  188 + if (cur_node.son_idx.size() > 1)
  189 + cur_node = node[cur_node.son_idx[j] - 1]; // move to next node
  190 + else
  191 + cur_node = node[cur_node.son_idx[0] - 1];
  192 + }
  193 + edge.push_back(cur_node.idx); // push back the start/end vertex of current edge
  194 + }
  195 +
  196 + // resample the tree-like SWC
  197 + void resample() {
  198 + unsigned n = node.size();
  199 +
  200 + std::vector<int> joint_node;
  201 + for (unsigned i = 1; i < n; i++) { // search all nodes(except the first one) to find joint nodes
  202 + if (node[i].son_idx.size() > 1) {
  203 + joint_node.push_back(node[i].idx); // store the original index
  204 + }
  205 + }
  206 +
  207 + std::vector<int> new_edge; // new edge in the network
  208 +
  209 + n = joint_node.size();
  210 +
  211 + for (unsigned i = 0; i < n; i++) { // for every joint nodes
  212 + std::vector<int> new_edge; // new edge in the network
  213 + swc_tree::swc_node<T> cur_node = node[joint_node[i] - 1]; // store current node
  214 +
  215 + // go up
  216 + swc_tree::swc_node<T> tmp_node = node[cur_node.parent_idx - 1];
  217 + while (tmp_node.parent_idx != -1 && tmp_node.son_idx.size() == 1) {
  218 + tmp_node = node[tmp_node.parent_idx - 1];
  219 + }
  220 + int target = tmp_node.parent_idx; // store the go-up target
  221 + create_up(new_edge, cur_node, target);
  222 + E.push_back(new_edge);
  223 + new_edge.clear();
  224 +
  225 + // go down
  226 + unsigned t = cur_node.son_idx.size();
  227 + for (unsigned j = 0; j < t; j++) { // for every son node
  228 + tmp_node = node[cur_node.son_idx[j] - 1]; // move down
  229 + while (tmp_node.son_idx.size() == 1) {
  230 + tmp_node = node[tmp_node.son_idx[0] - 1];
  231 + }
  232 + if (tmp_node.son_idx.size() == 0) {
  233 + create_down(new_edge, cur_node, j);
  234 + E.push_back(new_edge);
  235 + new_edge.clear();
  236 + }
  237 + }
  238 + }
  239 + }
  240 +
  241 + // get points in one edge
  242 + void get_points(int e, std::vector< stim::vec3<T> >& V) {
  243 + V.resize(E[e].size());
  244 + for (unsigned i = 0; i < E[e].size(); i++) {
  245 + unsigned id = E[e][i] - 1;
  246 +
  247 + V[i][0] = node[id].point[0];
  248 + V[i][1] = node[id].point[1];
  249 + V[i][2] = node[id].point[2];
  250 + }
  251 + }
  252 +
  253 + // get radius information in one edge
  254 + void get_radius(int e, std::vector<T>& radius) {
  255 + radius.resize(E[e].size());
  256 + for (unsigned i = 0; i < E[e].size(); i++) {
  257 + unsigned id = E[e][i] - 1;
  258 +
  259 + radius[i] = node[id].radius;
  260 + }
  261 + }
  262 +
173 // return the number of point in swc 263 // return the number of point in swc
174 - unsigned int numL() { 264 + unsigned int numP() {
175 return node.size(); 265 return node.size();
176 } 266 }
177 267
  268 + // return the number of edges in swc after resample
  269 + unsigned int numE() {
  270 + return E.size();
  271 + }
  272 +
178 273
179 }; 274 };
180 } // end of namespace stim 275 } // end of namespace stim