Commit f4105b89553b247a70fe04555ee2a41a792899a8

Authored by Jiaming Guo
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,6 +238,8 @@ namespace stim {
238 std::vector<typename stim::triple<unsigned, unsigned, float> > Q; // volume flow rate 238 std::vector<typename stim::triple<unsigned, unsigned, float> > Q; // volume flow rate
239 std::vector<T> QQ; // Q' vector 239 std::vector<T> QQ; // Q' vector
240 std::vector<T> pressure; // final pressure 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 public: 244 public:
243 245
@@ -254,6 +256,10 @@ namespace stim { @@ -254,6 +256,10 @@ namespace stim {
254 std::vector<typename stim::cone<T> > B; // cone(cylinder) model for making image stack 256 std::vector<typename stim::cone<T> > B; // cone(cylinder) model for making image stack
255 std::vector<typename stim::cuboid<T> > CU; // cuboid model for making image stack 257 std::vector<typename stim::cuboid<T> > CU; // cuboid model for making image stack
256 stim::gl_aaboundingbox<T> bb; // bounding box 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 flow() {} // default constructor 264 flow() {} // default constructor
259 ~flow() { 265 ~flow() {
@@ -804,8 +810,8 @@ namespace stim { @@ -804,8 +810,8 @@ namespace stim {
804 std::vector<typename stim::vec3<float> > cp2(subdivision + 1); 810 std::vector<typename stim::vec3<float> > cp2(subdivision + 1);
805 for (unsigned i = 0; i < num_edge; i++) { // for every edge 811 for (unsigned i = 0; i < num_edge; i++) { // for every edge
806 if (i == index) { // render in tranparency for direction indication 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 glDisable(GL_DEPTH_TEST); 815 glDisable(GL_DEPTH_TEST);
810 glColor4f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255, 0.5f); 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,19 +1058,33 @@ namespace stim {
1052 } 1058 }
1053 1059
1054 // draw the bridge as lines 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 if (!glIsList(dlist)) { 1067 if (!glIsList(dlist)) {
1058 dlist = glGenLists(1); 1068 dlist = glGenLists(1);
1059 glNewList(dlist, GL_COMPILE); 1069 glNewList(dlist, GL_COMPILE);
1060 - glColor3f(0.0f, 0.0f, 0.0f); 1070 +
  1071 + glLineWidth(50);
1061 for (unsigned i = 0; i < inlet.size(); i++) { 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 glBegin(GL_LINE_STRIP); 1078 glBegin(GL_LINE_STRIP);
1063 for (unsigned j = 0; j < inlet[i].V.size(); j++) 1079 for (unsigned j = 0; j < inlet[i].V.size(); j++)
1064 glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); 1080 glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]);
1065 glEnd(); 1081 glEnd();
1066 } 1082 }
1067 for (unsigned i = 0; i < outlet.size(); i++) { 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 glBegin(GL_LINE_STRIP); 1088 glBegin(GL_LINE_STRIP);
1069 for (unsigned j = 0; j < outlet[i].V.size(); j++) 1089 for (unsigned j = 0; j < outlet[i].V.size(); j++)
1070 glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); 1090 glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]);
@@ -1255,6 +1275,7 @@ namespace stim { @@ -1255,6 +1275,7 @@ namespace stim {
1255 bool online = false; // flag indicates the point is on the line-segment 1275 bool online = false; // flag indicates the point is on the line-segment
1256 float a, b; 1276 float a, b;
1257 1277
  1278 + // inner network
1258 for (unsigned i = 0; i < E.size(); i++) { 1279 for (unsigned i = 0; i < E.size(); i++) {
1259 for (unsigned j = 0; j < E[i].size() - 1; j++) { 1280 for (unsigned j = 0; j < E[i].size() - 1; j++) {
1260 v1 = E[i][j + 1] - E[i][j]; // a -> b = ab 1281 v1 = E[i][j + 1] - E[i][j]; // a -> b = ab
@@ -1284,6 +1305,60 @@ namespace stim { @@ -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 eps += get_radius(tmp_i, tmp_j); 1362 eps += get_radius(tmp_i, tmp_j);
1288 1363
1289 if (d < eps) { 1364 if (d < eps) {
@@ -1293,6 +1368,86 @@ namespace stim { @@ -1293,6 +1368,86 @@ namespace stim {
1293 1368
1294 return false; 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 /// build main feeder connection 1452 /// build main feeder connection
1298 // set up main feeder and main port of both input and output 1453 // set up main feeder and main port of both input and output
@@ -1404,6 +1559,8 @@ namespace stim { @@ -1404,6 +1559,8 @@ namespace stim {
1404 1559
1405 outlet.push_back(tmp_b); 1560 outlet.push_back(tmp_b);
1406 } 1561 }
  1562 +
  1563 + backup();
1407 } 1564 }
1408 1565
1409 // find the number of U-shape or square-shape structure for extending length of connection 1566 // find the number of U-shape or square-shape structure for extending length of connection
@@ -1436,12 +1593,13 @@ namespace stim { @@ -1436,12 +1593,13 @@ namespace stim {
1436 int coef_z = (z) ? 1 : -1; // z coefficient 1593 int coef_z = (z) ? 1 : -1; // z coefficient
1437 int inverse = 1; // inverse flag 1594 int inverse = 1; // inverse flag
1438 stim::vec3<T> cor_v; // corner vertex 1595 stim::vec3<T> cor_v; // corner vertex
1439 - 1596 + std::pair<stim::vec3<T>, stim::vec3<T>> tmp_bb;
1440 stim::vec3<T> tmp_v; 1597 stim::vec3<T> tmp_v;
1441 - if (feeder == 1) 1598 + if (feeder == 1)
1442 tmp_v = inlet[i].V[0]; 1599 tmp_v = inlet[i].V[0];
1443 - else if (feeder == 0) 1600 + else if (feeder == 0)
1444 tmp_v = outlet[i].V[0]; 1601 tmp_v = outlet[i].V[0];
  1602 + tmp_bb.first = tmp_v;
1445 1603
1446 // check whether the height of connections is acceptable 1604 // check whether the height of connections is acceptable
1447 if (height > threshold) { // acceptable 1605 if (height > threshold) { // acceptable
@@ -1522,6 +1680,8 @@ namespace stim { @@ -1522,6 +1680,8 @@ namespace stim {
1522 inlet[i].V.push_back(tmp_v); 1680 inlet[i].V.push_back(tmp_v);
1523 else if (feeder == 0) 1681 else if (feeder == 0)
1524 outlet[i].V.push_back(tmp_v); 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 tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); 1686 tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0);
1527 if (feeder == 1) 1687 if (feeder == 1)
@@ -1555,7 +1715,7 @@ namespace stim { @@ -1555,7 +1715,7 @@ namespace stim {
1555 inverse = 1; 1715 inverse = 1;
1556 } 1716 }
1557 // if use fragment to do square wave connection, need to push_back the corner vertex 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 if (feeder == 1) 1719 if (feeder == 1)
1560 inlet[i].V.push_back(cor_v); 1720 inlet[i].V.push_back(cor_v);
1561 else if (feeder == 0) 1721 else if (feeder == 0)
@@ -1565,25 +1725,30 @@ namespace stim { @@ -1565,25 +1725,30 @@ namespace stim {
1565 else { 1725 else {
1566 for (int j = 0; j < n; j++) { 1726 for (int j = 0; j < n; j++) {
1567 1727
1568 - // move in Z-shape 1728 + // up
1569 tmp_v = tmp_v + stim::vec3<T>(0, coef_up * height, 0); 1729 tmp_v = tmp_v + stim::vec3<T>(0, coef_up * height, 0);
1570 if (feeder == 1) 1730 if (feeder == 1)
1571 inlet[i].V.push_back(tmp_v); 1731 inlet[i].V.push_back(tmp_v);
1572 else if (feeder == 0) 1732 else if (feeder == 0)
1573 outlet[i].V.push_back(tmp_v); 1733 outlet[i].V.push_back(tmp_v);
1574 1734
  1735 + // left
1575 tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); 1736 tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0);
1576 if (feeder == 1) 1737 if (feeder == 1)
1577 inlet[i].V.push_back(tmp_v); 1738 inlet[i].V.push_back(tmp_v);
1578 else if (feeder == 0) 1739 else if (feeder == 0)
1579 outlet[i].V.push_back(tmp_v); 1740 outlet[i].V.push_back(tmp_v);
  1741 + if (j == n - 1)
  1742 + tmp_bb.second = tmp_v;
1580 1743
  1744 + // down
1581 tmp_v = tmp_v + stim::vec3<T>(0, -coef_up * height, 0); 1745 tmp_v = tmp_v + stim::vec3<T>(0, -coef_up * height, 0);
1582 if (feeder == 1) 1746 if (feeder == 1)
1583 inlet[i].V.push_back(tmp_v); 1747 inlet[i].V.push_back(tmp_v);
1584 else if (feeder == 0) 1748 else if (feeder == 0)
1585 outlet[i].V.push_back(tmp_v); 1749 outlet[i].V.push_back(tmp_v);
1586 1750
  1751 + // left
1587 tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); 1752 tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0);
1588 if (feeder == 1) 1753 if (feeder == 1)
1589 inlet[i].V.push_back(tmp_v); 1754 inlet[i].V.push_back(tmp_v);
@@ -1591,6 +1756,10 @@ namespace stim { @@ -1591,6 +1756,10 @@ namespace stim {
1591 outlet[i].V.push_back(tmp_v); 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 // automatically modify bridge to make it feasible 1765 // automatically modify bridge to make it feasible
@@ -1598,7 +1767,7 @@ namespace stim { @@ -1598,7 +1767,7 @@ namespace stim {
1598 1767
1599 glDeleteLists(dlist, 1); // delete display list for modify 1768 glDeleteLists(dlist, 1); // delete display list for modify
1600 glDeleteLists(dlist + 1, 1); 1769 glDeleteLists(dlist + 1, 1);
1601 - 1770 +
1602 // because of radius change at the port vertex, there will be a pressure drop at that port 1771 // because of radius change at the port vertex, there will be a pressure drop at that port
1603 // it follows the bernoulli equation 1772 // it follows the bernoulli equation
1604 // p1 + 1/2*rou*v1^2 + rou*g*h1 = p2 + 1/2*rou*v2^2 + rou*g*h2 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,13 +1984,15 @@ namespace stim {
1815 // automatically modify inlet bridge using square shape constructions 1984 // automatically modify inlet bridge using square shape constructions
1816 else { 1985 else {
1817 bool upper; // flag indicates the connection is upper than the bus 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 T new_l; // new length 1988 T new_l; // new length
1820 stim::vec3<T> bus_v; // the port point on the bus 1989 stim::vec3<T> bus_v; // the port point on the bus
1821 stim::vec3<T> mid_v; // the original corner point 1990 stim::vec3<T> mid_v; // the original corner point
1822 stim::vec3<T> tmp_v; // the pendant point 1991 stim::vec3<T> tmp_v; // the pendant point
1823 int n; 1992 int n;
1824 T width, height; // width and height of the square 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 for (unsigned i = 0; i < inlet.size(); i++) { 1997 for (unsigned i = 0; i < inlet.size(); i++) {
1827 if (i != inlet_index) { 1998 if (i != inlet_index) {
@@ -1857,6 +2028,10 @@ namespace stim { @@ -1857,6 +2028,10 @@ namespace stim {
1857 2028
1858 std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex 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 for (unsigned i = 0; i < outlet.size(); i++) { 2037 for (unsigned i = 0; i < outlet.size(); i++) {
@@ -1893,35 +2068,159 @@ namespace stim { @@ -1893,35 +2068,159 @@ namespace stim {
1893 2068
1894 std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex 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 /// make binary image stack 2224 /// make binary image stack
1926 // prepare for image stack 2225 // prepare for image stack
1927 void preparation(T &Xl, T &Xr, T &Yt, T &Yb, T &Z, T length = 210.0f, T height = 10.0f) { 2226 void preparation(T &Xl, T &Xr, T &Yt, T &Yb, T &Z, T length = 210.0f, T height = 10.0f) {
@@ -46,6 +46,7 @@ float min_v; @@ -46,6 +46,7 @@ float min_v;
46 int mods; // special keyboard input 46 int mods; // special keyboard input
47 std::vector<unsigned char> color; // velocity color map 47 std::vector<unsigned char> color; // velocity color map
48 std::vector<int> velocity_bar; // velocity bar 48 std::vector<int> velocity_bar; // velocity bar
  49 +float length = 210.0f; // cuboid length
49 50
50 // hard-coded parameters 51 // hard-coded parameters
51 float camera_factor = 1.2f; // start point of the camera as a function of X and Y size 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,7 +65,9 @@ float fragment_ratio = 0.0f; // fragment ratio
64 // glut event parameters 65 // glut event parameters
65 int mouse_x; // window x-coordinate 66 int mouse_x; // window x-coordinate
66 int mouse_y; // window y-coordinate 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 // simulation parameters 72 // simulation parameters
70 bool render_direction = false; // flag indicates rendering flow direction for one edge 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,6 +82,14 @@ bool build_inlet_outlet = false; // flag indicates building inlets and outlets
79 bool modified_bridge = false; // flag indicates having modified inlet/outlet connection 82 bool modified_bridge = false; // flag indicates having modified inlet/outlet connection
80 bool hilbert_curve = false; // flag indicates enabling hilbert curves constructions 83 bool hilbert_curve = false; // flag indicates enabling hilbert curves constructions
81 bool change_fragment = false; // flag indicates changing fragment for square wave connections 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 // manufacture parameters 94 // manufacture parameters
84 bool manufacture = false; // flag indicates manufacture mode 95 bool manufacture = false; // flag indicates manufacture mode
@@ -211,19 +222,41 @@ void glut_render() { @@ -211,19 +222,41 @@ void glut_render() {
211 flow.mark_vertex(); 222 flow.mark_vertex();
212 //flow.glSolidCone(subdivision); 223 //flow.glSolidCone(subdivision);
213 flow.glSolidCylinder(direction_index, color, subdivision); 224 flow.glSolidCylinder(direction_index, color, subdivision);
214 - flow.glSolidCuboid(); 225 + flow.glSolidCuboid(length);
215 if (render_direction) 226 if (render_direction)
216 flow.glSolidCone(direction_index, subdivision); 227 flow.glSolidCone(direction_index, subdivision);
217 } 228 }
218 229
219 if (build_inlet_outlet) { 230 if (build_inlet_outlet) {
220 - flow.line_bridge(); 231 + flow.line_bridge(redisplay);
221 } 232 }
222 233
223 if (manufacture) { 234 if (manufacture) {
224 flow.glSolidCuboid(); 235 flow.glSolidCuboid();
225 flow.tube_bridge(subdivision); 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 // render bars 261 // render bars
229 // bring up a pressure bar on left 262 // bring up a pressure bar on left
@@ -287,12 +320,13 @@ void glut_render() { @@ -287,12 +320,13 @@ void glut_render() {
287 glLoadIdentity(); 320 glLoadIdentity();
288 321
289 float step = (vY - 3 * border_factor); 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 glLineWidth(border_factor); 325 glLineWidth(border_factor);
293 glBegin(GL_LINES); 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 glVertex2f(border_factor, border_factor + i * step); 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 glVertex2f(border_factor, border_factor + (i + 1) * step); 330 glVertex2f(border_factor, border_factor + (i + 1) * step);
297 glEnd(); 331 glEnd();
298 } 332 }
@@ -376,6 +410,7 @@ void glut_menu(int value) { @@ -376,6 +410,7 @@ void glut_menu(int value) {
376 build_inlet_outlet = false; 410 build_inlet_outlet = false;
377 manufacture = false; 411 manufacture = false;
378 modified_bridge = false; 412 modified_bridge = false;
  413 + connection_done = false;
379 if (!flow.set) 414 if (!flow.set)
380 flow_initialize(); 415 flow_initialize();
381 flow_stable_state(); // main function of solving the linear system 416 flow_stable_state(); // main function of solving the linear system
@@ -388,9 +423,16 @@ void glut_menu(int value) { @@ -388,9 +423,16 @@ void glut_menu(int value) {
388 simulation = false; 423 simulation = false;
389 build_inlet_outlet = true; 424 build_inlet_outlet = true;
390 manufacture = false; 425 manufacture = false;
391 - if (!modified_bridge) { 426 + if (!modified_bridge && !connection_done) {
392 flow.set_main_feeder(); 427 flow.set_main_feeder();
393 flow.build_synthetic_connection(u, default_radius); 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 glut_set_menu(num, 3); 438 glut_set_menu(num, 3);
@@ -400,7 +442,6 @@ void glut_menu(int value) { @@ -400,7 +442,6 @@ void glut_menu(int value) {
400 simulation = false; 442 simulation = false;
401 build_inlet_outlet = false; 443 build_inlet_outlet = false;
402 manufacture = true; 444 manufacture = true;
403 - flow.check_synthetic_connection(u, default_radius);  
404 } 445 }
405 446
406 glutPostRedisplay(); 447 glutPostRedisplay();
@@ -426,40 +467,99 @@ void glut_motion(int x, int y) { @@ -426,40 +467,99 @@ void glut_motion(int x, int y) {
426 // defines passive mouse motion function 467 // defines passive mouse motion function
427 void glut_passive_motion(int x, int y) { 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 // check whether the mouse point near to an edge 472 // check whether the mouse point near to an edge
433 GLdouble posX, posY, posZ; 473 GLdouble posX, posY, posZ;
434 window_to_world(posX, posY, posZ); // get the world coordinates 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 bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, direction_index); 477 bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, direction_index);
438 if (flag) 478 if (flag)
439 render_direction = true; 479 render_direction = true;
440 else { 480 else {
441 if (render_direction) // if the direction is displaying currently, do a short delay 481 if (render_direction) // if the direction is displaying currently, do a short delay
442 - Sleep(1000); 482 + Sleep(300);
443 render_direction = false; 483 render_direction = false;
444 direction_index = -1; 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 // get click window coordinates 546 // get click window coordinates
452 void glut_mouse(int button, int state, int x, int y) { 547 void glut_mouse(int button, int state, int x, int y) {
453 548
  549 + mods = glutGetModifiers(); // get special keyboard input
  550 +
454 mouse_x = x; 551 mouse_x = x;
455 mouse_y = y; 552 mouse_y = y;
  553 + if (!mods) {
  554 + picked_connection = false;
  555 + render_new_connection = false;
  556 + }
456 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 557 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
457 LTbutton = true; 558 LTbutton = true;
458 else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) 559 else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
459 LTbutton = false; 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 GLdouble posX, posY, posZ; 563 GLdouble posX, posY, posZ;
464 window_to_world(posX, posY, posZ); // get the world coordinates 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,7 +570,7 @@ void glut_mouse(int button, int state, int x, int y) {
470 to_select_pressure = true; 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 if (y > 2 * border_factor || y < vY - border_factor) { // within the pressure bar range 574 if (y > 2 * border_factor || y < vY - border_factor) { // within the pressure bar range
475 to_select_pressure = false; 575 to_select_pressure = false;
476 float tmp_pressure = (float)(vY - y - border_factor) / ((float)vY - border_factor) * max_pressure; 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,13 +580,141 @@ void glut_mouse(int button, int state, int x, int y) {
480 flow.print_flow(); 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 if (y > 2 * border_factor || y < vY - border_factor) { // within the ratio bar range 584 if (y > 2 * border_factor || y < vY - border_factor) { // within the ratio bar range
485 fragment_ratio = (float)(vY - y - border_factor) / ((float)vY - border_factor) * 1.0f; 585 fragment_ratio = (float)(vY - y - border_factor) / ((float)vY - border_factor) * 1.0f;
486 flow.modify_synthetic_connection(u, rou, hilbert_curve, height_threshold, fragment_ratio, default_radius); 586 flow.modify_synthetic_connection(u, rou, hilbert_curve, height_threshold, fragment_ratio, default_radius);
487 change_fragment = false; 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 // define camera move based on mouse wheel move 720 // define camera move based on mouse wheel move