Commit 8334680aedb2270ba2dbd0924240d0e9fff3ad4b
1 parent
9b69bb4c
add square wave connections
Showing
2 changed files
with
546 additions
and
204 deletions
Show diff stats
... | ... | @@ -30,7 +30,7 @@ namespace stim { |
30 | 30 | std::vector<unsigned> v; // vertices' indices |
31 | 31 | std::vector<typename stim::vec3<T> > V; // vertices' coordinates |
32 | 32 | T l; // length |
33 | - T r; // radii | |
33 | + T r; // radius | |
34 | 34 | T deltaP; // pressure drop |
35 | 35 | T Q; // volume flow rate |
36 | 36 | }; |
... | ... | @@ -38,15 +38,15 @@ namespace stim { |
38 | 38 | template <typename T> |
39 | 39 | struct sphere { |
40 | 40 | stim::vec3<T> c; // center of sphere |
41 | - T r; // radii | |
41 | + T r; // radius | |
42 | 42 | }; |
43 | 43 | |
44 | 44 | template <typename T> |
45 | - struct cone { // radii changes gradually | |
45 | + struct cone { // radius changes gradually | |
46 | 46 | stim::vec3<T> c1; // center of geometry start hat |
47 | 47 | stim::vec3<T> c2; // center of geometry end hat |
48 | - T r1; // radii at start hat | |
49 | - T r2; // radii at end hat | |
48 | + T r1; // radius at start hat | |
49 | + T r2; // radius at end hat | |
50 | 50 | }; |
51 | 51 | |
52 | 52 | template <typename T> |
... | ... | @@ -105,7 +105,7 @@ namespace stim { |
105 | 105 | |
106 | 106 | float distance = FLT_MAX; |
107 | 107 | float tmp_distance; |
108 | - float rr; // radii at the surface where projection meets | |
108 | + float rr; // radius at the surface where projection meets | |
109 | 109 | |
110 | 110 | for (unsigned i = 0; i < num; i++) { // find the nearest cylinder |
111 | 111 | tmp_distance = ((world_pixel - E[i].c1).cross(world_pixel - E[i].c2)).len() / (E[i].c2 - E[i].c1).len(); |
... | ... | @@ -241,6 +241,7 @@ namespace stim { |
241 | 241 | |
242 | 242 | public: |
243 | 243 | |
244 | + bool set = false; // flag indicates the pressure has been set | |
244 | 245 | std::vector<T> P; // initial pressure |
245 | 246 | std::vector<T> v; // velocity |
246 | 247 | std::vector<typename stim::vec3<T> > main_feeder; // inlet/outlet main feeder |
... | ... | @@ -311,7 +312,7 @@ namespace stim { |
311 | 312 | } |
312 | 313 | } |
313 | 314 | |
314 | - // get the radii of vertex i | |
315 | + // get the radius of vertex i | |
315 | 316 | T get_radius(unsigned i) { |
316 | 317 | |
317 | 318 | unsigned tmp_e; // edge index |
... | ... | @@ -596,7 +597,7 @@ namespace stim { |
596 | 597 | // find two envelope caps for two spheres |
597 | 598 | // @param cp1, cp2: list of points on the cap |
598 | 599 | // @param center1, center2: center point of cap |
599 | - // @param r1, r2: radii of cap | |
600 | + // @param r1, r2: radius of cap | |
600 | 601 | void find_envelope(std::vector<typename stim::vec3<float> > &cp1, std::vector<typename stim::vec3<float> > &cp2, stim::vec3<float> center1, stim::vec3<float> center2, float r1, float r2, GLint subdivision) { |
601 | 602 | |
602 | 603 | stim::vec3<float> tmp_d; |
... | ... | @@ -700,7 +701,7 @@ namespace stim { |
700 | 701 | // calculate the bigger circle |
701 | 702 | d1 = t1 - center1; |
702 | 703 | dot = d1.dot(tmp_d); |
703 | - a = dot / (r1 * 1) * r1; // a = cos(alpha) * radii | |
704 | + a = dot / (r1 * 1) * r1; // a = cos(alpha) * radius | |
704 | 705 | new_c = center1 + a * tmp_d; |
705 | 706 | new_r = sqrt(pow(r1, 2) - pow(a, 2)); |
706 | 707 | new_u = t1 - new_c; |
... | ... | @@ -803,7 +804,7 @@ namespace stim { |
803 | 804 | std::vector<typename stim::vec3<T> > cp; |
804 | 805 | T radius; |
805 | 806 | |
806 | - glColor3f(1.0f, 1.0f, 1.0f); | |
807 | + glColor3f(0.0f, 0.0f, 0.0f); | |
807 | 808 | for (unsigned i = 0; i < num_edge; i++) { // for every edge |
808 | 809 | for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on current edge |
809 | 810 | tmp_d = E[i][j + 1] - E[i][j]; |
... | ... | @@ -812,9 +813,9 @@ namespace stim { |
812 | 813 | tmp_c.rotate(tmp_d); |
813 | 814 | radius = (E[i].r(j + 1) + E[i].r(j)) / 2; |
814 | 815 | if (v[i] > 0) // if flow flows from j to j+1 |
815 | - head = center + tmp_d * sqrt(3) * radius; | |
816 | + head = center + tmp_d * 2 * sqrt(3) * radius; | |
816 | 817 | else |
817 | - head = center - tmp_d * sqrt(3) * radius; | |
818 | + head = center - tmp_d * 2 * sqrt(3) * radius; | |
818 | 819 | |
819 | 820 | stim::circle<float> c(center, radius, tmp_d, tmp_c.U); |
820 | 821 | cp = c.glpoints(subdivision); |
... | ... | @@ -837,7 +838,7 @@ namespace stim { |
837 | 838 | stim::vec3<T> U = bb.B; // get the top right corner |
838 | 839 | width = U[2] - L[2] + 10.0f; |
839 | 840 | |
840 | - glColor3f(1.0f, 1.0f, 1.0f); | |
841 | + glColor3f(0.0f, 0.0f, 0.0f); | |
841 | 842 | for (unsigned i = 0; i < main_feeder.size(); i++) { |
842 | 843 | // front face |
843 | 844 | glBegin(GL_QUADS); |
... | ... | @@ -896,6 +897,7 @@ namespace stim { |
896 | 897 | if (!glIsList(dlist)) { |
897 | 898 | dlist = glGenLists(1); |
898 | 899 | glNewList(dlist, GL_COMPILE); |
900 | + glColor3f(0.0f, 0.0f, 0.0f); | |
899 | 901 | for (unsigned i = 0; i < inlet.size(); i++) { |
900 | 902 | glBegin(GL_LINE_STRIP); |
901 | 903 | for (unsigned j = 0; j < inlet[i].V.size(); j++) |
... | ... | @@ -915,7 +917,7 @@ namespace stim { |
915 | 917 | } |
916 | 918 | |
917 | 919 | // draw the bridge as tubes |
918 | - void tube_bridge(T subdivision, T radii = 5.0f) { | |
920 | + void tube_bridge(T subdivision, T radius = 5.0f) { | |
919 | 921 | |
920 | 922 | if (!glIsList(dlist + 1)) { |
921 | 923 | glNewList(dlist + 1, GL_COMPILE); |
... | ... | @@ -924,13 +926,14 @@ namespace stim { |
924 | 926 | stim::circle<T> unit_c; // unit circle for finding the rotation start direction |
925 | 927 | std::vector<typename stim::vec3<T> > cp1; |
926 | 928 | std::vector<typename stim::vec3<T> > cp2; |
929 | + glColor3f(0.0f, 0.0f, 0.0f); | |
927 | 930 | |
928 | 931 | for (unsigned i = 0; i < inlet.size(); i++) { |
929 | 932 | // render vertex as sphere |
930 | 933 | for (unsigned j = 1; j < inlet[i].V.size() - 1; j++) { |
931 | 934 | glPushMatrix(); |
932 | 935 | glTranslatef(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); |
933 | - glutSolidSphere(radii, subdivision, subdivision); | |
936 | + glutSolidSphere(radius, subdivision, subdivision); | |
934 | 937 | glPopMatrix(); |
935 | 938 | } |
936 | 939 | // render edge as cylinder |
... | ... | @@ -957,7 +960,7 @@ namespace stim { |
957 | 960 | for (unsigned j = 1; j < outlet[i].V.size() - 1; j++) { |
958 | 961 | glPushMatrix(); |
959 | 962 | glTranslatef(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); |
960 | - glutSolidSphere(radii, subdivision, subdivision); | |
963 | + glutSolidSphere(radius, subdivision, subdivision); | |
961 | 964 | glPopMatrix(); |
962 | 965 | } |
963 | 966 | // render edge as cylinder |
... | ... | @@ -1038,7 +1041,7 @@ namespace stim { |
1038 | 1041 | // mark the vertex |
1039 | 1042 | void mark_vertex() { |
1040 | 1043 | |
1041 | - glColor3f(1.0f, 1.0f, 1.0f); | |
1044 | + glColor3f(0.0f, 0.0f, 0.0f); | |
1042 | 1045 | for (unsigned i = 0; i < num_vertex; i++) { |
1043 | 1046 | glRasterPos3f(V[i][0], V[i][1] + get_radius(i), V[i][2]); |
1044 | 1047 | std::stringstream ss; |
... | ... | @@ -1137,7 +1140,7 @@ namespace stim { |
1137 | 1140 | |
1138 | 1141 | // build connection between all inlets and outlets |
1139 | 1142 | // connection will trail along one axis around the bounding box |
1140 | - void build_synthetic_connection(T viscosity, T radii = 5.0f) { | |
1143 | + void build_synthetic_connection(T viscosity, T radius = 5.0f) { | |
1141 | 1144 | |
1142 | 1145 | stim::vec3<T> L = bb.A; // get the bottom left corner |
1143 | 1146 | stim::vec3<T> U = bb.B; // get the top right corner |
... | ... | @@ -1162,7 +1165,7 @@ namespace stim { |
1162 | 1165 | tmp_b.v.push_back(input[i].first); |
1163 | 1166 | tmp_b.Q = input[i].third; |
1164 | 1167 | tmp_b.l = (bus_v - mid_v).len() + (mid_v - tmp_v).len(); |
1165 | - tmp_b.r = radii; | |
1168 | + tmp_b.r = radius; | |
1166 | 1169 | |
1167 | 1170 | inlet.push_back(tmp_b); |
1168 | 1171 | } |
... | ... | @@ -1182,19 +1185,206 @@ namespace stim { |
1182 | 1185 | tmp_b.v.push_back(output[i].first); |
1183 | 1186 | tmp_b.Q = output[i].third; |
1184 | 1187 | tmp_b.l = (bus_v - mid_v).len() + (mid_v - tmp_v).len(); |
1185 | - tmp_b.r = radii; | |
1188 | + tmp_b.r = radius; | |
1186 | 1189 | |
1187 | 1190 | outlet.push_back(tmp_b); |
1188 | 1191 | } |
1189 | 1192 | } |
1190 | 1193 | |
1194 | + // find the number of U-shape or square-shape structure for extending length of connection | |
1195 | + // @param t: width = t * radius | |
1196 | + int find_number_square(T origin_l, T desire_l, T radius = 5.0f, int times = 4) { | |
1197 | + | |
1198 | + bool done = false; // flag indicates the current number of square shape structure is feasible | |
1199 | + int n = origin_l / (times * 2 * radius); // number of square shape structure | |
1200 | + T need_l = desire_l - origin_l; | |
1201 | + T height; // height of the square shapce structure | |
1202 | + | |
1203 | + while (!done) { | |
1204 | + height = need_l / (2 * n); // calculate the height | |
1205 | + if (height > 2 * radius) { | |
1206 | + done = true; | |
1207 | + } | |
1208 | + else { | |
1209 | + n--; | |
1210 | + } | |
1211 | + } | |
1212 | + | |
1213 | + return n; | |
1214 | + } | |
1215 | + | |
1216 | + // build square connections | |
1217 | + 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) { | |
1218 | + | |
1219 | + int coef_up = (up) ? 1 : -1; // y coefficient | |
1220 | + int coef_left = (left) ? 1 : -1; // x coefficient | |
1221 | + int coef_z = (z) ? 1 : -1; // z coefficient | |
1222 | + int inverse = 1; // inverse flag | |
1223 | + stim::vec3<T> cor_v; // corner vertex | |
1224 | + | |
1225 | + stim::vec3<T> tmp_v; | |
1226 | + if (feeder == 1) | |
1227 | + tmp_v = inlet[i].V[0]; | |
1228 | + else if (feeder == 0) | |
1229 | + tmp_v = outlet[i].V[0]; | |
1230 | + | |
1231 | + // check whether the height of connections is acceptable | |
1232 | + if (height > threshold) { // acceptable | |
1233 | + // re-calculate height | |
1234 | + if (ratio > 0.0f && ratio <= 1.0f) { // use fragment if set | |
1235 | + cor_v = tmp_v + stim::vec3<T>(-coef_left * origin_l, 0, 0); // get the original corner vertex | |
1236 | + desire_l = desire_l - origin_l * (1.0f - ratio / 1.0f); | |
1237 | + origin_l = (T)origin_l * ratio / 1.0f; | |
1238 | + n = find_number_square(origin_l, desire_l); | |
1239 | + } | |
1240 | + height = (desire_l - (1 + 2 * n) * origin_l) / std::pow(2 * n, 2); | |
1241 | + // check whether the connections are good | |
1242 | + while (height > threshold) { | |
1243 | + n++; | |
1244 | + width = (T)(origin_l) / (2 * n); | |
1245 | + height = (desire_l - (1 + 2 * n) * origin_l) / std::pow(2 * n, 2); | |
1246 | + // check whether it appears overlap | |
1247 | + if (width < times * radius) { | |
1248 | + n--; | |
1249 | + width = (T)(origin_l) / (2 * n); | |
1250 | + height = (desire_l - (1 + 2 * n) * origin_l) / std::pow(2 * n, 2); | |
1251 | + break; | |
1252 | + } | |
1253 | + } | |
1254 | + while (height < times * radius) { | |
1255 | + n--; | |
1256 | + width = (T)(origin_l) / (2 * n); | |
1257 | + height = (desire_l - (1 + 2 * n) * origin_l) / std::pow(2 * n, 2); | |
1258 | + } | |
1259 | + | |
1260 | + // cube-like structure construction | |
1261 | + for (int j = 0; j < n; j++) { | |
1262 | + // "up" | |
1263 | + for (int k = 0; k < n; k++) { | |
1264 | + // in | |
1265 | + tmp_v = tmp_v + stim::vec3<T>(0, 0, coef_z * height); | |
1266 | + if (feeder == 1) | |
1267 | + inlet[i].V.push_back(tmp_v); | |
1268 | + else if (feeder == 0) | |
1269 | + outlet[i].V.push_back(tmp_v); | |
1270 | + // "up" | |
1271 | + tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); | |
1272 | + if (feeder == 1) | |
1273 | + inlet[i].V.push_back(tmp_v); | |
1274 | + else if (feeder == 0) | |
1275 | + outlet[i].V.push_back(tmp_v); | |
1276 | + // out | |
1277 | + tmp_v = tmp_v + stim::vec3<T>(0, 0, -coef_z * height); | |
1278 | + if (feeder == 1) | |
1279 | + inlet[i].V.push_back(tmp_v); | |
1280 | + else if (feeder == 0) | |
1281 | + outlet[i].V.push_back(tmp_v); | |
1282 | + // "down" | |
1283 | + tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); | |
1284 | + if (feeder == 1) | |
1285 | + inlet[i].V.push_back(tmp_v); | |
1286 | + else if (feeder == 0) | |
1287 | + outlet[i].V.push_back(tmp_v); | |
1288 | + } | |
1289 | + | |
1290 | + // "left" | |
1291 | + tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); | |
1292 | + if (feeder == 1) | |
1293 | + inlet[i].V.push_back(tmp_v); | |
1294 | + else if (feeder == 0) | |
1295 | + outlet[i].V.push_back(tmp_v); | |
1296 | + | |
1297 | + if (inverse == 1) // revert inverse | |
1298 | + inverse = -1; | |
1299 | + else | |
1300 | + inverse = 1; | |
1301 | + | |
1302 | + // "down" | |
1303 | + for (int k = 0; k < n; k++) { | |
1304 | + | |
1305 | + tmp_v = tmp_v + stim::vec3<T>(0, 0, coef_z * height); | |
1306 | + if (feeder == 1) | |
1307 | + inlet[i].V.push_back(tmp_v); | |
1308 | + else if (feeder == 0) | |
1309 | + outlet[i].V.push_back(tmp_v); | |
1310 | + | |
1311 | + tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); | |
1312 | + if (feeder == 1) | |
1313 | + inlet[i].V.push_back(tmp_v); | |
1314 | + else if (feeder == 0) | |
1315 | + outlet[i].V.push_back(tmp_v); | |
1316 | + | |
1317 | + tmp_v = tmp_v + stim::vec3<T>(0, 0, -coef_z * height); | |
1318 | + if (feeder == 1) | |
1319 | + inlet[i].V.push_back(tmp_v); | |
1320 | + else if (feeder == 0) | |
1321 | + outlet[i].V.push_back(tmp_v); | |
1322 | + | |
1323 | + tmp_v = tmp_v + stim::vec3<T>(0, inverse * coef_up * width, 0); | |
1324 | + if (feeder == 1) | |
1325 | + inlet[i].V.push_back(tmp_v); | |
1326 | + else if (feeder == 0) | |
1327 | + outlet[i].V.push_back(tmp_v); | |
1328 | + } | |
1329 | + | |
1330 | + // "left" | |
1331 | + tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); | |
1332 | + if (feeder == 1) | |
1333 | + inlet[i].V.push_back(tmp_v); | |
1334 | + else if (feeder == 0) | |
1335 | + outlet[i].V.push_back(tmp_v); | |
1336 | + | |
1337 | + if (inverse == 1) // revert inverse | |
1338 | + inverse = -1; | |
1339 | + else | |
1340 | + inverse = 1; | |
1341 | + } | |
1342 | + // if use fragment to do square wave connection, need to push_back the corner vertex | |
1343 | + if (ratio > 0.0f && ratio <= 1.0f) { | |
1344 | + if (feeder == 1) | |
1345 | + inlet[i].V.push_back(cor_v); | |
1346 | + else if (feeder == 0) | |
1347 | + outlet[i].V.push_back(cor_v); | |
1348 | + } | |
1349 | + } | |
1350 | + else { | |
1351 | + for (int j = 0; j < n; j++) { | |
1352 | + | |
1353 | + // move in Z-shape | |
1354 | + tmp_v = tmp_v + stim::vec3<T>(0, coef_up * height, 0); | |
1355 | + if (feeder == 1) | |
1356 | + inlet[i].V.push_back(tmp_v); | |
1357 | + else if (feeder == 0) | |
1358 | + outlet[i].V.push_back(tmp_v); | |
1359 | + | |
1360 | + tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); | |
1361 | + if (feeder == 1) | |
1362 | + inlet[i].V.push_back(tmp_v); | |
1363 | + else if (feeder == 0) | |
1364 | + outlet[i].V.push_back(tmp_v); | |
1365 | + | |
1366 | + tmp_v = tmp_v + stim::vec3<T>(0, -coef_up * height, 0); | |
1367 | + if (feeder == 1) | |
1368 | + inlet[i].V.push_back(tmp_v); | |
1369 | + else if (feeder == 0) | |
1370 | + outlet[i].V.push_back(tmp_v); | |
1371 | + | |
1372 | + tmp_v = tmp_v + stim::vec3<T>(-coef_left * width, 0, 0); | |
1373 | + if (feeder == 1) | |
1374 | + inlet[i].V.push_back(tmp_v); | |
1375 | + else if (feeder == 0) | |
1376 | + outlet[i].V.push_back(tmp_v); | |
1377 | + } | |
1378 | + } | |
1379 | + } | |
1380 | + | |
1191 | 1381 | // automatically modify bridge to make it feasible |
1192 | - void modify_synthetic_connection(T viscosity, T rou, T radii = 5.0f) { | |
1382 | + void modify_synthetic_connection(T viscosity, T rou, bool H, T threshold, T ratio = 0.0f, T radius = 5.0f) { | |
1193 | 1383 | |
1194 | 1384 | glDeleteLists(dlist, 1); // delete display list for modify |
1195 | 1385 | glDeleteLists(dlist + 1, 1); |
1196 | 1386 | |
1197 | - // because of radii change at the port vertex, there will be a pressure drop at that port | |
1387 | + // because of radius change at the port vertex, there will be a pressure drop at that port | |
1198 | 1388 | // it follows the bernoulli equation |
1199 | 1389 | // p1 + 1/2*rou*v1^2 + rou*g*h1 = p2 + 1/2*rou*v2^2 + rou*g*h2 |
1200 | 1390 | // Q1 = Q2 -> v1*r1^2 = v2*r2^2 |
... | ... | @@ -1203,7 +1393,7 @@ namespace stim { |
1203 | 1393 | for (unsigned i = 0; i < pendant_vertex.size(); i++) { |
1204 | 1394 | idx = pendant_vertex[i]; |
1205 | 1395 | T tmp_v = get_velocity(idx); // velocity at that pendant vertex |
1206 | - T ar = get_radius(idx) / radii; | |
1396 | + T ar = get_radius(idx) / radius; | |
1207 | 1397 | new_pressure[idx] = pressure[idx] + 1.0f / 2.0f * rou * std::pow(tmp_v, 2) * (1.0f - std::pow(ar, 4)); |
1208 | 1398 | } |
1209 | 1399 | |
... | ... | @@ -1213,217 +1403,302 @@ namespace stim { |
1213 | 1403 | unsigned inlet_index; |
1214 | 1404 | T tmp_p; |
1215 | 1405 | for (unsigned i = 0; i < inlet.size(); i++) { |
1216 | - tmp_p = new_pressure[inlet[i].v[0]] + ((8 * viscosity * inlet[i].l * inlet[i].Q) / ((float)stim::PI * std::pow(radii, 4))); | |
1406 | + tmp_p = new_pressure[inlet[i].v[0]] + ((8 * viscosity * inlet[i].l * inlet[i].Q) / ((float)stim::PI * std::pow(radius, 4))); | |
1217 | 1407 | if (tmp_p > source_pressure) { |
1218 | 1408 | source_pressure = tmp_p; |
1219 | 1409 | inlet_index = i; |
1220 | 1410 | } |
1221 | 1411 | } |
1222 | 1412 | |
1223 | - // automatically modify inlet bridge to make it feasible | |
1224 | - bool upper = false; // flag indicates the whether the port is upper than main feeder | |
1225 | - bool invert = false; // there are two version of hilbert curve depends on starting position with respect to the cup | |
1226 | - T new_l; | |
1227 | - stim::vec3<T> bus_v; // the port point on the bus | |
1228 | - stim::vec3<T> mid_v; // the original corner point | |
1229 | - stim::vec3<T> tmp_v; // the pendant point | |
1230 | - int order = 0; // order of hilbert curve (iteration) | |
1231 | - for (unsigned i = 0; i < inlet.size(); i++) { | |
1232 | - if (i != inlet_index) { | |
1233 | - new_l = (source_pressure - new_pressure[inlet[i].v[0]]) * ((float)stim::PI * std::pow(radii, 4)) / (8 * viscosity * inlet[i].Q); | |
1413 | + // find minimum pressure outlet port | |
1414 | + T end_pressure = FLT_MAX; | |
1415 | + unsigned outlet_index; | |
1416 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1417 | + tmp_p = new_pressure[outlet[i].v[0]] - ((8 * viscosity * outlet[i].l * outlet[i].Q) / ((float)stim::PI * std::pow(radius, 4))); | |
1418 | + if (tmp_p < end_pressure) { | |
1419 | + end_pressure = tmp_p; | |
1420 | + outlet_index = i; | |
1421 | + } | |
1422 | + } | |
1234 | 1423 | |
1235 | - if (inlet[i].V[2][1] > main_feeder[0][1]) { // check out upper side of lower side | |
1236 | - upper = true; | |
1237 | - invert = false; | |
1238 | - } | |
1239 | - else { | |
1240 | - upper = false; | |
1241 | - invert = true; | |
1242 | - } | |
1424 | + // automatically modify inlet bridge using Hilbert curves | |
1425 | + if (H) { | |
1426 | + bool upper = false; // flag indicates the whether the port is upper than main feeder | |
1427 | + bool invert = false; // there are two version of hilbert curve depends on starting position with respect to the cup | |
1428 | + T new_l; | |
1429 | + stim::vec3<T> bus_v; // the port point on the bus | |
1430 | + stim::vec3<T> mid_v; // the original corner point | |
1431 | + stim::vec3<T> tmp_v; // the pendant point | |
1432 | + int order = 0; // order of hilbert curve (iteration) | |
1433 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1434 | + if (i != inlet_index) { | |
1435 | + new_l = (source_pressure - new_pressure[inlet[i].v[0]]) * ((float)stim::PI * std::pow(radius, 4)) / (8 * viscosity * inlet[i].Q); | |
1243 | 1436 | |
1244 | - T origin_l = (inlet[i].V[1] - inlet[i].V[2]).len(); | |
1245 | - T desire_l = new_l - (inlet[i].V[0] - inlet[i].V[1]).len(); | |
1246 | - find_hilbert_order(origin_l, desire_l, order); | |
1247 | - | |
1248 | - bus_v = inlet[i].V[0]; | |
1249 | - mid_v = inlet[i].V[1]; | |
1250 | - tmp_v = inlet[i].V[2]; | |
1251 | - inlet[i].V.clear(); | |
1252 | - inlet[i].V.push_back(tmp_v); | |
1253 | - inlet[i].l = new_l; | |
1254 | - | |
1255 | - if (desire_l - origin_l < 2 * radii) { // do not need to use hilbert curve, just increase the length by draging out | |
1256 | - T d = new_l - inlet[i].l; | |
1257 | - stim::vec3<T> corner = stim::vec3<T>(tmp_v[0], tmp_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), tmp_v[2]); | |
1258 | - inlet[i].V.push_back(corner); | |
1259 | - corner = stim::vec3<T>(mid_v[0], mid_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), mid_v[2]); | |
1260 | - inlet[i].V.push_back(corner); | |
1261 | - inlet[i].V.push_back(bus_v); | |
1262 | - } | |
1263 | - else { | |
1264 | - T fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); // the length of the opening of cup | |
1265 | - T dl = fragment / (std::pow(2, order) - 1); // unit cup length | |
1266 | - | |
1267 | - if (dl > 2 * radii) { // if the radii is feasible | |
1268 | - if (upper) | |
1269 | - hilbert_curve(i, &tmp_v[0], order, dl, 1, invert, DOWN); | |
1270 | - else | |
1271 | - hilbert_curve(i, &tmp_v[0], order, dl, 1, invert, UP); | |
1272 | - | |
1273 | - if (tmp_v[0] != mid_v[0]) | |
1274 | - inlet[i].V.push_back(mid_v); | |
1437 | + if (inlet[i].V[2][1] > main_feeder[0][1]) { // check out upper side of lower side | |
1438 | + upper = true; | |
1439 | + invert = false; | |
1440 | + } | |
1441 | + else { | |
1442 | + upper = false; | |
1443 | + invert = true; | |
1444 | + } | |
1445 | + | |
1446 | + T origin_l = (inlet[i].V[1] - inlet[i].V[2]).len(); | |
1447 | + T desire_l = new_l - (inlet[i].V[0] - inlet[i].V[1]).len(); | |
1448 | + find_hilbert_order(origin_l, desire_l, order); | |
1449 | + | |
1450 | + bus_v = inlet[i].V[0]; | |
1451 | + mid_v = inlet[i].V[1]; | |
1452 | + tmp_v = inlet[i].V[2]; | |
1453 | + inlet[i].V.clear(); | |
1454 | + inlet[i].V.push_back(tmp_v); | |
1455 | + inlet[i].l = new_l; | |
1456 | + | |
1457 | + if (desire_l - origin_l < 2 * radius) { // do not need to use hilbert curve, just increase the length by draging out | |
1458 | + T d = new_l - inlet[i].l; | |
1459 | + stim::vec3<T> corner = stim::vec3<T>(tmp_v[0], tmp_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), tmp_v[2]); | |
1460 | + inlet[i].V.push_back(corner); | |
1461 | + corner = stim::vec3<T>(mid_v[0], mid_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), mid_v[2]); | |
1462 | + inlet[i].V.push_back(corner); | |
1275 | 1463 | inlet[i].V.push_back(bus_v); |
1276 | 1464 | } |
1277 | - else { // if the radii is not feasible | |
1278 | - int count = 1; | |
1279 | - while (dl <= 2 * radii) { | |
1280 | - dl = origin_l / (std::pow(2, order - count) - 1); | |
1281 | - count++; | |
1282 | - } | |
1283 | - count--; | |
1465 | + else { | |
1466 | + T fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); // the length of the opening of cup | |
1467 | + T dl = fragment / (std::pow(2, order) - 1); // unit cup length | |
1284 | 1468 | |
1285 | - if (upper) | |
1286 | - hilbert_curve(i, &tmp_v[0], order - count, dl, 1, invert, DOWN); | |
1287 | - else | |
1288 | - hilbert_curve(i, &tmp_v[0], order - count, dl, 1, invert, UP); | |
1469 | + if (dl > 2 * radius) { // if the radius is feasible | |
1470 | + if (upper) | |
1471 | + hilbert_curve(i, &tmp_v[0], order, dl, 1, invert, DOWN); | |
1472 | + else | |
1473 | + hilbert_curve(i, &tmp_v[0], order, dl, 1, invert, UP); | |
1289 | 1474 | |
1290 | - desire_l -= origin_l * ((std::pow(4, order - count) - 1) / (std::pow(2, order - count) - 1)); | |
1291 | - origin_l = (bus_v - mid_v).len(); | |
1292 | - desire_l += origin_l; | |
1475 | + if (tmp_v[0] != mid_v[0]) | |
1476 | + inlet[i].V.push_back(mid_v); | |
1477 | + inlet[i].V.push_back(bus_v); | |
1478 | + } | |
1479 | + else { // if the radius is not feasible | |
1480 | + int count = 1; | |
1481 | + while (dl <= 2 * radius) { | |
1482 | + dl = origin_l / (std::pow(2, order - count) - 1); | |
1483 | + count++; | |
1484 | + } | |
1485 | + count--; | |
1486 | + | |
1487 | + if (upper) | |
1488 | + hilbert_curve(i, &tmp_v[0], order - count, dl, 1, invert, DOWN); | |
1489 | + else | |
1490 | + hilbert_curve(i, &tmp_v[0], order - count, dl, 1, invert, UP); | |
1491 | + | |
1492 | + desire_l -= origin_l * ((std::pow(4, order - count) - 1) / (std::pow(2, order - count) - 1)); | |
1493 | + origin_l = (bus_v - mid_v).len(); | |
1494 | + desire_l += origin_l; | |
1495 | + | |
1496 | + find_hilbert_order(origin_l, desire_l, order); | |
1497 | + | |
1498 | + fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); | |
1499 | + dl = fragment / (std::pow(2, order) - 1); | |
1500 | + if (dl < 2 * radius) | |
1501 | + std::cout << "infeasible connection between inlets!" << std::endl; | |
1502 | + | |
1503 | + if (upper) | |
1504 | + hilbert_curve(i, &tmp_v[0], order, dl, 1, !invert, LEFT); | |
1505 | + else | |
1506 | + hilbert_curve(i, &tmp_v[0], order, dl, 1, !invert, RIGHT); | |
1507 | + | |
1508 | + if (tmp_v[1] != bus_v[1]) | |
1509 | + inlet[i].V.push_back(bus_v); | |
1510 | + } | |
1511 | + } | |
1512 | + std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex | |
1513 | + } | |
1514 | + } | |
1293 | 1515 | |
1294 | - find_hilbert_order(origin_l, desire_l, order); | |
1516 | + // automatically modify outlet bridge to make it feasible | |
1517 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1518 | + if (i != outlet_index) { | |
1519 | + new_l = (new_pressure[outlet[i].v[0]] - end_pressure) * ((float)stim::PI * std::pow(radius, 4)) / (8 * viscosity * outlet[i].Q); | |
1295 | 1520 | |
1296 | - fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); | |
1297 | - dl = fragment / (std::pow(2, order) - 1); | |
1298 | - if (dl < 2 * radii) | |
1299 | - std::cout << "infeasible connection between inlets!" << std::endl; | |
1521 | + if (outlet[i].V[2][1] > main_feeder[1][1]) { | |
1522 | + upper = true; | |
1523 | + invert = true; | |
1524 | + } | |
1525 | + else { | |
1526 | + upper = false; | |
1527 | + invert = false; | |
1528 | + } | |
1300 | 1529 | |
1301 | - if (upper) | |
1302 | - hilbert_curve(i, &tmp_v[0], order, dl, 1, !invert, LEFT); | |
1303 | - else | |
1304 | - hilbert_curve(i, &tmp_v[0], order, dl, 1, !invert, RIGHT); | |
1530 | + T origin_l = (outlet[i].V[1] - outlet[i].V[2]).len(); | |
1531 | + T desire_l = new_l - (outlet[i].V[0] - outlet[i].V[1]).len(); | |
1532 | + find_hilbert_order(origin_l, desire_l, order); | |
1533 | + | |
1534 | + bus_v = outlet[i].V[0]; | |
1535 | + mid_v = outlet[i].V[1]; | |
1536 | + tmp_v = outlet[i].V[2]; | |
1537 | + outlet[i].V.clear(); | |
1538 | + outlet[i].V.push_back(tmp_v); | |
1539 | + outlet[i].l = new_l; | |
1540 | + | |
1541 | + if (desire_l - origin_l < 2 * radius) { // do not need to use hilbert curve, just increase the length by draging out | |
1542 | + T d = new_l - outlet[i].l; | |
1543 | + stim::vec3<T> corner = stim::vec3<T>(tmp_v[0], tmp_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), tmp_v[2]); | |
1544 | + outlet[i].V.push_back(corner); | |
1545 | + corner = stim::vec3<T>(mid_v[0], mid_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), mid_v[2]); | |
1546 | + outlet[i].V.push_back(corner); | |
1547 | + outlet[i].V.push_back(bus_v); | |
1548 | + } | |
1549 | + else { | |
1550 | + T fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); // the length of the opening of cup | |
1551 | + T dl = fragment / (std::pow(2, order) - 1); // unit cup length | |
1305 | 1552 | |
1306 | - if (tmp_v[1] != bus_v[1]) | |
1307 | - inlet[i].V.push_back(bus_v); | |
1553 | + if (dl > 2 * radius) { // if the radius is feasible | |
1554 | + if (upper) | |
1555 | + hilbert_curve(i, &tmp_v[0], order, dl, 0, invert, DOWN); | |
1556 | + else | |
1557 | + hilbert_curve(i, &tmp_v[0], order, dl, 0, invert, UP); | |
1558 | + | |
1559 | + if (tmp_v[0] != mid_v[0]) | |
1560 | + outlet[i].V.push_back(mid_v); | |
1561 | + outlet[i].V.push_back(bus_v); | |
1562 | + } | |
1563 | + else { // if the radius is not feasible | |
1564 | + int count = 1; | |
1565 | + while (dl <= 2 * radius) { | |
1566 | + dl = origin_l / (std::pow(2, order - count) - 1); | |
1567 | + count++; | |
1568 | + } | |
1569 | + count--; | |
1570 | + | |
1571 | + if (upper) | |
1572 | + hilbert_curve(i, &tmp_v[0], order - count, dl, 0, invert, DOWN); | |
1573 | + else | |
1574 | + hilbert_curve(i, &tmp_v[0], order - count, dl, 0, invert, UP); | |
1575 | + | |
1576 | + desire_l -= origin_l * ((std::pow(4, order - count) - 1) / (std::pow(2, order - count) - 1)); | |
1577 | + origin_l = (bus_v - mid_v).len(); | |
1578 | + desire_l += origin_l; | |
1579 | + | |
1580 | + find_hilbert_order(origin_l, desire_l, order); | |
1581 | + | |
1582 | + fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); | |
1583 | + dl = fragment / (std::pow(2, order) - 1); | |
1584 | + if (dl < 2 * radius) | |
1585 | + std::cout << "infeasible connection between outlets!" << std::endl; | |
1586 | + | |
1587 | + if (upper) | |
1588 | + hilbert_curve(i, &tmp_v[0], order, dl, 0, !invert, LEFT); | |
1589 | + else | |
1590 | + hilbert_curve(i, &tmp_v[0], order, dl, 0, !invert, RIGHT); | |
1591 | + | |
1592 | + if (tmp_v[1] != bus_v[1]) | |
1593 | + outlet[i].V.push_back(bus_v); | |
1594 | + } | |
1308 | 1595 | } |
1596 | + std::reverse(outlet[i].V.begin(), outlet[i].V.end()); | |
1309 | 1597 | } |
1310 | - std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex | |
1311 | 1598 | } |
1312 | 1599 | } |
1600 | + // automatically modify inlet bridge using square shape constructions | |
1601 | + else { | |
1602 | + bool upper; // flag indicates the connection is upper than the bus | |
1603 | + bool z; // flag indicates the connection direction along z-axis | |
1604 | + T new_l; // new length | |
1605 | + stim::vec3<T> bus_v; // the port point on the bus | |
1606 | + stim::vec3<T> mid_v; // the original corner point | |
1607 | + stim::vec3<T> tmp_v; // the pendant point | |
1608 | + int n; | |
1609 | + T width, height; // width and height of the square | |
1313 | 1610 | |
1314 | - // find minimum pressure outlet port | |
1315 | - source_pressure = FLT_MAX; | |
1316 | - unsigned outlet_index; | |
1317 | - for (unsigned i = 0; i < outlet.size(); i++) { | |
1318 | - tmp_p = new_pressure[outlet[i].v[0]] - ((8 * viscosity * outlet[i].l * outlet[i].Q) / ((float)stim::PI * std::pow(radii, 4))); | |
1319 | - if (tmp_p < source_pressure) { | |
1320 | - source_pressure = tmp_p; | |
1321 | - outlet_index = i; | |
1322 | - } | |
1323 | - } | |
1611 | + for (unsigned i = 0; i < inlet.size(); i++) { | |
1612 | + if (i != inlet_index) { | |
1613 | + new_l = (source_pressure - new_pressure[inlet[i].v[0]]) * ((float)stim::PI * std::pow(radius, 4)) / (8 * viscosity * inlet[i].Q); // calculate the new length of the connection | |
1324 | 1614 | |
1325 | - // automatically modify outlet bridge to make it feasible | |
1326 | - for (unsigned i = 0; i < outlet.size(); i++) { | |
1327 | - if (i != outlet_index) { | |
1328 | - new_l = (new_pressure[outlet[i].v[0]] - source_pressure) * ((float)stim::PI * std::pow(radii, 4)) / (8 * viscosity * outlet[i].Q); | |
1615 | + bus_v = inlet[i].V[0]; | |
1616 | + mid_v = inlet[i].V[1]; | |
1617 | + tmp_v = inlet[i].V[2]; | |
1329 | 1618 | |
1330 | - if (outlet[i].V[2][1] > main_feeder[1][1]) { | |
1331 | - upper = true; | |
1332 | - invert = true; | |
1333 | - } | |
1334 | - else { | |
1335 | - upper = false; | |
1336 | - invert = false; | |
1337 | - } | |
1619 | + if (inlet[i].V[2][1] > main_feeder[0][1]) // check out upper side of lower side | |
1620 | + upper = true; | |
1621 | + else | |
1622 | + upper = false; | |
1338 | 1623 | |
1339 | - T origin_l = (outlet[i].V[1] - outlet[i].V[2]).len(); | |
1340 | - T desire_l = new_l - (outlet[i].V[0] - outlet[i].V[1]).len(); | |
1341 | - find_hilbert_order(origin_l, desire_l, order); | |
1342 | - | |
1343 | - bus_v = outlet[i].V[0]; | |
1344 | - mid_v = outlet[i].V[1]; | |
1345 | - tmp_v = outlet[i].V[2]; | |
1346 | - outlet[i].V.clear(); | |
1347 | - outlet[i].V.push_back(tmp_v); | |
1348 | - outlet[i].l = new_l; | |
1349 | - | |
1350 | - if (desire_l - origin_l < 2 * radii) { // do not need to use hilbert curve, just increase the length by draging out | |
1351 | - T d = new_l - outlet[i].l; | |
1352 | - stim::vec3<T> corner = stim::vec3<T>(tmp_v[0], tmp_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), tmp_v[2]); | |
1353 | - outlet[i].V.push_back(corner); | |
1354 | - corner = stim::vec3<T>(mid_v[0], mid_v[1] + d / 2.0f * (tmp_v[1] > main_feeder[0][1] ? 1 : -1), mid_v[2]); | |
1355 | - outlet[i].V.push_back(corner); | |
1356 | - outlet[i].V.push_back(bus_v); | |
1624 | + if (inlet[i].V[2][2] > main_feeder[0][2]) | |
1625 | + z = true; | |
1626 | + else | |
1627 | + z = false; | |
1628 | + | |
1629 | + T origin_l = (inlet[i].V[1] - inlet[i].V[2]).len(); | |
1630 | + T desire_l = new_l - (inlet[i].V[0] - inlet[i].V[1]).len(); | |
1631 | + inlet[i].V.clear(); | |
1632 | + inlet[i].V.push_back(tmp_v); | |
1633 | + inlet[i].l = new_l; | |
1634 | + | |
1635 | + n = find_number_square(origin_l, desire_l); | |
1636 | + | |
1637 | + width = (T)origin_l / (2 * n); | |
1638 | + height = (desire_l - origin_l) / (2 * n); | |
1639 | + | |
1640 | + build_square_connection(i, width, height, origin_l, desire_l, n, 1, threshold, z, true, upper, 10, ratio); | |
1641 | + inlet[i].V.push_back(bus_v); | |
1642 | + | |
1643 | + std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex | |
1357 | 1644 | } |
1358 | - else { | |
1359 | - T fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); // the length of the opening of cup | |
1360 | - T dl = fragment / (std::pow(2, order) - 1); // unit cup length | |
1361 | - | |
1362 | - if (dl > 2 * radii) { // if the radii is feasible | |
1363 | - if (upper) | |
1364 | - hilbert_curve(i, &tmp_v[0], order, dl, 0, invert, DOWN); | |
1365 | - else | |
1366 | - hilbert_curve(i, &tmp_v[0], order, dl, 0, invert, UP); | |
1367 | - | |
1368 | - if (tmp_v[0] != mid_v[0]) | |
1369 | - outlet[i].V.push_back(mid_v); | |
1370 | - outlet[i].V.push_back(bus_v); | |
1371 | - } | |
1372 | - else { // if the radii is not feasible | |
1373 | - int count = 1; | |
1374 | - while (dl <= 2 * radii) { | |
1375 | - dl = origin_l / (std::pow(2, order - count) - 1); | |
1376 | - count++; | |
1377 | - } | |
1378 | - count--; | |
1645 | + } | |
1646 | + | |
1647 | + for (unsigned i = 0; i < outlet.size(); i++) { | |
1648 | + if (i != outlet_index) { | |
1649 | + new_l = (new_pressure[outlet[i].v[0]] - end_pressure) * ((float)stim::PI * std::pow(radius, 4)) / (8 * viscosity * outlet[i].Q); // calculate the new length of the connection | |
1379 | 1650 | |
1380 | - if (upper) | |
1381 | - hilbert_curve(i, &tmp_v[0], order - count, dl, 0, invert, DOWN); | |
1382 | - else | |
1383 | - hilbert_curve(i, &tmp_v[0], order - count, dl, 0, invert, UP); | |
1651 | + bus_v = outlet[i].V[0]; | |
1652 | + mid_v = outlet[i].V[1]; | |
1653 | + tmp_v = outlet[i].V[2]; | |
1384 | 1654 | |
1385 | - desire_l -= origin_l * ((std::pow(4, order - count) - 1) / (std::pow(2, order - count) - 1)); | |
1386 | - origin_l = (bus_v - mid_v).len(); | |
1387 | - desire_l += origin_l; | |
1655 | + if (outlet[i].V[2][1] > main_feeder[1][1]) // check out upper side of lower side | |
1656 | + upper = true; | |
1657 | + else | |
1658 | + upper = false; | |
1388 | 1659 | |
1389 | - find_hilbert_order(origin_l, desire_l, order); | |
1660 | + if (outlet[i].V[2][2] > main_feeder[1][2]) | |
1661 | + z = true; | |
1662 | + else | |
1663 | + z = false; | |
1390 | 1664 | |
1391 | - fragment = (desire_l - origin_l) / ((std::pow(4, order) - 1) / (std::pow(2, order) - 1) - 1); | |
1392 | - dl = fragment / (std::pow(2, order) - 1); | |
1393 | - if (dl < 2 * radii) | |
1394 | - std::cout << "infeasible connection between outlets!" << std::endl; | |
1665 | + T origin_l = (outlet[i].V[1] - outlet[i].V[2]).len(); | |
1666 | + T desire_l = new_l - (outlet[i].V[0] - outlet[i].V[1]).len(); | |
1667 | + outlet[i].V.clear(); | |
1668 | + outlet[i].V.push_back(tmp_v); | |
1669 | + outlet[i].l = new_l; | |
1395 | 1670 | |
1396 | - if (upper) | |
1397 | - hilbert_curve(i, &tmp_v[0], order, dl, 0, !invert, LEFT); | |
1398 | - else | |
1399 | - hilbert_curve(i, &tmp_v[0], order, dl, 0, !invert, RIGHT); | |
1671 | + n = find_number_square(origin_l, desire_l); | |
1400 | 1672 | |
1401 | - if (tmp_v[1] != bus_v[1]) | |
1402 | - outlet[i].V.push_back(bus_v); | |
1403 | - } | |
1673 | + width = (T)origin_l / (2 * n); | |
1674 | + height = (desire_l - origin_l) / (2 * n); | |
1675 | + | |
1676 | + build_square_connection(i, width, height, origin_l, desire_l, n, 0, threshold, z, false, upper, 10, ratio); | |
1677 | + outlet[i].V.push_back(bus_v); | |
1678 | + | |
1679 | + std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex | |
1404 | 1680 | } |
1405 | - std::reverse(outlet[i].V.begin(), outlet[i].V.end()); | |
1406 | 1681 | } |
1407 | 1682 | } |
1408 | 1683 | } |
1409 | 1684 | |
1410 | 1685 | // check current bridge to see feasibility |
1411 | - void check_synthetic_connection(T viscosity, T radii = 5.0f) { | |
1686 | + void check_synthetic_connection(T viscosity, T radius = 5.0f) { | |
1412 | 1687 | |
1413 | 1688 | T eps = 0.01f; |
1414 | - T source_pressure = pressure[inlet[0].v[0]] + (8 * viscosity * inlet[0].l * inlet[0].Q) / ((float)stim::PI * std::pow(radii, 4)); | |
1689 | + T source_pressure = pressure[inlet[0].v[0]] + (8 * viscosity * inlet[0].l * inlet[0].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1415 | 1690 | T tmp_p; |
1416 | 1691 | for (unsigned i = 1; i < inlet.size(); i++) { |
1417 | - tmp_p = pressure[inlet[i].v[0]] + (8 * viscosity * inlet[i].l * inlet[i].Q) / ((float)stim::PI * std::pow(radii, 4)); | |
1692 | + tmp_p = pressure[inlet[i].v[0]] + (8 * viscosity * inlet[i].l * inlet[i].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1418 | 1693 | T delta = fabs(tmp_p - source_pressure); |
1419 | 1694 | if (delta > eps) { |
1420 | 1695 | std::cout << "Nonfeasible connection!" << std::endl; |
1421 | 1696 | break; |
1422 | 1697 | } |
1423 | 1698 | } |
1424 | - source_pressure = pressure[outlet[0].v[0]] - (8 * viscosity * outlet[0].l * outlet[0].Q) / ((float)stim::PI * std::pow(radii, 4)); | |
1699 | + source_pressure = pressure[outlet[0].v[0]] - (8 * viscosity * outlet[0].l * outlet[0].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1425 | 1700 | for (unsigned i = 1; i < outlet.size(); i++) { |
1426 | - tmp_p = pressure[outlet[i].v[0]] - (8 * viscosity * outlet[i].l * outlet[i].Q) / ((float)stim::PI * std::pow(radii, 4)); | |
1701 | + tmp_p = pressure[outlet[i].v[0]] - (8 * viscosity * outlet[i].l * outlet[i].Q) / ((float)stim::PI * std::pow(radius, 4)); | |
1427 | 1702 | T delta = fabs(tmp_p - source_pressure); |
1428 | 1703 | if (delta > eps) { |
1429 | 1704 | std::cout << "Nonfeasible connection!" << std::endl; |
... | ... | @@ -1436,7 +1711,7 @@ namespace stim { |
1436 | 1711 | // prepare for image stack |
1437 | 1712 | void preparation(T &Xl, T &Xr, T &Yt, T &Yb, T &Z, T length = 210.0f, T height = 10.0f) { |
1438 | 1713 | |
1439 | - T max_radii = 0.0f; | |
1714 | + T max_radius = 0.0f; | |
1440 | 1715 | T top = FLT_MIN; |
1441 | 1716 | T bottom = FLT_MAX; |
1442 | 1717 | |
... | ... | @@ -1519,17 +1794,17 @@ namespace stim { |
1519 | 1794 | top = A[i].c[1]; |
1520 | 1795 | if (A[i].c[1] < bottom) |
1521 | 1796 | bottom = A[i].c[1]; |
1522 | - if (A[i].r > max_radii) | |
1523 | - max_radii = A[i].r; | |
1797 | + if (A[i].r > max_radius) | |
1798 | + max_radius = A[i].r; | |
1524 | 1799 | } |
1525 | 1800 | |
1526 | 1801 | Yt = top; // top bound y coordinate |
1527 | 1802 | Yb = bottom; // bottom bound y coordinate |
1528 | - Z = (bb.B[2] - bb.A[2] + 2 * max_radii); // bounding box width(along z-axis) | |
1803 | + Z = (bb.B[2] - bb.A[2] + 2 * max_radius); // bounding box width(along z-axis) | |
1529 | 1804 | } |
1530 | 1805 | |
1531 | 1806 | /// making image stack main function |
1532 | - void make_image_stack(T dx, T dy, T dz, std::string stackdir, T radii = 5.0f) { | |
1807 | + void make_image_stack(T dx, T dy, T dz, std::string stackdir, T radius = 5.0f) { | |
1533 | 1808 | |
1534 | 1809 | /// preparation for making image stack |
1535 | 1810 | T X, Xl, Xr, Y, Yt, Yb, Z; | ... | ... |
main.cu
... | ... | @@ -54,10 +54,12 @@ float zoom_factor = 10.0f; // zooming factor |
54 | 54 | float border_factor = 20.0f; // border |
55 | 55 | float radii_factor = 1.0f; // radii changing factor |
56 | 56 | GLint subdivision = 20; // slices and stacks |
57 | -float default_radii = 5.0f; // default radii of network vertex | |
57 | +float default_radius = 5.0f; // default radii of network vertex | |
58 | 58 | float delta = 0.01f; // small discrepancy |
59 | 59 | float eps = 20.0f; // epsilon threshold |
60 | 60 | float max_pressure = 0.0f; // maximum pressure that the channel can bear |
61 | +float height_threshold = 100.0f; // connection height constraint | |
62 | +float fragment_ratio = 0.0f; // fragment ratio | |
61 | 63 | |
62 | 64 | // glut event parameters |
63 | 65 | int mouse_x; // window x-coordinate |
... | ... | @@ -73,6 +75,8 @@ unsigned pressure_index; // the index of vertex that is clicked |
73 | 75 | // build inlet/outlet parameters |
74 | 76 | bool build_inlet_outlet = false; // flag indicates building inlets and outlets |
75 | 77 | bool modified_bridge = false; // flag indicates having modified inlet/outlet connection |
78 | +bool hilbert_curve = false; // flag indicates enabling hilbert curves constructions | |
79 | +bool change_fragment = false; // flag indicates changing fragment for square wave connections | |
76 | 80 | |
77 | 81 | // manufacture parameters |
78 | 82 | bool manufacture = false; // flag indicates manufacture mode |
... | ... | @@ -89,7 +93,7 @@ inline void get_background() { |
89 | 93 | // set the initial radii |
90 | 94 | flow.init(num_edge, num_vertex); // initialize flow object |
91 | 95 | for (unsigned i = 0; i < num_edge; i++) |
92 | - flow.set_r(i, default_radii); | |
96 | + flow.set_r(i, default_radius); | |
93 | 97 | } |
94 | 98 | |
95 | 99 | // convert from window coordinates to world coordinates |
... | ... | @@ -116,6 +120,7 @@ inline void window_to_world(GLdouble &x, GLdouble &y, GLdouble &z) { |
116 | 120 | // initialize flow object |
117 | 121 | void flow_initialize() { |
118 | 122 | |
123 | + flow.set = true; | |
119 | 124 | stim::vec3<float> center = bb.center(); |
120 | 125 | |
121 | 126 | for (unsigned i = 0; i < pendant_vertex.size(); i++) { |
... | ... | @@ -187,6 +192,7 @@ void glut_render() { |
187 | 192 | |
188 | 193 | glEnable(GL_DEPTH_TEST); |
189 | 194 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
195 | + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); | |
190 | 196 | glut_projection(); |
191 | 197 | glut_modelview(); |
192 | 198 | |
... | ... | @@ -238,7 +244,7 @@ void glut_render() { |
238 | 244 | glFlush(); |
239 | 245 | |
240 | 246 | // pressure bar text |
241 | - glColor3f(1.0f, 1.0f, 1.0f); | |
247 | + glColor3f(0.0f, 0.0f, 0.0f); | |
242 | 248 | glRasterPos2f(0.0f, vY - border_factor); |
243 | 249 | std::stringstream ss_p; |
244 | 250 | ss_p << "Pressure Bar"; |
... | ... | @@ -251,7 +257,7 @@ void glut_render() { |
251 | 257 | glRasterPos2f((border_factor * 1.5f), (border_factor + i * step)); |
252 | 258 | std::stringstream ss_n; |
253 | 259 | ss_n << (float)i * max_pressure / 10; |
254 | - glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_10, (const unsigned char*)(ss_n.str().c_str())); | |
260 | + glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss_n.str().c_str())); | |
255 | 261 | } |
256 | 262 | glPopMatrix(); |
257 | 263 | glMatrixMode(GL_PROJECTION); |
... | ... | @@ -286,7 +292,7 @@ void glut_render() { |
286 | 292 | glFlush(); |
287 | 293 | |
288 | 294 | // pressure bar text |
289 | - glColor3f(1.0f, 1.0f, 1.0f); | |
295 | + glColor3f(0.0f, 0.0f, 0.0f); | |
290 | 296 | glRasterPos2f(0.0f, vY - border_factor); |
291 | 297 | std::stringstream ss_p; |
292 | 298 | ss_p << "Velocity range"; |
... | ... | @@ -299,13 +305,58 @@ void glut_render() { |
299 | 305 | glRasterPos2f(border_factor * 1.5f, border_factor + i * step); |
300 | 306 | std::stringstream ss_n; |
301 | 307 | ss_n << min_v + i * (max_v - min_v) / 10; |
302 | - glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_10, (const unsigned char*)(ss_n.str().c_str())); | |
308 | + glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss_n.str().c_str())); | |
303 | 309 | } |
304 | 310 | glPopMatrix(); |
305 | 311 | glMatrixMode(GL_PROJECTION); |
306 | 312 | glPopMatrix(); |
307 | 313 | } |
308 | - | |
314 | + | |
315 | + // bring up a ratio bar on the left | |
316 | + if (change_fragment) { | |
317 | + | |
318 | + glMatrixMode(GL_PROJECTION); // set up the 2d viewport for mode text printing | |
319 | + glPushMatrix(); | |
320 | + glLoadIdentity(); | |
321 | + vX = glutGet(GLUT_WINDOW_WIDTH); // get the current window width | |
322 | + vY = glutGet(GLUT_WINDOW_HEIGHT); // get the current window height | |
323 | + glViewport(0, 0, vX, vY); // locate to left bottom corner | |
324 | + gluOrtho2D(0, vX, 0, vY); // define othogonal aspect | |
325 | + | |
326 | + glMatrixMode(GL_MODELVIEW); | |
327 | + glPushMatrix(); | |
328 | + glLoadIdentity(); | |
329 | + | |
330 | + glLineWidth(border_factor); | |
331 | + glBegin(GL_LINES); | |
332 | + glColor3f(0.0, 0.0, 1.0); // blue to red | |
333 | + glVertex2f(border_factor, border_factor); | |
334 | + glColor3f(1.0, 0.0, 0.0); | |
335 | + glVertex2f(border_factor, (vY - 2.0f * border_factor)); | |
336 | + glEnd(); | |
337 | + glFlush(); | |
338 | + | |
339 | + // pressure bar text | |
340 | + glColor3f(0.0f, 0.0f, 0.0f); | |
341 | + glRasterPos2f(0.0f, vY - border_factor); | |
342 | + std::stringstream ss_p; | |
343 | + ss_p << "Ratio bar"; | |
344 | + glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss_p.str().c_str())); | |
345 | + | |
346 | + // pressure range text | |
347 | + float step = vY - 3.0f * border_factor; | |
348 | + step /= 10; | |
349 | + for (unsigned i = 0; i < 11; i++) { | |
350 | + glRasterPos2f((border_factor * 1.5f), (border_factor + i * step)); | |
351 | + std::stringstream ss_n; | |
352 | + ss_n << (float)i * 1.0f / 10; | |
353 | + glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*)(ss_n.str().c_str())); | |
354 | + } | |
355 | + glPopMatrix(); | |
356 | + glMatrixMode(GL_PROJECTION); | |
357 | + glPopMatrix(); | |
358 | + } | |
359 | + | |
309 | 360 | glutSwapBuffers(); |
310 | 361 | } |
311 | 362 | |
... | ... | @@ -318,7 +369,8 @@ void glut_menu(int value) { |
318 | 369 | build_inlet_outlet = false; |
319 | 370 | manufacture = false; |
320 | 371 | modified_bridge = false; |
321 | - flow_initialize(); | |
372 | + if (!flow.set) | |
373 | + flow_initialize(); | |
322 | 374 | flow_stable_state(); // main function of solving the linear system |
323 | 375 | flow.print_flow(); |
324 | 376 | |
... | ... | @@ -331,7 +383,7 @@ void glut_menu(int value) { |
331 | 383 | manufacture = false; |
332 | 384 | if (!modified_bridge) { |
333 | 385 | flow.set_main_feeder(); |
334 | - flow.build_synthetic_connection(u); | |
386 | + flow.build_synthetic_connection(u, default_radius); | |
335 | 387 | } |
336 | 388 | |
337 | 389 | glut_set_menu(num, 3); |
... | ... | @@ -341,7 +393,7 @@ void glut_menu(int value) { |
341 | 393 | simulation = false; |
342 | 394 | build_inlet_outlet = false; |
343 | 395 | manufacture = true; |
344 | - flow.check_synthetic_connection(u); | |
396 | + flow.check_synthetic_connection(u, default_radius); | |
345 | 397 | } |
346 | 398 | |
347 | 399 | glutPostRedisplay(); |
... | ... | @@ -396,6 +448,13 @@ void glut_mouse(int button, int state, int x, int y) { |
396 | 448 | flow.print_flow(); |
397 | 449 | } |
398 | 450 | } |
451 | + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && modified_bridge && change_fragment) { | |
452 | + if (y > 2 * border_factor || y < vY - border_factor) { // within the ratio bar range | |
453 | + fragment_ratio = (float)(vY - y - border_factor) / ((float)vY - border_factor) * 1.0f; | |
454 | + flow.modify_synthetic_connection(u, rou, hilbert_curve, height_threshold, fragment_ratio, default_radius); | |
455 | + change_fragment = false; | |
456 | + } | |
457 | + } | |
399 | 458 | } |
400 | 459 | |
401 | 460 | // define camera move based on mouse wheel move |
... | ... | @@ -419,7 +478,7 @@ void glut_wheel(int wheel, int direction, int x, int y) { |
419 | 478 | tmp_r = flow.get_radius(pressure_index); |
420 | 479 | tmp_r -= radii_factor; |
421 | 480 | if (tmp_r <= 0) |
422 | - tmp_r = default_radii; | |
481 | + tmp_r = default_radius; | |
423 | 482 | } |
424 | 483 | flow.set_radius(pressure_index, tmp_r); |
425 | 484 | flow_stable_state(); |
... | ... | @@ -464,12 +523,16 @@ void glut_keyboard(unsigned char key, int x, int y) { |
464 | 523 | #endif |
465 | 524 | } |
466 | 525 | else if (build_inlet_outlet && !modified_bridge) { |
467 | - flow.modify_synthetic_connection(u, rou); | |
468 | 526 | modified_bridge = true; |
527 | + | |
528 | + if (hilbert_curve) | |
529 | + flow.modify_synthetic_connection(u, rou, hilbert_curve, height_threshold); | |
530 | + else | |
531 | + change_fragment = true; | |
469 | 532 | } |
470 | 533 | break; |
471 | 534 | } |
472 | - | |
535 | + | |
473 | 536 | glutPostRedisplay(); |
474 | 537 | } |
475 | 538 | |
... | ... | @@ -510,6 +573,7 @@ int main(int argc, char* argv[]) { |
510 | 573 | args.add("maxpress", "maximum allowed pressure in g / units / s^2, default 2 is for blood when units = um", "2", "real value > 0"); |
511 | 574 | args.add("viscosity", "set the viscosity of the fluid (in g / units / s), default .00001 is for blood when units = um", ".00001", "real value > 0"); |
512 | 575 | args.add("rou", "set the desity of the fluid (in g / units^3), default 1.06*10^-12 is for blood when units = um", ".00000000000106", "real value > 0"); |
576 | + args.add("hilbert", "enable hilbert curves connections", "0", "value 1 for enablement"); | |
513 | 577 | args.add("stackres", "spacing between pixel samples in each dimension(in units/pixel)", "1 1 1", "real value > 0"); |
514 | 578 | args.add("stackdir", "set the directory of the output image stack", "", "any existing directory (ex. /home/name/network)"); |
515 | 579 | |
... | ... | @@ -540,6 +604,9 @@ int main(int argc, char* argv[]) { |
540 | 604 | // normally the blood density in capillaries: 1060 kg/m^3 = 1.06*10^-12 g/um^3 |
541 | 605 | rou = args["rou"].as_float(); |
542 | 606 | |
607 | + // check whether to enable hilbert curves or not | |
608 | + hilbert_curve = args["hilbert"].as_int(); | |
609 | + | |
543 | 610 | // get the vexel and image stack size |
544 | 611 | dx = args["stackres"].as_float(0); |
545 | 612 | dy = args["stackres"].as_float(1); | ... | ... |