Show volume of current group alongside total volume.
parent
a0e992374d
commit
915f55aabc
|
@ -70,6 +70,8 @@ New measurement/analysis features:
|
||||||
* New command for measuring center of mass, with live updates as the sketch
|
* New command for measuring center of mass, with live updates as the sketch
|
||||||
changes, "Analyze → Center of Mass".
|
changes, "Analyze → Center of Mass".
|
||||||
* New option for displaying areas of closed contours.
|
* New option for displaying areas of closed contours.
|
||||||
|
* When calculating volume of the mesh, volume of the solid from the current
|
||||||
|
group is now shown alongside total volume of all solids.
|
||||||
* When selecting a point and a line, projected distance to current
|
* When selecting a point and a line, projected distance to current
|
||||||
workplane is displayed.
|
workplane is displayed.
|
||||||
|
|
||||||
|
|
53
src/mesh.cpp
53
src/mesh.cpp
|
@ -1128,3 +1128,56 @@ void SMesh::RemoveDegenerateTriangles() {
|
||||||
}
|
}
|
||||||
l.RemoveTagged();
|
l.RemoveTagged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double SMesh::CalculateVolume() const {
|
||||||
|
double vol = 0;
|
||||||
|
for(STriangle tr : l) {
|
||||||
|
// Translate to place vertex A at (x, y, 0)
|
||||||
|
Vector trans = Vector::From(tr.a.x, tr.a.y, 0);
|
||||||
|
tr.a = (tr.a).Minus(trans);
|
||||||
|
tr.b = (tr.b).Minus(trans);
|
||||||
|
tr.c = (tr.c).Minus(trans);
|
||||||
|
|
||||||
|
// Rotate to place vertex B on the y-axis. Depending on
|
||||||
|
// whether the triangle is CW or CCW, C is either to the
|
||||||
|
// right or to the left of the y-axis. This handles the
|
||||||
|
// sign of our normal.
|
||||||
|
Vector u = Vector::From(-tr.b.y, tr.b.x, 0);
|
||||||
|
u = u.WithMagnitude(1);
|
||||||
|
Vector v = Vector::From(tr.b.x, tr.b.y, 0);
|
||||||
|
v = v.WithMagnitude(1);
|
||||||
|
Vector n = Vector::From(0, 0, 1);
|
||||||
|
|
||||||
|
tr.a = (tr.a).DotInToCsys(u, v, n);
|
||||||
|
tr.b = (tr.b).DotInToCsys(u, v, n);
|
||||||
|
tr.c = (tr.c).DotInToCsys(u, v, n);
|
||||||
|
|
||||||
|
n = tr.Normal().WithMagnitude(1);
|
||||||
|
|
||||||
|
// Triangles on edge don't contribute
|
||||||
|
if(fabs(n.z) < LENGTH_EPS) continue;
|
||||||
|
|
||||||
|
// The plane has equation p dot n = a dot n
|
||||||
|
double d = (tr.a).Dot(n);
|
||||||
|
// nx*x + ny*y + nz*z = d
|
||||||
|
// nz*z = d - nx*x - ny*y
|
||||||
|
double A = -n.x/n.z, B = -n.y/n.z, C = d/n.z;
|
||||||
|
|
||||||
|
double mac = tr.c.y/tr.c.x, mbc = (tr.c.y - tr.b.y)/tr.c.x;
|
||||||
|
double xc = tr.c.x, yb = tr.b.y;
|
||||||
|
|
||||||
|
// I asked Maple for
|
||||||
|
// int(int(A*x + B*y +C, y=mac*x..(mbc*x + yb)), x=0..xc);
|
||||||
|
double integral =
|
||||||
|
(1.0/3)*(
|
||||||
|
A*(mbc-mac)+
|
||||||
|
(1.0/2)*B*(mbc*mbc-mac*mac)
|
||||||
|
)*(xc*xc*xc)+
|
||||||
|
(1.0/2)*(A*yb+B*yb*mbc+C*(mbc-mac))*xc*xc+
|
||||||
|
C*yb*xc+
|
||||||
|
(1.0/2)*B*yb*yb*xc;
|
||||||
|
|
||||||
|
vol += integral;
|
||||||
|
}
|
||||||
|
return vol;
|
||||||
|
}
|
||||||
|
|
|
@ -280,6 +280,7 @@ public:
|
||||||
|
|
||||||
void PrecomputeTransparency();
|
void PrecomputeTransparency();
|
||||||
void RemoveDegenerateTriangles();
|
void RemoveDegenerateTriangles();
|
||||||
|
double CalculateVolume() const;
|
||||||
|
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
void RemapFaces(Group *g, int remap);
|
void RemapFaces(Group *g, int remap);
|
||||||
|
|
|
@ -772,65 +772,26 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::VOLUME: {
|
case Command::VOLUME: {
|
||||||
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
||||||
|
double totalVol = g->displayMesh.CalculateVolume();
|
||||||
|
std::string msg = ssprintf(
|
||||||
|
_("The volume of the solid model is:\n\n"
|
||||||
|
" %s"),
|
||||||
|
SS.MmToStringSI(totalVol, /*dim=*/3).c_str());
|
||||||
|
|
||||||
double vol = 0;
|
SMesh curMesh = {};
|
||||||
int i;
|
g->thisShell.TriangulateInto(&curMesh);
|
||||||
for(i = 0; i < m->l.n; i++) {
|
double curVol = curMesh.CalculateVolume();
|
||||||
STriangle tr = m->l[i];
|
if(curVol > 0.0) {
|
||||||
|
msg += ssprintf(
|
||||||
// Translate to place vertex A at (x, y, 0)
|
_("\nThe volume of current group mesh is:\n\n"
|
||||||
Vector trans = Vector::From(tr.a.x, tr.a.y, 0);
|
" %s"),
|
||||||
tr.a = (tr.a).Minus(trans);
|
SS.MmToStringSI(curVol, /*dim=*/3).c_str());
|
||||||
tr.b = (tr.b).Minus(trans);
|
|
||||||
tr.c = (tr.c).Minus(trans);
|
|
||||||
|
|
||||||
// Rotate to place vertex B on the y-axis. Depending on
|
|
||||||
// whether the triangle is CW or CCW, C is either to the
|
|
||||||
// right or to the left of the y-axis. This handles the
|
|
||||||
// sign of our normal.
|
|
||||||
Vector u = Vector::From(-tr.b.y, tr.b.x, 0);
|
|
||||||
u = u.WithMagnitude(1);
|
|
||||||
Vector v = Vector::From(tr.b.x, tr.b.y, 0);
|
|
||||||
v = v.WithMagnitude(1);
|
|
||||||
Vector n = Vector::From(0, 0, 1);
|
|
||||||
|
|
||||||
tr.a = (tr.a).DotInToCsys(u, v, n);
|
|
||||||
tr.b = (tr.b).DotInToCsys(u, v, n);
|
|
||||||
tr.c = (tr.c).DotInToCsys(u, v, n);
|
|
||||||
|
|
||||||
n = tr.Normal().WithMagnitude(1);
|
|
||||||
|
|
||||||
// Triangles on edge don't contribute
|
|
||||||
if(fabs(n.z) < LENGTH_EPS) continue;
|
|
||||||
|
|
||||||
// The plane has equation p dot n = a dot n
|
|
||||||
double d = (tr.a).Dot(n);
|
|
||||||
// nx*x + ny*y + nz*z = d
|
|
||||||
// nz*z = d - nx*x - ny*y
|
|
||||||
double A = -n.x/n.z, B = -n.y/n.z, C = d/n.z;
|
|
||||||
|
|
||||||
double mac = tr.c.y/tr.c.x, mbc = (tr.c.y - tr.b.y)/tr.c.x;
|
|
||||||
double xc = tr.c.x, yb = tr.b.y;
|
|
||||||
|
|
||||||
// I asked Maple for
|
|
||||||
// int(int(A*x + B*y +C, y=mac*x..(mbc*x + yb)), x=0..xc);
|
|
||||||
double integral =
|
|
||||||
(1.0/3)*(
|
|
||||||
A*(mbc-mac)+
|
|
||||||
(1.0/2)*B*(mbc*mbc-mac*mac)
|
|
||||||
)*(xc*xc*xc)+
|
|
||||||
(1.0/2)*(A*yb+B*yb*mbc+C*(mbc-mac))*xc*xc+
|
|
||||||
C*yb*xc+
|
|
||||||
(1.0/2)*B*yb*yb*xc;
|
|
||||||
|
|
||||||
vol += integral;
|
|
||||||
}
|
}
|
||||||
Message(_("The volume of the solid model is:\n\n"
|
|
||||||
" %s\n\n"
|
msg += _("\n\nCurved surfaces have been approximated as triangles.\n"
|
||||||
"Curved surfaces have been approximated as triangles.\n"
|
"This introduces error, typically of around 1%.");
|
||||||
"This introduces error, typically of around 1%%."),
|
Message("%s", msg.c_str());
|
||||||
SS.MmToStringSI(vol, /*dim=*/3).c_str());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue