Commit 2b28db3e764ab147540b5bd987c965de4c3f049b

Authored by Jiaming Guo
1 parent 5bd6c411

better render

stim/biomodels/network.h
... ... @@ -395,31 +395,40 @@ public:
395 395 stim::swc<T> S; // create swc variable
396 396 S.load(filename); // load the node information
397 397 S.create_tree(); // link those node according to their linking relationships as a tree
  398 + S.resample();
398 399  
399 400 //NT.push_back(S.node[0].type); // set the neuronal_type value to the first vertex in the network
400 401 std::vector<unsigned> id2vert; // this list stores the SWC vertex ID associated with each network vertex
401 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 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 415 c3.update(); // update the L information
410 416  
411 417 stim::cylinder<T> C3(c3); // create a new cylinder in order to copy the origin radius information
412 418 // upadate the R information
413 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 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 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 433 std::vector<unsigned>::iterator it; //create an iterator for searching the id2vert array
425 434 unsigned it_idx; //create an integer for the id2vert entry index
... ... @@ -441,7 +450,7 @@ public:
441 450  
442 451 it = find(id2vert.begin(), id2vert.end(), i[1]); //look for the second ID
443 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 454 new_vertex.e[1].push_back(E.size()); //add the current edge as incoming
446 455 new_edge.v[1] = V.size(); //add the new vertex to the edge
447 456 V.push_back(new_vertex); //add the new vertex to the vertex list
... ... @@ -620,8 +629,6 @@ public:
620 629 kdt.create(c, n_data, MaxTreeLevels);
621 630  
622 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 633 size_t n = R.E[e].size(); // the number of points in current edge
627 634 T* query = new T[3 * n];
... ... @@ -634,8 +641,8 @@ public:
634 641 kdt.cpu_search(queryPt, n, nnIdx, dists); //find the distance between A and the current network
635 642  
636 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 648 #endif
... ... @@ -746,10 +753,8 @@ public:
746 753 edge_point_num[ee] = B.E[ee].size();
747 754  
748 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 759 T* queryPt = new T[3 * n];
755 760 T* m1 = new T[n];
... ... @@ -761,7 +766,7 @@ public:
761 766  
762 767 for(unsigned p = 0; p < A.E[e].size(); p++){
763 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 771 unsigned id = 0; //mapping edge's idx
767 772 size_t num = 0; //total number of points before #th edge
... ... @@ -909,9 +914,8 @@ public:
909 914  
910 915 for(unsigned e = 0; e < R.E.size(); e++){ // for each edge in A
911 916 T M; // the sum of metrics of current edge
912   - unsigned errormag_id = R.E[e].nmags() - 1;
913 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 919 M = M / A.E[e].size();
916 920 if(M > threshold)
917 921 C[e] = (unsigned)-1;
... ...
stim/visualization/gl_network.h
... ... @@ -115,6 +115,8 @@ public:
115 115 if (!glIsList(dlist)) { // if dlist isn't a display list, create it
116 116 dlist = glGenLists(1); // generate a display list
117 117 glNewList(dlist, GL_COMPILE); // start a new display list
  118 + glEnable(GL_COLOR_MATERIAL);
  119 + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
118 120 for (unsigned e = 0; e < E.size(); e++) { // for each edge in the network
119 121 for (unsigned p = 1; p < E[e].size(); p++) { // for each point on that edge
120 122 stim::circle<T> C1 = E[e].circ(p - 1);
... ... @@ -125,7 +127,7 @@ public:
125 127 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);
126 128 glBegin(GL_QUAD_STRIP);
127 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 131 glVertex3f(Cp1[i][0], Cp1[i][1], Cp1[i][2]);
130 132 glTexCoord1f(E[e].r(p));
131 133 glVertex3f(Cp2[i][0], Cp2[i][1], Cp2[i][2]);
... ... @@ -150,77 +152,67 @@ public:
150 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 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 195 ///@param map is the mapping relationship between two networks
209 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 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 213 stim::circle<T> C1 = E[e].circ(p - 1);
222 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 216 C2.set_R(2*radius);
225 217 std::vector< stim::vec3<T> >Cp1 = C1.glpoints(20);
226 218 std::vector< stim::vec3<T> >Cp2 = C2.glpoints(20);
... ... @@ -252,52 +244,27 @@ public:
252 244 }
253 245 }
254 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 254 ///@param dlist1 is the display list
261 255 ///@param map is the mapping relationship between two networks
262 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 258 if (!glIsList(dlist1)) {
265 259 dlist1 = glGenLists(1);
266 260 glNewList(dlist1, GL_COMPILE);
267 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 268 glBegin(GL_LINE_STRIP);
302 269 for (unsigned p = 0; p < E[e].size(); p++) {
303 270 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);
... ... @@ -305,7 +272,7 @@ public:
305 272 glEnd();
306 273 }
307 274 else {
308   - glColor3f(1.0, 1.0, 1.0); // white color
  275 + glColor3f(1.0, 1.0, 1.0); // white color
309 276 glBegin(GL_LINE_STRIP);
310 277 for (unsigned p = 0; p < E[e].size(); p++) {
311 278 glVertex3f(E[e][p][0], E[e][p][1], E[e][p][2]);
... ... @@ -315,7 +282,7 @@ public:
315 282 }
316 283 glEndList();
317 284 }
318   - glCallList(dlist2);
  285 + glCallList(dlist1);
319 286 }
320 287  
321 288 //void glRandColorCenterlineGT(GLuint &dlist1, std::vector<unsigned> map, std::vector<T> colormap){
... ...
stim/visualization/swc.h
... ... @@ -86,6 +86,8 @@ namespace stim {
86 86 class swc {
87 87 public:
88 88 std::vector< typename swc_tree::swc_node<T> > node;
  89 + std::vector< std::vector<int> > E; // list of nodes
  90 +
89 91 swc() {}; // default constructor
90 92  
91 93 // load the swc as tree nodes
... ... @@ -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 263 // return the number of point in swc
174   - unsigned int numL() {
  264 + unsigned int numP() {
175 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 275 } // end of namespace stim
... ...