Commit 8f6c2057eeb0eb428641e9cd53a7f437139dbdfb
1 parent
4bb615eb
fixed index marking bugs after network subdivided
Showing
2 changed files
with
110 additions
and
24 deletions
Show diff stats
@@ -67,7 +67,7 @@ namespace stim { | @@ -67,7 +67,7 @@ namespace stim { | ||
67 | #ifdef __CUDACC__ | 67 | #ifdef __CUDACC__ |
68 | // for sphere | 68 | // for sphere |
69 | template <typename T> | 69 | template <typename T> |
70 | - __global__ void inside_sphere(const stim::sphere<T> *V, size_t num, T Z,size_t *R, T *S, unsigned char *ptr, int x, int y, int z) { | 70 | + __global__ void inside_sphere(const stim::sphere<T> *V, size_t num, T Z,size_t *R, T *S, unsigned char *ptr, int x, int y, int z, T std = 1.0f) { |
71 | 71 | ||
72 | unsigned ix = blockDim.x * blockIdx.x + threadIdx.x; | 72 | unsigned ix = blockDim.x * blockIdx.x + threadIdx.x; |
73 | unsigned iy = blockDim.y * blockIdx.y + threadIdx.y; | 73 | unsigned iy = blockDim.y * blockIdx.y + threadIdx.y; |
@@ -93,11 +93,16 @@ namespace stim { | @@ -93,11 +93,16 @@ namespace stim { | ||
93 | } | 93 | } |
94 | if (distance <= V[idx].r) | 94 | if (distance <= V[idx].r) |
95 | ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; | 95 | ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; |
96 | + else { | ||
97 | + T g = gaussianFunction(std::pow(distance - V[idx].r, 2), std); | ||
98 | + if(g > 0.1f) | ||
99 | + ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; | ||
100 | + } | ||
96 | } | 101 | } |
97 | 102 | ||
98 | // for cone | 103 | // for cone |
99 | template <typename T> | 104 | template <typename T> |
100 | - __global__ void inside_cone(const stim::cone<T> *E, size_t num, T Z, size_t *R, T *S, unsigned char *ptr, int x, int y, int z) { | 105 | + __global__ void inside_cone(const stim::cone<T> *E, size_t num, T Z, size_t *R, T *S, unsigned char *ptr, int x, int y, int z, T std = 1.0f) { |
101 | 106 | ||
102 | unsigned ix = blockDim.x * blockIdx.x + threadIdx.x; | 107 | unsigned ix = blockDim.x * blockIdx.x + threadIdx.x; |
103 | unsigned iy = blockDim.y * blockIdx.y + threadIdx.y; | 108 | unsigned iy = blockDim.y * blockIdx.y + threadIdx.y; |
@@ -129,6 +134,11 @@ namespace stim { | @@ -129,6 +134,11 @@ namespace stim { | ||
129 | } | 134 | } |
130 | if (distance <= rr) | 135 | if (distance <= rr) |
131 | ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; | 136 | ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; |
137 | + else { | ||
138 | + T g = gaussianFunction(std::pow(distance - rr, 2), std); | ||
139 | + if (g > 0.1f) | ||
140 | + ptr[(R[2] - 1 - iy) * R[0] * R[1] + ix * R[0]] = 255; | ||
141 | + } | ||
132 | } | 142 | } |
133 | 143 | ||
134 | // for source bus | 144 | // for source bus |
@@ -252,7 +262,7 @@ namespace stim { | @@ -252,7 +262,7 @@ namespace stim { | ||
252 | 262 | ||
253 | bool set = false; // flag indicates the pressure has been set | 263 | bool set = false; // flag indicates the pressure has been set |
254 | std::vector<T> P; // initial pressure | 264 | std::vector<T> P; // initial pressure |
255 | - std::vector<T> v; // velocity | 265 | + std::vector<T> v; // average velocity along each edge |
256 | std::vector<typename stim::vec3<T> > main_feeder; // inlet/outlet main feeder | 266 | std::vector<typename stim::vec3<T> > main_feeder; // inlet/outlet main feeder |
257 | std::vector<unsigned> pendant_vertex; | 267 | std::vector<unsigned> pendant_vertex; |
258 | std::vector<typename stim::triple<unsigned, unsigned, T> > input; // first one store which vertex, second one stores which edge, third one stores in/out volume flow rate of that vertex | 268 | std::vector<typename stim::triple<unsigned, unsigned, T> > input; // first one store which vertex, second one stores which edge, third one stores in/out volume flow rate of that vertex |
@@ -350,12 +360,22 @@ namespace stim { | @@ -350,12 +360,22 @@ namespace stim { | ||
350 | return E[tmp_e].r(tmp_v); | 360 | return E[tmp_e].r(tmp_v); |
351 | } | 361 | } |
352 | 362 | ||
353 | - // get the radius of index j of edge i | 363 | + // get the radius of point j on edge i |
354 | T get_radius(unsigned i, unsigned j) { | 364 | T get_radius(unsigned i, unsigned j) { |
355 | return E[i].r(j); | 365 | return E[i].r(j); |
356 | } | 366 | } |
357 | 367 | ||
358 | - // get the pendant vertices | 368 | + // back up vertices |
369 | + std::vector<stim::vec3<T> > back_vertex() { | ||
370 | + std::vector<stim::vec3<T> > result; | ||
371 | + | ||
372 | + for (unsigned i = 0; i < num_vertex; i++) | ||
373 | + result.push_back(stim::vec3<T>(V[i][0], V[i][1], V[i][2])); | ||
374 | + | ||
375 | + return result; | ||
376 | + } | ||
377 | + | ||
378 | + // get pendant vertices | ||
359 | std::vector<unsigned> get_pendant_vertex() { | 379 | std::vector<unsigned> get_pendant_vertex() { |
360 | std::vector<unsigned> result; | 380 | std::vector<unsigned> result; |
361 | int count = 0; | 381 | int count = 0; |
@@ -851,7 +871,7 @@ namespace stim { | @@ -851,7 +871,7 @@ namespace stim { | ||
851 | } | 871 | } |
852 | else | 872 | else |
853 | glColor3f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255); | 873 | glColor3f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255); |
854 | - | 874 | + |
855 | for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on the edge | 875 | for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on the edge |
856 | center1 = E[i][j]; | 876 | center1 = E[i][j]; |
857 | center2 = E[i][j + 1]; | 877 | center2 = E[i][j + 1]; |
@@ -1532,13 +1552,13 @@ namespace stim { | @@ -1532,13 +1552,13 @@ namespace stim { | ||
1532 | } | 1552 | } |
1533 | 1553 | ||
1534 | // mark the vertex | 1554 | // mark the vertex |
1535 | - void mark_vertex(T scale = 1.0f) { | 1555 | + void mark_vertex(std::vector<stim::vec3<T> > vertex, T scale = 1.0f) { |
1536 | 1556 | ||
1537 | glColor3f(0.0f, 0.0f, 0.0f); | 1557 | glColor3f(0.0f, 0.0f, 0.0f); |
1538 | - for (unsigned i = 0; i < num_vertex; i++) { | ||
1539 | - glRasterPos3f(V[i][0], V[i][1] + get_radius(i) * scale, V[i][2]); | 1558 | + for (unsigned i = 0; i < vertex.size(); i++) { |
1559 | + glRasterPos3f(vertex[i][0], vertex[i][1] + get_radius(i) * scale, vertex[i][2]); // place position | ||
1540 | std::stringstream ss; | 1560 | std::stringstream ss; |
1541 | - ss << i; | 1561 | + ss << i; // store index value |
1542 | glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss.str().c_str())); | 1562 | glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss.str().c_str())); |
1543 | } | 1563 | } |
1544 | } | 1564 | } |
@@ -2877,7 +2897,18 @@ namespace stim { | @@ -2877,7 +2897,18 @@ namespace stim { | ||
2877 | f_file.close(); | 2897 | f_file.close(); |
2878 | } | 2898 | } |
2879 | 2899 | ||
2880 | - /// Calculate the inverse of A and store the result in C | 2900 | + /// check whether current network needs to be subdivided |
2901 | + bool check_subdivision() { | ||
2902 | + | ||
2903 | + for (size_t i = 0; i < num_edge; i++) { | ||
2904 | + if (E[i].size() > 2) { | ||
2905 | + return true; | ||
2906 | + } | ||
2907 | + } | ||
2908 | + return false; | ||
2909 | + } | ||
2910 | + | ||
2911 | + /// calculate the inverse of A and store the result in C | ||
2881 | void inversion(T** A, int order, T* C) { | 2912 | void inversion(T** A, int order, T* C) { |
2882 | 2913 | ||
2883 | #ifdef __CUDACC__ | 2914 | #ifdef __CUDACC__ |
@@ -2970,6 +3001,15 @@ namespace stim { | @@ -2970,6 +3001,15 @@ namespace stim { | ||
2970 | free(minor); | 3001 | free(minor); |
2971 | #endif | 3002 | #endif |
2972 | } | 3003 | } |
3004 | + | ||
3005 | + /// arithmetic | ||
3006 | + // assignment | ||
3007 | + flow<T> & operator= (flow<T> rhs) { | ||
3008 | + E = rhs.E; | ||
3009 | + V = rhs.V; | ||
3010 | + | ||
3011 | + return *this; | ||
3012 | + } | ||
2973 | }; | 3013 | }; |
2974 | } | 3014 | } |
2975 | 3015 |
main.cu
@@ -40,6 +40,7 @@ unsigned num_vertex; // number of vertex in the network | @@ -40,6 +40,7 @@ unsigned num_vertex; // number of vertex in the network | ||
40 | std::vector<unsigned> pendant_vertex; // list of pendant vertex index in GT | 40 | std::vector<unsigned> pendant_vertex; // list of pendant vertex index in GT |
41 | std::vector<std::string> menu_option = { "simulation", "build inlet/outlet", "manufacture", "adjustment" }; | 41 | std::vector<std::string> menu_option = { "simulation", "build inlet/outlet", "manufacture", "adjustment" }; |
42 | stim::flow<float> flow; // flow object | 42 | stim::flow<float> flow; // flow object |
43 | +stim::flow<float> backup; // flow backup | ||
43 | float move_pace; // camera moving parameter | 44 | float move_pace; // camera moving parameter |
44 | float u; // viscosity | 45 | float u; // viscosity |
45 | float rou; // density | 46 | float rou; // density |
@@ -79,7 +80,7 @@ int mouse_x; // window x-coordinate | @@ -79,7 +80,7 @@ int mouse_x; // window x-coordinate | ||
79 | int mouse_y; // window y-coordinate | 80 | int mouse_y; // window y-coordinate |
80 | int picked_x; // picked window x-coordinate | 81 | int picked_x; // picked window x-coordinate |
81 | int picked_y; // picked window y-coordinate | 82 | int picked_y; // picked window y-coordinate |
82 | -bool LTbutton = false; // true means down while false means up | 83 | +bool LTbutton = false; // true means down while false means up |
83 | 84 | ||
84 | // simulation parameters | 85 | // simulation parameters |
85 | bool render_direction = false; // flag indicates rendering flow direction for one edge | 86 | bool render_direction = false; // flag indicates rendering flow direction for one edge |
@@ -89,8 +90,10 @@ bool to_select_pressure = false; // flag indicates having selected a vertex to m | @@ -89,8 +90,10 @@ bool to_select_pressure = false; // flag indicates having selected a vertex to m | ||
89 | bool mark_index = true; // flag indicates marking the index near the vertex | 90 | bool mark_index = true; // flag indicates marking the index near the vertex |
90 | bool glyph_mode = false; // flag indicates rendering glyph for flow velocity field | 91 | bool glyph_mode = false; // flag indicates rendering glyph for flow velocity field |
91 | bool frame_mode = false; // flag indicates rendering filament framing structrues | 92 | bool frame_mode = false; // flag indicates rendering filament framing structrues |
93 | +bool subdivided = false; // flag indicates subdivision status | ||
92 | unsigned pressure_index; // the index of vertex that is clicked | 94 | unsigned pressure_index; // the index of vertex that is clicked |
93 | unsigned direction_index = UINT_MAX;// the index of edge that is pointed at | 95 | unsigned direction_index = UINT_MAX;// the index of edge that is pointed at |
96 | +std::vector<stim::vec3<float> > back_vertex; // vertex back up for marking indices | ||
94 | 97 | ||
95 | // build inlet/outlet parameters | 98 | // build inlet/outlet parameters |
96 | bool build_inlet_outlet = false; // flag indicates building inlets and outlets | 99 | bool build_inlet_outlet = false; // flag indicates building inlets and outlets |
@@ -169,6 +172,8 @@ void flow_initialize() { | @@ -169,6 +172,8 @@ void flow_initialize() { | ||
169 | 172 | ||
170 | flow.set = true; | 173 | flow.set = true; |
171 | stim::vec3<float> center = bb.center(); | 174 | stim::vec3<float> center = bb.center(); |
175 | + flow.P.clear(); | ||
176 | + flow.P.resize(num_vertex, 0); // clear up initialized pressure | ||
172 | 177 | ||
173 | for (unsigned i = 0; i < pendant_vertex.size(); i++) { | 178 | for (unsigned i = 0; i < pendant_vertex.size(); i++) { |
174 | if (flow.get_vertex(pendant_vertex[i])[0] <= center[0]) | 179 | if (flow.get_vertex(pendant_vertex[i])[0] <= center[0]) |
@@ -271,7 +276,7 @@ void glut_render() { | @@ -271,7 +276,7 @@ void glut_render() { | ||
271 | if (!glyph_mode) { | 276 | if (!glyph_mode) { |
272 | flow.glSolidSphere(max_pressure, subdivision, scale); | 277 | flow.glSolidSphere(max_pressure, subdivision, scale); |
273 | if (mark_index) | 278 | if (mark_index) |
274 | - flow.mark_vertex(scale); | 279 | + flow.mark_vertex(back_vertex, scale); |
275 | //flow.glSolidCone(subdivision); | 280 | //flow.glSolidCone(subdivision); |
276 | flow.glSolidCylinder(direction_index, color, subdivision, scale); | 281 | flow.glSolidCylinder(direction_index, color, subdivision, scale); |
277 | } | 282 | } |
@@ -288,7 +293,7 @@ void glut_render() { | @@ -288,7 +293,7 @@ void glut_render() { | ||
288 | if (!glyph_mode) { | 293 | if (!glyph_mode) { |
289 | flow.glSolidSphere(max_pressure, subdivision, scale); | 294 | flow.glSolidSphere(max_pressure, subdivision, scale); |
290 | if (mark_index) { | 295 | if (mark_index) { |
291 | - flow.mark_vertex(scale); | 296 | + flow.mark_vertex(back_vertex, scale); |
292 | //flow.mark_edge(); | 297 | //flow.mark_edge(); |
293 | } | 298 | } |
294 | //flow.glSolidCone(subdivision); | 299 | //flow.glSolidCone(subdivision); |
@@ -299,7 +304,7 @@ void glut_render() { | @@ -299,7 +304,7 @@ void glut_render() { | ||
299 | flow.glyph(color, subdivision, scale, frame_mode); | 304 | flow.glyph(color, subdivision, scale, frame_mode); |
300 | } | 305 | } |
301 | flow.glSolidCuboid(subdivision, manufacture, length); // render bus source | 306 | flow.glSolidCuboid(subdivision, manufacture, length); // render bus source |
302 | - if (render_direction) // render the flow direction of the vertex pointed | 307 | + if (render_direction && !glyph_mode) // render the flow direction of the vertex pointed |
303 | flow.glSolidCone(direction_index, subdivision, scale); | 308 | flow.glSolidCone(direction_index, subdivision, scale); |
304 | } | 309 | } |
305 | 310 | ||
@@ -495,6 +500,7 @@ void glut_menu(int value) { | @@ -495,6 +500,7 @@ void glut_menu(int value) { | ||
495 | // first time | 500 | // first time |
496 | if (!flow.set) { // only first time simulation called "simulation", ^_^ | 501 | if (!flow.set) { // only first time simulation called "simulation", ^_^ |
497 | get_background(); // get the graph information | 502 | get_background(); // get the graph information |
503 | + back_vertex = flow.back_vertex(); // vertex back up for marking indices | ||
498 | flow_initialize(); // initialize flow condition | 504 | flow_initialize(); // initialize flow condition |
499 | menu_option[0] = "resimulation"; | 505 | menu_option[0] = "resimulation"; |
500 | } | 506 | } |
@@ -584,6 +590,7 @@ void glut_passive_motion(int x, int y) { | @@ -584,6 +590,7 @@ void glut_passive_motion(int x, int y) { | ||
584 | render_direction = false; | 590 | render_direction = false; |
585 | direction_index = -1; | 591 | direction_index = -1; |
586 | } | 592 | } |
593 | + undo = true; | ||
587 | } | 594 | } |
588 | 595 | ||
589 | if (mods == GLUT_ACTIVE_SHIFT && picked_connection) { | 596 | if (mods == GLUT_ACTIVE_SHIFT && picked_connection) { |
@@ -888,7 +895,7 @@ void glut_keyboard(unsigned char key, int x, int y) { | @@ -888,7 +895,7 @@ void glut_keyboard(unsigned char key, int x, int y) { | ||
888 | 895 | ||
889 | // register different keyboard operation | 896 | // register different keyboard operation |
890 | switch (key) { | 897 | switch (key) { |
891 | - | 898 | + |
892 | // saving network flow profile | 899 | // saving network flow profile |
893 | case 's': | 900 | case 's': |
894 | flow.save_network(); | 901 | flow.save_network(); |
@@ -903,7 +910,39 @@ void glut_keyboard(unsigned char key, int x, int y) { | @@ -903,7 +910,39 @@ void glut_keyboard(unsigned char key, int x, int y) { | ||
903 | flow.saveNwt(filename); | 910 | flow.saveNwt(filename); |
904 | break; | 911 | break; |
905 | } | 912 | } |
906 | - | 913 | + |
914 | + // subdivide current network for more detailed calculation | ||
915 | + case 'd': { | ||
916 | + // subdivide current network due to the limitation of current computation if needed | ||
917 | + if (!subdivided && simulation && !glyph_mode) { | ||
918 | + subdivided = true; | ||
919 | + | ||
920 | + // check whether current network can be subdivided | ||
921 | + if (flow.check_subdivision()) { | ||
922 | + flow.subdivision(); | ||
923 | + get_background(); | ||
924 | + } | ||
925 | + | ||
926 | + flow_initialize(); // initialize flow condition | ||
927 | + // resimulation | ||
928 | + flow_stable_state(); // main function of solving the linear system | ||
929 | + flow.print_flow(); | ||
930 | + undo = true; | ||
931 | + } | ||
932 | + else if (subdivided && simulation && !glyph_mode) { | ||
933 | + subdivided = false; | ||
934 | + flow = backup; // load back up | ||
935 | + | ||
936 | + get_background(); | ||
937 | + flow_initialize(); | ||
938 | + // resimulation | ||
939 | + flow_stable_state(); // main function of solving the linear system | ||
940 | + flow.print_flow(); | ||
941 | + undo = true; | ||
942 | + } | ||
943 | + break; | ||
944 | + } | ||
945 | + | ||
907 | // flow vector field visualization, Glyphs | 946 | // flow vector field visualization, Glyphs |
908 | case 'f': | 947 | case 'f': |
909 | if (glyph_mode && !manufacture && (simulation || build_inlet_outlet)) { | 948 | if (glyph_mode && !manufacture && (simulation || build_inlet_outlet)) { |
@@ -923,7 +962,7 @@ void glut_keyboard(unsigned char key, int x, int y) { | @@ -923,7 +962,7 @@ void glut_keyboard(unsigned char key, int x, int y) { | ||
923 | } | 962 | } |
924 | undo = true; | 963 | undo = true; |
925 | break; | 964 | break; |
926 | - | 965 | + |
927 | // filaments around arrows | 966 | // filaments around arrows |
928 | case 'g': | 967 | case 'g': |
929 | if (glyph_mode) { | 968 | if (glyph_mode) { |
@@ -932,8 +971,9 @@ void glut_keyboard(unsigned char key, int x, int y) { | @@ -932,8 +971,9 @@ void glut_keyboard(unsigned char key, int x, int y) { | ||
932 | else | 971 | else |
933 | frame_mode = true; | 972 | frame_mode = true; |
934 | } | 973 | } |
974 | + undo = true; | ||
935 | break; | 975 | break; |
936 | - | 976 | + |
937 | // open/close index marks | 977 | // open/close index marks |
938 | case 'e': | 978 | case 'e': |
939 | if (mark_index) | 979 | if (mark_index) |
@@ -1047,12 +1087,18 @@ int main(int argc, char* argv[]) { | @@ -1047,12 +1087,18 @@ int main(int argc, char* argv[]) { | ||
1047 | } | 1087 | } |
1048 | else { // load network from user | 1088 | else { // load network from user |
1049 | std::vector<std::string> tmp = stim::parser::split(args.arg(0), '.'); | 1089 | std::vector<std::string> tmp = stim::parser::split(args.arg(0), '.'); |
1050 | - if ("obj" == tmp[1]) | 1090 | + if ("obj" == tmp[1]) { |
1051 | flow.load_obj(args.arg(0)); | 1091 | flow.load_obj(args.arg(0)); |
1052 | - else if ("nwt" == tmp[1]) // stim network binary format | ||
1053 | - flow.loadNwt(args.arg(0)); | ||
1054 | - else if ("swc" == tmp[1]) | ||
1055 | - flow.load_swc(args.arg(0)); | 1092 | + backup.load_obj(args.arg(0)); |
1093 | + } | ||
1094 | + else if ("nwt" == tmp[1]) { // stim network binary format | ||
1095 | + flow.loadNwt(args.arg(0)); | ||
1096 | + backup.loadNwt(args.arg(0)); | ||
1097 | + } | ||
1098 | + else if ("swc" == tmp[1]) { | ||
1099 | + flow.load_swc(args.arg(0)); | ||
1100 | + backup.load_swc(args.arg(0)); | ||
1101 | + } | ||
1056 | else { | 1102 | else { |
1057 | std::cout << "Invalid file type" << std::endl; | 1103 | std::cout << "Invalid file type" << std::endl; |
1058 | std::exit(1); | 1104 | std::exit(1); |