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