diff --git a/src/Mod/Fem/App/FemConstraint.cpp b/src/Mod/Fem/App/FemConstraint.cpp index 98d7fc92f..32c8bcd26 100644 --- a/src/Mod/Fem/App/FemConstraint.cpp +++ b/src/Mod/Fem/App/FemConstraint.cpp @@ -78,7 +78,7 @@ App::DocumentObjectExecReturn *Constraint::execute(void) void Constraint::onChanged(const App::Property* prop) { - Base::Console().Error("Constraint::onChanged() %s\n", prop->getName()); + //Base::Console().Error("Constraint::onChanged() %s\n", prop->getName()); if (prop == &References) { // If References are changed, recalculate the normal direction. If no useful reference is found, // use z axis or previous value. If several faces are selected, only the first one is used @@ -254,7 +254,10 @@ Base::Vector3f Constraint::getBasePoint(const Base::Vector3f& base, const Base:: { // Get the point specified by Location and Distance App::DocumentObject* objLoc = location.getValue(); - std::string subName = location.getSubValues().front(); + std::vector names = location.getSubValues(); + if (names.size() == 0) + return Base::Vector3f(0,0,0); + std::string subName = names.front(); Part::Feature* featLoc = static_cast(objLoc); TopoDS_Shape shloc = featLoc->Shape.getShape().getSubShape(subName.c_str()); @@ -292,3 +295,35 @@ Base::Vector3f Constraint::getBasePoint(const Base::Vector3f& base, const Base:: gp_Pnt inter = intersector.Point(1); return Base::Vector3f(inter.X(), inter.Y(), inter.Z()); } + +const Base::Vector3f Constraint::getDirection(const App::PropertyLinkSub &direction) +{ + App::DocumentObject* obj = direction.getValue(); + std::vector names = direction.getSubValues(); + if (names.size() == 0) + return Base::Vector3f(0,0,0); + std::string subName = names.front(); + Part::Feature* feat = static_cast(obj); + TopoDS_Shape sh = feat->Shape.getShape().getSubShape(subName.c_str()); + gp_Dir dir; + + if (sh.ShapeType() == TopAbs_FACE) { + BRepAdaptor_Surface surface(TopoDS::Face(sh)); + if (surface.GetType() == GeomAbs_Plane) { + dir = surface.Plane().Axis().Direction(); + } else { + return Base::Vector3f(0,0,0); // "Direction must be a planar face or linear edge" + } + } else if (sh.ShapeType() == TopAbs_EDGE) { + BRepAdaptor_Curve line(TopoDS::Edge(sh)); + if (line.GetType() == GeomAbs_Line) { + dir = line.Line().Direction(); + } else { + return Base::Vector3f(0,0,0); // "Direction must be a planar face or linear edge" + } + } + + Base::Vector3f the_direction(dir.X(), dir.Y(), dir.Z()); + the_direction.Normalize(); + return the_direction; +} diff --git a/src/Mod/Fem/App/FemConstraint.h b/src/Mod/Fem/App/FemConstraint.h index 181418327..157d76285 100644 --- a/src/Mod/Fem/App/FemConstraint.h +++ b/src/Mod/Fem/App/FemConstraint.h @@ -42,6 +42,7 @@ public: virtual ~Constraint(); App::PropertyLinkSubList References; + // Read-only (calculated values). These trigger changes in the ViewProvider App::PropertyVector NormalDirection; /// recalculate the object @@ -62,6 +63,7 @@ protected: const bool getCylinder(float& radius, float& height, Base::Vector3f& base, Base::Vector3f& axis) const; Base::Vector3f getBasePoint(const Base::Vector3f& base, const Base::Vector3f& axis, const App::PropertyLinkSub &location, const float& dist); + const Base::Vector3f getDirection(const App::PropertyLinkSub &direction); }; diff --git a/src/Mod/Fem/App/FemConstraintBearing.cpp b/src/Mod/Fem/App/FemConstraintBearing.cpp index 51aa790d0..ed399bd02 100644 --- a/src/Mod/Fem/App/FemConstraintBearing.cpp +++ b/src/Mod/Fem/App/FemConstraintBearing.cpp @@ -58,13 +58,12 @@ ConstraintBearing::ConstraintBearing() App::DocumentObjectExecReturn *ConstraintBearing::execute(void) { - Base::Console().Error("ConstraintBearing: execute()\n"); return Constraint::execute(); } void ConstraintBearing::onChanged(const App::Property* prop) { - Base::Console().Error("ConstraintBearing: onChanged %s\n", prop->getName()); + //Base::Console().Error("ConstraintBearing: onChanged %s\n", prop->getName()); // Note: If we call this at the end, then the symbol ist not oriented correctly initially // because the NormalDirection has not been calculated yet Constraint::onChanged(prop); diff --git a/src/Mod/Fem/App/FemConstraintBearing.h b/src/Mod/Fem/App/FemConstraintBearing.h index 6385e6b48..66fcd0e07 100644 --- a/src/Mod/Fem/App/FemConstraintBearing.h +++ b/src/Mod/Fem/App/FemConstraintBearing.h @@ -41,8 +41,11 @@ public: /// Constructor ConstraintBearing(void); + /// Location reference App::PropertyLinkSub Location; + /// Distance from location reference App::PropertyFloat Dist; + /// Is the bearing free to move in axial direction? App::PropertyBool AxialFree; // Read-only (calculated values). These trigger changes in the ViewProvider App::PropertyFloat Radius; diff --git a/src/Mod/Fem/App/FemConstraintForce.cpp b/src/Mod/Fem/App/FemConstraintForce.cpp index 034acaae9..771929d23 100644 --- a/src/Mod/Fem/App/FemConstraintForce.cpp +++ b/src/Mod/Fem/App/FemConstraintForce.cpp @@ -75,34 +75,9 @@ void ConstraintForce::onChanged(const App::Property* prop) Points.touch(); // This triggers ViewProvider::updateData() } } else if (prop == &Direction) { - App::DocumentObject* obj = Direction.getValue(); - std::vector names = Direction.getSubValues(); - if (names.size() == 0) { + Base::Vector3f direction = getDirection(Direction); + if (direction.Length() < Precision::Confusion()) return; - } - std::string subName = names.front(); - Part::Feature* feat = static_cast(obj); - TopoDS_Shape sh = feat->Shape.getShape().getSubShape(subName.c_str()); - gp_Dir dir; - - if (sh.ShapeType() == TopAbs_FACE) { - BRepAdaptor_Surface surface(TopoDS::Face(sh)); - if (surface.GetType() == GeomAbs_Plane) { - dir = surface.Plane().Axis().Direction(); - } else { - return; // "Direction must be a planar face or linear edge" - } - } else if (sh.ShapeType() == TopAbs_EDGE) { - BRepAdaptor_Curve line(TopoDS::Edge(sh)); - if (line.GetType() == GeomAbs_Line) { - dir = line.Line().Direction(); - } else { - return; // "Direction must be a planar face or linear edge" - } - } - - Base::Vector3f direction(dir.X(), dir.Y(), dir.Z()); - direction.Normalize(); naturalDirectionVector = direction; if (Reversed.getValue()) direction = -direction; diff --git a/src/Mod/Fem/App/FemConstraintGear.cpp b/src/Mod/Fem/App/FemConstraintGear.cpp index 7505b8bbf..cc4a68ca5 100644 --- a/src/Mod/Fem/App/FemConstraintGear.cpp +++ b/src/Mod/Fem/App/FemConstraintGear.cpp @@ -45,6 +45,14 @@ PROPERTY_SOURCE(Fem::ConstraintGear, Fem::ConstraintBearing); ConstraintGear::ConstraintGear() { ADD_PROPERTY(Diameter,(0)); + ADD_PROPERTY(Force,(0.0)); + ADD_PROPERTY(ForceAngle,(0.0)); + ADD_PROPERTY_TYPE(Direction,(0),"ConstraintGear",(App::PropertyType)(App::Prop_None), + "Element giving direction of gear force"); + ADD_PROPERTY(Reversed,(0)); + ADD_PROPERTY_TYPE(DirectionVector,(Base::Vector3f(0,1,0)),"ConstraintGear",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "Direction of gear force"); + naturalDirectionVector = Base::Vector3f(0,1,0); } App::DocumentObjectExecReturn *ConstraintGear::execute(void) @@ -55,4 +63,24 @@ App::DocumentObjectExecReturn *ConstraintGear::execute(void) void ConstraintGear::onChanged(const App::Property* prop) { ConstraintBearing::onChanged(prop); + + if (prop == &Direction) { + Base::Vector3f direction = getDirection(Direction); + if (direction.Length() < Precision::Confusion()) + return; + naturalDirectionVector = direction; + if (Reversed.getValue()) + direction = -direction; + DirectionVector.setValue(direction); + DirectionVector.touch(); + } else if (prop == &Reversed) { + if (Reversed.getValue() && (DirectionVector.getValue() == naturalDirectionVector)) { + DirectionVector.setValue(-naturalDirectionVector); + DirectionVector.touch(); + } else if (!Reversed.getValue() && (DirectionVector.getValue() != naturalDirectionVector)) { + DirectionVector.setValue(naturalDirectionVector); + DirectionVector.touch(); + } + } + // The computation for the force angle is simpler in the ViewProvider directly } diff --git a/src/Mod/Fem/App/FemConstraintGear.h b/src/Mod/Fem/App/FemConstraintGear.h index a18053ff0..11926f350 100644 --- a/src/Mod/Fem/App/FemConstraintGear.h +++ b/src/Mod/Fem/App/FemConstraintGear.h @@ -42,6 +42,12 @@ public: ConstraintGear(void); App::PropertyFloat Diameter; + App::PropertyFloat Force; + App::PropertyFloat ForceAngle; + App::PropertyLinkSub Direction; + App::PropertyBool Reversed; + // Read-only (calculated values). These trigger changes in the ViewProvider + App::PropertyVector DirectionVector; /// recalculate the object virtual App::DocumentObjectExecReturn *execute(void); @@ -53,6 +59,9 @@ public: protected: virtual void onChanged(const App::Property* prop); + +private: + Base::Vector3f naturalDirectionVector; }; } //namespace Fem diff --git a/src/Mod/Fem/App/FemConstraintPulley.cpp b/src/Mod/Fem/App/FemConstraintPulley.cpp index d4c5efbbe..7b83d6b34 100644 --- a/src/Mod/Fem/App/FemConstraintPulley.cpp +++ b/src/Mod/Fem/App/FemConstraintPulley.cpp @@ -40,15 +40,23 @@ using namespace Fem; -PROPERTY_SOURCE(Fem::ConstraintPulley, Fem::ConstraintBearing); +PROPERTY_SOURCE(Fem::ConstraintPulley, Fem::ConstraintGear); ConstraintPulley::ConstraintPulley() { - ADD_PROPERTY(Diameter,(0)); ADD_PROPERTY(OtherDiameter,(0)); ADD_PROPERTY(CenterDistance,(0)); - ADD_PROPERTY_TYPE(Angle,(0),"ConstraintPulley",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), - "Angle of pulley forces"); + ADD_PROPERTY(IsDriven,(0)); + ADD_PROPERTY(TensionForce,(0.0)); + + ADD_PROPERTY_TYPE(BeltAngle,(0),"ConstraintPulley",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "Angle of belt forces"); + ADD_PROPERTY_TYPE(BeltForce1,(0.0),"ConstraintPulley",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "First belt force"); + ADD_PROPERTY_TYPE(BeltForce2,(0.0),"ConstraintPulley",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "Second belt force"); + ForceAngle.setValue(90.0); + Diameter.setValue(300.0); } App::DocumentObjectExecReturn *ConstraintPulley::execute(void) @@ -58,12 +66,31 @@ App::DocumentObjectExecReturn *ConstraintPulley::execute(void) void ConstraintPulley::onChanged(const App::Property* prop) { - ConstraintBearing::onChanged(prop); + ConstraintGear::onChanged(prop); if ((prop == &Diameter) || (prop == &OtherDiameter) || (prop == &CenterDistance)) { if (CenterDistance.getValue() > Precision::Confusion()) { - Angle.setValue(asin((Diameter.getValue() - OtherDiameter.getValue())/2/CenterDistance.getValue())); - Angle.touch(); + BeltAngle.setValue(asin((Diameter.getValue() - OtherDiameter.getValue())/2/CenterDistance.getValue())); + BeltAngle.touch(); } + } else if ((prop == &Force) || (prop == &TensionForce) || (prop == &IsDriven)) { + double radius = Diameter.getValue() / 2.0; + if (radius < Precision::Confusion()) + return; + double force = Force.getValue() / (radius/1000); + if (fabs(force) < Precision::Confusion()) + return; + bool neg = (force < 0.0); + if (neg) + force *= -1.0; + + if ((IsDriven.getValue() && neg) || (!IsDriven.getValue() && !neg)) { + BeltForce1.setValue(force + TensionForce.getValue()); + BeltForce2.setValue(TensionForce.getValue()); + } else { + BeltForce2.setValue(force + TensionForce.getValue()); + BeltForce1.setValue(TensionForce.getValue()); + } + BeltForce1.touch(); } } diff --git a/src/Mod/Fem/App/FemConstraintPulley.h b/src/Mod/Fem/App/FemConstraintPulley.h index 5540d0ba6..611652570 100644 --- a/src/Mod/Fem/App/FemConstraintPulley.h +++ b/src/Mod/Fem/App/FemConstraintPulley.h @@ -28,12 +28,12 @@ #include #include -#include "FemConstraintBearing.h" +#include "FemConstraintGear.h" namespace Fem { -class AppFemExport ConstraintPulley : public Fem::ConstraintBearing +class AppFemExport ConstraintPulley : public Fem::ConstraintGear { PROPERTY_HEADER(Fem::ConstraintPulley); @@ -41,11 +41,18 @@ public: /// Constructor ConstraintPulley(void); - App::PropertyFloat Diameter; + /// Other pulley diameter App::PropertyFloat OtherDiameter; + /// Center distance between the pulleys App::PropertyFloat CenterDistance; + /// Driven pulley or driving pulley? + App::PropertyBool IsDriven; + /// Belt tension force + App::PropertyFloat TensionForce; // Read-only (calculated values). These trigger changes in the ViewProvider - App::PropertyFloat Angle; + App::PropertyFloat BeltAngle; + App::PropertyFloat BeltForce1; + App::PropertyFloat BeltForce2; /// recalculate the object virtual App::DocumentObjectExecReturn *execute(void); @@ -57,6 +64,7 @@ public: protected: virtual void onChanged(const App::Property* prop); + }; } //namespace Fem diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 162e3efaa..3c9c080bc 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -49,7 +49,7 @@ set(FemGui_UIC_SRCS TaskCreateNodeSet.ui TaskObjectName.ui TaskFemConstraint.ui - TaskFemConstraintCylindrical.ui + TaskFemConstraintBearing.ui TaskFemConstraintFixed.ui TaskFemConstraintForce.ui ) @@ -63,7 +63,7 @@ SET(FemGui_DLG_SRCS TaskFemConstraint.ui TaskFemConstraint.cpp TaskFemConstraint.h - TaskFemConstraintCylindrical.ui + TaskFemConstraintBearing.ui TaskFemConstraintBearing.cpp TaskFemConstraintBearing.h TaskFemConstraintFixed.ui diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index f5bdf54da..95618a625 100755 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -228,9 +228,11 @@ void CmdFemConstraintPulley::activated(int iMsg) openCommand("Make FEM constraint for pulley"); doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPulley\",\"%s\")",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Diameter = 100.0",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.OtherDiameter = 200.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Diameter = 300.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.OtherDiameter = 100.0",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.CenterDistance = 500.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Force = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.TensionForce = 100.0",FeatName.c_str()); updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); diff --git a/src/Mod/Fem/Gui/TaskFemConstraint.cpp b/src/Mod/Fem/Gui/TaskFemConstraint.cpp index 2a54ed956..1169971f0 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraint.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraint.cpp @@ -43,7 +43,6 @@ #include "TaskFemConstraint.h" #include #include -//#include #include #include #include @@ -65,6 +64,39 @@ TaskFemConstraint::TaskFemConstraint(ViewProviderFemConstraint *ConstraintView,Q : TaskBox(Gui::BitmapFactory().pixmap(pixmapname),tr("FEM constraint parameters"),true, parent),ConstraintView(ConstraintView) { selectionMode = selref; + + // Setup the dialog inside the Shaft Wizard dialog + if ((ConstraintView->wizardWidget != NULL) && (ConstraintView->wizardSubLayout != NULL)) { + // Hide the shaft wizard table widget to make more space + ConstraintView->wizardSubLayout->itemAt(0)->widget()->hide(); + QGridLayout* buttons = ConstraintView->wizardSubLayout->findChild(); + for (int b = 0; b < buttons->count(); b++) + buttons->itemAt(b)->widget()->hide(); + + // Show this dialog for the FEM constraint + ConstraintView->wizardWidget->addWidget(this); + + // Add buttons to finish editing the constraint without closing the shaft wizard dialog + okButton = new QPushButton(QObject::tr("Ok")); + cancelButton = new QPushButton(QObject::tr("Cancel")); + buttonBox = new QDialogButtonBox(); + buttonBox->addButton(okButton, QDialogButtonBox::AcceptRole); + buttonBox->addButton(cancelButton, QDialogButtonBox::RejectRole); + QObject::connect(okButton, SIGNAL(clicked()), this, SLOT(onButtonWizOk())); + QObject::connect(cancelButton, SIGNAL(clicked()), this, SLOT(onButtonWizCancel())); + ConstraintView->wizardWidget->addWidget(buttonBox); + } +} + +void TaskFemConstraint::keyPressEvent(QKeyEvent *ke) +{ + if ((ConstraintView->wizardWidget != NULL) && (ConstraintView->wizardSubLayout != NULL)) + // Prevent from closing this dialog AND the shaft wizard dialog + // TODO: This should trigger an update in the shaft wizard but its difficult to access a python dialog from here... + if (ke->key() == Qt::Key_Return) + return; + + TaskBox::keyPressEvent(ke); } const std::string TaskFemConstraint::getReferences(const std::vector& items) const @@ -95,10 +127,37 @@ void TaskFemConstraint::onButtonReference(const bool pressed) { selectionMode = selref; else selectionMode = selnone; - //ui->buttonReference->setChecked(pressed); Gui::Selection().clearSelection(); } +void TaskFemConstraint::onButtonWizOk() +{ + // Remove dialog elements + buttonBox->removeButton(okButton); + delete okButton; + buttonBox->removeButton(cancelButton); + delete cancelButton; + ConstraintView->wizardWidget->removeWidget(buttonBox); + delete buttonBox; + ConstraintView->wizardWidget->removeWidget(this); + + // Show the wizard shaft dialog again + ConstraintView->wizardSubLayout->itemAt(0)->widget()->show(); + QGridLayout* buttons = ConstraintView->wizardSubLayout->findChild(); + for (int b = 0; b < buttons->count(); b++) + buttons->itemAt(b)->widget()->show(); + + Gui::Application::Instance->activeDocument()->resetEdit(); // Reaches ViewProviderFemConstraint::unsetEdit() eventually +} + +void TaskFemConstraint::onButtonWizCancel() +{ + Fem::Constraint* pcConstraint = static_cast(ConstraintView->getObject()); + if (pcConstraint != NULL) + pcConstraint->getDocument()->remObject(pcConstraint->getNameInDocument()); + onButtonWizOk(); +} + const QString TaskFemConstraint::makeRefText(const App::DocumentObject* obj, const std::string& subName) const { return QString::fromUtf8((std::string(obj->getNameInDocument()) + ":" + subName).c_str()); diff --git a/src/Mod/Fem/Gui/TaskFemConstraint.h b/src/Mod/Fem/Gui/TaskFemConstraint.h index ada796573..72390e113 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraint.h +++ b/src/Mod/Fem/Gui/TaskFemConstraint.h @@ -29,15 +29,7 @@ #include #include "ViewProviderFemConstraint.h" -/* -namespace App { -class Property; -} -namespace Gui { -class ViewProvider; -} -*/ namespace FemGui { class TaskFemConstraint : public Gui::TaskView::TaskBox, public Gui::SelectionObserver @@ -54,10 +46,14 @@ public: protected Q_SLOTS: void onReferenceDeleted(const int row); void onButtonReference(const bool pressed = true); + // Shaft Wizard integration + void onButtonWizOk(); + void onButtonWizCancel(); protected: virtual void changeEvent(QEvent *e) { TaskBox::changeEvent(e); } const QString makeRefText(const App::DocumentObject* obj, const std::string& subName) const; + virtual void keyPressEvent(QKeyEvent * ke); private: virtual void onSelectionChanged(const Gui::SelectionChanges&) {} @@ -66,6 +62,12 @@ protected: QWidget* proxy; ViewProviderFemConstraint *ConstraintView; enum {seldir, selref, selloc, selnone} selectionMode; + +private: + // This seems to be the only way to access the widgets again in order to remove them from the dialog + QDialogButtonBox* buttonBox; + QPushButton* okButton; + QPushButton* cancelButton; }; /// simulation dialog for the TaskView diff --git a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp index cf5b4374f..cf98b3003 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp @@ -39,7 +39,7 @@ # include #endif -#include "ui_TaskFemConstraintCylindrical.h" +#include "ui_TaskFemConstraintBearing.h" #include "TaskFemConstraintBearing.h" #include #include @@ -61,12 +61,13 @@ using namespace Gui; /* TRANSLATOR FemGui::TaskFemConstraintBearing */ -TaskFemConstraintBearing::TaskFemConstraintBearing(ViewProviderFemConstraint *ConstraintView,QWidget *parent, const char *pixmapname) +TaskFemConstraintBearing::TaskFemConstraintBearing(ViewProviderFemConstraint *ConstraintView,QWidget *parent, + const char *pixmapname) : TaskFemConstraint(ConstraintView, parent, pixmapname) { // we need a separate container widget to add all controls to proxy = new QWidget(this); - ui = new Ui_TaskFemConstraintCylindrical(); + ui = new Ui_TaskFemConstraintBearing(); ui->setupUi(proxy); QMetaObject::connectSlotsByName(this); @@ -107,8 +108,8 @@ TaskFemConstraintBearing::TaskFemConstraintBearing(ViewProviderFemConstraint *Co bool axialfree = pcConstraint->AxialFree.getValue(); // Fill data into dialog elements - ui->spinDistance->setMinimum(INT_MIN); - ui->spinDistance->setMaximum(INT_MAX); + ui->spinDistance->setMinimum(-FLOAT_MAX); + ui->spinDistance->setMaximum(FLOAT_MAX); ui->spinDistance->setValue(d); ui->listReferences->clear(); for (int i = 0; i < Objects.size(); i++) @@ -118,13 +119,23 @@ TaskFemConstraintBearing::TaskFemConstraintBearing(ViewProviderFemConstraint *Co ui->lineLocation->setText(loc); ui->checkAxial->setChecked(axialfree); - // Adjust ui to constraint type + // Hide unwanted ui elements ui->labelDiameter->setVisible(false); ui->spinDiameter->setVisible(false); ui->labelOtherDiameter->setVisible(false); ui->spinOtherDiameter->setVisible(false); ui->labelCenterDistance->setVisible(false); ui->spinCenterDistance->setVisible(false); + ui->checkIsDriven->setVisible(false); + ui->labelForce->setVisible(false); + ui->spinForce->setVisible(false); + ui->labelTensionForce->setVisible(false); + ui->spinTensionForce->setVisible(false); + ui->labelForceAngle->setVisible(false); + ui->spinForceAngle->setVisible(false); + ui->buttonDirection->setVisible(false); + ui->lineDirection->setVisible(false); + ui->checkReversed->setVisible(false); ui->spinDistance->blockSignals(false); ui->listReferences->blockSignals(false); @@ -149,7 +160,6 @@ void TaskFemConstraintBearing::onSelectionChanged(const Gui::SelectionChanges& m if (selectionMode == selnone) return; - std::vector references(1,subName); Fem::ConstraintBearing* pcConstraint = static_cast(ConstraintView->getObject()); App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName); Part::Feature* feat = static_cast(obj); @@ -162,13 +172,13 @@ void TaskFemConstraintBearing::onSelectionChanged(const Gui::SelectionChanges& m if (Objects.size() > 0) { QMessageBox::warning(this, tr("Selection error"), tr("Please use only a single reference for bearing constraint")); return; - } - // Only cylindrical faces allowed + } if (subName.substr(0,4) != "Face") { QMessageBox::warning(this, tr("Selection error"), tr("Only faces can be picked")); return; } + // Only cylindrical faces allowed BRepAdaptor_Surface surface(TopoDS::Face(ref)); if (surface.GetType() != GeomAbs_Cylinder) { QMessageBox::warning(this, tr("Selection error"), tr("Only cylindrical faces can be picked")); @@ -200,6 +210,7 @@ void TaskFemConstraintBearing::onSelectionChanged(const Gui::SelectionChanges& m QMessageBox::warning(this, tr("Selection error"), tr("Only faces and edges can be picked")); return; } + std::vector references(1,subName); pcConstraint->Location.setValue(obj, references); ui->lineLocation->setText(makeRefText(obj, subName)); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintBearing.h b/src/Mod/Fem/Gui/TaskFemConstraintBearing.h index 671d114b4..e6a566f48 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintBearing.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintBearing.h @@ -31,7 +31,7 @@ #include "TaskFemConstraint.h" #include "ViewProviderFemConstraintBearing.h" -class Ui_TaskFemConstraintCylindrical; +class Ui_TaskFemConstraintBearing; namespace App { class Property; @@ -66,12 +66,11 @@ private Q_SLOTS: protected: virtual void changeEvent(QEvent *e); - -private: virtual void onSelectionChanged(const Gui::SelectionChanges& msg); protected: - Ui_TaskFemConstraintCylindrical* ui; + Ui_TaskFemConstraintBearing* ui; + }; /// simulation dialog for the TaskView diff --git a/src/Mod/Fem/Gui/TaskFemConstraintCylindrical.ui b/src/Mod/Fem/Gui/TaskFemConstraintBearing.ui similarity index 54% rename from src/Mod/Fem/Gui/TaskFemConstraintCylindrical.ui rename to src/Mod/Fem/Gui/TaskFemConstraintBearing.ui index c0ee3cb29..e83859004 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintCylindrical.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintBearing.ui @@ -1,13 +1,13 @@ - TaskFemConstraintCylindrical - + TaskFemConstraintBearing + 0 0 257 - 338 + 534 @@ -25,9 +25,12 @@ - + + + true + Gear diameter @@ -49,11 +52,14 @@ - + + + true + - Other diameter + Other pulley dia @@ -66,14 +72,14 @@ 99999.000000000000000 - 200.000000000000000 + 100.000000000000000 - + @@ -90,12 +96,122 @@ 99999.000000000000000 - 500.000000000000000 + 1000.000000000000000 + + + + + + Force + + + + + + + -99999.000000000000000 + + + 99999.000000000000000 + + + 1000.000000000000000 + + + + + + + + + + + Belt tension force + + + + + + + -99999.000000000000000 + + + 99999.000000000000000 + + + 1000.000000000000000 + + + + + + + + + Driven pulley + + + + + + + + + Force location [deg] + + + + + + + 1 + + + 0.000000000000000 + + + 360.000000000000000 + + + 0.000000000000000 + + + + + + + + + + + Force Direction + + + + + + + + + + + + Reversed direction + + + + + + + Axial free + + + @@ -147,13 +263,6 @@ - - - - Axial free - - - diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp index 4d0d5c3ff..8a51a99e4 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp @@ -108,7 +108,7 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce *C // Fill data into dialog elements ui->spinForce->setMinimum(0); - ui->spinForce->setMaximum(INT_MAX); + ui->spinForce->setMaximum(FLOAT_MAX); ui->spinForce->setValue(f); ui->listReferences->clear(); for (int i = 0; i < Objects.size(); i++) diff --git a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp index 0ee3868e1..b7acec743 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp @@ -29,7 +29,7 @@ # include # include # include -# include +# include */ # include # include # include @@ -38,10 +38,9 @@ # include # include # include -*/ #endif -#include "ui_TaskFemConstraintCylindrical.h" +#include "ui_TaskFemConstraintBearing.h" #include "TaskFemConstraintGear.h" #include #include @@ -63,40 +62,187 @@ using namespace Gui; /* TRANSLATOR FemGui::TaskFemConstraintGear */ -TaskFemConstraintGear::TaskFemConstraintGear(ViewProviderFemConstraintGear *ConstraintView,QWidget *parent) - : TaskFemConstraintBearing(ConstraintView, parent, "Fem_ConstraintGear") +TaskFemConstraintGear::TaskFemConstraintGear(ViewProviderFemConstraint *ConstraintView,QWidget *parent, const char *pixmapname) + : TaskFemConstraintBearing(ConstraintView, parent, pixmapname) { - // we need a separate container widget to add all controls to connect(ui->spinDiameter, SIGNAL(valueChanged(double)), this, SLOT(onDiameterChanged(double))); + connect(ui->spinForce, SIGNAL(valueChanged(double)), + this, SLOT(onForceChanged(double))); + connect(ui->spinForceAngle, SIGNAL(valueChanged(double)), + this, SLOT(onForceAngleChanged(double))); + connect(ui->buttonDirection, SIGNAL(pressed()), + this, SLOT(onButtonDirection())); + connect(ui->checkReversed, SIGNAL(toggled(bool)), + this, SLOT(onCheckReversed(bool))); // Temporarily prevent unnecessary feature recomputes ui->spinDiameter->blockSignals(true); + ui->spinForce->blockSignals(true); + ui->spinForceAngle->blockSignals(true); + ui->checkReversed->blockSignals(true); // Get the feature data - Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); + Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); double dia = pcConstraint->Diameter.getValue(); + double force = pcConstraint->Force.getValue(); + double angle = pcConstraint->ForceAngle.getValue(); + std::vector dirStrings = pcConstraint->Direction.getSubValues(); + QString dir; + if (!dirStrings.empty()) + dir = makeRefText(pcConstraint->Direction.getValue(), dirStrings.front()); + bool reversed = pcConstraint->Reversed.getValue(); // Fill data into dialog elements ui->spinDiameter->setMinimum(0); - ui->spinDiameter->setMaximum(INT_MAX); + ui->spinDiameter->setMaximum(FLOAT_MAX); ui->spinDiameter->setValue(dia); + ui->spinForce->setMinimum(0); + ui->spinForce->setMaximum(FLOAT_MAX); + ui->spinForce->setValue(force); + ui->spinForceAngle->setMinimum(0); + ui->spinForceAngle->setMaximum(360); + ui->spinForceAngle->setValue(angle); + ui->lineDirection->setText(dir); + ui->checkReversed->setChecked(reversed); - // Adjust ui to specific constraint type - ui->checkAxial->setVisible(false); - ui->spinDiameter->setVisible(true); + // Adjust ui ui->labelDiameter->setVisible(true); + ui->spinDiameter->setVisible(true); + ui->labelForce->setVisible(true); + ui->spinForce->setVisible(true); + ui->labelForceAngle->setVisible(true); + ui->spinForceAngle->setVisible(true); + ui->buttonDirection->setVisible(true); + ui->lineDirection->setVisible(true); + ui->checkReversed->setVisible(true); + ui->checkAxial->setVisible(false); ui->spinDiameter->blockSignals(false); - - onButtonReference(true); + ui->spinForce->blockSignals(false); + ui->spinForceAngle->blockSignals(false); + ui->checkReversed->blockSignals(false); } + +void TaskFemConstraintGear::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + TaskFemConstraintBearing::onSelectionChanged(msg); + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + // Don't allow selection in other document + if (strcmp(msg.pDocName, ConstraintView->getObject()->getDocument()->getName()) != 0) + return; + + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + std::string subName(msg.pSubName); + + if (selectionMode == selnone) + return; + + std::vector references(1,subName); + Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); + App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName); + Part::Feature* feat = static_cast(obj); + TopoDS_Shape ref = feat->Shape.getShape().getSubShape(subName.c_str()); + + if (selectionMode == seldir) { + if (subName.substr(0,4) == "Face") { + BRepAdaptor_Surface surface(TopoDS::Face(ref)); + if (surface.GetType() != GeomAbs_Plane) { + QMessageBox::warning(this, tr("Selection error"), tr("Only planar faces can be picked")); + return; + } + } else if (subName.substr(0,4) == "Edge") { + BRepAdaptor_Curve line(TopoDS::Edge(ref)); + if (line.GetType() != GeomAbs_Line) { + QMessageBox::warning(this, tr("Selection error"), tr("Only linear edges can be picked")); + return; + } + } else { + QMessageBox::warning(this, tr("Selection error"), tr("Only faces and edges can be picked")); + return; + } + pcConstraint->Direction.setValue(obj, references); + ui->lineDirection->setText(makeRefText(obj, subName)); + + // Turn off direction selection mode + onButtonDirection(false); + } + + Gui::Selection().clearSelection(); + } +} + void TaskFemConstraintGear::onDiameterChanged(double l) { Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->Diameter.setValue((float)l); } +void TaskFemConstraintGear::onForceChanged(double f) +{ + Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); + pcConstraint->Force.setValue((float)f); +} + +void TaskFemConstraintGear::onForceAngleChanged(double a) +{ + Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); + pcConstraint->ForceAngle.setValue((float)a); +} + +void TaskFemConstraintGear::onButtonDirection(const bool pressed) { + if (pressed) { + selectionMode = seldir; + } else { + selectionMode = selnone; + } + ui->buttonDirection->setChecked(pressed); + Gui::Selection().clearSelection(); +} + +void TaskFemConstraintGear::onCheckReversed(const bool pressed) +{ + Fem::ConstraintGear* pcConstraint = static_cast(ConstraintView->getObject()); + pcConstraint->Reversed.setValue(pressed); +} + +double TaskFemConstraintGear::getForce(void) const +{ + return ui->spinForce->value(); +} + +double TaskFemConstraintGear::getForceAngle(void) const +{ + return ui->spinForceAngle->value(); +} + +const std::string TaskFemConstraintGear::getDirectionName(void) const +{ + std::string dir = ui->lineDirection->text().toStdString(); + if (dir.empty()) + return ""; + + int pos = dir.find_last_of(":"); + return dir.substr(0, pos).c_str(); +} + +const std::string TaskFemConstraintGear::getDirectionObject(void) const +{ + std::string dir = ui->lineDirection->text().toStdString(); + if (dir.empty()) + return ""; + + int pos = dir.find_last_of(":"); + return dir.substr(pos+1).c_str(); +} + +bool TaskFemConstraintGear::getReverse() const +{ + return ui->checkReversed->isChecked(); +} + double TaskFemConstraintGear::getDiameter(void) const { return ui->spinDiameter->value(); @@ -107,10 +253,14 @@ void TaskFemConstraintGear::changeEvent(QEvent *e) TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { ui->spinDiameter->blockSignals(true); - ui->spinDistance->blockSignals(true); + ui->spinForce->blockSignals(true); + ui->spinForceAngle->blockSignals(true); + ui->checkReversed->blockSignals(true); ui->retranslateUi(proxy); ui->spinDiameter->blockSignals(false); - ui->spinDistance->blockSignals(false); + ui->spinForce->blockSignals(false); + ui->spinForceAngle->blockSignals(true); + ui->checkReversed->blockSignals(false); } } @@ -123,7 +273,7 @@ TaskDlgFemConstraintGear::TaskDlgFemConstraintGear(ViewProviderFemConstraintGear { this->ConstraintView = ConstraintView; assert(ConstraintView); - this->parameter = new TaskFemConstraintGear(ConstraintView);; + this->parameter = new TaskFemConstraintGear(ConstraintView, 0, "Fem_ConstraintGear"); Content.push_back(parameter); } @@ -137,8 +287,23 @@ bool TaskDlgFemConstraintGear::accept() try { //Gui::Command::openCommand("FEM force constraint changed"); + std::string dirname = parameterGear->getDirectionName().data(); + std::string dirobj = parameterGear->getDirectionObject().data(); + + if (!dirname.empty()) { + QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); + buf = buf.arg(QString::fromStdString(dirname)); + buf = buf.arg(QString::fromStdString(dirobj)); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Direction = %s", name.c_str(), buf.toStdString().c_str()); + } else { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Direction = None", name.c_str()); + } + + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %s", name.c_str(), parameterGear->getReverse() ? "True" : "False"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Diameter = %f",name.c_str(), parameterGear->getDiameter()); - } + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Force = %f",name.c_str(), parameterGear->getForce()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ForceAngle = %f",name.c_str(), parameterGear->getForceAngle()); + } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); return false; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintGear.h b/src/Mod/Fem/Gui/TaskFemConstraintGear.h index bfc8eee09..048d9d696 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintGear.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintGear.h @@ -31,16 +31,6 @@ #include "TaskFemConstraintBearing.h" #include "ViewProviderFemConstraintGear.h" -class Ui_TaskFemConstraintGear; - -namespace App { -class Property; -} - -namespace Gui { -class ViewProvider; -} - namespace FemGui { class TaskFemConstraintGear : public TaskFemConstraintBearing @@ -48,16 +38,26 @@ class TaskFemConstraintGear : public TaskFemConstraintBearing Q_OBJECT public: - TaskFemConstraintGear(ViewProviderFemConstraintGear *ConstraintView,QWidget *parent = 0); + TaskFemConstraintGear(ViewProviderFemConstraint *ConstraintView,QWidget *parent = 0, + const char* pixmapname = "Fem_ConstraintGear"); double getDiameter(void) const; + double getForce(void) const; + double getForceAngle(void) const; + const std::string getDirectionName(void) const; + const std::string getDirectionObject(void) const; + bool getReverse(void) const; private Q_SLOTS: void onDiameterChanged(double dia); + void onForceChanged(double force); + void onForceAngleChanged(double angle); + void onButtonDirection(const bool pressed = true); + void onCheckReversed(bool); protected: virtual void changeEvent(QEvent *e); - + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); }; /// simulation dialog for the TaskView @@ -66,6 +66,7 @@ class TaskDlgFemConstraintGear : public TaskDlgFemConstraintBearing Q_OBJECT public: + TaskDlgFemConstraintGear() {} TaskDlgFemConstraintGear(ViewProviderFemConstraintGear *ConstraintView); /// is called by the framework if the dialog is accepted (Ok) diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp index f239a37ec..e6d7c55ce 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp @@ -26,7 +26,7 @@ #ifndef _PreComp_ #endif -#include "ui_TaskFemConstraintCylindrical.h" +#include "ui_TaskFemConstraintBearing.h" #include "TaskFemConstraintPulley.h" #include #include @@ -49,59 +49,61 @@ using namespace Gui; /* TRANSLATOR FemGui::TaskFemConstraintPulley */ TaskFemConstraintPulley::TaskFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView,QWidget *parent) - : TaskFemConstraintBearing(ConstraintView, parent, "Fem_ConstraintPulley") + : TaskFemConstraintGear(ConstraintView, parent, "Fem_ConstraintPulley") { - // we need a separate container widget to add all controls to - connect(ui->spinDiameter, SIGNAL(valueChanged(double)), - this, SLOT(onDiameterChanged(double))); connect(ui->spinOtherDiameter, SIGNAL(valueChanged(double)), this, SLOT(onOtherDiameterChanged(double))); connect(ui->spinCenterDistance, SIGNAL(valueChanged(double)), this, SLOT(onCenterDistanceChanged(double))); + connect(ui->checkIsDriven, SIGNAL(toggled(bool)), + this, SLOT(onCheckIsDriven(bool))); + connect(ui->spinTensionForce, SIGNAL(valueChanged(double)), + this, SLOT(onTensionForceChanged(double))); // Temporarily prevent unnecessary feature recomputes - ui->spinDiameter->blockSignals(true); ui->spinOtherDiameter->blockSignals(true); ui->spinCenterDistance->blockSignals(true); + ui->checkIsDriven->blockSignals(true); + ui->spinTensionForce->blockSignals(true); // Get the feature data Fem::ConstraintPulley* pcConstraint = static_cast(ConstraintView->getObject()); - double dia = pcConstraint->Diameter.getValue(); double otherdia = pcConstraint->OtherDiameter.getValue(); double centerdist = pcConstraint->CenterDistance.getValue(); + bool isdriven = pcConstraint->IsDriven.getValue(); + double tensionforce = pcConstraint->TensionForce.getValue(); // Fill data into dialog elements - ui->spinDiameter->setMinimum(0); - ui->spinDiameter->setMaximum(INT_MAX); - ui->spinDiameter->setValue(dia); ui->spinOtherDiameter->setMinimum(0); - ui->spinOtherDiameter->setMaximum(INT_MAX); + ui->spinOtherDiameter->setMaximum(FLOAT_MAX); ui->spinOtherDiameter->setValue(otherdia); - ui->spinCenterDistance->setMinimum(INT_MIN); - ui->spinCenterDistance->setMaximum(INT_MAX); + ui->spinCenterDistance->setMinimum(0); + ui->spinCenterDistance->setMaximum(FLOAT_MAX); ui->spinCenterDistance->setValue(centerdist); + ui->checkIsDriven->setChecked(isdriven); + ui->spinForce->setMinimum(-FLOAT_MAX); + ui->spinTensionForce->setMinimum(0); + ui->spinTensionForce->setMaximum(FLOAT_MAX); + ui->spinTensionForce->setValue(tensionforce); - // Adjust ui to specific constraint type - ui->checkAxial->setVisible(false); - ui->spinDiameter->setVisible(true); - ui->labelDiameter->setVisible(true); + // Adjust ui + ui->buttonDirection->setVisible(false); + ui->lineDirection->setVisible(false); + ui->checkReversed->setVisible(false); ui->labelDiameter->setText(tr("Pulley diameter")); + ui->labelForce->setText(tr("Torque [Nm]")); ui->labelOtherDiameter->setVisible(true); ui->spinOtherDiameter->setVisible(true); ui->labelCenterDistance->setVisible(true); ui->spinCenterDistance->setVisible(true); + ui->checkIsDriven->setVisible(true); + ui->labelTensionForce->setVisible(true); + ui->spinTensionForce->setVisible(true); - ui->spinDiameter->blockSignals(false); ui->spinOtherDiameter->blockSignals(false); ui->spinCenterDistance->blockSignals(false); - - onButtonReference(true); -} - -void TaskFemConstraintPulley::onDiameterChanged(double l) -{ - Fem::ConstraintPulley* pcConstraint = static_cast(ConstraintView->getObject()); - pcConstraint->Diameter.setValue((float)l); + ui->checkIsDriven->blockSignals(false); + ui->spinTensionForce->blockSignals(false); } void TaskFemConstraintPulley::onOtherDiameterChanged(double l) @@ -116,9 +118,31 @@ void TaskFemConstraintPulley::onCenterDistanceChanged(double l) pcConstraint->CenterDistance.setValue((float)l); } -double TaskFemConstraintPulley::getDiameter(void) const +void TaskFemConstraintPulley::onTensionForceChanged(double force) { - return ui->spinDiameter->value(); + Fem::ConstraintPulley* pcConstraint = static_cast(ConstraintView->getObject()); + pcConstraint->TensionForce.setValue((float)force); +} + +void TaskFemConstraintPulley::onCheckIsDriven(const bool pressed) +{ + Fem::ConstraintPulley* pcConstraint = static_cast(ConstraintView->getObject()); + pcConstraint->IsDriven.setValue(pressed); +} + +double TaskFemConstraintPulley::getTorque(void) const +{ + return ui->spinForce->value(); +} + +double TaskFemConstraintPulley::getTensionForce(void) const +{ + return ui->spinTensionForce->value(); +} + +bool TaskFemConstraintPulley::getIsDriven() const +{ + return ui->checkIsDriven->isChecked(); } double TaskFemConstraintPulley::getOtherDiameter(void) const @@ -135,15 +159,15 @@ void TaskFemConstraintPulley::changeEvent(QEvent *e) { TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { - ui->spinDiameter->blockSignals(true); - ui->spinDistance->blockSignals(true); ui->spinOtherDiameter->blockSignals(true); ui->spinCenterDistance->blockSignals(true); + ui->checkIsDriven->blockSignals(true); + ui->spinTensionForce->blockSignals(true); ui->retranslateUi(proxy); - ui->spinDiameter->blockSignals(false); - ui->spinDistance->blockSignals(false); ui->spinOtherDiameter->blockSignals(false); ui->spinCenterDistance->blockSignals(false); + ui->checkIsDriven->blockSignals(false); + ui->spinTensionForce->blockSignals(false); } } @@ -169,17 +193,18 @@ bool TaskDlgFemConstraintPulley::accept() const TaskFemConstraintPulley* parameterPulley = static_cast(parameter); try { - //Gui::Command::openCommand("FEM force constraint changed"); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Diameter = %f",name.c_str(), parameterPulley->getDiameter()); + //Gui::Command::openCommand("FEM pulley constraint changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.OtherDiameter = %f",name.c_str(), parameterPulley->getOtherDiameter()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.CenterDistance = %f",name.c_str(), parameterPulley->getCenterDistance()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.IsDriven = %s",name.c_str(), parameterPulley->getIsDriven() ? "True" : "False"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.TensionForce = %f",name.c_str(), parameterPulley->getTensionForce()); } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); return false; } - return TaskDlgFemConstraintBearing::accept(); + return TaskDlgFemConstraintGear::accept(); } #include "moc_TaskFemConstraintPulley.cpp" diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPulley.h b/src/Mod/Fem/Gui/TaskFemConstraintPulley.h index 11196dafe..f2b92c5b9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPulley.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintPulley.h @@ -28,44 +28,36 @@ #include #include -#include "TaskFemConstraintBearing.h" +#include "TaskFemConstraintGear.h" #include "ViewProviderFemConstraintPulley.h" -class Ui_TaskFemConstraintPulley; - -namespace App { -class Property; -} - -namespace Gui { -class ViewProvider; -} - namespace FemGui { -class TaskFemConstraintPulley : public TaskFemConstraintBearing +class TaskFemConstraintPulley : public TaskFemConstraintGear { Q_OBJECT public: TaskFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView,QWidget *parent = 0); - double getDiameter(void) const; double getOtherDiameter(void) const; double getCenterDistance(void) const; + double getTensionForce(void) const; + double getTorque(void) const; + bool getIsDriven(void) const; private Q_SLOTS: - void onDiameterChanged(double dia); void onOtherDiameterChanged(double dia); void onCenterDistanceChanged(double dia); + void onTensionForceChanged(double force); + void onCheckIsDriven(bool); protected: virtual void changeEvent(QEvent *e); - }; /// simulation dialog for the TaskView -class TaskDlgFemConstraintPulley : public TaskDlgFemConstraintBearing +class TaskDlgFemConstraintPulley : public TaskDlgFemConstraintGear { Q_OBJECT diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp index 778b59b3a..0668c05f8 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp @@ -43,6 +43,10 @@ #include "TaskFemConstraint.h" #include "Gui/Control.h" +#include "Gui/MainWindow.h" +#include "Gui/Command.h" +#include "Gui/Application.h" +#include "Gui/Document.h" #include @@ -79,9 +83,11 @@ ViewProviderFemConstraint::ViewProviderFemConstraint() TextColor.touch(); FontSize.touch(); - FaceColor.touch(); + FaceColor.touch(); - oldDlg = NULL; + wizardWidget = NULL; + wizardSubLayout = NULL; + constraintDialog = NULL; } ViewProviderFemConstraint::~ViewProviderFemConstraint() @@ -95,7 +101,6 @@ ViewProviderFemConstraint::~ViewProviderFemConstraint() void ViewProviderFemConstraint::attach(App::DocumentObject* pcObject) { - Base::Console().Error("VP FemConstraint attach %s\n", pcObject->getNameInDocument()); ViewProviderDocumentObject::attach(pcObject); SoPickStyle* ps = new SoPickStyle(); @@ -142,11 +147,6 @@ void ViewProviderFemConstraint::setupContextMenu(QMenu* menu, QObject* receiver, void ViewProviderFemConstraint::onChanged(const App::Property* prop) { - if (this->getObject() != NULL) - Base::Console().Error("%s: VP onChanged: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VP onChanged: %s\n", prop->getName()); - if (prop == &Mirror || prop == &DistFactor) { updateData(prop); } @@ -166,19 +166,30 @@ void ViewProviderFemConstraint::onChanged(const App::Property* prop) } } +bool ViewProviderFemConstraint::setEdit(int ModNum) +{ + return Gui::ViewProviderGeometryObject::setEdit(ModNum); +} + void ViewProviderFemConstraint::unsetEdit(int ModNum) { - if (ModNum == ViewProvider::Default) { - // when pressing ESC make sure to close the dialog - Gui::Control().closeDialog(); - } - else { - ViewProviderDocumentObject::unsetEdit(ModNum); - } + if ((wizardWidget != NULL) && (wizardSubLayout != NULL) && (constraintDialog != NULL)) { + wizardWidget = NULL; + wizardSubLayout = NULL; + delete constraintDialog; + constraintDialog = NULL; - if (oldDlg != NULL) { - Gui::Control().showDialog(oldDlg); - oldDlg = NULL; + // Notify the Shaft Wizard that we have finished editing + // See WizardShaft.py on why we do it this way + Gui::Command::runCommand(Gui::Command::Doc, "Gui.runCommand('PartDesign_WizardShaftCallBack')"); + } else { + if (ModNum == ViewProvider::Default) { + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + ViewProviderDocumentObject::unsetEdit(ModNum); + } } } /* @@ -388,3 +399,41 @@ void ViewProviderFemConstraint::updateFixed(const SoNode* node, const int idx, c updateCube(sep, idx+CONE_CHILDREN+PLACEMENT_CHILDREN, width, width, width/4); } +QObject* ViewProviderFemConstraint::findChildByName(const QObject* parent, const QString& name) +{ + for (QObjectList::const_iterator o = parent->children().begin(); o != parent->children().end(); o++) { + if ((*o)->objectName() == name) + return *o; + if (!(*o)->children().empty()) { + QObject* result = findChildByName(*o, name); + if (result != NULL) + return result; + } + } + + return NULL; +} + +void ViewProviderFemConstraint::checkForWizard() +{ + wizardWidget= NULL; + wizardSubLayout = NULL; + Gui::MainWindow* mw = Gui::getMainWindow(); + if (mw == NULL) return; + QDockWidget* dw = mw->findChild(QObject::tr("Combo View")); + if (dw == NULL) return; + QWidget* cw = dw->findChild(QObject::tr("Combo View")); + if (cw == NULL) return; + QTabWidget* tw = cw->findChild(QObject::tr("combiTab")); + if (tw == NULL) return; + QStackedWidget* sw = tw->findChild(QObject::tr("qt_tabwidget_stackedwidget")); + if (sw == NULL) return; + QScrollArea* sa = sw->findChild(); + if (sa== NULL) return; + QWidget* wd = sa->widget(); // This is the reason why we cannot use findChildByName() right away!!! + if (wd == NULL) return; + QObject* wiz = findChildByName(wd, QObject::tr("ShaftWizard")); // FIXME: Actually, we don't want to translate this... + if (wiz != NULL) + wizardWidget = static_cast(wiz); + wizardSubLayout = wiz->findChild(QObject::tr("ShaftWizardLayout")); +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraint.h b/src/Mod/Fem/Gui/ViewProviderFemConstraint.h index 015f8d38c..82e1803d5 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraint.h +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraint.h @@ -28,6 +28,8 @@ #include "Gui/ViewProviderGeometryObject.h" #include +#include +#include class SoFontStyle; class SoText2; @@ -46,6 +48,8 @@ class View3DInventorViewer; namespace FemGui { +class TaskFemConstraint; + class FemGuiExport ViewProviderFemConstraint : public Gui::ViewProviderGeometryObject { PROPERTY_HEADER(FemGui::ViewProviderFemConstraint); @@ -73,7 +77,7 @@ public: protected: void onChanged(const App::Property* prop); - virtual bool setEdit(int ModNum) { return Gui::ViewProviderGeometryObject::setEdit(ModNum); } + virtual bool setEdit(int ModNum); virtual void unsetEdit(int ModNum); static void createPlacement(SoSeparator* sep, const SbVec3f &base, const SbRotation &r); @@ -103,7 +107,15 @@ private: protected: SoSeparator * pShapeSep; - Gui::TaskView::TaskDialog *oldDlg; + // Shaft design wizard integration +protected: + friend class TaskFemConstraint; + QVBoxLayout* wizardWidget; + QVBoxLayout* wizardSubLayout; + TaskFemConstraint* constraintDialog; + + void checkForWizard(); + static QObject* findChildByName(const QObject* parent, const QString& name); }; } //namespace FemGui diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp index f19849181..9c29278a4 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp @@ -34,6 +34,7 @@ #include #include "TaskFemConstraintBearing.h" #include "Gui/Control.h" +#include "Gui/MainWindow.h" #include @@ -45,6 +46,7 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintBearing, FemGui::ViewProviderFe ViewProviderFemConstraintBearing::ViewProviderFemConstraintBearing() { sPixmap = "view-femconstraintbearing"; + wizardWidget = NULL; } ViewProviderFemConstraintBearing::~ViewProviderFemConstraintBearing() @@ -53,6 +55,9 @@ ViewProviderFemConstraintBearing::~ViewProviderFemConstraintBearing() bool ViewProviderFemConstraintBearing::setEdit(int ModNum) { + Base::Console().Error("ViewProviderFemConstraintBearing::setEdit()\n"); + Base::Console().Error("Active dialog: %s\n", Gui::Control().activeDialog()->objectName().toStdString().c_str()); + if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing @@ -62,21 +67,28 @@ bool ViewProviderFemConstraintBearing::setEdit(int ModNum) if (constrDlg && constrDlg->getConstraintView() != this) constrDlg = 0; // another constraint left open its task panel if (dlg && !constrDlg) { - // Allow stacking of dialogs, for ShaftWizard application - // Note: If other features start to allow stacking, we need to check for oldDlg != NULL - oldDlg = dlg; - /* - QMessageBox msgBox; - msgBox.setText(QObject::tr("A dialog is already open in the task panel")); - msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) - Gui::Control().closeDialog(); - else + // This case will occur in the ShaftWizard application + checkForWizard(); + if ((wizardWidget == NULL) || (wizardSubLayout == NULL)) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } else if (constraintDialog != NULL) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog return false; - */ + } else { + constraintDialog = new TaskFemConstraintBearing(this); + return true; + } } // clear the selection (convenience) @@ -97,11 +109,6 @@ bool ViewProviderFemConstraintBearing::setEdit(int ModNum) void ViewProviderFemConstraintBearing::updateData(const App::Property* prop) { - if (this->getObject() != NULL) - Base::Console().Error("%s: VP updateData: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VP updateData: %s\n", prop->getName()); - // Gets called whenever a property of the attached object changes Fem::ConstraintBearing* pcConstraint = static_cast(this->getObject()); diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h b/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h index a7ceff6df..603a04313 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h @@ -28,6 +28,7 @@ #include "ViewProviderFemConstraint.h" #include +#include class SoFontStyle; class SoText2; diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp index 88fdf84cb..ca08541d6 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp @@ -57,6 +57,7 @@ ViewProviderFemConstraintFixed::~ViewProviderFemConstraintFixed() bool ViewProviderFemConstraintFixed::setEdit(int ModNum) { + Base::Console().Error("ViewProviderFemConstraintFixed::setEdit()\n"); if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing @@ -66,21 +67,28 @@ bool ViewProviderFemConstraintFixed::setEdit(int ModNum) if (constrDlg && constrDlg->getConstraintView() != this) constrDlg = 0; // another constraint left open its task panel if (dlg && !constrDlg) { - // Allow stacking of dialogs, for ShaftWizard application - // Note: If other features start to allow stacking, we need to check for oldDlg != NULL - oldDlg = dlg; - /* - QMessageBox msgBox; - msgBox.setText(QObject::tr("A dialog is already open in the task panel")); - msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) - Gui::Control().closeDialog(); - else + // This case will occur in the ShaftWizard application + checkForWizard(); + if ((wizardWidget == NULL) || (wizardSubLayout == NULL)) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } else if (constraintDialog != NULL) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog return false; - */ + } else { + constraintDialog = new TaskFemConstraintFixed(this); + return true; + } } // clear the selection (convenience) @@ -93,8 +101,7 @@ bool ViewProviderFemConstraintFixed::setEdit(int ModNum) Gui::Control().showDialog(new TaskDlgFemConstraintFixed(this)); return true; - } - else { + } else { return ViewProviderDocumentObject::setEdit(ModNum); } } @@ -105,11 +112,6 @@ bool ViewProviderFemConstraintFixed::setEdit(int ModNum) void ViewProviderFemConstraintFixed::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes - if (this->getObject() != NULL) - Base::Console().Error("%s: VPF updateData: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VPF updateData: %s\n", prop->getName()); - Fem::ConstraintFixed* pcConstraint = static_cast(this->getObject()); /* diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp index 8003f45e8..fd82e3381 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp @@ -46,7 +46,7 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintForce, FemGui::ViewProviderFemC ViewProviderFemConstraintForce::ViewProviderFemConstraintForce() { - sPixmap = "view-femconstraintforce"; + sPixmap = "view-femconstraintforce"; } ViewProviderFemConstraintForce::~ViewProviderFemConstraintForce() @@ -55,6 +55,8 @@ ViewProviderFemConstraintForce::~ViewProviderFemConstraintForce() bool ViewProviderFemConstraintForce::setEdit(int ModNum) { + Base::Console().Error("ViewProviderFemConstraintForce::setEdit(%u)\n", ModNum); + if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing @@ -64,21 +66,28 @@ bool ViewProviderFemConstraintForce::setEdit(int ModNum) if (constrDlg && constrDlg->getConstraintView() != this) constrDlg = 0; // another constraint left open its task panel if (dlg && !constrDlg) { - // Allow stacking of dialogs, for ShaftWizard application - // Note: If other features start to allow stacking, we need to check for oldDlg != NULL - oldDlg = dlg; - /* - QMessageBox msgBox; - msgBox.setText(QObject::tr("A dialog is already open in the task panel")); - msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) - Gui::Control().closeDialog(); - else + // This case will occur in the ShaftWizard application + checkForWizard(); + if ((wizardWidget == NULL) || (wizardSubLayout == NULL)) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } else if (constraintDialog != NULL) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog return false; - */ + } else { + constraintDialog = new TaskFemConstraintForce(this); + return true; + } } // clear the selection (convenience) @@ -103,11 +112,6 @@ bool ViewProviderFemConstraintForce::setEdit(int ModNum) void ViewProviderFemConstraintForce::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes - if (this->getObject() != NULL) - Base::Console().Error("%s: VPF updateData: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VPF updateData: %s\n", prop->getName()); - Fem::ConstraintForce* pcConstraint = static_cast(this->getObject()); /* diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp index e30aecb78..c8b441755 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp @@ -27,6 +27,7 @@ # include # include # include +# include # include #endif @@ -53,6 +54,7 @@ ViewProviderFemConstraintGear::~ViewProviderFemConstraintGear() bool ViewProviderFemConstraintGear::setEdit(int ModNum) { + Base::Console().Error("ViewProviderFemConstraintGear::setEdit()\n"); if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing @@ -62,21 +64,28 @@ bool ViewProviderFemConstraintGear::setEdit(int ModNum) if (constrDlg && constrDlg->getConstraintView() != this) constrDlg = 0; // another constraint left open its task panel if (dlg && !constrDlg) { - // Allow stacking of dialogs, for ShaftWizard application - // Note: If other features start to allow stacking, we need to check for oldDlg != NULL - oldDlg = dlg; - /* - QMessageBox msgBox; - msgBox.setText(QObject::tr("A dialog is already open in the task panel")); - msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) - Gui::Control().closeDialog(); - else + // This case will occur in the ShaftWizard application + checkForWizard(); + if ((wizardWidget == NULL) || (wizardSubLayout == NULL)) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } else if (constraintDialog != NULL) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog return false; - */ + } else { + constraintDialog = new TaskFemConstraintGear(this); + return true; + } } // clear the selection (convenience) @@ -97,57 +106,84 @@ bool ViewProviderFemConstraintGear::setEdit(int ModNum) void ViewProviderFemConstraintGear::updateData(const App::Property* prop) { - // Gets called whenever a property of the attached object changes Fem::ConstraintGear* pcConstraint = static_cast(this->getObject()); - if (this->getObject() != NULL) - Base::Console().Error("%s: VP updateData: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VP updateData: %s\n", prop->getName()); + // Gets called whenever a property of the attached object changes if (strcmp(prop->getName(),"BasePoint") == 0) { if (pcConstraint->Height.getValue() > Precision::Confusion()) { // Remove and recreate the symbol pShapeSep->removeAllChildren(); - // This should always point outside of the cylinder Base::Vector3f base = pcConstraint->BasePoint.getValue(); Base::Vector3f axis = pcConstraint->Axis.getValue(); + Base::Vector3f direction = pcConstraint->DirectionVector.getValue(); + if (direction.Length() < Precision::Confusion()) + direction = Base::Vector3f(0,1,0); float radius = pcConstraint->Radius.getValue(); float dia = pcConstraint->Diameter.getValue(); if (dia < 2 * radius) dia = 2 * radius; + float angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; SbVec3f b(base.x, base.y, base.z); - SbVec3f dir(axis.x, axis.y, axis.z); - SbRotation rot(SbVec3f(0,1,0), dir); + SbVec3f ax(axis.x, axis.y, axis.z); + SbVec3f dir(direction.x, direction.y, direction.z); - createPlacement(pShapeSep, b, rot); + createPlacement(pShapeSep, b, SbRotation(SbVec3f(0,1,0), ax)); pShapeSep->addChild(createCylinder(pcConstraint->Height.getValue() * 0.8, dia/2)); - createPlacement(pShapeSep, SbVec3f(-dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(0,0,1))); + createPlacement(pShapeSep, SbVec3f(dia/2 * sin(angle), 0, dia/2 * cos(angle)), SbRotation(ax, dir)); pShapeSep->addChild(createArrow(dia/2, dia/8)); } } else if (strcmp(prop->getName(),"Diameter") == 0) { if (pShapeSep->getNumChildren() > 0) { // Change the symbol - Base::Vector3f base = pcConstraint->BasePoint.getValue(); Base::Vector3f axis = pcConstraint->Axis.getValue(); - //float radius = pcConstraint->Radius.getValue(); + Base::Vector3f direction = pcConstraint->DirectionVector.getValue(); + if (direction.Length() < Precision::Confusion()) + direction = Base::Vector3f(0,1,0); float dia = pcConstraint->Diameter.getValue(); float radius = pcConstraint->Radius.getValue(); if (dia < 2 * radius) dia = 2 * radius; + float angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; - SbVec3f b(base.x, base.y, base.z); - SbVec3f dir(axis.x, axis.y, axis.z); - SbRotation rot(SbVec3f(0,1,0), dir); + SbVec3f ax(axis.x, axis.y, axis.z); + SbVec3f dir(direction.x, direction.y, direction.z); - updatePlacement(pShapeSep, 0, b, rot); const SoSeparator* sep = static_cast(pShapeSep->getChild(2)); updateCylinder(sep, 0, pcConstraint->Height.getValue() * 0.8, dia/2); - updatePlacement(pShapeSep, 3, SbVec3f(-dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(0,0,1))); + updatePlacement(pShapeSep, 3, SbVec3f(dia/2 * sin(angle), 0, dia/2 * cos(angle)), SbRotation(ax, dir)); sep = static_cast(pShapeSep->getChild(5)); updateArrow(sep, 0, dia/2, dia/8); } + } else if ((strcmp(prop->getName(),"DirectionVector") == 0) || (strcmp(prop->getName(),"ForceAngle") == 0)) { + // Note: "Reversed" also triggers "DirectionVector" + if (pShapeSep->getNumChildren() > 0) { + // Re-orient the symbol + Base::Vector3f axis = pcConstraint->Axis.getValue(); + Base::Vector3f direction = pcConstraint->DirectionVector.getValue(); + if (direction.Length() < Precision::Confusion()) + direction = Base::Vector3f(0,1,0); + float dia = pcConstraint->Diameter.getValue(); + float angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + + SbVec3f ax(axis.x, axis.y, axis.z); + SbVec3f dir(direction.x, direction.y, direction.z); + /*Base::Console().Error("Axis: %f, %f, %f\n", axis.x, axis.y, axis.z); + Base::Console().Error("Direction: %f, %f, %f\n", direction.x, direction.y, direction.z); + SbRotation rot = SbRotation(ax, dir); + SbMatrix m; + rot.getValue(m); + SbMat m2; + m.getValue(m2); + Base::Console().Error("Matrix: %f, %f, %f, %f\n", m[0][0], m[1][0], m[2][0], m[3][0]); + // Note: In spite of the fact that the rotation matrix takes on 3 different values if 3 + // normal directions are chosen, the resulting arrow will only point in two different + // directions when ax = (1,0,0) (but for ax=(0,1,0) it points in 3 different directions!) + */ + + updatePlacement(pShapeSep, 3, SbVec3f(dia/2 * sin(angle), 0, dia/2 * cos(angle)), SbRotation(ax, dir)); + } } ViewProviderFemConstraint::updateData(prop); diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp index df4762364..518b4b487 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp @@ -53,6 +53,7 @@ ViewProviderFemConstraintPulley::~ViewProviderFemConstraintPulley() bool ViewProviderFemConstraintPulley::setEdit(int ModNum) { + Base::Console().Error("ViewProviderFemConstraintPulley::setEdit()\n"); if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing @@ -62,21 +63,28 @@ bool ViewProviderFemConstraintPulley::setEdit(int ModNum) if (constrDlg && constrDlg->getConstraintView() != this) constrDlg = 0; // another constraint left open its task panel if (dlg && !constrDlg) { - // Allow stacking of dialogs, for ShaftWizard application - // Note: If other features start to allow stacking, we need to check for oldDlg != NULL - oldDlg = dlg; - /* - QMessageBox msgBox; - msgBox.setText(QObject::tr("A dialog is already open in the task panel")); - msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) - Gui::Control().closeDialog(); - else + // This case will occur in the ShaftWizard application + checkForWizard(); + if ((wizardWidget == NULL) || (wizardSubLayout == NULL)) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } else if (constraintDialog != NULL) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog return false; - */ + } else { + constraintDialog = new TaskFemConstraintPulley(this); + return true; + } } // clear the selection (convenience) @@ -99,10 +107,6 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes Fem::ConstraintPulley* pcConstraint = static_cast(this->getObject()); - if (this->getObject() != NULL) - Base::Console().Error("%s: VP updateData: %s\n", this->getObject()->getNameInDocument(), prop->getName()); - else - Base::Console().Error("Anonymous: VP updateData: %s\n", prop->getName()); if (strcmp(prop->getName(),"BasePoint") == 0) { if (pcConstraint->Height.getValue() > Precision::Confusion()) { @@ -116,49 +120,104 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) float dia = pcConstraint->Diameter.getValue(); if (dia < 2 * radius) dia = 2 * radius; - float angle = pcConstraint->Angle.getValue(); + float forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + float beltAngle = pcConstraint->BeltAngle.getValue(); + double rat1 = 0.8, rat2 = 0.2; + float f1 = pcConstraint->BeltForce1.getValue(); + float f2 = pcConstraint->BeltForce2.getValue(); + if (f1+f2 > Precision::Confusion()) { + rat1 = f1 / (f1+f2); + rat2 = f2 / (f1+f2); + } SbVec3f b(base.x, base.y, base.z); - SbVec3f dir(axis.x, axis.y, axis.z); - SbRotation rot(SbVec3f(0,-1,0), dir); + SbVec3f ax(axis.x, axis.y, axis.z); - createPlacement(pShapeSep, b, rot); // child 0 and 1 + createPlacement(pShapeSep, b, SbRotation(SbVec3f(0,1,0), ax)); // child 0 and 1 pShapeSep->addChild(createCylinder(pcConstraint->Height.getValue() * 0.8, dia/2)); // child 2 SoSeparator* sep = new SoSeparator(); - createPlacement(sep, SbVec3f(dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(sin(angle),0,cos(angle)))); - sep->addChild(createArrow(dia/2, dia/8)); + createPlacement(sep, SbVec3f(dia/2 * sin(forceAngle+beltAngle), 0, dia/2 * cos(forceAngle+beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(sin(forceAngle+beltAngle+M_PI_2),0,cos(forceAngle+beltAngle+M_PI_2)))); + createPlacement(sep, SbVec3f(0, dia/8 + dia/2 * rat1, 0), SbRotation()); + sep->addChild(createArrow(dia/8 + dia/2 * rat1, dia/8)); pShapeSep->addChild(sep); // child 3 sep = new SoSeparator(); - createPlacement(sep, SbVec3f(-dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(-sin(angle),0,cos(angle)))); - sep->addChild(createArrow(dia/2, dia/8)); + createPlacement(sep, SbVec3f(-dia/2 * sin(forceAngle-beltAngle), 0, -dia/2 * cos(forceAngle-beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(-sin(forceAngle-beltAngle-M_PI_2),0,-cos(forceAngle-beltAngle-M_PI_2)))); + createPlacement(sep, SbVec3f(0, dia/8 + dia/2 * rat2, 0), SbRotation()); + sep->addChild(createArrow(dia/8 + dia/2 * rat2, dia/8)); pShapeSep->addChild(sep); // child 4 } - } else if (strcmp(prop->getName(),"Angle") == 0) { + } else if (strcmp(prop->getName(),"Diameter") == 0) { if (pShapeSep->getNumChildren() > 0) { // Change the symbol - Base::Vector3f base = pcConstraint->BasePoint.getValue(); - Base::Vector3f axis = pcConstraint->Axis.getValue(); float radius = pcConstraint->Radius.getValue(); float dia = pcConstraint->Diameter.getValue(); if (dia < 2 * radius) dia = 2 * radius; - float angle = pcConstraint->Angle.getValue(); + float forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + float beltAngle = pcConstraint->BeltAngle.getValue(); + double rat1 = 0.8, rat2 = 0.2; + float f1 = pcConstraint->BeltForce1.getValue(); + float f2 = pcConstraint->BeltForce2.getValue(); + if (f1+f2 > Precision::Confusion()) { + rat1 = f1 / (f1+f2); + rat2 = f2 / (f1+f2); + } - SbVec3f b(base.x, base.y, base.z); - SbVec3f dir(axis.x, axis.y, axis.z); - SbRotation rot(SbVec3f(0,-1,0), dir); - - updatePlacement(pShapeSep, 0, b, rot); const SoSeparator* sep = static_cast(pShapeSep->getChild(2)); updateCylinder(sep, 0, pcConstraint->Height.getValue() * 0.8, dia/2); sep = static_cast(pShapeSep->getChild(3)); - updatePlacement(sep, 0, SbVec3f(dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(sin(angle),0,cos(angle)))); - const SoSeparator* subsep = static_cast(sep->getChild(2)); - updateArrow(subsep, 0, dia/2, dia/8); + updatePlacement(sep, 0, SbVec3f(dia/2 * sin(forceAngle+beltAngle), 0, dia/2 * cos(forceAngle+beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(sin(forceAngle+beltAngle+M_PI_2),0,cos(forceAngle+beltAngle+M_PI_2)))); + updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat1, 0), SbRotation()); + const SoSeparator* subsep = static_cast(sep->getChild(4)); + updateArrow(subsep, 0, dia/8 + dia/2 * rat1, dia/8); sep = static_cast(pShapeSep->getChild(4)); - updatePlacement(sep, 0, SbVec3f(-dia/2,0,0), SbRotation(SbVec3f(0,1,0), SbVec3f(-sin(angle),0,cos(angle)))); - subsep = static_cast(sep->getChild(2)); - updateArrow(subsep, 0, dia/2, dia/8); + updatePlacement(sep, 0, SbVec3f(-dia/2 * sin(forceAngle-beltAngle), 0, -dia/2 * cos(forceAngle-beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(-sin(forceAngle-beltAngle-M_PI_2),0,-cos(forceAngle-beltAngle-M_PI_2)))); + updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat2, 0), SbRotation()); + subsep = static_cast(sep->getChild(4)); + updateArrow(subsep, 0, dia/8 + dia/2 * rat2, dia/8); + } + } else if ((strcmp(prop->getName(), "ForceAngle") == 0) || (strcmp(prop->getName(), "BeltAngle") == 0)) { + if (pShapeSep->getNumChildren() > 0) { + float radius = pcConstraint->Radius.getValue(); + float dia = pcConstraint->Diameter.getValue(); + if (dia < 2 * radius) + dia = 2 * radius; + float forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + float beltAngle = pcConstraint->BeltAngle.getValue(); + + const SoSeparator* sep = static_cast(pShapeSep->getChild(3)); + updatePlacement(sep, 0, SbVec3f(dia/2 * sin(forceAngle+beltAngle), 0, dia/2 * cos(forceAngle+beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(sin(forceAngle+beltAngle+M_PI_2),0,cos(forceAngle+beltAngle+M_PI_2)))); + sep = static_cast(pShapeSep->getChild(4)); + updatePlacement(sep, 0, SbVec3f(-dia/2 * sin(forceAngle-beltAngle), 0, -dia/2 * cos(forceAngle-beltAngle)), + SbRotation(SbVec3f(0,1,0), SbVec3f(-sin(forceAngle-beltAngle-M_PI_2),0,-cos(forceAngle-beltAngle-M_PI_2)))); + } + } else if ((strcmp(prop->getName(), "BeltForce1") == 0) || (strcmp(prop->getName(), "BeltForce2") == 0)) { + if (pShapeSep->getNumChildren() > 0) { + float radius = pcConstraint->Radius.getValue(); + float dia = pcConstraint->Diameter.getValue(); + if (dia < 2 * radius) + dia = 2 * radius; + double rat1 = 0.8, rat2 = 0.2; + float f1 = pcConstraint->BeltForce1.getValue(); + float f2 = pcConstraint->BeltForce2.getValue(); + if (f1+f2 > Precision::Confusion()) { + rat1 = f1 / (f1+f2); + rat2 = f2 / (f1+f2); + } + + const SoSeparator* sep = static_cast(pShapeSep->getChild(3)); + updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat1, 0), SbRotation()); + const SoSeparator* subsep = static_cast(sep->getChild(4)); + updateArrow(subsep, 0, dia/8 + dia/2 * rat1, dia/8); + sep = static_cast(pShapeSep->getChild(4)); + updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat2, 0), SbRotation()); + subsep = static_cast(sep->getChild(4)); + updateArrow(subsep, 0, dia/8 + dia/2 * rat2, dia/8); } }