From 83ce80f1337e7302d00b41be0f05ea349b793c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Wed, 18 May 2016 19:49:05 +0200 Subject: [PATCH] fixes #0002512 Allow multi-face part design tools --- src/Mod/PartDesign/App/FeatureBoolean.cpp | 2 +- src/Mod/PartDesign/App/FeatureChamfer.cpp | 2 +- src/Mod/PartDesign/App/FeatureDraft.cpp | 2 +- src/Mod/PartDesign/App/FeatureFillet.cpp | 2 +- src/Mod/PartDesign/App/FeatureGroove.cpp | 13 +++++++--- src/Mod/PartDesign/App/FeatureHole.cpp | 4 +-- src/Mod/PartDesign/App/FeatureLoft.cpp | 6 ++--- src/Mod/PartDesign/App/FeaturePad.cpp | 6 ++--- src/Mod/PartDesign/App/FeaturePipe.cpp | 6 ++--- src/Mod/PartDesign/App/FeaturePocket.cpp | 18 ++++++------- src/Mod/PartDesign/App/FeaturePrimitive.cpp | 6 ++--- src/Mod/PartDesign/App/FeatureRevolution.cpp | 12 ++++++--- src/Mod/PartDesign/App/FeatureSketchBased.cpp | 26 ++++++++++--------- src/Mod/PartDesign/App/FeatureSketchBased.h | 4 +-- src/Mod/PartDesign/App/FeatureThickness.cpp | 4 +-- src/Mod/PartDesign/App/FeatureTransformed.cpp | 2 +- 16 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index 129d2473d..0245a6460 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -165,7 +165,7 @@ App::DocumentObjectExecReturn *Boolean::execute(void) result = mkTrf.Shape(); } - this->Shape.setValue(result); + this->Shape.setValue(getSolid(result)); return App::DocumentObject::StdReturn; } diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp index 23e5d751e..43b450451 100644 --- a/src/Mod/PartDesign/App/FeatureChamfer.cpp +++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp @@ -115,7 +115,7 @@ App::DocumentObjectExecReturn *Chamfer::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } - this->Shape.setValue(shape); + this->Shape.setValue(getSolid(shape)); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { diff --git a/src/Mod/PartDesign/App/FeatureDraft.cpp b/src/Mod/PartDesign/App/FeatureDraft.cpp index 3ccbb7c49..a2b34dcc6 100644 --- a/src/Mod/PartDesign/App/FeatureDraft.cpp +++ b/src/Mod/PartDesign/App/FeatureDraft.cpp @@ -302,7 +302,7 @@ App::DocumentObjectExecReturn *Draft::execute(void) if (shape.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is null"); - this->Shape.setValue(shape); + this->Shape.setValue(getSolid(shape)); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp b/src/Mod/PartDesign/App/FeatureFillet.cpp index e1f37bbb2..d3083017b 100644 --- a/src/Mod/PartDesign/App/FeatureFillet.cpp +++ b/src/Mod/PartDesign/App/FeatureFillet.cpp @@ -106,7 +106,7 @@ App::DocumentObjectExecReturn *Fillet::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } - this->Shape.setValue(shape); + this->Shape.setValue(getSolid(shape)); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index cb6f15ba5..a5d925efb 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -129,9 +129,14 @@ App::DocumentObjectExecReturn *Groove::execute(void) sketchshape.Move(invObjLoc); // Check distance between sketchshape and axis - to avoid failures and crashes - if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(sketchshape))) - return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); - + TopExp_Explorer xp; + xp.Init(sketchshape, TopAbs_FACE); + for (;xp.More(); xp.Next()) { + + if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(xp.Current()))) + return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); + } + // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); @@ -164,7 +169,7 @@ App::DocumentObjectExecReturn *Groove::execute(void) Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" - "Intersecting sketch entities or multiple faces in a sketch are not allowed."); + "Intersecting sketch entities in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index 64b22db98..f5c028b75 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -136,7 +136,7 @@ App::DocumentObjectExecReturn *Hole::execute(void) // // if the sketch has a support fuse them to get one result object (PAD!) // if (SupportObject) { // // Set the subtractive shape property for later usage in e.g. pattern - // this->SubShape.setValue(PrismMaker.Shape()); + // this->SubShape.setValue(getSolid(PrismMaker.Shape())); // const TopoDS_Shape& support = SupportObject->Shape.getValue(); // if (support.IsNull()) // return new App::DocumentObjectExecReturn("Support shape is invalid"); @@ -148,7 +148,7 @@ App::DocumentObjectExecReturn *Hole::execute(void) // // Let's check if the fusion has been successful // if (!mkCut.IsDone()) // return new App::DocumentObjectExecReturn("Cut with support failed"); - // this->Shape.setValue(mkCut.Shape()); + // this->Shape.setValue(getSolid(mkCut.Shape())); // } // else{ // return new App::DocumentObjectExecReturn("Cannot create a tool out of sketch with no support"); diff --git a/src/Mod/PartDesign/App/FeatureLoft.cpp b/src/Mod/PartDesign/App/FeatureLoft.cpp index 66d2c3d62..277060dfa 100644 --- a/src/Mod/PartDesign/App/FeatureLoft.cpp +++ b/src/Mod/PartDesign/App/FeatureLoft.cpp @@ -178,7 +178,7 @@ App::DocumentObjectExecReturn *Loft::execute(void) AddSubShape.setValue(result); if(base.IsNull()) { - Shape.setValue(result); + Shape.setValue(getSolid(result)); return App::DocumentObject::StdReturn; } @@ -194,7 +194,7 @@ App::DocumentObjectExecReturn *Loft::execute(void) return new App::DocumentObjectExecReturn("Loft: Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); } else if(getAddSubType() == FeatureAddSub::Subtractive) { @@ -208,7 +208,7 @@ App::DocumentObjectExecReturn *Loft::execute(void) return new App::DocumentObjectExecReturn("Loft: Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); } return App::DocumentObject::StdReturn; diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 909177473..cbd33bcc5 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -213,7 +213,7 @@ App::DocumentObjectExecReturn *Pad::execute(void) if (!base.IsNull()) { // auto obj = getDocument()->addObject("Part::Feature", "prism"); -// static_cast(obj)->Shape.setValue(prism); +// static_cast(obj)->Shape.setValue(getSolid(prism)); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(base, prism); // Let's check if the fusion has been successful @@ -226,9 +226,9 @@ App::DocumentObjectExecReturn *Pad::execute(void) if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is not a solid"); solRes = refineShapeIfActive(solRes); - this->Shape.setValue(solRes); + this->Shape.setValue(getSolid(solRes)); } else { - this->Shape.setValue(prism); + this->Shape.setValue(getSolid(prism)); } return App::DocumentObject::StdReturn; diff --git a/src/Mod/PartDesign/App/FeaturePipe.cpp b/src/Mod/PartDesign/App/FeaturePipe.cpp index f14993f1d..0fe7ed791 100644 --- a/src/Mod/PartDesign/App/FeaturePipe.cpp +++ b/src/Mod/PartDesign/App/FeaturePipe.cpp @@ -285,7 +285,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void) AddSubShape.setValue(result); if(base.IsNull()) { - Shape.setValue(result); + Shape.setValue(getSolid(result)); return App::DocumentObject::StdReturn; } @@ -301,7 +301,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); } else if(getAddSubType() == FeatureAddSub::Subtractive) { @@ -315,7 +315,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); } return App::DocumentObject::StdReturn; diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index 516fe8eba..365cf4746 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -94,10 +94,10 @@ App::DocumentObjectExecReturn *Pocket::execute(void) return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small"); Part::Feature* obj = 0; - TopoDS_Face face; + TopoDS_Shape profileshape; try { obj = getVerifiedObject(); - face = getVerifiedFace(); + profileshape = getVerifiedFace(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } @@ -126,9 +126,9 @@ App::DocumentObjectExecReturn *Pocket::execute(void) gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); - if (face.IsNull()) + if (profileshape.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed"); - face.Move(invObjLoc); + profileshape.Move(invObjLoc); std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToFace") { @@ -148,7 +148,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } - getUpToFace(upToFace, base, supportface, face, method, dir, Offset.getValue()); + getUpToFace(upToFace, base, supportface, profileshape, method, dir, Offset.getValue()); // BRepFeat_MakePrism(..., 2, 1) in combination with PerForm(upToFace) is buggy when the // prism that is being created is contained completely inside the base solid @@ -161,7 +161,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) if (!Ex.More()) supportface = TopoDS_Face(); BRepFeat_MakePrism PrismMaker; - PrismMaker.Init(base, face, supportface, dir, 0, 1); + PrismMaker.Init(base, profileshape, supportface, dir, 0, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) @@ -175,10 +175,10 @@ App::DocumentObjectExecReturn *Pocket::execute(void) // FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!! TopoDS_Shape result = refineShapeIfActive(mkCut.Shape()); this->AddSubShape.setValue(result); - this->Shape.setValue(prism); + this->Shape.setValue(getSolid(prism)); } else { TopoDS_Shape prism; - generatePrism(prism, face, method, dir, L, 0.0, + generatePrism(prism, profileshape, method, dir, L, 0.0, Midplane.getValue(), Reversed.getValue()); if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty"); @@ -198,7 +198,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is not a solid"); solRes = refineShapeIfActive(solRes); remapSupportShape(solRes); - this->Shape.setValue(solRes); + this->Shape.setValue(getSolid(solRes)); } return App::DocumentObject::StdReturn; diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.cpp b/src/Mod/PartDesign/App/FeaturePrimitive.cpp index 269b6340e..8b5267e0f 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.cpp +++ b/src/Mod/PartDesign/App/FeaturePrimitive.cpp @@ -103,7 +103,7 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri AddSubShape.setValue(primitiveShape); if(getAddSubType() == FeatureAddSub::Additive) - Shape.setValue(primitiveShape); + Shape.setValue(getSolid(primitiveShape)); else return new App::DocumentObjectExecReturn("Cannot subtract primitive feature without base feature"); @@ -122,7 +122,7 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); AddSubShape.setValue(primitiveShape); } else if(getAddSubType() == FeatureAddSub::Subtractive) { @@ -137,7 +137,7 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); boolOp = refineShapeIfActive(boolOp); - Shape.setValue(boolOp); + Shape.setValue(getSolid(boolOp)); AddSubShape.setValue(primitiveShape); } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 93ecf904b..d615aa466 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -131,8 +131,12 @@ App::DocumentObjectExecReturn *Revolution::execute(void) sketchshape.Move(invObjLoc); // Check distance between sketchshape and axis - to avoid failures and crashes - if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(sketchshape))) - return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); + TopExp_Explorer xp; + xp.Init(sketchshape, TopAbs_FACE); + for (;xp.More(); xp.Next()) { + if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(xp.Current()))) + return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); + } // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); @@ -153,7 +157,7 @@ App::DocumentObjectExecReturn *Revolution::execute(void) result = refineShapeIfActive(result); } - this->Shape.setValue(result); + this->Shape.setValue(getSolid(result)); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); @@ -164,7 +168,7 @@ App::DocumentObjectExecReturn *Revolution::execute(void) Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" - "Intersecting sketch entities or multiple faces in a sketch are not allowed."); + "Intersecting sketch entities in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index f982b563b..61bfe2eb4 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -192,7 +192,7 @@ Part::Feature* ProfileBased::getVerifiedObject(bool silent) const { return static_cast(result); } -TopoDS_Face ProfileBased::getVerifiedFace(bool silent) const { +TopoDS_Shape ProfileBased::getVerifiedFace(bool silent) const { App::DocumentObject* result = Profile.getValue(); const char* err = nullptr; @@ -203,7 +203,7 @@ TopoDS_Face ProfileBased::getVerifiedFace(bool silent) const { if (result->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { auto wires = getProfileWires(); - return TopoDS::Face(makeFace(wires)); + return makeFace(wires); } else if(result->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if(Profile.getSubValues().empty()) @@ -1233,16 +1233,18 @@ Base::Vector3d ProfileBased::getProfileNormal() const { SketchOrientation.multVec(SketchVector,SketchVector); } else { - TopoDS_Face face = getVerifiedFace(true); - BRepAdaptor_Surface adapt(face); - double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter())/2.; - double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter())/2.; - BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion()); - if(prop.IsNormalDefined()) { - gp_Pnt pnt; gp_Vec vec; - // handles the orientation state of the shape - BRepGProp_Face(face).Normal(u,v,pnt,vec); - SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z()); + TopoDS_Shape shape = getVerifiedFace(true); + if(shape.ShapeType() == TopAbs_FACE) { + BRepAdaptor_Surface adapt(TopoDS::Face(shape)); + double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter())/2.; + double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter())/2.; + BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion()); + if(prop.IsNormalDefined()) { + gp_Pnt pnt; gp_Vec vec; + // handles the orientation state of the shape + BRepGProp_Face(TopoDS::Face(shape)).Normal(u,v,pnt,vec); + SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z()); + } } } diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 21a5adcce..b809f8031 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -85,11 +85,11 @@ public: /** * Verifies the linked Object and returns the shape used as profile - * @param silent if profile property is malformed and the parameter is true + * @param silent if profirle property is malformed and the parameter is true * silently returns nullptr, otherwice throw a Base::Exception. * Default is false. */ - TopoDS_Face getVerifiedFace(bool silent = false) const; + TopoDS_Shape getVerifiedFace(bool silent = false) const; /// Returns the wires the sketch is composed of std::vector getProfileWires() const; diff --git a/src/Mod/PartDesign/App/FeatureThickness.cpp b/src/Mod/PartDesign/App/FeatureThickness.cpp index 2e5734574..e5641dd45 100644 --- a/src/Mod/PartDesign/App/FeatureThickness.cpp +++ b/src/Mod/PartDesign/App/FeatureThickness.cpp @@ -85,8 +85,8 @@ App::DocumentObjectExecReturn *Thickness::execute(void) join = 2; if (fabs(thickness) > 2*tol) - this->Shape.setValue(TopShape.makeThickSolid(closingFaces, thickness, tol, false, false, mode, join)); + this->Shape.setValue(getSolid(TopShape.makeThickSolid(closingFaces, thickness, tol, false, false, mode, join))); else - this->Shape.setValue(TopShape._Shape); + this->Shape.setValue(getSolid(TopShape._Shape)); return App::DocumentObject::StdReturn; } diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index a3387631b..41d8836a2 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -358,7 +358,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) for (trsf_it::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) rejected[it->first].push_back(**it2); - this->Shape.setValue(support); + this->Shape.setValue(getSolid(support)); return App::DocumentObject::StdReturn; }