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 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
... ...
... ... @@ -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
... ...