| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a0e9923 commit 915f55a
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,6 +70,8 @@ New measurement/analysis features: | |||
| 70 | 70 | * New command for measuring center of mass, with live updates as the sketch | |
| 71 | 71 | changes, "Analyze → Center of Mass". | |
| 72 | 72 | * New option for displaying areas of closed contours. | |
| 73 | + * When calculating volume of the mesh, volume of the solid from the current | ||
| 74 | + group is now shown alongside total volume of all solids. | ||
| 73 | 75 | * When selecting a point and a line, projected distance to current | |
| 74 | 76 | workplane is displayed. | |
| 75 | 77 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1128,3 +1128,56 @@ void SMesh::RemoveDegenerateTriangles() { | |||
| 1128 | 1128 | } | |
| 1129 | 1129 | l.RemoveTagged(); | |
| 1130 | 1130 | } | |
| 1131 | + | ||
| 1132 | + double SMesh::CalculateVolume() const { | ||
| 1133 | + double vol = 0; | ||
| 1134 | + for(STriangle tr : l) { | ||
| 1135 | + // Translate to place vertex A at (x, y, 0) | ||
| 1136 | + Vector trans = Vector::From(tr.a.x, tr.a.y, 0); | ||
| 1137 | + tr.a = (tr.a).Minus(trans); | ||
| 1138 | + tr.b = (tr.b).Minus(trans); | ||
| 1139 | + tr.c = (tr.c).Minus(trans); | ||
| 1140 | + | ||
| 1141 | + // Rotate to place vertex B on the y-axis. Depending on | ||
| 1142 | + // whether the triangle is CW or CCW, C is either to the | ||
| 1143 | + // right or to the left of the y-axis. This handles the | ||
| 1144 | + // sign of our normal. | ||
| 1145 | + Vector u = Vector::From(-tr.b.y, tr.b.x, 0); | ||
| 1146 | + u = u.WithMagnitude(1); | ||
| 1147 | + Vector v = Vector::From(tr.b.x, tr.b.y, 0); | ||
| 1148 | + v = v.WithMagnitude(1); | ||
| 1149 | + Vector n = Vector::From(0, 0, 1); | ||
| 1150 | + | ||
| 1151 | + tr.a = (tr.a).DotInToCsys(u, v, n); | ||
| 1152 | + tr.b = (tr.b).DotInToCsys(u, v, n); | ||
| 1153 | + tr.c = (tr.c).DotInToCsys(u, v, n); | ||
| 1154 | + | ||
| 1155 | + n = tr.Normal().WithMagnitude(1); | ||
| 1156 | + | ||
| 1157 | + // Triangles on edge don't contribute | ||
| 1158 | + if(fabs(n.z) < LENGTH_EPS) continue; | ||
| 1159 | + | ||
| 1160 | + // The plane has equation p dot n = a dot n | ||
| 1161 | + double d = (tr.a).Dot(n); | ||
| 1162 | + // nx*x + ny*y + nz*z = d | ||
| 1163 | + // nz*z = d - nx*x - ny*y | ||
| 1164 | + double A = -n.x/n.z, B = -n.y/n.z, C = d/n.z; | ||
| 1165 | + | ||
| 1166 | + double mac = tr.c.y/tr.c.x, mbc = (tr.c.y - tr.b.y)/tr.c.x; | ||
| 1167 | + double xc = tr.c.x, yb = tr.b.y; | ||
| 1168 | + | ||
| 1169 | + // I asked Maple for | ||
| 1170 | + // int(int(A*x + B*y +C, y=mac*x..(mbc*x + yb)), x=0..xc); | ||
| 1171 | + double integral = | ||
| 1172 | + (1.0/3)*( | ||
| 1173 | + A*(mbc-mac)+ | ||
| 1174 | + (1.0/2)*B*(mbc*mbc-mac*mac) | ||
| 1175 | + )*(xc*xc*xc)+ | ||
| 1176 | + (1.0/2)*(A*yb+B*yb*mbc+C*(mbc-mac))*xc*xc+ | ||
| 1177 | + C*yb*xc+ | ||
| 1178 | + (1.0/2)*B*yb*yb*xc; | ||
| 1179 | + | ||
| 1180 | + vol += integral; | ||
| 1181 | + } | ||
| 1182 | + return vol; | ||
| 1183 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -280,6 +280,7 @@ class SMesh { | |||
| 280 | 280 | ||
| 281 | 281 | void PrecomputeTransparency(); | |
| 282 | 282 | void RemoveDegenerateTriangles(); | |
| 283 | + double CalculateVolume() const; | ||
| 283 | 284 | ||
| 284 | 285 | bool IsEmpty() const; | |
| 285 | 286 | void RemapFaces(Group *g, int remap); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -772,65 +772,26 @@ void SolveSpaceUI::MenuAnalyze(Command id) { | |||
| 772 | 772 | } | |
| 773 | 773 | ||
| 774 | 774 | case Command::VOLUME: { | |
| 775 | - SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); | ||
| 776 | - | ||
| 777 | - double vol = 0; | ||
| 778 | - int i; | ||
| 779 | - for(i = 0; i < m->l.n; i++) { | ||
| 780 | - STriangle tr = m->l[i]; | ||
| 781 | - | ||
| 782 | - // Translate to place vertex A at (x, y, 0) | ||
| 783 | - Vector trans = Vector::From(tr.a.x, tr.a.y, 0); | ||
| 784 | - tr.a = (tr.a).Minus(trans); | ||
| 785 | - tr.b = (tr.b).Minus(trans); | ||
| 786 | - tr.c = (tr.c).Minus(trans); | ||
| 787 | - | ||
| 788 | - // Rotate to place vertex B on the y-axis. Depending on | ||
| 789 | - // whether the triangle is CW or CCW, C is either to the | ||
| 790 | - // right or to the left of the y-axis. This handles the | ||
| 791 | - // sign of our normal. | ||
| 792 | - Vector u = Vector::From(-tr.b.y, tr.b.x, 0); | ||
| 793 | - u = u.WithMagnitude(1); | ||
| 794 | - Vector v = Vector::From(tr.b.x, tr.b.y, 0); | ||
| 795 | - v = v.WithMagnitude(1); | ||
| 796 | - Vector n = Vector::From(0, 0, 1); | ||
| 797 | - | ||
| 798 | - tr.a = (tr.a).DotInToCsys(u, v, n); | ||
| 799 | - tr.b = (tr.b).DotInToCsys(u, v, n); | ||
| 800 | - tr.c = (tr.c).DotInToCsys(u, v, n); | ||
| 801 | - | ||
| 802 | - n = tr.Normal().WithMagnitude(1); | ||
| 803 | - | ||
| 804 | - // Triangles on edge don't contribute | ||
| 805 | - if(fabs(n.z) < LENGTH_EPS) continue; | ||
| 806 | - | ||
| 807 | - // The plane has equation p dot n = a dot n | ||
| 808 | - double d = (tr.a).Dot(n); | ||
| 809 | - // nx*x + ny*y + nz*z = d | ||
| 810 | - // nz*z = d - nx*x - ny*y | ||
| 811 | - double A = -n.x/n.z, B = -n.y/n.z, C = d/n.z; | ||
| 812 | - | ||
| 813 | - double mac = tr.c.y/tr.c.x, mbc = (tr.c.y - tr.b.y)/tr.c.x; | ||
| 814 | - double xc = tr.c.x, yb = tr.b.y; | ||
| 815 | - | ||
| 816 | - // I asked Maple for | ||
| 817 | - // int(int(A*x + B*y +C, y=mac*x..(mbc*x + yb)), x=0..xc); | ||
| 818 | - double integral = | ||
| 819 | - (1.0/3)*( | ||
| 820 | - A*(mbc-mac)+ | ||
| 821 | - (1.0/2)*B*(mbc*mbc-mac*mac) | ||
| 822 | - )*(xc*xc*xc)+ | ||
| 823 | - (1.0/2)*(A*yb+B*yb*mbc+C*(mbc-mac))*xc*xc+ | ||
| 824 | - C*yb*xc+ | ||
| 825 | - (1.0/2)*B*yb*yb*xc; | ||
| 826 | - | ||
| 827 | - vol += integral; | ||
| 775 | + Group *g = SK.GetGroup(SS.GW.activeGroup); | ||
| 776 | + double totalVol = g->displayMesh.CalculateVolume(); | ||
| 777 | + std::string msg = ssprintf( | ||
| 778 | + _("The volume of the solid model is:\n\n" | ||
| 779 | + " %s"), | ||
| 780 | + SS.MmToStringSI(totalVol, /*dim=*/3).c_str()); | ||
| 781 | + | ||
| 782 | + SMesh curMesh = {}; | ||
| 783 | + g->thisShell.TriangulateInto(&curMesh); | ||
| 784 | + double curVol = curMesh.CalculateVolume(); | ||
| 785 | + if(curVol > 0.0) { | ||
| 786 | + msg += ssprintf( | ||
| 787 | + _("\nThe volume of current group mesh is:\n\n" | ||
| 788 | + " %s"), | ||
| 789 | + SS.MmToStringSI(curVol, /*dim=*/3).c_str()); | ||
| 828 | 790 | } | |
| 829 | - Message(_("The volume of the solid model is:\n\n" | ||
| 830 | - " %s\n\n" | ||
| 831 | - "Curved surfaces have been approximated as triangles.\n" | ||
| 832 | - "This introduces error, typically of around 1%%."), | ||
| 833 | - SS.MmToStringSI(vol, /*dim=*/3).c_str()); | ||
| 791 | + | ||
| 792 | + msg += _("\n\nCurved surfaces have been approximated as triangles.\n" | ||
| 793 | + "This introduces error, typically of around 1%."); | ||
| 794 | + Message("%s", msg.c_str()); | ||
| 834 | 795 | break; | |
| 835 | 796 | } | |
| 836 | 797 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments