Intgrate Jans FEM PullRequest
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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}
|
||||
)
|
||||
|
||||
329
src/Mod/Fem/App/FemConstraint.cpp
Normal file
329
src/Mod/Fem/App/FemConstraint.cpp
Normal 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;
|
||||
}
|
||||
73
src/Mod/Fem/App/FemConstraint.h
Normal file
73
src/Mod/Fem/App/FemConstraint.h
Normal 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
|
||||
117
src/Mod/Fem/App/FemConstraintBearing.cpp
Normal file
117
src/Mod/Fem/App/FemConstraintBearing.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
71
src/Mod/Fem/App/FemConstraintBearing.h
Normal file
71
src/Mod/Fem/App/FemConstraintBearing.h
Normal 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
|
||||
84
src/Mod/Fem/App/FemConstraintFixed.cpp
Normal file
84
src/Mod/Fem/App/FemConstraintFixed.cpp
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/Mod/Fem/App/FemConstraintFixed.h
Normal file
63
src/Mod/Fem/App/FemConstraintFixed.h
Normal 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
|
||||
101
src/Mod/Fem/App/FemConstraintForce.cpp
Normal file
101
src/Mod/Fem/App/FemConstraintForce.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/Mod/Fem/App/FemConstraintForce.h
Normal file
69
src/Mod/Fem/App/FemConstraintForce.h
Normal 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
|
||||
86
src/Mod/Fem/App/FemConstraintGear.cpp
Normal file
86
src/Mod/Fem/App/FemConstraintGear.cpp
Normal 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
|
||||
}
|
||||
70
src/Mod/Fem/App/FemConstraintGear.h
Normal file
70
src/Mod/Fem/App/FemConstraintGear.h
Normal 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
|
||||
98
src/Mod/Fem/App/FemConstraintPulley.cpp
Normal file
98
src/Mod/Fem/App/FemConstraintPulley.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
73
src/Mod/Fem/App/FemConstraintPulley.h
Normal file
73
src/Mod/Fem/App/FemConstraintPulley.h
Normal 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
|
||||
@@ -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();
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
435
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintBearing.svg
Normal file
435
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintBearing.svg
Normal 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 |
192
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintFixed.svg
Normal file
192
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintFixed.svg
Normal 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 |
204
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintForce.svg
Normal file
204
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintForce.svg
Normal 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 |
1175
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintGear.svg
Normal file
1175
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintGear.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 46 KiB |
1069
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintPulley.svg
Normal file
1069
src/Mod/Fem/Gui/Resources/icons/Fem_ConstraintPulley.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 38 KiB |
212
src/Mod/Fem/Gui/TaskFemConstraint.cpp
Normal file
212
src/Mod/Fem/Gui/TaskFemConstraint.cpp
Normal 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"
|
||||
107
src/Mod/Fem/Gui/TaskFemConstraint.h
Normal file
107
src/Mod/Fem/Gui/TaskFemConstraint.h
Normal 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
|
||||
208
src/Mod/Fem/Gui/TaskFemConstraint.ui
Normal file
208
src/Mod/Fem/Gui/TaskFemConstraint.ui
Normal 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>
|
||||
356
src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp
Normal file
356
src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp
Normal 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"
|
||||
92
src/Mod/Fem/Gui/TaskFemConstraintBearing.h
Normal file
92
src/Mod/Fem/Gui/TaskFemConstraintBearing.h
Normal 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
|
||||
270
src/Mod/Fem/Gui/TaskFemConstraintBearing.ui
Normal file
270
src/Mod/Fem/Gui/TaskFemConstraintBearing.ui
Normal 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>
|
||||
217
src/Mod/Fem/Gui/TaskFemConstraintFixed.cpp
Normal file
217
src/Mod/Fem/Gui/TaskFemConstraintFixed.cpp
Normal 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"
|
||||
84
src/Mod/Fem/Gui/TaskFemConstraintFixed.h
Normal file
84
src/Mod/Fem/Gui/TaskFemConstraintFixed.h
Normal 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
|
||||
44
src/Mod/Fem/Gui/TaskFemConstraintFixed.ui
Normal file
44
src/Mod/Fem/Gui/TaskFemConstraintFixed.ui
Normal 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>
|
||||
363
src/Mod/Fem/Gui/TaskFemConstraintForce.cpp
Normal file
363
src/Mod/Fem/Gui/TaskFemConstraintForce.cpp
Normal 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"
|
||||
92
src/Mod/Fem/Gui/TaskFemConstraintForce.h
Normal file
92
src/Mod/Fem/Gui/TaskFemConstraintForce.h
Normal 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
|
||||
89
src/Mod/Fem/Gui/TaskFemConstraintForce.ui
Normal file
89
src/Mod/Fem/Gui/TaskFemConstraintForce.ui
Normal 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>
|
||||
315
src/Mod/Fem/Gui/TaskFemConstraintGear.cpp
Normal file
315
src/Mod/Fem/Gui/TaskFemConstraintGear.cpp
Normal 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"
|
||||
79
src/Mod/Fem/Gui/TaskFemConstraintGear.h
Normal file
79
src/Mod/Fem/Gui/TaskFemConstraintGear.h
Normal 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
|
||||
210
src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp
Normal file
210
src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp
Normal 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"
|
||||
74
src/Mod/Fem/Gui/TaskFemConstraintPulley.h
Normal file
74
src/Mod/Fem/Gui/TaskFemConstraintPulley.h
Normal 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
|
||||
439
src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp
Normal file
439
src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp
Normal 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"));
|
||||
}
|
||||
124
src/Mod/Fem/Gui/ViewProviderFemConstraint.h
Normal file
124
src/Mod/Fem/Gui/ViewProviderFemConstraint.h
Normal 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
|
||||
153
src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp
Normal file
153
src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.cpp
Normal 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);
|
||||
}
|
||||
75
src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h
Normal file
75
src/Mod/Fem/Gui/ViewProviderFemConstraintBearing.h
Normal 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
|
||||
163
src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp
Normal file
163
src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.cpp
Normal 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);
|
||||
}
|
||||
74
src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.h
Normal file
74
src/Mod/Fem/Gui/ViewProviderFemConstraintFixed.h
Normal 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
|
||||
202
src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp
Normal file
202
src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp
Normal 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);
|
||||
}
|
||||
78
src/Mod/Fem/Gui/ViewProviderFemConstraintForce.h
Normal file
78
src/Mod/Fem/Gui/ViewProviderFemConstraintForce.h
Normal 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
|
||||
191
src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp
Normal file
191
src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp
Normal 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);
|
||||
}
|
||||
74
src/Mod/Fem/Gui/ViewProviderFemConstraintGear.h
Normal file
74
src/Mod/Fem/Gui/ViewProviderFemConstraintGear.h
Normal 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
|
||||
225
src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp
Normal file
225
src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp
Normal 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);
|
||||
}
|
||||
74
src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.h
Normal file
74
src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user