[TD]fix area calculation

This commit is contained in:
wandererfan
2024-10-17 15:27:11 -04:00
committed by Yorik van Havre
parent 6c85c37b38
commit 1de4dc600d
10 changed files with 261 additions and 14 deletions

View File

@@ -34,6 +34,7 @@
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
@@ -47,6 +48,7 @@
#include <Geom_Plane.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <ShapeAnalysis.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
@@ -224,6 +226,11 @@ DrawViewDimension::DrawViewDimension()
UnderTolerance.setStatus(App::Property::ReadOnly, true);
FormatSpecUnderTolerance.setStatus(App::Property::ReadOnly, true);
// legacy behaviour if this is false
ADD_PROPERTY_TYPE(UseActualArea, (true), "Area", App::Prop_Output,
"If true, area dimensions return the area of the face minus the areas of any enclosed faces. \
If false, the area of the face's outer boundary is returned.");
measurement = new Measure::Measurement();
// TODO: should have better initial datumLabel position than (0, 0) in the DVP?? something
// closer to the object being measured?
@@ -277,6 +284,7 @@ void DrawViewDimension::resetArea()
{
m_areaPoint.center = Base::Vector3d(0, 0, 0);
m_areaPoint.area = 0.0;
m_areaPoint.actualArea = 0.0;
}
void DrawViewDimension::onChanged(const App::Property* prop)
@@ -686,7 +694,6 @@ double DrawViewDimension::getDimValue()
//! retrieve the dimension value for "true" dimensions. The returned value is in internal units (mm).
double DrawViewDimension::getTrueDimValue() const
{
// Base::Console().Message("DVD::getTrueDimValue()\n");
double result = 0.0;
if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) {
@@ -763,7 +770,17 @@ double DrawViewDimension::getProjectedDimValue() const
result = legAngle;
}
else if (Type.isValue("Area")) {
result = m_areaPoint.area / scale / scale;
// 2d reference makes scaled values in areaPoint
// 3d reference makes actual values in areaPoint :p
double divisor{scale / scale};
if (has3DReferences()) {
divisor = 1.0;
}
if (UseActualArea.getValue()) {
result = m_areaPoint.actualArea / divisor;
} else {
result = m_areaPoint.area / divisor;
}
}
return result;
@@ -1383,27 +1400,71 @@ areaPoint DrawViewDimension::getAreaParameters(ReferenceVector references)
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (4)";
throw Base::RuntimeError(ssMessage.str());
}
auto dvp = static_cast<DrawViewPart*>(refObject);
pts.area = face->getArea();
pts.center = face->getCenter();
auto filteredFaces = GeometryUtils::findHolesInFace(dvp, references.front().getSubName());
auto perforatedFace = GeometryUtils::makePerforatedFace(face, filteredFaces);
// these areas are scaled because the source geometry is scaled, but it makes no sense to
// report a scaled area.
auto unscale = getViewPart()->getScale() * getViewPart()->getScale();
pts.area = face->getArea() / unscale; // this will be the 2d area as projected onto the page? not really filled area?
pts.actualArea = getActualArea(perforatedFace) / unscale;
pts.center = getFaceCenter(perforatedFace);
pts.invertY(); // geometry class is over, back to -Y up/.
}
else {
// this is a 3d reference
// this is a 3d reference. perforations should be handled for us by OCC
TopoDS_Shape geometry = references[0].getGeometry();
if (geometry.IsNull() || geometry.ShapeType() != TopAbs_FACE) {
throw Base::RuntimeError("Geometry for dimension reference is null.");
}
const TopoDS_Face& face = TopoDS::Face(geometry);
GProp_GProps props;
BRepGProp::SurfaceProperties(face, props);
pts.area = props.Mass();
pts.center = DrawUtil::toVector3d(props.CentreOfMass());
// these areas are unscaled as the source is 3d geometry.
pts.area = getFilledArea(face);
pts.actualArea = getActualArea(face);
pts.center = getFaceCenter(face);
pts.move(getViewPart()->getCurrentCentroid());
pts.project(getViewPart());
}
return pts;
}
//! returns the center of mass of a face (density = k)
Base::Vector3d DrawViewDimension::getFaceCenter(const TopoDS_Face& face)
{
GProp_GProps props;
BRepGProp::SurfaceProperties(face, props);
auto center = DrawUtil::toVector3d(props.CentreOfMass());
return center;
}
//! returns the "net" area of a face (area of the face's outer boundary less the area of any holes)
double DrawViewDimension::getActualArea(const TopoDS_Face& face)
{
GProp_GProps props;
BRepGProp::SurfaceProperties(face, props);
return props.Mass();
}
//! returns the "gross" area of a face (area of the face's outer boundary)
double DrawViewDimension::getFilledArea(const TopoDS_Face& face)
{
TopoDS_Wire outerwire = ShapeAnalysis::OuterWire(face);
if (outerwire.IsNull()) {
return 0.0;
}
double area = ShapeAnalysis::ContourArea(outerwire);
return area;
}
DrawViewPart* DrawViewDimension::getViewPart() const
{
if (References2D.getValues().empty()) {