FEM: add gitattributes file to let git manage file endings and normalize them

This commit is contained in:
Bernd Hahnebach
2019-12-10 22:13:03 +01:00
parent 97804f851d
commit e680701037
26 changed files with 4968 additions and 4906 deletions

View File

@@ -1,469 +1,469 @@
/***************************************************************************
* 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 <math.h> //OvG: Required for log10
# 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 "FemTools.h"
#include <App/DocumentObjectPy.h>
#include <App/FeaturePythonPyImp.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
#include <Base/Exception.h>
using namespace Fem;
// maybe in the c++ standard later, older compiler don't have round()
#if _MSC_VER <= 1700
double round(double r) {
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
#endif
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::Vector3d(0,0,1)),"Constraint",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),"Normal direction pointing outside of solid");
ADD_PROPERTY_TYPE(Scale,(1),"Base",App::PropertyType(App::Prop_Output),"Scale used for drawing constraints"); //OvG: Add scale parameter inherited by all derived constraints
References.setScope(App::LinkScope::Global);
}
Constraint::~Constraint()
{
}
App::DocumentObjectExecReturn *Constraint::execute(void)
{
References.touch();
Scale.touch();
return StdReturn;
}
//OvG: Provide the ability to determine how big to draw constraint arrows etc.
int Constraint::calcDrawScaleFactor(double lparam) const
{
return ((int)round(log(lparam)*log(lparam)*log(lparam)/10)>1)?((int)round(log(lparam)*log(lparam)*log(lparam)/10)):1;
}
int Constraint::calcDrawScaleFactor(double lvparam, double luparam) const
{
return calcDrawScaleFactor((lvparam+luparam)/2.0);
}
int Constraint::calcDrawScaleFactor() const
{
return 1;
}
#define CONSTRAINTSTEPLIMIT 50
void Constraint::onChanged(const App::Property* prop)
{
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 (std::size_t 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.getShape().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();
}
bool Constraint::getPoints(std::vector<Base::Vector3d> &points, std::vector<Base::Vector3d> &normals, int * scale) const
{
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
// Extract geometry from References
TopoDS_Shape sh;
for (std::size_t 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.emplace_back(p.X(), p.Y(), p.Z());
normals.push_back(NormalDirection.getValue());
//OvG: Scale by whole object mass in case of a vertex
GProp_GProps props;
BRepGProp::VolumeProperties(toposhape.getShape(), props);
double lx = props.Mass();
*scale = this->calcDrawScaleFactor(sqrt(lx)*0.5); //OvG: setup draw scale for constraint
}
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 >= 30) //OvG: Increase 10 units distance proportionately to l for larger objects.
{
*scale = this->calcDrawScaleFactor(l); //OvG: setup draw scale for constraint
steps = (int)round(l / (10*( *scale)));
steps = steps<3?3:steps;
}
else if (l >= 20)
{
steps = (int)round(l / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
steps = 1;
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
steps = steps>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:steps; //OvG: Place upper limit on number of steps
double step = (lp - fp) / steps;
for (int i = 0; i < steps + 1; i++) {
// Parameter values must be in the range [fp, lp] (#0003683)
gp_Pnt p = curve.Value(fp + i * step);
points.emplace_back(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();
double l;
double lv, lu;
// 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);
try {
isoc.Load(GeomAbs_IsoU, ufp);
l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vfp);
gp_Pnt p2 = hsurf->Value(ufp, vlp);
l = p1.Distance(p2);
}
try {
isoc.Load(GeomAbs_IsoU, ulp);
lv = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ulp, vfp);
gp_Pnt p2 = hsurf->Value(ulp, vlp);
lv = (l + p1.Distance(p2))/2.0;
}
try {
isoc.Load(GeomAbs_IsoV, vfp);
l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vfp);
gp_Pnt p2 = hsurf->Value(ulp, vfp);
l = p1.Distance(p2);
}
try {
isoc.Load(GeomAbs_IsoV, vlp);
lu = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vlp);
gp_Pnt p2 = hsurf->Value(ulp, vlp);
lu = (l + p1.Distance(p2))/2.0;
}
int stepsv;
if (lv >= 30) //OvG: Increase 10 units distance proportionately to lv for larger objects.
{
*scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint
stepsv = (int)round(lv / (10*( *scale)));
stepsv = stepsv<3?3:stepsv;
}
else if (lv >= 20.0)
{
stepsv = (int)round(lv / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
stepsv = 2; // Minimum of three arrows to ensure (as much as possible) that at least one is displayed
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
stepsv = stepsv>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsv; //OvG: Place upper limit on number of steps
int stepsu;
if (lu >= 30) //OvG: Increase 10 units distance proportionately to lu for larger objects.
{
*scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint
stepsu = (int)round(lu / (10*( *scale)));
stepsu = stepsu<3?3:stepsu;
}
else if (lu >= 20.0)
{
stepsu = (int)round(lu / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
stepsu = 2;
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
stepsu = stepsu>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsu; //OvG: Place upper limit on number of steps
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.emplace_back(p.X(), p.Y(), p.Z());
props.Normal(u, v,center,normal);
normal.Normalize();
normals.emplace_back(normal.X(), normal.Y(), normal.Z());
}
}
}
}
}
return true;
}
bool Constraint::getCylinder(double &radius, double &height, Base::Vector3d& base, Base::Vector3d& 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);
const 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::Vector3d(b.X(), b.Y(), b.Z());
gp_Dir dir = cyl.Axis().Direction();
axis = Base::Vector3d(dir.X(), dir.Y(), dir.Z());
return true;
}
Base::Vector3d Constraint::getBasePoint(const Base::Vector3d& base, const Base::Vector3d& axis,
const App::PropertyLinkSub& location, const double& 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::Vector3d(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::Vector3d(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::Vector3d(0,0,0);
gp_Pnt inter = intersector.Point(1);
return Base::Vector3d(inter.X(), inter.Y(), inter.Z());
}
const Base::Vector3d Constraint::getDirection(const App::PropertyLinkSub &direction)
{
App::DocumentObject* obj = direction.getValue();
std::vector<std::string> names = direction.getSubValues();
if (names.size() == 0)
return Base::Vector3d(0,0,0);
std::string subName = names.front();
Part::Feature* feat = static_cast<Part::Feature*>(obj);
const Part::TopoShape& shape = feat->Shape.getShape();
if (shape.isNull())
return Base::Vector3d(0,0,0);
TopoDS_Shape sh;
try {
sh = shape.getSubShape(subName.c_str());
}
catch (Standard_Failure&) {
std::stringstream str;
str << "No such sub-element '" << subName << "'";
throw Base::AttributeError(str.str());
}
return Fem::Tools::getDirectionFromShape(sh);
}
// Python feature ---------------------------------------------------------
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(Fem::ConstraintPython, Fem::Constraint)
template<> const char* Fem::ConstraintPython::getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintPython";
}
template<> PyObject* Fem::ConstraintPython::getPyObject(void) {
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new App::FeaturePythonPyT<App::DocumentObjectPy>(this),true);
}
return Py::new_reference_to(PythonObject);
}
// explicit template instantiation
template class AppFemExport FeaturePythonT<Fem::Constraint>;
/// @endcond
}
/***************************************************************************
* 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 <math.h> //OvG: Required for log10
# 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 "FemTools.h"
#include <App/DocumentObjectPy.h>
#include <App/FeaturePythonPyImp.h>
#include <Mod/Part/App/PartFeature.h>
#include <Base/Console.h>
#include <Base/Exception.h>
using namespace Fem;
// maybe in the c++ standard later, older compiler don't have round()
#if _MSC_VER <= 1700
double round(double r) {
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
#endif
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::Vector3d(0,0,1)),"Constraint",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output),"Normal direction pointing outside of solid");
ADD_PROPERTY_TYPE(Scale,(1),"Base",App::PropertyType(App::Prop_Output),"Scale used for drawing constraints"); //OvG: Add scale parameter inherited by all derived constraints
References.setScope(App::LinkScope::Global);
}
Constraint::~Constraint()
{
}
App::DocumentObjectExecReturn *Constraint::execute(void)
{
References.touch();
Scale.touch();
return StdReturn;
}
//OvG: Provide the ability to determine how big to draw constraint arrows etc.
int Constraint::calcDrawScaleFactor(double lparam) const
{
return ((int)round(log(lparam)*log(lparam)*log(lparam)/10)>1)?((int)round(log(lparam)*log(lparam)*log(lparam)/10)):1;
}
int Constraint::calcDrawScaleFactor(double lvparam, double luparam) const
{
return calcDrawScaleFactor((lvparam+luparam)/2.0);
}
int Constraint::calcDrawScaleFactor() const
{
return 1;
}
#define CONSTRAINTSTEPLIMIT 50
void Constraint::onChanged(const App::Property* prop)
{
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 (std::size_t 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.getShape().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();
}
bool Constraint::getPoints(std::vector<Base::Vector3d> &points, std::vector<Base::Vector3d> &normals, int * scale) const
{
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
// Extract geometry from References
TopoDS_Shape sh;
for (std::size_t 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.emplace_back(p.X(), p.Y(), p.Z());
normals.push_back(NormalDirection.getValue());
//OvG: Scale by whole object mass in case of a vertex
GProp_GProps props;
BRepGProp::VolumeProperties(toposhape.getShape(), props);
double lx = props.Mass();
*scale = this->calcDrawScaleFactor(sqrt(lx)*0.5); //OvG: setup draw scale for constraint
}
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 >= 30) //OvG: Increase 10 units distance proportionately to l for larger objects.
{
*scale = this->calcDrawScaleFactor(l); //OvG: setup draw scale for constraint
steps = (int)round(l / (10*( *scale)));
steps = steps<3?3:steps;
}
else if (l >= 20)
{
steps = (int)round(l / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
steps = 1;
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
steps = steps>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:steps; //OvG: Place upper limit on number of steps
double step = (lp - fp) / steps;
for (int i = 0; i < steps + 1; i++) {
// Parameter values must be in the range [fp, lp] (#0003683)
gp_Pnt p = curve.Value(fp + i * step);
points.emplace_back(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();
double l;
double lv, lu;
// 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);
try {
isoc.Load(GeomAbs_IsoU, ufp);
l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vfp);
gp_Pnt p2 = hsurf->Value(ufp, vlp);
l = p1.Distance(p2);
}
try {
isoc.Load(GeomAbs_IsoU, ulp);
lv = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ulp, vfp);
gp_Pnt p2 = hsurf->Value(ulp, vlp);
lv = (l + p1.Distance(p2))/2.0;
}
try {
isoc.Load(GeomAbs_IsoV, vfp);
l = GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion());
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vfp);
gp_Pnt p2 = hsurf->Value(ulp, vfp);
l = p1.Distance(p2);
}
try {
isoc.Load(GeomAbs_IsoV, vlp);
lu = (l + GCPnts_AbscissaPoint::Length(isoc, Precision::Confusion()))/2.0;
}
catch (const Standard_Failure&) {
gp_Pnt p1 = hsurf->Value(ufp, vlp);
gp_Pnt p2 = hsurf->Value(ulp, vlp);
lu = (l + p1.Distance(p2))/2.0;
}
int stepsv;
if (lv >= 30) //OvG: Increase 10 units distance proportionately to lv for larger objects.
{
*scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint
stepsv = (int)round(lv / (10*( *scale)));
stepsv = stepsv<3?3:stepsv;
}
else if (lv >= 20.0)
{
stepsv = (int)round(lv / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
stepsv = 2; // Minimum of three arrows to ensure (as much as possible) that at least one is displayed
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
stepsv = stepsv>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsv; //OvG: Place upper limit on number of steps
int stepsu;
if (lu >= 30) //OvG: Increase 10 units distance proportionately to lu for larger objects.
{
*scale = this->calcDrawScaleFactor(lv,lu); //OvG: setup draw scale for constraint
stepsu = (int)round(lu / (10*( *scale)));
stepsu = stepsu<3?3:stepsu;
}
else if (lu >= 20.0)
{
stepsu = (int)round(lu / 10);
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
else
{
stepsu = 2;
*scale = this->calcDrawScaleFactor(); //OvG: setup draw scale for constraint
}
stepsu = stepsu>CONSTRAINTSTEPLIMIT?CONSTRAINTSTEPLIMIT:stepsu; //OvG: Place upper limit on number of steps
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.emplace_back(p.X(), p.Y(), p.Z());
props.Normal(u, v,center,normal);
normal.Normalize();
normals.emplace_back(normal.X(), normal.Y(), normal.Z());
}
}
}
}
}
return true;
}
bool Constraint::getCylinder(double &radius, double &height, Base::Vector3d& base, Base::Vector3d& 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);
const 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::Vector3d(b.X(), b.Y(), b.Z());
gp_Dir dir = cyl.Axis().Direction();
axis = Base::Vector3d(dir.X(), dir.Y(), dir.Z());
return true;
}
Base::Vector3d Constraint::getBasePoint(const Base::Vector3d& base, const Base::Vector3d& axis,
const App::PropertyLinkSub& location, const double& 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::Vector3d(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::Vector3d(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::Vector3d(0,0,0);
gp_Pnt inter = intersector.Point(1);
return Base::Vector3d(inter.X(), inter.Y(), inter.Z());
}
const Base::Vector3d Constraint::getDirection(const App::PropertyLinkSub &direction)
{
App::DocumentObject* obj = direction.getValue();
std::vector<std::string> names = direction.getSubValues();
if (names.size() == 0)
return Base::Vector3d(0,0,0);
std::string subName = names.front();
Part::Feature* feat = static_cast<Part::Feature*>(obj);
const Part::TopoShape& shape = feat->Shape.getShape();
if (shape.isNull())
return Base::Vector3d(0,0,0);
TopoDS_Shape sh;
try {
sh = shape.getSubShape(subName.c_str());
}
catch (Standard_Failure&) {
std::stringstream str;
str << "No such sub-element '" << subName << "'";
throw Base::AttributeError(str.str());
}
return Fem::Tools::getDirectionFromShape(sh);
}
// Python feature ---------------------------------------------------------
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(Fem::ConstraintPython, Fem::Constraint)
template<> const char* Fem::ConstraintPython::getViewProviderName(void) const {
return "FemGui::ViewProviderFemConstraintPython";
}
template<> PyObject* Fem::ConstraintPython::getPyObject(void) {
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new App::FeaturePythonPyT<App::DocumentObjectPy>(this),true);
}
return Py::new_reference_to(PythonObject);
}
// explicit template instantiation
template class AppFemExport FeaturePythonT<Fem::Constraint>;
/// @endcond
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,246 +1,246 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostFilter_H
#define Fem_FemPostFilter_H
#include "FemPostObject.h"
#include <App/PropertyUnits.h>
#include <vtkSmartPointer.h>
#include <vtkTableBasedClipDataSet.h>
#include <vtkExtractGeometry.h>
#include <vtkGeometryFilter.h>
#include <vtkPassThrough.h>
#include <vtkPlane.h>
#include <vtkWarpVector.h>
#include <vtkCutter.h>
#include <vtkLineSource.h>
#include <vtkPointSource.h>
#include <vtkProbeFilter.h>
#include <vtkThreshold.h>
namespace Fem
{
class AppFemExport FemPostFilter : public Fem::FemPostObject
{
PROPERTY_HEADER(Fem::FemPostFilter);
public:
/// Constructor
FemPostFilter(void);
virtual ~FemPostFilter();
App::PropertyLink Input;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
vtkDataObject* getInputData();
//pipeline handling for derived filter
struct FilterPipeline {
vtkSmartPointer<vtkAlgorithm> source, target;
vtkSmartPointer<vtkProbeFilter> filterSource, filterTarget;
std::vector<vtkSmartPointer<vtkAlgorithm> > algorithmStorage;
};
void addFilterPipeline(const FilterPipeline& p, std::string name);
void setActiveFilterPipeline(std::string name);
FilterPipeline& getFilterPipeline(std::string name);
private:
//handling of multiple pipelines which can be the filter
std::map<std::string, FilterPipeline> m_pipelines;
std::string m_activePipeline;
};
class AppFemExport FemPostClipFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostClipFilter);
public:
FemPostClipFilter(void);
virtual ~FemPostClipFilter();
App::PropertyLink Function;
App::PropertyBool InsideOut;
App::PropertyBool CutCells;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostClip";
}
virtual short int mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
vtkSmartPointer<vtkExtractGeometry> m_extractor;
};
class AppFemExport FemPostDataAlongLineFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostDataAlongLineFilter);
public:
FemPostDataAlongLineFilter(void);
virtual ~FemPostDataAlongLineFilter();
App::PropertyVector Point2;
App::PropertyVector Point1;
App::PropertyInteger Resolution;
App::PropertyFloatList XAxisData;
App::PropertyFloatList YAxisData;
App::PropertyString PlotData;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostDataAlongLine";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void GetAxisData();
private:
vtkSmartPointer<vtkLineSource> m_line;
vtkSmartPointer<vtkProbeFilter> m_probe;
};
class AppFemExport FemPostDataAtPointFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostDataAtPointFilter);
public:
FemPostDataAtPointFilter(void);
virtual ~FemPostDataAtPointFilter();
App::PropertyVectorDistance Center;
App::PropertyDistance Radius;
App::PropertyString FieldName;
App::PropertyFloatList PointData;
App::PropertyString Unit;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostDataAtPoint";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void GetPointData();
private:
vtkSmartPointer<vtkPointSource> m_point;
vtkSmartPointer<vtkProbeFilter> m_probe;
};
class AppFemExport FemPostScalarClipFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostScalarClipFilter);
public:
FemPostScalarClipFilter(void);
virtual ~FemPostScalarClipFilter();
App::PropertyBool InsideOut;
App::PropertyFloatConstraint Value;
App::PropertyEnumeration Scalars;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostScalarClip";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void setConstraintForField();
private:
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
App::Enumeration m_scalarFields;
App::PropertyFloatConstraint::Constraints m_constraints;
};
class AppFemExport FemPostWarpVectorFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostWarpVectorFilter);
public:
FemPostWarpVectorFilter(void);
virtual ~FemPostWarpVectorFilter();
App::PropertyFloat Factor;
App::PropertyEnumeration Vector;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostWarpVector";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkWarpVector> m_warp;
App::Enumeration m_vectorFields;
};
class AppFemExport FemPostCutFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostCutFilter);
public:
FemPostCutFilter(void);
virtual ~FemPostCutFilter();
App::PropertyLink Function;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostCut";
}
virtual short int mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkCutter> m_cutter;
};
} //namespace Fem
#endif // Fem_FemPostFilter_H
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostFilter_H
#define Fem_FemPostFilter_H
#include "FemPostObject.h"
#include <App/PropertyUnits.h>
#include <vtkSmartPointer.h>
#include <vtkTableBasedClipDataSet.h>
#include <vtkExtractGeometry.h>
#include <vtkGeometryFilter.h>
#include <vtkPassThrough.h>
#include <vtkPlane.h>
#include <vtkWarpVector.h>
#include <vtkCutter.h>
#include <vtkLineSource.h>
#include <vtkPointSource.h>
#include <vtkProbeFilter.h>
#include <vtkThreshold.h>
namespace Fem
{
class AppFemExport FemPostFilter : public Fem::FemPostObject
{
PROPERTY_HEADER(Fem::FemPostFilter);
public:
/// Constructor
FemPostFilter(void);
virtual ~FemPostFilter();
App::PropertyLink Input;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
vtkDataObject* getInputData();
//pipeline handling for derived filter
struct FilterPipeline {
vtkSmartPointer<vtkAlgorithm> source, target;
vtkSmartPointer<vtkProbeFilter> filterSource, filterTarget;
std::vector<vtkSmartPointer<vtkAlgorithm> > algorithmStorage;
};
void addFilterPipeline(const FilterPipeline& p, std::string name);
void setActiveFilterPipeline(std::string name);
FilterPipeline& getFilterPipeline(std::string name);
private:
//handling of multiple pipelines which can be the filter
std::map<std::string, FilterPipeline> m_pipelines;
std::string m_activePipeline;
};
class AppFemExport FemPostClipFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostClipFilter);
public:
FemPostClipFilter(void);
virtual ~FemPostClipFilter();
App::PropertyLink Function;
App::PropertyBool InsideOut;
App::PropertyBool CutCells;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostClip";
}
virtual short int mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
vtkSmartPointer<vtkExtractGeometry> m_extractor;
};
class AppFemExport FemPostDataAlongLineFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostDataAlongLineFilter);
public:
FemPostDataAlongLineFilter(void);
virtual ~FemPostDataAlongLineFilter();
App::PropertyVector Point2;
App::PropertyVector Point1;
App::PropertyInteger Resolution;
App::PropertyFloatList XAxisData;
App::PropertyFloatList YAxisData;
App::PropertyString PlotData;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostDataAlongLine";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void GetAxisData();
private:
vtkSmartPointer<vtkLineSource> m_line;
vtkSmartPointer<vtkProbeFilter> m_probe;
};
class AppFemExport FemPostDataAtPointFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostDataAtPointFilter);
public:
FemPostDataAtPointFilter(void);
virtual ~FemPostDataAtPointFilter();
App::PropertyVectorDistance Center;
App::PropertyDistance Radius;
App::PropertyString FieldName;
App::PropertyFloatList PointData;
App::PropertyString Unit;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostDataAtPoint";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void GetPointData();
private:
vtkSmartPointer<vtkPointSource> m_point;
vtkSmartPointer<vtkProbeFilter> m_probe;
};
class AppFemExport FemPostScalarClipFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostScalarClipFilter);
public:
FemPostScalarClipFilter(void);
virtual ~FemPostScalarClipFilter();
App::PropertyBool InsideOut;
App::PropertyFloatConstraint Value;
App::PropertyEnumeration Scalars;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostScalarClip";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
void setConstraintForField();
private:
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
App::Enumeration m_scalarFields;
App::PropertyFloatConstraint::Constraints m_constraints;
};
class AppFemExport FemPostWarpVectorFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostWarpVectorFilter);
public:
FemPostWarpVectorFilter(void);
virtual ~FemPostWarpVectorFilter();
App::PropertyFloat Factor;
App::PropertyEnumeration Vector;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostWarpVector";
}
virtual short int mustExecute(void) const;
protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkWarpVector> m_warp;
App::Enumeration m_vectorFields;
};
class AppFemExport FemPostCutFilter : public FemPostFilter {
PROPERTY_HEADER(Fem::FemPostCutFilter);
public:
FemPostCutFilter(void);
virtual ~FemPostCutFilter();
App::PropertyLink Function;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostCut";
}
virtual short int mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
protected:
virtual void onChanged(const App::Property* prop);
private:
vtkSmartPointer<vtkCutter> m_cutter;
};
} //namespace Fem
#endif // Fem_FemPostFilter_H

View File

@@ -1,131 +1,131 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 "FemPostFunction.h"
#include <Base/Console.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostFunctionProvider, App::DocumentObject)
FemPostFunctionProvider::FemPostFunctionProvider(void): DocumentObject() {
ADD_PROPERTY(Functions, (0));
}
FemPostFunctionProvider::~FemPostFunctionProvider() {
}
void FemPostFunctionProvider::onChanged(const Property* prop) {
App::DocumentObject::onChanged(prop);
}
PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject)
FemPostFunction::FemPostFunction()
{
}
FemPostFunction::~FemPostFunction()
{
}
DocumentObjectExecReturn* FemPostFunction::execute(void) {
return DocumentObject::StdReturn;
}
PROPERTY_SOURCE(Fem::FemPostPlaneFunction, Fem::FemPostFunction)
FemPostPlaneFunction::FemPostPlaneFunction(void): FemPostFunction() {
ADD_PROPERTY(Origin,(Base::Vector3d(0.0,0.0,0.0)));
ADD_PROPERTY(Normal,(Base::Vector3d(0.0,0.0,1.0)));
m_plane = vtkSmartPointer<vtkPlane>::New();
m_implicit = m_plane;
m_plane->SetOrigin(0., 0., 0.);
m_plane->SetNormal(0., 0., 1.);
}
FemPostPlaneFunction::~FemPostPlaneFunction() {
}
void FemPostPlaneFunction::onChanged(const Property* prop) {
if(prop == &Origin) {
const Base::Vector3d& vec = Origin.getValue();
m_plane->SetOrigin(vec[0], vec[1], vec[2]);
}
else if(prop == &Normal) {
const Base::Vector3d& vec = Normal.getValue();
m_plane->SetNormal(vec[0], vec[1], vec[2]);
}
Fem::FemPostFunction::onChanged(prop);
}
PROPERTY_SOURCE(Fem::FemPostSphereFunction, Fem::FemPostFunction)
FemPostSphereFunction::FemPostSphereFunction(void): FemPostFunction() {
ADD_PROPERTY(Radius,(5));
ADD_PROPERTY(Center,(Base::Vector3d(1.0,0.0,0.0)));
m_sphere = vtkSmartPointer<vtkSphere>::New();
m_implicit = m_sphere;
m_sphere->SetCenter(0., 0., 0.);
m_sphere->SetRadius(5);
}
FemPostSphereFunction::~FemPostSphereFunction() {
}
void FemPostSphereFunction::onChanged(const Property* prop) {
if(prop == &Center) {
const Base::Vector3d& vec = Center.getValue();
m_sphere->SetCenter(vec[0], vec[1], vec[2]);
}
else if(prop == &Radius) {
m_sphere->SetRadius(Radius.getValue());
}
Fem::FemPostFunction::onChanged(prop);
}
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 "FemPostFunction.h"
#include <Base/Console.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostFunctionProvider, App::DocumentObject)
FemPostFunctionProvider::FemPostFunctionProvider(void): DocumentObject() {
ADD_PROPERTY(Functions, (0));
}
FemPostFunctionProvider::~FemPostFunctionProvider() {
}
void FemPostFunctionProvider::onChanged(const Property* prop) {
App::DocumentObject::onChanged(prop);
}
PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject)
FemPostFunction::FemPostFunction()
{
}
FemPostFunction::~FemPostFunction()
{
}
DocumentObjectExecReturn* FemPostFunction::execute(void) {
return DocumentObject::StdReturn;
}
PROPERTY_SOURCE(Fem::FemPostPlaneFunction, Fem::FemPostFunction)
FemPostPlaneFunction::FemPostPlaneFunction(void): FemPostFunction() {
ADD_PROPERTY(Origin,(Base::Vector3d(0.0,0.0,0.0)));
ADD_PROPERTY(Normal,(Base::Vector3d(0.0,0.0,1.0)));
m_plane = vtkSmartPointer<vtkPlane>::New();
m_implicit = m_plane;
m_plane->SetOrigin(0., 0., 0.);
m_plane->SetNormal(0., 0., 1.);
}
FemPostPlaneFunction::~FemPostPlaneFunction() {
}
void FemPostPlaneFunction::onChanged(const Property* prop) {
if(prop == &Origin) {
const Base::Vector3d& vec = Origin.getValue();
m_plane->SetOrigin(vec[0], vec[1], vec[2]);
}
else if(prop == &Normal) {
const Base::Vector3d& vec = Normal.getValue();
m_plane->SetNormal(vec[0], vec[1], vec[2]);
}
Fem::FemPostFunction::onChanged(prop);
}
PROPERTY_SOURCE(Fem::FemPostSphereFunction, Fem::FemPostFunction)
FemPostSphereFunction::FemPostSphereFunction(void): FemPostFunction() {
ADD_PROPERTY(Radius,(5));
ADD_PROPERTY(Center,(Base::Vector3d(1.0,0.0,0.0)));
m_sphere = vtkSmartPointer<vtkSphere>::New();
m_implicit = m_sphere;
m_sphere->SetCenter(0., 0., 0.);
m_sphere->SetRadius(5);
}
FemPostSphereFunction::~FemPostSphereFunction() {
}
void FemPostSphereFunction::onChanged(const Property* prop) {
if(prop == &Center) {
const Base::Vector3d& vec = Center.getValue();
m_sphere->SetCenter(vec[0], vec[1], vec[2]);
}
else if(prop == &Radius) {
m_sphere->SetRadius(Radius.getValue());
}
Fem::FemPostFunction::onChanged(prop);
}

View File

@@ -1,135 +1,135 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostFunction_H
#define Fem_FemPostFunction_H
#include "FemPostObject.h"
#include <App/PropertyUnits.h>
#include <vtkSmartPointer.h>
#include <vtkImplicitFunction.h>
#include <vtkPlane.h>
#include <vtkSphere.h>
#include <vtkBoundingBox.h>
namespace Fem
{
class AppFemExport FemPostFunction : public App::DocumentObject
{
PROPERTY_HEADER(Fem::FemPostFunction);
public:
/// Constructor
FemPostFunction(void);
virtual ~FemPostFunction();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostFunction";
}
virtual App::DocumentObjectExecReturn* execute(void);
//bound box handling
void setBoundingBox(vtkBoundingBox b) {m_boundingBox = b;};
//get the algorithm or the data
vtkSmartPointer<vtkImplicitFunction> getImplicitFunction() {return m_implicit;};
protected:
vtkSmartPointer<vtkImplicitFunction> m_implicit;
vtkBoundingBox m_boundingBox;
};
class AppFemExport FemPostFunctionProvider : public App::DocumentObject {
PROPERTY_HEADER(Fem::FemPostFunctionProvider);
public:
FemPostFunctionProvider(void);
virtual ~FemPostFunctionProvider();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostFunctionProvider";
}
App::PropertyLinkList Functions;
protected:
virtual void onChanged(const App::Property* prop);
};
// ---------------------------------------------------------------------------
class AppFemExport FemPostPlaneFunction : public FemPostFunction
{
PROPERTY_HEADER(Fem::FemPostPlaneFunction);
public:
FemPostPlaneFunction(void);
virtual ~FemPostPlaneFunction();
App::PropertyVector Normal;
App::PropertyVectorDistance Origin;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostPlaneFunction";
}
protected:
virtual void onChanged(const App::Property* prop);
vtkSmartPointer<vtkPlane> m_plane;
};
// ---------------------------------------------------------------------------
class AppFemExport FemPostSphereFunction : public FemPostFunction
{
PROPERTY_HEADER(Fem::FemPostSphereFunction);
public:
FemPostSphereFunction(void);
virtual ~FemPostSphereFunction();
App::PropertyDistance Radius;
App::PropertyVectorDistance Center;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostSphereFunction";
}
protected:
virtual void onChanged(const App::Property* prop);
vtkSmartPointer<vtkSphere> m_sphere;
};
} //namespace Fem
#endif // Fem_FemPostFunction_H
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostFunction_H
#define Fem_FemPostFunction_H
#include "FemPostObject.h"
#include <App/PropertyUnits.h>
#include <vtkSmartPointer.h>
#include <vtkImplicitFunction.h>
#include <vtkPlane.h>
#include <vtkSphere.h>
#include <vtkBoundingBox.h>
namespace Fem
{
class AppFemExport FemPostFunction : public App::DocumentObject
{
PROPERTY_HEADER(Fem::FemPostFunction);
public:
/// Constructor
FemPostFunction(void);
virtual ~FemPostFunction();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostFunction";
}
virtual App::DocumentObjectExecReturn* execute(void);
//bound box handling
void setBoundingBox(vtkBoundingBox b) {m_boundingBox = b;};
//get the algorithm or the data
vtkSmartPointer<vtkImplicitFunction> getImplicitFunction() {return m_implicit;};
protected:
vtkSmartPointer<vtkImplicitFunction> m_implicit;
vtkBoundingBox m_boundingBox;
};
class AppFemExport FemPostFunctionProvider : public App::DocumentObject {
PROPERTY_HEADER(Fem::FemPostFunctionProvider);
public:
FemPostFunctionProvider(void);
virtual ~FemPostFunctionProvider();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostFunctionProvider";
}
App::PropertyLinkList Functions;
protected:
virtual void onChanged(const App::Property* prop);
};
// ---------------------------------------------------------------------------
class AppFemExport FemPostPlaneFunction : public FemPostFunction
{
PROPERTY_HEADER(Fem::FemPostPlaneFunction);
public:
FemPostPlaneFunction(void);
virtual ~FemPostPlaneFunction();
App::PropertyVector Normal;
App::PropertyVectorDistance Origin;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostPlaneFunction";
}
protected:
virtual void onChanged(const App::Property* prop);
vtkSmartPointer<vtkPlane> m_plane;
};
// ---------------------------------------------------------------------------
class AppFemExport FemPostSphereFunction : public FemPostFunction
{
PROPERTY_HEADER(Fem::FemPostSphereFunction);
public:
FemPostSphereFunction(void);
virtual ~FemPostSphereFunction();
App::PropertyDistance Radius;
App::PropertyVectorDistance Center;
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostSphereFunction";
}
protected:
virtual void onChanged(const App::Property* prop);
vtkSmartPointer<vtkSphere> m_sphere;
};
} //namespace Fem
#endif // Fem_FemPostFunction_H

View File

@@ -1,63 +1,63 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <vtkPointData.h>
# include <vtkCellData.h>
#endif
#include "FemPostObject.h"
#include <Base/Console.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostObject, App::GeoFeature)
FemPostObject::FemPostObject()
{
ADD_PROPERTY(Data,(0));
}
FemPostObject::~FemPostObject()
{
}
vtkBoundingBox FemPostObject::getBoundingBox() {
vtkBoundingBox box;
if(Data.getValue() && Data.getValue()->IsA("vtkDataSet"))
box.AddBounds(vtkDataSet::SafeDownCast(Data.getValue())->GetBounds());
//TODO: add calculation of multiblock and Multipiece datasets
return box;
}
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <vtkPointData.h>
# include <vtkCellData.h>
#endif
#include "FemPostObject.h"
#include <Base/Console.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostObject, App::GeoFeature)
FemPostObject::FemPostObject()
{
ADD_PROPERTY(Data,(0));
}
FemPostObject::~FemPostObject()
{
}
vtkBoundingBox FemPostObject::getBoundingBox() {
vtkBoundingBox box;
if(Data.getValue() && Data.getValue()->IsA("vtkDataSet"))
box.AddBounds(vtkDataSet::SafeDownCast(Data.getValue())->GetBounds());
//TODO: add calculation of multiblock and Multipiece datasets
return box;
}

View File

@@ -1,53 +1,53 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostObject_H
#define Fem_FemPostObject_H
#include <App/GeoFeature.h>
#include "PropertyPostDataObject.h"
#include <vtkBoundingBox.h>
namespace Fem
{
//poly data is the only data we can visualize, hence every post processing object needs to expose it
class AppFemExport FemPostObject : public App::GeoFeature
{
PROPERTY_HEADER(Fem::FemPostObject);
public:
/// Constructor
FemPostObject(void);
virtual ~FemPostObject();
Fem::PropertyPostDataObject Data;
vtkBoundingBox getBoundingBox();
};
} //namespace Fem
#endif // Fem_FemPostObject_H
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostObject_H
#define Fem_FemPostObject_H
#include <App/GeoFeature.h>
#include "PropertyPostDataObject.h"
#include <vtkBoundingBox.h>
namespace Fem
{
//poly data is the only data we can visualize, hence every post processing object needs to expose it
class AppFemExport FemPostObject : public App::GeoFeature
{
PROPERTY_HEADER(Fem::FemPostObject);
public:
/// Constructor
FemPostObject(void);
virtual ~FemPostObject();
Fem::PropertyPostDataObject Data;
vtkBoundingBox getBoundingBox();
};
} //namespace Fem
#endif // Fem_FemPostObject_H

View File

@@ -1,275 +1,275 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <SMESH_Mesh.hxx>
# include <vtkDataSetReader.h>
# include <vtkGeometryFilter.h>
# include <vtkStructuredGrid.h>
# include <vtkUnstructuredGrid.h>
# include <vtkImageData.h>
# include <vtkRectilinearGrid.h>
# include <vtkAppendFilter.h>
# include <vtkXMLUnstructuredGridReader.h>
# include <vtkXMLPolyDataReader.h>
# include <vtkXMLStructuredGridReader.h>
# include <vtkXMLRectilinearGridReader.h>
# include <vtkXMLImageDataReader.h>
#endif
#include "FemPostPipeline.h"
#include "FemMesh.h"
#include "FemMeshObject.h"
#include "FemVTKTools.h"
#include <Base/Console.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
#include <Mod/Fem/App/FemPostPipelinePy.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject)
const char* FemPostPipeline::ModeEnums[]= {"Serial","Parallel",NULL};
FemPostPipeline::FemPostPipeline()
{
ADD_PROPERTY_TYPE(Filter, (0), "Pipeline", App::Prop_None, "The filter used in in this pipeline");
ADD_PROPERTY_TYPE(Functions, (0), "Pipeline", App::Prop_Hidden, "The function provider which groups all pipeline functions");
ADD_PROPERTY_TYPE(Mode,(long(0)), "Pipeline", App::Prop_None, "Selects the pipeline data transition mode. In serial every filter"
"gets the output of the previous one as input, in parallel every"
"filter gets the pipelien source as input.");
Mode.setEnums(ModeEnums);
}
FemPostPipeline::~FemPostPipeline()
{
}
short FemPostPipeline::mustExecute(void) const
{
if(Mode.isTouched())
return 1;
return FemPostFilter::mustExecute();
}
DocumentObjectExecReturn* FemPostPipeline::execute(void) {
//if we are the toplevel pipeline our data object is not created by filters, we are the main source!
if(!Input.getValue())
return StdReturn;
//now if we are a filter than our data object is created by the filter we hold
//if we are in serial mode we just copy over the data of the last filter,
//but if we are in parallel we need to combine all filter results
if(Mode.getValue() == 0) {
//serial
Data.setValue(getLastPostObject()->Data.getValue());
}
else {
//parallel. go through all filters and append the result
const std::vector<App::DocumentObject*>& filters = Filter.getValues();
std::vector<App::DocumentObject*>::const_iterator it = filters.begin();
vtkSmartPointer<vtkAppendFilter> append = vtkSmartPointer<vtkAppendFilter>::New();
for(;it != filters.end(); ++it) {
append->AddInputDataObject(static_cast<FemPostObject*>(*it)->Data.getValue());
}
append->Update();
Data.setValue(append->GetOutputDataObject(0));
}
return Fem::FemPostObject::execute();
}
bool FemPostPipeline::canRead(Base::FileInfo File) {
if (File.hasExtension("vtk") ||
// from FemResult only unstructural mesh is supported in femvtktoools.cpp
File.hasExtension("vtp") ||
File.hasExtension("vts") ||
File.hasExtension("vtr") ||
File.hasExtension("vti") ||
File.hasExtension("vtu"))
return true;
return false;
}
void FemPostPipeline::read(Base::FileInfo File) {
// checking on the file
if (!File.isReadable())
throw Base::FileException("File to load not existing or not readable", File);
if (File.hasExtension("vtu"))
readXMLFile<vtkXMLUnstructuredGridReader>(File.filePath());
else if (File.hasExtension("vtp"))
readXMLFile<vtkXMLPolyDataReader>(File.filePath());
else if (File.hasExtension("vts"))
readXMLFile<vtkXMLStructuredGridReader>(File.filePath());
else if (File.hasExtension("vtr"))
readXMLFile<vtkXMLRectilinearGridReader>(File.filePath());
else if (File.hasExtension("vti"))
readXMLFile<vtkXMLImageDataReader>(File.filePath());
else if (File.hasExtension("vtk"))
readXMLFile<vtkDataSetReader>(File.filePath());
else
throw Base::FileException("Unknown extension");
}
// PyObject *FemPostPipeline::getPyObject()
// {
// if (PythonObject.is(Py::_None())){
// // ref counter is set to 1
// PythonObject = Py::Object(new DocumentObjectPy(this),true);
// }
// return Py::new_reference_to(PythonObject);
// }
void FemPostPipeline::onChanged(const Property* prop)
{
if(prop == &Filter || prop == &Mode) {
//we check if all connections are right and add new ones if needed
std::vector<App::DocumentObject*> objs = Filter.getValues();
if(objs.empty())
return;
std::vector<App::DocumentObject*>::iterator it = objs.begin();
FemPostFilter* filter = static_cast<FemPostFilter*>(*it);
//If we have a Input we need to ensure our filters are connected correctly
if(Input.getValue()) {
//the first filter is always connected to the input
if(filter->Input.getValue() != Input.getValue())
filter->Input.setValue(Input.getValue());
//all the others need to be connected to the previous filter or the source, dependent on the mode
++it;
for(; it != objs.end(); ++it) {
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
if(Mode.getValue() == 0) { //serial mode
if( nextFilter->Input.getValue() != filter)
nextFilter->Input.setValue(filter);
}
else { //Parallel mode
if( nextFilter->Input.getValue() != Input.getValue())
nextFilter->Input.setValue(Input.getValue());
}
filter = nextFilter;
};
}
//if we have no input the filters are responsible of grabbing the pipeline data themself
else {
//the first filter must always grab the data
if(filter->Input.getValue() != NULL)
filter->Input.setValue(NULL);
//all the others need to be connected to the previous filter or grab the data, dependent on mode
++it;
for(; it != objs.end(); ++it) {
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
if(Mode.getValue() == 0) { //serial mode
if( nextFilter->Input.getValue() != filter)
nextFilter->Input.setValue(filter);
}
else { //Parallel mode
if( nextFilter->Input.getValue() != NULL)
nextFilter->Input.setValue(NULL);
}
filter = nextFilter;
};
}
}
App::GeoFeature::onChanged(prop);
}
FemPostObject* FemPostPipeline::getLastPostObject() {
if(Filter.getValues().empty())
return this;
return static_cast<FemPostObject*>(Filter.getValues().back());
}
bool FemPostPipeline::holdsPostObject(FemPostObject* obj) {
std::vector<App::DocumentObject*>::const_iterator it = Filter.getValues().begin();
for(; it != Filter.getValues().end(); ++it) {
if(*it == obj)
return true;
}
return false;
}
void FemPostPipeline::load(FemResultObject* res) {
if(!res->Mesh.getValue() || !res->Mesh.getValue()->isDerivedFrom(Fem::FemMeshObject::getClassTypeId())) {
Base::Console().Warning("Mesh of result object is empty or not derived from Fem::FemMeshObject\n");
return;
}
//first copy the mesh over
// ***************************
const FemMesh& mesh = static_cast<FemMeshObject*>(res->Mesh.getValue())->FemMesh.getValue();
vtkSmartPointer<vtkUnstructuredGrid> grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
FemVTKTools::exportVTKMesh(&mesh, grid);
//Now copy the point data over
// ***************************
FemVTKTools::exportFreeCADResult(res, grid);
Data.setValue(grid);
}
PyObject* FemPostPipeline::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new FemPostPipelinePy(this),true);
}
return Py::new_reference_to(PythonObject);
}
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <SMESH_Mesh.hxx>
# include <vtkDataSetReader.h>
# include <vtkGeometryFilter.h>
# include <vtkStructuredGrid.h>
# include <vtkUnstructuredGrid.h>
# include <vtkImageData.h>
# include <vtkRectilinearGrid.h>
# include <vtkAppendFilter.h>
# include <vtkXMLUnstructuredGridReader.h>
# include <vtkXMLPolyDataReader.h>
# include <vtkXMLStructuredGridReader.h>
# include <vtkXMLRectilinearGridReader.h>
# include <vtkXMLImageDataReader.h>
#endif
#include "FemPostPipeline.h"
#include "FemMesh.h"
#include "FemMeshObject.h"
#include "FemVTKTools.h"
#include <Base/Console.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
#include <Mod/Fem/App/FemPostPipelinePy.h>
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject)
const char* FemPostPipeline::ModeEnums[]= {"Serial","Parallel",NULL};
FemPostPipeline::FemPostPipeline()
{
ADD_PROPERTY_TYPE(Filter, (0), "Pipeline", App::Prop_None, "The filter used in in this pipeline");
ADD_PROPERTY_TYPE(Functions, (0), "Pipeline", App::Prop_Hidden, "The function provider which groups all pipeline functions");
ADD_PROPERTY_TYPE(Mode,(long(0)), "Pipeline", App::Prop_None, "Selects the pipeline data transition mode. In serial every filter"
"gets the output of the previous one as input, in parallel every"
"filter gets the pipelien source as input.");
Mode.setEnums(ModeEnums);
}
FemPostPipeline::~FemPostPipeline()
{
}
short FemPostPipeline::mustExecute(void) const
{
if(Mode.isTouched())
return 1;
return FemPostFilter::mustExecute();
}
DocumentObjectExecReturn* FemPostPipeline::execute(void) {
//if we are the toplevel pipeline our data object is not created by filters, we are the main source!
if(!Input.getValue())
return StdReturn;
//now if we are a filter than our data object is created by the filter we hold
//if we are in serial mode we just copy over the data of the last filter,
//but if we are in parallel we need to combine all filter results
if(Mode.getValue() == 0) {
//serial
Data.setValue(getLastPostObject()->Data.getValue());
}
else {
//parallel. go through all filters and append the result
const std::vector<App::DocumentObject*>& filters = Filter.getValues();
std::vector<App::DocumentObject*>::const_iterator it = filters.begin();
vtkSmartPointer<vtkAppendFilter> append = vtkSmartPointer<vtkAppendFilter>::New();
for(;it != filters.end(); ++it) {
append->AddInputDataObject(static_cast<FemPostObject*>(*it)->Data.getValue());
}
append->Update();
Data.setValue(append->GetOutputDataObject(0));
}
return Fem::FemPostObject::execute();
}
bool FemPostPipeline::canRead(Base::FileInfo File) {
if (File.hasExtension("vtk") ||
// from FemResult only unstructural mesh is supported in femvtktoools.cpp
File.hasExtension("vtp") ||
File.hasExtension("vts") ||
File.hasExtension("vtr") ||
File.hasExtension("vti") ||
File.hasExtension("vtu"))
return true;
return false;
}
void FemPostPipeline::read(Base::FileInfo File) {
// checking on the file
if (!File.isReadable())
throw Base::FileException("File to load not existing or not readable", File);
if (File.hasExtension("vtu"))
readXMLFile<vtkXMLUnstructuredGridReader>(File.filePath());
else if (File.hasExtension("vtp"))
readXMLFile<vtkXMLPolyDataReader>(File.filePath());
else if (File.hasExtension("vts"))
readXMLFile<vtkXMLStructuredGridReader>(File.filePath());
else if (File.hasExtension("vtr"))
readXMLFile<vtkXMLRectilinearGridReader>(File.filePath());
else if (File.hasExtension("vti"))
readXMLFile<vtkXMLImageDataReader>(File.filePath());
else if (File.hasExtension("vtk"))
readXMLFile<vtkDataSetReader>(File.filePath());
else
throw Base::FileException("Unknown extension");
}
// PyObject *FemPostPipeline::getPyObject()
// {
// if (PythonObject.is(Py::_None())){
// // ref counter is set to 1
// PythonObject = Py::Object(new DocumentObjectPy(this),true);
// }
// return Py::new_reference_to(PythonObject);
// }
void FemPostPipeline::onChanged(const Property* prop)
{
if(prop == &Filter || prop == &Mode) {
//we check if all connections are right and add new ones if needed
std::vector<App::DocumentObject*> objs = Filter.getValues();
if(objs.empty())
return;
std::vector<App::DocumentObject*>::iterator it = objs.begin();
FemPostFilter* filter = static_cast<FemPostFilter*>(*it);
//If we have a Input we need to ensure our filters are connected correctly
if(Input.getValue()) {
//the first filter is always connected to the input
if(filter->Input.getValue() != Input.getValue())
filter->Input.setValue(Input.getValue());
//all the others need to be connected to the previous filter or the source, dependent on the mode
++it;
for(; it != objs.end(); ++it) {
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
if(Mode.getValue() == 0) { //serial mode
if( nextFilter->Input.getValue() != filter)
nextFilter->Input.setValue(filter);
}
else { //Parallel mode
if( nextFilter->Input.getValue() != Input.getValue())
nextFilter->Input.setValue(Input.getValue());
}
filter = nextFilter;
};
}
//if we have no input the filters are responsible of grabbing the pipeline data themself
else {
//the first filter must always grab the data
if(filter->Input.getValue() != NULL)
filter->Input.setValue(NULL);
//all the others need to be connected to the previous filter or grab the data, dependent on mode
++it;
for(; it != objs.end(); ++it) {
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
if(Mode.getValue() == 0) { //serial mode
if( nextFilter->Input.getValue() != filter)
nextFilter->Input.setValue(filter);
}
else { //Parallel mode
if( nextFilter->Input.getValue() != NULL)
nextFilter->Input.setValue(NULL);
}
filter = nextFilter;
};
}
}
App::GeoFeature::onChanged(prop);
}
FemPostObject* FemPostPipeline::getLastPostObject() {
if(Filter.getValues().empty())
return this;
return static_cast<FemPostObject*>(Filter.getValues().back());
}
bool FemPostPipeline::holdsPostObject(FemPostObject* obj) {
std::vector<App::DocumentObject*>::const_iterator it = Filter.getValues().begin();
for(; it != Filter.getValues().end(); ++it) {
if(*it == obj)
return true;
}
return false;
}
void FemPostPipeline::load(FemResultObject* res) {
if(!res->Mesh.getValue() || !res->Mesh.getValue()->isDerivedFrom(Fem::FemMeshObject::getClassTypeId())) {
Base::Console().Warning("Mesh of result object is empty or not derived from Fem::FemMeshObject\n");
return;
}
//first copy the mesh over
// ***************************
const FemMesh& mesh = static_cast<FemMeshObject*>(res->Mesh.getValue())->FemMesh.getValue();
vtkSmartPointer<vtkUnstructuredGrid> grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
FemVTKTools::exportVTKMesh(&mesh, grid);
//Now copy the point data over
// ***************************
FemVTKTools::exportFreeCADResult(res, grid);
Data.setValue(grid);
}
PyObject* FemPostPipeline::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new FemPostPipelinePy(this),true);
}
return Py::new_reference_to(PythonObject);
}

View File

@@ -1,88 +1,88 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostPipeline_H
#define Fem_FemPostPipeline_H
#include "FemPostObject.h"
#include "FemPostFilter.h"
#include "FemPostFunction.h"
#include "FemResultObject.h"
#include <vtkSmartPointer.h>
#include <vtkDataSet.h>
namespace Fem
{
class AppFemExport FemPostPipeline : public Fem::FemPostFilter
{
PROPERTY_HEADER(Fem::FemPostPipeline);
public:
/// Constructor
FemPostPipeline(void);
virtual ~FemPostPipeline();
App::PropertyLinkList Filter;
App::PropertyLink Functions;
App::PropertyEnumeration Mode;
short mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
PyObject* getPyObject();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostPipeline";
}
//load data from files
static bool canRead(Base::FileInfo file);
void read(Base::FileInfo file);
//load from results
void load(FemResultObject* res);
//Pipeline handling
FemPostObject* getLastPostObject();
bool holdsPostObject(FemPostObject* obj);
protected:
virtual void onChanged(const App::Property* prop);
private:
static const char* ModeEnums[];
template<class TReader> void readXMLFile(std::string file) {
vtkSmartPointer<TReader> reader = vtkSmartPointer<TReader>::New();
reader->SetFileName(file.c_str());
reader->Update();
Data.setValue(reader->GetOutput());
}
};
} //namespace Fem
#endif // Fem_FemPostPipeline_H
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_FemPostPipeline_H
#define Fem_FemPostPipeline_H
#include "FemPostObject.h"
#include "FemPostFilter.h"
#include "FemPostFunction.h"
#include "FemResultObject.h"
#include <vtkSmartPointer.h>
#include <vtkDataSet.h>
namespace Fem
{
class AppFemExport FemPostPipeline : public Fem::FemPostFilter
{
PROPERTY_HEADER(Fem::FemPostPipeline);
public:
/// Constructor
FemPostPipeline(void);
virtual ~FemPostPipeline();
App::PropertyLinkList Filter;
App::PropertyLink Functions;
App::PropertyEnumeration Mode;
short mustExecute(void) const;
virtual App::DocumentObjectExecReturn* execute(void);
PyObject* getPyObject();
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostPipeline";
}
//load data from files
static bool canRead(Base::FileInfo file);
void read(Base::FileInfo file);
//load from results
void load(FemResultObject* res);
//Pipeline handling
FemPostObject* getLastPostObject();
bool holdsPostObject(FemPostObject* obj);
protected:
virtual void onChanged(const App::Property* prop);
private:
static const char* ModeEnums[];
template<class TReader> void readXMLFile(std::string file) {
vtkSmartPointer<TReader> reader = vtkSmartPointer<TReader>::New();
reader->SetFileName(file.c_str());
reader->Update();
Data.setValue(reader->GetOutput());
}
};
} //namespace Fem
#endif // Fem_FemPostPipeline_H

View File

@@ -1,358 +1,358 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <vtkPolyData.h>
# include <vtkStructuredGrid.h>
# include <vtkRectilinearGrid.h>
# include <vtkUnstructuredGrid.h>
# include <vtkUniformGrid.h>
# include <vtkCompositeDataSet.h>
# include <vtkMultiBlockDataSet.h>
# include <vtkMultiPieceDataSet.h>
# include <vtkXMLDataSetWriter.h>
# include <vtkXMLPolyDataReader.h>
# include <vtkXMLStructuredGridReader.h>
# include <vtkXMLUnstructuredGridReader.h>
# include <vtkXMLRectilinearGridReader.h>
# include <vtkXMLImageDataReader.h>
#endif
#include <Base/FileInfo.h>
#include <Base/Console.h>
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <App/Application.h>
#include <App/DocumentObject.h>
#include "PropertyPostDataObject.h"
#ifndef _PreComp_
#endif
using namespace Fem;
TYPESYSTEM_SOURCE(Fem::PropertyPostDataObject , App::Property)
PropertyPostDataObject::PropertyPostDataObject()
{
}
PropertyPostDataObject::~PropertyPostDataObject()
{
}
void PropertyPostDataObject::setValue(const vtkSmartPointer<vtkDataObject>& ds)
{
aboutToSetValue();
if(ds) {
createDataObjectByExternalType(ds);
m_dataObject->DeepCopy(ds);
}
else
m_dataObject = NULL;
hasSetValue();
}
const vtkSmartPointer<vtkDataObject>& PropertyPostDataObject::getValue(void)const
{
return m_dataObject;
}
bool PropertyPostDataObject::isComposite() {
return m_dataObject && !m_dataObject->IsA("vtkDataSet");
}
bool PropertyPostDataObject::isDataSet() {
return m_dataObject && m_dataObject->IsA("vtkDataSet");
}
int PropertyPostDataObject::getDataType() {
if(!m_dataObject)
return -1;
return m_dataObject->GetDataObjectType();
}
PyObject *PropertyPostDataObject::getPyObject(void)
{
//TODO: fetch the vtk python object from the data set and return it
return new PyObject();
}
void PropertyPostDataObject::setPyObject(PyObject * /*value*/)
{
}
App::Property *PropertyPostDataObject::Copy(void) const
{
PropertyPostDataObject *prop = new PropertyPostDataObject();
if (m_dataObject) {
prop->createDataObjectByExternalType(m_dataObject);
prop->m_dataObject->DeepCopy(m_dataObject);
}
return prop;
}
void PropertyPostDataObject::createDataObjectByExternalType(vtkSmartPointer< vtkDataObject > ex) {
switch( ex->GetDataObjectType() ) {
case VTK_POLY_DATA:
m_dataObject = vtkSmartPointer<vtkPolyData>::New();
break;
case VTK_STRUCTURED_GRID:
m_dataObject = vtkSmartPointer<vtkStructuredGrid>::New();
break;
case VTK_RECTILINEAR_GRID:
m_dataObject = vtkSmartPointer<vtkRectilinearGrid>::New();
break;
case VTK_UNSTRUCTURED_GRID:
m_dataObject = vtkSmartPointer<vtkUnstructuredGrid>::New();
break;
case VTK_UNIFORM_GRID:
m_dataObject = vtkSmartPointer<vtkUniformGrid>::New();
break;
case VTK_COMPOSITE_DATA_SET:
m_dataObject = vtkCompositeDataSet::New();
break;
case VTK_MULTIBLOCK_DATA_SET:
m_dataObject = vtkSmartPointer<vtkMultiBlockDataSet>::New();
break;
case VTK_MULTIPIECE_DATA_SET:
m_dataObject = vtkSmartPointer<vtkMultiPieceDataSet>::New();
break;
default:
break;
};
}
void PropertyPostDataObject::Paste(const App::Property &from)
{
aboutToSetValue();
m_dataObject = dynamic_cast<const PropertyPostDataObject&>(from).m_dataObject;
hasSetValue();
}
unsigned int PropertyPostDataObject::getMemSize (void) const
{
return m_dataObject->GetActualMemorySize();
}
void PropertyPostDataObject::getPaths(std::vector<App::ObjectIdentifier> & /*paths*/) const
{
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("ShapeType")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Orientation")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Length")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Area")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Volume")));
}
void PropertyPostDataObject::Save (Base::Writer &writer) const
{
std::string extension;
if(!m_dataObject)
return;
switch( m_dataObject->GetDataObjectType() ) {
case VTK_POLY_DATA:
extension = "vtp";
break;
case VTK_STRUCTURED_GRID:
extension = "vts";
break;
case VTK_RECTILINEAR_GRID:
extension = "vtr";
break;
case VTK_UNSTRUCTURED_GRID:
extension = "vtu";
break;
case VTK_UNIFORM_GRID:
extension = "vti"; //image data
break;
//TODO:multi-datasets use multiple files, this needs to be implemented specially
// case VTK_COMPOSITE_DATA_SET:
// prop->m_dataObject = vtkCompositeDataSet::New();
// break;
// case VTK_MULTIBLOCK_DATA_SET:
// prop->m_dataObject = vtkMultiBlockDataSet::New();
// break;
// case VTK_MULTIPIECE_DATA_SET:
// prop->m_dataObject = vtkMultiPieceDataSet::New();
// break;
default:
break;
};
if(!writer.isForceXML()) {
std::string file = "Data." + extension;
writer.Stream() << writer.ind() << "<Data file=\""
<< writer.addFile(file.c_str(), this)
<< "\"/>" << std::endl;
}
}
void PropertyPostDataObject::Restore(Base::XMLReader &reader)
{
reader.readElement("Data");
if(!reader.hasAttribute("file"))
return;
std::string file (reader.getAttribute("file") );
if (!file.empty()) {
// initiate a file read
reader.addFile(file.c_str(),this);
}
}
void PropertyPostDataObject::SaveDocFile (Base::Writer &writer) const
{
// If the shape is empty we simply store nothing. The file size will be 0 which
// can be checked when reading in the data.
if (!m_dataObject)
return;
// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(App::Application::getTempFileName());
vtkSmartPointer<vtkXMLDataSetWriter> xmlWriter = vtkSmartPointer<vtkXMLDataSetWriter>::New();
xmlWriter->SetInputDataObject(m_dataObject);
xmlWriter->SetFileName(fi.filePath().c_str());
xmlWriter->SetDataModeToBinary();
if ( xmlWriter->Write() != 1 ) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Dataset of '%s' cannot be written to vtk file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save vtk file '%s'\n", fi.filePath().c_str());
}
std::stringstream ss;
ss << "Cannot save vtk file '" << fi.filePath() << "'";
writer.addError(ss.str());
}
Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file){
std::streambuf* buf = file.rdbuf();
writer.Stream() << buf;
}
file.close();
// remove temp file
fi.deleteFile();
}
void PropertyPostDataObject::RestoreDocFile(Base::Reader &reader)
{
Base::FileInfo xml(reader.getFileName());
// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(App::Application::getTempFileName());
// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();
// Read the data from the temp file
if (ulSize > 0) {
std::string extension = xml.extension();
//TODO: read in of composite data structures need to be coded, including replace of "GetOutputAsDataSet()"
vtkSmartPointer<vtkXMLReader> xmlReader;
if(extension == "vtp")
xmlReader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
else if (extension == "vts")
xmlReader = vtkSmartPointer<vtkXMLStructuredGridReader>::New();
else if (extension == "vtr")
xmlReader = vtkSmartPointer<vtkXMLRectilinearGridReader>::New();
else if (extension == "vtu")
xmlReader = vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
else if (extension == "vti")
xmlReader = vtkSmartPointer<vtkXMLImageDataReader>::New();
xmlReader->SetFileName(fi.filePath().c_str());
xmlReader->Update();
if (!xmlReader->GetOutputAsDataSet()) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded Dataset file '%s' seems to be empty\n", fi.filePath().c_str());
}
}
else {
aboutToSetValue();
createDataObjectByExternalType(xmlReader->GetOutputAsDataSet());
m_dataObject->DeepCopy(xmlReader->GetOutputAsDataSet());
hasSetValue();
}
}
// delete the temp file
fi.deleteFile();
}
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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 <vtkPolyData.h>
# include <vtkStructuredGrid.h>
# include <vtkRectilinearGrid.h>
# include <vtkUnstructuredGrid.h>
# include <vtkUniformGrid.h>
# include <vtkCompositeDataSet.h>
# include <vtkMultiBlockDataSet.h>
# include <vtkMultiPieceDataSet.h>
# include <vtkXMLDataSetWriter.h>
# include <vtkXMLPolyDataReader.h>
# include <vtkXMLStructuredGridReader.h>
# include <vtkXMLUnstructuredGridReader.h>
# include <vtkXMLRectilinearGridReader.h>
# include <vtkXMLImageDataReader.h>
#endif
#include <Base/FileInfo.h>
#include <Base/Console.h>
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <App/Application.h>
#include <App/DocumentObject.h>
#include "PropertyPostDataObject.h"
#ifndef _PreComp_
#endif
using namespace Fem;
TYPESYSTEM_SOURCE(Fem::PropertyPostDataObject , App::Property)
PropertyPostDataObject::PropertyPostDataObject()
{
}
PropertyPostDataObject::~PropertyPostDataObject()
{
}
void PropertyPostDataObject::setValue(const vtkSmartPointer<vtkDataObject>& ds)
{
aboutToSetValue();
if(ds) {
createDataObjectByExternalType(ds);
m_dataObject->DeepCopy(ds);
}
else
m_dataObject = NULL;
hasSetValue();
}
const vtkSmartPointer<vtkDataObject>& PropertyPostDataObject::getValue(void)const
{
return m_dataObject;
}
bool PropertyPostDataObject::isComposite() {
return m_dataObject && !m_dataObject->IsA("vtkDataSet");
}
bool PropertyPostDataObject::isDataSet() {
return m_dataObject && m_dataObject->IsA("vtkDataSet");
}
int PropertyPostDataObject::getDataType() {
if(!m_dataObject)
return -1;
return m_dataObject->GetDataObjectType();
}
PyObject *PropertyPostDataObject::getPyObject(void)
{
//TODO: fetch the vtk python object from the data set and return it
return new PyObject();
}
void PropertyPostDataObject::setPyObject(PyObject * /*value*/)
{
}
App::Property *PropertyPostDataObject::Copy(void) const
{
PropertyPostDataObject *prop = new PropertyPostDataObject();
if (m_dataObject) {
prop->createDataObjectByExternalType(m_dataObject);
prop->m_dataObject->DeepCopy(m_dataObject);
}
return prop;
}
void PropertyPostDataObject::createDataObjectByExternalType(vtkSmartPointer< vtkDataObject > ex) {
switch( ex->GetDataObjectType() ) {
case VTK_POLY_DATA:
m_dataObject = vtkSmartPointer<vtkPolyData>::New();
break;
case VTK_STRUCTURED_GRID:
m_dataObject = vtkSmartPointer<vtkStructuredGrid>::New();
break;
case VTK_RECTILINEAR_GRID:
m_dataObject = vtkSmartPointer<vtkRectilinearGrid>::New();
break;
case VTK_UNSTRUCTURED_GRID:
m_dataObject = vtkSmartPointer<vtkUnstructuredGrid>::New();
break;
case VTK_UNIFORM_GRID:
m_dataObject = vtkSmartPointer<vtkUniformGrid>::New();
break;
case VTK_COMPOSITE_DATA_SET:
m_dataObject = vtkCompositeDataSet::New();
break;
case VTK_MULTIBLOCK_DATA_SET:
m_dataObject = vtkSmartPointer<vtkMultiBlockDataSet>::New();
break;
case VTK_MULTIPIECE_DATA_SET:
m_dataObject = vtkSmartPointer<vtkMultiPieceDataSet>::New();
break;
default:
break;
};
}
void PropertyPostDataObject::Paste(const App::Property &from)
{
aboutToSetValue();
m_dataObject = dynamic_cast<const PropertyPostDataObject&>(from).m_dataObject;
hasSetValue();
}
unsigned int PropertyPostDataObject::getMemSize (void) const
{
return m_dataObject->GetActualMemorySize();
}
void PropertyPostDataObject::getPaths(std::vector<App::ObjectIdentifier> & /*paths*/) const
{
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("ShapeType")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Orientation")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Length")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Area")));
// paths.push_back(App::ObjectIdentifier(getContainer()) << App::ObjectIdentifier::Component::SimpleComponent(getName())
// << App::ObjectIdentifier::Component::SimpleComponent(App::ObjectIdentifier::String("Volume")));
}
void PropertyPostDataObject::Save (Base::Writer &writer) const
{
std::string extension;
if(!m_dataObject)
return;
switch( m_dataObject->GetDataObjectType() ) {
case VTK_POLY_DATA:
extension = "vtp";
break;
case VTK_STRUCTURED_GRID:
extension = "vts";
break;
case VTK_RECTILINEAR_GRID:
extension = "vtr";
break;
case VTK_UNSTRUCTURED_GRID:
extension = "vtu";
break;
case VTK_UNIFORM_GRID:
extension = "vti"; //image data
break;
//TODO:multi-datasets use multiple files, this needs to be implemented specially
// case VTK_COMPOSITE_DATA_SET:
// prop->m_dataObject = vtkCompositeDataSet::New();
// break;
// case VTK_MULTIBLOCK_DATA_SET:
// prop->m_dataObject = vtkMultiBlockDataSet::New();
// break;
// case VTK_MULTIPIECE_DATA_SET:
// prop->m_dataObject = vtkMultiPieceDataSet::New();
// break;
default:
break;
};
if(!writer.isForceXML()) {
std::string file = "Data." + extension;
writer.Stream() << writer.ind() << "<Data file=\""
<< writer.addFile(file.c_str(), this)
<< "\"/>" << std::endl;
}
}
void PropertyPostDataObject::Restore(Base::XMLReader &reader)
{
reader.readElement("Data");
if(!reader.hasAttribute("file"))
return;
std::string file (reader.getAttribute("file") );
if (!file.empty()) {
// initiate a file read
reader.addFile(file.c_str(),this);
}
}
void PropertyPostDataObject::SaveDocFile (Base::Writer &writer) const
{
// If the shape is empty we simply store nothing. The file size will be 0 which
// can be checked when reading in the data.
if (!m_dataObject)
return;
// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(App::Application::getTempFileName());
vtkSmartPointer<vtkXMLDataSetWriter> xmlWriter = vtkSmartPointer<vtkXMLDataSetWriter>::New();
xmlWriter->SetInputDataObject(m_dataObject);
xmlWriter->SetFileName(fi.filePath().c_str());
xmlWriter->SetDataModeToBinary();
if ( xmlWriter->Write() != 1 ) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Dataset of '%s' cannot be written to vtk file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save vtk file '%s'\n", fi.filePath().c_str());
}
std::stringstream ss;
ss << "Cannot save vtk file '" << fi.filePath() << "'";
writer.addError(ss.str());
}
Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file){
std::streambuf* buf = file.rdbuf();
writer.Stream() << buf;
}
file.close();
// remove temp file
fi.deleteFile();
}
void PropertyPostDataObject::RestoreDocFile(Base::Reader &reader)
{
Base::FileInfo xml(reader.getFileName());
// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(App::Application::getTempFileName());
// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();
// Read the data from the temp file
if (ulSize > 0) {
std::string extension = xml.extension();
//TODO: read in of composite data structures need to be coded, including replace of "GetOutputAsDataSet()"
vtkSmartPointer<vtkXMLReader> xmlReader;
if(extension == "vtp")
xmlReader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
else if (extension == "vts")
xmlReader = vtkSmartPointer<vtkXMLStructuredGridReader>::New();
else if (extension == "vtr")
xmlReader = vtkSmartPointer<vtkXMLRectilinearGridReader>::New();
else if (extension == "vtu")
xmlReader = vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
else if (extension == "vti")
xmlReader = vtkSmartPointer<vtkXMLImageDataReader>::New();
xmlReader->SetFileName(fi.filePath().c_str());
xmlReader->Update();
if (!xmlReader->GetOutputAsDataSet()) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded Dataset file '%s' seems to be empty\n", fi.filePath().c_str());
}
}
else {
aboutToSetValue();
createDataObjectByExternalType(xmlReader->GetOutputAsDataSet());
m_dataObject->DeepCopy(xmlReader->GetOutputAsDataSet());
hasSetValue();
}
}
// delete the temp file
fi.deleteFile();
}

View File

@@ -1,90 +1,90 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_PROPERTYPOSTDATASET_H
#define FEM_PROPERTYPOSTDATASET_H
#include "PreCompiled.h"
#include <App/Property.h>
#include <vtkSmartPointer.h>
#include <vtkDataObject.h>
#include <vtkDataSet.h>
namespace Fem
{
/** The vtk data set property class.
* @author Stefan Tröger
*/
class FemExport PropertyPostDataObject : public App::Property
{
TYPESYSTEM_HEADER();
public:
PropertyPostDataObject();
~PropertyPostDataObject();
/** @name Getter/setter */
//@{
/// set the dataset
void setValue(const vtkSmartPointer<vtkDataObject>&);
/// get the part shape
const vtkSmartPointer<vtkDataObject>& getValue(void) const;
/// check if we hold a dataset or a dataobject (which would mean a composite data structure)
bool isDataSet();
bool isComposite();
int getDataType();
//@}
/** @name Python interface */
//@{
PyObject* getPyObject(void);
void setPyObject(PyObject *value);
//@}
/** @name Save/restore */
//@{
void Save (Base::Writer &writer) const;
void Restore(Base::XMLReader &reader);
void SaveDocFile (Base::Writer &writer) const;
void RestoreDocFile(Base::Reader &reader);
App::Property *Copy(void) const;
void Paste(const App::Property &from);
unsigned int getMemSize (void) const;
//@}
/// Get valid paths for this property; used by auto completer
virtual void getPaths(std::vector<App::ObjectIdentifier> & paths) const;
protected:
void createDataObjectByExternalType(vtkSmartPointer<vtkDataObject> ex);
vtkSmartPointer<vtkDataObject> m_dataObject;
};
} //namespace FEM
#endif // FEM_PROPERTYPOSTDATASET_H
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.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_PROPERTYPOSTDATASET_H
#define FEM_PROPERTYPOSTDATASET_H
#include "PreCompiled.h"
#include <App/Property.h>
#include <vtkSmartPointer.h>
#include <vtkDataObject.h>
#include <vtkDataSet.h>
namespace Fem
{
/** The vtk data set property class.
* @author Stefan Tröger
*/
class FemExport PropertyPostDataObject : public App::Property
{
TYPESYSTEM_HEADER();
public:
PropertyPostDataObject();
~PropertyPostDataObject();
/** @name Getter/setter */
//@{
/// set the dataset
void setValue(const vtkSmartPointer<vtkDataObject>&);
/// get the part shape
const vtkSmartPointer<vtkDataObject>& getValue(void) const;
/// check if we hold a dataset or a dataobject (which would mean a composite data structure)
bool isDataSet();
bool isComposite();
int getDataType();
//@}
/** @name Python interface */
//@{
PyObject* getPyObject(void);
void setPyObject(PyObject *value);
//@}
/** @name Save/restore */
//@{
void Save (Base::Writer &writer) const;
void Restore(Base::XMLReader &reader);
void SaveDocFile (Base::Writer &writer) const;
void RestoreDocFile(Base::Reader &reader);
App::Property *Copy(void) const;
void Paste(const App::Property &from);
unsigned int getMemSize (void) const;
//@}
/// Get valid paths for this property; used by auto completer
virtual void getPaths(std::vector<App::ObjectIdentifier> & paths) const;
protected:
void createDataObjectByExternalType(vtkSmartPointer<vtkDataObject> ex);
vtkSmartPointer<vtkDataObject> m_dataObject;
};
} //namespace FEM
#endif // FEM_PROPERTYPOSTDATASET_H