Intgrate Jans FEM PullRequest

This commit is contained in:
jriegel
2013-03-22 12:49:05 +01:00
58 changed files with 10175 additions and 316 deletions

View File

@@ -41,6 +41,11 @@
#include "FemSetNodesObject.h"
#include "HypothesisPy.h"
#include "FemConstraintBearing.h"
#include "FemConstraintFixed.h"
#include "FemConstraintForce.h"
#include "FemConstraintGear.h"
#include "FemConstraintPulley.h"
extern struct PyMethodDef Fem_methods[];
@@ -115,6 +120,12 @@ void AppFemExport initFem()
Fem::FemSetGeometryObject ::init();
Fem::FemSetNodesObject ::init();
Fem::Constraint ::init();
Fem::ConstraintBearing ::init();
Fem::ConstraintFixed ::init();
Fem::ConstraintForce ::init();
Fem::ConstraintGear ::init();
Fem::ConstraintPulley ::init();
}
} // extern "C"

View File

@@ -24,10 +24,10 @@ set(Fem_LIBS
Mesh
FreeCADApp
)
if(SMESH_FOUND)
include_directories( ${SMESH_INCLUDE_DIR} )
list( APPEND Fem_LIBS ${SMESH_LIBRARIES} )
if(SMESH_FOUND)
include_directories( ${SMESH_INCLUDE_DIR} )
list( APPEND Fem_LIBS ${SMESH_LIBRARIES} )
endif(SMESH_FOUND)
generate_from_xml(FemMeshPy)
@@ -64,6 +64,18 @@ SET(Fem_SRCS
FemMesh.h
FemMeshProperty.cpp
FemMeshProperty.h
FemConstraint.cpp
FemConstraint.h
FemConstraintBearing.h
FemConstraintBearing.cpp
FemConstraintFixed.cpp
FemConstraintFixed.h
FemConstraintForce.cpp
FemConstraintForce.h
FemConstraintGear.cpp
FemConstraintGear.h
FemConstraintPulley.cpp
FemConstraintPulley.h
${Mod_SRCS}
${Python_SRCS}
)

View File

@@ -0,0 +1,329 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <TopoDS.hxx>
# include <BRepGProp_Face.hxx>
# include <gp_Vec.hxx>
# include <gp_Pnt.hxx>
# include <gp_Pln.hxx>
# include <gp_Cylinder.hxx>
# include <gp_Ax3.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <GCPnts_AbscissaPoint.hxx>
# include <Adaptor3d_IsoCurve.hxx>
# include <Adaptor3d_HSurface.hxx>
# include <BRepAdaptor_HSurface.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <GProp_GProps.hxx>
# include <BRepGProp.hxx>
# include <TopoDS_Vertex.hxx>
# include <BRepClass_FaceClassifier.hxx>
# include <BRep_Tool.hxx>
# include <BRepGProp_Face.hxx>
# include <ShapeAnalysis.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
# include <GeomAPI_IntCS.hxx>
# include <Geom_Plane.hxx>
# include <Geom_Line.hxx>
# include <Precision.hxx>
#endif
#include "FemConstraint.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::Constraint, App::DocumentObject);
Constraint::Constraint()
{
ADD_PROPERTY_TYPE(References,(0,0),"Constraint",(App::PropertyType)(App::Prop_None),"Elements where the constraint is applied");
ADD_PROPERTY_TYPE(NormalDirection,(Base::Vector3f(0,0,1)),"Constraint",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),"Normal direction pointing outside of solid");
}
Constraint::~Constraint()
{
}
App::DocumentObjectExecReturn *Constraint::execute(void)
{
References.touch();
return StdReturn;
}
void Constraint::onChanged(const App::Property* prop)
{
//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
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
// Extract geometry from References
TopoDS_Shape sh;
for (int i = 0; i < Objects.size(); i++) {
App::DocumentObject* obj = Objects[i];
Part::Feature* feat = static_cast<Part::Feature*>(obj);
const Part::TopoShape& toposhape = feat->Shape.getShape();
if (!toposhape._Shape.IsNull()) {
sh = toposhape.getSubShape(SubElements[i].c_str());
if (sh.ShapeType() == TopAbs_FACE) {
// Get face normal in center point
TopoDS_Face face = TopoDS::Face(sh);
BRepGProp_Face props(face);
gp_Vec normal;
gp_Pnt center;
double u1,u2,v1,v2;
props.Bounds(u1,u2,v1,v2);
props.Normal((u1+u2)/2.0,(v1+v2)/2.0,center,normal);
normal.Normalize();
NormalDirection.setValue(normal.X(), normal.Y(), normal.Z());
// One face is enough...
App::DocumentObject::onChanged(prop);
return;
}
}
}
}
App::DocumentObject::onChanged(prop);
}
void Constraint::onDocumentRestored()
{
// This seems to be the only way to make the ViewProvider display the constraint
References.touch();
App::DocumentObject::onDocumentRestored();
}
const bool Constraint::getPoints(std::vector<Base::Vector3f> &points, std::vector<Base::Vector3f> &normals) const
{
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
// Extract geometry from References
TopoDS_Shape sh;
for (int i = 0; i < Objects.size(); i++) {
App::DocumentObject* obj = Objects[i];
Part::Feature* feat = static_cast<Part::Feature*>(obj);
const Part::TopoShape& toposhape = feat->Shape.getShape();
if (toposhape.isNull())
return false;
sh = toposhape.getSubShape(SubElements[i].c_str());
if (sh.ShapeType() == TopAbs_VERTEX) {
const TopoDS_Vertex& vertex = TopoDS::Vertex(sh);
gp_Pnt p = BRep_Tool::Pnt(vertex);
points.push_back(Base::Vector3f(p.X(), p.Y(), p.Z()));
normals.push_back(NormalDirection.getValue());
} else if (sh.ShapeType() == TopAbs_EDGE) {
BRepAdaptor_Curve curve(TopoDS::Edge(sh));
double fp = curve.FirstParameter();
double lp = curve.LastParameter();
GProp_GProps props;
BRepGProp::LinearProperties(TopoDS::Edge(sh), props);
double l = props.Mass();
// Create points with 10 units distance, but at least one at the beginning and end of the edge
int steps;
if (l >= 20)
steps = round(l / 10);
else
steps = 1;
double step = (lp - fp) / steps;
for (int i = 0; i < steps + 1; i++) {
gp_Pnt p = curve.Value(i * step);
points.push_back(Base::Vector3f(p.X(), p.Y(), p.Z()));
normals.push_back(NormalDirection.getValue());
}
} else if (sh.ShapeType() == TopAbs_FACE) {
TopoDS_Face face = TopoDS::Face(sh);
// Surface boundaries
BRepAdaptor_Surface surface(face);
double ufp = surface.FirstUParameter();
double ulp = surface.LastUParameter();
double vfp = surface.FirstVParameter();
double vlp = surface.LastVParameter();
// Surface normals
BRepGProp_Face props(face);
gp_Vec normal;
gp_Pnt center;
// Get an estimate for the number of arrows by finding the average length of curves
Handle(Adaptor3d_HSurface) hsurf;
hsurf = new BRepAdaptor_HSurface(surface);
Adaptor3d_IsoCurve isoc(hsurf, GeomAbs_IsoU, vfp);
double l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
isoc.Load(GeomAbs_IsoU, vlp);
double lv = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
isoc.Load(GeomAbs_IsoV, ufp);
l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
isoc.Load(GeomAbs_IsoV, ulp);
double lu = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
int stepsv;
if (lv >= 20.0)
stepsv = round(lv / 10);
else
stepsv = 2; // Minimum of three arrows to ensure (as much as possible) that at least one is displayed
int stepsu;
if (lu >= 20.0)
stepsu = round(lu / 10);
else
stepsu = 2;
double stepv = (vlp - vfp) / stepsv;
double stepu = (ulp - ufp) / stepsu;
// Create points and normals
for (int i = 0; i < stepsv + 1; i++) {
for (int j = 0; j < stepsu + 1; j++) {
double v = vfp + i * stepv;
double u = ufp + j * stepu;
gp_Pnt p = surface.Value(u, v);
BRepClass_FaceClassifier classifier(face, p, Precision::Confusion());
if (classifier.State() != TopAbs_OUT) {
points.push_back(Base::Vector3f(p.X(), p.Y(), p.Z()));
props.Normal(u, v,center,normal);
normal.Normalize();
normals.push_back(Base::Vector3f(normal.X(), normal.Y(), normal.Z()));
}
}
}
}
}
return true;
}
const bool Constraint::getCylinder(float& radius, float& height, Base::Vector3f& base, Base::Vector3f& axis) const
{
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
if (Objects.empty())
return false;
App::DocumentObject* obj = Objects[0];
Part::Feature* feat = static_cast<Part::Feature*>(obj);
Part::TopoShape toposhape = feat->Shape.getShape();
if (toposhape.isNull())
return false;
TopoDS_Shape sh = toposhape.getSubShape(SubElements[0].c_str());
TopoDS_Face face = TopoDS::Face(sh);
BRepAdaptor_Surface surface(face);
gp_Cylinder cyl = surface.Cylinder();
gp_Pnt start = surface.Value(surface.FirstUParameter(), surface.FirstVParameter());
gp_Pnt end = surface.Value(surface.FirstUParameter(), surface.LastVParameter());
height = start.Distance(end);
radius = cyl.Radius();
gp_Pnt b = cyl.Location();
base = Base::Vector3f(b.X(), b.Y(), b.Z());
gp_Dir dir = cyl.Axis().Direction();
axis = Base::Vector3f(dir.X(), dir.Y(), dir.Z());
return true;
}
Base::Vector3f Constraint::getBasePoint(const Base::Vector3f& base, const Base::Vector3f& axis,
const App::PropertyLinkSub& location, const float& dist)
{
// Get the point specified by Location and Distance
App::DocumentObject* objLoc = location.getValue();
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());
// Get a plane from the Location reference
gp_Pln plane;
gp_Dir cylaxis(axis.x, axis.y, axis.z);
if (shloc.ShapeType() == TopAbs_FACE) {
BRepAdaptor_Surface surface(TopoDS::Face(shloc));
plane = surface.Plane();
} else {
BRepAdaptor_Curve curve(TopoDS::Edge(shloc));
gp_Lin line = curve.Line();
gp_Dir tang = line.Direction().Crossed(cylaxis);
gp_Dir norm = line.Direction().Crossed(tang);
plane = gp_Pln(line.Location(), norm);
}
// Translate the plane in direction of the cylinder (for positive values of Distance)
Handle_Geom_Plane pln = new Geom_Plane(plane);
gp_Pnt cylbase(base.x, base.y, base.z);
GeomAPI_ProjectPointOnSurf proj(cylbase, pln);
if (!proj.IsDone())
return Base::Vector3f(0,0,0);
gp_Pnt projPnt = proj.NearestPoint();
if ((fabs(dist) > Precision::Confusion()) && (projPnt.IsEqual(cylbase, Precision::Confusion()) == Standard_False))
plane.Translate(gp_Vec(projPnt, cylbase).Normalized().Multiplied(dist));
Handle_Geom_Plane plnt = new Geom_Plane(plane);
// Intersect translated plane with cylinder axis
Handle_Geom_Curve crv = new Geom_Line(cylbase, cylaxis);
GeomAPI_IntCS intersector(crv, plnt);
if (!intersector.IsDone())
return Base::Vector3f(0,0,0);
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

@@ -0,0 +1,73 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINT_H
#define FEM_CONSTRAINT_H
#include <Base/Vector3D.h>
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
namespace Fem
{
class AppFemExport Constraint : public App::DocumentObject
{
PROPERTY_HEADER(Fem::Constraint);
public:
/// Constructor
Constraint(void);
virtual ~Constraint();
App::PropertyLinkSubList References;
// Read-only (calculated values). These trigger changes in the ViewProvider
App::PropertyVector NormalDirection;
/// recalculate the object
virtual App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraint";
}
protected:
virtual void onChanged(const App::Property* prop);
virtual void onDocumentRestored();
protected:
/// Calculate the points where symbols should be drawn
const bool getPoints(std::vector<Base::Vector3f>& points, std::vector<Base::Vector3f>& normals) const;
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);
};
} //namespace Fem
#endif // FEM_CONSTRAINT_H

View File

@@ -0,0 +1,117 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
#include <TopoDS.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
#endif
#include "FemConstraintBearing.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::ConstraintBearing, Fem::Constraint);
ConstraintBearing::ConstraintBearing()
{
ADD_PROPERTY_TYPE(Location,(0),"ConstraintBearing",(App::PropertyType)(App::Prop_None),
"Element giving axial location of constraint");
ADD_PROPERTY(Dist,(0.0));
ADD_PROPERTY(AxialFree,(0));
ADD_PROPERTY(Radius,(0.0));
ADD_PROPERTY(Height,(0.0));
ADD_PROPERTY_TYPE(BasePoint,(Base::Vector3f(0,0,0)),"ConstraintBearing",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Base point of cylindrical bearing seat");
ADD_PROPERTY_TYPE(Axis,(Base::Vector3f(0,1,0)),"ConstraintBearing",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Axis of bearing seat");
}
App::DocumentObjectExecReturn *ConstraintBearing::execute(void)
{
return Constraint::execute();
}
void ConstraintBearing::onChanged(const App::Property* prop)
{
//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);
if (prop == &References) {
// Find data of cylinder
float radius, height;
Base::Vector3f base, axis;
if (!getCylinder(radius, height, base, axis))
return;
Radius.setValue(radius);
Axis.setValue(axis);
Height.setValue(height);
// Update base point
base = base + axis * height/2;
if (Location.getValue() != NULL) {
base = getBasePoint(base, axis, Location, Dist.getValue());
}
BasePoint.setValue(base);
BasePoint.touch(); // This triggers ViewProvider::updateData()
} else if ((prop == &Location) || (prop == &Dist)) {
App::DocumentObject* obj = Location.getValue();
std::vector<std::string> names = Location.getSubValues();
if (names.size() == 0) {
return;
}
std::string subName = names.front();
Part::Feature* feat = static_cast<Part::Feature*>(obj);
TopoDS_Shape sh = feat->Shape.getShape().getSubShape(subName.c_str());
if (sh.ShapeType() == TopAbs_FACE) {
BRepAdaptor_Surface surface(TopoDS::Face(sh));
if (surface.GetType() != GeomAbs_Plane) {
return; // "Location 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) {
return; // "Location must be a planar face or linear edge"
}
}
float radius, height;
Base::Vector3f base, axis;
if (!getCylinder(radius, height, base, axis))
return;
base = getBasePoint(base + axis * height/2, axis, Location, Dist.getValue());
BasePoint.setValue(base);
BasePoint.touch();
}
}

View File

@@ -0,0 +1,71 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINTBEARING_H
#define FEM_CONSTRAINTBEARING_H
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#include "FemConstraint.h"
namespace Fem
{
class AppFemExport ConstraintBearing : public Fem::Constraint
{
PROPERTY_HEADER(Fem::ConstraintBearing);
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;
App::PropertyFloat Height;
App::PropertyVector BasePoint;
App::PropertyVector Axis;
/// recalculate the object
virtual App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintBearing";
}
protected:
virtual void onChanged(const App::Property* prop);
};
} //namespace Fem
#endif // FEM_CONSTRAINTBEARING_H

View File

@@ -0,0 +1,84 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <Adaptor3d_IsoCurve.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRep_Tool.hxx>
#include <Precision.hxx>
#endif
#include "FemConstraintFixed.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::ConstraintFixed, Fem::Constraint);
ConstraintFixed::ConstraintFixed()
{
ADD_PROPERTY_TYPE(Points,(Base::Vector3f()),"ConstraintFixed",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Points where symbols are drawn");
ADD_PROPERTY_TYPE(Normals,(Base::Vector3f()),"ConstraintFixed",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Normals where symbols are drawn");
Points.setValues(std::vector<Base::Vector3f>());
Normals.setValues(std::vector<Base::Vector3f>());
}
App::DocumentObjectExecReturn *ConstraintFixed::execute(void)
{
return Constraint::execute();
}
void ConstraintFixed::onChanged(const App::Property* prop)
{
// Note: If we call this at the end, then the symbols are not oriented correctly initially
// because the NormalDirection has not been calculated yet
Constraint::onChanged(prop);
if (prop == &References) {
std::vector<Base::Vector3f> points;
std::vector<Base::Vector3f> normals;
if (getPoints(points, normals)) {
Points.setValues(points);
Normals.setValues(normals);
Points.touch(); // This triggers ViewProvider::updateData()
}
}
}

View File

@@ -0,0 +1,63 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINTFIXED_H
#define FEM_CONSTRAINTFIXED_H
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#include "FemConstraint.h"
namespace Fem
{
class AppFemExport ConstraintFixed : public Fem::Constraint
{
PROPERTY_HEADER(Fem::ConstraintFixed);
public:
/// Constructor
ConstraintFixed(void);
// Read-only (calculated values). These trigger changes in the ViewProvider
App::PropertyVectorList Points;
App::PropertyVectorList Normals;
/// recalculate the object
virtual App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintFixed";
}
protected:
virtual void onChanged(const App::Property* prop);
};
} //namespace Fem
#endif // FEM_CONSTRAINTFIXED_H

View File

@@ -0,0 +1,101 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
#include <TopoDS.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
#endif
#include "FemConstraintForce.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::ConstraintForce, Fem::Constraint);
ConstraintForce::ConstraintForce()
{
ADD_PROPERTY(Force,(0.0));
ADD_PROPERTY_TYPE(Direction,(0),"ConstraintForce",(App::PropertyType)(App::Prop_None),
"Element giving direction of constraint");
ADD_PROPERTY(Reversed,(0));
ADD_PROPERTY_TYPE(Points,(Base::Vector3f()),"ConstraintForce",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Points where arrows are drawn");
ADD_PROPERTY_TYPE(DirectionVector,(Base::Vector3f(0,0,1)),"ConstraintForce",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Direction of arrows");
naturalDirectionVector = Base::Vector3f(0,0,1);
Points.setValues(std::vector<Base::Vector3f>());
}
App::DocumentObjectExecReturn *ConstraintForce::execute(void)
{
return Constraint::execute();
}
void ConstraintForce::onChanged(const App::Property* prop)
{
// Note: If we call this at the end, then the arrows are not oriented correctly initially
// because the NormalDirection has not been calculated yet
Constraint::onChanged(prop);
if (prop == &References) {
std::vector<Base::Vector3f> points;
std::vector<Base::Vector3f> normals;
if (getPoints(points, normals)) {
Points.setValues(points); // We don't use the normals because all arrows should have the same direction
Points.touch(); // This triggers ViewProvider::updateData()
}
} else 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();
}
} else if (prop == &NormalDirection) {
// Set a default direction if no direction reference has been given
if (Direction.getValue() == NULL) {
DirectionVector.setValue(NormalDirection.getValue());
naturalDirectionVector = NormalDirection.getValue();
}
}
}

View File

@@ -0,0 +1,69 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINTFORCE_H
#define FEM_CONSTRAINTFORCE_H
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#include "FemConstraint.h"
namespace Fem
{
class AppFemExport ConstraintForce : public Fem::Constraint
{
PROPERTY_HEADER(Fem::ConstraintForce);
public:
/// Constructor
ConstraintForce(void);
App::PropertyFloat Force;
App::PropertyLinkSub Direction;
App::PropertyBool Reversed;
// Read-only (calculated values). These trigger changes in the ViewProvider
App::PropertyVectorList Points;
App::PropertyVector DirectionVector;
/// recalculate the object
virtual App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintForce";
}
protected:
virtual void onChanged(const App::Property* prop);
private:
Base::Vector3f naturalDirectionVector;
};
} //namespace Fem
#endif // FEM_CONSTRAINTFORCE_H

View File

@@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
#include <TopoDS.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
#endif
#include "FemConstraintGear.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::ConstraintGear, Fem::ConstraintBearing);
ConstraintGear::ConstraintGear()
{
ADD_PROPERTY(Diameter,(100.0));
ADD_PROPERTY(Force,(1000.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(1,1,1).Normalize()),"ConstraintGear",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),
"Direction of gear force");
naturalDirectionVector = Base::Vector3f(1,1,1).Normalize();
}
App::DocumentObjectExecReturn *ConstraintGear::execute(void)
{
return ConstraintBearing::execute();
}
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

@@ -0,0 +1,70 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINTGear_H
#define FEM_CONSTRAINTGear_H
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#include "FemConstraintBearing.h"
namespace Fem
{
class AppFemExport ConstraintGear : public Fem::ConstraintBearing
{
PROPERTY_HEADER(Fem::ConstraintGear);
public:
/// Constructor
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);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintGear";
}
protected:
virtual void onChanged(const App::Property* prop);
private:
Base::Vector3f naturalDirectionVector;
};
} //namespace Fem
#endif // FEM_CONSTRAINTGear_H

View File

@@ -0,0 +1,98 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
#include <TopoDS.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
#endif
#include "FemConstraintPulley.h"
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace Fem;
PROPERTY_SOURCE(Fem::ConstraintPulley, Fem::ConstraintGear);
ConstraintPulley::ConstraintPulley()
{
ADD_PROPERTY(OtherDiameter,(100.0));
ADD_PROPERTY(CenterDistance,(500.0));
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(00.0);
Diameter.setValue(300.0);
// calculate initial values of read-only properties
onChanged(&Force);
}
App::DocumentObjectExecReturn *ConstraintPulley::execute(void)
{
return ConstraintBearing::execute();
}
void ConstraintPulley::onChanged(const App::Property* prop)
{
ConstraintGear::onChanged(prop);
if ((prop == &Diameter) || (prop == &OtherDiameter) || (prop == &CenterDistance)) {
if (CenterDistance.getValue() > Precision::Confusion()) {
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

@@ -0,0 +1,73 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef FEM_CONSTRAINTPulley_H
#define FEM_CONSTRAINTPulley_H
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <App/PropertyGeo.h>
#include "FemConstraintGear.h"
namespace Fem
{
class AppFemExport ConstraintPulley : public Fem::ConstraintGear
{
PROPERTY_HEADER(Fem::ConstraintPulley);
public:
/// Constructor
ConstraintPulley(void);
/// 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 BeltAngle;
App::PropertyFloat BeltForce1;
App::PropertyFloat BeltForce2;
/// recalculate the object
virtual App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintPulley";
}
protected:
virtual void onChanged(const App::Property* prop);
};
} //namespace Fem
#endif // FEM_CONSTRAINTPulley_H

View File

@@ -34,6 +34,12 @@
#include "ViewProviderSetElements.h"
#include "ViewProviderSetFaces.h"
#include "ViewProviderSetGeometry.h"
#include "ViewProviderFemConstraint.h"
#include "ViewProviderFemConstraintBearing.h"
#include "ViewProviderFemConstraintFixed.h"
#include "ViewProviderFemConstraintForce.h"
#include "ViewProviderFemConstraintGear.h"
#include "ViewProviderFemConstraintPulley.h"
#include "Workbench.h"
//#include "resources/qrc_Fem.cpp"
@@ -63,16 +69,22 @@ void FemGuiExport initFemGui()
(void) Py_InitModule("FemGui", FemGui_Import_methods); /* mod name, table ptr */
Base::Console().Log("Loading GUI of Fem module... done\n");
// instanciating the commands
// instantiating the commands
CreateFemCommands();
// addition objects
FemGui::Workbench ::init();
FemGui::ViewProviderFemMesh ::init();
FemGui::ViewProviderSetNodes ::init();
FemGui::ViewProviderSetElements ::init();
FemGui::ViewProviderSetFaces ::init();
FemGui::ViewProviderSetGeometry ::init();
FemGui::ViewProviderFemMesh ::init();
FemGui::ViewProviderSetNodes ::init();
FemGui::ViewProviderSetElements ::init();
FemGui::ViewProviderSetFaces ::init();
FemGui::ViewProviderSetGeometry ::init();
FemGui::ViewProviderFemConstraint ::init();
FemGui::ViewProviderFemConstraintBearing ::init();
FemGui::ViewProviderFemConstraintFixed ::init();
FemGui::ViewProviderFemConstraintForce ::init();
FemGui::ViewProviderFemConstraintGear ::init();
FemGui::ViewProviderFemConstraintPulley ::init();
// add resources and reloads the translators
loadFemResource();

View File

@@ -23,10 +23,10 @@ set(FemGui_LIBS
Fem
FreeCADGui
)
if(SMESH_FOUND)
include_directories( ${SMESH_INCLUDE_DIR} )
list( APPEND FemGui_LIBS ${SMESH_LIBRARIES} )
if(SMESH_FOUND)
include_directories( ${SMESH_INCLUDE_DIR} )
list( APPEND FemGui_LIBS ${SMESH_LIBRARIES} )
endif(SMESH_FOUND)
set(FemGui_MOC_HDRS
@@ -34,6 +34,12 @@ set(FemGui_MOC_HDRS
TaskObjectName.h
TaskCreateNodeSet.h
TaskDlgCreateNodeSet.h
TaskFemConstraint.h
TaskFemConstraintBearing.h
TaskFemConstraintFixed.h
TaskFemConstraintForce.h
TaskFemConstraintGear.h
TaskFemConstraintPulley.h
)
fc_wrap_cpp(FemGui_MOC_SRCS ${FemGui_MOC_HDRS})
SOURCE_GROUP("Moc" FILES ${FemGui_MOC_SRCS})
@@ -42,9 +48,37 @@ set(FemGui_UIC_SRCS
Hypothesis.ui
TaskCreateNodeSet.ui
TaskObjectName.ui
TaskFemConstraint.ui
TaskFemConstraintBearing.ui
TaskFemConstraintFixed.ui
TaskFemConstraintForce.ui
)
qt4_wrap_ui(FemGui_UIC_HDRS ${FemGui_UIC_SRCS})
SET(FemGui_DLG_SRCS
${FemGui_UIC_HDRS}
Hypothesis.ui
Hypothesis.cpp
Hypothesis.h
TaskFemConstraint.ui
TaskFemConstraint.cpp
TaskFemConstraint.h
TaskFemConstraintBearing.ui
TaskFemConstraintBearing.cpp
TaskFemConstraintBearing.h
TaskFemConstraintFixed.ui
TaskFemConstraintFixed.cpp
TaskFemConstraintFixed.h
TaskFemConstraintForce.ui
TaskFemConstraintForce.cpp
TaskFemConstraintForce.h
TaskFemConstraintGear.cpp
TaskFemConstraintGear.h
TaskFemConstraintPulley.cpp
TaskFemConstraintPulley.h
)
SOURCE_GROUP("Dialogs" FILES ${FemGui_DLG_SRCS})
qt4_add_resources(FemResource_SRCS Resources/Fem.qrc)
SOURCE_GROUP("Resources" FILES ${FemResource_SRCS})
@@ -62,14 +96,26 @@ SET(FemGui_SRCS_ViewProvider
ViewProviderSetGeometry.h
FemSelectionGate.cpp
FemSelectionGate.h
ViewProviderFemConstraint.cpp
ViewProviderFemConstraint.h
ViewProviderFemConstraintBearing.cpp
ViewProviderFemConstraintBearing.h
ViewProviderFemConstraintFixed.cpp
ViewProviderFemConstraintFixed.h
ViewProviderFemConstraintForce.cpp
ViewProviderFemConstraintForce.h
ViewProviderFemConstraintGear.cpp
ViewProviderFemConstraintGear.h
ViewProviderFemConstraintPulley.cpp
ViewProviderFemConstraintPulley.h
)
SOURCE_GROUP("ViewProvider" FILES ${FemGui_SRCS_ViewProvider})
SET(FemGui_SRCS_TaskBoxes
TaskObjectName.ui
TaskObjectName.ui
TaskObjectName.cpp
TaskObjectName.h
TaskCreateNodeSet.ui
TaskCreateNodeSet.ui
TaskCreateNodeSet.cpp
TaskCreateNodeSet.h
)
@@ -81,6 +127,9 @@ SET(FemGui_SRCS_TaskDlg
Hypothesis.ui
Hypothesis.cpp
Hypothesis.h
TaskFemConstraint.ui
TaskFemConstraint.cpp
TaskFemConstraint.h
)
SOURCE_GROUP("Task_Dialogs" FILES ${FemGui_SRCS_TaskDlg})
@@ -104,6 +153,18 @@ SET(FemGui_SRCS
${FemGui_SRCS_TaskDlg}
${FemGui_SRCS_TaskBoxes}
${FemGui_SRCS_Module}
ViewProviderFemConstraint.cpp
ViewProviderFemConstraint.h
ViewProviderFemConstraintBearing.cpp
ViewProviderFemConstraintBearing.h
ViewProviderFemConstraintFixed.cpp
ViewProviderFemConstraintFixed.h
ViewProviderFemConstraintForce.cpp
ViewProviderFemConstraintForce.h
ViewProviderFemConstraintGear.cpp
ViewProviderFemConstraintGear.h
ViewProviderFemConstraintPulley.cpp
ViewProviderFemConstraintPulley.h
)
@@ -111,11 +172,11 @@ SET(FemGui_SRCS
add_library(FemGui SHARED ${FemGui_SRCS})
target_link_libraries(FemGui ${FemGui_LIBS})
fc_target_copy_resource(FemGui
${CMAKE_SOURCE_DIR}/src/Mod/Fem
${CMAKE_BINARY_DIR}/Mod/Fem
InitGui.py)
fc_target_copy_resource(FemGui
${CMAKE_SOURCE_DIR}/src/Mod/Fem
${CMAKE_BINARY_DIR}/Mod/Fem
InitGui.py)
if(MSVC)
set_target_properties(FemGui PROPERTIES SUFFIX ".pyd")

View File

@@ -52,6 +52,7 @@
#include <Mod/Fem/App/FemMeshObject.h>
#include <Mod/Fem/App/FemSetNodesObject.h>
#include <strstream>
#include <Mod/Fem/App/FemConstraint.h>
#include "Hypothesis.h"
@@ -85,6 +86,162 @@ bool CmdFemCreateFromShape::isActive(void)
return Gui::Selection().countObjectsOfType(type) > 0;
}
DEF_STD_CMD_A(CmdFemConstraintBearing);
CmdFemConstraintBearing::CmdFemConstraintBearing()
: Command("Fem_ConstraintBearing")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Create FEM bearing constraint");
sToolTipText = QT_TR_NOOP("Create FEM constraint for a bearing");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Fem_ConstraintBearing";
}
void CmdFemConstraintBearing::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("FemConstraintBearing");
openCommand("Make FEM constraint for bearing");
doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintBearing\",\"%s\")",FeatName.c_str());
updateActive();
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
}
bool CmdFemConstraintBearing::isActive(void)
{
return hasActiveDocument();
}
DEF_STD_CMD_A(CmdFemConstraintFixed);
CmdFemConstraintFixed::CmdFemConstraintFixed()
: Command("Fem_ConstraintFixed")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Create FEM fixed constraint");
sToolTipText = QT_TR_NOOP("Create FEM constraint for a fixed geometric entity");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Fem_ConstraintFixed";
}
void CmdFemConstraintFixed::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("FemConstraintFixed");
openCommand("Make FEM constraint fixed geometry");
doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintFixed\",\"%s\")",FeatName.c_str());
updateActive();
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
}
bool CmdFemConstraintFixed::isActive(void)
{
return hasActiveDocument();
}
DEF_STD_CMD_A(CmdFemConstraintForce);
CmdFemConstraintForce::CmdFemConstraintForce()
: Command("Fem_ConstraintForce")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Create FEM force constraint");
sToolTipText = QT_TR_NOOP("Create FEM constraint for a force acting on a geometric entity");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Fem_ConstraintForce";
}
void CmdFemConstraintForce::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("FemConstraintForce");
openCommand("Make FEM constraint force on geometry");
doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintForce\",\"%s\")",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Force = 0.0",FeatName.c_str());
updateActive();
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
}
bool CmdFemConstraintForce::isActive(void)
{
return hasActiveDocument();
}
DEF_STD_CMD_A(CmdFemConstraintGear);
CmdFemConstraintGear::CmdFemConstraintGear()
: Command("Fem_ConstraintGear")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Create FEM gear constraint");
sToolTipText = QT_TR_NOOP("Create FEM constraint for a gear");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Fem_ConstraintGear";
}
void CmdFemConstraintGear::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("FemConstraintGear");
openCommand("Make FEM constraint for gear");
doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintGear\",\"%s\")",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Diameter = 100.0",FeatName.c_str());
updateActive();
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
}
bool CmdFemConstraintGear::isActive(void)
{
return hasActiveDocument();
}
DEF_STD_CMD_A(CmdFemConstraintPulley);
CmdFemConstraintPulley::CmdFemConstraintPulley()
: Command("Fem_ConstraintPulley")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Create FEM pulley constraint");
sToolTipText = QT_TR_NOOP("Create FEM constraint for a pulley");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Fem_ConstraintPulley";
}
void CmdFemConstraintPulley::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("FemConstraintPulley");
openCommand("Make FEM constraint for pulley");
doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPulley\",\"%s\")",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());
}
bool CmdFemConstraintPulley::isActive(void)
{
return hasActiveDocument();
}
// #####################################################################################################
@@ -281,4 +438,9 @@ void CreateFemCommands(void)
rcCmdMgr.addCommand(new CmdFemCreateFromShape());
rcCmdMgr.addCommand(new CmdFemCreateNodesSet());
rcCmdMgr.addCommand(new CmdFemDefineNodesSet());
rcCmdMgr.addCommand(new CmdFemConstraintBearing());
rcCmdMgr.addCommand(new CmdFemConstraintFixed());
rcCmdMgr.addCommand(new CmdFemConstraintForce());
rcCmdMgr.addCommand(new CmdFemConstraintGear());
rcCmdMgr.addCommand(new CmdFemConstraintPulley());
}

View File

@@ -2,6 +2,11 @@
<qresource>
<file>icons/Fem_FemMesh.svg</file>
<file>icons/Fem_FemMesh_createnodebypoly.svg</file>
<file>icons/Fem_ConstraintForce.svg</file>
<file>icons/Fem_ConstraintFixed.svg</file>
<file>icons/Fem_ConstraintBearing.svg</file>
<file>icons/Fem_ConstraintGear.svg</file>
<file>icons/Fem_ConstraintPulley.svg</file>
<file>translations/Fem_af.qm</file>
<file>translations/Fem_de.qm</file>
<file>translations/Fem_fi.qm</file>

View File

@@ -0,0 +1,435 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Fem_FemMesh_cylinder_bearing_constraint4.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3705-4"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<linearGradient
id="linearGradient3377-2">
<stop
id="stop3379-2"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-3"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3703-3"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3056">
<stop
id="stop3058"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3060"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="97.369568"
fx="135.38333"
cy="97.369568"
cx="135.38333"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)"
gradientUnits="userSpaceOnUse"
id="radialGradient3074"
xlink:href="#linearGradient3377-2"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3823"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3825"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3841"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3843"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="12.375"
inkscape:cx="32"
inkscape:cy="32"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="964"
inkscape:window-x="-2"
inkscape:window-y="-3"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3618"
transform="matrix(0.50599351,0,0,0.48648068,-35.672941,-25.74129)">
<path
style="fill:url(#radialGradient3705);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.80832386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 171.2941,68.210998 -21.70809,11.437026 12.47229,11.324747 5.1557,31.240899 20.33537,-16.92901 c 9.37869,-11.559736 8.48852,-22.165838 -1.72338,-32.960883 -6.6217,-4.568224 -7.83572,-4.118974 -14.53189,-4.112779 z"
id="rect3522"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 56.954382,8.9166822 C 53.935653,10.441822 49.573711,13.274107 45.130787,15.536369"
id="path2412"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 62.052587,14.762138 c -0.127218,0.135606 -10.177263,6.053378 -11.376976,6.603078"
id="path2414"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 61.489636,21.35739 c -1.899655,1.361624 -5.333235,3.65227 -7.277147,5.10191"
id="path2418"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 45.378285,10.474883 c 5.636128,0.561281 7.279784,1.491002 9.58545,4.465874 2.870922,3.797818 3.526904,5.848823 1.830644,12.314901"
id="path2424-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="arc"
style="fill:none;stroke:none"
id="path3036"
sodipodi:cx="16.722221"
sodipodi:cy="36.055557"
sodipodi:rx="8.0555553"
sodipodi:ry="10.055555"
d="m 24.777777,36.055557 a 8.0555553,10.055555 0 0 1 -1.128969,5.133794"
sodipodi:start="0"
sodipodi:end="0.53581627"
sodipodi:open="true"
transform="matrix(1.0128486,0.03420996,0,1.1009373,5.8744265,-9.7732447)" />
<path
sodipodi:type="arc"
style="fill:#b4b4b4;fill-opacity:1;stroke:#000000;stroke-width:1.28042458999999997;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3808"
sodipodi:cx="19.388889"
sodipodi:cy="40.555557"
sodipodi:rx="18.30003"
sodipodi:ry="13.222222"
d="m 37.688919,40.555557 a 18.30003,13.222222 0 1 1 -36.6000594,0 18.30003,13.222222 0 1 1 36.6000594,0 z"
transform="matrix(1.3441572,0.50475062,-0.12164844,1.7237278,5.1182762,-42.632996)" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3810"
sodipodi:cx="20.944445"
sodipodi:cy="41.611111"
sodipodi:rx="8.0555553"
sodipodi:ry="12.012263"
d="m 29,41.611111 a 8.0555553,12.012263 0 1 1 -16.111111,0 8.0555553,12.012263 0 1 1 16.111111,0 z"
transform="matrix(0.81018431,-0.63333461,0.60783522,0.90117726,-16.974202,12.338046)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,33.992641,21.934694)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-45"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,23.834069,27.254225)" />
<path
style="fill:#f40000;fill-opacity:1;stroke:#000000;stroke-width:1.05597484px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 21.153168,25.667519 C 21.025177,35.351544 25.561842,43.796806 33.286287,44.882935 26.131543,56.77873 6.263446,28.436375 21.153168,25.667519 z"
id="path3908"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:#f40000;fill-opacity:1;stroke:#000000;stroke-width:1.97466362;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 42.886744,59.384848 C 47.339312,56.803801 52.258805,53.102661 55.390107,50.35423 64.813086,34.837583 47.125365,7.7819532 25.168467,9.7931457 21.9589,10.700376 18.728875,11.583255 15.129401,12.569413 40.005982,9.4493588 64.467265,45.676332 42.886744,59.384848 z"
id="path3910"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-8"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,11.380788,22.293009)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-1"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,3.7905184,12.628982)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-2"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,1.5823369,-0.78273632)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-7"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,35.597133,9.8923117)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-9"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,28.78286,-2.1148497)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-14"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,18.240429,-9.1134328)" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:1.86111116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-3"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(0.80789104,0.02728731,0,0.90607726,7.3572329,-9.1684755)" />
<g
id="g3618-4"
transform="matrix(0.50599351,0,0,0.48648068,-61.885654,-8.2655652)" />
<g
id="g3845">
<g
transform="translate(0.55555533,-0.22222218)"
id="g3811">
<path
transform="matrix(0.50599351,0,0,0.48648068,-61.885654,-8.2655652)"
style="fill:url(#radialGradient3841);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.80832386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 162.52779,70.383423 -23.04725,9.71624 23.00405,9.747146 1.50426,35.076691 19.18669,-13.36515 c 6.73538,-10.17164 5.85327,-21.697968 -3.8551,-32.757432 -5.1144,-4.565872 -7.14987,-7.157434 -16.79265,-8.417495 z"
id="rect3522-3"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.50599351,0,0,0.48648068,-61.885654,-8.2655652)"
style="fill:url(#radialGradient3843);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.80832386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 132.82272,84.89331 c 10.75418,-10.005637 21.38515,-6.127815 31.80315,7.238395 8.01925,12.601635 7.23189,20.981435 -0.57918,32.709415 -9.97656,5.54633 -24.96587,2.99222 -33.00616,-9.97927 -5.69827,-10.29304 -6.15159,-21.332455 1.78219,-29.96854 z"
id="rect3520-5"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 16.20194,31.59182 0.05375,21.928308"
id="path2400-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 25.920467,27.206825 c -3.018729,1.525139 -5.388102,2.224723 -9.831027,4.486985"
id="path2412-6"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 32.955269,35.052415 c -0.127219,0.135606 -7.836626,4.886678 -9.036339,5.436379"
id="path2414-8"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 33.1042,41.289049 C 31.204544,42.650673 26.027118,46.11066 24.083206,47.5603"
id="path2418-3"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 3.0537409,37.805779 23.887483,40.53112"
id="path2424-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 23.908616,47.44324 3.310322,44.454882"
id="path2432-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 25.728346,32.193375 c 1.759441,2.263214 7.149518,8.424344 0.775134,16.648131"
id="path2400-7-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 15.571605,28.389271 c 6.072813,-0.100149 7.716092,1.272051 10.32724,3.920744"
id="path2424-3-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2390-1"
d="m 9.0461086,30.888332 0.0051,20.906576"
style="fill:none;stroke:#000000;stroke-width:0.46444172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Fem_fixed_geometry_constraint1.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="9.03125"
inkscape:cx="32"
inkscape:cy="32.055363"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1276"
inkscape:window-height="750"
inkscape:window-x="-13"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3618"
transform="matrix(0.51498391,0,0,0.49033246,-43.844928,-28.337883)">
<path
style="fill:url(#radialGradient3705);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.80832386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 181.23365,60.447364 -41.75311,19.652299 22.79277,9.74401 1.71554,35.079827 34.90073,-21.47145 c 8.77297,-10.605473 11.81226,-24.974574 2.14058,-36.620683 -5.76166,-5.245683 -10.14552,-7.612661 -19.79651,-6.384003 z"
id="rect3522"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient3703);fill-opacity:1;fill-rule:evenodd;stroke:#ff2600;stroke-width:2.80792084999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 132.82272,84.89331 c 10.75418,-10.005637 21.38515,-6.127815 31.80315,7.238395 8.01928,12.601795 7.83274,24.767805 -0.57918,32.709415 -9.97656,5.54633 -24.96587,2.99222 -33.00616,-9.97927 -5.69827,-10.29304 -6.15159,-21.332455 1.78219,-29.96854 z"
id="rect3520"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 28.785325,11.12855 0.0052,21.515011"
id="path2390"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 36.737378,12.499439 36.570635,34.269187"
id="path2400"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 56.372527,2.2112135 C 53.300162,3.7484279 41.698378,10.10061 37.176513,12.380783"
id="path2412"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 61.760695,7.7936612 C 61.631216,7.9303412 44.151611,19.141175 42.930582,19.695228"
id="path2414"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 62.133726,14.965487 C 60.200318,16.337892 47.069308,24.807974 44.205044,26.601271"
id="path2418"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 22.13757,16.880244 20.65028,3.300552"
id="path2424"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 43.362992,26.815464 21.955804,23.581992"
id="path2432"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 36.981657,7.4999087 c 6.180714,-0.100942 7.85319,1.282121 10.423968,3.8930043 1.703939,2.222352 7.189786,8.432262 0.702143,16.721162"
id="path2424-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="arc"
style="fill:#fc0000;fill-opacity:1;stroke:#000000;stroke-width:0.35115141;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3812-6-9"
sodipodi:cx="8.333333"
sodipodi:cy="31"
sodipodi:rx="3.612802"
sodipodi:ry="3.569948"
d="m 11.946135,31 a 3.612802,3.569948 0 1 1 -7.225604,0 3.612802,3.569948 0 1 1 7.225604,0 z"
transform="matrix(2.3057079,0.01441438,1.3432008,0.88771711,-49.53095,16.068104)" />
<path
style="fill:#ff2600;fill-opacity:1;stroke:#000000;stroke-width:0.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 1.5501729,41.854671 1e-7,15.944636 c 4.0192826,4.935847 14.951421,5.673547 19.15571,3.98616 L 20.816609,45.730103 C 19.515769,47.578628 3.8647977,46.492346 1.5501729,41.854671 z"
id="path3800"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#ff2600;fill-opacity:1;stroke:#000000;stroke-width:0.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4.4290657,42.076124 0,-10.186851 c 1.2697887,-4.348714 4.2620171,-5.215101 7.5294113,-5.536332 4.248114,-0.09718 7.584697,4.89505 7.307959,9.522491 l -0.110727,8.747405 c -0.700644,0.514735 -3.488262,0.851874 -4.539792,-0.66436 l 0.221454,-9.079585 c -0.04849,-1.503613 -0.837387,-4.069575 -2.657441,-4.096885 -1.634568,-0.110783 -3.1977552,0.706119 -3.6539785,2.65744 l 0.1107267,9.633217 c -1.0949131,0.664208 -3.6999373,0.100965 -4.2076125,-0.99654 z"
id="path3802"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 43.384578,3.9792341 c 6.180714,-0.100942 7.410283,1.0606677 10.423967,3.893004 C 55.512484,10.09459 60.998331,16.3045 54.510688,24.5934"
id="path2424-3-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Fem_force_on_geometry_constraint1.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-4"
id="radialGradient3703-8"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377-4">
<stop
id="stop3379-3"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-0"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="9.03125"
inkscape:cx="32"
inkscape:cy="32"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1276"
inkscape:window-height="750"
inkscape:window-x="-13"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3618"
transform="matrix(0.51498391,0,0,0.49033246,-43.844928,-28.337883)">
<path
style="fill:url(#radialGradient3705);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.80832386;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 181.23365,60.447364 -42.39814,17.845743 23.4378,11.550566 3.43562,36.434747 33.18065,-22.82637 c 8.77297,-10.605473 11.81226,-24.974574 2.14058,-36.620683 -5.76166,-5.245683 -10.14552,-7.612661 -19.79651,-6.384003 z"
id="rect3522"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient3703);fill-opacity:1;fill-rule:evenodd;stroke:#ff2600;stroke-width:2.80792084999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 132.82272,84.89331 c 10.75418,-10.005637 21.38515,-6.127815 31.80315,7.238395 8.01928,12.601795 7.83274,24.767805 -0.57918,32.709415 -9.97656,5.54633 -24.96587,2.99222 -33.00616,-9.97927 -5.69827,-10.29304 -6.15159,-21.332455 1.78219,-29.96854 z"
id="rect3520"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 28.785325,11.12855 0.0052,21.515011"
id="path2390"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 36.737378,12.499439 36.570635,34.269187"
id="path2400"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 56.372527,2.2112135 C 53.300162,3.7484279 42.030558,9.6577034 37.508693,11.937876"
id="path2412"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 61.760695,7.7936612 C 61.631216,7.9303412 44.705244,18.808995 43.484215,19.363048"
id="path2414"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 62.133726,14.965487 C 60.200318,16.337892 48.065848,24.254341 45.201584,26.047638"
id="path2418"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 22.13757,16.880244 20.65028,3.300552"
id="path2424"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff2600;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 43.362992,26.815464 21.955804,23.581992"
id="path2432"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 36.760204,6.6140955 c 3.744727,-0.8760285 8.074643,2.1679342 10.645421,4.7788175 1.703939,2.222352 7.189786,9.318075 0.702143,17.606975"
id="path2424-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:#ff2600;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 0.55363321,56.692041 11.737024,44.069203 c 1.269788,-1.580547 1.715304,-2.114755 2.989619,-3.653979 -2.284758,-1.979533 -3.598694,-2.523635 -6.2006916,-4.31834 7.0761596,-0.171163 8.8680506,0.05508 15.1695506,0.332181 l 5.314879,14.50519 c -2.927383,-2.167973 -3.827006,-2.630129 -6.6436,-4.318338 -1.557787,1.737623 -2.327923,2.683217 -3.764705,4.429066 L 8.1937713,63.335639 C 4.8843257,60.345868 3.4972946,59.339719 0.55363321,56.692041 z"
id="path3802"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.47040084;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 43.384578,3.9792341 c 6.180714,-0.100942 7.410283,1.0606677 10.423967,3.893004 C 55.512484,10.09459 60.998331,16.3045 54.510688,24.5934"
id="path2424-3-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#7b5600;stroke-width:0.92551678;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 23.825095,12.352013 c 6.041975,-5.3755328 12.014726,-3.2921713 17.867828,3.888831 4.505436,6.77032 4.400633,13.306515 -0.3254,17.573147 -5.605087,2.979768 -14.026467,1.607572 -18.543708,-5.361367 -3.201435,-5.52994 -3.456121,-11.46087 1.00128,-16.100611 z"
id="rect3520-8"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,212 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax1.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraint.h"
#include "TaskFemConstraint.h"
#include <App/Application.h>
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraint.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraint */
TaskFemConstraint::TaskFemConstraint(ViewProviderFemConstraint *ConstraintView,QWidget *parent,const char* pixmapname)
: 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
{
std::string result;
for (std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); i++) {
int pos = i->find_last_of(":");
std::string objStr = "App.ActiveDocument." + i->substr(0, pos);
std::string refStr = "\"" + i->substr(pos+1) + "\"";
result = result + (i != items.begin() ? ", " : "") + "(" + objStr + "," + refStr + ")";
}
return result;
}
void TaskFemConstraint::onReferenceDeleted(const int row) {
Fem::Constraint* pcConstraint = static_cast<Fem::Constraint*>(ConstraintView->getObject());
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
Objects.erase(Objects.begin() + row);
SubElements.erase(SubElements.begin() + row);
pcConstraint->References.setValues(Objects, SubElements);
}
void TaskFemConstraint::onButtonReference(const bool pressed) {
if (pressed)
selectionMode = selref;
else
selectionMode = selnone;
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());
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraint::accept()
{
std::string name = ConstraintView->getObject()->getNameInDocument();
try {
std::string refs = parameter->getReferences();
if (!refs.empty()) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.References = [%s]", name.c_str(), refs.c_str());
} else {
QMessageBox::warning(parameter, tr("Input error"), tr("You must specify at least one reference"));
return false;
}
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
if (!ConstraintView->getObject()->isValid())
throw Base::Exception(ConstraintView->getObject()->getStatusString());
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
Gui::Command::commitCommand();
}
catch (const Base::Exception& e) {
QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what()));
return false;
}
return true;
}
bool TaskDlgFemConstraint::reject()
{
// roll back the changes
Gui::Command::abortCommand();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
return true;
}
#include "moc_TaskFemConstraint.cpp"

View File

@@ -0,0 +1,107 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraint_H
#define GUI_TASKVIEW_TaskFemConstraint_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "ViewProviderFemConstraint.h"
namespace FemGui {
class TaskFemConstraint : public Gui::TaskView::TaskBox, public Gui::SelectionObserver
{
Q_OBJECT
public:
TaskFemConstraint(ViewProviderFemConstraint *ConstraintView,QWidget *parent = 0,const char* pixmapname = "");
virtual ~TaskFemConstraint() {}
virtual const std::string getReferences(void) const {}
const std::string getReferences(const std::vector<std::string>& items) const;
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&) {}
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
class TaskDlgFemConstraint : public Gui::TaskView::TaskDialog
{
Q_OBJECT
public:
/*
/// is called the TaskView when the dialog is opened
virtual void open() {}
/// is called by the framework if an button is clicked which has no accept or reject role
virtual void clicked(int) {}
/// is called by the framework if the dialog is accepted (Ok)
*/
virtual bool accept();
/// is called by the framework if the dialog is rejected (Cancel)
virtual bool reject();
/// is called by the framework if the user presses the help button
virtual bool isAllowedAlterDocument(void) const
{ return false; }
/// returns for Close and Help button
virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const
{ return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; }
ViewProviderFemConstraint* getConstraintView() const
{ return ConstraintView; }
protected:
ViewProviderFemConstraint *ConstraintView;
TaskFemConstraint *parameter;
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraint_H

View File

@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskFemConstraint</class>
<widget class="QWidget" name="TaskFemConstraint">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>461</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="comboType"/>
</item>
<item>
<widget class="QPushButton" name="buttonReference">
<property name="text">
<string>Add reference</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listReferences"/>
</item>
<item>
<layout class="QHBoxLayout" name="layoutForce">
<item>
<widget class="QLabel" name="labelForce">
<property name="text">
<string>Load [N]</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>500.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDistance_2">
<item>
<widget class="QLabel" name="labelDiameter">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDiameter">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDistance_3">
<item>
<widget class="QLabel" name="labelOtherDia">
<property name="text">
<string>Other diameter</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinOtherDia">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>200.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDistance_4">
<item>
<widget class="QLabel" name="labelCenterDistance">
<property name="text">
<string>Center distance</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinCenterDistance">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>500.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDirection">
<item>
<widget class="QPushButton" name="buttonDirection">
<property name="text">
<string>Direction</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineDirection"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkReverse">
<property name="text">
<string>Reverse direction</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="layoutLocation">
<item>
<widget class="QPushButton" name="buttonLocation">
<property name="text">
<string>Location</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineLocation"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDistance">
<item>
<widget class="QLabel" name="labelDistance">
<property name="text">
<string>Distance</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDistance">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>56</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,356 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax1.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintBearing.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>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraintBearing.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraintBearing */
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_TaskFemConstraintBearing();
ui->setupUi(proxy);
QMetaObject::connectSlotsByName(this);
// Create a context menu for the listview of the references
QAction* action = new QAction(tr("Delete"), ui->listReferences);
action->connect(action, SIGNAL(triggered()),
this, SLOT(onReferenceDeleted()));
ui->listReferences->addAction(action);
ui->listReferences->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(ui->spinDistance, SIGNAL(valueChanged(double)),
this, SLOT(onDistanceChanged(double)));
connect(ui->buttonReference, SIGNAL(pressed()),
this, SLOT(onButtonReference()));
connect(ui->buttonLocation, SIGNAL(pressed()),
this, SLOT(onButtonLocation()));
connect(ui->checkAxial, SIGNAL(toggled(bool)),
this, SLOT(onCheckAxial(bool)));
this->groupLayout()->addWidget(proxy);
// Temporarily prevent unnecessary feature recomputes
ui->spinDistance->blockSignals(true);
ui->listReferences->blockSignals(true);
ui->buttonReference->blockSignals(true);
ui->buttonLocation->blockSignals(true);
ui->checkAxial->blockSignals(true);
// Get the feature data
Fem::ConstraintBearing* pcConstraint = static_cast<Fem::ConstraintBearing*>(ConstraintView->getObject());
double d = pcConstraint->Dist.getValue();
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
std::vector<std::string> locStrings = pcConstraint->Location.getSubValues();
QString loc;
if (!locStrings.empty())
loc = makeRefText(pcConstraint->Location.getValue(), locStrings.front());
bool axialfree = pcConstraint->AxialFree.getValue();
// Fill data into dialog elements
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++)
ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i]));
if (Objects.size() > 0)
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
ui->lineLocation->setText(loc);
ui->checkAxial->setChecked(axialfree);
// 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);
ui->buttonReference->blockSignals(false);
ui->buttonLocation->blockSignals(false);
ui->checkAxial->blockSignals(false);
onButtonReference(true);
}
void TaskFemConstraintBearing::onSelectionChanged(const Gui::SelectionChanges& 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;
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);
TopoDS_Shape ref = feat->Shape.getShape().getSubShape(subName.c_str());
if (selectionMode == selref) {
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
if (Objects.size() > 0) {
QMessageBox::warning(this, tr("Selection error"), tr("Please use only a single reference for bearing constraint"));
return;
}
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"));
return;
}
// add the new reference
Objects.push_back(obj);
SubElements.push_back(subName);
pcConstraint->References.setValues(Objects,SubElements);
ui->listReferences->addItem(makeRefText(obj, subName));
// Turn off reference selection mode
onButtonReference(false);
} else if (selectionMode == selloc) {
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;
}
std::vector<std::string> references(1,subName);
pcConstraint->Location.setValue(obj, references);
ui->lineLocation->setText(makeRefText(obj, subName));
// Turn off location selection mode
onButtonLocation(false);
}
Gui::Selection().clearSelection();
}
}
void TaskFemConstraintBearing::onDistanceChanged(double l)
{
Fem::ConstraintBearing* pcConstraint = static_cast<Fem::ConstraintBearing*>(ConstraintView->getObject());
pcConstraint->Dist.setValue((float)l);
}
void TaskFemConstraintBearing::onReferenceDeleted() {
int row = ui->listReferences->currentIndex().row();
TaskFemConstraint::onReferenceDeleted(row);
ui->listReferences->model()->removeRow(row);
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
}
void TaskFemConstraintBearing::onButtonLocation(const bool pressed) {
if (pressed) {
selectionMode = selloc;
} else {
selectionMode = selnone;
}
ui->buttonLocation->setChecked(pressed);
Gui::Selection().clearSelection();
}
void TaskFemConstraintBearing::onCheckAxial(const bool pressed)
{
Fem::ConstraintBearing* pcConstraint = static_cast<Fem::ConstraintBearing*>(ConstraintView->getObject());
pcConstraint->AxialFree.setValue(pressed);
}
double TaskFemConstraintBearing::getDistance(void) const
{
return ui->spinDistance->value();
}
const std::string TaskFemConstraintBearing::getReferences() const
{
int rows = ui->listReferences->model()->rowCount();
std::vector<std::string> items;
for (int r = 0; r < rows; r++)
items.push_back(ui->listReferences->item(r)->text().toStdString());
return TaskFemConstraint::getReferences(items);
}
const std::string TaskFemConstraintBearing::getLocationName(void) const
{
std::string loc = ui->lineLocation->text().toStdString();
if (loc.empty())
return "";
int pos = loc.find_last_of(":");
return loc.substr(0, pos).c_str();
}
const std::string TaskFemConstraintBearing::getLocationObject(void) const
{
std::string loc = ui->lineLocation->text().toStdString();
if (loc.empty())
return "";
int pos = loc.find_last_of(":");
return loc.substr(pos+1).c_str();
}
bool TaskFemConstraintBearing::getAxial() const
{
return ui->checkAxial->isChecked();
}
TaskFemConstraintBearing::~TaskFemConstraintBearing()
{
delete ui;
}
void TaskFemConstraintBearing::changeEvent(QEvent *e)
{
TaskBox::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->spinDistance->blockSignals(true);
ui->retranslateUi(proxy);
ui->spinDistance->blockSignals(false);
}
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgFemConstraintBearing::TaskDlgFemConstraintBearing(ViewProviderFemConstraintBearing *ConstraintView)
{
this->ConstraintView = ConstraintView;
assert(ConstraintView);
this->parameter = new TaskFemConstraintBearing(ConstraintView);
Content.push_back(parameter);
}
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraintBearing::accept()
{
std::string name = ConstraintView->getObject()->getNameInDocument();
const TaskFemConstraintBearing* parameterBearing = static_cast<const TaskFemConstraintBearing*>(parameter);
try {
//Gui::Command::openCommand("FEM force constraint changed");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Dist = %f",name.c_str(), parameterBearing->getDistance());
std::string locname = parameterBearing->getLocationName().data();
std::string locobj = parameterBearing->getLocationObject().data();
if (!locname.empty()) {
QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])");
buf = buf.arg(QString::fromStdString(locname));
buf = buf.arg(QString::fromStdString(locobj));
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Location = %s", name.c_str(), buf.toStdString().c_str());
} else {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Location = None", name.c_str());
}
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.AxialFree = %s", name.c_str(), parameterBearing->getAxial() ? "True" : "False");
}
catch (const Base::Exception& e) {
QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what()));
return false;
}
return TaskDlgFemConstraint::accept();
}
#include "moc_TaskFemConstraintBearing.cpp"

View File

@@ -0,0 +1,92 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraintBearing_H
#define GUI_TASKVIEW_TaskFemConstraintBearing_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "TaskFemConstraint.h"
#include "ViewProviderFemConstraintBearing.h"
class Ui_TaskFemConstraintBearing;
namespace App {
class Property;
}
namespace Gui {
class ViewProvider;
}
namespace FemGui {
class TaskFemConstraintBearing : public TaskFemConstraint
{
Q_OBJECT
public:
TaskFemConstraintBearing(ViewProviderFemConstraint *ConstraintView, QWidget *parent = 0,
const char* pixmapname = "Fem_ConstraintBearing");
virtual ~TaskFemConstraintBearing();
double getDistance(void) const;
virtual const std::string getReferences() const;
const std::string getLocationName(void) const;
const std::string getLocationObject(void) const;
bool getAxial(void) const;
private Q_SLOTS:
void onReferenceDeleted(void);
void onDistanceChanged(double l);
void onButtonLocation(const bool pressed = true);
void onCheckAxial(bool);
protected:
virtual void changeEvent(QEvent *e);
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
protected:
Ui_TaskFemConstraintBearing* ui;
};
/// simulation dialog for the TaskView
class TaskDlgFemConstraintBearing : public TaskDlgFemConstraint
{
Q_OBJECT
public:
TaskDlgFemConstraintBearing() {}
TaskDlgFemConstraintBearing(ViewProviderFemConstraintBearing *ConstraintView);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraintBearing_H

View File

@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskFemConstraintBearing</class>
<widget class="QWidget" name="TaskFemConstraintBearing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="buttonReference">
<property name="text">
<string>Add reference</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listReferences"/>
</item>
<item>
<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>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDiameter">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_6">
<item>
<widget class="QLabel" name="labelOtherDiameter">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Other pulley dia</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinOtherDiameter">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDiameter_7">
<item>
<widget class="QLabel" name="labelCenterDistance">
<property name="text">
<string>Center distance</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinCenterDistance">
<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_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>-360.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>
<widget class="QPushButton" name="buttonLocation">
<property name="text">
<string>Location</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineLocation"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDistance">
<item>
<widget class="QLabel" name="labelDistance">
<property name="text">
<string>Distance</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDistance">
<property name="minimum">
<double>-99999.000000000000000</double>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>56</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,217 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax1.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraintFixed.h"
#include "TaskFemConstraintFixed.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>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraintFixed.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraintFixed */
TaskFemConstraintFixed::TaskFemConstraintFixed(ViewProviderFemConstraintFixed *ConstraintView,QWidget *parent)
: TaskFemConstraint(ConstraintView, parent, "Fem_ConstraintFixed")
{
// we need a separate container widget to add all controls to
proxy = new QWidget(this);
ui = new Ui_TaskFemConstraintFixed();
ui->setupUi(proxy);
QMetaObject::connectSlotsByName(this);
// Create a context menu for the listview of the references
QAction* action = new QAction(tr("Delete"), ui->listReferences);
action->connect(action, SIGNAL(triggered()),
this, SLOT(onReferenceDeleted()));
ui->listReferences->addAction(action);
ui->listReferences->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(ui->buttonReference, SIGNAL(pressed()),
this, SLOT(onButtonReference()));
this->groupLayout()->addWidget(proxy);
// Temporarily prevent unnecessary feature recomputes
ui->listReferences->blockSignals(true);
ui->buttonReference->blockSignals(true);
// Get the feature data
Fem::ConstraintFixed* pcConstraint = static_cast<Fem::ConstraintFixed*>(ConstraintView->getObject());
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
// Fill data into dialog elements
ui->listReferences->clear();
for (int i = 0; i < Objects.size(); i++)
ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i]));
if (Objects.size() > 0)
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
ui->listReferences->blockSignals(false);
ui->buttonReference->blockSignals(false);
// Selection mode can be always on since there is nothing else in the UI
onButtonReference(true);
}
void TaskFemConstraintFixed::onSelectionChanged(const Gui::SelectionChanges& 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::ConstraintFixed* pcConstraint = static_cast<Fem::ConstraintFixed*>(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 == selref) {
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
// Ensure we don't have mixed reference types
if (SubElements.size() > 0) {
if (subName.substr(0,4) != SubElements.front().substr(0,4)) {
QMessageBox::warning(this, tr("Selection error"), tr("Mixed shape types are not possible. Use a second constraint instead"));
return;
}
} else {
if ((subName.substr(0,4) != "Face") && (subName.substr(0,4) != "Edge") && (subName.substr(0,6) != "Vertex")) {
QMessageBox::warning(this, tr("Selection error"), tr("Only faces, edges and vertices can be picked"));
return;
}
}
// Avoid duplicates
int pos = 0;
for (; pos < Objects.size(); pos++)
if (obj == Objects[pos])
break;
if (pos != Objects.size())
if (subName == SubElements[pos])
return;
// add the new reference
Objects.push_back(obj);
SubElements.push_back(subName);
pcConstraint->References.setValues(Objects,SubElements);
ui->listReferences->addItem(makeRefText(obj, subName));
}
Gui::Selection().clearSelection();
}
}
void TaskFemConstraintFixed::onReferenceDeleted() {
int row = ui->listReferences->currentIndex().row();
TaskFemConstraint::onReferenceDeleted(row);
ui->listReferences->model()->removeRow(row);
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
}
const std::string TaskFemConstraintFixed::getReferences() const
{
int rows = ui->listReferences->model()->rowCount();
std::vector<std::string> items;
for (int r = 0; r < rows; r++)
items.push_back(ui->listReferences->item(r)->text().toStdString());
return TaskFemConstraint::getReferences(items);
}
TaskFemConstraintFixed::~TaskFemConstraintFixed()
{
delete ui;
}
void TaskFemConstraintFixed::changeEvent(QEvent *e)
{
TaskBox::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(proxy);
}
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgFemConstraintFixed::TaskDlgFemConstraintFixed(ViewProviderFemConstraintFixed *ConstraintView)
{
this->ConstraintView = ConstraintView;
assert(ConstraintView);
this->parameter = new TaskFemConstraintFixed(ConstraintView);;
Content.push_back(parameter);
}
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraintFixed::accept()
{
return TaskDlgFemConstraint::accept();
}
#include "moc_TaskFemConstraintFixed.cpp"

View File

@@ -0,0 +1,84 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraintFixed_H
#define GUI_TASKVIEW_TaskFemConstraintFixed_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "TaskFemConstraint.h"
#include "ViewProviderFemConstraintFixed.h"
class Ui_TaskFemConstraintFixed;
namespace App {
class Property;
}
namespace Gui {
class ViewProvider;
}
namespace FemGui {
class TaskFemConstraintFixed : public TaskFemConstraint
{
Q_OBJECT
public:
TaskFemConstraintFixed(ViewProviderFemConstraintFixed *ConstraintView,QWidget *parent = 0);
virtual ~TaskFemConstraintFixed();
virtual const std::string getReferences() const;
private Q_SLOTS:
void onReferenceDeleted(void);
protected:
virtual void changeEvent(QEvent *e);
private:
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
private:
Ui_TaskFemConstraintFixed* ui;
};
/// simulation dialog for the TaskView
class TaskDlgFemConstraintFixed : public TaskDlgFemConstraint
{
Q_OBJECT
public:
TaskDlgFemConstraintFixed(ViewProviderFemConstraintFixed *ConstraintView);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraintFixed_H

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskFemConstraintFixed</class>
<widget class="QWidget" name="TaskFemConstraintFixed">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>233</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="buttonReference">
<property name="text">
<string>Add reference</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listReferences"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>56</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,363 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax1.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraintForce.h"
#include "TaskFemConstraintForce.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>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraintForce.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraintForce */
TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce *ConstraintView,QWidget *parent)
: TaskFemConstraint(ConstraintView, parent, "Fem_ConstraintForce")
{
// we need a separate container widget to add all controls to
proxy = new QWidget(this);
ui = new Ui_TaskFemConstraintForce();
ui->setupUi(proxy);
QMetaObject::connectSlotsByName(this);
// Create a context menu for the listview of the references
QAction* action = new QAction(tr("Delete"), ui->listReferences);
action->connect(action, SIGNAL(triggered()),
this, SLOT(onReferenceDeleted()));
ui->listReferences->addAction(action);
ui->listReferences->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(ui->spinForce, SIGNAL(valueChanged(double)),
this, SLOT(onForceChanged(double)));
connect(ui->buttonReference, SIGNAL(pressed()),
this, SLOT(onButtonReference()));
connect(ui->buttonDirection, SIGNAL(pressed()),
this, SLOT(onButtonDirection()));
connect(ui->checkReverse, SIGNAL(toggled(bool)),
this, SLOT(onCheckReverse(bool)));
this->groupLayout()->addWidget(proxy);
// Temporarily prevent unnecessary feature recomputes
ui->spinForce->blockSignals(true);
ui->listReferences->blockSignals(true);
ui->buttonReference->blockSignals(true);
ui->buttonDirection->blockSignals(true);
ui->checkReverse->blockSignals(true);
// Get the feature data
Fem::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
double f = pcConstraint->Force.getValue();
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
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->spinForce->setMinimum(0);
ui->spinForce->setMaximum(FLOAT_MAX);
ui->spinForce->setValue(f);
ui->listReferences->clear();
for (int i = 0; i < Objects.size(); i++)
ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i]));
if (Objects.size() > 0)
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
ui->lineDirection->setText(dir.isEmpty() ? tr("") : dir);
ui->checkReverse->setChecked(reversed);
ui->spinForce->blockSignals(false);
ui->listReferences->blockSignals(false);
ui->buttonReference->blockSignals(false);
ui->buttonDirection->blockSignals(false);
ui->checkReverse->blockSignals(false);
updateUI();
}
void TaskFemConstraintForce::updateUI()
{
if (ui->listReferences->model()->rowCount() == 0) {
// Go into reference selection mode if no reference has been selected yet
onButtonReference(true);
return;
}
std::string ref = ui->listReferences->item(0)->text().toStdString();
int pos = ref.find_last_of(":");
if (ref.substr(pos+1, 6) == "Vertex")
ui->labelForce->setText(tr("Force [N]"));
else if (ref.substr(pos+1, 4) == "Edge")
ui->labelForce->setText(tr("Force [N/mm]"));
else if (ref.substr(pos+1, 4) == "Face")
ui->labelForce->setText(tr("Force [N/mm²]"));
}
void TaskFemConstraintForce::onSelectionChanged(const Gui::SelectionChanges& 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::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(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 == selref) {
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
// Ensure we don't have mixed reference types
if (SubElements.size() > 0) {
if (subName.substr(0,4) != SubElements.front().substr(0,4)) {
QMessageBox::warning(this, tr("Selection error"), tr("Mixed shape types are not possible. Use a second constraint instead"));
return;
}
} else {
if ((subName.substr(0,4) != "Face") && (subName.substr(0,4) != "Edge") && (subName.substr(0,6) != "Vertex")) {
QMessageBox::warning(this, tr("Selection error"), tr("Only faces, edges and vertices can be picked"));
return;
}
}
// Avoid duplicates
int pos = 0;
for (; pos < Objects.size(); pos++)
if (obj == Objects[pos])
break;
if (pos != Objects.size())
if (subName == SubElements[pos])
return;
// add the new reference
Objects.push_back(obj);
SubElements.push_back(subName);
pcConstraint->References.setValues(Objects,SubElements);
ui->listReferences->addItem(makeRefText(obj, subName));
// Turn off reference selection mode
onButtonReference(false);
} else 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();
updateUI();
}
}
void TaskFemConstraintForce::onForceChanged(double f)
{
Fem::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
pcConstraint->Force.setValue((float)f);
}
void TaskFemConstraintForce::onReferenceDeleted() {
int row = ui->listReferences->currentIndex().row();
TaskFemConstraint::onReferenceDeleted(row);
ui->listReferences->model()->removeRow(row);
ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
}
void TaskFemConstraintForce::onButtonDirection(const bool pressed) {
if (pressed) {
selectionMode = seldir;
} else {
selectionMode = selnone;
}
ui->buttonDirection->setChecked(pressed);
Gui::Selection().clearSelection();
}
void TaskFemConstraintForce::onCheckReverse(const bool pressed)
{
Fem::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
pcConstraint->Reversed.setValue(pressed);
}
double TaskFemConstraintForce::getForce(void) const
{
return ui->spinForce->value();
}
const std::string TaskFemConstraintForce::getReferences() const
{
int rows = ui->listReferences->model()->rowCount();
std::vector<std::string> items;
for (int r = 0; r < rows; r++)
items.push_back(ui->listReferences->item(r)->text().toStdString());
return TaskFemConstraint::getReferences(items);
}
const std::string TaskFemConstraintForce::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 TaskFemConstraintForce::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 TaskFemConstraintForce::getReverse() const
{
return ui->checkReverse->isChecked();
}
TaskFemConstraintForce::~TaskFemConstraintForce()
{
delete ui;
}
void TaskFemConstraintForce::changeEvent(QEvent *e)
{
TaskBox::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->spinForce->blockSignals(true);
ui->retranslateUi(proxy);
ui->spinForce->blockSignals(false);
}
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgFemConstraintForce::TaskDlgFemConstraintForce(ViewProviderFemConstraintForce *ConstraintView)
{
this->ConstraintView = ConstraintView;
assert(ConstraintView);
this->parameter = new TaskFemConstraintForce(ConstraintView);;
Content.push_back(parameter);
}
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraintForce::accept()
{
std::string name = ConstraintView->getObject()->getNameInDocument();
const TaskFemConstraintForce* parameterForce = static_cast<const TaskFemConstraintForce*>(parameter);
try {
//Gui::Command::openCommand("FEM force constraint changed");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Force = %f",name.c_str(), parameterForce->getForce());
std::string dirname = parameterForce->getDirectionName().data();
std::string dirobj = parameterForce->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(), parameterForce->getReverse() ? "True" : "False");
}
catch (const Base::Exception& e) {
QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what()));
return false;
}
return TaskDlgFemConstraint::accept();
}
#include "moc_TaskFemConstraintForce.cpp"

View File

@@ -0,0 +1,92 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraintForce_H
#define GUI_TASKVIEW_TaskFemConstraintForce_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "TaskFemConstraint.h"
#include "ViewProviderFemConstraintForce.h"
class Ui_TaskFemConstraintForce;
namespace App {
class Property;
}
namespace Gui {
class ViewProvider;
}
namespace FemGui {
class TaskFemConstraintForce : public TaskFemConstraint
{
Q_OBJECT
public:
TaskFemConstraintForce(ViewProviderFemConstraintForce *ConstraintView,QWidget *parent = 0);
virtual ~TaskFemConstraintForce();
double getForce(void) const;
virtual const std::string getReferences() const;
const std::string getDirectionName(void) const;
const std::string getDirectionObject(void) const;
bool getReverse(void) const;
private Q_SLOTS:
void onReferenceDeleted(void);
void onForceChanged(double);
void onButtonDirection(const bool pressed = true);
void onCheckReverse(bool);
protected:
virtual void changeEvent(QEvent *e);
private:
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
void updateUI();
private:
Ui_TaskFemConstraintForce* ui;
};
/// simulation dialog for the TaskView
class TaskDlgFemConstraintForce : public TaskDlgFemConstraint
{
Q_OBJECT
public:
TaskDlgFemConstraintForce(ViewProviderFemConstraintForce *ConstraintView);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraintForce_H

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskFemConstraintForce</class>
<widget class="QWidget" name="TaskFemConstraintForce">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>233</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="buttonReference">
<property name="text">
<string>Add reference</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listReferences"/>
</item>
<item>
<layout class="QHBoxLayout" name="layoutForce">
<item>
<widget class="QLabel" name="labelForce">
<property name="text">
<string>Load [N]</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>500.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layoutDirection">
<item>
<widget class="QPushButton" name="buttonDirection">
<property name="text">
<string>Direction</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineDirection"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkReverse">
<property name="text">
<string>Reverse direction</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>56</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,315 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
/*
# include <sstream>
# include <QRegExp>
# include <QTextStream>
# include <QMessageBox>
# include <Precision.hxx>*/
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <Geom_Plane.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax1.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Line.hxx>
# include <gp_Lin.hxx>
#endif
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintGear.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>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraintGear.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraintGear */
TaskFemConstraintGear::TaskFemConstraintGear(ViewProviderFemConstraint *ConstraintView,QWidget *parent, const char *pixmapname)
: TaskFemConstraintBearing(ConstraintView, parent, pixmapname)
{
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());
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(FLOAT_MAX);
ui->spinDiameter->setValue(dia);
ui->spinForce->setMinimum(0);
ui->spinForce->setMaximum(FLOAT_MAX);
ui->spinForce->setValue(force);
ui->spinForceAngle->setMinimum(-360);
ui->spinForceAngle->setMaximum(360);
ui->spinForceAngle->setValue(angle);
ui->lineDirection->setText(dir);
ui->checkReversed->setChecked(reversed);
// 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);
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();
}
void TaskFemConstraintGear::changeEvent(QEvent *e)
{
TaskBox::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->spinDiameter->blockSignals(true);
ui->spinForce->blockSignals(true);
ui->spinForceAngle->blockSignals(true);
ui->checkReversed->blockSignals(true);
ui->retranslateUi(proxy);
ui->spinDiameter->blockSignals(false);
ui->spinForce->blockSignals(false);
ui->spinForceAngle->blockSignals(true);
ui->checkReversed->blockSignals(false);
}
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgFemConstraintGear::TaskDlgFemConstraintGear(ViewProviderFemConstraintGear *ConstraintView)
{
this->ConstraintView = ConstraintView;
assert(ConstraintView);
this->parameter = new TaskFemConstraintGear(ConstraintView, 0, "Fem_ConstraintGear");
Content.push_back(parameter);
}
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraintGear::accept()
{
std::string name = ConstraintView->getObject()->getNameInDocument();
const TaskFemConstraintGear* parameterGear = static_cast<const TaskFemConstraintGear*>(parameter);
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;
}
return TaskDlgFemConstraintBearing::accept();
}
#include "moc_TaskFemConstraintGear.cpp"

View File

@@ -0,0 +1,79 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraintGear_H
#define GUI_TASKVIEW_TaskFemConstraintGear_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "TaskFemConstraintBearing.h"
#include "ViewProviderFemConstraintGear.h"
namespace FemGui {
class TaskFemConstraintGear : public TaskFemConstraintBearing
{
Q_OBJECT
public:
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
class TaskDlgFemConstraintGear : public TaskDlgFemConstraintBearing
{
Q_OBJECT
public:
TaskDlgFemConstraintGear() {}
TaskDlgFemConstraintGear(ViewProviderFemConstraintGear *ConstraintView);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraintGear_H

View File

@@ -0,0 +1,210 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include "ui_TaskFemConstraintBearing.h"
#include "TaskFemConstraintPulley.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>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Mod/Fem/App/FemConstraintPulley.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
using namespace FemGui;
using namespace Gui;
/* TRANSLATOR FemGui::TaskFemConstraintPulley */
TaskFemConstraintPulley::TaskFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView,QWidget *parent)
: TaskFemConstraintGear(ConstraintView, parent, "Fem_ConstraintPulley")
{
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->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 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->spinOtherDiameter->setMinimum(0);
ui->spinOtherDiameter->setMaximum(FLOAT_MAX);
ui->spinOtherDiameter->setValue(otherdia);
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
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->spinOtherDiameter->blockSignals(false);
ui->spinCenterDistance->blockSignals(false);
ui->checkIsDriven->blockSignals(false);
ui->spinTensionForce->blockSignals(false);
}
void TaskFemConstraintPulley::onOtherDiameterChanged(double l)
{
Fem::ConstraintPulley* pcConstraint = static_cast<Fem::ConstraintPulley*>(ConstraintView->getObject());
pcConstraint->OtherDiameter.setValue((float)l);
}
void TaskFemConstraintPulley::onCenterDistanceChanged(double l)
{
Fem::ConstraintPulley* pcConstraint = static_cast<Fem::ConstraintPulley*>(ConstraintView->getObject());
pcConstraint->CenterDistance.setValue((float)l);
}
void TaskFemConstraintPulley::onTensionForceChanged(double force)
{
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
{
return ui->spinOtherDiameter->value();
}
double TaskFemConstraintPulley::getCenterDistance(void) const
{
return ui->spinCenterDistance->value();
}
void TaskFemConstraintPulley::changeEvent(QEvent *e)
{
TaskBox::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->spinOtherDiameter->blockSignals(true);
ui->spinCenterDistance->blockSignals(true);
ui->checkIsDriven->blockSignals(true);
ui->spinTensionForce->blockSignals(true);
ui->retranslateUi(proxy);
ui->spinOtherDiameter->blockSignals(false);
ui->spinCenterDistance->blockSignals(false);
ui->checkIsDriven->blockSignals(false);
ui->spinTensionForce->blockSignals(false);
}
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgFemConstraintPulley::TaskDlgFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView)
{
this->ConstraintView = ConstraintView;
assert(ConstraintView);
this->parameter = new TaskFemConstraintPulley(ConstraintView);;
Content.push_back(parameter);
}
//==== calls from the TaskView ===============================================================
bool TaskDlgFemConstraintPulley::accept()
{
std::string name = ConstraintView->getObject()->getNameInDocument();
const TaskFemConstraintPulley* parameterPulley = static_cast<const TaskFemConstraintPulley*>(parameter);
try {
//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 TaskDlgFemConstraintGear::accept();
}
#include "moc_TaskFemConstraintPulley.cpp"

View File

@@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskFemConstraintPulley_H
#define GUI_TASKVIEW_TaskFemConstraintPulley_H
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
#include <Gui/TaskView/TaskDialog.h>
#include "TaskFemConstraintGear.h"
#include "ViewProviderFemConstraintPulley.h"
namespace FemGui {
class TaskFemConstraintPulley : public TaskFemConstraintGear
{
Q_OBJECT
public:
TaskFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView,QWidget *parent = 0);
double getOtherDiameter(void) const;
double getCenterDistance(void) const;
double getTensionForce(void) const;
double getTorque(void) const;
bool getIsDriven(void) const;
private Q_SLOTS:
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 TaskDlgFemConstraintGear
{
Q_OBJECT
public:
TaskDlgFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
};
} //namespace FemGui
#endif // GUI_TASKVIEW_TaskFemConstraintPulley_H

View File

@@ -0,0 +1,439 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoFontStyle.h>
# include <Inventor/nodes/SoText2.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoCylinder.h>
# include <Inventor/nodes/SoCone.h>
# include <Inventor/nodes/SoCube.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoComplexity.h>
#endif
#include "ViewProviderFemConstraint.h"
#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>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraint, Gui::ViewProviderDocumentObject)
ViewProviderFemConstraint::ViewProviderFemConstraint()
{
ADD_PROPERTY(TextColor,(0.0f,0.0f,0.0f));
ADD_PROPERTY(FaceColor,(1.0f,0.0f,0.2f));
ADD_PROPERTY(ShapeColor,(1.0f,0.0f,0.2f));
ADD_PROPERTY(FontSize,(18));
ADD_PROPERTY(DistFactor,(1.0));
ADD_PROPERTY(Mirror,(false));
pFont = new SoFontStyle();
pFont->ref();
pLabel = new SoText2();
pLabel->ref();
pTextColor = new SoBaseColor();
pTextColor->ref();
pMaterials = new SoMaterial();
pMaterials->ref();
pMaterials->diffuseColor.setValue(1.0f, 0.0f, 0.2f);
pMaterials->transparency.setValue(0.1);
//pMaterials->ambientColor.setValue(0.8f, 0.8f, 0.8f);
//pMaterials->shininess.setValue(1.0);
pShapeSep = new SoSeparator();
pShapeSep->ref();
TextColor.touch();
FontSize.touch();
FaceColor.touch();
wizardWidget = NULL;
wizardSubLayout = NULL;
constraintDialog = NULL;
}
ViewProviderFemConstraint::~ViewProviderFemConstraint()
{
pFont->unref();
pLabel->unref();
pTextColor->unref();
pMaterials->unref();
pShapeSep->unref();
}
void ViewProviderFemConstraint::attach(App::DocumentObject* pcObject)
{
ViewProviderDocumentObject::attach(pcObject);
SoPickStyle* ps = new SoPickStyle();
ps->style = SoPickStyle::UNPICKABLE;
SoSeparator* sep = new SoSeparator();
SoShapeHints* hints = new SoShapeHints();
hints->shapeType.setValue(SoShapeHints::UNKNOWN_SHAPE_TYPE);
hints->vertexOrdering.setValue(SoShapeHints::COUNTERCLOCKWISE);
sep->addChild(ps);
sep->addChild(hints);
sep->addChild(pMaterials);
sep->addChild(pShapeSep);
addDisplayMaskMode(sep, "Base");
}
std::vector<std::string> ViewProviderFemConstraint::getDisplayModes(void) const
{
// add modes
std::vector<std::string> StrList;
StrList.push_back("Base");
return StrList;
}
void ViewProviderFemConstraint::setDisplayMode(const char* ModeName)
{
if (strcmp(ModeName, "Base") == 0)
setDisplayMaskMode("Base");
ViewProviderDocumentObject::setDisplayMode(ModeName);
}
std::vector<App::DocumentObject*> ViewProviderFemConstraint::claimChildren(void)const
{
return std::vector<App::DocumentObject*>();
}
void ViewProviderFemConstraint::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
QAction* act;
act = menu->addAction(QObject::tr("Edit constraint"), receiver, member);
act->setData(QVariant((int)ViewProvider::Default));
ViewProviderDocumentObject::setupContextMenu(menu, receiver, member);
}
void ViewProviderFemConstraint::onChanged(const App::Property* prop)
{
if (prop == &Mirror || prop == &DistFactor) {
updateData(prop);
}
else if (prop == &TextColor) {
const App::Color& c = TextColor.getValue();
pTextColor->rgb.setValue(c.r,c.g,c.b);
}
else if (prop == &FaceColor) {
const App::Color& c = FaceColor.getValue();
pMaterials->diffuseColor.setValue(c.r,c.g,c.b);
}
else if (prop == &FontSize) {
pFont->size = FontSize.getValue();
}
else {
ViewProviderDocumentObject::onChanged(prop);
}
}
bool ViewProviderFemConstraint::setEdit(int ModNum)
{
return Gui::ViewProviderGeometryObject::setEdit(ModNum);
}
void ViewProviderFemConstraint::unsetEdit(int ModNum)
{
if ((wizardWidget != NULL) && (wizardSubLayout != NULL) && (constraintDialog != NULL)) {
wizardWidget = NULL;
wizardSubLayout = NULL;
delete constraintDialog;
constraintDialog = 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);
}
}
}
/*
// Create a local coordinate system with the z-axis given in dir
void getLocalCoordinateSystem(const SbVec3f& z, SbVec3f& y, SbVec3f& x)
{
// Find the y axis in an arbitrary direction, normal to z
// Conditions:
// y1 * z1 + y2 * z2 + y3 * z3 = |y| |z| cos(90°) = 0
// |y| = sqrt(y1^2 + y2^2 + y3^2) = 1
float z1, z2, z3;
z.getValue(z1, z2, z3);
float y1, y2, y3;
if (fabs(z1) > Precision::Confusion()) {
// Choose: y3 = 0
// Solution:
// y1 * z1 + y2 * z2 = 0
// y1 = - z2/z1 y2
// sqrt(z2^2/z1^2 y2^2 + y2^2) = 1
// y2^2 ( 1 + z2^2/z1^2)) = +-1 -> choose +1 otherwise no solution
// y2 = +- sqrt(1 / (1 + z2^2/z1^2))
y3 = 0;
y2 = sqrt(1 / (1 + z2*z2 / (z1*z1)));
y1 = -z2/z1 * y2;
// Note: result might be (0, 1, 0)
} else if (fabs(z2) > Precision::Confusion()) {
// Given: z1 = 0
// Choose: y1 = 0
// Solution:
// y2 * z2 + y3 * z3 = 0
// y2 = - z3/z2 y3
// sqrt(z3^2/z2^2 y3^3 + y3^2) = 1
// y3^2 (1 + z3^2/z2^2)) = +1
// y3 = +- sqrt(1 / (1 + z3^2/z2^2))
y1 = 0;
y3 = sqrt(1 / (1 + z3*z3 / (z2*z2)));
y2 = -z3/z2 * y3;
// Note: result might be (0, 0, 1)
} else if (fabs(z3) > Precision::Confusion()) {
// Given: z1 = z2 = 0
// Choose the remaining possible axis
y1 = 1;
y2 = 0;
y3 = 0;
}
y = SbVec3f(y1, y2, y3);
x = y.cross(z);
}
*/
#define PLACEMENT_CHILDREN 2
void ViewProviderFemConstraint::createPlacement(SoSeparator* sep, const SbVec3f &base, const SbRotation &r)
{
SoTranslation* trans = new SoTranslation();
trans->ref();
trans->translation.setValue(base);
sep->addChild(trans);
SoRotation* rot = new SoRotation();
rot->ref();
rot->rotation.setValue(r);
sep->addChild(rot);
}
void ViewProviderFemConstraint::updatePlacement(const SoSeparator* sep, const int idx, const SbVec3f &base, const SbRotation &r)
{
SoTranslation* trans = static_cast<SoTranslation*>(sep->getChild(idx));
trans->translation.setValue(base);
SoRotation* rot = static_cast<SoRotation*>(sep->getChild(idx+1));
rot->rotation.setValue(r);
}
#define CONE_CHILDREN 2
void ViewProviderFemConstraint::createCone(SoSeparator* sep, const double height, const double radius)
{
// Adjust cone so that the tip is on base
SoTranslation* trans = new SoTranslation();
trans->ref();
trans->translation.setValue(SbVec3f(0,-height/2,0));
sep->addChild(trans);
SoCone* cone = new SoCone();
cone->ref();
cone->height.setValue(height);
cone->bottomRadius.setValue(radius);
sep->addChild(cone);
}
SoSeparator* ViewProviderFemConstraint::createCone(const double height, const double radius)
{
// Create a new cone node
SoSeparator* sep = new SoSeparator();
createCone(sep, height, radius);
return sep;
}
void ViewProviderFemConstraint::updateCone(const SoNode* node, const int idx, const double height, const double radius)
{
const SoSeparator* sep = static_cast<const SoSeparator*>(node);
SoTranslation* trans = static_cast<SoTranslation*>(sep->getChild(idx));
trans->translation.setValue(SbVec3f(0,-height/2,0));
SoCone* cone = static_cast<SoCone*>(sep->getChild(idx+1));
cone->height.setValue(height);
cone->bottomRadius.setValue(radius);
}
#define CYLINDER_CHILDREN 1
void ViewProviderFemConstraint::createCylinder(SoSeparator* sep, const double height, const double radius)
{
SoCylinder* cyl = new SoCylinder();
cyl->ref();
cyl->height.setValue(height);
cyl->radius.setValue(radius);
sep->addChild(cyl);
}
SoSeparator* ViewProviderFemConstraint::createCylinder(const double height, const double radius)
{
// Create a new cylinder node
SoSeparator* sep = new SoSeparator();
createCylinder(sep, height, radius);
return sep;
}
void ViewProviderFemConstraint::updateCylinder(const SoNode* node, const int idx, const double height, const double radius)
{
const SoSeparator* sep = static_cast<const SoSeparator*>(node);
SoCylinder* cyl = static_cast<SoCylinder*>(sep->getChild(idx));
cyl->height.setValue(height);
cyl->radius.setValue(radius);
}
#define CUBE_CHILDREN 1
void ViewProviderFemConstraint::createCube(SoSeparator* sep, const double width, const double length, const double height)
{
SoCube* cube = new SoCube();
cube->ref();
cube->width.setValue(width);
cube->depth.setValue(length);
cube->height.setValue(height);
sep->addChild(cube);
}
SoSeparator* ViewProviderFemConstraint::createCube(const double width, const double length, const double height)
{
SoSeparator* sep = new SoSeparator();
createCube(sep, width, length, height);
return sep;
}
void ViewProviderFemConstraint::updateCube(const SoNode* node, const int idx, const double width, const double length, const double height)
{
const SoSeparator* sep = static_cast<const SoSeparator*>(node);
SoCube* cube = static_cast<SoCube*>(sep->getChild(idx));
cube->width.setValue(width);
cube->depth.setValue(length);
cube->height.setValue(height);
}
#define ARROW_CHILDREN (CONE_CHILDREN + PLACEMENT_CHILDREN + CYLINDER_CHILDREN)
void ViewProviderFemConstraint::createArrow(SoSeparator* sep, const double length, const double radius)
{
createCone(sep, radius, radius/2);
createPlacement(sep, SbVec3f(0, -radius/2-(length-radius)/2, 0), SbRotation());
createCylinder(sep, length-radius, radius/5);
}
SoSeparator* ViewProviderFemConstraint::createArrow(const double length, const double radius)
{
SoSeparator* sep = new SoSeparator();
createArrow(sep, length, radius);
return sep;
}
void ViewProviderFemConstraint::updateArrow(const SoNode* node, const int idx, const double length, const double radius)
{
const SoSeparator* sep = static_cast<const SoSeparator*>(node);
updateCone(sep, idx, radius, radius/2);
updatePlacement(sep, idx+CONE_CHILDREN, SbVec3f(0, -radius/2-(length-radius)/2, 0), SbRotation());
updateCylinder(sep, idx+CONE_CHILDREN+PLACEMENT_CHILDREN, length-radius, radius/5);
}
#define FIXED_CHILDREN (CONE_CHILDREN + PLACEMENT_CHILDREN + CUBE_CHILDREN)
void ViewProviderFemConstraint::createFixed(SoSeparator* sep, const double height, const double width, const bool gap)
{
createCone(sep, height-width/4, height-width/4);
createPlacement(sep, SbVec3f(0, -(height-width/4)/2-width/8 - (gap ? 1.0 : 0.1) * width/8, 0), SbRotation());
createCube(sep, width, width, width/4);
}
SoSeparator* ViewProviderFemConstraint::createFixed(const double height, const double width, const bool gap)
{
SoSeparator* sep = new SoSeparator();
createFixed(sep, height, width, gap);
return sep;
}
void ViewProviderFemConstraint::updateFixed(const SoNode* node, const int idx, const double height, const double width, const bool gap)
{
const SoSeparator* sep = static_cast<const SoSeparator*>(node);
updateCone(sep, idx, height-width/4, height-width/4);
updatePlacement(sep, idx+CONE_CHILDREN, SbVec3f(0, -(height-width/4)/2-width/8 - (gap ? 1.0 : 0.0) * width/8, 0), SbRotation());
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

@@ -0,0 +1,124 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINT_H
#define GUI_VIEWPROVIDERFEMCONSTRAINT_H
#include <TopoDS_Shape.hxx>
#include "Gui/ViewProviderGeometryObject.h"
#include <QObject>
#include <QVBoxLayout>
#include <QTableWidget>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class TaskFemConstraint;
class FemGuiExport ViewProviderFemConstraint : public Gui::ViewProviderGeometryObject
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraint);
public:
/// Constructor
ViewProviderFemConstraint(void);
virtual ~ViewProviderFemConstraint();
// Display properties
App::PropertyColor TextColor;
App::PropertyColor FaceColor;
App::PropertyColor ShapeColor;
App::PropertyInteger FontSize;
App::PropertyFloat DistFactor;
App::PropertyBool Mirror;
void attach(App::DocumentObject *);
virtual void updateData(const App::Property* prop) { Gui::ViewProviderGeometryObject::updateData(prop); }
std::vector<std::string> getDisplayModes(void) const;
void setDisplayMode(const char* ModeName);
std::vector<App::DocumentObject*> claimChildren(void)const;
void setupContextMenu(QMenu*, QObject*, const char*);
protected:
void onChanged(const App::Property* prop);
virtual bool setEdit(int ModNum);
virtual void unsetEdit(int ModNum);
static void createPlacement(SoSeparator* sep, const SbVec3f &base, const SbRotation &r);
static void updatePlacement(const SoSeparator* sep, const int idx, const SbVec3f &base, const SbRotation &r);
static void createCone(SoSeparator* sep, const double height, const double radius);
static SoSeparator* createCone(const double height, const double radius);
static void updateCone(const SoNode* node, const int idx, const double height, const double radius);
static void createCylinder(SoSeparator* sep, const double height, const double radius);
static SoSeparator* createCylinder(const double height, const double radius);
static void updateCylinder(const SoNode* node, const int idx, const double height, const double radius);
static void createCube(SoSeparator* sep, const double width, const double length, const double height);
static SoSeparator* createCube(const double width, const double length, const double height);
static void updateCube(const SoNode* node, const int idx, const double width, const double length, const double height);
static void createArrow(SoSeparator* sep, const double length, const double radius);
static SoSeparator* createArrow(const double length, const double radius);
static void updateArrow(const SoNode* node, const int idx, const double length, const double radius);
static void createFixed(SoSeparator* sep, const double height, const double width, const bool gap = false);
static SoSeparator* createFixed(const double height, const double width, const bool gap = false);
static void updateFixed(const SoNode* node, const int idx, const double height, const double width, const bool gap = false);
private:
SoFontStyle * pFont;
SoText2 * pLabel;
SoBaseColor * pTextColor;
SoMaterial * pMaterials;
protected:
SoSeparator * pShapeSep;
// 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
#endif // GUI_VIEWPROVIDERFEMCONSTRAINT_H

View File

@@ -0,0 +1,153 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Precision.hxx>
#endif
#include "ViewProviderFemConstraintBearing.h"
#include <Mod/Fem/App/FemConstraintBearing.h>
#include "TaskFemConstraintBearing.h"
#include "Gui/Control.h"
#include "Gui/MainWindow.h"
#include <Base/Console.h>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintBearing, FemGui::ViewProviderFemConstraint)
ViewProviderFemConstraintBearing::ViewProviderFemConstraintBearing()
{
sPixmap = "Fem_ConstraintBearing";
wizardWidget = NULL;
}
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
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgFemConstraintBearing *constrDlg = qobject_cast<TaskDlgFemConstraintBearing *>(dlg);
if (constrDlg && constrDlg->getConstraintView() != this)
constrDlg = 0; // another constraint left open its task panel
if (dlg && !constrDlg) {
// 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)
Gui::Selection().clearSelection();
// start the edit dialog
if (constrDlg)
Gui::Control().showDialog(constrDlg);
else
Gui::Control().showDialog(new TaskDlgFemConstraintBearing(this));
return true;
}
else {
return ViewProviderDocumentObject::setEdit(ModNum);
}
}
void ViewProviderFemConstraintBearing::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
Fem::ConstraintBearing* pcConstraint = static_cast<Fem::ConstraintBearing*>(this->getObject());
if (strcmp(prop->getName(),"References") == 0)
Base::Console().Error("\n"); // enable a breakpoint here
if (strcmp(prop->getName(),"BasePoint") == 0) {
// Remove and recreate the symbol
pShapeSep->removeAllChildren();
// This should always point outside of the cylinder
Base::Vector3f normal = pcConstraint->NormalDirection.getValue();
Base::Vector3f base = pcConstraint->BasePoint.getValue();
float radius = pcConstraint->Radius.getValue();
base = base + radius * normal;
SbVec3f b(base.x, base.y, base.z);
SbVec3f dir(normal.x, normal.y, normal.z);
SbRotation rot(SbVec3f(0,-1,0), dir);
createPlacement(pShapeSep, b, rot);
pShapeSep->addChild(createFixed(radius/2, radius/2 * 1.5, pcConstraint->AxialFree.getValue()));
} else if (strcmp(prop->getName(),"AxialFree") == 0) {
if (pShapeSep->getNumChildren() > 0) {
// Change the symbol
Base::Vector3f normal = pcConstraint->NormalDirection.getValue();
Base::Vector3f base = pcConstraint->BasePoint.getValue();
float radius = pcConstraint->Radius.getValue();
base = base + radius * normal;
SbVec3f b(base.x, base.y, base.z);
SbVec3f dir(normal.x, normal.y, normal.z);
SbRotation rot(SbVec3f(0,-1,0), dir);
updatePlacement(pShapeSep, 0, b, rot);
const SoSeparator* sep = static_cast<SoSeparator*>(pShapeSep->getChild(2));
updateFixed(sep, 0, radius/2, radius/2 * 1.5, pcConstraint->AxialFree.getValue());
}
}
ViewProviderFemConstraint::updateData(prop);
}

View File

@@ -0,0 +1,75 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTBEARING_H
#define GUI_VIEWPROVIDERFEMCONSTRAINTBEARING_H
#include <TopoDS_Shape.hxx>
#include "ViewProviderFemConstraint.h"
#include <QObject>
#include <QVBoxLayout>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
class SoLightModel;
class SoCoordinate3;
class SoIndexedLineSet;
class SoIndexedFaceSet;
class SoEventCallback;
class SoMarkerSet;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class FemGuiExport ViewProviderFemConstraintBearing : public FemGui::ViewProviderFemConstraint
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraintBearing);
public:
/// Constructor
ViewProviderFemConstraintBearing();
virtual ~ViewProviderFemConstraintBearing();
virtual void updateData(const App::Property*);
protected:
virtual bool setEdit(int ModNum);
};
} //namespace FemGui
#endif // GUI_VIEWPROVIDERFEMCONSTRAINTBEARING_H

View File

@@ -0,0 +1,163 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/nodes/SoMultipleCopy.h>
# include <Precision.hxx>
#endif
#include "ViewProviderFemConstraintFixed.h"
#include <Mod/Fem/App/FemConstraintFixed.h>
#include "TaskFemConstraintFixed.h"
#include "Gui/Control.h"
#include <Base/Console.h>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintFixed, FemGui::ViewProviderFemConstraint)
ViewProviderFemConstraintFixed::ViewProviderFemConstraintFixed()
{
sPixmap = "Fem_ConstraintFixed";
}
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
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgFemConstraintFixed *constrDlg = qobject_cast<TaskDlgFemConstraintFixed *>(dlg);
if (constrDlg && constrDlg->getConstraintView() != this)
constrDlg = 0; // another constraint left open its task panel
if (dlg && !constrDlg) {
// 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)
Gui::Selection().clearSelection();
// start the edit dialog
if (constrDlg)
Gui::Control().showDialog(constrDlg);
else
Gui::Control().showDialog(new TaskDlgFemConstraintFixed(this));
return true;
} else {
return ViewProviderDocumentObject::setEdit(ModNum);
}
}
#define HEIGHT 4
#define WIDTH (1.5*HEIGHT)
void ViewProviderFemConstraintFixed::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
Fem::ConstraintFixed* pcConstraint = static_cast<Fem::ConstraintFixed*>(this->getObject());
/*
// This has a HUGE performance penalty as opposed to separate nodes for every symbol
// The problem seems to be SoCone
if (pShapeSep->getNumChildren() == 0) {
// Set up the nodes
SoMultipleCopy* cp = new SoMultipleCopy();
cp->ref();
cp->matrix.setNum(0);
cp->addChild((SoNode*)createFixed(HEIGHT, WIDTH));
pShapeSep->addChild(cp);
}
*/
if (strcmp(prop->getName(),"Points") == 0) {
// Note: Points and Normals are always updated together
pShapeSep->removeAllChildren();
const std::vector<Base::Vector3f>& points = pcConstraint->Points.getValues();
const std::vector<Base::Vector3f>& normals = pcConstraint->Normals.getValues();
std::vector<Base::Vector3f>::const_iterator n = normals.begin();
/*
SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0));
cp->matrix.setNum(points.size());
int idx = 0;
*/
for (std::vector<Base::Vector3f>::const_iterator p = points.begin(); p != points.end(); p++) {
SbVec3f base(p->x, p->y, p->z);
SbVec3f dir(n->x, n->y, n->z);
SbRotation rot(SbVec3f(0,-1,0), dir);
/*
SbMatrix m;
m.setTransform(base, rot, SbVec3f(1,1,1));
cp->matrix.set1Value(idx, m);
idx++
*/
SoSeparator* sep = new SoSeparator();
createPlacement(sep, base, rot);
createFixed(sep, HEIGHT, WIDTH);
pShapeSep->addChild(sep);
n++;
}
}
ViewProviderFemConstraint::updateData(prop);
}

View File

@@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTFIXED_H
#define GUI_VIEWPROVIDERFEMCONSTRAINTFIXED_H
#include <TopoDS_Shape.hxx>
#include "ViewProviderFemConstraint.h"
#include <QObject>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
class SoLightModel;
class SoCoordinate3;
class SoIndexedLineSet;
class SoIndexedFaceSet;
class SoEventCallback;
class SoMarkerSet;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class FemGuiExport ViewProviderFemConstraintFixed : public FemGui::ViewProviderFemConstraint
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraintFixed);
public:
/// Constructor
ViewProviderFemConstraintFixed();
virtual ~ViewProviderFemConstraintFixed();
virtual void updateData(const App::Property*);
protected:
virtual bool setEdit(int ModNum);
};
} //namespace FemGui
#endif // GUI_VIEWPROVIDERFEMCONSTRAINTFIXED_H

View File

@@ -0,0 +1,202 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/nodes/SoMultipleCopy.h>
# include <Precision.hxx>
#endif
#include "ViewProviderFemConstraintForce.h"
#include <Mod/Fem/App/FemConstraintForce.h>
#include "TaskFemConstraintForce.h"
#include "Gui/Control.h"
#include <Base/Console.h>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintForce, FemGui::ViewProviderFemConstraint)
ViewProviderFemConstraintForce::ViewProviderFemConstraintForce()
{
sPixmap = "Fem_ConstraintForce";
}
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
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgFemConstraintForce *constrDlg = qobject_cast<TaskDlgFemConstraintForce *>(dlg);
if (constrDlg && constrDlg->getConstraintView() != this)
constrDlg = 0; // another constraint left open its task panel
if (dlg && !constrDlg) {
// 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)
Gui::Selection().clearSelection();
// start the edit dialog
if (constrDlg)
Gui::Control().showDialog(constrDlg);
else
Gui::Control().showDialog(new TaskDlgFemConstraintForce(this));
return true;
}
else {
return ViewProviderDocumentObject::setEdit(ModNum);
}
}
#define ARROWLENGTH 9
#define ARROWHEADRADIUS (ARROWLENGTH/3)
void ViewProviderFemConstraintForce::updateData(const App::Property* prop)
{
// Gets called whenever a property of the attached object changes
Fem::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(this->getObject());
/*
// This has a HUGE performance penalty as opposed to separate nodes for every symbol
// The problem seems to be SoCone
if (pShapeSep->getNumChildren() == 0) {
// Set up the nodes
SoMultipleCopy* cp = new SoMultipleCopy();
cp->ref();
cp->matrix.setNum(0);
cp->addChild((SoNode*)createArrow(ARROWLENGTH, ARROWHEADRADIUS));
pShapeSep->addChild(cp);
}
*/
if (strcmp(prop->getName(),"Points") == 0) {
// Redraw all arrows
pShapeSep->removeAllChildren();
// This should always point outside of the solid
Base::Vector3f normal = pcConstraint->NormalDirection.getValue();
// Get default direction (on first call to method)
Base::Vector3f forceDirection = pcConstraint->DirectionVector.getValue();
if (forceDirection.Length() < Precision::Confusion())
forceDirection = normal;
SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z);
SbRotation rot(SbVec3f(0,1,0), dir);
const std::vector<Base::Vector3f>& points = pcConstraint->Points.getValues();
/*
SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0));
cp->matrix.setNum(points.size());
int idx = 0;*/
for (std::vector<Base::Vector3f>::const_iterator p = points.begin(); p != points.end(); p++) {
SbVec3f base(p->x, p->y, p->z);
if (forceDirection.GetAngle(normal) < M_PI_2) // Move arrow so it doesn't disappear inside the solid
base = base + dir * ARROWLENGTH;
/*
SbMatrix m;
m.setTransform(base, rot, SbVec3f(1,1,1));
cp->matrix.set1Value(idx, m);
idx++;
*/
SoSeparator* sep = new SoSeparator();
createPlacement(sep, base, rot);
createArrow(sep, ARROWLENGTH, ARROWHEADRADIUS);
pShapeSep->addChild(sep);
}
} else if (strcmp(prop->getName(),"DirectionVector") == 0) { // Note: "Reversed" also triggers "DirectionVector"
// Re-orient all arrows
Base::Vector3f normal = pcConstraint->NormalDirection.getValue();
Base::Vector3f forceDirection = pcConstraint->DirectionVector.getValue();
if (forceDirection.Length() < Precision::Confusion())
forceDirection = normal;
SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z);
SbRotation rot(SbVec3f(0,1,0), dir);
const std::vector<Base::Vector3f>& points = pcConstraint->Points.getValues();
/*
SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0));
cp->matrix.setNum(points.size());
*/
int idx = 0;
for (std::vector<Base::Vector3f>::const_iterator p = points.begin(); p != points.end(); p++) {
SbVec3f base(p->x, p->y, p->z);
if (forceDirection.GetAngle(normal) < M_PI_2)
base = base + dir * ARROWLENGTH;
/*
SbMatrix m;
m.setTransform(base, rot, SbVec3f(1,1,1));
cp->matrix.set1Value(idx, m);*/
SoSeparator* sep = static_cast<SoSeparator*>(pShapeSep->getChild(idx));
updatePlacement(sep, 0, base, rot);
updateArrow(sep, 2, ARROWLENGTH, ARROWHEADRADIUS);
idx++;
}
}
ViewProviderFemConstraint::updateData(prop);
}

View File

@@ -0,0 +1,78 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTFORCE_H
#define GUI_VIEWPROVIDERFEMCONSTRAINTFORCE_H
#include <TopoDS_Shape.hxx>
#include "ViewProviderFemConstraint.h"
#include <QObject>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
class SoLightModel;
class SoCoordinate3;
class SoIndexedLineSet;
class SoIndexedFaceSet;
class SoEventCallback;
class SoMarkerSet;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class FemGuiExport ViewProviderFemConstraintForce : public FemGui::ViewProviderFemConstraint
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraintForce);
public:
/// Constructor
ViewProviderFemConstraintForce();
virtual ~ViewProviderFemConstraintForce();
virtual void updateData(const App::Property*);
protected:
virtual bool setEdit(int ModNum);
private:
/// Direction of the force
Base::Vector3f forceDirection;
};
} //namespace FemGui
#endif // GUI_VIEWPROVIDERFEMCONSTRAINTFORCE_H

View File

@@ -0,0 +1,191 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/SbMatrix.h>
# include <Precision.hxx>
#endif
#include "ViewProviderFemConstraintGear.h"
#include <Mod/Fem/App/FemConstraintGear.h>
#include "TaskFemConstraintGear.h"
#include "Gui/Control.h"
#include <Base/Console.h>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintGear, FemGui::ViewProviderFemConstraint)
ViewProviderFemConstraintGear::ViewProviderFemConstraintGear()
{
sPixmap = "Fem_ConstraintGear";
}
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
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgFemConstraintGear *constrDlg = qobject_cast<TaskDlgFemConstraintGear *>(dlg);
if (constrDlg && constrDlg->getConstraintView() != this)
constrDlg = 0; // another constraint left open its task panel
if (dlg && !constrDlg) {
// 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)
Gui::Selection().clearSelection();
// start the edit dialog
if (constrDlg)
Gui::Control().showDialog(constrDlg);
else
Gui::Control().showDialog(new TaskDlgFemConstraintGear(this));
return true;
}
else {
return ViewProviderDocumentObject::setEdit(ModNum);
}
}
void ViewProviderFemConstraintGear::updateData(const App::Property* prop)
{
Fem::ConstraintGear* pcConstraint = static_cast<Fem::ConstraintGear*>(this->getObject());
// 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();
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 ax(axis.x, axis.y, axis.z);
SbVec3f dir(direction.x, direction.y, direction.z);
//Base::Console().Error("DirectionVector: %f, %f, %f\n", direction.x, direction.y, direction.z);
createPlacement(pShapeSep, b, SbRotation(SbVec3f(0,1,0), ax));
pShapeSep->addChild(createCylinder(pcConstraint->Height.getValue() * 0.8, dia/2));
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 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 radius = pcConstraint->Radius.getValue();
if (dia < 2 * radius)
dia = 2 * radius;
float angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI;
SbVec3f ax(axis.x, axis.y, axis.z);
SbVec3f dir(direction.x, direction.y, direction.z);
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 * 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

@@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTGear_H
#define GUI_VIEWPROVIDERFEMCONSTRAINTGear_H
#include <TopoDS_Shape.hxx>
#include "ViewProviderFemConstraint.h"
#include <QObject>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
class SoLightModel;
class SoCoordinate3;
class SoIndexedLineSet;
class SoIndexedFaceSet;
class SoEventCallback;
class SoMarkerSet;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class FemGuiExport ViewProviderFemConstraintGear : public FemGui::ViewProviderFemConstraint
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraintGear);
public:
/// Constructor
ViewProviderFemConstraintGear();
virtual ~ViewProviderFemConstraintGear();
virtual void updateData(const App::Property*);
protected:
virtual bool setEdit(int ModNum);
};
} //namespace FemGui
#endif // GUI_VIEWPROVIDERFEMCONSTRAINTGear_H

View File

@@ -0,0 +1,225 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTranslation.h>
# include <Inventor/nodes/SoRotation.h>
# include <Precision.hxx>
#endif
#include "ViewProviderFemConstraintPulley.h"
#include <Mod/Fem/App/FemConstraintPulley.h>
#include "TaskFemConstraintPulley.h"
#include "Gui/Control.h"
#include <Base/Console.h>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintPulley, FemGui::ViewProviderFemConstraint)
ViewProviderFemConstraintPulley::ViewProviderFemConstraintPulley()
{
sPixmap = "Fem_ConstraintPulley";
}
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
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgFemConstraintPulley *constrDlg = qobject_cast<TaskDlgFemConstraintPulley *>(dlg);
if (constrDlg && constrDlg->getConstraintView() != this)
constrDlg = 0; // another constraint left open its task panel
if (dlg && !constrDlg) {
// 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)
Gui::Selection().clearSelection();
// start the edit dialog
if (constrDlg)
Gui::Control().showDialog(constrDlg);
else
Gui::Control().showDialog(new TaskDlgFemConstraintPulley(this));
return true;
}
else {
return ViewProviderDocumentObject::setEdit(ModNum);
}
}
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 (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();
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();
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 ax(axis.x, axis.y, axis.z);
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 * 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 * 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(),"Diameter") == 0) {
if (pShapeSep->getNumChildren() > 0) {
// Change the symbol
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();
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(2));
updateCylinder(sep, 0, pcConstraint->Height.getValue() * 0.8, dia/2);
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))));
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 * 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);
}
}
ViewProviderFemConstraint::updateData(prop);
}

View File

@@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (c) 2013 Jan Rheinländer <jrheinlaender[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTPulley_H
#define GUI_VIEWPROVIDERFEMCONSTRAINTPulley_H
#include <TopoDS_Shape.hxx>
#include "ViewProviderFemConstraint.h"
#include <QObject>
class SoFontStyle;
class SoText2;
class SoBaseColor;
class SoTranslation;
class SbRotation;
class SoMaterial;
class SoLightModel;
class SoCoordinate3;
class SoIndexedLineSet;
class SoIndexedFaceSet;
class SoEventCallback;
class SoMarkerSet;
namespace Gui {
class View3DInventorViewer;
namespace TaskView {
class TaskDialog;
}
}
namespace FemGui
{
class FemGuiExport ViewProviderFemConstraintPulley : public FemGui::ViewProviderFemConstraint
{
PROPERTY_HEADER(FemGui::ViewProviderFemConstraintPulley);
public:
/// Constructor
ViewProviderFemConstraintPulley();
virtual ~ViewProviderFemConstraintPulley();
virtual void updateData(const App::Property*);
protected:
virtual bool setEdit(int ModNum);
};
} //namespace FemGui
#endif // GUI_VIEWPROVIDERFEMCONSTRAINTPulley_H

View File

@@ -29,7 +29,7 @@
#include "Workbench.h"
#include <Gui/ToolBarManager.h>
#include <Gui/MenuManager.h>
#include <Gui/MenuManager.h>
using namespace FemGui;
@@ -56,7 +56,12 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem* fem = new Gui::ToolBarItem(root);
fem->setCommand("FEM");
*fem << "Fem_CreateFromShape"
<< "Fem_CreateNodesSet";
<< "Fem_CreateNodesSet"
<< "Fem_ConstraintFixed"
<< "Fem_ConstraintForce"
<< "Fem_ConstraintBearing"
<< "Fem_ConstraintGear"
<< "Fem_ConstraintPulley";
return root;
}
@@ -68,7 +73,12 @@ Gui::MenuItem* Workbench::setupMenuBar() const
root->insertItem(item, fem);
fem->setCommand("&FEM");
*fem << "Fem_CreateFromShape"
<< "Fem_CreateNodesSet";
<< "Fem_CreateNodesSet"
<< "Fem_ConstraintFixed"
<< "Fem_ConstraintForce"
<< "Fem_ConstraintBearing"
<< "Fem_ConstraintGear"
<< "Fem_ConstraintPulley";
return root;
}

View File

@@ -1,76 +0,0 @@
# PartDesign gui init module
# (c) 2003 Juergen Riegel
#
# Gathering all the information to start FreeCAD
# This is the second one of three init scripts, the third one
# runs when the gui is up
#***************************************************************************
#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU General Public License (GPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#* Juergen Riegel 2002 *
#***************************************************************************/
class PartDesignWorkbench ( Workbench ):
"PartDesign workbench object"
from WizardShaft import WizardShaft
Icon = """
/* XPM */
static char * partdesign_xpm[] = {
"16 16 9 1",
" c None",
". c #040006",
"+ c #070F38",
"@ c #002196",
"# c #0030F3",
"$ c #5A4D20",
"% c #858EB2",
"& c #DEB715",
"* c #BFB99D",
" & ........ ",
"&&&$..@@@@@@+...",
"&&&&$@#####@..@.",
"&&&&&$......@#@.",
"&&&&&&@@@+.###@.",
"$&&&&&&@#@.###@.",
".$&&&&&%#@.###@.",
".@*&&&*%#@.###@.",
".@#*&**%#@.###@.",
".@#@%%%.@@.###@.",
".@@@@@@@#@.###@.",
".@#######@.###@.",
".@#######@.##+. ",
".+@@@####@.@.. ",
" ......+++.. ",
" ... "};
"""
MenuText = "Part Design"
ToolTip = "Part Design workbench"
def Initialize(self):
# load the module
import PartDesignGui
import PartDesign
def GetClassName(self):
return "PartDesignGui::Workbench"
Gui.addWorkbench(PartDesignWorkbench())

View File

@@ -21,6 +21,7 @@
# ******************************************************************************/
import FreeCAD # just for debug printing to console...
import numpy as np
class SegmentFunctionSegment:
"One segment of a segment function"
@@ -39,6 +40,10 @@ class SegmentFunctionSegment:
"Return true if the start of this segment is xval"
#FIXME: 1E-9 is arbitrary here. But since units are in meters, 1E-9 is a nanometer...
return abs(self.start - xval) < 1E-9
def isZero(self):
#FIXME: 1E-9 is arbitrary here. But since units are in meters, 1E-9 is a nanometer...
return abs(self.coefficient) < 1E-5
def value(self, xval):
if xval < self.start:
@@ -48,13 +53,21 @@ class SegmentFunctionSegment:
def clone(self):
return SegmentFunctionSegment(self.start, self.variable, self.coefficient, self.exponent)
def negate(self):
self.coefficient *= -1
return self
def negated(self):
return SegmentFunctionSegment(self.start, self.variable, self.coefficient * -1.0, self.exponent)
def __mul__(self, value):
return SegmentFunctionSegment(self.start, self.variable, self.coefficient * value, self.exponent)
def integrate(self):
self.exponent = self.exponent + 1
self.coefficient = self.coefficient * 1 / self.exponent
return self
def asString(self):
return "%f * {%s - %f}^%i" % (self.coefficient, self.variable, self.start, self.exponent)
@@ -69,11 +82,38 @@ class SegmentFunction:
self.variable = "x"
self.segments = []
self.name = name
def findSegment(self, xval):
"Find segment valid for the given xval"
for s in self.segments:
if s.start <= xval:
return s
return self.segments[len(self.segments)]
def isZero(self):
for s in self.segments:
if not s.isZero():
return False
return True
def negate(self):
for s in self.segments:
s.negate()
return self
def negated(self):
result = SegmentFunction()
result.variable = self.variable
for s in self.segments:
result.segments.append(s.negated())
return result
def __mul__(self, value):
result = SegmentFunction()
result.variable = self.variable
for s in self.segments:
result.segments.append(s * value)
return result
def index(self, xval):
"Find insert position for start value xval"
@@ -90,11 +130,14 @@ class SegmentFunction:
for key in sorted(dict.iterkeys()):
#if abs(dict[key]) > 1E-9:
self.segments.append(SegmentFunctionSegment(key, var, dict[key], 0))
def addSegment(self, st, coeff, exp = 0.0):
if abs(coeff) > 1E-9:
self.segments.insert(self.index(st), SegmentFunctionSegment(st, self.variable, coeff, exp))
def addSegments(self, dict):
for key in sorted(dict.iterkeys()):
if abs(dict[key]) > 1E-9:
self.segments.insert(self.index(key), SegmentFunctionSegment(key, self.variable, dict[key], 0))
self.addSegment(key, dict[key])
def setMaxX(self, mx):
self.maxX = mx
@@ -124,6 +167,7 @@ class SegmentFunction:
"Integrate all segments with respect to the variable"
for s in self.segments:
s.integrate()
return self
def integrated(self):
"Return a copy of self integrated with respect to the variable"
@@ -156,3 +200,206 @@ class SegmentFunction:
FreeCAD.Console.PrintMessage(" + ")
FreeCAD.Console.PrintMessage("\n")
class IntervalFunction:
"Function defined in intervals"
intervals = [] # vector of tuples (begin, length)
values = [] # vector of constant values applicable for this interval
def __init__(self):
self.intervals = []
self.values = []
def addInterval(self, begin, length, value):
self.intervals.append((begin, length))
self.values.append(value)
def value(self, xval):
for i in range(len(self.intervals)):
if xval >= self.intervals[i][0] and xval < self.intervals[i][0] + self.intervals[i][1]:
return self.values[i]
return self.values[len(self.values)-1]
def lowervalue(self, xval):
return self.value(xval - 1E-8)
def index(self, xval):
lastStart = 0.0
for i in range(len(self.intervals)):
newStart = self.intervals[i][0]
if (xval >= lastStart) and (xval < newStart):
return i-1
lastStart = newStart
return len(self.intervals)-1
def interval(self, xval):
"Return interval (begin, length) for this xval"
return self.intervals[self.index(xval)]
def begin(self, xval):
return self.intervals[self.index(xval)][0]
def length(self, xval):
return self.intervals[self.index(xval)][1]
class StressFunction:
"Specialization for segment-wise display of stresses"
# The hairy thing about this is that the segments of the segfunc usually do not correspond with the intervals of the intfunc!
segfunc = None # The segment function for the force/moment
intfunc = None # The divisors, an interval function giving a specific value for each interval
name = "sigma"
def __init__(self, f, i):
self.segfunc = f
self.intfunc = i
def isZero(self):
return self.segfunc.isZero()
def evaluate(self, maxX, pointsX):
# Note: This usually creates a few more points than specified in pointsX
offset = (maxX - self.segfunc.segments[0].start) / (pointsX - 1)
xvals = set([self.segfunc.segments[0].start + s * offset for s in range(pointsX)])
starts = set([self.segfunc.segments[i].start for i in range(len(self.segfunc.segments))])
xvals = xvals.union(starts) # Make sure we have a point on each segment start
divs = set([self.intfunc.intervals[i][0] for i in range(len(self.intfunc.intervals))])
xvals = xvals.union(divs)
xresult = []
yresult = []
for xval in sorted(xvals):
if xval in starts:
# create double point at segment border
xresult.append(xval)
yresult.append(self.segfunc.lowervalue(xval) / self.intfunc.value(xval))
if (xval in divs):
# create double point at divisor border
xresult.append(xval)
yresult.append(self.segfunc.value(xval) / self.intfunc.lowervalue(xval))
xresult.append(xval)
yresult.append(self.segfunc.value(xval) / self.intfunc.value(xval))
return (xresult, yresult)
class TranslationFunction:
"Specialization for segment-wise display of translations"
tangfunc = None # The segment function for the tangent to the bending line
transfunc = None # The segment function for translations of the shaft (the bending line)
intfunc = None # The divisors, a vector of tuples (location, divisor)
boundaries = {} # The boundary conditions, dictionary of location:[left boundary, right boundary]
module = 2.1E12
name = "w"
def __init__(self, f, E, d, tangents, translations):
if f.isZero():
return
# Note: Integration has to be segment-wise because the area moment is not constant in different segments. But this only becomes relevant
# when boundary conditions are being applied
# E I_i w_i'(x) = tangfunc + C_i0
self.tangfunc = f.integrated()
self.tangfunc.name = "w'"
self.tangfunc.output()
# E I_i w_i(x) = transfunc + C_i0 x + C_i1
self.transfunc = self.tangfunc.integrated() # + C_i0 * x + C_i1 (integration constants for interval number i)
self.transfunc.name = "w"
self.transfunc.output()
self.module = E
self.intfunc = d
# Solve boundary conditions. There are two types:
# External boundary conditions, e.g. a given tangent direction or translation value at a given x-value
# Internal boundary conditions, i.e. at the segment borders the tangent direction and translation of the lines must be equal
# Note that the relevant boundaries are those of the intfunc (where the area moment of the shaft cross-section changes)
# Every interval of the transfunc has two integration constants C_i0 and C_i1 that need to be defined
# Matrix of coefficients
A = np.zeros(shape = (2 * len(self.intfunc.intervals), 2 * len(self.intfunc.intervals)))
# Vector of RHS values
b = np.zeros(shape = 2 * len(self.intfunc.intervals))
# Current row where coefficients of next equation will be added
row = 0
# First look at external boundary conditions
for bound in tangents:
xval = bound[0]
tang = bound[1]
i = self.intfunc.index(xval) # index of this segment
I_i = self.intfunc.value(xval) # Area moment of this segment
# w_i'(xval) = tang => (tangfunc(xval) + C_i0) / (E * I_i) = tang => C_i0 = tang * (E * I_i) - tangfunc(xval)
A[row][2 * i] = 1.0
b[row] = tang * E * I_i - self.tangfunc.value(xval)
row += 1
for bound in translations:
xval = bound[0]
trans = bound[1]
i = self.intfunc.index(xval) # index of this segment
I_i = self.intfunc.value(xval) # Area moment of this segment
# w_i(xval) = trans => (transfunc(xval) + C_i0 * xval + C_i1) / (E * I_i) = trans => xval / (E * I_i) * C_i0 + 1 / (E * I_i) * C_i1 = trans - transfunc(xval) / (E * I_i)
A[row][2 * i] = xval / (E * I_i)
A[row][2 * i + 1] = 1 / (E * I_i)
b[row] = trans - self.transfunc.value(xval) / (E * I_i)
row += 1
# Now look at internal boundary conditions (n intervals have n-1 common segment boundaries)
for i in range(len(self.intfunc.intervals) - 1):
x_start = self.intfunc.intervals[i][0]
x_end = x_start + self.intfunc.intervals[i][1]
I_i = self.intfunc.value(x_start) # Area moment of this segment
I_ip1 = self.intfunc.value(x_end)
# w_i'(x_end) = w_i+1'(xend) => (tangfunc(x_end) + C_i0) / (E * I_i) = (tangfunc(x_end) * C_i+1,0) / (E * I_i+1)
# => 1 / (E * I_i) C_i0 - 1 / (E * I_i+1) * C_i+1,0 = tangfunc(x_end) / (E * I_i+1) - tangfunc(x_end) / (E * I_i)
A[row][2 * i] = 1 / (E * I_i)
A[row][2 * (i+1)] = -1 / (E * I_ip1)
b[row] = self.tangfunc.value(x_end) / (E * I_ip1) - self.tangfunc.value(x_end) / (E * I_i)
row += 1
# w_i(x_end) = w_i+1(xend) => (transfunc(x_end) + C_i0 * x_end + C_i1) / (E * I_i) = (transfunc(x_end) * C_i+1,0) * x_end + C_i+1,1) / (E * I_i+1)
# => x_end / (E * I_i) C_i0 + 1 / (E * I_i) C_i1 - x_end / (E * I_i+1) * C_i+1,0 - 1 / (E * I_i+1) * C_i+1,1 = transfunc(x_end) / (E * I_i+1) - transfunc(x_end) / (E * I_i)
A[row][2 * i] = x_end / (E * I_i)
A[row][2 * i + 1] = 1 / (E * I_i)
A[row][2 * (i+1)] = -x_end / (E * I_ip1)
A[row][2 * (i+1) + 1] = -1 / (E * I_ip1)
b[row] = self.transfunc.value(x_end) / (E * I_ip1) - self.transfunc.value(x_end) / (E * I_i)
row += 1
#FreeCAD.Console.PrintMessage(A)
#FreeCAD.Console.PrintMessage(" * x = ")
#FreeCAD.Console.PrintMessage(b)
#FreeCAD.Console.PrintMessage("\n")
try:
self.boundaries = np.linalg.solve(A, b) # A * self.boundaries = b
except np.linalg.linalg.LinAlgError, e:
FreeCAD.Console.PrintMessage(e.message)
FreeCAD.Console.PrintMessage(". No solution possible.\n")
return
def isZero(self):
if self.transfunc is None:
return True
return self.transfunc.isZero()
def evaluate(self, maxX, pointsX):
# Note: This usually creates a few more points than specified in pointsX
offset = (maxX - self.transfunc.segments[0].start) / (pointsX - 1)
xvals = set([self.transfunc.segments[0].start + s * offset for s in range(pointsX)])
starts = set([self.transfunc.segments[i].start for i in range(len(self.transfunc.segments))])
xvals = xvals.union(starts) # Make sure we have a point on each segment start
divs = set([self.intfunc.intervals[i][0] for i in range(len(self.intfunc.intervals))])
xvals = xvals.union(divs)
E = self.module
xresult = []
yresult = []
for xval in sorted(xvals):
if xval in divs:
i = self.intfunc.index(xval)
(begin, length) = self.intfunc.interval(xval)
I_i = self.intfunc.value(xval)
C_i0 = self.boundaries[2 * i]
C_i1 = self.boundaries[2 * i + 1]
FreeCAD.Console.PrintMessage("Interval %u: %f to %f, I_i: %f, C_i0: %f, C_i1: %f\n" % (i, begin, length, I_i, C_i0, C_i1))
xresult.append(xval)
# w(xval) = (transfunc(xval) + C_i0 * xval + C_i1) / (E * I_i)
value = (self.transfunc.value(xval) + C_i0 * xval + C_i1) / (E * I_i)
yresult.append(value)
return (xresult, yresult)

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
#/******************************************************************************
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
# * *
@@ -20,18 +21,18 @@
# * *
# ******************************************************************************/
import FreeCAD, FreeCADGui # FreeCAD just required for debug printing to the console...
from SegmentFunction import SegmentFunction
import FreeCAD, FreeCADGui
from SegmentFunction import SegmentFunction, IntervalFunction, StressFunction, TranslationFunction
from ShaftFeature import ShaftFeature
from ShaftDiagram import Diagram
import math
class ShaftSegment:
length = 0.0
diameter = 0.0
innerdiameter = 0.0
loadType = "None"
loadSize = 0.0
loadLocation = 0.0
constraintType = "None"
constraint = None
def __init__(self, l, d, di):
self.length = l
@@ -40,22 +41,47 @@ class ShaftSegment:
class Shaft:
"The axis of the shaft is always assumed to correspond to the X-axis"
parent = None
doc = None
# List of shaft segments (each segment has a different diameter)
segments = []
# The sketch
sketch = 0
#featureWindow = None
# The feature
feature = 0
# The diagrams
diagrams = {} # map of function name against Diagram object
# Calculation of shaft
Qy = 0 # force in direction of y axis
Qz = 0 # force in direction of z axis
Mbz = 0 # bending moment around z axis
Mby = 0 # bending moment around y axis
Mtz = 0 # torsion moment around z axis
F = [None, None, None] # force in direction of [x,y,z]-axis
M = [None, None, None] # bending moment around [x,z,y]-axis
w = [None, None, None] # Shaft translation due to bending
sigmaN = [None, None, None] # normal stress in direction of x-axis, shear stress in direction of [y,z]-axis
sigmaB = [None, None, None] # # torque stress around x-axis, maximum bending stress in direction of [y,z]-axis
# Names (note Qy corresponds with Mz, and Qz with My)
Fstr = ["Nx","Qy","Qz"] # Forces
Mstr = ["Mx","Mz","My"] # Moments
wstr = ["", "wy", "wz"] # Translations
sigmaNstr = ["sigmax","sigmay","sigmaz"] # Normal/shear stresses
sigmaBstr = ["taut","sigmabz", "sigmaby"] # Torsion/bending stresses
# For diagram labelling
Qstrings = (("Normal force [x]", "x", "mm", "N_x", "N"),
("Shear force [y]", "x", "mm", "Q_y", "N"),
("Shear force [z]", "x", "mm", "Q_z", "N"))
Mstrings = (("Torque [x]", "x", "mm", "M_t", "Nm"),
("Bending moment [z]", "x", "mm", "M_{b,z}", "Nm"),
("Bending moment [y]", "x", "mm", "M_{b,y}", "Nm"))
wstrings = (("", "", "", "", ""),
("Translation [y]", "x", "mm", "w_y", "mm"),
("Translation [z]", "x", "mm", "w_z", "mm"))
sigmaNstrings = (("Normal stress [x]", "x", "mm", "\sigma_x", u"N/mm²"),
("Shear stress [y]", "x", "mm", "\sigma_y", u"N/mm²"),
("Shear stress [z]", "x", "mm", "\sigma_z", u"N/mm²"))
sigmaBstrings = (("Torque stress [x]", "x", "mm", "\tau_t", u"N/mm²"),
("Bending stress [z]", "x", "mm", "\sigma_{b,z}", u"N/mm²"),
("Bending stress [y]", "x", "mm", "\sigma_{b,y}", u"N/mm²"))
def __init__(self, doc):
self.sketch = ShaftFeature(doc)
def __init__(self, parent):
self.parent = parent
self.doc = parent.doc
self.feature = ShaftFeature(self.doc)
def getLengthTo(self, index):
"Get the total length of all segments up to the given one"
@@ -65,40 +91,81 @@ class Shaft:
return result
def addSegment(self, l, d, di):
#print "Adding segment: ", l, " : ", d
self.segments.append(ShaftSegment(l,d,di))
self.sketch.addSegment(l, d, di)
# We don't call equilibrium() here because the new segment has no loads defined yet
self.feature.addSegment(l, d, di)
# We don't call equilibrium() here because the new segment has no constraints defined yet
# Fix face reference of fixed segment if it is the last one
for i in range(1, len(self.segments)):
if self.segments[i].constraintType is not "Fixed":
continue
if i == len(self.segments) - 1:
self.segments[index].constraint.References = [( self.feature.feature, "Face%u" % (2 * (index+1) + 1) )]
else:
# Remove reference since it is now in the middle of the shaft (which is not allowed)
self.segments[index].constraint.References = [(None, "")]
def updateSegment(self, index, length = None, diameter = None, innerdiameter = None):
oldLength = self.segments[index].length
#print "Old length of ", index, ": ", oldLength, ", new Length: ", length, " diameter: ", diameter
if length is not None:
self.segments[index].length = length
if diameter is not None:
self.segments[index].diameter = diameter
if innerdiameter is not None:
self.segments[index].innerdiameter = innerdiameter
self.sketch.updateSegment(index, oldLength, self.segments[index].length,
self.segments[index].diameter, self.segments[index].innerdiameter)
self.feature.updateSegment(index, oldLength, self.segments[index].length, self.segments[index].diameter, self.segments[index].innerdiameter)
self.equilibrium()
self.updateDiagrams()
def updateLoad(self, index, loadType = None, loadSize = None, loadLocation = None):
if (loadType is not None):
self.segments[index].loadType = loadType
if (loadSize is not None):
self.segments[index].loadSize = loadSize
if (loadLocation is not None):
if (loadLocation >= 0) and (loadLocation <= self.segments[index].length):
self.segments[index].loadLocation = loadLocation
else:
# TODO: Show warning
FreeCAD.Console.PrintMessage("Load location must be inside segment\n")
#self.feature.updateForces() graphical representation of the forces
def updateConstraint(self, index, constraintType):
if (constraintType is not None):
# Did the constraint type change?
if (self.segments[index].constraintType != "None") and (self.segments[index].constraintType != constraintType):
self.doc.removeObject(self.segments[index].constraint.Name)
self.segments[index].constraint = None
self.segments[index].constraintType = constraintType
# Create constraint if it does not exist yet or has changed
if self.segments[index].constraint is None:
if (constraintType == "Force"):
# TODO: Create a reference point and put the force onto it
constraint = self.doc.addObject("Fem::ConstraintForce","ShaftConstraintForce")
constraint.Force = 1000.0
self.segments[index].constraint = constraint
elif (constraintType == "Fixed"):
# TODO: Use robust reference as soon as it is available for the face
constraint = self.doc.addObject("Fem::ConstraintFixed","ShaftConstraintFixed")
if index == 0:
constraint.References = [( self.feature.feature, "Face1")]
elif index == len(self.segments) - 1:
constraint.References = [( self.feature.feature, "Face%u" % (2 * (index+1) + 1) )]
self.segments[index].constraint = constraint
elif (constraintType == "Bearing"):
# TODO: Use robust reference as soon as it is available for the cylindrical face reference
constraint = self.doc.addObject("Fem::ConstraintBearing","ShaftConstraintBearing")
constraint.References = [( self.feature.feature, "Face%u" % (2 * (index+1)) )]
constraint.AxialFree = True
self.segments[index].constraint = constraint
elif (constraintType == "Pulley"):
constraint= self.doc.addObject("Fem::ConstraintPulley","ShaftConstraintPulley")
constraint.References = [( self.feature.feature, "Face%u" % (2 * (index+1)) )]
self.segments[index].constraint = constraint
elif (constraintType == "Gear"):
constraint = self.doc.addObject("Fem::ConstraintGear","ShaftConstraintGear")
constraint.References = [( self.feature.feature, "Face%u" % (2 * (index+1)) )]
self.segments[index].constraint = constraint
self.equilibrium()
self.updateDiagrams()
def editConstraint(self, index):
if (self.segments[index].constraint is not None):
FreeCADGui.activeDocument().setEdit(self.segments[index].constraint.Name)
def getConstraint(self, index):
return self.segments[index].constraint
def updateEdge(self, column, start):
App.Console.PrintMessage("Not implemented yet - waiting for robust references...")
@@ -132,114 +199,375 @@ class Shaft:
# FIXME: This is impossible without robust references anchored in the sketch!!!
return
def updateDiagrams(self):
if (self.Qy == 0) or (self.Mbz == 0):
return
if self.Qy.name in self.diagrams:
# Update diagram
self.diagrams[self.Qy.name].update(self.Qy, self.getLengthTo(len(self.segments)) / 1000.0)
else:
# Create diagram
self.diagrams[self.Qy.name] = Diagram()
self.diagrams[self.Qy.name].create("Shear force", self.Qy, self.getLengthTo(len(self.segments)) / 1000.0, "x", "mm", 1000.0, "Q_y", "N", 1.0, 10)
if self.Mbz.name in self.diagrams:
# Update diagram
self.diagrams[self.Mbz.name].update(self.Mbz, self.getLengthTo(len(self.segments)) / 1000.0)
else:
# Create diagram
self.diagrams[self.Mbz.name] = Diagram()
self.diagrams[self.Mbz.name].create("Bending moment", self.Mbz, self.getLengthTo(len(self.segments)) / 1000.0, "x", "mm", 1000.0, "M_{b,z}", "Nm", 1.0, 10)
def updateDiagrams(self):
for ax in range(3):
if self.F[ax] is not None:
if self.F[ax].name in self.diagrams:
self.diagrams[self.F[ax].name].update(self.F[ax], self.getLengthTo(len(self.segments)) / 1000.0)
if self.M[ax] is not None:
if self.M[ax].name in self.diagrams:
self.diagrams[self.M[ax].name].update(self.M[ax], self.getLengthTo(len(self.segments)) / 1000.0)
if self.w[ax] is not None:
if self.w[ax].name in self.diagrams:
self.diagrams[self.w[ax].name].update(self.w[ax], self.getLengthTo(len(self.segments)) / 1000.0)
if self.sigmaN[ax] is not None:
if self.sigmaN[ax].name in self.diagrams:
self.diagrams[self.sigmaN[ax].name].update(self.sigmaN[ax], self.getLengthTo(len(self.segments)) / 1000.0)
if self.sigmaB[ax] is not None:
if self.sigmaB[ax].name in self.diagrams:
self.diagrams[self.sigmaB[ax].name].update(self.sigmaB[ax], self.getLengthTo(len(self.segments)) / 1000.0)
def showDiagram(self, which):
if which in self.Fstr:
ax = self.Fstr.index(which)
text = self.Qstrings[ax]
if self.F[ax] == None:
# No data
return
if self.F[ax].name in self.diagrams:
# Diagram is already open, close it again
self.diagrams[self.F[ax].name].close()
del (self.diagrams[self.F[ax].name])
return
self.diagrams[self.F[ax].name] = Diagram()
self.diagrams[self.F[ax].name].create(text[0], self.F[ax], self.getLengthTo(len(self.segments)) / 1000.0, text[1], text[2], 1000.0, text[3], text[4], 1.0, 10)
elif which in self.Mstr:
ax = self.Mstr.index(which)
text = self.Mstrings[ax]
if self.M[ax] == None:
# No data
return
if self.M[ax].name in self.diagrams:
# Diagram is already open, close it again
self.diagrams[self.M[ax].name].close()
del (self.diagrams[self.M[ax].name])
return
self.diagrams[self.M[ax].name] = Diagram()
self.diagrams[self.M[ax].name].create(text[0], self.M[ax], self.getLengthTo(len(self.segments)) / 1000.0, text[1], text[2], 1000.0, text[3], text[4], 1.0, 20)
elif which in self.wstr:
ax = self.wstr.index(which)
text = self.wstrings[ax]
if self.w[ax] == None:
# No data
return
if self.w[ax].name in self.diagrams:
# Diagram is already open, close it again
self.diagrams[self.w[ax].name].close()
del (self.diagrams[self.w[ax].name])
return
self.diagrams[self.w[ax].name] = Diagram()
self.diagrams[self.w[ax].name].create(text[0], self.w[ax], self.getLengthTo(len(self.segments)) / 1000.0, text[1], text[2], 1000.0, text[3], text[4], 1000.0, 30)
elif which in self.sigmaNstr:
ax = self.sigmaNstr.index(which)
text = self.sigmaNstrings[ax]
if self.sigmaN[ax] == None:
# No data
return
if self.sigmaN[ax].name in self.diagrams:
# Diagram is already open, close it again
self.diagrams[self.sigmaN[ax].name].close()
del (self.diagrams[self.sigmaN[ax].name])
return
self.diagrams[self.sigmaN[ax].name] = Diagram()
self.diagrams[self.sigmaN[ax].name].create(text[0], self.sigmaN[ax], self.getLengthTo(len(self.segments)) / 1000.0, text[1], text[2], 1000.0, text[3], text[4], 1.0E-6, 10)
elif which in self.sigmaBstr:
ax = self.sigmaBstr.index(which)
text = self.sigmaBstrings[ax]
if self.sigmaB[ax] == None:
# No data
return
if self.sigmaB[ax].name in self.diagrams:
# Diagram is already open, close it again
self.diagrams[self.sigmaB[ax].name].close()
del (self.diagrams[self.sigmaB[ax].name])
return
self.diagrams[self.sigmaB[ax].name] = Diagram()
self.diagrams[self.sigmaB[ax].name].create(text[0], self.sigmaB[ax], self.getLengthTo(len(self.segments)) / 1000.0, text[1], text[2], 1000.0, text[3], text[4], 1.0E-6, 20)
def addTo(self, dict, location, value):
if location not in dict:
dict[location] = value
else:
dict[location] += value
def equilibrium(self):
# Build equilibrium equations
forces = {0.0:0.0} # dictionary of (location : outer force)
moments = {0.0:0.0} # dictionary of (location : outer moment)
variableNames = [""] # names of all variables
locations = {} # dictionary of (variableName : location)
coefficientsFy = [0] # force equilibrium equation
coefficientsMbz = [0] # moment equilibrium equation
for i in range(len(self.segments)):
lType = self.segments[i].loadType
load = -1 # -1 means unknown (just for debug printing)
location = -1
if lType == "Fixed":
# Fixed segment
if i == 0:
location = 0
variableNames.append("Fy%u" % i)
coefficientsFy.append(1)
coefficientsMbz.append(0)
variableNames.append("Mz%u" % i)
coefficientsFy.append(0)
coefficientsMbz.append(1) # Force does not contribute because location is zero
elif i == len(self.segments) - 1:
location = self.getLengthTo(len(self.segments)) / 1000
variableNames.append("Fy%u" % i)
coefficientsFy.append(1)
coefficientsMbz.append(location)
variableNames.append("Mz%u" % i)
coefficientsFy.append(0)
coefficientsMbz.append(1)
else:
# TODO: Better error message
FreeCAD.Console.PrintMessage("Fixed constraint must be at beginning or end of shaft\n")
return
locations["Fy%u" % i] = location
locations["Mz%u" % i] = location
elif lType == "Static":
# Static load (currently force only)
load = self.segments[i].loadSize
location = (self.getLengthTo(i) + self.segments[i].loadLocation) / 1000 # convert to meters
coefficientsFy[0] = coefficientsFy[0] - load
forces[location] = load
coefficientsMbz[0] = coefficientsMbz[0] - load * location
moments[location] = 0
#elif lType == "None":
# # No loads on segment
FreeCAD.Console.PrintMessage("Segment: %u, type: %s, load: %f, location: %f\n" % (i, lType, load, location))
self.printEquilibrium(variableNames, coefficientsFy)
self.printEquilibrium(variableNames, coefficientsMbz)
# Build matrix and vector for linear algebra solving algorithm
try:
import numpy as np
except ImportError:
FreeCAD.Console.PrintMessage("numpy is not installed on your system\n")
raise ImportError("numpy not installed")
if (len(coefficientsFy) < 3) or (len(coefficientsMbz) < 3):
return
A = np.array([coefficientsFy[1:], coefficientsMbz[1:]])
b = np.array([coefficientsFy[0], coefficientsMbz[0]])
solution = np.linalg.solve(A, b)
# Initialization of structures. All three axes are handled separately so everything is 3-fold
# dictionaries of (location : outer force/moment) with reverse sign, which means that the segment functions for the section force and section moment
# created from them will have signs as by the convention in
# http://www.umwelt-campus.de/ucb/fileadmin/users/90_t.preussler/dokumente/Skripte/TEMECH/TMI/Ebene_Balkenstatik.pdf (page 10)
# (see also example on page 19)
forces = [{0.0:0.0}, {0.0:0.0}, {0.0:0.0}]
moments = [{0.0:0.0}, {0.0:0.0}, {0.0:0.0}]
# Boundary conditions for shaft bending line
tangents = [[], [], []] # Tangents to shaft bending line
translations = [[], [], []] # Shaft displacement
# Variable names, e.g. Fx, Mz. Because the system must be exactly determined, not more than two independent variables for each
# force/moment per axis are possible (if there are more no solution is calculated)
variableNames = [[""], [""], [""]]
# # dictionary of (variableName : location) giving the x-coordinate at which the force/moment represented by the variable acts on the shaft
locations = {}
# Coefficients of the equilibrium equations in the form a = b * F1 + c * F2 and d = e * M1 + f * M2
# LHS (variables a1, a2, a3, d3) initialized to zero
coefficientsF = [[0], [0], [0]]
coefficientsM = [[0], [0], [0]]
# Complete dictionary of forces and moments
if variableNames[1][0] == "F":
forces[locations[variableNames[1]]] = solution[0]
else:
moments[locations[variableNames[1]]] = solution[0]
for i in range(len(self.segments)):
cType = self.segments[i].constraintType
constraint = self.segments[i].constraint
if cType == "Fixed":
# Fixed segment
if i == 0:
# At beginning of shaft
location = 0
elif i == len(self.segments) - 1:
# At end of shaft
location = self.getLengthTo(len(self.segments)) / 1000.0 # convert to meters
else:
# TODO: Better error message
FreeCAD.Console.PrintMessage("Fixed constraint must be at beginning or end of shaft\n")
return
for ax in range(3):
# Create a new reaction force
variableNames[ax].append("%s%u" % (self.Fstr[ax], i))
coefficientsF[ax].append(1)
# Register location of reaction force
locations["%s%u" % (self.Fstr[ax], i)] = location
# Boundary conditions for the translations
tangents[ax].append((location, 0.0))
translations[ax].append((location, 0.0))
coefficientsM[0].append(0) # Reaction force contributes no moment around x axis
coefficientsM[1].append(location) # Reaction force contributes a positive moment around z axis
coefficientsM[2].append(-location) # Reaction force contributes a negative moment around y axis
for ax in range(3):
# Create a new reaction moment
variableNames[ax].append("%s%u" % (self.Mstr[ax], i))
coefficientsF[ax].append(0)
coefficientsM[ax].append(1)
locations["%s%u" % (self.Mstr[ax], i)] = location
elif cType == "Force":
# Static force (currently force on midpoint of segment only)
force = constraint.DirectionVector.multiply(constraint.Force)
# TODO: Extract value of the location from geometry
location = (self.getLengthTo(i) + self.segments[i].length/2.0) / 1000.0
# The force itself
for ax in range(3):
if abs(force[ax]) > 0.0:
coefficientsF[ax][0] = coefficientsF[ax][0] - force[ax] # neg. because this coefficient is on the LHS of the equilibrium equation
self.addTo(forces[ax], location, -force[ax]) # neg. to fulfill the convention mentioned above
# Moments created by the force (by definition no moment is created by the force in x-direction)
if abs(force[1]) > 0.0:
coefficientsM[1][0] = coefficientsM[1][0] - force[1] * location # moment around z-axis
self.addTo(moments[1], location, 0)
if abs(force[2]) > 0.0:
coefficientsM[2][0] = coefficientsM[2][0] + force[2] * location # moment around y-axis
self.addTo(moments[2], location, 0) # No outer moment acts here!
elif cType == "Bearing":
location = constraint.BasePoint.x / 1000.0 # TODO: This assumes that the shaft feature starts with the first segment at (0,0,0) and its axis corresponds to the x-axis
# Bearing reaction forces. TODO: the bearing is assumed to not induce any reaction moments
start = (0 if constraint.AxialFree == False else 1)
for ax in range(start, 3):
variableNames[ax].append("%s%u" % (self.Fstr[ax], i))
coefficientsF[ax].append(1)
locations["%s%u" % (self.Fstr[ax], i)] = location
# Boundary condition
translations[ax].append((location, 0.0))
if constraint.AxialFree == False:
coefficientsM[0].append(0) # Reaction force contributes no moment around x axis
coefficientsM[1].append(location) # Reaction force contributes a positive moment around z axis
coefficientsM[2].append(-location) # Reaction force contributes a negative moment around y axis
elif cType == "Gear":
force = constraint.DirectionVector.multiply(constraint.Force)
location = constraint.BasePoint.x / 1000.0
lever = [0, constraint.Diameter/2.0/1000.0 * math.sin(constraint.ForceAngle / 180.0 * math.pi),
constraint.Diameter/2.0 /1000.0* math.cos(constraint.ForceAngle / 180.0 * math.pi)]
# Effect of the gear force
for ax in range(3):
if abs(force[ax]) > 0.0:
# Effect of the force
coefficientsF[ax][0] = coefficientsF[ax][0] - force[ax]
self.addTo(forces[ax], location, -force[ax])
# Moments created by the force (by definition no moment is created by the force in x-direction)
if abs(force[1]) > 0.0:
coefficientsM[1][0] = coefficientsM[1][0] - force[1] * location # moment around z-axis
self.addTo(moments[1], location, 0)
if abs(force[2]) > 0.0:
coefficientsM[2][0] = coefficientsM[2][0] + force[2] * location # moment around y-axis
self.addTo(moments[2], location, 0) # No outer moment acts here!
# Moments created by the force and lever
if abs(force[0]) > 0.0:
momenty = force[0] * lever[2]
momentz = force[0] * lever[1]
coefficientsM[1][0] = coefficientsM[1][0] + momentz # moment around z-axis
self.addTo(moments[1], location, momentz)
coefficientsM[2][0] = coefficientsM[2][0] - momenty # moment around y-axis
self.addTo(moments[2], location, -momenty)
if abs(force[1]) > 0.0:
moment = force[1] * lever[2]
coefficientsM[0][0] = coefficientsM[0][0] + moment
self.addTo(moments[0], location, moment)
if abs(force[2]) > 0.0:
moment = force[2] * lever[1]
coefficientsM[0][0] = coefficientsM[0][0] - moment
self.addTo(moments[0], location, -moment)
elif cType == "Pulley":
forceAngle1 = (constraint.ForceAngle + constraint.BeltAngle + 90.0) / 180.0 * math.pi
forceAngle2 = (constraint.ForceAngle - constraint.BeltAngle + 90.0) / 180.0 * math.pi
#FreeCAD.Console.PrintMessage("BeltForce1: %f, BeltForce2: %f\n" % (constraint.BeltForce1, constraint.BeltForce2))
#FreeCAD.Console.PrintMessage("Angle1: %f, Angle2: %f\n" % (forceAngle1, forceAngle2))
force = [0, -constraint.BeltForce1 * math.sin(forceAngle1) - constraint.BeltForce2 * math.sin(forceAngle2),
constraint.BeltForce1 * math.cos(forceAngle1) + constraint.BeltForce2 * math.cos(forceAngle2)]
location = constraint.BasePoint.x / 1000.0
# Effect of the pulley forces
for ax in range(3):
if abs(force[ax]) > 0.0:
# Effect of the force
coefficientsF[ax][0] = coefficientsF[ax][0] - force[ax]
self.addTo(forces[ax], location, -force[ax])
# Moments created by the force (by definition no moment is created by the force in x-direction)
if abs(force[1] ) > 0.0:
coefficientsM[1][0] = coefficientsM[1][0] - force[1] * location # moment around z-axis
self.addTo(moments[1], location, 0)
if abs(force[2]) > 0.0:
coefficientsM[2][0] = coefficientsM[2][0] + force[2] * location # moment around y-axis
self.addTo(moments[2], location, 0) # No outer moment acts here!
# Torque
moment = constraint.Force * (1 if constraint.IsDriven is True else -1)
coefficientsM[0][0] = coefficientsM[0][0] + moment
self.addTo(moments[0], location, moment)
if variableNames[2][0] == "F":
forces[locations[variableNames[2]]] = solution[1]
else:
moments[locations[variableNames[2]]] = solution[1]
areas = [None, None, None]
areamoments = [None, None, None]
bendingmoments = [None, None, None]
torquemoments = [None, None, None]
for ax in range(3):
FreeCAD.Console.PrintMessage("Axis: %u\n" % ax)
self.printEquilibrium(variableNames[ax], coefficientsF[ax])
self.printEquilibrium(variableNames[ax], coefficientsM[ax])
FreeCAD.Console.PrintMessage(forces)
FreeCAD.Console.PrintMessage(moments)
self.Qy = SegmentFunction("Qy")
self.Qy.buildFromDict("x", forces)
self.Qy.output()
self.Mbz = self.Qy.integrated().negate()
self.Mbz.addSegments(moments) # takes care of boundary conditions
self.Mbz.name = "Mbz"
self.Mbz.output()
if len(coefficientsF[ax]) <= 1:
# Note: coefficientsF and coefficientsM always have the same length
FreeCAD.Console.PrintMessage("Matrix is singular, no solution possible\n")
self.parent.updateButtons(ax, False)
continue
# Handle special cases. Note that the code above should ensure that coefficientsF and coefficientsM always have same length
solution = [None, None]
if len(coefficientsF[ax]) == 2:
if coefficientsF[ax][1] != 0.0 and coefficientsF[ax][0] != 0.0:
solution[0] = coefficientsF[ax][0] / coefficientsF[ax][1]
if coefficientsM[ax][1] != 0.0 and coefficientsM[ax][0] != 0.0:
solution[1] = coefficientsM[ax][0] / coefficientsM[ax][1]
if abs(solution[0] - solution[1]) < 1E9:
FreeCAD.Console.PrintMessage("System is statically undetermined. No solution possible.\n")
self.parent.updateButtons(ax, False)
continue
else:
# Build matrix and vector for linear algebra solving algorithm
# TODO: This could easily be done manually... there are only 2 variables and 6 coefficients
A = np.array([coefficientsF[ax][1:], coefficientsM[ax][1:]])
b = np.array([coefficientsF[ax][0], coefficientsM[ax][0]])
try:
solution = np.linalg.solve(A, b) # A * solution = b
except np.linalg.linalg.LinAlgError, e:
FreeCAD.Console.PrintMessage(e.message)
FreeCAD.Console.PrintMessage(". No solution possible.\n")
self.parent.updateButtons(ax, False)
continue
# Complete dictionary of forces and moments with the two reaction forces that were calculated
for i in range(2):
if solution[i] is None:
continue
FreeCAD.Console.PrintMessage("Reaction force/moment: %s = %f\n" % (variableNames[ax][i+1], solution[i]))
if variableNames[ax][i+1][0] == "M":
moments[ax][locations[variableNames[ax][i+1]]] = -solution[i]
else:
forces[ax][locations[variableNames[ax][i+1]]] = -solution[i]
FreeCAD.Console.PrintMessage(forces[ax])
FreeCAD.Console.PrintMessage("\n")
FreeCAD.Console.PrintMessage(moments[ax])
FreeCAD.Console.PrintMessage("\n")
# Forces
self.F[ax] = SegmentFunction(self.Fstr[ax])
self.F[ax].buildFromDict("x", forces[ax])
self.parent.updateButton(1, ax, not self.F[ax].isZero())
self.F[ax].output()
# Moments
if ax == 0:
self.M[0] = SegmentFunction(self.Mstr[0])
self.M[0].buildFromDict("x", moments[0])
elif ax == 1:
self.M[1] = self.F[1].integrated().negate()
self.M[1].name = self.Mstr[1]
self.M[1].addSegments(moments[1]) # takes care of boundary conditions
elif ax == 2:
self.M[2] = self.F[2].integrated()
self.M[2].name = self.Mstr[2]
self.M[2].addSegments(moments[2]) # takes care of boundary conditions
self.parent.updateButton(2, ax, not self.M[ax].isZero())
self.M[ax].output()
# Areas and area moments
location = 0.0
areas[ax] = IntervalFunction() # A [m²]
areamoments[ax] = IntervalFunction() # I [m⁴]
bendingmoments[ax] = IntervalFunction() # W_b [m³]
torquemoments[ax] = IntervalFunction() # W_t [m³]
for i in range(len(self.segments)):
od = self.segments[i].diameter/1000.0
id = self.segments[i].innerdiameter/1000.0
length = self.segments[i].length/1000.0
areas[ax].addInterval(location, length, math.pi/4.0 * (math.pow(od, 2.0) - math.pow(id, 2.0)))
areamoment = math.pi/64.0 * (math.pow(od, 4.0) - math.pow(id, 4.0))
areamoments[ax].addInterval(location, length, areamoment)
bendingmoments[ax].addInterval(location, length, areamoment / (od / 2.0))
torquemoments[ax].addInterval(location, length, 2 * (areamoment / (od / 2.0)))
location += length
# Bending line
if ax > 0:
if len(tangents[ax])+ len(translations[ax]) == 2:
# TODO: Get Young's module from material type instead of using 210000 N/mm² = 2.1E12 N/m²
self.w[ax] = TranslationFunction(self.M[ax].negated(), 2.1E12, areamoments[ax], tangents[ax], translations[ax])
self.w[ax].name= self.wstr[ax]
self.parent.updateButton(3, ax, not self.w[ax].isZero())
else:
self.parent.updateButton(3, ax, False)
# Normal/shear stresses and torque/bending stresses
self.sigmaN[ax] = StressFunction(self.F[ax], areas[ax])
self.sigmaN[ax].name = self.sigmaNstr[ax]
self.parent.updateButton(4, ax, not self.sigmaN[ax].isZero())
if ax == 0:
self.sigmaB[ax] = StressFunction(self.M[ax] , torquemoments[ax])
else:
self.sigmaB[ax] = StressFunction(self.M[ax], bendingmoments[ax])
self.sigmaB[ax].name = self.sigmaBstr[ax]
self.parent.updateButton(5, ax, not self.sigmaB[ax].isZero())
def printEquilibrium(self, var, coeff):
# Auxiliary method for debugging purposes
# Auxiliary method for debugging purposes
for i in range(len(var)):
if i == 0:
FreeCAD.Console.PrintMessage("%f = " % coeff[i])

View File

@@ -38,6 +38,7 @@ class Diagram:
ypoints = []
# Plot object
thePlot = None
win = None
def create(self, title, function, xlength, xname, xunit, xscale, yname, yunit, yscale, numxpoints):
# Initialize
@@ -54,7 +55,7 @@ class Diagram:
self.numxpoints = numxpoints
# Create a plot window
win = Plot.figure(title)
self.win = Plot.figure(title)
# Get the plot object from the window
self.thePlot = Plot.getPlot()
# Format the plot object
@@ -96,3 +97,7 @@ class Diagram:
axes.set_xlim(right = max(self.xpoints) * 1.05)
axes.set_ylim(min(self.ypoints) * 1.05, max(self.ypoints) * 1.05)
self.thePlot.update()
def close(self):
# Close the associated mdiSubWindow
self.win.parent().close()

View File

@@ -21,7 +21,6 @@
# ******************************************************************************/
import FreeCAD, FreeCADGui
#import os
from PyQt4 import QtCore, QtGui
from WizardShaftTable import WizardShaftTable
from Shaft import Shaft
@@ -38,6 +37,8 @@ class TaskWizardShaft:
shaft = 0
# Feature
featureWindow = 0
# Buttons
buttons = [[None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None]]
def __init__(self, doc):
mw = QtGui.qApp.activeWindow()
@@ -54,15 +55,97 @@ class TaskWizardShaft:
featureWindow = cw.subWindowList()[-1]
else:
featureWindow = cw.activeSubWindow()
# Buttons for diagram display
buttons = QtGui.QGridLayout()
bnames = [["All [x]", "All [y]", "All [z]" ],
["N [x]", "Q [y]", "Q [z]"],
["Mt [x]", "Mb [z]", "Mb [y]"],
["", "w [y]", "w [z]"],
["sigma [x]", "sigma [y]", "sigma [z]"],
["tau [x]", "sigmab [z]", "sigmab [y]"]]
slots = [[self.slotAllx, self.slotAlly, self.slotAllz],
[self.slotFx, self.slotQy, self.slotQz],
[self.slotMx, self.slotMz, self.slotMy],
[self.slotNone, self.slotWy, self.slotWz],
[self.slotSigmax, self.slotSigmay, self.slotSigmaz],
[self.slotTaut, self.slotSigmabz, self.slotSigmaby]]
for col in range(3):
for row in range(6):
button = QtGui.QPushButton(bnames[row][col])
buttons.addWidget(button, row, col)
self.buttons[row][col] = button
button.clicked.connect(slots[row][col])
# Create Shaft object
self.shaft = Shaft(self.doc)
# Assign a table widget to the dock window
self.table = WizardShaftTable(self, self.shaft)
self.form = self.table.widget
self.form.setWindowTitle("Shaft wizard")
self.shaft = Shaft(self)
# Create table widget
self.form = QtGui.QWidget()
self.table = WizardShaftTable(self, self.shaft)
# The top layout will contain the Shaft Wizard layout plus the elements of the FEM constraints dialog
layout = QtGui.QVBoxLayout()
layout.setObjectName("ShaftWizard") # Do not change or translate: Required to detect whether Shaft Wizard is running in FemGui::ViewProviderFemConstraintXXX
sublayout = QtGui.QVBoxLayout()
sublayout.setObjectName("ShaftWizardLayout") # Do not change or translate
sublayout.addWidget(self.table.widget)
sublayout.addLayout(buttons)
layout.addLayout(sublayout)
self.form.setLayout(layout)
# Switch to feature window
mdi=QtGui.qApp.activeWindow().findChild(QtGui.QMdiArea)
cw.setActiveSubWindow(featureWindow)
def slotAllx(self):
self.shaft.showDiagram("Allx")
def slotAlly(self):
self.shaft.showDiagram("Ally")
def slotAllz(self):
self.shaft.showDiagram("Allz")
def slotFx(self):
self.shaft.showDiagram("Nx")
def slotQy(self):
self.shaft.showDiagram("Qy")
def slotQz(self):
self.shaft.showDiagram("Qz")
def slotMx(self):
self.shaft.showDiagram("Mx")
def slotMz(self):
self.shaft.showDiagram("Mz")
def slotMy(self):
self.shaft.showDiagram("My")
def slotNone(self):
pass
def slotWy(self):
self.shaft.showDiagram("wy")
def slotWz(self):
self.shaft.showDiagram("wz")
def slotSigmax(self):
self.shaft.showDiagram("sigmax")
def slotSigmay(self):
self.shaft.showDiagram("sigmay")
def slotSigmaz(self):
self.shaft.showDiagram("sigmaz")
def slotTaut(self):
self.shaft.showDiagram("taut")
def slotSigmabz(self):
self.shaft.showDiagram("sigmabz")
def slotSigmaby(self):
self.shaft.showDiagram("sigmaby")
def updateButton(self, row, col, flag):
self.buttons[row][col].setEnabled(flag)
def updateButtons(self, col, flag):
for row in range(len(self.buttons)):
self.updateButton(row, col, flag)
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
@@ -75,10 +158,20 @@ class TaskWizardShaft:
del self.form
return True
class WizardShaftGui:
def Activated(self):
FreeCADGui.Control.showDialog(TaskWizardShaft(FreeCAD.ActiveDocument))
# Work-around to allow a callback
# Problem: From the FemConstraint ViewProvider, we need to tell the Shaft instance that the user finished editing the constraint
# We can find the Shaft Wizard dialog object from C++, but there is not way to reach the Shaft instance
# Also it seems to be impossible to access the active dialog from Python, so Gui::Command::runCommand() is not an option either
# Note: Another way would be to create a hidden widget in the Shaft Wizard dialog and write some data to it, triggering a slot
# in the python code
WizardShaftDlg = None
class WizardShaftGui:
def Activated(self):
global WizardShaftDlg
WizardShaftDlg = TaskWizardShaft(FreeCAD.ActiveDocument)
FreeCADGui.Control.showDialog(WizardShaftDlg)
def GetResources(self):
IconPath = FreeCAD.ConfigGet("AppHomePath") + "Mod/PartDesign/WizardShaft/WizardShaft.svg"
MenuText = 'Shaft design wizard...'
@@ -87,8 +180,29 @@ class WizardShaftGui:
def IsActive(self):
return FreeCAD.ActiveDocument != None
def __del__(self):
global WizardShaftDlg
WizardShaftDlg = None
class WizardShaftGuiCallback:
def Activated(self):
global WizardShaftDlg
if WizardShaftDlg != None and WizardShaftDlg.table != None:
WizardShaftDlg.table.finishEditConstraint()
def isActive(self):
global WizardShaftDlg
return (WizardShaftDlg is not None)
def GetResources(self):
IconPath = FreeCAD.ConfigGet("AppHomePath") + "Mod/PartDesign/WizardShaft/WizardShaft.svg"
MenuText = 'Shaft design wizard...'
ToolTip = 'Start the shaft design wizard'
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
FreeCADGui.addCommand('PartDesign_WizardShaft', WizardShaftGui())
FreeCADGui.addCommand('PartDesign_WizardShaftCallBack', WizardShaftGuiCallback())
#Note: Start wizard in Python Console with
# Gui.runCommand('PartDesign_WizardShaft')

View File

@@ -31,21 +31,18 @@ class WizardShaftTable:
"Length" : 0,
"Diameter" : 1,
"InnerDiameter" : 2,
"LoadType" : 3,
"LoadSize" : 4,
"LoadLocation" : 5,
"StartEdgeType" : 6,
"StartEdgeSize" : 7,
"EndEdgeType" : 8,
"EndEdgeSize" : 9
"ConstraintType" : 3,
"StartEdgeType" : 4,
"StartEdgeSize" : 5,
"EndEdgeType" : 6,
"EndEdgeSize" : 7
}
rowDictReverse = {}
headers = ["Length [mm]",
headers = [
"Length [mm]",
"Diameter [mm]",
"Inner diameter [mm]",
"Load type",
"Load [N]",
"Location [mm]",
"Constraint type",
"Start edge type",
"Start edge size",
"End edge type",
@@ -54,6 +51,8 @@ class WizardShaftTable:
widget = 0
wizard = 0
shaft = 0
editedRow = None
editedColumn = None
def __init__(self, w, s):
for key in self.rowDict.iterkeys():
@@ -62,9 +61,10 @@ class WizardShaftTable:
self.wizard = w
self.shaft = s
# Create table widget
self.widget = QtGui.QTableWidget(len(self.rowDict), 0)
self.widget = QtGui.QTableWidget(len(self.rowDict), 0)
self.widget.setObjectName("ShaftWizardTable") # Do not change or translate: Used in ViewProviderFemConstraintXXX
self.widget.setWindowTitle("Shaft wizard")
self.widget.resize(QtCore.QSize(300,200))
#self.widget.setFocusPolicy(QtCore.Qt.StrongFocus)
# Label rows and columns
self.widget.setVerticalHeaderLabels(self.headers)
@@ -82,14 +82,12 @@ class WizardShaftTable:
self.addColumn()
self.setLength(0, 40.0)
self.setDiameter(0, 50.0)
self.setLoadType(0, "Static")
self.setLoadSize(0, 1000.0)
self.setLoadLocation(0, 25.0)
self.setConstraintType(0, "Bearing")
# Section 2
self.addColumn()
self.setLength(1, 80.0)
self.setDiameter(1, 60.0)
self.setLoadType(1, "Fixed")
self.setConstraintType(1, "Force")
def slotInsertColumn(self, point):
# FIXME: Allow inserting columns, not just adding at the end
@@ -144,32 +142,21 @@ class WizardShaftTable:
widget.setValue(innerdiameter)
widget.valueChanged.connect(self.slotValueChanged)
widget.editingFinished.connect(self.slotEditingFinished)
# Load type
# Constraint type
widget = QtGui.QComboBox(self.widget)
widget.insertItem(0, "None")
widget.insertItem(1, "Fixed")
widget.insertItem(2, "Static")
widget.insertItem(2, "Force")
widget.insertItem(3, "Bearing")
widget.insertItem(4, "Pulley")
self.widget.setCellWidget(self.rowDict["LoadType"], index, widget)
widget.insertItem(4, "Gear")
widget.insertItem(5, "Pulley")
action = QtGui.QAction("Edit constraint", widget)
action.triggered.connect(self.slotEditConstraint)
widget.addAction(action)
widget.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.widget.setCellWidget(self.rowDict["ConstraintType"], index, widget)
widget.setCurrentIndex(0)
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
# Load size
widget = QtGui.QDoubleSpinBox(self.widget)
widget.setMinimum(-1E9)
widget.setMaximum(1E9)
self.widget.setCellWidget(self.rowDict["LoadSize"], index, widget)
widget.setValue(0)
widget.valueChanged.connect(self.slotValueChanged)
widget.editingFinished.connect(self.slotEditingFinished)
# Load location
widget = QtGui.QDoubleSpinBox(self.widget)
widget.setMinimum(0)
widget.setMaximum(1E9)
self.widget.setCellWidget(self.rowDict["LoadLocation"], index, widget)
widget.setValue(0)
widget.valueChanged.connect(self.slotValueChanged)
widget.editingFinished.connect(self.slotEditingFinished)
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotConstraintType)
# Start edge type
widget = QtGui.QComboBox(self.widget)
widget.insertItem(0, "None",)
@@ -177,7 +164,7 @@ class WizardShaftTable:
widget.insertItem(2, "Fillet")
self.widget.setCellWidget(self.rowDict["StartEdgeType"],index, widget)
widget.setCurrentIndex(0)
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
#self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
# Start edge size
widget = QtGui.QDoubleSpinBox(self.widget)
widget.setMinimum(0)
@@ -193,7 +180,7 @@ class WizardShaftTable:
widget.insertItem(2, "Fillet")
self.widget.setCellWidget(self.rowDict["EndEdgeType"],index, widget)
widget.setCurrentIndex(0)
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
#self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
# End edge size
widget = QtGui.QDoubleSpinBox(self.widget)
widget.setMinimum(0)
@@ -208,6 +195,8 @@ class WizardShaftTable:
self.editedValue = value
def slotEditingFinished(self):
if self.editedRow == None:
return
rowName = self.rowDictReverse[self.editedRow]
if rowName is None:
return
@@ -217,12 +206,8 @@ class WizardShaftTable:
self.shaft.updateSegment(self.editedColumn, diameter = self.getDoubleValue(rowName, self.editedColumn))
elif rowName == "InnerDiameter":
self.shaft.updateSegment(self.editedColumn, innerdiameter = self.getDoubleValue(rowName, self.editedColumn))
elif rowName == "LoadType":
self.shaft.updateLoad(self.editedColumn, loadType = self.getListValue(rowName, self.editedColumn))
elif rowName == "LoadSize":
self.shaft.updateLoad(self.editedColumn, loadSize = self.getDoubleValue(rowName, self.editedColumn))
elif rowName == "LoadLocation":
self.shaft.updateLoad(self.editedColumn, loadLocation = self.getDoubleValue(rowName, self.editedColumn))
elif rowName == "Constraintype":
self.shaft.updateConstraint(self.editedColumn, self.getListValue(rowName, self.editedColumn))
elif rowName == "StartEdgeType":
pass
elif rowName == "StartEdgeSize":
@@ -232,6 +217,13 @@ class WizardShaftTable:
elif rowName == "EndEdgeSize":
pass
def slotEditConstraint(self):
(self.editedRow, self.editedColumn) = self.getFocusedCell() # Because finishEditConstraint() will trigger slotEditingFinished() which requires this information
self.shaft.editConstraint(self.editedColumn)
def finishEditConstraint(self):
self.shaft.updateConstraint(self.editedColumn, self.getConstraintType(self.editedColumn))
def setLength(self, column, l):
self.setDoubleValue("Length", column, l)
self.shaft.updateSegment(column, length = l)
@@ -254,32 +246,15 @@ class WizardShaftTable:
return self.getDoubleValue("InnerDiameter", column)
@QtCore.pyqtSlot('QString')
def slotLoadType(self, text):
if text != "Fixed":
if (self.getLoadSize is None) or (self.getLoadLocation is None):
return
self.shaft.updateLoad(self.getFocusedColumn(), loadType = text)
def slotConstraintType(self, text):
self.shaft.updateConstraint(self.getFocusedColumn(), text)
def setLoadType(self, column, t):
self.setListValue("LoadType", column, t)
self.shaft.updateLoad(column, loadType = t)
def setConstraintType(self, column, t):
self.setListValue("ConstraintType", column, t)
self.shaft.updateConstraint(column, t)
def getLoadType(self, column):
return self.getListValue("LoadType", column)
def setLoadSize(self, column, s):
self.setDoubleValue("LoadSize", column, s)
self.shaft.updateLoad(column, loadSize = s)
def getLoadSize(self, column):
return self.getDoubleValue("LoadSize", column)
def setLoadLocation(self, column, l):
self.setDoubleValue("LoadLocation", column, l)
self.shaft.updateLoad(column, loadLocation = l)
def getLoadLocation(self, column):
return self.getDoubleValue("LoadLocation", column)
def getConstraintType(self, column):
return self.getListValue("ConstraintType", column)
def slotStartEdgeType(self, old, new):
pass
@@ -334,7 +309,7 @@ class WizardShaftTable:
def getListValue(self, row, column):
widget = self.widget.cellWidget(self.rowDict[row], column)
if widget is not None:
return widget.currentText().toAscii()[0].upper()
return widget.currentText().toAscii() #[0].upper()
else:
return None