Commit 0224d2ef24298c824520c87e21a96cb28a8c14d2
1 parent
057ea93b
fixed square wave connection bugs : degenerate case. Added new features for vect…
…or field visualization
Showing
2 changed files
with
214 additions
and
39 deletions
Show diff stats
... | ... | @@ -1013,7 +1013,7 @@ namespace stim { |
1013 | 1013 | } |
1014 | 1014 | |
1015 | 1015 | // draw main feeder as solid cube |
1016 | - void glSolidCuboid(bool manufacture = false, T length = 40.0f, T height = 10.0f) { | |
1016 | + void glSolidCuboid(bool arrow, GLint subdivision, bool manufacture = false, T length = 40.0f, T height = 10.0f) { | |
1017 | 1017 | |
1018 | 1018 | T width; |
1019 | 1019 | stim::vec3<T> L = bb.A; // get the bottom left corner |
... | ... | @@ -1073,6 +1073,46 @@ namespace stim { |
1073 | 1073 | glVertex3f(main_feeder[i][0] + length / 2, main_feeder[i][1] - height / 2, main_feeder[i][2] + width / 2); |
1074 | 1074 | glEnd(); |
1075 | 1075 | } |
1076 | + | |
1077 | + // render total flow direction | |
1078 | + if (arrow) { | |
1079 | + stim::vec3<T> d = main_feeder[1] - main_feeder[0]; | |
1080 | + d = d.norm(); | |
1081 | + stim::vec3<T> v1, v2, v3; | |
1082 | + stim::vec3<T> center = bb.center(); | |
1083 | + stim::vec3<T> size = bb.size(); | |
1084 | + stim::circle<float> tmp_c; | |
1085 | + tmp_c.rotate(d); | |
1086 | + std::vector<typename stim::vec3<float> > cp1(subdivision + 1); | |
1087 | + std::vector<typename stim::vec3<float> > cp2(subdivision + 1); | |
1088 | + v2 = center - stim::vec3<T>(0.0f, size[1] + 10.0f, 0.0f); | |
1089 | + v1 = v2 - stim::vec3<T>(30.0f, 0.0f, 0.0f); | |
1090 | + v3 = v2 + stim::vec3<T>(30.0f, 0.0f, 0.0f); | |
1091 | + v2 = v2 + stim::vec3<T>(20.0f, 0.0f, 0.0f); | |
1092 | + | |
1093 | + // draw the total flow direciton indicating arrow | |
1094 | + stim::circle<T> c1(v1, 5.0f / 2, d, tmp_c.U); | |
1095 | + cp1 = c1.glpoints(subdivision); | |
1096 | + stim::circle<T> c2(v2, 5.0f / 2, d, tmp_c.U); | |
1097 | + cp2 = c2.glpoints(subdivision); | |
1098 | + | |
1099 | + glColor3f(0.0f, 1.0f, 0.0f); | |
1100 | + glBegin(GL_QUAD_STRIP); | |
1101 | + for (unsigned k = 0; k < cp1.size(); k++) { | |
1102 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | |
1103 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1104 | + } | |
1105 | + glEnd(); | |
1106 | + | |
1107 | + // render the cone part | |
1108 | + stim::circle<T> c3(v2, 5.0f, d, tmp_c.U); | |
1109 | + cp2 = c3.glpoints(subdivision); | |
1110 | + glBegin(GL_TRIANGLE_FAN); | |
1111 | + glVertex3f(v3[0], v3[1], v3[2]); | |
1112 | + for (unsigned k = 0; k < cp2.size(); k++) | |
1113 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1114 | + glEnd(); | |
1115 | + } | |
1076 | 1116 | glFlush(); |
1077 | 1117 | } |
1078 | 1118 | |
... | ... | @@ -1163,8 +1203,8 @@ namespace stim { |
1163 | 1203 | glPopMatrix(); |
1164 | 1204 | } |
1165 | 1205 | |
1166 | - // draw the bridge as lines | |
1167 | - void line_bridge(bool &redisplay) { | |
1206 | + // draw the bridge as lines or arrows | |
1207 | + void line_bridge(bool &redisplay, bool arrow, T r = 4.0f) { | |
1168 | 1208 | |
1169 | 1209 | if (redisplay) |
1170 | 1210 | glDeleteLists(dlist, 1); |
... | ... | @@ -1173,28 +1213,152 @@ namespace stim { |
1173 | 1213 | if (!glIsList(dlist)) { |
1174 | 1214 | dlist = glGenLists(1); |
1175 | 1215 | glNewList(dlist, GL_COMPILE); |
1176 | - | |
1177 | - glLineWidth(5); | |
1178 | - for (unsigned i = 0; i < inlet.size(); i++) { | |
1179 | - if (inlet_feasibility[i]) | |
1180 | - glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1181 | - else | |
1182 | - glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1183 | 1216 | |
1184 | - glBegin(GL_LINE_STRIP); | |
1185 | - for (unsigned j = 0; j < inlet[i].V.size(); j++) | |
1186 | - glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | |
1187 | - glEnd(); | |
1217 | + // render flow direction arrows | |
1218 | + if (arrow) { | |
1219 | + // v1----v2-->v3 | |
1220 | + T k = 4.0f; // quartering | |
1221 | + stim::vec3<T> v1, v2, v3; // three point | |
1222 | + stim::vec3<T> d; // direction vector | |
1223 | + stim::circle<float> tmp_c; | |
1224 | + std::vector<typename stim::vec3<float> > cp1(subdivision + 1); | |
1225 | + std::vector<typename stim::vec3<float> > cp2(subdivision + 1); | |
1226 | + | |
1227 | + // inlet, right-going | |
1228 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1229 | + if (inlet_feasibility[i]) | |
1230 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1231 | + else | |
1232 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1233 | + for (unsigned j = 0; j < inlet[i].V.size() - 1; j++) { | |
1234 | + v1 = inlet[i].V[j]; | |
1235 | + v3 = inlet[i].V[j + 1]; | |
1236 | + d = v3 - v1; | |
1237 | + // place the arrow in the middel of one edge | |
1238 | + v2 = v1 + (1.0f / k * 2.0f) * d; // looks like =->= | |
1239 | + v1 = v1 + (1.0f / k) * d; | |
1240 | + v3 = v3 - (1.0f / k) * d; | |
1241 | + d = d.norm(); | |
1242 | + tmp_c.rotate(d); | |
1243 | + | |
1244 | + // render the cylinder part | |
1245 | + stim::circle<T> c1(v1, r / 2, d, tmp_c.U); | |
1246 | + cp1 = c1.glpoints(subdivision); | |
1247 | + stim::circle<T> c2(v2, r / 2, d, tmp_c.U); | |
1248 | + cp2 = c2.glpoints(subdivision); | |
1249 | + | |
1250 | + glBegin(GL_QUAD_STRIP); | |
1251 | + for (unsigned k = 0; k < cp1.size(); k++) { | |
1252 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | |
1253 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1254 | + } | |
1255 | + glEnd(); | |
1256 | + | |
1257 | + // render the cone part | |
1258 | + stim::circle<T> c3(v2, r, d, tmp_c.U); | |
1259 | + cp2 = c3.glpoints(subdivision); | |
1260 | + glBegin(GL_TRIANGLE_FAN); | |
1261 | + glVertex3f(v3[0], v3[1], v3[2]); | |
1262 | + for (unsigned k = 0; k < cp2.size(); k++) | |
1263 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1264 | + glEnd(); | |
1265 | + } | |
1266 | + } | |
1267 | + | |
1268 | + // outlet, right-going | |
1269 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1270 | + if (outlet_feasibility[i]) | |
1271 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1272 | + else | |
1273 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1274 | + for (unsigned j = 0; j < outlet[i].V.size() - 1; j++) { | |
1275 | + v1 = outlet[i].V[j + 1]; | |
1276 | + v3 = outlet[i].V[j]; | |
1277 | + d = v3 - v1; | |
1278 | + // place the arrow in the middel of one edge | |
1279 | + v2 = v1 + (1.0f / k * 2.0f) * d; // looks like =->= | |
1280 | + v1 = v1 + (1.0f / k) * d; | |
1281 | + v3 = v3 - (1.0f / k) * d; | |
1282 | + d = d.norm(); | |
1283 | + tmp_c.rotate(d); | |
1284 | + | |
1285 | + // render the cylinder part | |
1286 | + stim::circle<T> c1(v1, r / 2, d, tmp_c.U); | |
1287 | + cp1 = c1.glpoints(subdivision); | |
1288 | + stim::circle<T> c2(v2, r / 2, d, tmp_c.U); | |
1289 | + cp2 = c2.glpoints(subdivision); | |
1290 | + | |
1291 | + glBegin(GL_QUAD_STRIP); | |
1292 | + for (unsigned k = 0; k < cp1.size(); k++) { | |
1293 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | |
1294 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1295 | + } | |
1296 | + glEnd(); | |
1297 | + | |
1298 | + // render the cone part | |
1299 | + stim::circle<T> c3(v2, r, d, tmp_c.U); | |
1300 | + cp2 = c3.glpoints(subdivision); | |
1301 | + glBegin(GL_TRIANGLE_FAN); | |
1302 | + glVertex3f(v3[0], v3[1], v3[2]); | |
1303 | + for (unsigned k = 0; k < cp2.size(); k++) | |
1304 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | |
1305 | + glEnd(); | |
1306 | + } | |
1307 | + } | |
1308 | + | |
1309 | + // render transparent lines as indexing | |
1310 | + glEnable(GL_BLEND); // enable color blend | |
1311 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set blend function | |
1312 | + glDisable(GL_DEPTH_TEST); | |
1313 | + glLineWidth(5); | |
1314 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1315 | + if (inlet_feasibility[i]) | |
1316 | + glColor4f(0.0f, 0.0f, 0.0f, 0.2f); // feasible -> black | |
1317 | + else | |
1318 | + glColor4f(1.0f, 0.0f, 0.0f, 0.2f); // nonfeasible -> red | |
1319 | + | |
1320 | + glBegin(GL_LINE_STRIP); | |
1321 | + for (unsigned j = 0; j < inlet[i].V.size(); j++) | |
1322 | + glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | |
1323 | + glEnd(); | |
1324 | + } | |
1325 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1326 | + if (outlet_feasibility[i]) | |
1327 | + glColor4f(0.0f, 0.0f, 0.0f, 0.2f); // feasible -> black | |
1328 | + else | |
1329 | + glColor4f(1.0f, 0.0f, 0.0f, 0.2f); // nonfeasible -> red | |
1330 | + glBegin(GL_LINE_STRIP); | |
1331 | + for (unsigned j = 0; j < outlet[i].V.size(); j++) | |
1332 | + glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | |
1333 | + glEnd(); | |
1334 | + } | |
1335 | + glDisable(GL_BLEND); | |
1336 | + glEnable(GL_DEPTH_TEST); | |
1188 | 1337 | } |
1189 | - for (unsigned i = 0; i < outlet.size(); i++) { | |
1190 | - if (outlet_feasibility[i]) | |
1191 | - glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1192 | - else | |
1193 | - glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1194 | - glBegin(GL_LINE_STRIP); | |
1195 | - for (unsigned j = 0; j < outlet[i].V.size(); j++) | |
1196 | - glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | |
1197 | - glEnd(); | |
1338 | + // render connection lines | |
1339 | + else { | |
1340 | + glLineWidth(5); | |
1341 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1342 | + if (inlet_feasibility[i]) | |
1343 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1344 | + else | |
1345 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1346 | + | |
1347 | + glBegin(GL_LINE_STRIP); | |
1348 | + for (unsigned j = 0; j < inlet[i].V.size(); j++) | |
1349 | + glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | |
1350 | + glEnd(); | |
1351 | + } | |
1352 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1353 | + if (outlet_feasibility[i]) | |
1354 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1355 | + else | |
1356 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1357 | + glBegin(GL_LINE_STRIP); | |
1358 | + for (unsigned j = 0; j < outlet[i].V.size(); j++) | |
1359 | + glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | |
1360 | + glEnd(); | |
1361 | + } | |
1198 | 1362 | } |
1199 | 1363 | glFlush(); |
1200 | 1364 | glEndList(); |
... | ... | @@ -1617,10 +1781,10 @@ namespace stim { |
1617 | 1781 | |
1618 | 1782 | // find the number of U-shape or square-shape structure for extending length of connection |
1619 | 1783 | // @param t: width = t * radius |
1620 | - int find_number_square(T origin_l, T desire_l, T radius = 5.0f, int times = 4) { | |
1784 | + int find_number_square(T origin_l, T desire_l, T radius = 5.0f, int times = 10) { | |
1621 | 1785 | |
1622 | 1786 | bool done = false; // flag indicates the current number of square shape structure is feasible |
1623 | - int n = origin_l / (times * 4 * radius);// number of square shape structure | |
1787 | + int n = origin_l / (times * 4 * radius); // number of square shape structure | |
1624 | 1788 | T need_l = desire_l - origin_l; |
1625 | 1789 | T height; // height of the square shapce structure |
1626 | 1790 | |
... | ... | @@ -1638,7 +1802,7 @@ namespace stim { |
1638 | 1802 | } |
1639 | 1803 | |
1640 | 1804 | // build square connections |
1641 | - void build_square_connection(int i, T width, T height, T origin_l, T desire_l, int n, int feeder, T threshold, bool z, bool left = true, bool up = true, int times = 4, T ratio = 0, T radius = 5.0f) { | |
1805 | + void build_square_connection(int i, T width, T height, T origin_l, T desire_l, int n, int feeder, T threshold, bool z, bool left = true, bool up = true, int times = 10, T ratio = 0, T radius = 5.0f) { | |
1642 | 1806 | |
1643 | 1807 | int coef_up = (up) ? 1 : -1; // y coefficient |
1644 | 1808 | int coef_left = (left) ? 1 : -1; // x coefficient |
... | ... | @@ -1669,8 +1833,8 @@ namespace stim { |
1669 | 1833 | |
1670 | 1834 | // there are cases that the fragment can not satisfy the requirement for width |
1671 | 1835 | if (width < times * radius || n == 0) { // check feasibility |
1672 | - ratio = 0.0f; // load | |
1673 | - desire_l = tmp_d; | |
1836 | + ratio = 0.0f; // load original lengths | |
1837 | + desire_l = tmp_d; | |
1674 | 1838 | origin_l = tmp_l; |
1675 | 1839 | |
1676 | 1840 | std::cout << "Warning: current ratio is not feasible, use full original line." << std::endl; |
... | ... | @@ -2134,7 +2298,7 @@ namespace stim { |
2134 | 2298 | width = (T)origin_l / (2 * n); |
2135 | 2299 | height = (desire_l - origin_l) / (2 * n); |
2136 | 2300 | |
2137 | - build_square_connection(i, width, height, origin_l, desire_l, n, 1, threshold, z, true, upper, 5, ratio); | |
2301 | + build_square_connection(i, width, height, origin_l, desire_l, n, 1, threshold, z, true, upper, 2, ratio); | |
2138 | 2302 | inlet[i].V.push_back(bus_v); |
2139 | 2303 | |
2140 | 2304 | std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex |
... | ... | @@ -2183,7 +2347,7 @@ namespace stim { |
2183 | 2347 | width = (T)origin_l / (2 * n); |
2184 | 2348 | height = (desire_l - origin_l) / (2 * n); |
2185 | 2349 | |
2186 | - build_square_connection(i, width, height, origin_l, desire_l, n, 0, threshold, z, false, upper, 5, ratio); | |
2350 | + build_square_connection(i, width, height, origin_l, desire_l, n, 0, threshold, z, false, upper, 2, ratio); | |
2187 | 2351 | outlet[i].V.push_back(bus_v); |
2188 | 2352 | |
2189 | 2353 | std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex | ... | ... |
main.cu
... | ... | @@ -268,17 +268,16 @@ void glut_render() { |
268 | 268 | else |
269 | 269 | flow.glyph(color, subdivision); |
270 | 270 | |
271 | - flow.glSolidCuboid(manufacture, length); | |
271 | + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length); | |
272 | 272 | if (render_direction) |
273 | 273 | flow.glSolidCone(direction_index, scale, subdivision); |
274 | 274 | } |
275 | 275 | |
276 | - if (build_inlet_outlet) { | |
277 | - flow.line_bridge(redisplay); | |
278 | - } | |
279 | - | |
276 | + if (build_inlet_outlet) | |
277 | + flow.line_bridge(redisplay, flow_direction); | |
278 | + | |
280 | 279 | if (manufacture) { |
281 | - flow.glSolidCuboid(manufacture, length); | |
280 | + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length); | |
282 | 281 | flow.tube_bridge(subdivision); |
283 | 282 | } |
284 | 283 | |
... | ... | @@ -470,7 +469,8 @@ void glut_menu(int value) { |
470 | 469 | flow_stable_state(); // main function of solving the linear system |
471 | 470 | flow.print_flow(); |
472 | 471 | |
473 | - glut_set_menu(num, 2); | |
472 | + if (!flow_direction) | |
473 | + glut_set_menu(num, 2); | |
474 | 474 | } |
475 | 475 | |
476 | 476 | if (value == 2) { |
... | ... | @@ -496,6 +496,7 @@ void glut_menu(int value) { |
496 | 496 | simulation = false; |
497 | 497 | build_inlet_outlet = false; |
498 | 498 | manufacture = true; |
499 | + flow_direction = false; // manufacuture mode doesn't need flow direction | |
499 | 500 | } |
500 | 501 | |
501 | 502 | if (value == 4) { |
... | ... | @@ -855,10 +856,20 @@ void glut_keyboard(unsigned char key, int x, int y) { |
855 | 856 | |
856 | 857 | // flow vector field visualization, Glyphs |
857 | 858 | case 'f': |
858 | - if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) | |
859 | + if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) { | |
859 | 860 | flow_direction = false; |
860 | - else if(!flow_direction && !manufacture && (simulation || build_inlet_outlet)) | |
861 | + redisplay = true; // lines and arrows rendering use the same display list | |
862 | + int num = glutGet(GLUT_MENU_NUM_ITEMS); | |
863 | + if (num == 1) | |
864 | + glut_set_menu(num, 2); | |
865 | + } | |
866 | + else if (!flow_direction && !manufacture && (simulation || build_inlet_outlet)) { | |
861 | 867 | flow_direction = true; |
868 | + redisplay = true; | |
869 | + int num = glutGet(GLUT_MENU_NUM_ITEMS); | |
870 | + if (num == 2) | |
871 | + glut_set_menu(num, 1); | |
872 | + } | |
862 | 873 | break; |
863 | 874 | |
864 | 875 | // open/close index marks | ... | ... |