diff --git a/src/Mod/Part/App/Part2DObject.cpp b/src/Mod/Part/App/Part2DObject.cpp index 422d2383f..373d60e89 100644 --- a/src/Mod/Part/App/Part2DObject.cpp +++ b/src/Mod/Part/App/Part2DObject.cpp @@ -51,6 +51,8 @@ using namespace Part; +const int Part2DObject::H_Axis = -2; +const int Part2DObject::V_Axis = -3; PROPERTY_SOURCE(Part::Part2DObject, Part::Feature) @@ -184,6 +186,16 @@ void Part2DObject::positionBySupport(void) Placement.setValue(Base::Placement(mtrx)); } +int Part2DObject::getAxisCount(void) const +{ + return 0; +} + +Base::Axis Part2DObject::getAxis(int axId) const +{ + return Base::Axis(); +} + bool Part2DObject::seekTrimPoints(const std::vector &geomlist, int GeoId, const Base::Vector3d &point, int &GeoId1, Base::Vector3d &intersect1, diff --git a/src/Mod/Part/App/Part2DObject.h b/src/Mod/Part/App/Part2DObject.h index d8c0aabac..b5e862878 100644 --- a/src/Mod/Part/App/Part2DObject.h +++ b/src/Mod/Part/App/Part2DObject.h @@ -26,6 +26,7 @@ #define PART_PART2DOBJECT_H #include +#include #include "PartFeature.h" @@ -68,6 +69,11 @@ public: */ void positionBySupport(void); + /// returns the number of construction lines (to be used as axes) + virtual int getAxisCount(void) const; + /// retrieves an axis iterating through the construction lines of the sketch (indices start at 0) + virtual Base::Axis getAxis(int axId) const; + /** calculate the points where a curve with index GeoId should be trimmed * with respect to the rest of the curves contained in the list geomlist * and a picked point. The outputs intersect1 and intersect2 specify the @@ -80,6 +86,9 @@ public: int &GeoId1, Base::Vector3d &intersect1, int &GeoId2, Base::Vector3d &intersect2); + static const int H_Axis; + static const int V_Axis; + /** @name methods overide Feature */ //@{ /// recalculate the Feature diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 89639a5ea..317aa52d1 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -35,6 +35,7 @@ # include #endif +#include #include #include #include @@ -54,11 +55,14 @@ Revolution::Revolution() ADD_PROPERTY(Base,(Base::Vector3f(0.0f,0.0f,0.0f))); ADD_PROPERTY(Axis,(Base::Vector3f(0.0f,1.0f,0.0f))); ADD_PROPERTY(Angle,(360.0)); + ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Revolution",(App::PropertyType)(App::Prop_None),"Reference axis of revolution"); } short Revolution::mustExecute() const { - if (Sketch.isTouched() || + if (Placement.isTouched() || + Sketch.isTouched() || + ReferenceAxis.isTouched() || Axis.isTouched() || Base.isTouched() || Angle.isTouched()) @@ -73,7 +77,10 @@ App::DocumentObjectExecReturn *Revolution::execute(void) return new App::DocumentObjectExecReturn("No sketch linked"); if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); - TopoDS_Shape shape = static_cast(link)->Shape.getShape()._Shape; + + Part::Part2DObject* pcSketch=static_cast(link); + + TopoDS_Shape shape = pcSketch->Shape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); @@ -94,40 +101,63 @@ App::DocumentObjectExecReturn *Revolution::execute(void) } if (wires.empty()) // there can be several wires return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); -#if 0 - App::DocumentObject* support = sketch->Support.getValue(); - Base::Placement placement = sketch->Placement.getValue(); - Base::Vector3d axis(0,1,0); - placement.getRotation().multVec(axis, axis); - Base::BoundBox3d bbox = sketch->Shape.getBoundingBox(); - bbox.Enlarge(0.1); - Base::Vector3d base(bbox.MaxX, bbox.MaxY, bbox.MaxZ); -#endif + // get the Sketch plane - Base::Placement SketchPos = static_cast(link)->Placement.getValue(); - Base::Rotation SketchOrientation = SketchPos.getRotation(); - // get rvolve axis - Base::Vector3f v = Axis.getValue(); - Base::Vector3d SketchOrientationVector(v.x,v.y,v.z); - SketchOrientation.multVec(SketchOrientationVector,SketchOrientationVector); + Base::Placement SketchPlm = pcSketch->Placement.getValue(); + // get reference axis + App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == pcSketch) { + bool hasValidAxis=false; + Base::Axis axis; + if (subReferenceAxis[0] == "V_Axis") { + hasValidAxis = true; + axis = pcSketch->getAxis(Part::Part2DObject::V_Axis); + } + else if (subReferenceAxis[0] == "H_Axis") { + hasValidAxis = true; + axis = pcSketch->getAxis(Part::Part2DObject::H_Axis); + } + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { + int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + if (AxId >= 0 && AxId < pcSketch->getAxisCount()) { + hasValidAxis = true; + axis = pcSketch->getAxis(AxId); + } + } + if (hasValidAxis) { + axis *= SketchPlm; + Base::Vector3d base=axis.getBase(); + Base::Vector3d dir=axis.getDirection(); + Base.setValue(base.x,base.y,base.z); + Axis.setValue(dir.x,dir.y,dir.z); + } + } + // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); - gp_Dir dir(SketchOrientationVector.x,SketchOrientationVector.y,SketchOrientationVector.z); + Base::Vector3f v = Axis.getValue(); + gp_Dir dir(v.x,v.y,v.z); // get the support of the Sketch if any - App::DocumentObject* SupportLink = static_cast(link)->Support.getValue(); + App::DocumentObject* pcSupport = pcSketch->Support.getValue(); Part::Feature *SupportObject = 0; - if (SupportLink && SupportLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - SupportObject = static_cast(SupportLink); + if (pcSupport && pcSupport->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + SupportObject = static_cast(pcSupport); TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); + this->positionBySketch(); + TopLoc_Location invObjLoc = this->getLocation().Inverted(); + pnt.Transform(invObjLoc.Transformation()); + dir.Transform(invObjLoc.Transformation()); + // revolve the face to a solid - BRepPrimAPI_MakeRevol RevolMaker(aFace,gp_Ax1(pnt, dir), Base::toRadians(Angle.getValue())); + BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), Base::toRadians(Angle.getValue())); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); @@ -136,9 +166,9 @@ App::DocumentObjectExecReturn *Revolution::execute(void) const TopoDS_Shape& support = SupportObject->Shape.getValue(); if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Fuse mkFuse(support, result); + BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); // Let's check if the fusion has been successful - if (!mkFuse.IsDone()) + if (!mkFuse.IsDone()) throw Base::Exception("Fusion with support failed"); result = mkFuse.Shape(); } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index b6faf2192..4d6677d54 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -41,6 +41,11 @@ public: App::PropertyVector Axis; App::PropertyAngle Angle; + /** if this property is set to a valid link, both Axis and Base properties + * are calculated according to the linked line + */ + App::PropertyLinkSub ReferenceAxis; + /** @name methods override feature */ //@{ /// recalculate the feature diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 1ebd2db1c..286e51815 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -51,7 +51,6 @@ #include "FeatureSketchBased.h" #include - using namespace PartDesign; namespace PartDesign { @@ -256,4 +255,10 @@ TopoDS_Shape SketchBased::makeFace(const std::vector& w) const } } +int SketchBased::getSketchAxisCount(void) const +{ + Part::Part2DObject *sketch = static_cast(Sketch.getValue()); + return sketch->getAxisCount(); +} + } diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 947c0356e..e688100b2 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -47,6 +47,9 @@ public: */ void positionBySketch(void); + /// retrieves the number of axes in the linked sketch (defined as construction lines) + int getSketchAxisCount(void) const; + protected: TopoDS_Face validateFace(const TopoDS_Face&) const; TopoDS_Shape makeFace(const std::vector&) const; diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index dd57f1c4f..6737140b2 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -48,7 +48,7 @@ using namespace std; //DEF_STD_CMD_A(CmdPartDesignNewSketch); // //CmdPartDesignNewSketch::CmdPartDesignNewSketch() -// :Command("PartDesign_NewSketch") +// :Command("PartDesign_NewSketch") //{ // sAppModule = "PartDesign"; // sGroup = QT_TR_NOOP("PartDesign"); @@ -72,7 +72,7 @@ using namespace std; // doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str()); // doCommand(Gui,"Gui.activeDocument().activeView().setCamera('%s')",cam.c_str()); // doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); -// +// // //getDocument()->recompute(); //} // @@ -293,7 +293,8 @@ void CmdPartDesignRevolution::activated(int iMsg) openCommand("Make Revolution"); doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Revolution\",\"%s\")",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",FeatName.c_str(),sketch->getNameInDocument()); - doCommand(Doc,"App.activeDocument().%s.Axis = App.Vector(0,1,0)",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])", + FeatName.c_str(), sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Angle = 360.0",FeatName.c_str()); updateActive(); if (isActiveObjectValid()) { diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index d0ac1895b..05b01058f 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -65,15 +65,37 @@ TaskRevolutionParameters::TaskRevolutionParameters(ViewProviderRevolution *Revol PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); double l = pcRevolution->Angle.getValue(); - Base::Vector3f Ax = pcRevolution->Axis.getValue(); - ui->doubleSpinBox->setValue(l); - ui->doubleSpinBox->selectAll(); - QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); - if (Ax.y > 0) - ui->axis->setCurrentIndex(0); - else - ui->axis->setCurrentIndex(1); + + int count=pcRevolution->getSketchAxisCount(); + + for (int i=ui->axis->count()-1; i >= count+2; i--) + ui->axis->removeItem(i); + for (int i=ui->axis->count(); i < count+2; i++) + ui->axis->addItem(QString::fromAscii("Sketch axis %1").arg(i-2)); + + int pos=-1; + + App::DocumentObject *pcReferenceAxis = pcRevolution->ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = pcRevolution->ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == pcRevolution->Sketch.getValue()) { + assert(subReferenceAxis.size()==1); + if (subReferenceAxis[0] == "V_Axis") + pos = 0; + else if (subReferenceAxis[0] == "H_Axis") + pos = 1; + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") + pos = 2 + std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + } + + if (pos < 0 || pos >= ui->axis->count()) { + ui->axis->addItem(QString::fromAscii("Undefined")); + pos = ui->axis->count()-1; + } + + ui->axis->setCurrentIndex(pos); + + setFocus (); } void TaskRevolutionParameters::onAngleChanged(double len) @@ -86,11 +108,21 @@ void TaskRevolutionParameters::onAngleChanged(double len) void TaskRevolutionParameters::onAxisChanged(int num) { PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); - if(num == 0) - pcRevolution->Axis.setValue(Base::Vector3f(0,1,0)); - else - pcRevolution->Axis.setValue(Base::Vector3f(1,0,0)); - + Sketcher::SketchObject *pcSketch = static_cast(pcRevolution->Sketch.getValue()); + if (pcSketch) { + int maxcount = pcSketch->getAxisCount()+2; + if (num == 0) + pcRevolution->ReferenceAxis.setValue(pcSketch, std::vector(1,"V_Axis")); + else if (num == 1) + pcRevolution->ReferenceAxis.setValue(pcSketch, std::vector(1,"H_Axis")); + else if (num >= 2 && num < maxcount) { + QString buf = QString::fromUtf8("Axis%1").arg(num-2); + std::string str = buf.toStdString(); + pcRevolution->ReferenceAxis.setValue(pcSketch, std::vector(1,str)); + } + if (num < maxcount && ui->axis->count() > maxcount) + ui->axis->setMaxCount(maxcount); + } pcRevolution->getDocument()->recomputeFeature(pcRevolution); } @@ -100,16 +132,31 @@ double TaskRevolutionParameters::getAngle(void) const return ui->doubleSpinBox->value(); } -Base::Vector3f TaskRevolutionParameters::getAxis(void) const +QString TaskRevolutionParameters::getReferenceAxis(void) const { - if( ui->axis->currentIndex() == 0) - return Base::Vector3f(0,1,0); + // get the support and Sketch + PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); + Sketcher::SketchObject *pcSketch = static_cast(pcRevolution->Sketch.getValue()); + + QString buf; + if (pcSketch) { + buf = QString::fromUtf8("(App.ActiveDocument.%1,[%2])"); + buf = buf.arg(QString::fromUtf8(pcSketch->getNameInDocument())); + if (ui->axis->currentIndex() == 0) + buf = buf.arg(QString::fromUtf8("'V_Axis'")); + else if (ui->axis->currentIndex() == 1) + buf = buf.arg(QString::fromUtf8("'H_Axis'")); + else if (ui->axis->currentIndex() >= 2) { + buf = buf.arg(QString::fromUtf8("'Axis%1'")); + buf = buf.arg(ui->axis->currentIndex()-2); + } + } else - return Base::Vector3f(1,0,0); + buf = QString::fromUtf8("''"); + return buf; } - TaskRevolutionParameters::~TaskRevolutionParameters() { delete ui; @@ -147,12 +194,12 @@ TaskDlgRevolutionParameters::~TaskDlgRevolutionParameters() void TaskDlgRevolutionParameters::open() { - + } void TaskDlgRevolutionParameters::clicked(int) { - + } bool TaskDlgRevolutionParameters::accept() @@ -161,8 +208,8 @@ bool TaskDlgRevolutionParameters::accept() //Gui::Command::openCommand("Revolution changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Angle = %f",name.c_str(),parameter->getAngle()); - Base::Vector3f axis = parameter->getAxis(); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Axis = FreeCAD.Vector(%f,%f,%f)",name.c_str(),axis.x,axis.y,axis.z); + std::string axis = parameter->getReferenceAxis().toStdString(); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ReferenceAxis = %s",name.c_str(),axis.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); @@ -173,18 +220,18 @@ bool TaskDlgRevolutionParameters::accept() bool TaskDlgRevolutionParameters::reject() { // get the support and Sketch - PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); + PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); Sketcher::SketchObject *pcSketch; App::DocumentObject *pcSupport; if (pcRevolution->Sketch.getValue()) { - pcSketch = static_cast(pcRevolution->Sketch.getValue()); + pcSketch = static_cast(pcRevolution->Sketch.getValue()); pcSupport = pcSketch->Support.getValue(); } // role back the done things Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); - + // if abort command deleted the object the support is visible again if (!Gui::Application::Instance->getViewProvider(pcRevolution)) { if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch)) diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h index 71d396428..dcafbd618 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h @@ -52,8 +52,8 @@ public: TaskRevolutionParameters(ViewProviderRevolution *RevolutionView,QWidget *parent = 0); ~TaskRevolutionParameters(); - Base::Vector3f getAxis (void) const; - double getAngle(void) const; + QString getReferenceAxis(void) const; + double getAngle(void) const; private Q_SLOTS: void onAngleChanged(double); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui index aed4c1e66..e7a062aa7 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui @@ -27,12 +27,12 @@ - Vertical + Vertical sketch axis - Horizontal + Horizontal sketch axis diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index bdbeb9b1c..c0c9fc65d 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -222,6 +222,12 @@ int SketchObject::getAxisCount(void) const Base::Axis SketchObject::getAxis(int axId) const { const std::vector< Part::Geometry * > &vals = this->Geometry.getValues(); + if (axId == H_Axis) { + return Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0)); + } + else if (axId == V_Axis) { + return Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0)); + } int count=0; for (std::vector::const_iterator geo=vals.begin(); diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index e182f7a0d..2e91d49b9 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -89,10 +89,6 @@ public: int movePoint(int geoIndex1, PointPos Pos1, const Base::Vector3d& toPoint, bool relative=false); /// retrieves the coordinates of a point Base::Vector3d getPoint(int geoIndex1, PointPos Pos1); - /// returns the number of construction lines (to be used as axes) - int getAxisCount(void) const; - /// retrieves an axis iterating through the construction lines of the sketch (indices start at 0) - Base::Axis getAxis(int axId) const; /// toggle geometry to draft line int toggleConstruction(int GeoNbr); @@ -125,6 +121,11 @@ public: virtual unsigned int getMemSize(void) const; virtual void Save(Base::Writer &/*writer*/) const; virtual void Restore(Base::XMLReader &/*reader*/); + + /// returns the number of construction lines (to be used as axes) + virtual int getAxisCount(void) const; + /// retrieves an axis iterating through the construction lines of the sketch (indices start at 0) + virtual Base::Axis getAxis(int axId) const; protected: /// get called by the container when a property has changed