From 7a4bc95d47885e0d704dcad03d9db2db9c80864f Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 27 Jun 2024 16:56:16 -0400 Subject: [PATCH] Toponaming: Transfer in missing Code for BaseFeatures and Sketches --- src/Mod/Part/App/BodyBase.cpp | 6 ++ src/Mod/Part/App/PartFeature.cpp | 31 +++--- src/Mod/PartDesign/App/Body.cpp | 62 ++++++++++- src/Mod/PartDesign/App/FeatureBase.cpp | 31 ++++-- src/Mod/Sketcher/App/SketchObject.cpp | 144 +++++++++++++++++++++++-- src/Mod/Sketcher/App/SketchObject.h | 3 + 6 files changed, 240 insertions(+), 37 deletions(-) diff --git a/src/Mod/Part/App/BodyBase.cpp b/src/Mod/Part/App/BodyBase.cpp index 8b26c78e14..7bef103057 100644 --- a/src/Mod/Part/App/BodyBase.cpp +++ b/src/Mod/Part/App/BodyBase.cpp @@ -52,6 +52,12 @@ BodyBase* BodyBase::findBodyOf(const App::DocumentObject* f) if (body->hasObject(f)) return body; } + // for(;;) { + // auto group = App::GeoFeatureGroupExtension::getGroupOfObject(f); + // if(!group || group->isDerivedFrom(BodyBase::getClassTypeId())) + // return static_cast(group); + // f = group; + // } } return nullptr; diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index 50795b6b08..f64183646a 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -387,10 +387,11 @@ App::DocumentObject* Feature::getSubObject(const char* subname, TopoShape ts(Shape.getShape()); bool doTransform = mat != ts.getTransform(); if (doTransform) { - ts.setShape(ts.getShape().Located(TopLoc_Location())); + ts.setShape(ts.getShape().Located(TopLoc_Location()), false); } if (subname && *subname && !ts.isNull()) { - ts = ts.getSubShape(subname); + // ts = ts.getSubShape(subname); // TODO WAS THIS WRONG? + ts = ts.getSubTopoShape(subname,true); } if (doTransform && !ts.isNull()) { static int sCopy = -1; @@ -483,13 +484,12 @@ static std::vector> getElementSource(App::Docu break; } } - // TODO: 02/24 Toponaming project: It appears that getElementOwner is always nullptr. - // if (owner->isDerivedFrom(App::GeoFeature::getClassTypeId())) { - // auto o = - // static_cast(owner)->getElementOwner(ret.back().second); - // if (o) - // doc = o->getDocument(); - // } + if (owner->isDerivedFrom(App::GeoFeature::getClassTypeId())) { + auto o = + static_cast(owner)->getElementOwner(ret.back().second); + if (o) + doc = o->getDocument(); + } obj = doc->getObjectByID(tag < 0 ? -tag : tag); if (type) { for (auto& hist : history) { @@ -586,13 +586,12 @@ std::list Feature::getElementHistory(App::DocumentObject* fea break; } } - // TODO: 02/24 Toponaming project: It appears that getElementOwner is always nullptr. - // if(feature->isDerivedFrom(App::GeoFeature::getClassTypeId())) { - // auto owner = - // static_cast(feature)->getElementOwner(element); - // if(owner) - // doc = owner->getDocument(); - // } + if(feature->isDerivedFrom(App::GeoFeature::getClassTypeId())) { + auto owner = + static_cast(feature)->getElementOwner(element); + if(owner) + doc = owner->getDocument(); + } obj = doc->getObjectByID(std::abs(tag)); } if (!recursive) { diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index 930b160ba0..0ca740c239 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -32,6 +32,7 @@ #include "BodyPy.h" #include "FeatureBase.h" #include "FeatureSketchBased.h" +#include "FeatureSolid.h" #include "FeatureTransformed.h" #include "ShapeBinder.h" @@ -118,6 +119,22 @@ App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start) start = Tip.getValue(); } +// +// #ifdef FC_USE_TNP_FIX +// int index; +// if (!start || !start->getNameInDocument() +// // || start->isDerivedFrom(PartDesign::Extrusion::getClassTypeId()) +// || start->isDerivedFrom(PartDesign::Solid::getClassTypeId()) +// || !this->Group.find(start->getNameInDocument(), &index)) { // No Tip +// return nullptr; +// } +// const auto & objs = this->Group.getValues(); +// for (--index; index>=0; --index) { +// if (isSolidFeature(objs[index])) +// return objs[index]; +// } +// +// #else if (!start) { // No Tip return nullptr; } @@ -136,7 +153,7 @@ App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start) if (rvIt != features.rend()) { // the solid found in model list return *rvIt; } - +// #endif return nullptr; } @@ -146,6 +163,20 @@ App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start) start = Tip.getValue(); } +// #ifdef FC_USE_TNP_FIX +// int index; +// if (!start || !start->getNameInDocument() +// || !this->Group.find(start->getNameInDocument(), &index)) { // No Tip +// return nullptr; +// } +// +// const auto & objs = this->Group.getValues(); +// int count = this->Group.getSize(); +// for (++index; indexisDerivedFrom()) { if (PartDesign::Feature::isDatum(obj)) { // Datum objects are not solid @@ -375,6 +409,7 @@ std::vector Body::removeObject(App::DocumentObject* featur App::DocumentObjectExecReturn *Body::execute() { + Part::BodyBase::execute(); /* Base::Console().Error("Body '%s':\n", getNameInDocument()); App::DocumentObject* tip = Tip.getValue(); @@ -502,6 +537,29 @@ std::vector Body::getSubObjects(int reason) const { App::DocumentObject *Body::getSubObject(const char *subname, PyObject **pyObj, Base::Matrix4D *pmat, bool transform, int depth) const { + // while(subname && *subname=='.') ++subname; // skip leading . + // + // // PartDesign::Feature now support grouping sibling features, and the user + // // is free to expand/collapse at any time. To not disrupt subname path + // // because of this, the body will peek the next two sub-objects reference, + // // and skip the first sub-object if possible. + // if(subname) { + // const char * firstDot = strchr(subname,'.'); + // if (firstDot) { + // const char * secondDot = strchr(firstDot+1, '.'); + // if (secondDot) { + // auto firstObj = Group.find(std::string(subname, firstDot).c_str()); + // if (!firstObj || firstObj->isDerivedFrom(PartDesign::Feature::getClassTypeId())) { + // auto secondObj = Group.find(std::string(firstDot+1, secondDot).c_str()); + // if (secondObj) { + // // we support only one level of sibling grouping, so no + // // recursive call to our own getSubObject() + // return Part::BodyBase::getSubObject(firstDot+1,pyObj,pmat,transform,depth+1); + // } + // } + // } + // } + // } #if 1 return Part::BodyBase::getSubObject(subname,pyObj,pmat,transform,depth); #else diff --git a/src/Mod/PartDesign/App/FeatureBase.cpp b/src/Mod/PartDesign/App/FeatureBase.cpp index d7fc21cb66..add16252a6 100644 --- a/src/Mod/PartDesign/App/FeatureBase.cpp +++ b/src/Mod/PartDesign/App/FeatureBase.cpp @@ -52,21 +52,31 @@ short int FeatureBase::mustExecute() const { if(BaseFeature.isTouched()) return 1; - return Part::Feature::mustExecute(); + return PartDesign::Feature::mustExecute(); } -App::DocumentObjectExecReturn* FeatureBase::execute() { +App::DocumentObjectExecReturn* FeatureBase::execute() +{ - if(!BaseFeature.getValue()) - return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "BaseFeature link is not set")); + if (!BaseFeature.getValue()) { + return new App::DocumentObjectExecReturn( + QT_TRANSLATE_NOOP("Exception", "BaseFeature link is not set")); + } - if(!BaseFeature.getValue()->isDerivedFrom(Part::Feature::getClassTypeId())) - return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "BaseFeature must be a Part::Feature")); + if (!BaseFeature.getValue()->isDerivedFrom(Part::Feature::getClassTypeId())) { + return new App::DocumentObjectExecReturn( + QT_TRANSLATE_NOOP("Exception", "BaseFeature must be a Part::Feature")); + } - auto shape = static_cast(BaseFeature.getValue())->Shape.getValue(); - if (shape.IsNull()) - return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "BaseFeature has an empty shape")); + auto shape = Part::Feature::getTopoShape(BaseFeature.getValue()); + if (!shape.countSubShapes(TopAbs_SOLID)) { + shape = shape.makeElementSolid(); + } + if (shape.isNull()) { + return new App::DocumentObjectExecReturn( + QT_TRANSLATE_NOOP("Exception", "BaseFeature has an empty shape")); + } Shape.setValue(shape); @@ -91,7 +101,7 @@ void FeatureBase::onChanged(const App::Property* prop) { trySetBaseFeatureOfBody(); } - Part::Feature::onChanged(prop); + PartDesign::Feature::onChanged(prop); } void FeatureBase::onDocumentRestored() @@ -100,6 +110,7 @@ void FeatureBase::onDocumentRestored() auto body = getFeatureBody(); if (!body) Placement.setStatus(App::Property::Hidden, false); + PartDesign::Feature::onDocumentRestored(); } }//namespace PartDesign diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index c595c57d8b..f45284e5ff 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -85,6 +85,10 @@ #include "SketchObjectPy.h" #include "SolverGeometryExtension.h" +#include +#include +#include + #undef DEBUG // #define DEBUG @@ -265,7 +269,8 @@ void SketchObject::buildShape() Part::TopoShape vertex(TopoDS::Vertex(geo->toShape())); int idx = getVertexIndexGeoPos(i-1, Sketcher::PointPos::start); std::string name = convertSubName(Data::IndexedName::fromConst("Vertex", idx+1), false); - + vertex.setElementName(Data::IndexedName::fromConst("Vertex", 1), + Data::MappedName::fromRawData(name.c_str()), 0L); vertices.push_back(vertex); vertices.back().copyElementMap(vertex, Part::OpCodes::Sketch); } else { @@ -285,14 +290,14 @@ void SketchObject::buildShape() } // FIXME: Commented since ExternalGeometryFacade is not added - // for(i=2;itestFlag(ExternalGeometryExtension::Defining)) - // continue; - // shapes.push_back(getEdge(geo, convertSubName( - // Data::IndexedName::fromConst("ExternalEdge", i-1), false).c_str())); - // } + for(i=2;itestFlag(ExternalGeometryExtension::Defining)) + continue; + shapes.push_back(getEdge(geo, convertSubName( + Data::IndexedName::fromConst("ExternalEdge", i-1), false).c_str())); + } if(shapes.empty() && vertices.empty()) { Shape.setValue(Part::TopoShape()); return; @@ -9420,6 +9425,127 @@ bool SketchObject::AutoLockTangencyAndPerpty(Constraint* cstr, bool bForce, bool return true; } +App::DocumentObject *SketchObject::getSubObject( + const char *subname, PyObject **pyObj, + Base::Matrix4D *pmat, bool transform, int depth) const +{ + while(subname && *subname=='.') ++subname; // skip leading . + std::string sub; + const char *mapped = Data::isMappedElement(subname); + if(!subname || !subname[0]) + return Part2DObject::getSubObject(subname,pyObj,pmat,transform,depth); + const char *element = Data::findElementName(subname); + // if(element != subname) { + // const char *dot = strchr(subname,'.'); + // if(!dot) + // return 0; + // std::string name(subname,dot-subname); + // auto child = Exports.find(name.c_str()); + // if(!child) + // return 0; + // return child->getSubObject(dot+1,pyObj,pmat,true,depth+1); + // } + + Data::IndexedName indexedName = checkSubName(subname); + int index = indexedName.getIndex(); + const char * shapetype = indexedName.getType(); + const Part::Geometry *geo = 0; + Part::TopoShape subshape; + Base::Vector3d point; + + if (auto realType = convertInternalName(indexedName.getType())) { + if (realType[0] == '\0') + // subshape = InternalShape.getShape(); + subshape = Shape.getShape(); + else { + auto shapeType = Part::TopoShape::shapeType(realType, true); + if (shapeType != TopAbs_SHAPE) + // subshape = InternalShape.getShape().getSubTopoShape(shapeType, indexedName.getIndex(), true); + subshape = Shape.getShape().getSubTopoShape(shapeType, indexedName.getIndex(), true); + } + if (subshape.isNull()) + return nullptr; + } + else if (!pyObj || !mapped) { + if (!pyObj + || (index > 0 + && !boost::algorithm::contains(subname, "edge") + && !boost::algorithm::contains(subname, "vertex"))) + return Part2DObject::getSubObject(subname,pyObj,pmat,transform,depth); + } else { + subshape = Shape.getShape().getSubTopoShape(subname, true); + if (!subshape.isNull()) + return Part2DObject::getSubObject(subname,pyObj,pmat,transform,depth); + } + + if (subshape.isNull()) { + if (boost::equals(shapetype,"Edge") || + boost::equals(shapetype,"edge")) { + geo = getGeometry(index - 1); + if (!geo) + return nullptr; + } else if (boost::equals(shapetype,"ExternalEdge")) { + int GeoId = index - 1; + GeoId = -GeoId - 3; + geo = getGeometry(GeoId); + if(!geo) + return nullptr; + } else if (boost::equals(shapetype,"Vertex") || + boost::equals(shapetype,"vertex")) { + int VtId = index- 1; + int GeoId; + PointPos PosId; + getGeoVertexIndex(VtId,GeoId,PosId); + if (PosId==PointPos::none) + return nullptr; + point = getPoint(GeoId,PosId); + } + else if (boost::equals(shapetype,"RootPoint")) + point = getPoint(Sketcher::GeoEnum::RtPnt,PointPos::start); + else if (boost::equals(shapetype,"H_Axis")) + geo = getGeometry(Sketcher::GeoEnum::HAxis); + else if (boost::equals(shapetype,"V_Axis")) + geo = getGeometry(Sketcher::GeoEnum::VAxis); + else if (boost::equals(shapetype,"Constraint")) { + int ConstrId = PropertyConstraintList::getIndexFromConstraintName(shapetype); + const std::vector< Constraint * > &vals = this->Constraints.getValues(); + if (ConstrId < 0 || ConstrId >= int(vals.size())) + return nullptr; + if(pyObj) + *pyObj = vals[ConstrId]->getPyObject(); + return const_cast(this); + } else + return nullptr; + } + + if (pmat && transform) + *pmat *= Placement.getValue().toMatrix(); + + if (pyObj) { + Part::TopoShape shape; + std::string name = convertSubName(indexedName,false); + if (geo) { + shape = getEdge(geo,name.c_str()); + if(pmat && !shape.isNull()) + shape.transformShape(*pmat,false,true); + } else if (!subshape.isNull()) { + shape = subshape; + if (pmat) + shape.transformShape(*pmat,false,true); + } else { + if(pmat) + point = (*pmat)*point; + shape = BRepBuilderAPI_MakeVertex(gp_Pnt(point.x,point.y,point.z)).Vertex(); + shape.setElementName(Data::IndexedName::fromConst("Vertex", 1), + Data::MappedName::fromRawData(name.c_str()), 0); + } + shape.Tag = getID(); + *pyObj = Py::new_reference_to(Part::shape2pyshape(shape)); + } + + return const_cast(this); +} + void SketchObject::setExpression(const App::ObjectIdentifier& path, std::shared_ptr expr) { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 2a5ab1b713..41875a8dd5 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -672,6 +672,9 @@ public: bool& yinv, eReasonList* rsn = nullptr) const; + DocumentObject *getSubObject(const char *subname, PyObject **pyObj=0, + Base::Matrix4D *mat=0, bool transform=true, int depth=0) const override; + Part::TopoShape getEdge(const Part::Geometry* geo, const char* name) const; Data::IndexedName checkSubName(const char* sub) const;