Commit f4105b89553b247a70fe04555ee2a41a792899a8
1 parent
9e60c6a7
add new function: smooth colormap, manually change direct connection...etc
Showing
2 changed files
with
573 additions
and
46 deletions
Show diff stats
... | ... | @@ -238,6 +238,8 @@ namespace stim { |
238 | 238 | std::vector<typename stim::triple<unsigned, unsigned, float> > Q; // volume flow rate |
239 | 239 | std::vector<T> QQ; // Q' vector |
240 | 240 | std::vector<T> pressure; // final pressure |
241 | + std::vector<typename std::vector<typename stim::vec3<T> > > in_backup; // inlet connection back up | |
242 | + std::vector<typename std::vector<typename stim::vec3<T> > > out_backup; | |
241 | 243 | |
242 | 244 | public: |
243 | 245 | |
... | ... | @@ -254,6 +256,10 @@ namespace stim { |
254 | 256 | std::vector<typename stim::cone<T> > B; // cone(cylinder) model for making image stack |
255 | 257 | std::vector<typename stim::cuboid<T> > CU; // cuboid model for making image stack |
256 | 258 | stim::gl_aaboundingbox<T> bb; // bounding box |
259 | + std::vector<bool> inlet_feasibility; // list of flags indicate whether one inlet connection is feasible | |
260 | + std::vector<bool> outlet_feasibility; | |
261 | + std::vector<typename std::pair<stim::vec3<T>, stim::vec3<T> > > inbb; // inlet connection bounding box | |
262 | + std::vector<typename std::pair<stim::vec3<T>, stim::vec3<T> > > outbb; // outlet connection bounding box | |
257 | 263 | |
258 | 264 | flow() {} // default constructor |
259 | 265 | ~flow() { |
... | ... | @@ -804,8 +810,8 @@ namespace stim { |
804 | 810 | std::vector<typename stim::vec3<float> > cp2(subdivision + 1); |
805 | 811 | for (unsigned i = 0; i < num_edge; i++) { // for every edge |
806 | 812 | if (i == index) { // render in tranparency for direction indication |
807 | - glEnable(GL_BLEND); // enable color blend | |
808 | - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set blend function | |
813 | + glEnable(GL_BLEND); // enable color blend | |
814 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set blend function | |
809 | 815 | glDisable(GL_DEPTH_TEST); |
810 | 816 | glColor4f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255, 0.5f); |
811 | 817 | } |
... | ... | @@ -1052,19 +1058,33 @@ namespace stim { |
1052 | 1058 | } |
1053 | 1059 | |
1054 | 1060 | // draw the bridge as lines |
1055 | - void line_bridge() { | |
1061 | + void line_bridge(bool &redisplay) { | |
1062 | + | |
1063 | + if (redisplay) | |
1064 | + glDeleteLists(dlist, 1); | |
1065 | + redisplay = false; | |
1056 | 1066 | |
1057 | 1067 | if (!glIsList(dlist)) { |
1058 | 1068 | dlist = glGenLists(1); |
1059 | 1069 | glNewList(dlist, GL_COMPILE); |
1060 | - glColor3f(0.0f, 0.0f, 0.0f); | |
1070 | + | |
1071 | + glLineWidth(50); | |
1061 | 1072 | for (unsigned i = 0; i < inlet.size(); i++) { |
1073 | + if (inlet_feasibility[i]) | |
1074 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1075 | + else | |
1076 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1077 | + | |
1062 | 1078 | glBegin(GL_LINE_STRIP); |
1063 | 1079 | for (unsigned j = 0; j < inlet[i].V.size(); j++) |
1064 | 1080 | glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); |
1065 | 1081 | glEnd(); |
1066 | 1082 | } |
1067 | 1083 | for (unsigned i = 0; i < outlet.size(); i++) { |
1084 | + if (outlet_feasibility[i]) | |
1085 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | |
1086 | + else | |
1087 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | |
1068 | 1088 | glBegin(GL_LINE_STRIP); |
1069 | 1089 | for (unsigned j = 0; j < outlet[i].V.size(); j++) |
1070 | 1090 | glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); |
... | ... | @@ -1255,6 +1275,7 @@ namespace stim { |
1255 | 1275 | bool online = false; // flag indicates the point is on the line-segment |
1256 | 1276 | float a, b; |
1257 | 1277 | |
1278 | + // inner network | |
1258 | 1279 | for (unsigned i = 0; i < E.size(); i++) { |
1259 | 1280 | for (unsigned j = 0; j < E[i].size() - 1; j++) { |
1260 | 1281 | v1 = E[i][j + 1] - E[i][j]; // a -> b = ab |
... | ... | @@ -1284,6 +1305,60 @@ namespace stim { |
1284 | 1305 | } |
1285 | 1306 | } |
1286 | 1307 | |
1308 | + // inlet connection | |
1309 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1310 | + v1 = inlet[i].V[2] - inlet[i].V[1]; | |
1311 | + v2 = v0 - inlet[i].V[1]; | |
1312 | + v3 = v0 - inlet[i].V[2]; | |
1313 | + | |
1314 | + tmp_d = v2.dot(v1); // av·ab | |
1315 | + | |
1316 | + // check the line relative position | |
1317 | + a = v2.dot(v1.norm()); | |
1318 | + b = v3.dot(v1.norm()); | |
1319 | + if (a < v1.len() && b < v1.len()) // if the length of projection fragment is longer than the line-segment | |
1320 | + online = true; | |
1321 | + else | |
1322 | + online = false; | |
1323 | + | |
1324 | + if (tmp_d <= 0.0 || tmp_d > std::pow(v1.len(), 2) && !online) // projection lies outside the line-segment | |
1325 | + continue; | |
1326 | + else { | |
1327 | + tmp_d = v1.cross(v2).len() / v1.len(); // perpendicular distance of point to segment: |v1 x v2| / |v1| | |
1328 | + if (tmp_d < d) { | |
1329 | + d = tmp_d; | |
1330 | + tmp_i = i; | |
1331 | + } | |
1332 | + } | |
1333 | + } | |
1334 | + | |
1335 | + // outlet connection | |
1336 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1337 | + v1 = outlet[i].V[2] - outlet[i].V[1]; | |
1338 | + v2 = v0 - outlet[i].V[1]; | |
1339 | + v3 = v0 - outlet[i].V[2]; | |
1340 | + | |
1341 | + tmp_d = v2.dot(v1); // av·ab | |
1342 | + | |
1343 | + // check the line relative position | |
1344 | + a = v2.dot(v1.norm()); | |
1345 | + b = v3.dot(v1.norm()); | |
1346 | + if (a < v1.len() && b < v1.len()) // if the length of projection fragment is longer than the line-segment | |
1347 | + online = true; | |
1348 | + else | |
1349 | + online = false; | |
1350 | + | |
1351 | + if (tmp_d <= 0.0 || tmp_d > std::pow(v1.len(), 2) && !online) // projection lies outside the line-segment | |
1352 | + continue; | |
1353 | + else { | |
1354 | + tmp_d = v1.cross(v2).len() / v1.len(); // perpendicular distance of point to segment: |v1 x v2| / |v1| | |
1355 | + if (tmp_d < d) { | |
1356 | + d = tmp_d; | |
1357 | + tmp_i = i; | |
1358 | + } | |
1359 | + } | |
1360 | + } | |
1361 | + | |
1287 | 1362 | eps += get_radius(tmp_i, tmp_j); |
1288 | 1363 | |
1289 | 1364 | if (d < eps) { |
... | ... | @@ -1293,6 +1368,86 @@ namespace stim { |
1293 | 1368 | |
1294 | 1369 | return false; |
1295 | 1370 | } |
1371 | + inline bool epsilon_edge(T x, T y, T z, T eps, unsigned &idx, unsigned &port) { | |
1372 | + | |
1373 | + T d = FLT_MAX; | |
1374 | + T tmp_d; | |
1375 | + unsigned tmp_i = 0; | |
1376 | + stim::vec3<T> v1; | |
1377 | + stim::vec3<T> v2; | |
1378 | + stim::vec3<T> v3; | |
1379 | + stim::vec3<T> v0 = stim::vec3<float>(x, y, z); | |
1380 | + bool online = false; // flag indicates the point is on the line-segment | |
1381 | + float a, b; | |
1382 | + | |
1383 | + // inlet connection | |
1384 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1385 | + for (unsigned j = 0; j < inlet[i].V.size() - 1; j++) { | |
1386 | + v1 = inlet[i].V[j + 1] - inlet[i].V[j]; | |
1387 | + v2 = v0 - inlet[i].V[j]; | |
1388 | + v3 = v0 - inlet[i].V[j + 1]; | |
1389 | + | |
1390 | + tmp_d = v2.dot(v1); // av·ab | |
1391 | + | |
1392 | + // check the line relative position | |
1393 | + a = v2.dot(v1.norm()); | |
1394 | + b = v3.dot(v1.norm()); | |
1395 | + if (a < v1.len() && b < v1.len()) // if the length of projection fragment is longer than the line-segment | |
1396 | + online = true; | |
1397 | + else | |
1398 | + online = false; | |
1399 | + | |
1400 | + if (tmp_d <= 0.0 || tmp_d > std::pow(v1.len(), 2) && !online) // projection lies outside the line-segment | |
1401 | + continue; | |
1402 | + else { | |
1403 | + tmp_d = v1.cross(v2).len() / v1.len(); // perpendicular distance of point to segment: |v1 x v2| / |v1| | |
1404 | + if (tmp_d < d) { | |
1405 | + d = tmp_d; | |
1406 | + tmp_i = i; | |
1407 | + port = 0; | |
1408 | + } | |
1409 | + } | |
1410 | + | |
1411 | + } | |
1412 | + } | |
1413 | + | |
1414 | + // outlet connection | |
1415 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1416 | + for (unsigned j = 0; j < outlet[i].V.size() - 1; j++) { | |
1417 | + v1 = outlet[i].V[j + 1] - outlet[i].V[j]; | |
1418 | + v2 = v0 - outlet[i].V[j]; | |
1419 | + v3 = v0 - outlet[i].V[j + 1]; | |
1420 | + | |
1421 | + tmp_d = v2.dot(v1); // av·ab | |
1422 | + | |
1423 | + // check the line relative position | |
1424 | + a = v2.dot(v1.norm()); | |
1425 | + b = v3.dot(v1.norm()); | |
1426 | + if (a < v1.len() && b < v1.len()) // if the length of projection fragment is longer than the line-segment | |
1427 | + online = true; | |
1428 | + else | |
1429 | + online = false; | |
1430 | + | |
1431 | + if (tmp_d <= 0.0 || tmp_d > std::pow(v1.len(), 2) && !online) // projection lies outside the line-segment | |
1432 | + continue; | |
1433 | + else { | |
1434 | + tmp_d = v1.cross(v2).len() / v1.len(); // perpendicular distance of point to segment: |v1 x v2| / |v1| | |
1435 | + if (tmp_d < d) { | |
1436 | + d = tmp_d; | |
1437 | + tmp_i = i; | |
1438 | + port = 1; | |
1439 | + } | |
1440 | + } | |
1441 | + } | |
1442 | + } | |
1443 | + | |
1444 | + if (d < eps) { | |
1445 | + idx = tmp_i; | |
1446 | + return true; | |
1447 | + } | |
1448 | + | |
1449 | + return false; | |
1450 | + } | |
1296 | 1451 | |
1297 | 1452 | /// build main feeder connection |
1298 | 1453 | // set up main feeder and main port of both input and output |
... | ... | @@ -1404,6 +1559,8 @@ namespace stim { |
1404 | 1559 | |
1405 | 1560 | outlet.push_back(tmp_b); |
1406 | 1561 | } |
1562 | + | |
1563 | + backup(); | |
1407 | 1564 | } |
1408 | 1565 | |
1409 | 1566 | // find the number of U-shape or square-shape structure for extending length of connection |
... | ... | @@ -1436,12 +1593,13 @@ namespace stim { |
1436 | 1593 | int coef_z = (z) ? 1 : -1; // z coefficient |
1437 | 1594 | int inverse = 1; // inverse flag |
1438 | 1595 | stim::vec3<T> cor_v; // corner vertex |
1439 | - | |
1596 | + std::pair<stim::vec3<T>, stim::vec3<T>> tmp_bb; | |
1440 | 1597 | stim::vec3<T> tmp_v; |
1441 | - if (feeder == 1) | |
1598 | + if (feeder == 1) | |
1442 | 1599 | tmp_v = inlet[i].V[0]; |
1443 | - else if (feeder == 0) | |
1600 | + else if (feeder == 0) | |
1444 | 1601 | tmp_v = outlet[i].V[0]; |
1602 | + tmp_bb.first = tmp_v; | |
1445 | 1603 | |
1446 | 1604 | // check whether the height of connections is acceptable |
1447 | 1605 | if (height > threshold) { // acceptable |
... | ... | @@ -1522,6 +1680,8 @@ namespace stim { |
1522 | 1680 | inlet[i].V.push_back(tmp_v); |
1523 | 1681 | else if (feeder == 0) |
1524 | 1682 | outlet[i].V.push_back(tmp_v); |
1683 | + if (j == n - 1 && k == 0) // first time go "in" | |
1684 | + tmp_bb.second = tmp_v; | |
1525 | 1685 | |
1526 | 1686 | tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); |
1527 | 1687 | if (feeder == 1) |
... | ... | @@ -1555,7 +1715,7 @@ namespace stim { |
1555 | 1715 | inverse = 1; |
1556 | 1716 | } |
1557 | 1717 | // if use fragment to do square wave connection, need to push_back the corner vertex |
1558 | - if (ratio > 0.0f && ratio <= 1.0f) { | |
1718 | + if (ratio > 0.0f && ratio < 1.0f) { | |
1559 | 1719 | if (feeder == 1) |
1560 | 1720 | inlet[i].V.push_back(cor_v); |
1561 | 1721 | else if (feeder == 0) |
... | ... | @@ -1565,25 +1725,30 @@ namespace stim { |
1565 | 1725 | else { |
1566 | 1726 | for (int j = 0; j < n; j++) { |
1567 | 1727 | |
1568 | - // move in Z-shape | |
1728 | + // up | |
1569 | 1729 | tmp_v = tmp_v + stim::vec3<T>(0, coef_up * height, 0); |
1570 | 1730 | if (feeder == 1) |
1571 | 1731 | inlet[i].V.push_back(tmp_v); |
1572 | 1732 | else if (feeder == 0) |
1573 | 1733 | outlet[i].V.push_back(tmp_v); |
1574 | 1734 | |
1735 | + // left | |
1575 | 1736 | tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); |
1576 | 1737 | if (feeder == 1) |
1577 | 1738 | inlet[i].V.push_back(tmp_v); |
1578 | 1739 | else if (feeder == 0) |
1579 | 1740 | outlet[i].V.push_back(tmp_v); |
1741 | + if (j == n - 1) | |
1742 | + tmp_bb.second = tmp_v; | |
1580 | 1743 | |
1744 | + // down | |
1581 | 1745 | tmp_v = tmp_v + stim::vec3<T>(0, -coef_up * height, 0); |
1582 | 1746 | if (feeder == 1) |
1583 | 1747 | inlet[i].V.push_back(tmp_v); |
1584 | 1748 | else if (feeder == 0) |
1585 | 1749 | outlet[i].V.push_back(tmp_v); |
1586 | 1750 | |
1751 | + // left | |
1587 | 1752 | tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); |
1588 | 1753 | if (feeder == 1) |
1589 | 1754 | inlet[i].V.push_back(tmp_v); |
... | ... | @@ -1591,6 +1756,10 @@ namespace stim { |
1591 | 1756 | outlet[i].V.push_back(tmp_v); |
1592 | 1757 | } |
1593 | 1758 | } |
1759 | + if (feeder == 1) | |
1760 | + inbb[i] = tmp_bb; | |
1761 | + else if (feeder == 0) | |
1762 | + outbb[i] = tmp_bb; | |
1594 | 1763 | } |
1595 | 1764 | |
1596 | 1765 | // automatically modify bridge to make it feasible |
... | ... | @@ -1598,7 +1767,7 @@ namespace stim { |
1598 | 1767 | |
1599 | 1768 | glDeleteLists(dlist, 1); // delete display list for modify |
1600 | 1769 | glDeleteLists(dlist + 1, 1); |
1601 | - | |
1770 | + | |
1602 | 1771 | // because of radius change at the port vertex, there will be a pressure drop at that port |
1603 | 1772 | // it follows the bernoulli equation |
1604 | 1773 | // p1 + 1/2*rou*v1^2 + rou*g*h1 = p2 + 1/2*rou*v2^2 + rou*g*h2 |
... | ... | @@ -1815,13 +1984,15 @@ namespace stim { |
1815 | 1984 | // automatically modify inlet bridge using square shape constructions |
1816 | 1985 | else { |
1817 | 1986 | bool upper; // flag indicates the connection is upper than the bus |
1818 | - bool z; // flag indicates the connection direction along z-axis | |
1987 | + bool z; // flag indicates the connection direction along z-axis | |
1819 | 1988 | T new_l; // new length |
1820 | 1989 | stim::vec3<T> bus_v; // the port point on the bus |
1821 | 1990 | stim::vec3<T> mid_v; // the original corner point |
1822 | 1991 | stim::vec3<T> tmp_v; // the pendant point |
1823 | 1992 | int n; |
1824 | 1993 | T width, height; // width and height of the square |
1994 | + inbb.resize(inlet.size()); // resize bounding box of inlets/outlets connections | |
1995 | + outbb.resize(outlet.size()); | |
1825 | 1996 | |
1826 | 1997 | for (unsigned i = 0; i < inlet.size(); i++) { |
1827 | 1998 | if (i != inlet_index) { |
... | ... | @@ -1857,6 +2028,10 @@ namespace stim { |
1857 | 2028 | |
1858 | 2029 | std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex |
1859 | 2030 | } |
2031 | + else { | |
2032 | + inbb[i].first = inlet[i].V[2]; | |
2033 | + inbb[i].second = inlet[i].V[1]; | |
2034 | + } | |
1860 | 2035 | } |
1861 | 2036 | |
1862 | 2037 | for (unsigned i = 0; i < outlet.size(); i++) { |
... | ... | @@ -1893,35 +2068,159 @@ namespace stim { |
1893 | 2068 | |
1894 | 2069 | std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex |
1895 | 2070 | } |
2071 | + else { | |
2072 | + outbb[i].first = outlet[i].V[2]; | |
2073 | + outbb[i].second = outlet[i].V[1]; | |
2074 | + } | |
1896 | 2075 | } |
1897 | 2076 | } |
2077 | + | |
2078 | + check_special_connection(); // check special connections | |
1898 | 2079 | } |
1899 | 2080 | |
1900 | - // check current bridge to see feasibility | |
1901 | - void check_synthetic_connection(T viscosity, T radius = 5.0f) { | |
2081 | + /// check current connections to find overlapping | |
2082 | + // phase 1 check -> direct connection intersection | |
2083 | + void check_direct_connection() { | |
1902 | 2084 | |
1903 | - T eps = 0.01f; | |
1904 | - T source_pressure = pressure[inlet[0].v[0]] + (8 * viscosity * inlet[0].l * inlet[0].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1905 | - T tmp_p; | |
1906 | - for (unsigned i = 1; i < inlet.size(); i++) { | |
1907 | - tmp_p = pressure[inlet[i].v[0]] + (8 * viscosity * inlet[i].l * inlet[i].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1908 | - T delta = fabs(tmp_p - source_pressure); | |
1909 | - if (delta > eps) { | |
1910 | - std::cout << "Nonfeasible connection!" << std::endl; | |
1911 | - break; | |
2085 | + unsigned num; | |
2086 | + // check inlet | |
2087 | + num = inlet.size(); | |
2088 | + inlet_feasibility.resize(num, true); | |
2089 | + for (unsigned i = 0; i < num; i++) { | |
2090 | + for (unsigned j = 0; j < num; j++) { | |
2091 | + if (i != j) { | |
2092 | + if (inlet[i].V[0][2] == inlet[j].V[0][2]) { | |
2093 | + if ((inlet[i].V[1][0] <= inlet[j].V[1][0] && fabs(inlet[i].V[1][1]) <= fabs(inlet[j].V[1][1])) || (inlet[i].V[1][0] >= inlet[j].V[1][0] && fabs(inlet[i].V[1][1]) >= fabs(inlet[j].V[1][1]))) { | |
2094 | + inlet_feasibility[i] = false; | |
2095 | + break; | |
2096 | + } | |
2097 | + } | |
2098 | + else | |
2099 | + inlet_feasibility[i] = true; | |
2100 | + } | |
1912 | 2101 | } |
1913 | 2102 | } |
1914 | - source_pressure = pressure[outlet[0].v[0]] - (8 * viscosity * outlet[0].l * outlet[0].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1915 | - for (unsigned i = 1; i < outlet.size(); i++) { | |
1916 | - tmp_p = pressure[outlet[i].v[0]] - (8 * viscosity * outlet[i].l * outlet[i].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1917 | - T delta = fabs(tmp_p - source_pressure); | |
1918 | - if (delta > eps) { | |
1919 | - std::cout << "Nonfeasible connection!" << std::endl; | |
1920 | - break; | |
2103 | + | |
2104 | + // check outlet | |
2105 | + num = outlet.size(); | |
2106 | + outlet_feasibility.resize(num, true); | |
2107 | + for (unsigned i = 0; i < num; i++) { | |
2108 | + for (unsigned j = 0; j < num; j++) { | |
2109 | + if (i != j) { | |
2110 | + if (outlet[i].V[0][2] == outlet[j].V[0][2]) { | |
2111 | + if ((outlet[i].V[1][0] <= outlet[j].V[1][0] && fabs(outlet[i].V[1][1]) >= fabs(outlet[j].V[1][1])) || (outlet[i].V[1][0] >= outlet[j].V[1][0] && fabs(outlet[i].V[1][1]) <= fabs(outlet[j].V[1][1]))) { | |
2112 | + outlet_feasibility[i] = false; | |
2113 | + break; | |
2114 | + } | |
2115 | + } | |
2116 | + else | |
2117 | + outlet_feasibility[i] = true; | |
2118 | + } | |
2119 | + } | |
2120 | + } | |
2121 | + } | |
2122 | + | |
2123 | + // phase 2 check -> special connection intersection | |
2124 | + void check_special_connection(T radius = 5.0f) { | |
2125 | + | |
2126 | + // temp AABB centers and halfwidths | |
2127 | + stim::vec3<T> c1, c2; | |
2128 | + stim::vec3<T> r1, r2; | |
2129 | + // inlets' special connections checking | |
2130 | + for (unsigned i = 0; i < inbb.size(); i++) { | |
2131 | + for (unsigned j = 0; j < inbb.size(); j++) { | |
2132 | + if (j != i) { | |
2133 | + c1 = stim::vec3<T>((inbb[i].first + inbb[i].second) / 2); | |
2134 | + c2 = stim::vec3<T>((inbb[j].first + inbb[j].second) / 2); | |
2135 | + for (unsigned k = 0; k < 3; k++) { | |
2136 | + r1[k] = fabs(inbb[i].first[k] - inbb[i].second[k]) / 2; | |
2137 | + r2[k] = fabs(inbb[j].first[k] - inbb[j].second[k]) / 2; | |
2138 | + } | |
2139 | + // test AABBAABB | |
2140 | + if (fabs(c1[0] - c2[0]) > (r1[0] + r2[0] + 2 * radius) || fabs(c1[1] - c2[1]) > (r1[1] + r2[1] + 2 * radius) || fabs(c1[2] - c2[2]) > (r1[2] + r2[2] + 2 * radius)) | |
2141 | + inlet_feasibility[i] = true; | |
2142 | + else | |
2143 | + inlet_feasibility[i] = false; | |
2144 | + } | |
2145 | + } | |
2146 | + } | |
2147 | + | |
2148 | + // outlets' special connections checking | |
2149 | + for (unsigned i = 0; i < outbb.size(); i++) { | |
2150 | + for (unsigned j = 0; j < outbb.size(); j++) { | |
2151 | + if (j != i) { | |
2152 | + c1 = stim::vec3<T>((outbb[i].first + outbb[i].second) / 2); | |
2153 | + c2 = stim::vec3<T>((outbb[j].first + outbb[j].second) / 2); | |
2154 | + for (unsigned k = 0; k < 3; k++) { | |
2155 | + r1[k] = fabs(outbb[i].first[k] - outbb[i].second[k]) / 2; | |
2156 | + r2[k] = fabs(outbb[j].first[k] - outbb[j].second[k]) / 2; | |
2157 | + } | |
2158 | + // test AABBAABB | |
2159 | + if (fabs(c1[0] - c2[0]) > (r1[0] + r2[0] + 2 * radius) || fabs(c1[1] - c2[1]) > (r1[1] + r2[1] + 2 * radius) || fabs(c1[2] - c2[2]) > (r1[2] + r2[2] + 2 * radius)) | |
2160 | + outlet_feasibility[i] = true; | |
2161 | + else | |
2162 | + outlet_feasibility[i] = false; | |
2163 | + } | |
2164 | + } | |
2165 | + } | |
2166 | + } | |
2167 | + | |
2168 | + // clear synthetic connections | |
2169 | + void clear_synthetic_connection() { | |
2170 | + | |
2171 | + // restore direct synthetic connecions | |
2172 | + T l = 0.0f; | |
2173 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
2174 | + inlet[i].V.clear(); | |
2175 | + for (unsigned j = 0; j < in_backup[i].size(); j++) { | |
2176 | + inlet[i].V.push_back(in_backup[i][j]); | |
2177 | + if (j != in_backup[i].size() - 1) | |
2178 | + l += (in_backup[i][j + 1] - in_backup[i][j]).len(); | |
2179 | + } | |
2180 | + inlet[i].l = l; | |
2181 | + l = 0.0f; | |
2182 | + } | |
2183 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
2184 | + outlet[i].V.clear(); | |
2185 | + for (unsigned j = 0; j < out_backup[i].size(); j++) { | |
2186 | + outlet[i].V.push_back(out_backup[i][j]); | |
2187 | + if (j != out_backup[i].size() - 1) | |
2188 | + l += (out_backup[i][j + 1] - out_backup[i][j]).len(); | |
1921 | 2189 | } |
2190 | + outlet[i].l = l; | |
2191 | + l = 0.0f; | |
1922 | 2192 | } |
2193 | + | |
2194 | + // clear up inlets/outlets connection bounding box | |
2195 | + inbb.clear(); | |
2196 | + outbb.clear(); | |
1923 | 2197 | } |
1924 | 2198 | |
2199 | + // back up direct synthetic connection whenever modified | |
2200 | + void backup() { | |
2201 | + | |
2202 | + in_backup.clear(); | |
2203 | + out_backup.clear(); | |
2204 | + | |
2205 | + // back up direct synthetic connecions | |
2206 | + std::vector<typename stim::vec3<T> > V; | |
2207 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
2208 | + for (unsigned j = 0; j < inlet[i].V.size(); j++) { | |
2209 | + V.push_back(inlet[i].V[j]); | |
2210 | + } | |
2211 | + in_backup.push_back(V); | |
2212 | + V.clear(); | |
2213 | + } | |
2214 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
2215 | + for (unsigned j = 0; j < outlet[i].V.size(); j++) { | |
2216 | + V.push_back(outlet[i].V[j]); | |
2217 | + } | |
2218 | + out_backup.push_back(V); | |
2219 | + V.clear(); | |
2220 | + } | |
2221 | + } | |
2222 | + | |
2223 | + | |
1925 | 2224 | /// make binary image stack |
1926 | 2225 | // prepare for image stack |
1927 | 2226 | void preparation(T &Xl, T &Xr, T &Yt, T &Yb, T &Z, T length = 210.0f, T height = 10.0f) { | ... | ... |
main.cu
... | ... | @@ -46,6 +46,7 @@ float min_v; |
46 | 46 | int mods; // special keyboard input |
47 | 47 | std::vector<unsigned char> color; // velocity color map |
48 | 48 | std::vector<int> velocity_bar; // velocity bar |
49 | +float length = 210.0f; // cuboid length | |
49 | 50 | |
50 | 51 | // hard-coded parameters |
51 | 52 | float camera_factor = 1.2f; // start point of the camera as a function of X and Y size |
... | ... | @@ -64,7 +65,9 @@ float fragment_ratio = 0.0f; // fragment ratio |
64 | 65 | // glut event parameters |
65 | 66 | int mouse_x; // window x-coordinate |
66 | 67 | int mouse_y; // window y-coordinate |
67 | -bool LTbutton = false; // true means down while false means up | |
68 | +int picked_x; // picked window x-coordinate | |
69 | +int picked_y; // picked window y-coordinate | |
70 | +bool LTbutton = false; // true means down while false means up | |
68 | 71 | |
69 | 72 | // simulation parameters |
70 | 73 | bool render_direction = false; // flag indicates rendering flow direction for one edge |
... | ... | @@ -79,6 +82,14 @@ bool build_inlet_outlet = false; // flag indicates building inlets and outlets |
79 | 82 | bool modified_bridge = false; // flag indicates having modified inlet/outlet connection |
80 | 83 | bool hilbert_curve = false; // flag indicates enabling hilbert curves constructions |
81 | 84 | bool change_fragment = false; // flag indicates changing fragment for square wave connections |
85 | +bool picked_connection = false; // flag indicates picked one connection | |
86 | +bool render_new_connection = false; // flag indicates rendering new line connection in trasparency | |
87 | +bool redisplay = false; // flag indicates redisplay rendering | |
88 | +bool connection_done = false; // flag indicates finishing connections | |
89 | +unsigned connection_index = -1; // the index of connection that is picked | |
90 | +unsigned port_index = 0; // inlet (0) or outlet (1) | |
91 | +stim::vec3<float> tmp_v1, tmp_v2; // temp vertex | |
92 | +int coef; // computational coefficient factor | |
82 | 93 | |
83 | 94 | // manufacture parameters |
84 | 95 | bool manufacture = false; // flag indicates manufacture mode |
... | ... | @@ -211,19 +222,41 @@ void glut_render() { |
211 | 222 | flow.mark_vertex(); |
212 | 223 | //flow.glSolidCone(subdivision); |
213 | 224 | flow.glSolidCylinder(direction_index, color, subdivision); |
214 | - flow.glSolidCuboid(); | |
225 | + flow.glSolidCuboid(length); | |
215 | 226 | if (render_direction) |
216 | 227 | flow.glSolidCone(direction_index, subdivision); |
217 | 228 | } |
218 | 229 | |
219 | 230 | if (build_inlet_outlet) { |
220 | - flow.line_bridge(); | |
231 | + flow.line_bridge(redisplay); | |
221 | 232 | } |
222 | 233 | |
223 | 234 | if (manufacture) { |
224 | 235 | flow.glSolidCuboid(); |
225 | 236 | flow.tube_bridge(subdivision); |
226 | 237 | } |
238 | + | |
239 | + if (picked_connection && render_new_connection) { | |
240 | + glEnable(GL_BLEND); | |
241 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
242 | + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); | |
243 | + glBegin(GL_LINE_STRIP); | |
244 | + if (!port_index) { | |
245 | + glVertex3f(flow.inlet[connection_index].V[1][0], flow.inlet[connection_index].V[1][1], flow.inlet[connection_index].V[1][2]); | |
246 | + glVertex3f(tmp_v1[0], tmp_v1[1], tmp_v1[2]); | |
247 | + glVertex3f(tmp_v2[0], tmp_v2[1], tmp_v2[2]); | |
248 | + glVertex3f(flow.inlet[connection_index].V[2][0], flow.inlet[connection_index].V[2][1], flow.inlet[connection_index].V[2][2]); | |
249 | + } | |
250 | + else { | |
251 | + glVertex3f(flow.outlet[connection_index].V[1][0], flow.outlet[connection_index].V[1][1], flow.outlet[connection_index].V[1][2]); | |
252 | + glVertex3f(tmp_v1[0], tmp_v1[1], tmp_v1[2]); | |
253 | + glVertex3f(tmp_v2[0], tmp_v2[1], tmp_v2[2]); | |
254 | + glVertex3f(flow.outlet[connection_index].V[2][0], flow.outlet[connection_index].V[2][1], flow.outlet[connection_index].V[2][2]); | |
255 | + } | |
256 | + glEnd(); | |
257 | + glFlush(); | |
258 | + glDisable(GL_BLEND); | |
259 | + } | |
227 | 260 | |
228 | 261 | // render bars |
229 | 262 | // bring up a pressure bar on left |
... | ... | @@ -287,12 +320,13 @@ void glut_render() { |
287 | 320 | glLoadIdentity(); |
288 | 321 | |
289 | 322 | float step = (vY - 3 * border_factor); |
290 | - step /= num_edge; | |
291 | - for (unsigned i = 0; i < num_edge; i++) { | |
323 | + step /= BREWER_CTRL_PTS - 1; | |
324 | + for (unsigned i = 0; i < BREWER_CTRL_PTS - 1; i++) { | |
292 | 325 | glLineWidth(border_factor); |
293 | 326 | glBegin(GL_LINES); |
294 | - glColor3f((float)color[velocity_bar[i] * 3 + 0] / 255, (float)color[velocity_bar[i] * 3 + 1] / 255, (float)color[velocity_bar[i] * 3 + 2] / 255); | |
327 | + glColor3f(BREWERCP[i * 4 + 0], BREWERCP[i * 4 + 1], BREWERCP[i * 4 + 2]); | |
295 | 328 | glVertex2f(border_factor, border_factor + i * step); |
329 | + glColor3f(BREWERCP[(i + 1) * 4 + 0], BREWERCP[(i + 1) * 4 + 1], BREWERCP[(i + 1) * 4 + 2]); | |
296 | 330 | glVertex2f(border_factor, border_factor + (i + 1) * step); |
297 | 331 | glEnd(); |
298 | 332 | } |
... | ... | @@ -376,6 +410,7 @@ void glut_menu(int value) { |
376 | 410 | build_inlet_outlet = false; |
377 | 411 | manufacture = false; |
378 | 412 | modified_bridge = false; |
413 | + connection_done = false; | |
379 | 414 | if (!flow.set) |
380 | 415 | flow_initialize(); |
381 | 416 | flow_stable_state(); // main function of solving the linear system |
... | ... | @@ -388,9 +423,16 @@ void glut_menu(int value) { |
388 | 423 | simulation = false; |
389 | 424 | build_inlet_outlet = true; |
390 | 425 | manufacture = false; |
391 | - if (!modified_bridge) { | |
426 | + if (!modified_bridge && !connection_done) { | |
392 | 427 | flow.set_main_feeder(); |
393 | 428 | flow.build_synthetic_connection(u, default_radius); |
429 | + flow.check_direct_connection(); // check whether direct connections intersect each other | |
430 | + connection_done = true; | |
431 | + } | |
432 | + else if (modified_bridge) { | |
433 | + modified_bridge = false; | |
434 | + redisplay = true; | |
435 | + flow.clear_synthetic_connection(); | |
394 | 436 | } |
395 | 437 | |
396 | 438 | glut_set_menu(num, 3); |
... | ... | @@ -400,7 +442,6 @@ void glut_menu(int value) { |
400 | 442 | simulation = false; |
401 | 443 | build_inlet_outlet = false; |
402 | 444 | manufacture = true; |
403 | - flow.check_synthetic_connection(u, default_radius); | |
404 | 445 | } |
405 | 446 | |
406 | 447 | glutPostRedisplay(); |
... | ... | @@ -426,40 +467,99 @@ void glut_motion(int x, int y) { |
426 | 467 | // defines passive mouse motion function |
427 | 468 | void glut_passive_motion(int x, int y) { |
428 | 469 | |
429 | - mouse_x = x; | |
430 | - mouse_y = y; | |
470 | + mods = glutGetModifiers(); | |
431 | 471 | |
432 | 472 | // check whether the mouse point near to an edge |
433 | 473 | GLdouble posX, posY, posZ; |
434 | 474 | window_to_world(posX, posY, posZ); // get the world coordinates |
435 | 475 | |
436 | - if (simulation || build_inlet_outlet) { | |
476 | + if (simulation || build_inlet_outlet && !mods) { | |
437 | 477 | bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, direction_index); |
438 | 478 | if (flag) |
439 | 479 | render_direction = true; |
440 | 480 | else { |
441 | 481 | if (render_direction) // if the direction is displaying currently, do a short delay |
442 | - Sleep(1000); | |
482 | + Sleep(300); | |
443 | 483 | render_direction = false; |
444 | 484 | direction_index = -1; |
445 | 485 | } |
446 | 486 | } |
447 | 487 | |
448 | - glutPostRedisplay(); // re-draw the visualization | |
488 | + if (mods == GLUT_ACTIVE_SHIFT && picked_connection) { | |
489 | + render_new_connection = true; | |
490 | + unsigned i; | |
491 | + if (!port_index) { | |
492 | + tmp_v1 = stim::vec3<float>(flow.inlet[connection_index].V[1][0], flow.inlet[connection_index].V[1][1] + (float)(picked_y - y), flow.inlet[connection_index].V[1][2]); | |
493 | + tmp_v2 = stim::vec3<float>(flow.inlet[connection_index].V[2][0], flow.inlet[connection_index].V[2][1] + (float)(picked_y - y), flow.inlet[connection_index].V[2][2]); | |
494 | + i = flow.inlet[connection_index].V.size(); | |
495 | + if (coef * tmp_v1[1] < coef * flow.inlet[connection_index].V[i - 1][1]) { | |
496 | + tmp_v1[1] = flow.inlet[connection_index].V[i - 1][1]; | |
497 | + tmp_v2[1] = flow.inlet[connection_index].V[i - 1][1]; | |
498 | + } | |
499 | + } | |
500 | + else { | |
501 | + tmp_v1 = stim::vec3<float>(flow.outlet[connection_index].V[1][0], flow.outlet[connection_index].V[1][1] + (float)(picked_y - y), flow.outlet[connection_index].V[1][2]); | |
502 | + tmp_v2 = stim::vec3<float>(flow.outlet[connection_index].V[2][0], flow.outlet[connection_index].V[2][1] + (float)(picked_y - y), flow.outlet[connection_index].V[2][2]); | |
503 | + i = flow.outlet[connection_index].V.size(); | |
504 | + if (coef * tmp_v1[1] < coef * flow.outlet[connection_index].V[i - 1][1]) { | |
505 | + tmp_v1[1] = flow.outlet[connection_index].V[i - 1][1]; | |
506 | + tmp_v2[1] = flow.outlet[connection_index].V[i - 1][1]; | |
507 | + } | |
508 | + } | |
509 | + } | |
510 | + else if (mods == GLUT_ACTIVE_CTRL && picked_connection) { | |
511 | + render_new_connection = true; | |
512 | + if (!port_index) { | |
513 | + tmp_v1 = stim::vec3<float>(flow.inlet[connection_index].V[0][0] + (float)(x - picked_x), flow.inlet[connection_index].V[0][1], flow.inlet[connection_index].V[0][2]); | |
514 | + tmp_v2 = stim::vec3<float>(flow.inlet[connection_index].V[1][0] + (float)(x - picked_x), flow.inlet[connection_index].V[1][1], flow.inlet[connection_index].V[1][2]); | |
515 | + if (tmp_v1[0] < flow.main_feeder[port_index][0] - length / 2) { | |
516 | + tmp_v1[0] = flow.main_feeder[port_index][0] - length / 2; | |
517 | + tmp_v2[0] = flow.main_feeder[port_index][0] - length / 2; | |
518 | + } | |
519 | + else if (tmp_v1[0] > flow.main_feeder[port_index][0] + length / 2) { | |
520 | + tmp_v1[0] = flow.main_feeder[port_index][0] + length / 2; | |
521 | + tmp_v2[0] = flow.main_feeder[port_index][0] + length / 2; | |
522 | + } | |
523 | + } | |
524 | + else { | |
525 | + tmp_v1 = stim::vec3<float>(flow.outlet[connection_index].V[0][0] + (float)(x - picked_x), flow.outlet[connection_index].V[0][1], flow.outlet[connection_index].V[0][2]); | |
526 | + tmp_v2 = stim::vec3<float>(flow.outlet[connection_index].V[1][0] + (float)(x - picked_x), flow.outlet[connection_index].V[1][1], flow.outlet[connection_index].V[1][2]); | |
527 | + if (tmp_v1[0] > flow.main_feeder[port_index][0] + length / 2) { | |
528 | + tmp_v1[0] = flow.main_feeder[port_index][0] + length / 2; | |
529 | + tmp_v2[0] = flow.main_feeder[port_index][0] + length / 2; | |
530 | + } | |
531 | + else if (tmp_v1[0] < flow.main_feeder[port_index][0] - length / 2) { | |
532 | + tmp_v1[0] = flow.main_feeder[port_index][0] - length / 2; | |
533 | + tmp_v2[0] = flow.main_feeder[port_index][0] - length / 2; | |
534 | + } | |
535 | + } | |
536 | + } | |
537 | + else | |
538 | + render_new_connection = false; | |
539 | + | |
540 | + mouse_x = x; | |
541 | + mouse_y = y; | |
542 | + | |
543 | + glutPostRedisplay(); // re-draw the visualization | |
449 | 544 | } |
450 | 545 | |
451 | 546 | // get click window coordinates |
452 | 547 | void glut_mouse(int button, int state, int x, int y) { |
453 | 548 | |
549 | + mods = glutGetModifiers(); // get special keyboard input | |
550 | + | |
454 | 551 | mouse_x = x; |
455 | 552 | mouse_y = y; |
553 | + if (!mods) { | |
554 | + picked_connection = false; | |
555 | + render_new_connection = false; | |
556 | + } | |
456 | 557 | if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) |
457 | 558 | LTbutton = true; |
458 | 559 | else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) |
459 | 560 | LTbutton = false; |
460 | 561 | |
461 | - if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && simulation && !to_select_pressure) { | |
462 | - | |
562 | + if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && !mods && simulation && !to_select_pressure) { | |
463 | 563 | GLdouble posX, posY, posZ; |
464 | 564 | window_to_world(posX, posY, posZ); // get the world coordinates |
465 | 565 | |
... | ... | @@ -470,7 +570,7 @@ void glut_mouse(int button, int state, int x, int y) { |
470 | 570 | to_select_pressure = true; |
471 | 571 | } |
472 | 572 | } |
473 | - else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && simulation && to_select_pressure) { | |
573 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && !mods && simulation && to_select_pressure) { | |
474 | 574 | if (y > 2 * border_factor || y < vY - border_factor) { // within the pressure bar range |
475 | 575 | to_select_pressure = false; |
476 | 576 | float tmp_pressure = (float)(vY - y - border_factor) / ((float)vY - border_factor) * max_pressure; |
... | ... | @@ -480,13 +580,141 @@ void glut_mouse(int button, int state, int x, int y) { |
480 | 580 | flow.print_flow(); |
481 | 581 | } |
482 | 582 | } |
483 | - else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && modified_bridge && change_fragment) { | |
583 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && !mods && modified_bridge && change_fragment) { | |
484 | 584 | if (y > 2 * border_factor || y < vY - border_factor) { // within the ratio bar range |
485 | 585 | fragment_ratio = (float)(vY - y - border_factor) / ((float)vY - border_factor) * 1.0f; |
486 | 586 | flow.modify_synthetic_connection(u, rou, hilbert_curve, height_threshold, fragment_ratio, default_radius); |
487 | 587 | change_fragment = false; |
488 | 588 | } |
489 | 589 | } |
590 | + // move connections along y-axis | |
591 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && mods == GLUT_ACTIVE_SHIFT && !modified_bridge && !picked_connection) { | |
592 | + GLdouble posX, posY, posZ; | |
593 | + window_to_world(posX, posY, posZ); // get the world coordinates | |
594 | + | |
595 | + bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, connection_index, port_index); | |
596 | + if (flag) { | |
597 | + picked_connection = true; | |
598 | + picked_x = x; | |
599 | + picked_y = y; | |
600 | + if (!port_index) | |
601 | + if (flow.inlet[connection_index].V[2][1] > flow.main_feeder[port_index][1]) | |
602 | + coef = 1; | |
603 | + else | |
604 | + coef = -1; | |
605 | + else | |
606 | + if (flow.outlet[connection_index].V[2][1] > flow.main_feeder[port_index][1]) | |
607 | + coef = 1; | |
608 | + else | |
609 | + coef = -1; | |
610 | + } | |
611 | + else | |
612 | + picked_connection = false; | |
613 | + } | |
614 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && mods == GLUT_ACTIVE_SHIFT && !modified_bridge && render_new_connection) { | |
615 | + float l = 0.0f; | |
616 | + std::vector<typename stim::vec3<float> > V; | |
617 | + unsigned i; | |
618 | + if (!port_index) { | |
619 | + i = flow.inlet[connection_index].V.size(); | |
620 | + if (tmp_v2[1] != flow.inlet[connection_index].V[i - 1][1]) { | |
621 | + V.resize(4); | |
622 | + V[0] = flow.inlet[connection_index].V[0]; | |
623 | + V[1] = tmp_v1; | |
624 | + V[2] = tmp_v2; | |
625 | + V[3] = flow.inlet[connection_index].V[i - 1]; | |
626 | + std::swap(flow.inlet[connection_index].V, V); | |
627 | + } | |
628 | + else { | |
629 | + V.resize(3); | |
630 | + V[0] = flow.inlet[connection_index].V[0]; | |
631 | + V[1] = tmp_v1; | |
632 | + V[2] = tmp_v2; | |
633 | + std::swap(flow.inlet[connection_index].V, V); | |
634 | + } | |
635 | + // calculate new length | |
636 | + for (unsigned i = 0; i < flow.inlet[connection_index].V.size() - 1; i++) { | |
637 | + l += (flow.inlet[connection_index].V[i + 1] - flow.inlet[connection_index].V[i]).len(); | |
638 | + } | |
639 | + flow.inlet[connection_index].l = l; | |
640 | + } | |
641 | + else { | |
642 | + i = flow.outlet[connection_index].V.size(); | |
643 | + if (tmp_v2[1] != flow.outlet[connection_index].V[i - 1][1]) { | |
644 | + V.resize(4); | |
645 | + V[0] = flow.outlet[connection_index].V[0]; | |
646 | + V[1] = tmp_v1; | |
647 | + V[2] = tmp_v2; | |
648 | + V[3] = flow.outlet[connection_index].V[i - 1]; | |
649 | + std::swap(flow.outlet[connection_index].V, V); | |
650 | + } | |
651 | + else { | |
652 | + V.resize(3); | |
653 | + V[0] = flow.outlet[connection_index].V[0]; | |
654 | + V[1] = tmp_v1; | |
655 | + V[2] = tmp_v2; | |
656 | + std::swap(flow.outlet[connection_index].V, V); | |
657 | + } | |
658 | + // calculate new length | |
659 | + for (unsigned i = 0; i < flow.outlet[connection_index].V.size() - 1; i++) { | |
660 | + l += (flow.outlet[connection_index].V[i + 1] - flow.outlet[connection_index].V[i]).len(); | |
661 | + } | |
662 | + flow.outlet[connection_index].l = l; | |
663 | + } | |
664 | + | |
665 | + redisplay = true; | |
666 | + render_new_connection = false; | |
667 | + picked_connection = false; | |
668 | + | |
669 | + flow.check_direct_connection(); | |
670 | + flow.backup(); // back up direct synthetic connections | |
671 | + } | |
672 | + // move connections along x-axis | |
673 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && mods == GLUT_ACTIVE_CTRL && !modified_bridge && !picked_connection) { | |
674 | + GLdouble posX, posY, posZ; | |
675 | + window_to_world(posX, posY, posZ); // get the world coordinates | |
676 | + | |
677 | + bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, connection_index, port_index); | |
678 | + if (flag) { | |
679 | + picked_connection = true; | |
680 | + picked_x = x; | |
681 | + picked_y = y; | |
682 | + if (!port_index) | |
683 | + coef = 1; | |
684 | + else | |
685 | + coef = -1; | |
686 | + } | |
687 | + else | |
688 | + picked_connection = false; | |
689 | + } | |
690 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && mods == GLUT_ACTIVE_CTRL && !modified_bridge && render_new_connection) { | |
691 | + float l = 0.0f; | |
692 | + if (!port_index) { | |
693 | + flow.inlet[connection_index].V[0] = tmp_v1; | |
694 | + flow.inlet[connection_index].V[1] = tmp_v2; | |
695 | + // calculate new length | |
696 | + for (unsigned i = 0; i < flow.inlet[connection_index].V.size() - 1; i++) { | |
697 | + l += (flow.inlet[connection_index].V[i + 1] - flow.inlet[connection_index].V[i]).len(); | |
698 | + } | |
699 | + flow.inlet[connection_index].l = l; | |
700 | + } | |
701 | + else { | |
702 | + flow.outlet[connection_index].V[0] = tmp_v1; | |
703 | + flow.outlet[connection_index].V[1] = tmp_v2; | |
704 | + // calculate new length | |
705 | + for (unsigned i = 0; i < flow.outlet[connection_index].V.size() - 1; i++) { | |
706 | + l += (flow.outlet[connection_index].V[i + 1] - flow.outlet[connection_index].V[i]).len(); | |
707 | + } | |
708 | + flow.outlet[connection_index].l = l; | |
709 | + } | |
710 | + | |
711 | + redisplay = true; | |
712 | + render_new_connection = false; | |
713 | + picked_connection = false; | |
714 | + | |
715 | + flow.check_direct_connection(); | |
716 | + flow.backup(); | |
717 | + } | |
490 | 718 | } |
491 | 719 | |
492 | 720 | // define camera move based on mouse wheel move | ... | ... |