Improvements to FEM constraint objects
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user