Commit 9e60c6a754f8cefc11dfc2cb509b6274405c4f17
1 parent
8334680a
fixed minor bug in edge detection
Showing
2 changed files
with
328 additions
and
61 deletions
Show diff stats
@@ -331,6 +331,11 @@ namespace stim { | @@ -331,6 +331,11 @@ namespace stim { | ||
331 | return E[tmp_e].r(tmp_v); | 331 | return E[tmp_e].r(tmp_v); |
332 | } | 332 | } |
333 | 333 | ||
334 | + // get the radius of index j of edge i | ||
335 | + T get_radius(unsigned i, unsigned j) { | ||
336 | + return E[i].r(j); | ||
337 | + } | ||
338 | + | ||
334 | // get the velocity of pendant vertex i | 339 | // get the velocity of pendant vertex i |
335 | T get_velocity(unsigned i) { | 340 | T get_velocity(unsigned i) { |
336 | 341 | ||
@@ -495,6 +500,7 @@ namespace stim { | @@ -495,6 +500,7 @@ namespace stim { | ||
495 | order = o; | 500 | order = o; |
496 | } | 501 | } |
497 | 502 | ||
503 | + // move hilbert curves | ||
498 | void move(unsigned i, T *c, direction dir, T dl, int feeder, bool invert) { | 504 | void move(unsigned i, T *c, direction dir, T dl, int feeder, bool invert) { |
499 | 505 | ||
500 | int cof = (invert) ? -1 : 1; | 506 | int cof = (invert) ? -1 : 1; |
@@ -524,6 +530,7 @@ namespace stim { | @@ -524,6 +530,7 @@ namespace stim { | ||
524 | outlet[i].V.push_back(tmp); | 530 | outlet[i].V.push_back(tmp); |
525 | } | 531 | } |
526 | 532 | ||
533 | + // form hilbert curves | ||
527 | void hilbert_curve(unsigned i, T *c, int order, T dl, int feeder, bool invert, direction dir = DOWN) { | 534 | void hilbert_curve(unsigned i, T *c, int order, T dl, int feeder, bool invert, direction dir = DOWN) { |
528 | 535 | ||
529 | if (order == 1) { | 536 | if (order == 1) { |
@@ -727,51 +734,84 @@ namespace stim { | @@ -727,51 +734,84 @@ namespace stim { | ||
727 | 734 | ||
728 | // waste? | 735 | // waste? |
729 | for (unsigned i = 0; i < num_edge; i++) { | 736 | for (unsigned i = 0; i < num_edge; i++) { |
730 | - for (unsigned j = 0; j < E[i].size(); j++) { | ||
731 | - if (j == 0) { // for start vertex | ||
732 | - if (P[E[i].v[0]] != 0) { | ||
733 | - stim::vec3<float> new_color; | ||
734 | - new_color[0] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[0]] / max_pressure; // red | ||
735 | - new_color[1] = 0.0f; // green | ||
736 | - new_color[2] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[0]] / max_pressure - 0.5f) : 1.0f; // blue | ||
737 | - glColor3f(new_color[0], new_color[1], new_color[2]); | ||
738 | - } | ||
739 | - } | ||
740 | - else if (j == E[i].size() - 1) { // for end vertex | ||
741 | - if (P[E[i].v[1]] != 0) { | ||
742 | - stim::vec3<float> new_color; | ||
743 | - new_color[0] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[1]] / max_pressure; // red | ||
744 | - new_color[1] = 0.0f; // green | ||
745 | - new_color[2] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[1]] / max_pressure - 0.5f) : 1.0f; // blue | ||
746 | - glColor3f(new_color[0], new_color[1], new_color[2]); | ||
747 | - } | ||
748 | - } | ||
749 | - else | ||
750 | - glColor3f(0.5f, 0.5f, 0.5f); // gray point | 737 | + // draw the starting vertex |
738 | + if (P[E[i].v[0]] != 0) { | ||
739 | + stim::vec3<float> new_color; | ||
740 | + new_color[0] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[0]] / max_pressure; // red | ||
741 | + new_color[1] = 0.0f; // green | ||
742 | + new_color[2] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[0]] / max_pressure - 0.5f) : 1.0f; // blue | ||
743 | + glColor3f(new_color[0], new_color[1], new_color[2]); | ||
751 | 744 | ||
752 | glPushMatrix(); | 745 | glPushMatrix(); |
753 | - glTranslatef(E[i][j][0], E[i][j][1], E[i][j][2]); | ||
754 | - glutSolidSphere(get_r(i, j), subdivision, subdivision); | 746 | + glTranslatef(E[i][0][0], E[i][0][1], E[i][0][2]); |
747 | + glutSolidSphere(get_r(i, 0), subdivision, subdivision); | ||
755 | glPopMatrix(); | 748 | glPopMatrix(); |
756 | } | 749 | } |
750 | + | ||
751 | + // draw the ending vertex | ||
752 | + if (P[E[i].v[1]] != 0) { | ||
753 | + stim::vec3<float> new_color; | ||
754 | + new_color[0] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[1]] / max_pressure; // red | ||
755 | + new_color[1] = 0.0f; // green | ||
756 | + new_color[2] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[1]] / max_pressure - 0.5f) : 1.0f; // blue | ||
757 | + glColor3f(new_color[0], new_color[1], new_color[2]); | ||
758 | + | ||
759 | + glPushMatrix(); | ||
760 | + glTranslatef(E[i][E[i].size() - 1][0], E[i][E[i].size() - 1][1], E[i][E[i].size() - 1][2]); | ||
761 | + glutSolidSphere(get_r(i, E[i].size() - 1), subdivision, subdivision); | ||
762 | + glPopMatrix(); | ||
763 | + } | ||
764 | + //for (unsigned j = 0; j < E[i].size(); j++) { | ||
765 | + // if (j == 0) { // for start vertex | ||
766 | + // if (P[E[i].v[0]] != 0) { | ||
767 | + // stim::vec3<float> new_color; | ||
768 | + // new_color[0] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[0]] / max_pressure; // red | ||
769 | + // new_color[1] = 0.0f; // green | ||
770 | + // new_color[2] = (P[E[i].v[0]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[0]] / max_pressure - 0.5f) : 1.0f; // blue | ||
771 | + // glColor3f(new_color[0], new_color[1], new_color[2]); | ||
772 | + // } | ||
773 | + // } | ||
774 | + // else if (j == E[i].size() - 1) { // for end vertex | ||
775 | + // if (P[E[i].v[1]] != 0) { | ||
776 | + // stim::vec3<float> new_color; | ||
777 | + // new_color[0] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f : 2.0f * P[E[i].v[1]] / max_pressure; // red | ||
778 | + // new_color[1] = 0.0f; // green | ||
779 | + // new_color[2] = (P[E[i].v[1]] / max_pressure) > 0.5f ? 1.0f - 2.0f * (P[E[i].v[1]] / max_pressure - 0.5f) : 1.0f; // blue | ||
780 | + // glColor3f(new_color[0], new_color[1], new_color[2]); | ||
781 | + // } | ||
782 | + // } | ||
783 | + // else | ||
784 | + // glColor3f(0.5f, 0.5f, 0.5f); // gray point | ||
785 | + | ||
786 | + // glPushMatrix(); | ||
787 | + // glTranslatef(E[i][j][0], E[i][j][1], E[i][j][2]); | ||
788 | + // glutSolidSphere(get_r(i, j), subdivision, subdivision); | ||
789 | + // glPopMatrix(); | ||
790 | + //} | ||
757 | } | 791 | } |
758 | } | 792 | } |
759 | 793 | ||
760 | // draw edges as series of cylinders | 794 | // draw edges as series of cylinders |
761 | - void glSolidCylinder(GLint subdivision, std::vector<unsigned char> color) { | 795 | + void glSolidCylinder(unsigned index, std::vector<unsigned char> color, GLint subdivision) { |
762 | 796 | ||
763 | stim::vec3<float> tmp_d; | 797 | stim::vec3<float> tmp_d; |
764 | stim::vec3<float> center1; | 798 | stim::vec3<float> center1; |
765 | stim::vec3<float> center2; | 799 | stim::vec3<float> center2; |
800 | + stim::circle<float> tmp_c; | ||
766 | float r1; | 801 | float r1; |
767 | float r2; | 802 | float r2; |
768 | std::vector<typename stim::vec3<float> > cp1(subdivision + 1); | 803 | std::vector<typename stim::vec3<float> > cp1(subdivision + 1); |
769 | std::vector<typename stim::vec3<float> > cp2(subdivision + 1); | 804 | std::vector<typename stim::vec3<float> > cp2(subdivision + 1); |
770 | for (unsigned i = 0; i < num_edge; i++) { // for every edge | 805 | for (unsigned i = 0; i < num_edge; i++) { // for every edge |
771 | - glEnable(GL_BLEND); // enable color blend | ||
772 | - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set blend function | ||
773 | - glDisable(GL_DEPTH_TEST); | ||
774 | - glColor4f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255, 0.5f); | 806 | + 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 | ||
809 | + 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); | ||
811 | + } | ||
812 | + else | ||
813 | + glColor3f((float)color[i * 3 + 0] / 255, (float)color[i * 3 + 1] / 255, (float)color[i * 3 + 2] / 255); | ||
814 | + | ||
775 | for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on the edge | 815 | for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on the edge |
776 | center1 = E[i][j]; | 816 | center1 = E[i][j]; |
777 | center2 = E[i][j + 1]; | 817 | center2 = E[i][j + 1]; |
@@ -779,8 +819,48 @@ namespace stim { | @@ -779,8 +819,48 @@ namespace stim { | ||
779 | r1 = get_r(i, j); | 819 | r1 = get_r(i, j); |
780 | r2 = get_r(i, j + 1); | 820 | r2 = get_r(i, j + 1); |
781 | 821 | ||
782 | - // calculate the envelope caps | ||
783 | - find_envelope(cp1, cp2, center1, center2, r1, r2, subdivision); | 822 | + //// calculate the envelope caps |
823 | + //find_envelope(cp1, cp2, center1, center2, r1, r2, subdivision); | ||
824 | + if (j == 0) { | ||
825 | + if (E[i].size() == 2) | ||
826 | + find_envelope(cp1, cp2, center1, center2, r1, r2, subdivision); | ||
827 | + else { | ||
828 | + tmp_d = center2 - center1; | ||
829 | + tmp_d = tmp_d.norm(); | ||
830 | + tmp_c.rotate(tmp_d); | ||
831 | + stim::circle<float> c1(center1, r1, tmp_d, tmp_c.U); | ||
832 | + cp1 = c1.glpoints(subdivision); | ||
833 | + tmp_d = (E[i][j + 2] - center2) + (center2 - center1); | ||
834 | + tmp_d = tmp_d.norm(); | ||
835 | + tmp_c.rotate(tmp_d); | ||
836 | + stim::circle<float> c2(center2, r2, tmp_d, tmp_c.U); | ||
837 | + cp2 = c2.glpoints(subdivision); | ||
838 | + } | ||
839 | + } | ||
840 | + else if (j == E[i].size() - 2) { | ||
841 | + tmp_d = (center2 - center1) + (center1 - E[i][j - 1]); | ||
842 | + tmp_d = tmp_d.norm(); | ||
843 | + tmp_c.rotate(tmp_d); | ||
844 | + stim::circle<float> c1(center1, r1, tmp_d, tmp_c.U); | ||
845 | + cp1 = c1.glpoints(subdivision); | ||
846 | + tmp_d = center2 - center1; | ||
847 | + tmp_d = tmp_d.norm(); | ||
848 | + tmp_c.rotate(tmp_d); | ||
849 | + stim::circle<float> c2(center2, r2, tmp_d, tmp_c.U); | ||
850 | + cp2 = c2.glpoints(subdivision); | ||
851 | + } | ||
852 | + else { | ||
853 | + tmp_d = (center2 - center1) + (center1 - E[i][j - 1]); | ||
854 | + tmp_d = tmp_d.norm(); | ||
855 | + tmp_c.rotate(tmp_d); | ||
856 | + stim::circle<float> c1(center1, r1, tmp_d, tmp_c.U); | ||
857 | + cp1 = c1.glpoints(subdivision); | ||
858 | + tmp_d = (E[i][j + 2] - center2) + (center2 - center1); | ||
859 | + tmp_d = tmp_d.norm(); | ||
860 | + tmp_c.rotate(tmp_d); | ||
861 | + stim::circle<float> c2(center2, r2, tmp_d, tmp_c.U); | ||
862 | + cp2 = c2.glpoints(subdivision); | ||
863 | + } | ||
784 | 864 | ||
785 | glBegin(GL_QUAD_STRIP); | 865 | glBegin(GL_QUAD_STRIP); |
786 | for (unsigned j = 0; j < cp1.size(); j++) { | 866 | for (unsigned j = 0; j < cp1.size(); j++) { |
@@ -789,12 +869,71 @@ namespace stim { | @@ -789,12 +869,71 @@ namespace stim { | ||
789 | } | 869 | } |
790 | glEnd(); | 870 | glEnd(); |
791 | } | 871 | } |
872 | + if (i == index) { | ||
873 | + glDisable(GL_BLEND); | ||
874 | + glEnable(GL_DEPTH_TEST); | ||
875 | + } | ||
876 | + | ||
792 | } | 877 | } |
793 | glFlush(); | 878 | glFlush(); |
794 | - glDisable(GL_BLEND); | ||
795 | } | 879 | } |
796 | 880 | ||
797 | // draw the flow direction as cone | 881 | // draw the flow direction as cone |
882 | + void glSolidCone(unsigned i, GLint subdivision) { | ||
883 | + | ||
884 | + stim::vec3<T> tmp_d; // direction | ||
885 | + stim::vec3<T> center; // cone hat center | ||
886 | + stim::vec3<T> head; // cone hat top | ||
887 | + stim::circle<T> tmp_c; | ||
888 | + std::vector<typename stim::vec3<T> > cp; | ||
889 | + T radius; | ||
890 | + | ||
891 | + glColor3f(0.0f, 0.0f, 0.0f); | ||
892 | + | ||
893 | + unsigned index = E[i].size() / 2 - 1; | ||
894 | + tmp_d = E[i][index + 1] - E[i][index]; | ||
895 | + tmp_d = tmp_d.norm(); | ||
896 | + center = (E[i][index + 1] + E[i][index]) / 2; | ||
897 | + tmp_c.rotate(tmp_d); | ||
898 | + radius = (E[i].r(index + 1) + E[i].r(index)) / 2; | ||
899 | + if (v[i] > 0) | ||
900 | + head = center + tmp_d * 2 * sqrt(3) * radius; | ||
901 | + else | ||
902 | + head = center - tmp_d * 2 * sqrt(3) * radius; | ||
903 | + | ||
904 | + stim::circle<float> c(center, radius, tmp_d, tmp_c.U); | ||
905 | + cp = c.glpoints(subdivision); | ||
906 | + | ||
907 | + glBegin(GL_TRIANGLE_FAN); | ||
908 | + glVertex3f(head[0], head[1], head[2]); | ||
909 | + for (unsigned k = 0; k < cp.size(); k++) | ||
910 | + glVertex3f(cp[k][0], cp[k][1], cp[k][2]); | ||
911 | + glEnd(); | ||
912 | + glFlush(); | ||
913 | + | ||
914 | + // draw a cone for every edge to indicate | ||
915 | + //for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on current edge | ||
916 | + // tmp_d = E[i][j + 1] - E[i][j]; | ||
917 | + // tmp_d = tmp_d.norm(); | ||
918 | + // center = (E[i][j + 1] + E[i][j]) / 2; | ||
919 | + // tmp_c.rotate(tmp_d); | ||
920 | + // radius = (E[i].r(j + 1) + E[i].r(j)) / 2; | ||
921 | + // if (v[i] > 0) // if flow flows from j to j+1 | ||
922 | + // head = center + tmp_d * 2 * sqrt(3) * radius; | ||
923 | + // else | ||
924 | + // head = center - tmp_d * 2 * sqrt(3) * radius; | ||
925 | + | ||
926 | + // stim::circle<float> c(center, radius, tmp_d, tmp_c.U); | ||
927 | + // cp = c.glpoints(subdivision); | ||
928 | + | ||
929 | + // glBegin(GL_TRIANGLE_FAN); | ||
930 | + // glVertex3f(head[0], head[1], head[2]); | ||
931 | + // for (unsigned k = 0; k < cp.size(); k++) | ||
932 | + // glVertex3f(cp[k][0], cp[k][1], cp[k][2]); | ||
933 | + // glEnd(); | ||
934 | + //} | ||
935 | + //glFlush(); | ||
936 | + } | ||
798 | void glSolidCone(GLint subdivision) { | 937 | void glSolidCone(GLint subdivision) { |
799 | 938 | ||
800 | stim::vec3<T> tmp_d; // direction | 939 | stim::vec3<T> tmp_d; // direction |
@@ -805,27 +944,48 @@ namespace stim { | @@ -805,27 +944,48 @@ namespace stim { | ||
805 | T radius; | 944 | T radius; |
806 | 945 | ||
807 | glColor3f(0.0f, 0.0f, 0.0f); | 946 | glColor3f(0.0f, 0.0f, 0.0f); |
947 | + // draw a cone for every edge to indicate | ||
808 | for (unsigned i = 0; i < num_edge; i++) { // for every edge | 948 | for (unsigned i = 0; i < num_edge; i++) { // for every edge |
809 | - for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on current edge | ||
810 | - tmp_d = E[i][j + 1] - E[i][j]; | ||
811 | - tmp_d = tmp_d.norm(); | ||
812 | - center = (E[i][j + 1] + E[i][j]) / 2; | ||
813 | - tmp_c.rotate(tmp_d); | ||
814 | - radius = (E[i].r(j + 1) + E[i].r(j)) / 2; | ||
815 | - if (v[i] > 0) // if flow flows from j to j+1 | ||
816 | - head = center + tmp_d * 2 * sqrt(3) * radius; | ||
817 | - else | ||
818 | - head = center - tmp_d * 2 * sqrt(3) * radius; | ||
819 | - | ||
820 | - stim::circle<float> c(center, radius, tmp_d, tmp_c.U); | ||
821 | - cp = c.glpoints(subdivision); | 949 | + unsigned k1 = E[i].size() / 2 - 1; // start and end index |
950 | + unsigned k2 = E[i].size() / 2; | ||
951 | + tmp_d = E[i][k2] - E[i][k1]; | ||
952 | + tmp_d = tmp_d.norm(); | ||
953 | + center = (E[i][k2] + E[i][k1]) / 2; | ||
954 | + tmp_c.rotate(tmp_d); | ||
955 | + radius = (E[i].r(k2) + E[i].r(k1)) / 2; | ||
956 | + if (v[i] > 0) // if flow flows from k1 to k2 | ||
957 | + head = center + tmp_d * 2 * sqrt(3) * radius; | ||
958 | + else | ||
959 | + head = center - tmp_d * 2 * sqrt(3) * radius; | ||
960 | + stim::circle<float> c(center, radius, tmp_d, tmp_c.U); | ||
961 | + cp = c.glpoints(subdivision); | ||
962 | + | ||
963 | + glBegin(GL_TRIANGLE_FAN); | ||
964 | + glVertex3f(head[0], head[1], head[2]); | ||
965 | + for (unsigned k = 0; k < cp.size(); k++) | ||
966 | + glVertex3f(cp[k][0], cp[k][1], cp[k][2]); | ||
967 | + glEnd(); | ||
822 | 968 | ||
823 | - glBegin(GL_TRIANGLE_FAN); | ||
824 | - glVertex3f(head[0], head[1], head[2]); | ||
825 | - for (unsigned k = 0; k < cp.size(); k++) | ||
826 | - glVertex3f(cp[k][0], cp[k][1], cp[k][2]); | ||
827 | - glEnd(); | ||
828 | - } | 969 | + //for (unsigned j = 0; j < E[i].size() - 1; j++) { // for every point on current edge |
970 | + // tmp_d = E[i][j + 1] - E[i][j]; | ||
971 | + // tmp_d = tmp_d.norm(); | ||
972 | + // center = (E[i][j + 1] + E[i][j]) / 2; | ||
973 | + // tmp_c.rotate(tmp_d); | ||
974 | + // radius = (E[i].r(j + 1) + E[i].r(j)) / 2; | ||
975 | + // if (v[i] > 0) // if flow flows from j to j+1 | ||
976 | + // head = center + tmp_d * 2 * sqrt(3) * radius; | ||
977 | + // else | ||
978 | + // head = center - tmp_d * 2 * sqrt(3) * radius; | ||
979 | + | ||
980 | + // stim::circle<float> c(center, radius, tmp_d, tmp_c.U); | ||
981 | + // cp = c.glpoints(subdivision); | ||
982 | + | ||
983 | + // glBegin(GL_TRIANGLE_FAN); | ||
984 | + // glVertex3f(head[0], head[1], head[2]); | ||
985 | + // for (unsigned k = 0; k < cp.size(); k++) | ||
986 | + // glVertex3f(cp[k][0], cp[k][1], cp[k][2]); | ||
987 | + // glEnd(); | ||
988 | + //} | ||
829 | } | 989 | } |
830 | glFlush(); | 990 | glFlush(); |
831 | } | 991 | } |
@@ -1054,14 +1214,14 @@ namespace stim { | @@ -1054,14 +1214,14 @@ namespace stim { | ||
1054 | // return true and a value if found | 1214 | // return true and a value if found |
1055 | inline bool epsilon_vertex(T x, T y, T z, T eps, unsigned& v) { | 1215 | inline bool epsilon_vertex(T x, T y, T z, T eps, unsigned& v) { |
1056 | 1216 | ||
1057 | - float d = FLT_MAX; // minimum distance between 2 vertices | ||
1058 | - float tmp_d = 0.0f; // temporary stores distance for loop | 1217 | + T d = FLT_MAX; // minimum distance between 2 vertices |
1218 | + T tmp_d = 0.0f; // temporary stores distance for loop | ||
1059 | unsigned tmp_i = 0; // temporary stores connection index for loop | 1219 | unsigned tmp_i = 0; // temporary stores connection index for loop |
1060 | - stim::vec3<float> tmp_v; // temporary stores current loop point | 1220 | + stim::vec3<T> tmp_v; // temporary stores current loop point |
1061 | d = FLT_MAX; // set to max of float number | 1221 | d = FLT_MAX; // set to max of float number |
1062 | 1222 | ||
1063 | for (unsigned i = 0; i < V.size(); i++) { | 1223 | for (unsigned i = 0; i < V.size(); i++) { |
1064 | - tmp_v = stim::vec3<float>(x, y, z); | 1224 | + tmp_v = stim::vec3<T>(x, y, z); |
1065 | 1225 | ||
1066 | tmp_v = tmp_v - V[i]; // calculate a vector between two vertices | 1226 | tmp_v = tmp_v - V[i]; // calculate a vector between two vertices |
1067 | tmp_d = tmp_v.len(); // calculate length of that vector | 1227 | tmp_d = tmp_v.len(); // calculate length of that vector |
@@ -1079,6 +1239,61 @@ namespace stim { | @@ -1079,6 +1239,61 @@ namespace stim { | ||
1079 | return false; | 1239 | return false; |
1080 | } | 1240 | } |
1081 | 1241 | ||
1242 | + // find the nearest inlet/outlet connection line of current click position | ||
1243 | + // ab -> line segment, v -> point | ||
1244 | + // return true and a value if found | ||
1245 | + inline bool epsilon_edge(T x, T y, T z, T eps, unsigned &idx) { | ||
1246 | + | ||
1247 | + T d = FLT_MAX; | ||
1248 | + T tmp_d; | ||
1249 | + unsigned tmp_i = 0; | ||
1250 | + unsigned tmp_j = 0; | ||
1251 | + stim::vec3<T> v1; | ||
1252 | + stim::vec3<T> v2; | ||
1253 | + stim::vec3<T> v3; | ||
1254 | + stim::vec3<T> v0 = stim::vec3<float>(x, y, z); | ||
1255 | + bool online = false; // flag indicates the point is on the line-segment | ||
1256 | + float a, b; | ||
1257 | + | ||
1258 | + for (unsigned i = 0; i < E.size(); i++) { | ||
1259 | + for (unsigned j = 0; j < E[i].size() - 1; j++) { | ||
1260 | + v1 = E[i][j + 1] - E[i][j]; // a -> b = ab | ||
1261 | + v2 = v0 - E[i][j]; // a -> v = av | ||
1262 | + v3 = v0 - E[i][j + 1]; // b -> v = bv | ||
1263 | + | ||
1264 | + tmp_d = v2.dot(v1); // avยทab | ||
1265 | + | ||
1266 | + // check the line relative position | ||
1267 | + a = v2.dot(v1.norm()); | ||
1268 | + b = v3.dot(v1.norm()); | ||
1269 | + if (a < v1.len() && b < v1.len()) // if the length of projection fragment is longer than the line-segment | ||
1270 | + online = true; | ||
1271 | + else | ||
1272 | + online = false; | ||
1273 | + | ||
1274 | + if (tmp_d <= 0.0 || tmp_d > std::pow(v1.len(), 2) && !online) // projection lies outside the line-segment | ||
1275 | + continue; | ||
1276 | + else { | ||
1277 | + tmp_d = v1.cross(v2).len() / v1.len(); // perpendicular distance of point to segment: |v1 x v2| / |v1| | ||
1278 | + if (tmp_d < d) { | ||
1279 | + d = tmp_d; | ||
1280 | + tmp_i = i; | ||
1281 | + tmp_j = j; | ||
1282 | + } | ||
1283 | + } | ||
1284 | + } | ||
1285 | + } | ||
1286 | + | ||
1287 | + eps += get_radius(tmp_i, tmp_j); | ||
1288 | + | ||
1289 | + if (d < eps) { | ||
1290 | + idx = tmp_i; | ||
1291 | + return true; | ||
1292 | + } | ||
1293 | + | ||
1294 | + return false; | ||
1295 | + } | ||
1296 | + | ||
1082 | /// build main feeder connection | 1297 | /// build main feeder connection |
1083 | // set up main feeder and main port of both input and output | 1298 | // set up main feeder and main port of both input and output |
1084 | void set_main_feeder(T border = 400.0f) { | 1299 | void set_main_feeder(T border = 400.0f) { |
main.cu
@@ -54,7 +54,7 @@ float zoom_factor = 10.0f; // zooming factor | @@ -54,7 +54,7 @@ float zoom_factor = 10.0f; // zooming factor | ||
54 | float border_factor = 20.0f; // border | 54 | float border_factor = 20.0f; // border |
55 | float radii_factor = 1.0f; // radii changing factor | 55 | float radii_factor = 1.0f; // radii changing factor |
56 | GLint subdivision = 20; // slices and stacks | 56 | GLint subdivision = 20; // slices and stacks |
57 | -float default_radius = 5.0f; // default radii of network vertex | 57 | +float default_radius = 5.0f; // default radii of network vertex |
58 | float delta = 0.01f; // small discrepancy | 58 | float delta = 0.01f; // small discrepancy |
59 | float eps = 20.0f; // epsilon threshold | 59 | float eps = 20.0f; // epsilon threshold |
60 | float max_pressure = 0.0f; // maximum pressure that the channel can bear | 60 | float max_pressure = 0.0f; // maximum pressure that the channel can bear |
@@ -67,10 +67,12 @@ int mouse_y; // window y-coordinate | @@ -67,10 +67,12 @@ int mouse_y; // window y-coordinate | ||
67 | bool LTbutton = false; // true means down while false means up | 67 | bool LTbutton = false; // true means down while false means up |
68 | 68 | ||
69 | // simulation parameters | 69 | // simulation parameters |
70 | +bool render_direction = false; // flag indicates rendering flow direction for one edge | ||
70 | bool simulation = false; // flag indicates simulation mode | 71 | bool simulation = false; // flag indicates simulation mode |
71 | bool color_bound = false; // flag indicates velocity color map bound | 72 | bool color_bound = false; // flag indicates velocity color map bound |
72 | bool to_select_pressure = false; // flag indicates having selected a vertex to modify pressure | 73 | bool to_select_pressure = false; // flag indicates having selected a vertex to modify pressure |
73 | unsigned pressure_index; // the index of vertex that is clicked | 74 | unsigned pressure_index; // the index of vertex that is clicked |
75 | +unsigned direction_index = -1; // the index of edge that is pointed at | ||
74 | 76 | ||
75 | // build inlet/outlet parameters | 77 | // build inlet/outlet parameters |
76 | bool build_inlet_outlet = false; // flag indicates building inlets and outlets | 78 | bool build_inlet_outlet = false; // flag indicates building inlets and outlets |
@@ -92,8 +94,11 @@ inline void get_background() { | @@ -92,8 +94,11 @@ inline void get_background() { | ||
92 | 94 | ||
93 | // set the initial radii | 95 | // set the initial radii |
94 | flow.init(num_edge, num_vertex); // initialize flow object | 96 | flow.init(num_edge, num_vertex); // initialize flow object |
95 | - for (unsigned i = 0; i < num_edge; i++) | ||
96 | - flow.set_r(i, default_radius); | 97 | + |
98 | + // if no radius information laoded | ||
99 | + if (!flow.get_radius(0, 0)) | ||
100 | + for (unsigned i = 0; i < num_edge; i++) | ||
101 | + flow.set_r(i, default_radius); | ||
97 | } | 102 | } |
98 | 103 | ||
99 | // convert from window coordinates to world coordinates | 104 | // convert from window coordinates to world coordinates |
@@ -197,15 +202,18 @@ void glut_render() { | @@ -197,15 +202,18 @@ void glut_render() { | ||
197 | glut_modelview(); | 202 | glut_modelview(); |
198 | 203 | ||
199 | if (!simulation && !build_inlet_outlet || manufacture) { | 204 | if (!simulation && !build_inlet_outlet || manufacture) { |
205 | + glColor3f(0.0f, 0.0f, 0.0f); | ||
200 | flow.glCylinder0(); | 206 | flow.glCylinder0(); |
201 | } | 207 | } |
202 | else { | 208 | else { |
203 | flow.bounding_box(); | 209 | flow.bounding_box(); |
204 | flow.glSolidSphere(max_pressure, subdivision); | 210 | flow.glSolidSphere(max_pressure, subdivision); |
205 | flow.mark_vertex(); | 211 | flow.mark_vertex(); |
206 | - flow.glSolidCone(subdivision); | ||
207 | - flow.glSolidCylinder(subdivision, color); | 212 | + //flow.glSolidCone(subdivision); |
213 | + flow.glSolidCylinder(direction_index, color, subdivision); | ||
208 | flow.glSolidCuboid(); | 214 | flow.glSolidCuboid(); |
215 | + if (render_direction) | ||
216 | + flow.glSolidCone(direction_index, subdivision); | ||
209 | } | 217 | } |
210 | 218 | ||
211 | if (build_inlet_outlet) { | 219 | if (build_inlet_outlet) { |
@@ -217,7 +225,6 @@ void glut_render() { | @@ -217,7 +225,6 @@ void glut_render() { | ||
217 | flow.tube_bridge(subdivision); | 225 | flow.tube_bridge(subdivision); |
218 | } | 226 | } |
219 | 227 | ||
220 | - | ||
221 | // render bars | 228 | // render bars |
222 | // bring up a pressure bar on left | 229 | // bring up a pressure bar on left |
223 | if (to_select_pressure) { | 230 | if (to_select_pressure) { |
@@ -416,6 +423,31 @@ void glut_motion(int x, int y) { | @@ -416,6 +423,31 @@ void glut_motion(int x, int y) { | ||
416 | glutPostRedisplay(); // re-draw the visualization | 423 | glutPostRedisplay(); // re-draw the visualization |
417 | } | 424 | } |
418 | 425 | ||
426 | +// defines passive mouse motion function | ||
427 | +void glut_passive_motion(int x, int y) { | ||
428 | + | ||
429 | + mouse_x = x; | ||
430 | + mouse_y = y; | ||
431 | + | ||
432 | + // check whether the mouse point near to an edge | ||
433 | + GLdouble posX, posY, posZ; | ||
434 | + window_to_world(posX, posY, posZ); // get the world coordinates | ||
435 | + | ||
436 | + if (simulation || build_inlet_outlet) { | ||
437 | + bool flag = flow.epsilon_edge((float)posX, (float)posY, (float)posZ, eps, direction_index); | ||
438 | + if (flag) | ||
439 | + render_direction = true; | ||
440 | + else { | ||
441 | + if (render_direction) // if the direction is displaying currently, do a short delay | ||
442 | + Sleep(1000); | ||
443 | + render_direction = false; | ||
444 | + direction_index = -1; | ||
445 | + } | ||
446 | + } | ||
447 | + | ||
448 | + glutPostRedisplay(); // re-draw the visualization | ||
449 | +} | ||
450 | + | ||
419 | // get click window coordinates | 451 | // get click window coordinates |
420 | void glut_mouse(int button, int state, int x, int y) { | 452 | void glut_mouse(int button, int state, int x, int y) { |
421 | 453 | ||
@@ -552,6 +584,7 @@ void glut_initialize() { | @@ -552,6 +584,7 @@ void glut_initialize() { | ||
552 | glutDisplayFunc(glut_render); | 584 | glutDisplayFunc(glut_render); |
553 | glutMouseFunc(glut_mouse); | 585 | glutMouseFunc(glut_mouse); |
554 | glutMotionFunc(glut_motion); | 586 | glutMotionFunc(glut_motion); |
587 | + glutPassiveMotionFunc(glut_passive_motion); | ||
555 | glutMouseWheelFunc(glut_wheel); | 588 | glutMouseWheelFunc(glut_wheel); |
556 | glutKeyboardFunc(glut_keyboard); | 589 | glutKeyboardFunc(glut_keyboard); |
557 | 590 | ||
@@ -565,6 +598,20 @@ void glut_initialize() { | @@ -565,6 +598,20 @@ void glut_initialize() { | ||
565 | cam.LookAt(c[0], c[1], c[2]); | 598 | cam.LookAt(c[0], c[1], c[2]); |
566 | } | 599 | } |
567 | 600 | ||
601 | +// output an advertisement for the lab, authors and usage information | ||
602 | +void advertise() { | ||
603 | + std::cout << std::endl << std::endl; | ||
604 | + std::cout << " =======================================================================================" << std::endl; | ||
605 | + std::cout << "|Thank you for using the synthetic microvascular model generator for microfluidics tool!|" << std::endl; | ||
606 | + std::cout << "|Scalable Tissue Imaging and Modeling (STIM) Lab, University of Houston |" << std::endl; | ||
607 | + std::cout << "|Developers: Jiaming Guo, David Mayerich |" << std::endl; | ||
608 | + std::cout << "|Source: https://git.stim.ee.uh.edu/Jack/flow3.git |" << std::endl; | ||
609 | + std::cout << " =======================================================================================" << std::endl << std::endl; | ||
610 | + | ||
611 | + std::cout << args.str(); | ||
612 | +} | ||
613 | + | ||
614 | +// main function: parse arguments and initialize GLUT | ||
568 | int main(int argc, char* argv[]) { | 615 | int main(int argc, char* argv[]) { |
569 | 616 | ||
570 | // add arguments | 617 | // add arguments |
@@ -573,12 +620,17 @@ int main(int argc, char* argv[]) { | @@ -573,12 +620,17 @@ int main(int argc, char* argv[]) { | ||
573 | args.add("maxpress", "maximum allowed pressure in g / units / s^2, default 2 is for blood when units = um", "2", "real value > 0"); | 620 | args.add("maxpress", "maximum allowed pressure in g / units / s^2, default 2 is for blood when units = um", "2", "real value > 0"); |
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"); | 621 | 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"); |
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"); | 622 | 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"); | 623 | + args.add("hilbert", "activate hilbert curves connections", "0", "value 1 for enablement"); |
577 | args.add("stackres", "spacing between pixel samples in each dimension(in units/pixel)", "1 1 1", "real value > 0"); | 624 | args.add("stackres", "spacing between pixel samples in each dimension(in units/pixel)", "1 1 1", "real value > 0"); |
578 | args.add("stackdir", "set the directory of the output image stack", "", "any existing directory (ex. /home/name/network)"); | 625 | args.add("stackdir", "set the directory of the output image stack", "", "any existing directory (ex. /home/name/network)"); |
579 | 626 | ||
580 | args.parse(argc, argv); // parse the command line | 627 | args.parse(argc, argv); // parse the command line |
581 | 628 | ||
629 | + if (args["help"].is_set()) { | ||
630 | + advertise(); | ||
631 | + std::exit(1); | ||
632 | + } | ||
633 | + | ||
582 | // load network | 634 | // load network |
583 | if (args["network"].is_set()) { // load network from user | 635 | if (args["network"].is_set()) { // load network from user |
584 | std::vector<std::string> tmp = stim::parser::split(args["network"].as_string(), '.'); | 636 | std::vector<std::string> tmp = stim::parser::split(args["network"].as_string(), '.'); |