From f712f5e4acd407bf6b832ec6cea99adcafeb5c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Wed, 20 Jan 2016 07:11:59 +0100 Subject: [PATCH] PartDesign: Modeling features work with faces -Rename Sketchbased to ProfileBased to show new behavior -Adopt ProfileBased to make the relevant helper functions work with faces too -Adopt features for unified use of helper functions -Adopt commands to allow face selection --- src/Mod/PartDesign/App/AppPartDesign.cpp | 2 +- src/Mod/PartDesign/App/FeatureGroove.cpp | 11 +- src/Mod/PartDesign/App/FeatureGroove.h | 2 +- src/Mod/PartDesign/App/FeatureHole.cpp | 2 +- src/Mod/PartDesign/App/FeatureHole.h | 2 +- src/Mod/PartDesign/App/FeatureLoft.cpp | 12 +- src/Mod/PartDesign/App/FeatureLoft.h | 2 +- src/Mod/PartDesign/App/FeaturePad.cpp | 22 +- src/Mod/PartDesign/App/FeaturePad.h | 2 +- src/Mod/PartDesign/App/FeaturePipe.cpp | 22 +- src/Mod/PartDesign/App/FeaturePipe.h | 2 +- src/Mod/PartDesign/App/FeaturePocket.cpp | 29 +- src/Mod/PartDesign/App/FeaturePocket.h | 2 +- src/Mod/PartDesign/App/FeatureRevolution.cpp | 11 +- src/Mod/PartDesign/App/FeatureRevolution.h | 2 +- src/Mod/PartDesign/App/FeatureSketchBased.cpp | 247 +++++++++++++++--- src/Mod/PartDesign/App/FeatureSketchBased.h | 58 ++-- src/Mod/PartDesign/App/FeatureTransformed.cpp | 4 +- src/Mod/PartDesign/Gui/Command.cpp | 140 +++++----- src/Mod/PartDesign/Gui/CommandBody.cpp | 4 +- .../Gui/TaskRevolutionParameters.cpp | 12 +- .../Gui/TaskSketchBasedParameters.cpp | 14 +- src/Mod/PartDesign/Gui/ViewProviderHole.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderLoft.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderPipe.cpp | 2 +- .../Gui/ViewProviderSketchBased.cpp | 10 +- 26 files changed, 417 insertions(+), 203 deletions(-) diff --git a/src/Mod/PartDesign/App/AppPartDesign.cpp b/src/Mod/PartDesign/App/AppPartDesign.cpp index cb3a4331f..0673475d5 100644 --- a/src/Mod/PartDesign/App/AppPartDesign.cpp +++ b/src/Mod/PartDesign/App/AppPartDesign.cpp @@ -87,7 +87,7 @@ PyMODINIT_FUNC init_PartDesign() PartDesign::Solid ::init(); PartDesign::DressUp ::init(); PartDesign::FeatureAddSub ::init(); - PartDesign::SketchBased ::init(); + PartDesign::ProfileBased ::init(); PartDesign::Transformed ::init(); PartDesign::Mirrored ::init(); PartDesign::LinearPattern ::init(); diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 575af788f..cb6f15ba5 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -49,7 +49,7 @@ using namespace PartDesign; namespace PartDesign { -PROPERTY_SOURCE(PartDesign::Groove, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Groove, PartDesign::ProfileBased) Groove::Groove() { @@ -69,7 +69,7 @@ short Groove::mustExecute() const Base.isTouched() || Angle.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Groove::execute(void) @@ -86,9 +86,9 @@ App::DocumentObjectExecReturn *Groove::execute(void) if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); - std::vector wires; + TopoDS_Shape sketchshape; try { - wires = getSketchWires(); + sketchshape = getVerifiedFace(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } @@ -110,7 +110,6 @@ App::DocumentObjectExecReturn *Groove::execute(void) gp_Dir dir(v.x,v.y,v.z); try { - TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); @@ -177,7 +176,7 @@ App::DocumentObjectExecReturn *Groove::execute(void) bool Groove::suggestReversed(void) { updateAxis(); - return SketchBased::getReversedAngle(Base.getValue(), Axis.getValue()) > 0.0; + return ProfileBased::getReversedAngle(Base.getValue(), Axis.getValue()) > 0.0; } void Groove::updateAxis(void) diff --git a/src/Mod/PartDesign/App/FeatureGroove.h b/src/Mod/PartDesign/App/FeatureGroove.h index de4cfb02f..7b997dd3e 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.h +++ b/src/Mod/PartDesign/App/FeatureGroove.h @@ -30,7 +30,7 @@ namespace PartDesign { -class PartDesignExport Groove : public SketchBased +class PartDesignExport Groove : public ProfileBased { PROPERTY_HEADER(PartDesign::Groove); diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index c0524969f..33ca7df0a 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -52,7 +52,7 @@ const char* Hole::TypeEnums[] = {"Dimension","UpToLast","UpToFirst",NULL}; const char* Hole::HoleTypeEnums[]= {"Simple","Counterbore","Countersunk",NULL}; const char* Hole::ThreadEnums[] = {"None","Metric","MetricFine",NULL}; -PROPERTY_SOURCE(PartDesign::Hole, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Hole, PartDesign::ProfileBased) Hole::Hole() { diff --git a/src/Mod/PartDesign/App/FeatureHole.h b/src/Mod/PartDesign/App/FeatureHole.h index 8318f1f1c..ee4b415ff 100644 --- a/src/Mod/PartDesign/App/FeatureHole.h +++ b/src/Mod/PartDesign/App/FeatureHole.h @@ -30,7 +30,7 @@ namespace PartDesign { -class PartDesignExport Hole : public SketchBased +class PartDesignExport Hole : public ProfileBased { PROPERTY_HEADER(PartDesign::Hole); diff --git a/src/Mod/PartDesign/App/FeatureLoft.cpp b/src/Mod/PartDesign/App/FeatureLoft.cpp index 337df6077..66d2c3d62 100644 --- a/src/Mod/PartDesign/App/FeatureLoft.cpp +++ b/src/Mod/PartDesign/App/FeatureLoft.cpp @@ -49,7 +49,7 @@ using namespace PartDesign; -PROPERTY_SOURCE(PartDesign::Loft, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Loft, PartDesign::ProfileBased) Loft::Loft() { @@ -68,7 +68,7 @@ short Loft::mustExecute() const if (Closed.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Loft::execute(void) @@ -76,12 +76,12 @@ App::DocumentObjectExecReturn *Loft::execute(void) std::vector wires; try { - wires = getSketchWires(); + wires = getProfileWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } - TopoDS_Shape sketchshape = makeFace(wires); + TopoDS_Shape sketchshape = getVerifiedFace(); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Loft: Creating a face from sketch failed"); @@ -145,7 +145,7 @@ App::DocumentObjectExecReturn *Loft::execute(void) } //build the top and bottom face, sew the shell and build the final solid - TopoDS_Shape front = makeFace(wires); + TopoDS_Shape front = getVerifiedFace(); front.Move(invObjLoc); std::vector backwires; for(std::vector& wires : wiresections) @@ -213,7 +213,7 @@ App::DocumentObjectExecReturn *Loft::execute(void) return App::DocumentObject::StdReturn; - return SketchBased::execute(); + return ProfileBased::execute(); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); diff --git a/src/Mod/PartDesign/App/FeatureLoft.h b/src/Mod/PartDesign/App/FeatureLoft.h index 2a4b374f4..cc4798e35 100644 --- a/src/Mod/PartDesign/App/FeatureLoft.h +++ b/src/Mod/PartDesign/App/FeatureLoft.h @@ -33,7 +33,7 @@ namespace PartDesign { -class PartDesignExport Loft : public SketchBased +class PartDesignExport Loft : public ProfileBased { PROPERTY_HEADER(PartDesign::Loft); diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 298d932fa..ba48d2e36 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -42,6 +42,7 @@ # include # include # include +#include #endif #include @@ -58,7 +59,7 @@ using namespace PartDesign; const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL}; -PROPERTY_SOURCE(PartDesign::Pad, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Pad, PartDesign::ProfileBased) Pad::Pad() { @@ -83,7 +84,7 @@ short Pad::mustExecute() const Offset.isTouched() || UpToFace.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Pad::execute(void) @@ -96,11 +97,11 @@ App::DocumentObjectExecReturn *Pad::execute(void) if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Second length of pad too small"); - Part::Part2DObject* sketch = 0; - std::vector wires; + Part::Feature* obj = 0; + TopoDS_Shape sketchshape; try { - sketch = getVerifiedSketch(); - wires = getSketchWires(); + obj = getVerifiedObject(); + sketchshape = getVerifiedFace(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } @@ -115,10 +116,8 @@ App::DocumentObjectExecReturn *Pad::execute(void) // get the Sketch plane - Base::Placement SketchPos = sketch->Placement.getValue(); - Base::Rotation SketchOrientation = SketchPos.getRotation(); - Base::Vector3d SketchVector(0,0,1); - SketchOrientation.multVec(SketchVector,SketchVector); + Base::Placement SketchPos = obj->Placement.getValue(); + Base::Vector3d SketchVector = getProfileNormal(); try { this->positionByPrevious(); @@ -129,7 +128,6 @@ App::DocumentObjectExecReturn *Pad::execute(void) gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); - TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pad: Creating a face from sketch failed"); sketchshape.Move(invObjLoc); @@ -214,6 +212,8 @@ App::DocumentObjectExecReturn *Pad::execute(void) this->AddSubShape.setValue(prism); if (!base.IsNull()) { +// auto obj = getDocument()->addObject("Part::Feature", "prism"); +// static_cast(obj)->Shape.setValue(prism); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(base, prism); // Let's check if the fusion has been successful diff --git a/src/Mod/PartDesign/App/FeaturePad.h b/src/Mod/PartDesign/App/FeaturePad.h index fd2c3de53..d4fcdeb35 100644 --- a/src/Mod/PartDesign/App/FeaturePad.h +++ b/src/Mod/PartDesign/App/FeaturePad.h @@ -33,7 +33,7 @@ namespace PartDesign { -class PartDesignExport Pad : public SketchBased +class PartDesignExport Pad : public ProfileBased { PROPERTY_HEADER(PartDesign::Pad); diff --git a/src/Mod/PartDesign/App/FeaturePipe.cpp b/src/Mod/PartDesign/App/FeaturePipe.cpp index 86247e973..b28e9e2d5 100644 --- a/src/Mod/PartDesign/App/FeaturePipe.cpp +++ b/src/Mod/PartDesign/App/FeaturePipe.cpp @@ -76,7 +76,7 @@ const char* Pipe::ModeEnums[] = {"Standart", "Fixed", "Frenet", "Auxillery", "Bi const char* Pipe::TransformEnums[] = {"Constant", "Multisection", "Linear", "S-shape", "Interpolation", NULL}; -PROPERTY_SOURCE(PartDesign::Pipe, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Pipe, PartDesign::ProfileBased) Pipe::Pipe() { @@ -106,7 +106,7 @@ short Pipe::mustExecute() const return 1; if (Transition.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Pipe::execute(void) @@ -114,14 +114,24 @@ App::DocumentObjectExecReturn *Pipe::execute(void) std::vector wires; try { - wires = getSketchWires(); + wires = getProfileWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } - TopoDS_Shape sketchshape = makeFace(wires); + TopoDS_Shape sketchshape = getVerifiedFace(); if (sketchshape.IsNull()) - return new App::DocumentObjectExecReturn("Pipe: Creating a face from sketch failed"); + return new App::DocumentObjectExecReturn("Pipe: No valid sketch or face as first section"); + else { + //TODO: currently we only allow planar faces. the reason for this is that with other faces in front, we could + //not use the current simulate approach and build the start and end face from the wires. As the shell + //beginns always at the spine and not the profile, the sketchshape cannot be used directly as front face. + //We would need a method to translate the frontshape to match the shell starting position somehow... + TopoDS_Face face = TopoDS::Face(sketchshape); + BRepAdaptor_Surface adapt(face); + if(adapt.GetType() != GeomAbs_Plane) + return new App::DocumentObjectExecReturn("Pipe: Only planar faces supportet"); + } // if the Base property has a valid shape, fuse the pipe into it TopoDS_Shape base; @@ -310,7 +320,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void) return App::DocumentObject::StdReturn; - return SketchBased::execute(); + return ProfileBased::execute(); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); diff --git a/src/Mod/PartDesign/App/FeaturePipe.h b/src/Mod/PartDesign/App/FeaturePipe.h index 08907abfc..ce563fbbe 100644 --- a/src/Mod/PartDesign/App/FeaturePipe.h +++ b/src/Mod/PartDesign/App/FeaturePipe.h @@ -31,7 +31,7 @@ namespace PartDesign { -class PartDesignExport Pipe : public SketchBased +class PartDesignExport Pipe : public ProfileBased { PROPERTY_HEADER(PartDesign::Pad); diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index 5ba8d2edd..a4278d98b 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -54,7 +54,7 @@ using namespace PartDesign; const char* Pocket::TypeEnums[]= {"Length","ThroughAll","UpToFirst","UpToFace",NULL}; -PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::ProfileBased) Pocket::Pocket() { @@ -77,7 +77,7 @@ short Pocket::mustExecute() const Offset.isTouched() || UpToFace.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Pocket::execute(void) @@ -93,11 +93,11 @@ App::DocumentObjectExecReturn *Pocket::execute(void) if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small"); - Part::Part2DObject* sketch = 0; - std::vector wires; + Part::Feature* obj = 0; + TopoDS_Face face; try { - sketch = getVerifiedSketch(); - wires = getSketchWires(); + obj = getVerifiedObject(); + face = getVerifiedFace(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } @@ -111,10 +111,8 @@ App::DocumentObjectExecReturn *Pocket::execute(void) } // get the Sketch plane - Base::Placement SketchPos = sketch->Placement.getValue(); - Base::Rotation SketchOrientation = SketchPos.getRotation(); - Base::Vector3d SketchVector(0,0,1); - SketchOrientation.multVec(SketchVector,SketchVector); + Base::Placement SketchPos = obj->Placement.getValue(); + Base::Vector3d SketchVector = getProfileNormal(); // turn around for pockets SketchVector *= -1; @@ -128,10 +126,9 @@ App::DocumentObjectExecReturn *Pocket::execute(void) gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); - TopoDS_Shape sketchshape = makeFace(wires); - if (sketchshape.IsNull()) + if (face.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed"); - sketchshape.Move(invObjLoc); + face.Move(invObjLoc); std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToFace") { @@ -151,7 +148,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } - getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue()); + getUpToFace(upToFace, base, supportface, face, 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 @@ -164,7 +161,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) if (!Ex.More()) supportface = TopoDS_Face(); BRepFeat_MakePrism PrismMaker; - PrismMaker.Init(base, sketchshape, supportface, dir, 0, 1); + PrismMaker.Init(base, face, supportface, dir, 0, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) @@ -181,7 +178,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) this->Shape.setValue(prism); } else { TopoDS_Shape prism; - generatePrism(prism, sketchshape, method, dir, L, 0.0, + generatePrism(prism, face, method, dir, L, 0.0, Midplane.getValue(), Reversed.getValue()); if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty"); diff --git a/src/Mod/PartDesign/App/FeaturePocket.h b/src/Mod/PartDesign/App/FeaturePocket.h index 89c21a658..e07cfa096 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.h +++ b/src/Mod/PartDesign/App/FeaturePocket.h @@ -30,7 +30,7 @@ namespace PartDesign { -class PartDesignExport Pocket : public SketchBased +class PartDesignExport Pocket : public ProfileBased { PROPERTY_HEADER(PartDesign::Pocket); diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 2b4107f71..93ecf904b 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -49,7 +49,7 @@ using namespace PartDesign; namespace PartDesign { -PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::SketchBased) +PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::ProfileBased) Revolution::Revolution() { @@ -69,7 +69,7 @@ short Revolution::mustExecute() const Base.isTouched() || Angle.isTouched()) return 1; - return SketchBased::mustExecute(); + return ProfileBased::mustExecute(); } App::DocumentObjectExecReturn *Revolution::execute(void) @@ -86,9 +86,9 @@ App::DocumentObjectExecReturn *Revolution::execute(void) if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); - std::vector wires; + TopoDS_Shape sketchshape; try { - wires = getSketchWires(); + sketchshape = getVerifiedFace(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } @@ -112,7 +112,6 @@ App::DocumentObjectExecReturn *Revolution::execute(void) gp_Dir dir(v.x,v.y,v.z); try { - TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); @@ -177,7 +176,7 @@ App::DocumentObjectExecReturn *Revolution::execute(void) bool Revolution::suggestReversed(void) { updateAxis(); - return SketchBased::getReversedAngle(Base.getValue(), Axis.getValue()) < 0.0; + return ProfileBased::getReversedAngle(Base.getValue(), Axis.getValue()) < 0.0; } void Revolution::updateAxis(void) diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index c27b9518b..0be240b69 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -30,7 +30,7 @@ namespace PartDesign { -class PartDesignExport Revolution : public SketchBased +class PartDesignExport Revolution : public ProfileBased { PROPERTY_HEADER(PartDesign::Revolution); diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 50f084854..eba5e465b 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -66,11 +66,16 @@ #include #include #include +#include +#include #include #include +#include +#include #include #include +#include #include #include "FeatureSketchBased.h" #include "DatumPlane.h" @@ -79,7 +84,7 @@ using namespace PartDesign; // sort bounding boxes according to diagonal length -class SketchBased::Wire_Compare : public std::binary_function { public: bool operator() (const TopoDS_Wire& w1, const TopoDS_Wire& w2) @@ -99,19 +104,19 @@ public: } }; -PROPERTY_SOURCE(PartDesign::SketchBased, PartDesign::FeatureAddSub) +PROPERTY_SOURCE(PartDesign::ProfileBased, PartDesign::FeatureAddSub) -SketchBased::SketchBased() +ProfileBased::ProfileBased() { - ADD_PROPERTY_TYPE(Sketch,(0),"SketchBased", App::Prop_None, "Reference to sketch"); + ADD_PROPERTY_TYPE(Profile,(0),"SketchBased", App::Prop_None, "Reference to sketch"); ADD_PROPERTY_TYPE(Midplane,(0),"SketchBased", App::Prop_None, "Extrude symmetric to sketch face"); ADD_PROPERTY_TYPE(Reversed, (0),"SketchBased", App::Prop_None, "Reverse extrusion direction"); ADD_PROPERTY_TYPE(UpToFace,(0),"SketchBased",(App::PropertyType)(App::Prop_None),"Face where feature will end"); } -short SketchBased::mustExecute() const +short ProfileBased::mustExecute() const { - if (Sketch.isTouched() || + if (Profile.isTouched() || Midplane.isTouched() || Reversed.isTouched() || UpToFace.isTouched()) @@ -119,7 +124,7 @@ short SketchBased::mustExecute() const return PartDesign::FeatureAddSub::mustExecute(); } -void SketchBased::positionByPrevious(void) +void ProfileBased::positionByPrevious(void) { Part::Feature* feat = getBaseObject(/* silent = */ true); if (feat) { @@ -136,7 +141,7 @@ void SketchBased::positionByPrevious(void) } } -void SketchBased::transformPlacement(const Base::Placement &transform) +void ProfileBased::transformPlacement(const Base::Placement &transform) { Part::Feature* feat = getBaseObject(/* silent = */ true); if (feat) { @@ -148,8 +153,8 @@ void SketchBased::transformPlacement(const Base::Placement &transform) positionByPrevious(); } -Part::Part2DObject* SketchBased::getVerifiedSketch(bool silent) const { - App::DocumentObject* result = Sketch.getValue(); +Part::Part2DObject* ProfileBased::getVerifiedSketch(bool silent) const { + App::DocumentObject* result = Profile.getValue(); const char* err = nullptr; if (!result) { @@ -166,10 +171,78 @@ Part::Part2DObject* SketchBased::getVerifiedSketch(bool silent) const { return static_cast(result); } -std::vector SketchBased::getSketchWires() const { +Part::Feature* ProfileBased::getVerifiedObject(bool silent) const { + + App::DocumentObject* result = Profile.getValue(); + const char* err = nullptr; + + if (!result) { + err = "No object linked"; + } else { + if (!result->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + err = "Linked object is not a Sketch, Part2DObject or Feature"; + } + + if (!silent && err) { + throw Base::Exception (err); + } + + return static_cast(result); +} + +TopoDS_Face ProfileBased::getVerifiedFace(bool silent) const { + + App::DocumentObject* result = Profile.getValue(); + const char* err = nullptr; + + if (!result) { + err = "No profile linked"; + } else { + if (result->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { + + auto wires = getProfileWires(); + return TopoDS::Face(makeFace(wires)); + } + else if(result->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + if(Profile.getSubValues().empty()) + err = "Linked object has no subshape specified"; + else { + + const TopoShape& shape = Profile.getValue()->Shape.getShape(); + TopoDS_Shape sub = shape.getSubShape(Profile.getSubValues()[0].c_str()); + if(sub.ShapeType() == TopAbs_FACE) + return TopoDS::Face(sub); + else if(sub.ShapeType() == TopAbs_WIRE) { + + auto wire = TopoDS::Wire(sub); + if(!wire.Closed()) + err = "Linked wire is not closed"; + else { + BRepBuilderAPI_MakeFace mk(wire); + mk.Build(); + return TopoDS::Face(mk.Shape()); + } + } + else + err = "Linked Subshape cannot be used"; + } + } + else + err = "Linked object is neither Sketch, Part2DObject or Part::Feature"; + } + + if (!silent && err) { + throw Base::Exception (err); + } + + return TopoDS_Face(); +} + + +std::vector ProfileBased::getProfileWires() const { std::vector result; - TopoDS_Shape shape = getVerifiedSketch()->Shape.getShape()._Shape; + TopoDS_Shape shape = getVerifiedFace(); if (shape.IsNull()) throw Base::Exception("Linked shape object is empty"); @@ -195,7 +268,7 @@ std::vector SketchBased::getSketchWires() const { // Note: We cannot return a reference, because it will become Null. // Not clear where, because we check for IsNull() here, but as soon as it is passed out of // this method, it becomes null! -const TopoDS_Face SketchBased::getSupportFace() const { +const TopoDS_Face ProfileBased::getSupportFace() const { const Part::Part2DObject* sketch = getVerifiedSketch(); if (sketch->MapMode.getValue() == Attacher::mmFlatFace && sketch->Support.getValue()) { const auto &Support = sketch->Support; @@ -229,15 +302,15 @@ const TopoDS_Face SketchBased::getSupportFace() const { } -int SketchBased::getSketchAxisCount(void) const +int ProfileBased::getSketchAxisCount(void) const { - Part::Part2DObject *sketch = static_cast(Sketch.getValue()); + Part::Part2DObject *sketch = static_cast(Profile.getValue()); if (!sketch) return -1; // the link to the sketch is lost return sketch->getAxisCount(); } -Part::Feature *SketchBased::getBaseObject(bool silent) const +Part::Feature *ProfileBased::getBaseObject(bool silent) const { // Test the base's class feature. Part::Feature *rv = Feature::getBaseObject(/* silent = */ true); @@ -245,13 +318,17 @@ Part::Feature *SketchBased::getBaseObject(bool silent) const return rv; } - // getVerifiedSketch() may throw it's own exception if fail - Part::Part2DObject* sketch = getVerifiedSketch(silent); + // getVerifiedObject() may throw it's own exception if fail + Part::Feature* obj = getVerifiedObject(silent); - if (!sketch) { + if(!obj) return nullptr; - } + + if (!obj->isDerivedFrom(Part::Part2DObject::getClassTypeId())) + return obj; + //due to former test we know we have a 2d object + Part::Part2DObject* sketch = getVerifiedSketch(silent); const char* err = nullptr; App::DocumentObject* spt = sketch->Support.getValue(); @@ -272,17 +349,17 @@ Part::Feature *SketchBased::getBaseObject(bool silent) const return rv; } -void SketchBased::onChanged(const App::Property* prop) +void ProfileBased::onChanged(const App::Property* prop) { - if (prop == &Sketch) { + if (prop == &Profile) { // if attached to a sketch then mark it as read-only - this->Placement.setStatus(App::Property::ReadOnly, Sketch.getValue() != 0); + this->Placement.setStatus(App::Property::ReadOnly, Profile.getValue() != 0); } FeatureAddSub::onChanged(prop); } -bool SketchBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) const +bool ProfileBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) const { Bnd_Box box1; BRepBndLib::Add(wire1, box1); @@ -323,7 +400,7 @@ bool SketchBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) c return false; } -TopoDS_Face SketchBased::validateFace(const TopoDS_Face& face) const +TopoDS_Face ProfileBased::validateFace(const TopoDS_Face& face) const { BRepCheck_Analyzer aChecker(face); if (!aChecker.IsValid()) { @@ -367,7 +444,7 @@ TopoDS_Face SketchBased::validateFace(const TopoDS_Face& face) const return face; } -TopoDS_Shape SketchBased::makeFace(std::list& wires) const +TopoDS_Shape ProfileBased::makeFace(std::list& wires) const { BRepBuilderAPI_MakeFace mkFace(wires.front()); const TopoDS_Face& face = mkFace.Face(); @@ -399,7 +476,7 @@ TopoDS_Shape SketchBased::makeFace(std::list& wires) const return validateFace(mkFace.Face()); } -TopoDS_Shape SketchBased::makeFace(const std::vector& w) const +TopoDS_Shape ProfileBased::makeFace(const std::vector& w) const { if (w.empty()) return TopoDS_Shape(); @@ -472,7 +549,7 @@ TopoDS_Shape SketchBased::makeFace(const std::vector& w) const } } -void SketchBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace, +void ProfileBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace, const App::PropertyLinkSub& refFace) { App::DocumentObject* ref = refFace.getValue(); @@ -503,7 +580,7 @@ void SketchBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace, throw Base::Exception("SketchBased: Up to face: Failed to extract face"); } -void SketchBased::getUpToFace(TopoDS_Face& upToFace, +void ProfileBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, @@ -593,7 +670,7 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace, } } -void SketchBased::generatePrism(TopoDS_Shape& prism, +void ProfileBased::generatePrism(TopoDS_Shape& prism, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir, @@ -639,7 +716,7 @@ void SketchBased::generatePrism(TopoDS_Shape& prism, } -const bool SketchBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoDS_Face& face, +const bool ProfileBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoDS_Face& face, const gp_Dir& dir) { // Project wire onto the face (face, not surface! So limits of face apply) // FIXME: The results of BRepProj_Projection do not seem to be very stable. Sometimes they return no result @@ -650,7 +727,7 @@ const bool SketchBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoD return (proj.More() && proj.Current().Closed()); } -const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face) +const bool ProfileBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face) { #if 1 BRepBuilderAPI_MakeEdge mkEdge(line); @@ -800,7 +877,7 @@ const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Fa #endif } -void SketchBased::remapSupportShape(const TopoDS_Shape& newShape) +void ProfileBased::remapSupportShape(const TopoDS_Shape& newShape) { TopTools_IndexedMapOfShape faceMap; TopExp::MapShapes(newShape, TopAbs_FACE, faceMap); @@ -911,7 +988,7 @@ struct gp_Pnt_Less : public std::binary_function wires = getSketchWires(); - TopoDS_Shape sketchshape = makeFace(wires); + Part::Feature* obj = getVerifiedObject(); + TopoDS_Shape sketchshape = getVerifiedFace(); // get centre of gravity of the sketch face GProp_GProps props; @@ -1010,7 +1086,7 @@ const double SketchBased::getReversedAngle(const Base::Vector3d &b, const Base:: // get cross product of projection direction with revolve axis direction Base::Vector3d cross = v % perp_dir; // get sketch vector pointing away from support material - Base::Placement SketchPos = sketch->Placement.getValue(); + Base::Placement SketchPos = obj->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchNormal(0,0,1); SketchOrientation.multVec(SketchNormal,SketchNormal); @@ -1022,7 +1098,7 @@ const double SketchBased::getReversedAngle(const Base::Vector3d &b, const Base:: } } -void SketchBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector &subReferenceAxis, +void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector &subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir) { dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found @@ -1116,7 +1192,7 @@ void SketchBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std: throw Base::Exception("Rotation axis reference is invalid"); } -TopoDS_Shape SketchBased::refineShapeIfActive(const TopoDS_Shape& oldShape) const +TopoDS_Shape ProfileBased::refineShapeIfActive(const TopoDS_Shape& oldShape) const { Base::Reference hGrp = App::GetApplication().GetUserParameter() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); @@ -1128,3 +1204,88 @@ TopoDS_Shape SketchBased::refineShapeIfActive(const TopoDS_Shape& oldShape) cons return oldShape; } + +Base::Vector3d ProfileBased::getProfileNormal() const { + + Base::Vector3d SketchVector(0,0,1); + auto obj = getVerifiedObject(true); + if(!obj) + return SketchVector; + + // get the Sketch plane + if(obj->isDerivedFrom(Part::Part2DObject::getClassTypeId())) { + Base::Placement SketchPos = obj->Placement.getValue(); + Base::Rotation SketchOrientation = SketchPos.getRotation(); + 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()); + } + } + + return SketchVector; +} + + +void ProfileBased::Restore(Base::XMLReader& reader) { + + reader.readElement("Properties"); + int Cnt = reader.getAttributeAsInteger("Count"); + + for (int i=0 ;i vec; + // read my element + reader.readElement("Link"); + // get the value of my attribute + std::string name = reader.getAttribute("value"); + + if (name != "") { + App::Document* document = getDocument(); + DocumentObject* object = document ? document->getObject(name.c_str()) : 0; + Profile.setValue(object, vec); + } + else { + Profile.setValue(0, vec); + } + } + else if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) + prop->Restore(reader); + } + catch (const Base::XMLParseException&) { + throw; // re-throw + } + catch (const Base::Exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const std::exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const char* e) { + Base::Console().Error("%s\n", e); + } + + reader.readEndElement("Property"); + } + reader.readEndElement("Properties"); +} diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index dd08067f4..21a5adcce 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -37,16 +37,16 @@ class gp_Lin; namespace PartDesign { -class PartDesignExport SketchBased : public PartDesign::FeatureAddSub +class PartDesignExport ProfileBased : public PartDesign::FeatureAddSub { PROPERTY_HEADER(PartDesign::SketchBased); public: - SketchBased(); + ProfileBased(); // Common properties for all sketch based features - /// Sketch used to create this feature - App::PropertyLink Sketch; + /// Profile used to create this feature + App::PropertyLinkSub Profile; /// Reverse extrusion direction App::PropertyBool Reversed; /// Make extrusion symmetric to sketch plane @@ -68,31 +68,46 @@ public: virtual void transformPlacement(const Base::Placement &transform); /** - * Verifies the linked Sketch object - * @param silent if sketch property is malformed and the parameter is true + * Verifies the linked Profile and returns it if it is a valid 2D object + * @param silent if profile property is malformed and the parameter is true * silently returns nullptr, otherwice throw a Base::Exception. * Default is false. */ Part::Part2DObject* getVerifiedSketch(bool silent=false) const; + + /** + * Verifies the linked Profile and returns it if it is a valid object + * @param silent if profile property is malformed and the parameter is true + * silently returns nullptr, otherwice throw a Base::Exception. + * Default is false. + */ + Part::Feature* getVerifiedObject(bool silent=false) const; + + /** + * Verifies the linked Object and returns the shape used as profile + * @param silent if profile 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; + /// Returns the wires the sketch is composed of - std::vector getSketchWires() const; + std::vector getProfileWires() const; + /// Returns the face of the sketch support (if any) const TopoDS_Face getSupportFace() const; + + Base::Vector3d getProfileNormal() const; /// retrieves the number of axes in the linked sketch (defined as construction lines) int getSketchAxisCount(void) const; virtual Part::Feature* getBaseObject(bool silent=false) const; - + + //backwards compatibility: profile property was renamed and has different type now + virtual void Restore(Base::XMLReader& reader); + protected: - void onChanged(const App::Property* prop); - TopoDS_Face validateFace(const TopoDS_Face&) const; - TopoDS_Shape makeFace(const std::vector&) const; - TopoDS_Shape makeFace(std::list&) const; // for internal use only - bool isInside(const TopoDS_Wire&, const TopoDS_Wire&) const; - bool isParallelPlane(const TopoDS_Shape&, const TopoDS_Shape&) const; - bool isEqualGeometry(const TopoDS_Shape&, const TopoDS_Shape&) const; - bool isQuasiEqual(const TopoDS_Shape&, const TopoDS_Shape&) const; void remapSupportShape(const TopoDS_Shape&); TopoDS_Shape refineShapeIfActive(const TopoDS_Shape&) const; @@ -136,6 +151,17 @@ protected: /// get Axis from ReferenceAxis void getAxis(const App::DocumentObject* pcReferenceAxis, const std::vector& subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir); + + TopoDS_Shape makeFace(const std::vector&) const; + +private: + void onChanged(const App::Property* prop); + TopoDS_Face validateFace(const TopoDS_Face&) const; + TopoDS_Shape makeFace(std::list&) const; // for internal use only + bool isInside(const TopoDS_Wire&, const TopoDS_Wire&) const; + bool isParallelPlane(const TopoDS_Shape&, const TopoDS_Shape&) const; + bool isEqualGeometry(const TopoDS_Shape&, const TopoDS_Shape&) const; + bool isQuasiEqual(const TopoDS_Shape&, const TopoDS_Shape&) const; }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index 8168804f0..f8ae76559 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -103,8 +103,8 @@ Part::Feature* Transformed::getBaseObject(bool silent) const { App::DocumentObject* Transformed::getSketchObject() const { std::vector originals = Originals.getValues(); - if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) { - return (static_cast(originals.front()))->getVerifiedSketch(); + if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) { + return (static_cast(originals.front()))->getVerifiedSketch(); } else if (!originals.empty() && originals.front()->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) { return NULL; diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 68c887592..fc14d05df 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -612,11 +612,11 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, } //=========================================================================== -// Common utility functions for SketchBased features +// Common utility functions for ProfileBased features //=========================================================================== // Take a list of Part2DObjects and classify them for creating a -// SketchBased feature. FirstFreeSketch is the first free sketch in the same body +// ProfileBased feature. FirstFreeSketch is the first free sketch in the same body // or sketches.end() if non available. The returned number is the amount of free sketches const unsigned validateSketches(std::vector& sketches, std::vector& status, @@ -705,9 +705,42 @@ const unsigned validateSketches(std::vector& sketches, return freeSketches; } -void prepareSketchBased(Gui::Command* cmd, const std::string& which, - boost::function func) +void prepareProfileBased(Gui::Command* cmd, const std::string& which, + boost::function func) { + auto base_worker = [which, cmd, func](App::DocumentObject* feature, std::string sub) { + + if(!feature || !feature->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + std::string FeatName = cmd->getUniqueObjectName(which.c_str()); + + Gui::Command::openCommand((std::string("Make ") + which).c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")", + which.c_str(), FeatName.c_str()); + + if(feature->isDerivedFrom(Part::Part2DObject::getClassTypeId())) { + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Profile = App.activeDocument().%s", + FeatName.c_str(), feature->getNameInDocument()); + } + else { + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Profile = (App.activeDocument().%s, [\"%s\"])", + FeatName.c_str(), feature->getNameInDocument(), sub.c_str()); + } + + func(static_cast(feature), FeatName); + }; + + //if a profie is selected we can make our life easy and fast + auto selection = cmd->getSelection().getSelectionEx(); + if(!selection.empty() && selection.front().hasSubNames()) { + + base_worker(selection.front().getObject(), selection.front().getSubNames().front()); + return; + } + + //no face profile was selected, do he extended sketch logic + bool bNoSketchWasSelected = false; // Get a valid sketch from the user // First check selections @@ -734,26 +767,12 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which, return true; }; - - auto worker = [which, cmd, func](std::vector features) { - - if(features.empty()) - return; + + auto sketch_worker = [&](std::vector features) { - auto firstValidSketch = features.begin(); - Part::Part2DObject* sketch = static_cast(*firstValidSketch); - - std::string FeatName = cmd->getUniqueObjectName(which.c_str()); - - Gui::Command::openCommand((std::string("Make ") + which).c_str()); - Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject(\"PartDesign::%s\",\"%s\")", - which.c_str(), FeatName.c_str()); - Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s", - FeatName.c_str(), sketch->getNameInDocument()); - - func(sketch, FeatName); + base_worker(features.front(), ""); }; - + //if there is a sketch selected which is from annother body or part we need to bring up the //pick task dialog to decide how those are handled bool ext = std::find_if( status.begin(), status.end(), @@ -814,7 +833,7 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which, Gui::Control().closeDialog(); Gui::Selection().clearSelection(); - pickDlg = new PartDesignGui::TaskDlgFeaturePick(sketches, status, accepter, worker); + pickDlg = new PartDesignGui::TaskDlgFeaturePick(sketches, status, accepter, sketch_worker); if(!bNoSketchWasSelected && ext) pickDlg->showExternal(true); @@ -827,14 +846,15 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which, else theSketch.push_back(*firstFreeSketch); - worker(theSketch); + sketch_worker(theSketch); } } -void finishSketchBased(const Gui::Command* cmd, const Part::Part2DObject* sketch, const std::string& FeatName) +void finishProfileBased(const Gui::Command* cmd, const Part::Feature* sketch, const std::string& FeatName) { - cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument()); + if(sketch && sketch->isDerivedFrom(Part::Part2DObject::getClassTypeId())) + cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument()); finishFeature(cmd, FeatName); } @@ -858,26 +878,28 @@ CmdPartDesignPad::CmdPartDesignPad() void CmdPartDesignPad::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* profile, std::string FeatName) { if (FeatName.empty()) return; // specific parameters for Pad Gui::Command::doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str()); - App::DocumentObjectGroup* grp = sketch->getGroup(); + App::DocumentObjectGroup* grp = profile->getGroup(); if (grp) { Gui::Command::doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)" ,grp->getNameInDocument(),FeatName.c_str()); - Gui::Command::doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)" - ,grp->getNameInDocument(),sketch->getNameInDocument()); + if(profile->isDerivedFrom(Part::Part2DObject::getClassTypeId())) + Gui::Command::doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)" + ,grp->getNameInDocument(), profile->getNameInDocument()); } Gui::Command::updateActive(); - finishSketchBased(cmd, sketch, FeatName); + Part::Part2DObject* sketch = dynamic_cast(profile); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "Pad", worker); + prepareProfileBased(this, "Pad", worker); } bool CmdPartDesignPad::isActive(void) @@ -905,16 +927,16 @@ CmdPartDesignPocket::CmdPartDesignPocket() void CmdPartDesignPocket::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; Gui::Command::doCommand(Doc,"App.activeDocument().%s.Length = 5.0",FeatName.c_str()); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "Pocket", worker); + prepareProfileBased(this, "Pocket", worker); } bool CmdPartDesignPocket::isActive(void) @@ -942,7 +964,7 @@ CmdPartDesignRevolution::CmdPartDesignRevolution() void CmdPartDesignRevolution::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; @@ -953,11 +975,11 @@ void CmdPartDesignRevolution::activated(int iMsg) if (pcRevolution && pcRevolution->suggestReversed()) Gui::Command::doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str()); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "Revolution", worker); + prepareProfileBased(this, "Revolution", worker); } bool CmdPartDesignRevolution::isActive(void) @@ -985,7 +1007,7 @@ CmdPartDesignGroove::CmdPartDesignGroove() void CmdPartDesignGroove::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; @@ -996,11 +1018,11 @@ void CmdPartDesignGroove::activated(int iMsg) if (pcGroove && pcGroove->suggestReversed()) Gui::Command::doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str()); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "Groove", worker); + prepareProfileBased(this, "Groove", worker); } bool CmdPartDesignGroove::isActive(void) @@ -1028,18 +1050,18 @@ CmdPartDesignAdditivePipe::CmdPartDesignAdditivePipe() void CmdPartDesignAdditivePipe::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; // specific parameters for pipe Gui::Command::updateActive(); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "AdditivePipe", worker); + prepareProfileBased(this, "AdditivePipe", worker); } bool CmdPartDesignAdditivePipe::isActive(void) @@ -1068,18 +1090,18 @@ CmdPartDesignSubtractivePipe::CmdPartDesignSubtractivePipe() void CmdPartDesignSubtractivePipe::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; // specific parameters for pipe Gui::Command::updateActive(); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "SubtractivePipe", worker); + prepareProfileBased(this, "SubtractivePipe", worker); } bool CmdPartDesignSubtractivePipe::isActive(void) @@ -1108,18 +1130,18 @@ CmdPartDesignAdditiveLoft::CmdPartDesignAdditiveLoft() void CmdPartDesignAdditiveLoft::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; // specific parameters for pipe Gui::Command::updateActive(); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "AdditiveLoft", worker); + prepareProfileBased(this, "AdditiveLoft", worker); } bool CmdPartDesignAdditiveLoft::isActive(void) @@ -1148,18 +1170,18 @@ CmdPartDesignSubtractiveLoft::CmdPartDesignSubtractiveLoft() void CmdPartDesignSubtractiveLoft::activated(int iMsg) { Gui::Command* cmd = this; - auto worker = [cmd](Part::Part2DObject* sketch, std::string FeatName) { + auto worker = [cmd](Part::Feature* sketch, std::string FeatName) { if (FeatName.empty()) return; // specific parameters for pipe Gui::Command::updateActive(); - finishSketchBased(cmd, sketch, FeatName); + finishProfileBased(cmd, sketch, FeatName); cmd->adjustCameraPosition(); }; - prepareSketchBased(this, "SubtractiveLoft", worker); + prepareProfileBased(this, "SubtractiveLoft", worker); } bool CmdPartDesignSubtractiveLoft::isActive(void) @@ -1523,8 +1545,8 @@ void CmdPartDesignMirrored::activated(int iMsg) if (features.empty()) return; - if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) { - Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); + if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) { + Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); if (sketch) Gui::Command::doCommand(Doc,"App.activeDocument().%s.MirrorPlane = (App.activeDocument().%s, [\"V_Axis\"])", FeatName.c_str(), sketch->getNameInDocument()); @@ -1571,8 +1593,8 @@ void CmdPartDesignLinearPattern::activated(int iMsg) if (features.empty()) return; - if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) { - Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); + if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) { + Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); if (sketch) doCommand(Doc,"App.activeDocument().%s.Direction = (App.activeDocument().%s, [\"H_Axis\"])", FeatName.c_str(), sketch->getNameInDocument()); @@ -1621,8 +1643,8 @@ void CmdPartDesignPolarPattern::activated(int iMsg) if (features.empty()) return; - if(features.front()->isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) { - Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); + if(features.front()->isDerivedFrom(PartDesign::ProfileBased::getClassTypeId())) { + Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(/* silent =*/ true); if (sketch) doCommand(Doc,"App.activeDocument().%s.Axis = (App.activeDocument().%s, [\"N_Axis\"])", FeatName.c_str(), sketch->getNameInDocument()); diff --git a/src/Mod/PartDesign/Gui/CommandBody.cpp b/src/Mod/PartDesign/Gui/CommandBody.cpp index ba891eaac..c99a6a53f 100644 --- a/src/Mod/PartDesign/Gui/CommandBody.cpp +++ b/src/Mod/PartDesign/Gui/CommandBody.cpp @@ -373,9 +373,9 @@ void CmdPartDesignMigrate::activated(int iMsg) // Fill the body with features for ( auto feature: *chainIt ) { - if ( feature->isDerivedFrom ( PartDesign::SketchBased::getClassTypeId() ) ) { + if ( feature->isDerivedFrom ( PartDesign::ProfileBased::getClassTypeId() ) ) { // add the sketch and also reroute it if needed - PartDesign::SketchBased *sketchBased = static_cast ( feature ); + PartDesign::ProfileBased *sketchBased = static_cast ( feature ); Part::Part2DObject *sketch = sketchBased->getVerifiedSketch( /*silent =*/ true); if ( sketch ) { doCommand ( Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index 2add23f83..70e5e41e6 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -86,7 +86,7 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* ui->checkBoxReversed->blockSignals(true); //bind property mirrors - PartDesign::SketchBased* pcFeat = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); if (pcFeat->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) { PartDesign::Revolution* rev = static_cast(vp->getObject()); this->propAngle = &(rev->Angle); @@ -114,7 +114,7 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* ui->checkBoxMidplane->setChecked(mirrored); ui->checkBoxReversed->setChecked(reversed); - PartDesign::SketchBased* sketchBased = static_cast(vp->getObject()); + PartDesign::ProfileBased* sketchBased = static_cast(vp->getObject()); // TODO This is quite ugly better redo it (2015-11-02, Fat-Zer) if ( sketchBased->isDerivedFrom(PartDesign::Revolution::getClassTypeId() ) ) { ui->revolveAngle->bind(static_cast ( sketchBased )->Angle); @@ -161,8 +161,8 @@ void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) this->axesInList.clear(); //add sketch axes - PartDesign::SketchBased* pcFeat = static_cast(vp->getObject()); - Part::Part2DObject* pcSketch = static_cast(pcFeat->Sketch.getValue()); + PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); + Part::Part2DObject* pcSketch = static_cast(pcFeat->Profile.getValue()); if (pcSketch){ addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis")); addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis")); @@ -268,7 +268,7 @@ void TaskRevolutionParameters::onAxisChanged(int num) { if (blockUpdate) return; - PartDesign::SketchBased* pcRevolution = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcRevolution = static_cast(vp->getObject()); if(axesInList.size() == 0) return; @@ -338,7 +338,7 @@ void TaskRevolutionParameters::getReferenceAxis(App::DocumentObject*& obj, std:: if(lnk.getValue() == 0){ throw Base::Exception("Still in reference selection mode; reference wasn't selected yet"); } else { - PartDesign::SketchBased* pcRevolution = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcRevolution = static_cast(vp->getObject()); if (! pcRevolution->getDocument()->isIn(lnk.getValue())){ throw Base::Exception("Object was deleted"); return; diff --git a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp index 114b46366..2f7745d4a 100644 --- a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp @@ -68,7 +68,7 @@ TaskSketchBasedParameters::TaskSketchBasedParameters(PartDesignGui::ViewProvider const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChanges& msg) { // Note: The validity checking has already been done in ReferenceSelection.cpp - PartDesign::SketchBased* pcSketchBased = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcSketchBased = static_cast(vp->getObject()); App::DocumentObject* selObj = pcSketchBased->getDocument()->getObject(msg.pObjectName); if (selObj == pcSketchBased) return QString::fromAscii(""); @@ -94,7 +94,7 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar) { // Note: Even if there is no solid, App::Plane and Part::Datum can still be selected - PartDesign::SketchBased* pcSketchBased = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcSketchBased = static_cast(vp->getObject()); // The solid this feature will be fused to App::DocumentObject* prevSolid = pcSketchBased->getBaseObject( /* silent =*/ true ); @@ -163,7 +163,7 @@ const QByteArray TaskSketchBasedParameters::onFaceName(const QString& text) ss << "Face" << faceId; std::vector upToFaces(1,ss.str()); - PartDesign::SketchBased* pcSketchBased = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcSketchBased = static_cast(vp->getObject()); pcSketchBased->UpToFace.setValue(obj, upToFaces); recomputeFeature(); @@ -210,11 +210,11 @@ bool TaskDlgSketchBasedParameters::accept() { // Make sure the feature is what we are expecting // Should be fine but you never know... - if ( !feature->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId()) ) { + if ( !feature->getTypeId().isDerivedFrom(PartDesign::ProfileBased::getClassTypeId()) ) { throw Base::Exception("Bad object processed in the sketch based dialog."); } - App::DocumentObject* sketch = static_cast(feature)->Sketch.getValue(); + App::DocumentObject* sketch = static_cast(feature)->Profile.getValue(); if (sketch) { Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument()); @@ -225,9 +225,9 @@ bool TaskDlgSketchBasedParameters::accept() { bool TaskDlgSketchBasedParameters::reject() { - PartDesign::SketchBased* pcSketchBased = static_cast(vp->getObject()); + PartDesign::ProfileBased* pcSketchBased = static_cast(vp->getObject()); // get the Sketch - Sketcher::SketchObject *pcSketch = static_cast(pcSketchBased->Sketch.getValue()); + Sketcher::SketchObject *pcSketch = static_cast(pcSketchBased->Profile.getValue()); bool rv; // rv should be true anyway but to be on the safe side dur to thurver changes better respect it. diff --git a/src/Mod/PartDesign/Gui/ViewProviderHole.cpp b/src/Mod/PartDesign/Gui/ViewProviderHole.cpp index 22ffd473f..f0c0d07bc 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderHole.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderHole.cpp @@ -45,7 +45,7 @@ ViewProviderHole::~ViewProviderHole() std::vector ViewProviderHole::claimChildren(void)const { std::vector temp; - temp.push_back(static_cast(getObject())->Sketch.getValue()); + temp.push_back(static_cast(getObject())->Profile.getValue()); return temp; } diff --git a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp index 0f35c5b3c..94e578461 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp @@ -55,7 +55,7 @@ ViewProviderLoft::~ViewProviderLoft() std::vector ViewProviderLoft::claimChildren(void)const { std::vector temp; - App::DocumentObject* sketch = static_cast(getObject())->Sketch.getValue(); + App::DocumentObject* sketch = static_cast(getObject())->Profile.getValue(); if (sketch != NULL) temp.push_back(sketch); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp index d93063ec0..d062f22ba 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp @@ -55,7 +55,7 @@ ViewProviderPipe::~ViewProviderPipe() std::vector ViewProviderPipe::claimChildren(void)const { std::vector temp; - App::DocumentObject* sketch = static_cast(getObject())->Sketch.getValue(); + App::DocumentObject* sketch = static_cast(getObject())->Profile.getValue(); if (sketch != NULL) temp.push_back(sketch); diff --git a/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp b/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp index 46db9872b..fb47925a0 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp @@ -50,8 +50,8 @@ ViewProviderSketchBased::~ViewProviderSketchBased() std::vector ViewProviderSketchBased::claimChildren(void) const { std::vector temp; - App::DocumentObject* sketch = static_cast(getObject())->Sketch.getValue(); - if (sketch != NULL) + App::DocumentObject* sketch = static_cast(getObject())->Profile.getValue(); + if (sketch != NULL && sketch->isDerivedFrom(Part::Part2DObject::getClassTypeId())) temp.push_back(sketch); return temp; @@ -59,12 +59,12 @@ std::vector ViewProviderSketchBased::claimChildren(void) c bool ViewProviderSketchBased::onDelete(const std::vector &s) { - PartDesign::SketchBased* feature = static_cast(getObject()); + PartDesign::ProfileBased* feature = static_cast(getObject()); // get the Sketch Sketcher::SketchObject *pcSketch = 0; - if (feature->Sketch.getValue()) - pcSketch = static_cast(feature->Sketch.getValue()); + if (feature->Profile.getValue()) + pcSketch = static_cast(feature->Profile.getValue()); // if abort command deleted the object the sketch is visible again if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))