Improvements to FEM constraint objects

This commit is contained in:
jrheinlaender 2013-03-08 19:59:08 +04:30
parent 517443fb59
commit f5c6e4eae3
29 changed files with 939 additions and 318 deletions

View File

@ -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<std::string> names = location.getSubValues();
if (names.size() == 0)
return Base::Vector3f(0,0,0);
std::string subName = names.front();
Part::Feature* featLoc = static_cast<Part::Feature*>(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<std::string> names = direction.getSubValues();
if (names.size() == 0)
return Base::Vector3f(0,0,0);
std::string subName = names.front();
Part::Feature* feat = static_cast<Part::Feature*>(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;
}

View File

@ -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);
};

View File

@ -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);

View File

@ -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;

View File

@ -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<std::string> 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<Part::Feature*>(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;

View File

@ -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
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -28,12 +28,12 @@
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#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

View File

@ -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

View File

@ -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());

View File

@ -43,7 +43,6 @@
#include "TaskFemConstraint.h"
#include <App/Application.h>
#include <App/Document.h>
//#include <App/PropertyGeo.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
@ -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<QGridLayout*>();
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 <Enter> 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<std::string>& 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<QGridLayout*>();
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<Fem::Constraint*>(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());

View File

@ -29,15 +29,7 @@
#include <Gui/TaskView/TaskDialog.h>
#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

View File

@ -39,7 +39,7 @@
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraintCylindrical.h"
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintBearing.h"
#include <App/Application.h>
#include <App/Document.h>
@ -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<std::string> references(1,subName);
Fem::ConstraintBearing* pcConstraint = static_cast<Fem::ConstraintBearing*>(ConstraintView->getObject());
App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName);
Part::Feature* feat = static_cast<Part::Feature*>(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<std::string> references(1,subName);
pcConstraint->Location.setValue(obj, references);
ui->lineLocation->setText(makeRefText(obj, subName));

View File

@ -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

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskFemConstraintCylindrical</class>
<widget class="QWidget" name="TaskFemConstraintCylindrical">
<class>TaskFemConstraintBearing</class>
<widget class="QWidget" name="TaskFemConstraintBearing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>338</height>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
@ -25,9 +25,12 @@
<widget class="QListWidget" name="listReferences"/>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter">
<layout class="QHBoxLayout" name="layoutDiameter_3">
<item>
<widget class="QLabel" name="labelDiameter">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Gear diameter</string>
</property>
@ -49,11 +52,14 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_3">
<layout class="QHBoxLayout" name="layoutDiameter_6">
<item>
<widget class="QLabel" name="labelOtherDiameter">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Other diameter</string>
<string>Other pulley dia</string>
</property>
</widget>
</item>
@ -66,14 +72,14 @@
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>200.000000000000000</double>
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_4">
<layout class="QHBoxLayout" name="layoutDiameter_7">
<item>
<widget class="QLabel" name="labelCenterDistance">
<property name="text">
@ -90,12 +96,122 @@
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>500.000000000000000</double>
<double>1000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_4">
<item>
<widget class="QLabel" name="labelForce">
<property name="text">
<string>Force</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinForce">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_8">
<item>
<widget class="QLabel" name="labelTensionForce">
<property name="text">
<string>Belt tension force</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinTensionForce">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkIsDriven">
<property name="text">
<string>Driven pulley</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_5">
<item>
<widget class="QLabel" name="labelForceAngle">
<property name="text">
<string>Force location [deg]</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinForceAngle">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutLocation_2">
<item>
<widget class="QPushButton" name="buttonDirection">
<property name="text">
<string>Force Direction</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineDirection"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkReversed">
<property name="text">
<string>Reversed direction</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkAxial">
<property name="text">
<string>Axial free</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="layoutLocation">
<item>
@ -147,13 +263,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkAxial">
<property name="text">
<string>Axial free</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -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++)

View File

@ -29,7 +29,7 @@
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>
# include <Precision.hxx>*/
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
@ -38,10 +38,9 @@
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
*/
#endif
#include "ui_TaskFemConstraintCylindrical.h"
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintGear.h"
#include <App/Application.h>
#include <App/Document.h>
@ -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<Fem::ConstraintGear*>(ConstraintView->getObject());
Fem::ConstraintGear* pcConstraint = static_cast<Fem::ConstraintGear*>(ConstraintView->getObject());
double dia = pcConstraint->Diameter.getValue();
double force = pcConstraint->Force.getValue();
double angle = pcConstraint->ForceAngle.getValue();
std::vector<std::string> 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<std::string> references(1,subName);
Fem::ConstraintGear* pcConstraint = static_cast<Fem::ConstraintGear*>(ConstraintView->getObject());
App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName);
Part::Feature* feat = static_cast<Part::Feature*>(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<Fem::ConstraintGear*>(ConstraintView->getObject());
pcConstraint->Diameter.setValue((float)l);
}
void TaskFemConstraintGear::onForceChanged(double f)
{
Fem::ConstraintGear* pcConstraint = static_cast<Fem::ConstraintGear*>(ConstraintView->getObject());
pcConstraint->Force.setValue((float)f);
}
void TaskFemConstraintGear::onForceAngleChanged(double a)
{
Fem::ConstraintGear* pcConstraint = static_cast<Fem::ConstraintGear*>(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<Fem::ConstraintGear*>(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;

View File

@ -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)

View File

@ -26,7 +26,7 @@
#ifndef _PreComp_
#endif
#include "ui_TaskFemConstraintCylindrical.h"
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintPulley.h"
#include <App/Application.h>
#include <App/Document.h>
@ -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<Fem::ConstraintPulley*>(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<Fem::ConstraintPulley*>(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<Fem::ConstraintPulley*>(ConstraintView->getObject());
pcConstraint->TensionForce.setValue((float)force);
}
void TaskFemConstraintPulley::onCheckIsDriven(const bool pressed)
{
Fem::ConstraintPulley* pcConstraint = static_cast<Fem::ConstraintPulley*>(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<const TaskFemConstraintPulley*>(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"

View File

@ -28,44 +28,36 @@
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#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

View File

@ -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 <Base/Console.h>
@ -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<QDockWidget*>(QObject::tr("Combo View"));
if (dw == NULL) return;
QWidget* cw = dw->findChild<QWidget*>(QObject::tr("Combo View"));
if (cw == NULL) return;
QTabWidget* tw = cw->findChild<QTabWidget*>(QObject::tr("combiTab"));
if (tw == NULL) return;
QStackedWidget* sw = tw->findChild<QStackedWidget*>(QObject::tr("qt_tabwidget_stackedwidget"));
if (sw == NULL) return;
QScrollArea* sa = sw->findChild<QScrollArea*>();
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<QVBoxLayout*>(wiz);
wizardSubLayout = wiz->findChild<QVBoxLayout*>(QObject::tr("ShaftWizardLayout"));
}

View File

@ -28,6 +28,8 @@
#include "Gui/ViewProviderGeometryObject.h"
#include <QObject>
#include <QVBoxLayout>
#include <QTableWidget>
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

View File

@ -34,6 +34,7 @@
#include <Mod/Fem/App/FemConstraintBearing.h>
#include "TaskFemConstraintBearing.h"
#include "Gui/Control.h"
#include "Gui/MainWindow.h"
#include <Base/Console.h>
@ -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<Fem::ConstraintBearing*>(this->getObject());

View File

@ -28,6 +28,7 @@
#include "ViewProviderFemConstraint.h"
#include <QObject>
#include <QVBoxLayout>
class SoFontStyle;
class SoText2;

View File

@ -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<Fem::ConstraintFixed*>(this->getObject());
/*

View File

@ -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<Fem::ConstraintForce*>(this->getObject());
/*

View File

@ -27,6 +27,7 @@
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/SbMatrix.h>
# include <Precision.hxx>
#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<Fem::ConstraintGear*>(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<SoSeparator*>(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<SoSeparator*>(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);

View File

@ -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<Fem::ConstraintPulley*>(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<SoSeparator*>(pShapeSep->getChild(2));
updateCylinder(sep, 0, pcConstraint->Height.getValue() * 0.8, dia/2);
sep = static_cast<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(sep->getChild(4));
updateArrow(subsep, 0, dia/8 + dia/2 * rat1, dia/8);
sep = static_cast<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(pShapeSep->getChild(3));
updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat1, 0), SbRotation());
const SoSeparator* subsep = static_cast<SoSeparator*>(sep->getChild(4));
updateArrow(subsep, 0, dia/8 + dia/2 * rat1, dia/8);
sep = static_cast<SoSeparator*>(pShapeSep->getChild(4));
updatePlacement(sep, 2, SbVec3f(0, dia/8 + dia/2 * rat2, 0), SbRotation());
subsep = static_cast<SoSeparator*>(sep->getChild(4));
updateArrow(subsep, 0, dia/8 + dia/2 * rat2, dia/8);
}
}