Fem: Move functions to Tools class

This commit is contained in:
marioalexis
2024-05-29 00:36:04 -03:00
parent 047b184df4
commit 25febcd7af
5 changed files with 144 additions and 93 deletions

View File

@@ -147,18 +147,6 @@ float Constraint::getScaleFactor() const
return Scale.getValue() * sizeFactor;
}
void setSubShapeLocation(const Part::Feature* feat, TopoDS_Shape& sh)
{
// subshape placement is not necessarily the same as the
// feature placement.
Base::Matrix4D matrix = Part::TopoShape::convert(sh.Location().Transformation());
Base::Placement shPla {matrix};
Base::Placement featlPlaInv = feat->Placement.getValue().inverse();
Base::Placement shGlobalPla = feat->globalPlacement() * featlPlaInv * shPla;
sh.Location(Part::Tools::fromPlacement(shGlobalPla));
}
constexpr int CONSTRAINTSTEPLIMIT = 50;
void Constraint::onChanged(const App::Property* prop)
@@ -177,26 +165,20 @@ void Constraint::onChanged(const App::Property* prop)
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(), !execute);
if (!sh.IsNull() && sh.ShapeType() == TopAbs_FACE) {
setSubShapeLocation(feat, sh);
// 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...
break;
}
sh = Tools::getFeatureSubShape(feat, SubElements[i].c_str(), !execute);
if (!sh.IsNull() && 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...
break;
}
}
@@ -274,22 +256,15 @@ bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
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(), true);
Part::Feature* feat = static_cast<Part::Feature*>(Objects[i]);
sh = Tools::getFeatureSubShape(feat, SubElements[i].c_str(), true);
if (sh.IsNull()) {
return false;
}
setSubShapeLocation(feat, sh);
// Scale by bounding box of the object
Bnd_Box box;
BRepBndLib::Add(toposhape.getShape(), box);
BRepBndLib::Add(feat->Shape.getShape().getShape(), box);
double l = sqrt(box.SquareExtent() / 3.0);
*scale = this->calcSizeFactor(l);
@@ -471,40 +446,6 @@ bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
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,

View File

@@ -198,16 +198,6 @@ protected:
std::vector<Base::Vector3d>& normals,
double* scale) const;
/**
* @brief Extract properties of cylindrical face.
*
* @note
* This method is very specific and doesn't require access to member
* variables. It should be rewritten at a different place.
*/
bool
getCylinder(double& radius, double& height, Base::Vector3d& base, Base::Vector3d& axis) const;
/**
* @brief Calculate point of cylindrical face where to render widget.
*

View File

@@ -32,7 +32,7 @@
#include <Mod/Part/App/PartFeature.h>
#include "FemConstraintBearing.h"
#include "FemTools.h"
using namespace Fem;
@@ -74,9 +74,17 @@ void ConstraintBearing::onChanged(const App::Property* prop)
if (prop == &References) {
// Find data of cylinder
std::vector<App::DocumentObject*> ref = References.getValues();
std::vector<std::string> subRef = References.getSubValues();
if (ref.empty()) {
return;
}
Part::Feature* feat = static_cast<Part::Feature*>(ref.front());
TopoDS_Shape sh = Tools::getFeatureSubShape(feat, subRef.front().c_str(), true);
double radius, height;
Base::Vector3d base, axis;
if (!getCylinder(radius, height, base, axis)) {
if (!Tools::getCylinderParams(sh, base, axis, height, radius)) {
return;
}
Radius.setValue(radius);
@@ -113,12 +121,19 @@ void ConstraintBearing::onChanged(const App::Property* prop)
}
}
double radius, height;
Base::Vector3d base, axis;
if (!getCylinder(radius, height, base, axis)) {
std::vector<App::DocumentObject*> ref = References.getValues();
std::vector<std::string> subRef = References.getSubValues();
if (ref.empty()) {
return;
}
feat = static_cast<Part::Feature*>(ref.front());
sh = Tools::getFeatureSubShape(feat, subRef.front().c_str(), true);
double radius, height;
Base::Vector3d base, axis;
if (!Tools::getCylinderParams(sh, base, axis, height, radius)) {
return;
}
base = getBasePoint(base + axis * height / 2, axis, Location, Dist.getValue());
BasePoint.setValue(base);
BasePoint.touch();
}

View File

@@ -27,16 +27,19 @@
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_Line.hxx>
#include <Precision.hxx>
#include <TColgp_Array2OfPnt.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Dir.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
@@ -44,6 +47,8 @@
#endif
#include <App/Application.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/Tools.h>
#include "FemTools.h"
@@ -322,3 +327,74 @@ std::string Fem::Tools::checkIfBinaryExists(std::string prefSection,
}
return "";
}
Base::Placement Fem::Tools::getSubShapeGlobalLocation(const Part::Feature* feat,
const TopoDS_Shape& sh)
{
Base::Matrix4D matrix = Part::TopoShape::convert(sh.Location().Transformation());
Base::Placement shPla {matrix};
Base::Placement featlPlaInv = feat->Placement.getValue().inverse();
Base::Placement shGlobalPla = feat->globalPlacement() * featlPlaInv * shPla;
return shGlobalPla;
}
void Fem::Tools::setSubShapeGlobalLocation(const Part::Feature* feat, TopoDS_Shape& sh)
{
Base::Placement pla = getSubShapeGlobalLocation(feat, sh);
sh.Location(Part::Tools::fromPlacement(pla));
}
TopoDS_Shape
Fem::Tools::getFeatureSubShape(const Part::Feature* feat, const char* subName, bool silent)
{
TopoDS_Shape sh;
const Part::TopoShape& toposhape = feat->Shape.getShape();
if (toposhape.isNull()) {
return sh;
}
sh = toposhape.getSubShape(subName, silent);
if (sh.IsNull()) {
return sh;
}
setSubShapeGlobalLocation(feat, sh);
return sh;
}
bool Fem::Tools::getCylinderParams(const TopoDS_Shape& sh,
Base::Vector3d& base,
Base::Vector3d& axis,
double& height,
double& radius)
{
TopoDS_Face face = TopoDS::Face(sh);
BRepAdaptor_Surface surface(face);
if (!(surface.GetType() == GeomAbs_Cylinder)) {
return false;
}
gp_Cylinder cyl = surface.Cylinder();
gp_Pnt start = surface.Value(surface.FirstUParameter(), surface.FirstVParameter());
gp_Pnt end = surface.Value(surface.FirstUParameter(), surface.LastVParameter());
Handle(Geom_Curve) handle = new Geom_Line(cyl.Axis());
GeomAPI_ProjectPointOnCurve proj(start, handle);
gp_XYZ startProj = proj.NearestPoint().XYZ();
proj.Perform(end);
gp_XYZ endProj = proj.NearestPoint().XYZ();
gp_XYZ ax(endProj - startProj);
gp_XYZ center = (startProj + endProj) / 2.0;
gp_Dir dir(ax);
height = ax.Modulus();
radius = cyl.Radius();
base = Base::Vector3d(center.X(), center.Y(), center.Z());
axis = Base::Vector3d(dir.X(), dir.Y(), dir.Z());
return true;
}

View File

@@ -24,14 +24,22 @@
#ifndef FEM_TOOLS_H
#define FEM_TOOLS_H
#include <Base/Placement.h>
#include <Base/Vector3D.h>
#include <Mod/Fem/FemGlobal.h>
#include <gp_XYZ.hxx>
#include <TopoDS_Shape.hxx>
class TopoDS_Shape;
class TopoDS_Edge;
class TopoDS_Face;
namespace Part
{
class Feature;
}
namespace Fem
{
@@ -75,6 +83,27 @@ public:
static std::string checkIfBinaryExists(std::string prefSection,
std::string prefBinaryPath,
std::string prefBinaryName);
/*!
Subshape placement is not necessarily the same as the
feature placement
*/
static Base::Placement getSubShapeGlobalLocation(const Part::Feature* feat,
const TopoDS_Shape& sh);
static void setSubShapeGlobalLocation(const Part::Feature* feat, TopoDS_Shape& sh);
/*!
Get subshape from Part Feature. The subShape is returned with global location
*/
static TopoDS_Shape
getFeatureSubShape(const Part::Feature* feat, const char* subName, bool silent);
/*!
Get cylinder parameters. Base is located at the center of the cylinder
*/
static bool getCylinderParams(const TopoDS_Shape& sh,
Base::Vector3d& base,
Base::Vector3d& axis,
double& height,
double& radius);
};
} // namespace Fem