diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index 2dd69ed34f..f3800133e6 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -301,7 +301,8 @@ Base::Placement AttachEngine::placementFactory(const gp_Dir &ZAxis, gp_Ax3 ax3;//OCC representation of the final placement if (!makeYVertical) { ax3 = gp_Ax3(Origin, ZAxis, XAxis); - } else if (!makeLegacyFlatFaceOrientation) { + } + else if (!makeLegacyFlatFaceOrientation) { //align Y along Z, if possible gp_Vec YAxis(0.0,0.0,1.0); XAxis = YAxis.Crossed(gp_Vec(ZAxis)); @@ -310,7 +311,8 @@ Base::Placement AttachEngine::placementFactory(const gp_Dir &ZAxis, XAxis = (gp_Vec(1,0,0)*ZAxis.Z()).Normalized(); } ax3 = gp_Ax3(Origin, ZAxis, XAxis); - } else if (makeLegacyFlatFaceOrientation) { + } + else if (makeLegacyFlatFaceOrientation) { //find out, to which axis of support Normal is closest to. //The result will be written into pos variable (0..2 = X..Z) if (!placeOfRef) @@ -386,13 +388,11 @@ void AttachEngine::suggestMapModes(SuggestResult &result) const result.message = SuggestResult::srLinkBroken; result.bestFitMode = mmDeactivated; - - std::vector parts; std::vector shapes; std::vector shapeStorage; std::vector typeStr; try{ - readLinks(getRefObjects(),subnames, parts, shapes, shapeStorage, typeStr); + readLinks(getRefObjects(),subnames, shapes, shapeStorage, typeStr); } catch (Base::Exception &err) { result.references_Types = typeStr; result.message = SuggestResult::srLinkBroken; @@ -578,11 +578,10 @@ eRefType AttachEngine::getShapeType(const App::DocumentObject *obj, const std::s //const_cast is worth here, to keep obj argument const. We are not going to write anything to obj through this temporary link. tmpLink.setValue(const_cast(obj), subshape.c_str()); - std::vector parts; std::vector shapes; std::vector copiedShapeStorage; std::vector types; - readLinks(tmpLink.getValues(),tmpLink.getSubValues(), parts, shapes, copiedShapeStorage, types); + readLinks(tmpLink.getValues(), tmpLink.getSubValues(), shapes, copiedShapeStorage, types); assert(types.size() == 1); return types[0]; @@ -815,102 +814,69 @@ GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector &objs, +void AttachEngine::readLinks(const std::vector& objs, const std::vector &subs, - std::vector &geofs, std::vector &shapes, std::vector &storage, std::vector &types) { - geofs.resize(objs.size()); storage.reserve(objs.size()); shapes.resize(objs.size()); types.resize(objs.size()); for (std::size_t i = 0; i < objs.size(); i++) { - std::string fullSub = subs[i]; - const char* element = Data::findElementName(fullSub.c_str()); - App::DocumentObject* obj = objs[i]->getSubObject(subs[i].c_str()); - - auto* geof = dynamic_cast(obj); + auto* geof = dynamic_cast(objs[i]); if (!geof) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: attached to a non App::GeoFeature '" - << obj->getNameInDocument() << "'"); + // Accept App::Links to GeoFeatures + geof = dynamic_cast(objs[i]->getLinkedObject()); + if (!geof) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: attached to a non App::GeoFeature '" << objs[i]->getNameInDocument() << "'"); + } } - geofs[i] = geof; TopoDS_Shape myShape; - Base::Placement plc = App::GeoFeature::getGlobalPlacement(obj, objs[i], fullSub); - if (geof->isDerivedFrom(App::Plane::getClassTypeId())) { - // obtain Z axis and origin of placement - Base::Vector3d norm; - plc.getRotation().multVec(Base::Vector3d(0.0, 0.0, 1.0), norm); - Base::Vector3d org; - plc.multVec(Base::Vector3d(), org); - // make shape - an local-XY plane infinite face - gp_Pln plane = gp_Pln(gp_Pnt(org.x, org.y, org.z), gp_Dir(norm.x, norm.y, norm.z)); - myShape = BRepBuilderAPI_MakeFace(plane).Shape(); - myShape.Infinite(true); - } - else if (geof->isDerivedFrom(App::Line::getClassTypeId())) { - // obtain X axis and origin of placement - Base::Vector3d dir; - plc.getRotation().multVec(Base::Vector3d(0.0, 0.0, 1.0), dir); - Base::Vector3d org; - plc.multVec(Base::Vector3d(), org); - // make shape - an infinite line along local X axis - gp_Lin line = gp_Lin(gp_Pnt(org.x, org.y, org.z), gp_Dir(dir.x, dir.y, dir.z)); - myShape = BRepBuilderAPI_MakeEdge(line).Shape(); - myShape.Infinite(true); - } - else if (geof->isDerivedFrom(App::Point::getClassTypeId())) { - Base::Vector3d org; - plc.multVec(Base::Vector3d(), org); - gp_Pnt pnt = gp_Pnt(org.x, org.y, org.z); - myShape = BRepBuilderAPI_MakeVertex(pnt).Shape(); - } - else { - try { - Part::TopoShape shape = Part::Feature::getTopoShape(geof, element, true); - for (;;) { - if (shape.isNull()) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " - << objs[i]->getNameInDocument() << '.' << subs[i]); - } - if (shape.shapeType() != TopAbs_COMPOUND - || shape.countSubShapes(TopAbs_SHAPE) != 1) { - break; - } - // auto extract the single sub-shape from a compound - shape = shape.getSubTopoShape(TopAbs_SHAPE, 1); + try { + // getTopoShape support fully qualified subnames and should return shape with correct + // global placement. + Part::TopoShape shape = Part::Feature::getTopoShape(objs[i], subs[i].c_str(), true); + for (;;) { + if (shape.isNull()) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " + << objs[i]->getNameInDocument() << '.' << subs[i]); } - shape.setPlacement(plc); - myShape = shape.getShape(); - } - catch (Standard_Failure& e) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() - << '.' << subs[i] << std::endl - << e.GetMessageString()); - } - catch (Base::CADKernelError& e) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() - << '.' << subs[i] << std::endl - << e.what()); - } - if (myShape.IsNull()) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.' - << subs[i]); + if (shape.shapeType() != TopAbs_COMPOUND + || shape.countSubShapes(TopAbs_SHAPE) != 1) { + break; + } + // auto extract the single sub-shape from a compound + shape = shape.getSubTopoShape(TopAbs_SHAPE, 1); } + + myShape = shape.getShape(); } + catch (Standard_Failure& e) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() + << '.' << subs[i] << std::endl + << e.GetMessageString()); + } + catch (Base::CADKernelError& e) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() + << '.' << subs[i] << std::endl + << e.what()); + } + if (myShape.IsNull()) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.' + << subs[i]); + } + storage.emplace_back(myShape); shapes[i] = &(storage.back()); @@ -921,7 +887,6 @@ void AttachEngine::readLinks(const std::vector &objs, types[i] = eRefType(types[i] | rtFlagHasPlacement); } } - } void AttachEngine::throwWrongMode(eMapMode mmode) @@ -1175,22 +1140,18 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector parts; std::vector shapes; std::vector copiedShapeStorage; std::vector types; - readLinks(objs, subs, parts, shapes, copiedShapeStorage, types); + readLinks(objs, subs, shapes, copiedShapeStorage, types); - if (parts.empty()) { + if (shapes.empty()) { throw ExceptionCancel(); } // common stuff for all map modes - Base::Placement Place = App::GeoFeature::getGlobalPlacement(parts[0], objs[0], subs[0]); - Base::Console().Warning("parts[0] = %s\n", parts[0]->getNameInDocument()); - Base::Console().Warning("objs[0] = %s\n", objs[0]->getNameInDocument()); - Base::Console().Warning("subs[0] = %s\n", subs[0]); - Base::Console().Warning("Place = (%f, %f, %f)\n", Place.getPosition().x, Place.getPosition().y, Place.getPosition().z); + App::DocumentObject* subObj = objs[0]->getSubObject(subs[0].c_str()); + Base::Placement Place = App::GeoFeature::getGlobalPlacement(subObj, objs[0], subs[0]); Base::Vector3d vec = Place.getPosition(); gp_Pnt refOrg = gp_Pnt(vec.x, vec.y, vec.z); // origin of linked object @@ -2122,19 +2083,19 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector parts; std::vector shapes; std::vector copiedShapeStorage; std::vector types; - readLinks(objs, subs, parts, shapes, copiedShapeStorage, types); + readLinks(objs, subs, shapes, copiedShapeStorage, types); - if (parts.empty()) { + if (shapes.empty()) { throw ExceptionCancel(); } // common stuff for all map modes - Base::Placement Place = App::GeoFeature::getGlobalPlacement(parts[0], objs[0], subs[0]); + App::DocumentObject* subObj = objs[0]->getSubObject(subs[0].c_str()); + Base::Placement Place = App::GeoFeature::getGlobalPlacement(subObj, objs[0], subs[0]); Base::Vector3d vec = Place.getPosition(); gp_Pnt refOrg = gp_Pnt(vec.x, vec.y, vec.z); // origin of linked object @@ -2489,13 +2450,12 @@ AttachEnginePoint::_calculateAttachedPlacement(const std::vector parts; std::vector shapes; std::vector copiedShapeStorage; std::vector types; - readLinks(objs, subs, parts, shapes, copiedShapeStorage, types); + readLinks(objs, subs, shapes, copiedShapeStorage, types); - if (parts.empty()) { + if (shapes.empty()) { throw ExceptionCancel(); } diff --git a/src/Mod/Part/App/Attacher.h b/src/Mod/Part/App/Attacher.h index 4a16f318b0..dd0c8ba569 100644 --- a/src/Mod/Part/App/Attacher.h +++ b/src/Mod/Part/App/Attacher.h @@ -429,7 +429,7 @@ protected: return ret; } static void readLinks(const std::vector &objs, - const std::vector &subs, std::vector &geofs, + const std::vector &subs, std::vector& shapes, std::vector &storage, std::vector &types);