diff --git a/src/Mod/Import/App/ExportOCAF2.cpp b/src/Mod/Import/App/ExportOCAF2.cpp index 4649c6a676..ca0f71686b 100644 --- a/src/Mod/Import/App/ExportOCAF2.cpp +++ b/src/Mod/Import/App/ExportOCAF2.cpp @@ -381,7 +381,12 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, const char* name) { App::DocumentObject* obj; - auto shape = Part::Feature::getTopoShape(parentObj, sub, false, nullptr, &obj, false, !sub); + auto shape = Part::Feature::getTopoShape( + parentObj, + (sub ? Part::ShapeOption::NoFlag : Part::ShapeOption::Transform), + sub, + nullptr, + &obj); if (!obj || shape.isNull()) { if (obj) { FC_WARN(obj->getFullName() << " has null shape"); @@ -415,7 +420,9 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, auto linked = obj; auto linkedShape = shape; while (true) { - auto s = Part::Feature::getTopoShape(linked); + auto s = Part::Feature::getTopoShape(linked, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform); if (s.isNull() || !s.getShape().IsPartner(shape.getShape())) { break; } diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index de872e0dad..f4f32f8b5f 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -557,7 +557,9 @@ App::DocumentObject* ImportOCAF2::loadShapes() ret->recomputeFeature(true); } if (options.merge && ret && !ret->isDerivedFrom()) { - auto shape = Part::Feature::getTopoShape(ret); + auto shape = Part::Feature::getTopoShape(ret, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform); auto feature = pDocument->addObject("Feature"); auto name = Tools::labelName(pDoc->Main()); feature->Label.setValue(name.empty() ? default_name.c_str() : name.c_str()); diff --git a/src/Mod/Measure/App/Measurement.cpp b/src/Mod/Measure/App/Measurement.cpp index 661edd7ea0..73ae0344cc 100644 --- a/src/Mod/Measure/App/Measurement.cpp +++ b/src/Mod/Measure/App/Measurement.cpp @@ -125,7 +125,12 @@ MeasureType Measurement::findType() for (; obj != objects.end(); ++obj, ++subEl) { TopoDS_Shape refSubShape; try { - refSubShape = Part::Feature::getShape(*obj, (*subEl).c_str(), true); + refSubShape = Part::Feature::getShape(*obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + (*subEl).c_str()); + if (refSubShape.IsNull()) { return MeasureType::Invalid; } @@ -751,7 +756,12 @@ bool Measurement::planesAreParallel() const for (size_t i = 0; i < objects.size(); ++i) { TopoDS_Shape refSubShape; try { - refSubShape = Part::Feature::getShape(objects[i], subElements[i].c_str(), true); + refSubShape = Part::Feature::getShape(objects[i], + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subElements[i].c_str()); + if (refSubShape.IsNull()) { return false; } diff --git a/src/Mod/Measure/App/ShapeFinder.cpp b/src/Mod/Measure/App/ShapeFinder.cpp index 3d3fd6232a..fa22f96f7e 100644 --- a/src/Mod/Measure/App/ShapeFinder.cpp +++ b/src/Mod/Measure/App/ShapeFinder.cpp @@ -114,7 +114,9 @@ TopoDS_Shape ShapeFinder::getLocatedShape(const App::DocumentObject& rootObject, return {}; } - TopoDS_Shape shape = Part::Feature::getShape(target); + TopoDS_Shape shape = + Part::Feature::getShape(target, + Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (isShapeReallyNull(shape)) { return {}; } diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index 675dd06f87..96ec027d2e 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -217,7 +217,10 @@ void Tessellation::onEstimateMaximumEdgeLengthClicked() double edgeLen = 0; for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) { - auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName); + auto shape = Part::Feature::getTopoShape(sel.pObject, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sel.SubName); if (shape.hasSubShape(TopAbs_FACE)) { Base::BoundBox3d bbox = shape.getBoundBox(); edgeLen = std::max(edgeLen, bbox.LengthX()); @@ -249,7 +252,10 @@ bool Tessellation::accept() bool bodyWithNoTip = false; bool partWithNoFace = false; for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) { - auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName); + auto shape = Part::Feature::getTopoShape(sel.pObject, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sel.SubName); if (shape.hasSubShape(TopAbs_FACE)) { shapeObjects.emplace_back(sel.pObject, sel.SubName); } @@ -568,7 +574,10 @@ bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile) App::DocumentObject* part = sub.getObject(); if (part) { - Part::TopoShape shape = Part::Feature::getTopoShape(part, sub.getSubName().c_str()); + Part::TopoShape shape = Part::Feature::getTopoShape(part, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.getSubName().c_str()); shape.exportBrep(d->cadFile.c_str()); d->label = part->Label.getStrValue() + " (Meshed)"; diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 665c797c26..fc5b27c823 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -861,7 +861,7 @@ private: shape = static_cast(pcObj)->getGeometryPtr()->toShape(); else if (PyObject_TypeCheck(pcObj, &App::DocumentObjectPy::Type)) { auto obj = static_cast(pcObj)->getDocumentObjectPtr(); - shape = Feature::getTopoShape(obj); + shape = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform); } else { throw Py::TypeError("Expects argument of type DocumentObject, Shape, or Geometry"); } @@ -2288,9 +2288,17 @@ private: Base::Matrix4D mat; if(pyMat) mat = *static_cast(pyMat)->getMatrixPtr(); - auto shape = Feature::getTopoShape(obj,subname,Base::asBoolean(needSubElement), - &mat,&subObj,retType==2,Base::asBoolean(transform), - Base::asBoolean(noElementMap)); + + bool resolveLink = (retType == 2); + auto shape = Feature::getTopoShape(obj, + (resolveLink ? ShapeOption::ResolveLink : ShapeOption::NoFlag) + | (Base::asBoolean(needSubElement) ? ShapeOption::NeedSubElement : ShapeOption::NoFlag) + | (Base::asBoolean(transform) ? ShapeOption::Transform : ShapeOption::NoFlag) + | (Base::asBoolean(noElementMap) ? ShapeOption::NoElementMap : ShapeOption::NoFlag), + subname, + &mat, + &subObj); + if (Base::asBoolean(refine)) { shape = TopoShape(0, shape.Hasher).makeElementRefine(shape); } diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index 31492009e5..4ef29ccbe7 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -881,7 +881,11 @@ TopoShape AttachEngine::extractSubShape(App::DocumentObject* obj, const std::str try { // getTopoShape support fully qualified subnames and should return shape with correct // global placement. - shape = Feature::getTopoShape(obj, subname.c_str(), true); + shape = Feature::getTopoShape(obj, + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + subname.c_str()); for (;;) { if (shape.isNull()) { diff --git a/src/Mod/Part/App/FeatureChamfer.cpp b/src/Mod/Part/App/FeatureChamfer.cpp index 8a29a609d3..f98ae44dd4 100644 --- a/src/Mod/Part/App/FeatureChamfer.cpp +++ b/src/Mod/Part/App/FeatureChamfer.cpp @@ -48,8 +48,8 @@ App::DocumentObjectExecReturn *Chamfer::execute() return new App::DocumentObjectExecReturn("No object linked"); try { - TopoShape baseTopoShape = Feature::getTopoShape(link); - auto baseShape = Feature::getShape(link); + TopoShape baseTopoShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); + auto baseShape = Feature::getShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); BRepFilletAPI_MakeChamfer mkChamfer(baseShape); TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace; TopExp::MapShapesAndAncestors(baseShape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace); diff --git a/src/Mod/Part/App/FeatureCompound.cpp b/src/Mod/Part/App/FeatureCompound.cpp index 431ada08c8..70fe457337 100644 --- a/src/Mod/Part/App/FeatureCompound.cpp +++ b/src/Mod/Part/App/FeatureCompound.cpp @@ -63,7 +63,7 @@ App::DocumentObjectExecReturn *Compound::execute() if (!tempLinks.insert(obj).second) { continue; } - auto sh = Feature::getTopoShape(obj); + auto sh = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform); if (!sh.isNull()) { shapes.push_back(sh); } diff --git a/src/Mod/Part/App/FeatureExtrusion.cpp b/src/Mod/Part/App/FeatureExtrusion.cpp index 53fb59e28e..ec8cf1fb3e 100644 --- a/src/Mod/Part/App/FeatureExtrusion.cpp +++ b/src/Mod/Part/App/FeatureExtrusion.cpp @@ -170,10 +170,14 @@ bool Extrusion::fetchAxisLink(const App::PropertyLinkSub& axisLink, Base::Vector TopoDS_Shape axEdge; if (!axisLink.getSubValues().empty() && axisLink.getSubValues()[0].length() > 0) { - axEdge = Feature::getTopoShape(linked, axisLink.getSubValues()[0].c_str(), true /*need element*/).getShape(); + axEdge = Feature::getTopoShape(linked, + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + axisLink.getSubValues()[0].c_str()).getShape(); } else { - axEdge = Feature::getShape(linked); + axEdge = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform); } if (axEdge.IsNull()) @@ -263,7 +267,12 @@ Base::Vector3d Extrusion::calculateShapeNormal(const App::PropertyLink& shapeLin { App::DocumentObject* docobj = nullptr; Base::Matrix4D mat; - TopoDS_Shape sh = Feature::getShape(shapeLink.getValue(), nullptr, false, &mat, &docobj); + TopoDS_Shape sh = Feature::getShape(shapeLink.getValue(), + ShapeOption::ResolveLink + | ShapeOption::Transform, + nullptr, + &mat, + &docobj); if (!docobj) throw Base::ValueError("calculateShapeNormal: link is empty"); @@ -366,7 +375,7 @@ App::DocumentObjectExecReturn* Extrusion::execute() try { ExtrusionParameters params = computeFinalParameters(); TopoShape result(0); - extrudeShape(result, Feature::getTopoShape(link), params); + extrudeShape(result, Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform), params); this->Shape.setValue(result); return App::DocumentObject::StdReturn; } diff --git a/src/Mod/Part/App/FeatureFace.cpp b/src/Mod/Part/App/FeatureFace.cpp index 4b6cb26c20..3ea1908c4f 100644 --- a/src/Mod/Part/App/FeatureFace.cpp +++ b/src/Mod/Part/App/FeatureFace.cpp @@ -68,7 +68,7 @@ App::DocumentObjectExecReturn *Face::execute() for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { if (!(*it)) return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape)."); - TopoDS_Shape shape = Feature::getShape(*it); + TopoDS_Shape shape = Feature::getShape(*it, ShapeOption::ResolveLink | ShapeOption::Transform); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); diff --git a/src/Mod/Part/App/FeatureFillet.cpp b/src/Mod/Part/App/FeatureFillet.cpp index b7fbf423f6..9c10649ec6 100644 --- a/src/Mod/Part/App/FeatureFillet.cpp +++ b/src/Mod/Part/App/FeatureFillet.cpp @@ -54,8 +54,8 @@ App::DocumentObjectExecReturn *Fillet::execute() #if defined(__GNUC__) && defined (FC_OS_LINUX) Base::SignalException se; #endif - auto baseShape = Feature::getShape(link); - TopoShape baseTopoShape = Feature::getTopoShape(link); + auto baseShape = Feature::getShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); + TopoShape baseTopoShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); BRepFilletAPI_MakeFillet mkFillet(baseShape); TopTools_IndexedMapOfShape mapOfShape; TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfShape); diff --git a/src/Mod/Part/App/FeatureMirroring.cpp b/src/Mod/Part/App/FeatureMirroring.cpp index 94ce2bdca6..ac02e9a4f9 100644 --- a/src/Mod/Part/App/FeatureMirroring.cpp +++ b/src/Mod/Part/App/FeatureMirroring.cpp @@ -170,7 +170,13 @@ App::DocumentObjectExecReturn *Mirroring::execute() bool isEdge = false; //will be true if user selected edge subobject or if object only has 1 edge TopoDS_Shape shape; if (!subStrings.empty() && subStrings[0].length() > 0){ - shape = Feature::getTopoShape(linked, subStrings[0].c_str(), true).getShape(); + + shape = Feature::getTopoShape(linked, + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + subStrings[0].c_str()).getShape(); + if (strstr(subStrings[0].c_str(), "Face")){ isFace = true; //was face subobject, e.g. Face3 } else { @@ -179,7 +185,8 @@ App::DocumentObjectExecReturn *Mirroring::execute() } } } else { - shape = Feature::getShape(linked); //no subobjects were selected, so this is entire shape of feature + //no subobjects were selected, so this is entire shape of feature + shape = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform); } // if there is only 1 face or 1 edge, then we don't need to force the user to select that face or edge @@ -253,7 +260,7 @@ App::DocumentObjectExecReturn *Mirroring::execute() try { gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z)); - auto shape = Feature::getTopoShape(link); + auto shape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); if (shape.isNull()) Standard_Failure::Raise("Cannot mirror empty shape"); this->Shape.setValue(TopoShape(0).makeElementMirror(shape,ax2)); diff --git a/src/Mod/Part/App/FeatureOffset.cpp b/src/Mod/Part/App/FeatureOffset.cpp index 0aab028cbd..357344d902 100644 --- a/src/Mod/Part/App/FeatureOffset.cpp +++ b/src/Mod/Part/App/FeatureOffset.cpp @@ -85,7 +85,7 @@ App::DocumentObjectExecReturn *Offset::execute() bool self = SelfIntersection.getValue(); short mode = (short)Mode.getValue(); bool fill = Fill.getValue(); - auto shape = Feature::getTopoShape(source); + auto shape = Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform); if(shape.isNull()) return new App::DocumentObjectExecReturn("Invalid source link"); auto join = static_cast(Join.getValue()); @@ -132,7 +132,7 @@ App::DocumentObjectExecReturn *Offset2D::execute() if (!source) { return new App::DocumentObjectExecReturn("No source shape linked."); } - const TopoShape shape = Part::Feature::getTopoShape(source); + const TopoShape shape = Part::Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform); if (shape.isNull()) { return new App::DocumentObjectExecReturn("No source shape linked."); } diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 0104dbf3ce..ec2b21c331 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -116,12 +116,12 @@ App::DocumentObjectExecReturn* Boolean::execute() std::vector shapes; shapes.reserve(2); // Now, let's get the TopoDS_Shape - shapes.push_back(Feature::getTopoShape(Base.getValue())); + shapes.push_back(Feature::getTopoShape(Base.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform)); auto BaseShape = shapes[0].getShape(); if (BaseShape.IsNull()) { throw NullShapeException("Base shape is null"); } - shapes.push_back(Feature::getTopoShape(Tool.getValue())); + shapes.push_back(Feature::getTopoShape(Tool.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform)); auto ToolShape = shapes[1].getShape(); if (ToolShape.IsNull()) { throw NullShapeException("Tool shape is null"); diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 1d2e052bb5..ed61ca0529 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -88,7 +88,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute() { std::vector shapes; for (auto obj : Shapes.getValues()) { - TopoShape sh = Feature::getTopoShape(obj); + TopoShape sh = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform); if (sh.isNull()) { return new App::DocumentObjectExecReturn("Input shape is null"); } diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index 1833516962..efd7191bff 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -93,7 +93,7 @@ App::DocumentObjectExecReturn *MultiFuse::execute() std::vector::iterator it; for (it = obj.begin(); it != obj.end(); ++it) { - shapes.push_back(Feature::getTopoShape(*it)); + shapes.push_back(Feature::getTopoShape(*it, ShapeOption::ResolveLink | ShapeOption::Transform)); } bool argumentsAreInCompound = false; diff --git a/src/Mod/Part/App/FeatureProjectOnSurface.cpp b/src/Mod/Part/App/FeatureProjectOnSurface.cpp index 99c182f893..957152dc45 100644 --- a/src/Mod/Part/App/FeatureProjectOnSurface.cpp +++ b/src/Mod/Part/App/FeatureProjectOnSurface.cpp @@ -108,7 +108,11 @@ TopoDS_Face ProjectOnSurface::getSupportFace() const throw Base::ValueError("Expect exactly one support face"); } - auto topoSupport = Feature::getTopoShape(support, subStrings[0].c_str(), true); + auto topoSupport = Feature::getTopoShape(support, + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + subStrings[0].c_str()); return TopoDS::Face(topoSupport.getShape()); } @@ -122,7 +126,11 @@ std::vector ProjectOnSurface::getProjectionShapes() const } for (std::size_t index = 0; index < objects.size(); index++) { - auto topoSupport = Feature::getTopoShape(objects[index], subvalues[index].c_str(), true); + auto topoSupport = Feature::getTopoShape(objects[index], + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + subvalues[index].c_str()); shapes.push_back(topoSupport.getShape()); } diff --git a/src/Mod/Part/App/FeatureRevolution.cpp b/src/Mod/Part/App/FeatureRevolution.cpp index 1bc993ce01..ce82686107 100644 --- a/src/Mod/Part/App/FeatureRevolution.cpp +++ b/src/Mod/Part/App/FeatureRevolution.cpp @@ -91,9 +91,13 @@ bool Revolution::fetchAxisLink(const App::PropertyLinkSub &axisLink, TopoDS_Shape axEdge; if (!axisLink.getSubValues().empty() && axisLink.getSubValues()[0].length() > 0){ - axEdge = Feature::getTopoShape(linked, axisLink.getSubValues()[0].c_str(), true /*need element*/).getShape(); + axEdge = Feature::getTopoShape(linked, + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + axisLink.getSubValues()[0].c_str()).getShape(); } else { - axEdge = Feature::getShape(linked); + axEdge = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform); } if (axEdge.IsNull()) @@ -149,7 +153,7 @@ App::DocumentObjectExecReturn *Revolution::execute() angle = angle_edge; //apply "midplane" symmetry - TopoShape sourceShape = Feature::getTopoShape(link); + TopoShape sourceShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform); if (Symmetric.getValue()) { //rotate source shape backwards by half angle, to make resulting revolution symmetric to the profile gp_Trsf mov; diff --git a/src/Mod/Part/App/FeatureScale.cpp b/src/Mod/Part/App/FeatureScale.cpp index d2173a36dc..ac63507b27 100644 --- a/src/Mod/Part/App/FeatureScale.cpp +++ b/src/Mod/Part/App/FeatureScale.cpp @@ -151,7 +151,7 @@ App::DocumentObjectExecReturn* Scale::execute() try { Scale::ScaleParameters params = computeFinalParameters(); - TopoShape result = scaleShape(Feature::getTopoShape(link), params); + TopoShape result = scaleShape(Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform), params); this->Shape.setValue(result); return App::DocumentObject::StdReturn; } diff --git a/src/Mod/Part/App/MeasureClient.cpp b/src/Mod/Part/App/MeasureClient.cpp index 594297ee99..5d1a937496 100644 --- a/src/Mod/Part/App/MeasureClient.cpp +++ b/src/Mod/Part/App/MeasureClient.cpp @@ -98,7 +98,13 @@ TopoDS_Shape getLocatedShape(const App::SubObjectT& subject, Base::Matrix4D* mat return {}; } - Part::TopoShape shape = Part::Feature::getTopoShape(obj, subject.getElementName(), false, mat, nullptr, true); + Part::TopoShape shape = Part::Feature::getTopoShape( + obj, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subject.getElementName(), + mat); + if (shape.isNull()) { Base::Console().log("Part::MeasureClient::getLocatedShape: Did not retrieve shape for %s, %s\n", obj->getNameInDocument(), subject.getElementName()); return {}; @@ -121,7 +127,12 @@ TopoDS_Shape getLocatedShape(const App::SubObjectT& subject, Base::Matrix4D* mat App::MeasureElementType PartMeasureTypeCb(App::DocumentObject* ob, const char* subName) { - TopoDS_Shape shape = Part::Feature::getShape(ob, subName, true); + TopoDS_Shape shape = Part::Feature::getShape(ob, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subName); + if (shape.IsNull()) { // failure here on loading document with existing measurement. Base::Console().message("Part::PartMeasureTypeCb did not retrieve shape for %s, %s\n", ob->getNameInDocument(), subName); @@ -177,8 +188,13 @@ bool getShapeFromStrings(TopoDS_Shape &shapeOut, const App::SubObjectT& subject, if (!obj) { return {}; } - shapeOut = Part::Feature::getShape(obj, subject.getElementName(), true, mat); - return !shapeOut.IsNull(); + shapeOut = Part::Feature::getShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subject.getElementName(), + mat); + return !shapeOut.IsNull(); } diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index 35150b3d02..fbaa479fe7 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -544,7 +544,13 @@ static std::vector> getElementSource(App::Docu doc = nullptr; } else { - shape = Part::Feature::getTopoShape(obj, 0, false, 0, &owner); + shape = + Part::Feature::getTopoShape(obj, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + nullptr, + nullptr, + &owner); } if (type && shape.elementType(original) != type) { break; @@ -571,7 +577,7 @@ std::list Feature::getElementHistory(App::DocumentObject* fea bool sameType) { std::list ret; - TopoShape shape = getTopoShape(feature); + TopoShape shape = getTopoShape(feature, ShapeOption::ResolveLink | ShapeOption::Transform); Data::IndexedName idx(name); Data::MappedName element; Data::MappedName prevElement; @@ -648,7 +654,7 @@ std::list Feature::getElementHistory(App::DocumentObject* fea } } feature = obj; - shape = Feature::getTopoShape(feature); + shape = Feature::getTopoShape(feature, ShapeOption::ResolveLink | ShapeOption::Transform); element = original; if (element_type && shape.elementType(original) != element_type) { break; @@ -667,16 +673,14 @@ QVector Feature::getElementFromSource(App::DocumentObject* if (!obj || !src) { return res; } - - auto shape = getTopoShape(obj, - subname, - false, - nullptr, - nullptr, - true, - /*transform = */ false); + auto shape = getTopoShape(obj, ShapeOption::ResolveLink, subname, nullptr, nullptr); App::DocumentObject* owner = nullptr; - auto srcShape = getTopoShape(src, srcSub, false, nullptr, &owner); + auto srcShape = getTopoShape(src, + ShapeOption::ResolveLink + | ShapeOption::Transform, + srcSub, + nullptr, + &owner); int tagChanges; Data::MappedElement element; Data::IndexedName checkingSubname; @@ -792,7 +796,12 @@ QVector Feature::getRelatedElements(App::DocumentObject* ob bool withCache) { auto owner = obj; - auto shape = getTopoShape(obj, nullptr, false, 0, &owner); + auto shape = getTopoShape(obj, + ShapeOption::ResolveLink + | ShapeOption::Transform, + nullptr, + nullptr, + &owner); QVector ret; Data::MappedElement mapped = shape.getElementName(name); if (!mapped.name) { @@ -859,11 +868,13 @@ QVector Feature::getRelatedElements(App::DocumentObject* ob return ret; } -TopoDS_Shape Feature::getShape(const App::DocumentObject *obj, const char *subname, - bool needSubElement, Base::Matrix4D *pmat, App::DocumentObject **powner, - bool resolveLink, bool transform) +TopoDS_Shape Feature::getShape( const App::DocumentObject *obj, + ShapeOptions options, + const char *subname, + Base::Matrix4D *pmat, + App::DocumentObject **powner) { - return getTopoShape(obj,subname,needSubElement,pmat,powner,resolveLink,transform,true).getShape(); + return getTopoShape(obj, options | ShapeOption::NoElementMap, subname, pmat, powner).getShape(); } App::Material Feature::getMaterialAppearance() const @@ -886,7 +897,8 @@ void Feature::clearShapeCache() { // _ShapeCache.cache.clear(); } -static TopoShape _getTopoShape(const App::DocumentObject* obj, +/* +(const App::DocumentObject* obj, const char* subname, bool needSubElement, Base::Matrix4D* pmat, @@ -895,6 +907,14 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, bool noElementMap, const std::set hiddens, const App::DocumentObject* lastLink) +*/ +static TopoShape _getTopoShape(const App::DocumentObject* obj, + ShapeOptions options, + const char* subname, + Base::Matrix4D* pmat, + App::DocumentObject** powner, + const std::set hiddens, + const App::DocumentObject* lastLink) { TopoShape shape; @@ -911,7 +931,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, std::string _subname; auto subelement = Data::findElementName(subname); - if (!needSubElement && subname) { + if (!options.testFlag(ShapeOption::NeedSubElement) && subname) { // strip out element name if not needed if (subelement && *subelement) { _subname = std::string(subname, subelement); @@ -924,7 +944,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, }; if (canCache(obj) && PropertyShapeCache::getShape(obj, shape, subname)) { - if (noElementMap) { + if (options.testFlag(ShapeOption::NoElementMap)) { shape.resetElementMap(); shape.Tag = 0; if ( shape.Hasher ) { @@ -948,7 +968,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, hasher = owner->getDocument()->getStringHasher(); linked = owner->getLinkedObject(true, &linkMat, false); if (pmat) { - if (resolveLink && obj != owner) { + if (options.testFlag(ShapeOption::ResolveLink) && obj != owner) { *pmat = mat * linkMat; } else { @@ -959,7 +979,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, linked = owner; } if (powner) { - *powner = resolveLink ? linked : owner; + *powner = options.testFlag(ShapeOption::ResolveLink) ? linked : owner; } if (!shape.isNull()) { @@ -976,7 +996,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, PropertyShapeCache::setShape(obj, shape, subname); } } - if (noElementMap) { + if (options.testFlag(ShapeOption::NoElementMap)) { shape.resetElementMap(); shape.Tag = 0; if ( shape.Hasher ) { @@ -1064,7 +1084,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, } // nothing can be done if there is sub-element references - if (needSubElement && subelement && *subelement) { + if (options.testFlag(ShapeOption::NeedSubElement) && subelement && *subelement) { return shape; } @@ -1081,7 +1101,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, } } if (!shape.isNull()) { - if (noElementMap) { + if (options.testFlag(ShapeOption::NoElementMap)) { shape.resetElementMap(); shape.Tag = 0; if ( shape.Hasher) { @@ -1099,7 +1119,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, && (!link || (!link->_ChildCache.getSize() && link->getSubElements().size() <= 1))) { // if there is a linked object, and there is no child cache (which is used // for special handling of plain group), obtain shape from the linked object - shape = Feature::getTopoShape(linked, nullptr, false, nullptr, nullptr, false, false); + shape = Feature::getTopoShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform); if (shape.isNull()) { return shape; } @@ -1125,7 +1145,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, linked = link->getTrueLinkedObject(false, &baseMat); if (linked && linked != owner) { baseShape = - Feature::getTopoShape(linked, nullptr, false, nullptr, nullptr, false, false); + Feature::getTopoShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform); if (!link->getShowElementValue()) { baseShape.reTagElementMap(owner->getID(), owner->getDocument()->getStringHasher()); @@ -1181,14 +1201,13 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, } if (doGetShape) { shape = _getTopoShape(owner, + ShapeOption::NeedSubElement, sub.c_str(), - true, - 0, + nullptr, &subObj, - false, - false, nextHiddens, nextLink); + if (shape.isNull()) { continue; } @@ -1233,7 +1252,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, PropertyShapeCache::setShape(obj, shape, subname); } } - if (noElementMap) { + if (options.testFlag(ShapeOption::NoElementMap)) { shape.resetElementMap(); shape.Tag = 0; if ( shape.Hasher ) { @@ -1243,17 +1262,15 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj, return shape; } -TopoShape Feature::getTopoShape(const App::DocumentObject* obj, - const char* subname, - bool needSubElement, - Base::Matrix4D* pmat, - App::DocumentObject** powner, - bool resolveLink, - bool transform, - bool noElementMap) + +TopoShape Feature::getTopoShape(const App::DocumentObject* obj, + ShapeOptions options, + const char* subname, + Base::Matrix4D* pmat, + App::DocumentObject** powner) { if (!obj || !obj->getNameInDocument()) { - return TopoShape(); + return {}; } const App::DocumentObject* lastLink = 0; @@ -1268,7 +1285,7 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj, // transformation for easy shape caching, i.e. with `transform` set // to false. So we manually apply the top level transform if asked. - if (needSubElement && (!pmat || *pmat == Base::Matrix4D()) + if (options.testFlag(ShapeOption::NeedSubElement) && (!pmat || *pmat == Base::Matrix4D()) && obj->isDerivedFrom() && !obj->hasExtension(App::LinkBaseExtension::getExtensionClassTypeId())) { // Some OCC shape making is very sensitive to shape transformation. So @@ -1276,10 +1293,10 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj, // processing here. if (subname && *subname && Data::findElementName(subname) == subname) { TopoShape ts = static_cast(obj)->Shape.getShape(); - if (!transform) { + if (!options.testFlag(ShapeOption::Transform)) { ts.setShape(ts.getShape().Located(TopLoc_Location()), false); } - if (noElementMap) { + if (options.testFlag(ShapeOption::NoElementMap)) { ts = ts.getSubShape(subname, true); } else { @@ -1289,7 +1306,7 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj, if (powner) { *powner = const_cast(obj); } - if (pmat && transform) { + if (pmat && options.testFlag(ShapeOption::Transform)) { *pmat = static_cast(obj)->Placement.getValue().toMatrix(); } return ts; @@ -1299,52 +1316,56 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj, Base::Matrix4D mat; auto shape = _getTopoShape(obj, + options, subname, - needSubElement, &mat, powner, - resolveLink, - noElementMap, hiddens, lastLink); - if (needSubElement && shape.shapeType(true) == TopAbs_COMPOUND) { - if (shape.countSubShapes(TopAbs_SOLID) == 1) - shape = shape.getSubTopoShape(TopAbs_SOLID, 1); - else if (shape.countSubShapes(TopAbs_COMPSOLID) == 1) - shape = shape.getSubTopoShape(TopAbs_COMPSOLID, 1); - else if (shape.countSubShapes(TopAbs_FACE) == 1) - shape = shape.getSubTopoShape(TopAbs_FACE, 1); - else if (shape.countSubShapes(TopAbs_SHELL) == 1) - shape = shape.getSubTopoShape(TopAbs_SHELL, 1); - else if (shape.countSubShapes(TopAbs_EDGE) == 1) - shape = shape.getSubTopoShape(TopAbs_EDGE, 1); - else if (shape.countSubShapes(TopAbs_WIRE) == 1) - shape = shape.getSubTopoShape(TopAbs_WIRE, 1); - else if (shape.countSubShapes(TopAbs_VERTEX) == 1) - shape = shape.getSubTopoShape(TopAbs_VERTEX, 1); + if (options.testFlag(ShapeOption::NeedSubElement) + && !options.testFlag(ShapeOption::DontSimplifyCompound) + && shape.shapeType(true) == TopAbs_COMPOUND) { + shape = simplifyCompound(shape); } + Base::Matrix4D topMat; - if (pmat || transform) { - // Obtain top level transformation - if (pmat) { - topMat = *pmat; - } - if (transform) { - obj->getSubObject(nullptr, nullptr, &topMat); - } + if (pmat) { + topMat = *pmat; + } + if (options.testFlag(ShapeOption::Transform)) { + obj->getSubObject(nullptr, nullptr, &topMat); + } + if ((pmat || options.testFlag(ShapeOption::Transform)) && !shape.isNull()) { - // Apply the top level transformation - if (!shape.isNull()) { - shape.transformShape(topMat, false, true); - } - - if (pmat) { - *pmat = topMat * mat; - } + shape.transformShape(topMat, false, true); + } + if (pmat) { + *pmat = topMat * mat; } return shape; } +TopoShape Feature::simplifyCompound(TopoShape compoundShape) +{ + std::initializer_list simplificationOrder = { + TopAbs_SOLID, + TopAbs_COMPSOLID, + TopAbs_FACE, + TopAbs_SHELL, + TopAbs_SHELL, + TopAbs_WIRE, + TopAbs_VERTEX}; + + auto foundSimplification = + std::ranges::find_if(simplificationOrder, + [&](TopAbs_ShapeEnum topType) { + return compoundShape.countSubShapes(topType) == 1; + }); + if (foundSimplification != simplificationOrder.end()) { + return compoundShape.getSubTopoShape(*foundSimplification, 1); + } + return compoundShape; +} App::DocumentObject *Feature::getShapeOwner(const App::DocumentObject *obj, const char *subname) { @@ -1698,7 +1719,12 @@ bool Feature::isElementMappingDisabled(App::PropertyContainer* container) bool Feature::getCameraAlignmentDirection(Base::Vector3d& directionZ, Base::Vector3d &directionX, const char* subname) const { - const auto topoShape = getTopoShape(this, subname, true); + const auto topoShape = getTopoShape(this, + ShapeOptions( + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform), + subname); if (topoShape.isNull()) { return false; diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index 2496c4032a..8389417821 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -44,6 +45,18 @@ struct HistoryItem; namespace Part { +enum class ShapeOption +{ + NoFlag = 0, + NeedSubElement = 1, + ResolveLink = 2, + Transform = 4, + NoElementMap = 8, + DontSimplifyCompound = 16 +}; +using ShapeOptions = Base::Flags; + + class PartFeaturePy; /** Base class of all shape feature classes in FreeCAD @@ -130,15 +143,15 @@ public: * @param transform: if true, apply obj's transformation. Set to false * if pmat already include obj's transformation matrix. */ - static TopoDS_Shape getShape(const App::DocumentObject *obj, - const char *subname=nullptr, bool needSubElement=false, Base::Matrix4D *pmat=nullptr, - App::DocumentObject **owner=nullptr, bool resolveLink=true, bool transform=true); + static TopoDS_Shape getShape(const App::DocumentObject *obj, ShapeOptions options, + const char *subname=nullptr, Base::Matrix4D *pmat=nullptr, + App::DocumentObject **owner=nullptr); - static TopoShape getTopoShape(const App::DocumentObject *obj, - const char *subname=nullptr, bool needSubElement=false, Base::Matrix4D *pmat=nullptr, - App::DocumentObject **owner=nullptr, bool resolveLink=true, bool transform=true, - bool noElementMap=false); + static TopoShape getTopoShape(const App::DocumentObject* obj, ShapeOptions options, + const char* subname=nullptr, Base::Matrix4D* pmat=nullptr, + App::DocumentObject**owner=nullptr); + static TopoShape simplifyCompound(TopoShape compoundShape); static void clearShapeCache(); static App::DocumentObject *getShapeOwner(const App::DocumentObject *obj, const char *subname=nullptr); @@ -282,6 +295,7 @@ bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, } //namespace Part +ENABLE_BITMASK_OPERATORS(Part::ShapeOption) #endif // PART_FEATURE_H diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index f9e5643fcb..4a8fe0d37a 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -90,7 +90,7 @@ App::DocumentObjectExecReturn* RuledSurface::getShape(const App::PropertyLinkSub TopoDS_Shape& shape) const { App::DocumentObject* obj = link.getValue(); - const Part::TopoShape part = Part::Feature::getTopoShape(obj); + const Part::TopoShape part = Part::Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform); if (part.isNull()) { return new App::DocumentObjectExecReturn("No shape linked."); } @@ -127,7 +127,7 @@ App::DocumentObjectExecReturn* RuledSurface::execute() std::array links = {&Curve1, &Curve2}; for (auto link : links) { App::DocumentObject* obj = link->getValue(); - const Part::TopoShape part = Part::Feature::getTopoShape(obj); + const Part::TopoShape part = Part::Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform); if (part.isNull()) { return new App::DocumentObjectExecReturn("No shape linked."); } @@ -140,7 +140,11 @@ App::DocumentObjectExecReturn* RuledSurface::execute() return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked."); } else { - shapes.push_back(getTopoShape(link->getValue(), subs.front().c_str(), true)); + shapes.push_back(getTopoShape(link->getValue(), + ShapeOption::NeedSubElement + | ShapeOption::ResolveLink + | ShapeOption::Transform, + subs.front().c_str())); } if (shapes.back().isNull()) { return new App::DocumentObjectExecReturn("Invalid link."); @@ -216,7 +220,7 @@ App::DocumentObjectExecReturn* Loft::execute() try { std::vector shapes; for (auto& obj : Sections.getValues()) { - shapes.emplace_back(getTopoShape(obj)); + shapes.emplace_back(getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform)); if (shapes.back().isNull()) { return new App::DocumentObjectExecReturn("Invalid section link"); } @@ -300,7 +304,7 @@ App::DocumentObjectExecReturn* Sweep::execute() if (!Spine.getValue()) { return new App::DocumentObjectExecReturn("No spine"); } - TopoShape spine = getTopoShape(Spine.getValue()); + TopoShape spine = getTopoShape(Spine.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform); const auto& subs = Spine.getSubValues(); if (spine.isNull()) { return new App::DocumentObjectExecReturn("Invalid spine"); @@ -319,7 +323,7 @@ App::DocumentObjectExecReturn* Sweep::execute() std::vector shapes; shapes.push_back(spine); for (auto& obj : Sections.getValues()) { - shapes.emplace_back(getTopoShape(obj)); + shapes.emplace_back(getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform)); if (shapes.back().isNull()) { return new App::DocumentObjectExecReturn("Invalid section link"); } @@ -415,7 +419,7 @@ void Thickness::handleChangedPropertyType(Base::XMLReader& reader, App::DocumentObjectExecReturn* Thickness::execute() { std::vector shapes; - auto base = getTopoShape(Faces.getValue()); + auto base = getTopoShape(Faces.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform); if (base.isNull()) { return new App::DocumentObjectExecReturn("Invalid source shape"); } @@ -485,7 +489,7 @@ Reverse::Reverse() App::DocumentObjectExecReturn* Reverse::execute() { App::DocumentObject* source = Source.getValue(); - Part::TopoShape topoShape = Part::Feature::getTopoShape(source); + Part::TopoShape topoShape = Part::Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform); if (topoShape.isNull()) { return new App::DocumentObjectExecReturn("No part object linked."); } diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index b86d5343ee..efe07d270c 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -263,7 +263,7 @@ std::vector getShapesFromSelection() std::vector objs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId()); std::vector shapes; for (auto it : objs) { - Part::TopoShape shp = Part::Feature::getTopoShape(it); + Part::TopoShape shp = Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!shp.isNull()){ shapes.push_back(shp); } @@ -279,8 +279,7 @@ bool hasShapesInSelection() bool hasShapes = false; std::vector docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId()); for (auto it : docobjs) { - // Only check for the existence of a shape but don't perform a transformation - if (!Part::Feature::getTopoShape(it, nullptr, false, nullptr, nullptr, true, false, false).isNull()) { + if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink).isNull()) { hasShapes = true; break; } @@ -321,7 +320,7 @@ void CmdPartCut::activated(int iMsg) std::vector names; for (const auto & it : Sel) { const App::DocumentObject* obj = it.getObject(); - const TopoDS_Shape& shape = Part::Feature::getShape(obj); + const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n" @@ -380,7 +379,7 @@ void CmdPartCommon::activated(int iMsg) std::vector names; for (const auto & it : Sel) { const App::DocumentObject* obj = it.getObject(); - const TopoDS_Shape& shape = Part::Feature::getShape(obj); + const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n" @@ -434,7 +433,7 @@ void CmdPartFuse::activated(int iMsg) if (Sel.size() == 1){ numShapes = 1; //to be updated later in code Gui::SelectionObject selobj = Sel[0]; - TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject()); + TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); while (numShapes==1 && sh.ShapeType() == TopAbs_COMPOUND) { numShapes = 0; TopoDS_Iterator it(sh); @@ -458,7 +457,7 @@ void CmdPartFuse::activated(int iMsg) std::vector names; for (const auto & it : Sel) { const App::DocumentObject* obj = it.getObject(); - const TopoDS_Shape& shape = Part::Feature::getShape(obj); + const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n" @@ -1102,7 +1101,7 @@ void CmdPartMakeSolid::activated(int iMsg) (App::DocumentObject::getClassTypeId(), nullptr, Gui::ResolveMode::FollowLink); runCommand(Doc, "import Part"); for (auto it : objs) { - const TopoDS_Shape& shape = Part::Feature::getShape(it); + const TopoDS_Shape& shape = Part::Feature::getShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!shape.IsNull()) { TopAbs_ShapeEnum type = shape.ShapeType(); QString str; @@ -1180,7 +1179,7 @@ void CmdPartReverseShape::activated(int iMsg) (App::DocumentObject::getClassTypeId()); openCommand(QT_TRANSLATE_NOOP("Command", "Reverse")); for (auto it : objs) { - const TopoDS_Shape& shape = Part::Feature::getShape(it); + const TopoDS_Shape& shape = Part::Feature::getShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!shape.IsNull()) { std::string name = it->getNameInDocument(); name += "_rev"; @@ -1619,7 +1618,7 @@ void CmdPartOffset::activated(int iMsg) std::vector docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId()); std::vector shapes; for (auto it : docobjs) { - if (!Part::Feature::getTopoShape(it).isNull()) { + if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) { shapes.push_back(it); } } @@ -1677,7 +1676,7 @@ void CmdPartOffset2D::activated(int iMsg) std::vector shapes; for (auto it : docobjs) { - if (!Part::Feature::getTopoShape(it).isNull()) { + if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) { shapes.push_back(it); } } @@ -1831,7 +1830,7 @@ void CmdPartThickness::activated(int iMsg) selection = selobjs[0].getAsPropertyLinkSubString(); const std::vector& subnames = selobjs[0].getSubNames(); obj = selobjs[0].getObject(); - topoShape = Part::Feature::getTopoShape(obj); + topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!topoShape.isNull()) { for (std::vector::const_iterator it = subnames.begin(); it != subnames.end(); ++it) { subShapes.emplace_back(topoShape.getSubShape(subnames[0].c_str())); @@ -1966,17 +1965,26 @@ void CmdPartRuledSurface::activated(int iMsg) docobj1 = selobjs[0].getObject(); obj1 = docobj1->getNameInDocument(); obj2 = obj1; //changed later if 2 objects were selected - const Part::TopoShape& shape1 = Part::Feature::getTopoShape(docobj1); + const Part::TopoShape& shape1 = Part::Feature::getTopoShape(docobj1, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape1.isNull()) { ok = false; } if (ok && subnames1.size() <= 2) { if (!subnames1.empty()) { - curve1 = Part::Feature::getTopoShape(docobj1, subnames1[0].c_str(), true /*need element*/).getShape(); + curve2 = Part::Feature::getTopoShape(docobj1, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subnames1[0].c_str()).getShape(); + link1 = subnames1[0]; } if (subnames1.size() == 2) { - curve2 = Part::Feature::getTopoShape(docobj1, subnames1[1].c_str(), true /*need element*/).getShape(); + curve2 = Part::Feature::getTopoShape(docobj1, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subnames1[1].c_str()).getShape(); link2 = subnames1[1]; } if (subnames1.empty()) { @@ -1991,12 +1999,17 @@ void CmdPartRuledSurface::activated(int iMsg) docobj2 = selobjs[1].getObject(); obj2 = docobj2->getNameInDocument(); - const Part::TopoShape& shape2 = Part::Feature::getTopoShape(docobj2); + const Part::TopoShape& shape2 = Part::Feature::getTopoShape(docobj2, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape2.isNull()) { ok = false; } if (ok && subnames2.size() == 1) { - curve2 = Part::Feature::getTopoShape(docobj2, subnames2[0].c_str(), true /*need element*/).getShape(); + curve2 = Part::Feature::getTopoShape(docobj2, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subnames2[0].c_str()).getShape(); + link2 = subnames2[0]; } else { if (subnames2.empty()) { diff --git a/src/Mod/Part/Gui/CrossSections.cpp b/src/Mod/Part/Gui/CrossSections.cpp index 7f6dfa06eb..6907f7553e 100644 --- a/src/Mod/Part/Gui/CrossSections.cpp +++ b/src/Mod/Part/Gui/CrossSections.cpp @@ -215,7 +215,7 @@ void CrossSections::apply() getObjectsOfType(App::DocumentObject::getClassTypeId()); std::vector obj; for (auto it : docobjs) { - if (!Part::Feature::getTopoShape(it).isNull()) { + if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) { obj.push_back(it); } } diff --git a/src/Mod/Part/Gui/DlgExtrusion.cpp b/src/Mod/Part/Gui/DlgExtrusion.cpp index c7f0bbb621..8324c8b97e 100644 --- a/src/Mod/Part/Gui/DlgExtrusion.cpp +++ b/src/Mod/Part/Gui/DlgExtrusion.cpp @@ -77,12 +77,17 @@ public: std::string element(sSubName); if (element.substr(0,4) != "Edge") return false; - Part::TopoShape part = Part::Feature::getTopoShape(pObj); + Part::TopoShape part = Part::Feature::getTopoShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (part.isNull()) { return false; } try { - TopoDS_Shape sub = Part::Feature::getTopoShape(pObj, sSubName, true /*need element*/).getShape(); + TopoDS_Shape sub = Part::Feature::getTopoShape(pObj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sSubName).getShape(); + if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) { const TopoDS_Edge& edge = TopoDS::Edge(sub); BRepAdaptor_Curve adapt(edge); @@ -350,7 +355,7 @@ void DlgExtrusion::autoSolid() { try{ App::DocumentObject* dobj = &this->getShapeToExtrude(); - Part::TopoShape shape = Part::Feature::getTopoShape(dobj); + Part::TopoShape shape = Part::Feature::getTopoShape(dobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.isNull()) { return; } @@ -388,7 +393,7 @@ void DlgExtrusion::findShapes() std::vector objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape topoShape = Part::Feature::getTopoShape(obj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { continue; } @@ -467,7 +472,7 @@ void DlgExtrusion::apply() for (App::DocumentObject* sourceObj: objects) { assert(sourceObj); - if (Part::Feature::getTopoShape(sourceObj).isNull()){ + if (Part::Feature::getTopoShape(sourceObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()){ FC_ERR("Object " << sourceObj->getFullName() << " is not Part object (has no OCC shape). Can't extrude it."); continue; diff --git a/src/Mod/Part/Gui/DlgFilletEdges.cpp b/src/Mod/Part/Gui/DlgFilletEdges.cpp index ea0356bd02..4034b77597 100644 --- a/src/Mod/Part/Gui/DlgFilletEdges.cpp +++ b/src/Mod/Part/Gui/DlgFilletEdges.cpp @@ -626,7 +626,7 @@ void DlgFilletEdges::setupFillet(const std::vector& objs) std::vector subElements; QStandardItemModel *model = qobject_cast(ui->treeView->model()); bool block = model->blockSignals(true); // do not call toggleCheckState - auto baseShape = Part::Feature::getTopoShape(base); + auto baseShape = Part::Feature::getTopoShape(base, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); std::set elements; for(size_t i=0;i objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape topoShape = Part::Feature::getTopoShape(obj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { continue; } @@ -542,7 +542,7 @@ void DlgRevolution::autoSolid() { try{ App::DocumentObject &dobj = this->getShapeToRevolve(); - Part::TopoShape topoShape = Part::Feature::getTopoShape(&dobj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(&dobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { return; } else { diff --git a/src/Mod/Part/Gui/DlgScale.cpp b/src/Mod/Part/Gui/DlgScale.cpp index 1b4515284c..6a4d54b054 100644 --- a/src/Mod/Part/Gui/DlgScale.cpp +++ b/src/Mod/Part/Gui/DlgScale.cpp @@ -123,7 +123,7 @@ void DlgScale::findShapes() std::vector objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape topoShape = Part::Feature::getTopoShape(obj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { continue; } @@ -216,7 +216,7 @@ void DlgScale::apply() for (App::DocumentObject* sourceObj: objects) { assert(sourceObj); - if (Part::Feature::getTopoShape(sourceObj).isNull()){ + if (Part::Feature::getTopoShape(sourceObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()){ FC_ERR("Object " << sourceObj->getFullName() << " is not Part object (has no OCC shape). Can't scale it."); continue; diff --git a/src/Mod/Part/Gui/Mirroring.cpp b/src/Mod/Part/Gui/Mirroring.cpp index 86880d8692..911d125336 100644 --- a/src/Mod/Part/Gui/Mirroring.cpp +++ b/src/Mod/Part/Gui/Mirroring.cpp @@ -100,7 +100,12 @@ public: bool isEdge = false; //will be true if user selected edge subobject or if object only has 1 edge TopoDS_Shape shape; if (subString.length() > 0){ - shape = Part::Feature::getTopoShape(pObj, subString.c_str(), true).getShape(); + shape = Part::Feature::getTopoShape(pObj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sSubName).getShape(); + if (strstr(subString.c_str(), "Face")){ isFace = true; //was face subobject, e.g. Face3 } else { @@ -109,7 +114,8 @@ public: } } } else { - shape = Part::Feature::getShape(pObj); //no subobjects were selected, so this is entire shape of feature + //no subobjects were selected, so this is entire shape of feature + shape = Part::Feature::getShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); } // if there is only 1 face or 1 edge, then we don't need to force the user to select that face or edge @@ -250,7 +256,7 @@ void Mirroring::findShapes() std::vector objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape shape = Part::Feature::getTopoShape(obj); + Part::TopoShape shape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!shape.isNull()) { QString label = QString::fromUtf8(obj->Label.getValue()); QString name = QString::fromLatin1(obj->getNameInDocument()); diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.cpp b/src/Mod/Part/Gui/TaskCheckGeometry.cpp index 5ce8629a82..43c94f8de9 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.cpp +++ b/src/Mod/Part/Gui/TaskCheckGeometry.cpp @@ -443,7 +443,13 @@ void TaskCheckGeometryResults::goCheck() baseStream << " (" << label.c_str() << ")"; } - TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true); + TopoDS_Shape shape = Part::Feature::getShape( + sel.pObject, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sel.SubName); + if (shape.IsNull()) { ResultEntry *entry = new ResultEntry(); entry->parent = theRoot; diff --git a/src/Mod/Part/Gui/TaskLoft.cpp b/src/Mod/Part/Gui/TaskLoft.cpp index 3578a61a81..b1334829d4 100644 --- a/src/Mod/Part/Gui/TaskLoft.cpp +++ b/src/Mod/Part/Gui/TaskLoft.cpp @@ -99,7 +99,7 @@ void LoftWidget::findShapes() std::vector objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape topoShape = Part::Feature::getTopoShape(obj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { continue; } diff --git a/src/Mod/Part/Gui/TaskSweep.cpp b/src/Mod/Part/Gui/TaskSweep.cpp index 8371d3bb49..c1a485656e 100644 --- a/src/Mod/Part/Gui/TaskSweep.cpp +++ b/src/Mod/Part/Gui/TaskSweep.cpp @@ -80,7 +80,7 @@ public: if (Base::Tools::isNullOrEmpty(sSubName)) { // If selecting again the same edge the passed sub-element is empty. If the whole // shape is an edge or wire we can use it completely. - Part::TopoShape topoShape = Part::Feature::getTopoShape(pObj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { return false; } @@ -162,7 +162,7 @@ void SweepWidget::findShapes() std::vector objs = activeDoc->getObjectsOfType(); for (auto obj : objs) { - Part::TopoShape topoShape = Part::Feature::getTopoShape(obj); + Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (topoShape.isNull()) { continue; } @@ -225,7 +225,7 @@ bool SweepWidget::isPathValid(const Gui::SelectionObject& sel) const const std::vector& sub = sel.getSubNames(); TopoDS_Shape pathShape; - const Part::TopoShape& shape = Part::Feature::getTopoShape(path); + const Part::TopoShape& shape = Part::Feature::getTopoShape(path, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.isNull()){ return false; } @@ -295,10 +295,14 @@ bool SweepWidget::accept() docobj = selobjs[0].getObject(); spineObject = selobjs[0].getFeatName(); spineLabel = docobj->Label.getValue(); - topoShape = Part::Feature::getTopoShape(docobj); + topoShape = Part::Feature::getTopoShape(docobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!topoShape.isNull()) { for (std::vector::const_iterator it = subnames.begin(); it != subnames.end(); ++it) { - subShapes.push_back(Part::Feature::getTopoShape(docobj, subnames[0].c_str(), true /*need element*/)); + subShapes.push_back(Part::Feature::getTopoShape(docobj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subnames[0].c_str())); } for (const auto & it : subShapes) { TopoDS_Shape dsShape = it.getShape(); diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 9850151fea..30feec08bc 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -564,7 +564,7 @@ std::vector ViewProviderPartExt::getModelPoints(const SoPickedPo try { std::vector pts; std::string element = this->getElement(pp->getDetail()); - const auto &shape = Part::Feature::getTopoShape(getObject()); + const auto &shape = Part::Feature::getTopoShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); TopoDS_Shape subShape = shape.getSubShape(element.c_str()); @@ -943,7 +943,7 @@ void ViewProviderPartExt::updateVisual() haction.apply(this->lineset); haction.apply(this->nodeset); - TopoDS_Shape cShape = Part::Feature::getShape(getObject()); + TopoDS_Shape cShape = Part::Feature::getShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (cShape.IsNull()) { coords ->point .setNum(0); norm ->vector .setNum(0); diff --git a/src/Mod/PartDesign/App/FeatureBase.cpp b/src/Mod/PartDesign/App/FeatureBase.cpp index 497727f0fa..a55039dee4 100644 --- a/src/Mod/PartDesign/App/FeatureBase.cpp +++ b/src/Mod/PartDesign/App/FeatureBase.cpp @@ -69,7 +69,7 @@ App::DocumentObjectExecReturn* FeatureBase::execute() QT_TRANSLATE_NOOP("Exception", "BaseFeature must be a Part::Feature")); } - auto shape = Part::Feature::getTopoShape(BaseFeature.getValue()); + auto shape = Part::Feature::getTopoShape(BaseFeature.getValue(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (!shape.countSubShapes(TopAbs_SOLID)) { shape = shape.makeElementSolid(); } diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index 465ab8a841..1793357e4b 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -107,7 +107,7 @@ App::DocumentObjectExecReturn *Boolean::execute() std::vector shapes; shapes.push_back(baseTopShape); for(auto it=tools.begin(); it 1) { continue; } - TopoShape shape = Part::Feature::getTopoShape(obj, sub.c_str(), true); + TopoShape shape = Part::Feature::getTopoShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.c_str()); + if (shape.isNull()) { FC_ERR(getFullName() << ": failed to get profile shape " << obj->getFullName() << "." << sub); diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index e5f0f446d5..616b17305f 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -1855,7 +1855,11 @@ static gp_Pnt toPnt(gp_Vec dir) App::DocumentObjectExecReturn* Hole::execute() { - TopoShape profileshape = getProfileShape(); + TopoShape profileshape = + getProfileShape( Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform + | Part::ShapeOption::DontSimplifyCompound); // Find the base shape TopoShape base; diff --git a/src/Mod/PartDesign/App/FeatureLoft.cpp b/src/Mod/PartDesign/App/FeatureLoft.cpp index 440e8c2ff3..1bfe3cc696 100644 --- a/src/Mod/PartDesign/App/FeatureLoft.cpp +++ b/src/Mod/PartDesign/App/FeatureLoft.cpp @@ -77,13 +77,17 @@ Loft::getSectionShape(const char *name, auto subName = subs.empty() ? "" : subs.front(); auto useEntireSketch = obj->isDerivedFrom() && subName.find("Vertex") != 0; if (subs.empty() || std::ranges::find(subs, std::string()) != subs.end() || useEntireSketch ) { - shapes.push_back(Part::Feature::getTopoShape(obj)); + shapes.push_back(Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform)); if (shapes.back().isNull()) FC_THROWM(Part::NullShapeException, "Failed to get shape of " << name << " " << App::SubObjectT(obj, "").getSubObjectFullName(obj->getDocument()->getName())); } else { for (const auto &sub : subs) { - shapes.push_back(Part::Feature::getTopoShape(obj, sub.c_str(), /*needSubElement*/true)); + shapes.push_back(Part::Feature::getTopoShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.c_str())); if (shapes.back().isNull()) FC_THROWM(Part::NullShapeException, "Failed to get shape of " << name << " " << App::SubObjectT(obj, sub.c_str()).getSubObjectFullName(obj->getDocument()->getName())); diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index bce77bfae3..709ae3ba99 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -184,13 +184,18 @@ TopoShape ProfileBased::getTopoShapeVerifiedFace(bool silent, TopoShape shape; if (AllowMultiFace.getValue()) { if (subs.empty()) { - shape = Part::Feature::getTopoShape(obj); + shape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); } else { std::vector shapes; for (auto& sub : subs) { - auto subshape = - Part::Feature::getTopoShape(obj, sub.c_str(), /*needSubElement*/ true); + auto subshape = Part::Feature::getTopoShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.c_str()); + + if (subshape.isNull()) { FC_THROWM(Base::CADKernelError, "Sub shape not found: " << obj->getFullName() << "." << sub); @@ -207,7 +212,11 @@ TopoShape ProfileBased::getTopoShapeVerifiedFace(bool silent, sub = subs[0]; } } - shape = Part::Feature::getTopoShape(obj, sub.c_str(), !sub.empty()); + shape = Part::Feature::getTopoShape(obj, + (sub.empty() ? Part::ShapeOption::NoFlag : Part::ShapeOption::NeedSubElement) + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.c_str()); } if (shape.isNull()) { if (silent) { @@ -404,19 +413,20 @@ TopoDS_Shape ProfileBased::getVerifiedFace(bool silent) const { return TopoDS_Face(); } -TopoShape ProfileBased::getProfileShape() const +TopoShape ProfileBased::getProfileShape(Part::ShapeOptions subShapeOptions) const { TopoShape shape; const auto& subs = Profile.getSubValues(); auto profile = Profile.getValue(); if (subs.empty()) { - shape = Part::Feature::getTopoShape(profile); + shape = Part::Feature::getTopoShape(profile, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); } else { std::vector shapes; for (auto& sub : subs) { - shapes.push_back( - Part::Feature::getTopoShape(profile, sub.c_str(), /* needSubElement */ true)); + shapes.push_back(Part::Feature::getTopoShape(profile, + subShapeOptions, + sub.c_str())); } shape = TopoShape(shape.Tag).makeElementCompound(shapes); } @@ -567,9 +577,11 @@ TopoShape ProfileBased::getTopoShapeSupportFace() const const auto& Support = sketch->AttachmentSupport; App::DocumentObject* ref = Support.getValue(); shape = Part::Feature::getTopoShape( - ref, - Support.getSubValues().size() ? Support.getSubValues()[0].c_str() : "", - true); + ref, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + Support.getSubValues().empty() ? "" : Support.getSubValues()[0].c_str()); } if (!shape.isNull()) { if (shape.shapeType(true) != TopAbs_FACE) { @@ -663,7 +675,13 @@ void ProfileBased::getUpToFaceFromLinkSub(TopoShape& upToFace, const App::Proper } const auto& subs = refFace.getSubValues(); - upToFace = Part::Feature::getTopoShape(ref, subs.size() ? subs[0].c_str() : nullptr, true); + upToFace = Part::Feature::getTopoShape( + ref, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subs.empty() ? nullptr : subs[0].c_str()); + if (!upToFace.hasSubShape(TopAbs_FACE)) { throw Base::ValueError("SketchBased: Up to face: Failed to extract face"); } @@ -687,7 +705,12 @@ int ProfileBased::getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::P auto subStrings = subSet.second; if (subStrings.empty() || subStrings[0].empty()) { - TopoShape baseShape = Part::Feature::getTopoShape(ref, nullptr, true); + TopoShape baseShape = Part::Feature::getTopoShape(ref, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform); + + for (auto face : baseShape.getSubTopoShapes(TopAbs_FACE)){ faceList.push_back(face); ret ++; @@ -695,7 +718,13 @@ int ProfileBased::getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::P } else { for (auto &subString : subStrings){ - auto shape = Part::Feature::getTopoShape(ref, subString.c_str(), true); + auto shape = Part::Feature::getShape( + ref, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + subString.c_str()); + TopoShape face = shape; face = face.makeElementFace(); if (face.isNull()) { @@ -1419,7 +1448,7 @@ Base::Vector3d ProfileBased::getProfileNormal() const { if (shape.hasSubShape(TopAbs_EDGE)) { // Find the first planar face that contains the edge, and return the plane normal - TopoShape objShape = Part::Feature::getTopoShape(obj); + TopoShape objShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); for (int idx : objShape.findAncestors(shape.getSubShape(TopAbs_EDGE, 1), TopAbs_FACE)) { if (objShape.getSubTopoShape(TopAbs_FACE, idx).findPlane(pln)) { gp_Dir dir = pln.Axis().Direction(); diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 08be8a10ef..8d71e1c1b8 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -131,7 +131,11 @@ public: virtual Base::Vector3d getProfileNormal() const; - TopoShape getProfileShape() const; + // Use Part::ShapeOptions enum to pass flags + TopoShape getProfileShape(Part::ShapeOptions subShapeOptions = + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform) const; /// retrieves the number of axes in the linked sketch (defined as construction lines) int getSketchAxisCount() const; diff --git a/src/Mod/PartDesign/App/ShapeBinder.cpp b/src/Mod/PartDesign/App/ShapeBinder.cpp index 399d4a0ead..a34f94640b 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.cpp +++ b/src/Mod/PartDesign/App/ShapeBinder.cpp @@ -670,7 +670,11 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) { for (const auto& sub : subs) { ++subidx; try { - auto shape = Part::Feature::getTopoShape(obj, sub.c_str(), true); + auto shape = Part::Feature::getTopoShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + sub.c_str()); if (!shape.isNull()) { shapes.push_back(shape); shapeOwners.emplace_back(sidx, subidx); diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp index 4f8987f192..e9466efe63 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp @@ -151,7 +151,8 @@ void TaskDressUpParameters::addAllEdges(QListWidget* widget) if (!base) { return; } - int count = Part::Feature::getTopoShape(base).countSubShapes(TopAbs_EDGE); + int count = Part::Feature::getTopoShape(base, Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform).countSubShapes(TopAbs_EDGE); auto subValues = pcDressUp->Base.getSubValues(false); std::size_t len = subValues.size(); for (int i = 0; i < count; ++i) { diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index f54be7fdda..464b7e3b12 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -7099,7 +7099,9 @@ int SketchObject::addExternal(App::DocumentObject* Obj, return -1; } - auto wholeShape = Part::Feature::getTopoShape(Obj); + auto wholeShape = + Part::Feature::getTopoShape(Obj, + Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); auto shape = wholeShape.getSubTopoShape(SubName, /*silent*/ true); TopAbs_ShapeEnum shapeType = TopAbs_SHAPE; if (shape.shapeType(/*silent*/ true) != TopAbs_FACE) { diff --git a/src/Mod/Surface/App/Blending/FeatureBlendCurve.cpp b/src/Mod/Surface/App/Blending/FeatureBlendCurve.cpp index 41d115f035..b7542c037b 100644 --- a/src/Mod/Surface/App/Blending/FeatureBlendCurve.cpp +++ b/src/Mod/Surface/App/Blending/FeatureBlendCurve.cpp @@ -136,12 +136,15 @@ BlendPoint FeatureBlendCurve::GetBlendPoint(App::PropertyLinkSub& link, TopoDS_Shape axEdge; if (link.getSubValues().size() > 0 && link.getSubValues()[0].length() > 0) { - axEdge = - Feature::getTopoShape(linked, link.getSubValues()[0].c_str(), true /*need element*/) - .getShape(); + axEdge = Part::Feature::getShape(linked, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + link.getSubValues()[0].c_str()); } else { - axEdge = Feature::getShape(linked); + axEdge = Feature::getShape(linked, + Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); } if (axEdge.IsNull()) { diff --git a/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp b/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp index aecb2be68b..ec74750624 100644 --- a/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp +++ b/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp @@ -345,7 +345,7 @@ bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, const Part: // no match in refObj, so now search the cached objects for (auto& objectName : m_3dObjectCache) { auto object3d = getDimension()->getDocument()->getObject(objectName.c_str()); - auto shape3d = Part::Feature::getShape(object3d); + auto shape3d = Part::Feature::getShape(object3d, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); auto edgesAll = getDimension()->getEdges(shape3d); size_t iEdge {1}; for (auto& edge : edgesAll) { @@ -531,7 +531,7 @@ ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj, { // Base::Console().message("DAC::searchObjForEdge(%s)\n", obj->Label.getValue()); (void)exact; - auto shape3d = Part::Feature::getShape(obj); + auto shape3d = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape3d.IsNull()) { // how to handle this? return {}; diff --git a/src/Mod/TechDraw/App/DimensionReferences.cpp b/src/Mod/TechDraw/App/DimensionReferences.cpp index c756a457f6..d5581b2e10 100644 --- a/src/Mod/TechDraw/App/DimensionReferences.cpp +++ b/src/Mod/TechDraw/App/DimensionReferences.cpp @@ -309,7 +309,7 @@ bool ReferenceEntry::hasGeometry() const // 3d reference // TODO: shouldn't this be ShapeFinder.getLocatedShape? - auto shape = Part::Feature::getTopoShape(getObject()); + auto shape = Part::Feature::getTopoShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); auto subShape = shape.getSubShape(getSubName().c_str()); return !subShape.IsNull(); diff --git a/src/Mod/TechDraw/App/DrawComplexSection.cpp b/src/Mod/TechDraw/App/DrawComplexSection.cpp index e5bc9ca01d..2d461d3c79 100644 --- a/src/Mod/TechDraw/App/DrawComplexSection.cpp +++ b/src/Mod/TechDraw/App/DrawComplexSection.cpp @@ -594,7 +594,7 @@ TopoDS_Wire DrawComplexSection::makeProfileWire(App::DocumentObject* toolObj) return {}; } - TopoDS_Shape toolShape = Part::Feature::getShape(toolObj); + TopoDS_Shape toolShape = Part::Feature::getShape(toolObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (toolShape.IsNull()) { return {}; } @@ -709,7 +709,7 @@ TopoDS_Wire DrawComplexSection::makeSectionLineWire() App::DocumentObject* toolObj = CuttingToolWireObject.getValue(); DrawViewPart* baseDvp = freecad_cast(BaseView.getValue()); if (baseDvp) { - TopoDS_Shape toolShape = Part::Feature::getShape(toolObj); + TopoDS_Shape toolShape = Part::Feature::getShape(toolObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (toolShape.IsNull()) { // CuttingToolWireObject is likely still restoring and has no shape yet return {}; @@ -968,7 +968,7 @@ bool DrawComplexSection::canBuild(gp_Ax2 sectionCS, App::DocumentObject* profile return false; } - TopoDS_Shape shape = Part::Feature::getShape(profileObject); + TopoDS_Shape shape = Part::Feature::getShape(profileObject, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (BRep_Tool::IsClosed(shape)) { //closed profiles don't have a profile vector but should always make a section? return true; @@ -1090,7 +1090,7 @@ TopoDS_Wire DrawComplexSection::makeNoseToTailWire(const TopoDS_Wire& inWire) bool DrawComplexSection::isProfileObject(App::DocumentObject* obj) { //if the object's shape is a wire or an edge, then it can be a profile object - TopoDS_Shape shape = Part::Feature::getShape(obj); + TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.IsNull()) { return false; } @@ -1104,7 +1104,7 @@ bool DrawComplexSection::isProfileObject(App::DocumentObject* obj) bool DrawComplexSection::isMultiSegmentProfile(App::DocumentObject* obj) { //if the object's shape is a wire or an edge, then it can be a profile object - TopoDS_Shape shape = Part::Feature::getShape(obj); + TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.IsNull()) { return false; } @@ -1132,7 +1132,7 @@ bool DrawComplexSection::isMultiSegmentProfile(App::DocumentObject* obj) //check if the profile has curves in it bool DrawComplexSection::isLinearProfile(App::DocumentObject* obj) { - TopoDS_Shape shape = Part::Feature::getShape(obj); + TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.IsNull()) { return false; } diff --git a/src/Mod/TechDraw/App/ShapeExtractor.cpp b/src/Mod/TechDraw/App/ShapeExtractor.cpp index c50f8d81cf..3361ad39dc 100644 --- a/src/Mod/TechDraw/App/ShapeExtractor.cpp +++ b/src/Mod/TechDraw/App/ShapeExtractor.cpp @@ -135,7 +135,7 @@ TopoDS_Shape ShapeExtractor::getShapes(const std::vector l } } else { - auto shape = Part::Feature::getShape(obj); + auto shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); // if source obj has a shape, we use that shape. if(!SU::isShapeReallyNull(shape)) { if (checkShape(obj, shape)) { @@ -225,7 +225,8 @@ std::vector ShapeExtractor::getXShapes(const App::Link* xLink) childNeedsTransform = true; } } - auto shape = Part::Feature::getShape(l); // TODO: getTopoShape() ? + // TODO: getTopoShape() ? + auto shape = Part::Feature::getShape(l, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); Part::TopoShape ts(shape); if (ts.isInfinite()) { shape = ShapeFinder::stripInfiniteShapes(shape); @@ -280,7 +281,7 @@ TopoDS_Shape ShapeExtractor::getShapeFromXLink(const App::Link* xLink) App::DocumentObject* linkedObject = xLink->getLink(depth); if (linkedObject) { // have a linked object, get the shape - TopoDS_Shape shape = Part::Feature::getShape(linkedObject); + TopoDS_Shape shape = Part::Feature::getShape(linkedObject, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); if (shape.IsNull()) { // this is where we need to parse the target for objects with a shape?? return TopoDS_Shape(); @@ -465,7 +466,7 @@ Base::Vector3d ShapeExtractor::getLocation3dFromFeat(const App::DocumentObject* //! get the located and oriented version of docObj shape TopoDS_Shape ShapeExtractor::getLocatedShape(const App::DocumentObject* docObj) { - Part::TopoShape shape = Part::Feature::getTopoShape(docObj); + Part::TopoShape shape = Part::Feature::getTopoShape(docObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); const Part::Feature* pf = dynamic_cast(docObj); if (pf) { shape.setPlacement(pf->globalPlacement()); diff --git a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp index 7d9b4dc759..0c5b137723 100644 --- a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp +++ b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp @@ -645,7 +645,12 @@ std::pair DrawGuiUtil::getProjDirFromFace(App::D projDir = d3Dirs.first; rotVec = d3Dirs.second; - auto ts = Part::Feature::getShape(obj, faceName.c_str(), true); + auto ts = Part::Feature::getShape(obj, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, + faceName.c_str()); + if (ts.IsNull() || ts.ShapeType() != TopAbs_FACE) { Base::Console().warning("getProjDirFromFace(%s) is not a Face\n", faceName.c_str()); return dirs;