Measure: Fix several crashes in Measurement

Measurement::getShape() used to call ShapeFinder::getLocatedShape()
that failed to return a valid shape in many cases. And the calling
instance didn't check for a valid shape either which caused
a segmentation fault.

Solution:
Replace ShapeFinder::getLocatedShape() with Part::Feature::getShape()
that works more reliably and where needed check for a valid shape
before accessing it.

This fixes issue 19452 and improves the fix for 19349
This commit is contained in:
wmayer
2025-02-09 20:33:31 +01:00
committed by Ladislav Michl
parent 8e247bb469
commit 14de080897

View File

@@ -287,13 +287,11 @@ MeasureType Measurement::getType()
TopoDS_Shape
Measurement::getShape(App::DocumentObject* obj, const char* subName, TopAbs_ShapeEnum hint) const
{
TopoShape shape = ShapeFinder::getLocatedTopoShape(*obj, subName);
if (shape.shapeType() == TopAbs_COMPOUND && hint != TopAbs_COMPOUND
&& shape.hasSubShape(hint)) {
return shape.getSubTopoShape(hint, true).getShape();
}
return shape.getShape();
return Part::Feature::getShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subName);
}
@@ -331,7 +329,7 @@ double Measurement::length() const
// Get the length of one edge
TopoDS_Shape shape = getShape(*obj, (*subEl).c_str(), TopAbs_EDGE);
if (shape.IsNull()) {
if (shape.IsNull() || shape.Infinite()) {
continue;
}
const TopoDS_Edge& edge = TopoDS::Edge(shape);
@@ -435,8 +433,6 @@ double Measurement::planePlaneDistance() const
const auto& objects = References3D.getValues();
const auto& subElements = References3D.getSubValues();
std::vector<gp_Pln> planes;
// Get the first plane
TopoDS_Shape shape1 = getShape(objects[0], subElements[0].c_str(), TopAbs_FACE);
const TopoDS_Face& face1 = TopoDS::Face(shape1);
@@ -687,7 +683,11 @@ double Measurement::volume() const
for (size_t i = 0; i < objects.size(); ++i) {
GProp_GProps props = GProp_GProps();
BRepGProp::VolumeProperties(getShape(objects[i], subElements[i].c_str()), props);
TopoDS_Shape shape = getShape(objects[i], subElements[i].c_str());
if (shape.IsNull() || shape.Infinite()) {
continue;
}
BRepGProp::VolumeProperties(shape, props);
result += props.Mass();
}
}
@@ -710,7 +710,11 @@ double Measurement::area() const
for (size_t i = 0; i < objects.size(); ++i) {
GProp_GProps props;
BRepGProp::SurfaceProperties(getShape(objects[i], subElements[i].c_str()), props);
TopoDS_Shape shape = getShape(objects[i], subElements[i].c_str());
if (shape.IsNull() || shape.Infinite()) {
continue;
}
BRepGProp::SurfaceProperties(shape, props);
result += props.Mass(); // Area is obtained using Mass method for surface properties
}
}
@@ -745,7 +749,11 @@ Base::Vector3d Measurement::massCenter() const
// Compute inertia properties
GProp_GProps props = GProp_GProps();
BRepGProp::VolumeProperties(getShape((*obj), ""), props);
TopoDS_Shape shape = ShapeFinder::getLocatedShape(*(*obj), "");
if (shape.IsNull()) {
continue;
}
BRepGProp::VolumeProperties(shape, props);
gprops.Add(props);
// Get inertia properties
}
@@ -821,11 +829,17 @@ bool Measurement::linesAreParallel() const
// Get the first line
TopoDS_Shape shape1 = getShape(objects[0], subElements[0].c_str(), TopAbs_EDGE);
if (shape1.IsNull()) {
return false;
}
const TopoDS_Edge& edge1 = TopoDS::Edge(shape1);
BRepAdaptor_Curve curve1(edge1);
// Get the second line
TopoDS_Shape shape2 = getShape(objects[1], subElements[1].c_str(), TopAbs_EDGE);
if (shape2.IsNull()) {
return false;
}
const TopoDS_Edge& edge2 = TopoDS::Edge(shape2);
BRepAdaptor_Curve curve2(edge2);