Commit 0224d2ef24298c824520c87e21a96cb28a8c14d2

Authored by Jiaming Guo
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,7 +1013,7 @@ namespace stim {
1013 } 1013 }
1014 1014
1015 // draw main feeder as solid cube 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 T width; 1018 T width;
1019 stim::vec3<T> L = bb.A; // get the bottom left corner 1019 stim::vec3<T> L = bb.A; // get the bottom left corner
@@ -1073,6 +1073,46 @@ namespace stim { @@ -1073,6 +1073,46 @@ namespace stim {
1073 glVertex3f(main_feeder[i][0] + length / 2, main_feeder[i][1] - height / 2, main_feeder[i][2] + width / 2); 1073 glVertex3f(main_feeder[i][0] + length / 2, main_feeder[i][1] - height / 2, main_feeder[i][2] + width / 2);
1074 glEnd(); 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 glFlush(); 1116 glFlush();
1077 } 1117 }
1078 1118
@@ -1163,8 +1203,8 @@ namespace stim { @@ -1163,8 +1203,8 @@ namespace stim {
1163 glPopMatrix(); 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 if (redisplay) 1209 if (redisplay)
1170 glDeleteLists(dlist, 1); 1210 glDeleteLists(dlist, 1);
@@ -1173,28 +1213,152 @@ namespace stim { @@ -1173,28 +1213,152 @@ namespace stim {
1173 if (!glIsList(dlist)) { 1213 if (!glIsList(dlist)) {
1174 dlist = glGenLists(1); 1214 dlist = glGenLists(1);
1175 glNewList(dlist, GL_COMPILE); 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 glFlush(); 1363 glFlush();
1200 glEndList(); 1364 glEndList();
@@ -1617,10 +1781,10 @@ namespace stim { @@ -1617,10 +1781,10 @@ namespace stim {
1617 1781
1618 // find the number of U-shape or square-shape structure for extending length of connection 1782 // find the number of U-shape or square-shape structure for extending length of connection
1619 // @param t: width = t * radius 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 bool done = false; // flag indicates the current number of square shape structure is feasible 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 T need_l = desire_l - origin_l; 1788 T need_l = desire_l - origin_l;
1625 T height; // height of the square shapce structure 1789 T height; // height of the square shapce structure
1626 1790
@@ -1638,7 +1802,7 @@ namespace stim { @@ -1638,7 +1802,7 @@ namespace stim {
1638 } 1802 }
1639 1803
1640 // build square connections 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 int coef_up = (up) ? 1 : -1; // y coefficient 1807 int coef_up = (up) ? 1 : -1; // y coefficient
1644 int coef_left = (left) ? 1 : -1; // x coefficient 1808 int coef_left = (left) ? 1 : -1; // x coefficient
@@ -1669,8 +1833,8 @@ namespace stim { @@ -1669,8 +1833,8 @@ namespace stim {
1669 1833
1670 // there are cases that the fragment can not satisfy the requirement for width 1834 // there are cases that the fragment can not satisfy the requirement for width
1671 if (width < times * radius || n == 0) { // check feasibility 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 origin_l = tmp_l; 1838 origin_l = tmp_l;
1675 1839
1676 std::cout << "Warning: current ratio is not feasible, use full original line." << std::endl; 1840 std::cout << "Warning: current ratio is not feasible, use full original line." << std::endl;
@@ -2134,7 +2298,7 @@ namespace stim { @@ -2134,7 +2298,7 @@ namespace stim {
2134 width = (T)origin_l / (2 * n); 2298 width = (T)origin_l / (2 * n);
2135 height = (desire_l - origin_l) / (2 * n); 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 inlet[i].V.push_back(bus_v); 2302 inlet[i].V.push_back(bus_v);
2139 2303
2140 std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex 2304 std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex
@@ -2183,7 +2347,7 @@ namespace stim { @@ -2183,7 +2347,7 @@ namespace stim {
2183 width = (T)origin_l / (2 * n); 2347 width = (T)origin_l / (2 * n);
2184 height = (desire_l - origin_l) / (2 * n); 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 outlet[i].V.push_back(bus_v); 2351 outlet[i].V.push_back(bus_v);
2188 2352
2189 std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex 2353 std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex
@@ -268,17 +268,16 @@ void glut_render() { @@ -268,17 +268,16 @@ void glut_render() {
268 else 268 else
269 flow.glyph(color, subdivision); 269 flow.glyph(color, subdivision);
270 270
271 - flow.glSolidCuboid(manufacture, length); 271 + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length);
272 if (render_direction) 272 if (render_direction)
273 flow.glSolidCone(direction_index, scale, subdivision); 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 if (manufacture) { 279 if (manufacture) {
281 - flow.glSolidCuboid(manufacture, length); 280 + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length);
282 flow.tube_bridge(subdivision); 281 flow.tube_bridge(subdivision);
283 } 282 }
284 283
@@ -470,7 +469,8 @@ void glut_menu(int value) { @@ -470,7 +469,8 @@ void glut_menu(int value) {
470 flow_stable_state(); // main function of solving the linear system 469 flow_stable_state(); // main function of solving the linear system
471 flow.print_flow(); 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 if (value == 2) { 476 if (value == 2) {
@@ -496,6 +496,7 @@ void glut_menu(int value) { @@ -496,6 +496,7 @@ void glut_menu(int value) {
496 simulation = false; 496 simulation = false;
497 build_inlet_outlet = false; 497 build_inlet_outlet = false;
498 manufacture = true; 498 manufacture = true;
  499 + flow_direction = false; // manufacuture mode doesn't need flow direction
499 } 500 }
500 501
501 if (value == 4) { 502 if (value == 4) {
@@ -855,10 +856,20 @@ void glut_keyboard(unsigned char key, int x, int y) { @@ -855,10 +856,20 @@ void glut_keyboard(unsigned char key, int x, int y) {
855 856
856 // flow vector field visualization, Glyphs 857 // flow vector field visualization, Glyphs
857 case 'f': 858 case 'f':
858 - if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) 859 + if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) {
859 flow_direction = false; 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 flow_direction = true; 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 break; 873 break;
863 874
864 // open/close index marks 875 // open/close index marks