Skip to content

Commit

Permalink
Fem: Constraint symbol scaling based on shape size - fixes FreeCAD#7030
Browse files Browse the repository at this point in the history
  • Loading branch information
marioalexis84 committed Apr 22, 2024
1 parent 1e42992 commit 863cb80
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 70 deletions.
48 changes: 14 additions & 34 deletions src/Mod/Fem/App/FemConstraint.cpp
Expand Up @@ -28,6 +28,7 @@
#include <BRepAdaptor_CompCurve.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBndLib.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRepGProp.hxx>
#include <BRepGProp_Face.hxx>
Expand Down Expand Up @@ -131,22 +132,14 @@ App::DocumentObjectExecReturn* Constraint::execute()
}
}

// OvG: Provide the ability to determine how big to draw constraint arrows etc.
unsigned int Constraint::calcSizeFactor(double lparam) const
// Provide the ability to determine how big to draw constraint arrows etc.
// Try to get symbol size equal to 1/5 of the characteristic length of
// the object. Typical symbol size is 5, so use 1/25 of the characteristic length.
double Constraint::calcSizeFactor(double characLen) const
{
return (static_cast<int>(round(log(lparam) * log(lparam) * log(lparam) / 10)) > 1)
? (static_cast<int>(round(log(lparam) * log(lparam) * log(lparam) / 10)))
: 1;
}

unsigned int Constraint::calcSizeFactor(double lvparam, double luparam) const
{
return calcSizeFactor((lvparam + luparam) / 2.0);
}

unsigned int Constraint::calcSizeFactor() const
{
return 1;
double l = characLen / 25.0;
l = ((round(l)) > 1) ? round(l) : l;
return (l > Precision::Confusion() ? l : 1);
}

float Constraint::getScaleFactor() const
Expand Down Expand Up @@ -272,7 +265,7 @@ void Constraint::handleChangedPropertyType(Base::XMLReader& reader,

bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
std::vector<Base::Vector3d>& normals,
int* scale) const
double* scale) const
{
std::vector<App::DocumentObject*> Objects = References.getValues();
std::vector<std::string> SubElements = References.getSubValues();
Expand All @@ -294,42 +287,35 @@ bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
}

setSubShapeLocation(feat, sh);
// Scale by bounding box of the object
Bnd_Box box;
BRepBndLib::Add(toposhape.getShape(), box);
double l = sqrt(box.SquareExtent() / 3.0);
*scale = this->calcSizeFactor(l);

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();
// OvG: setup draw scale for constraint
*scale = this->calcSizeFactor(sqrt(lx) * 0.5);
}
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;
// OvG: Increase 10 units distance proportionately to l for larger objects.
if (l >= 30) {
*scale = this->calcSizeFactor(l); // OvG: setup draw scale for constraint
steps = static_cast<int>(round(l / (10 * (*scale))));
steps = steps < 3 ? 3 : steps;
}
else if (l >= 20) {
steps = static_cast<int>(round(l / 10));
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}
else {
steps = 1;
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}

// OvG: Place upper limit on number of steps
Expand Down Expand Up @@ -407,37 +393,31 @@ bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
// OvG: Increase 10 units distance proportionately to lv for larger objects.
int stepsv;
if (lv >= 30) {
*scale = this->calcSizeFactor(lv, lu); // OvG: setup draw scale for constraint
stepsv = static_cast<int>(round(lv / (10 * (*scale))));
stepsv = stepsv < 3 ? 3 : stepsv;
}
else if (lv >= 20.0) {
stepsv = static_cast<int>(round(lv / 10));
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}
else {
// Minimum of three arrows to ensure (as much as possible) that at
// least one is displayed
stepsv = 2;
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}

// OvG: Place upper limit on number of steps
stepsv = stepsv > CONSTRAINTSTEPLIMIT ? CONSTRAINTSTEPLIMIT : stepsv;
int stepsu;
// OvG: Increase 10 units distance proportionately to lu for larger objects.
if (lu >= 30) {
*scale = this->calcSizeFactor(lv, lu); // OvG: setup draw scale for constraint
stepsu = static_cast<int>(round(lu / (10 * (*scale))));
stepsu = stepsu < 3 ? 3 : stepsu;
}
else if (lu >= 20.0) {
stepsu = static_cast<int>(round(lu / 10));
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}
else {
stepsu = 2;
*scale = this->calcSizeFactor(); // OvG: setup draw scale for constraint
}

// OvG: Place upper limit on number of steps
Expand Down
39 changes: 4 additions & 35 deletions src/Mod/Fem/App/FemConstraint.h
Expand Up @@ -123,43 +123,12 @@ class FemExport Constraint: public App::DocumentObject, public App::Suppressible
App::DocumentObjectExecReturn* execute() override;

/**
* @brief Calculates scale factor based on length of edge.
* @brief Calculates scale factor based on characteristic length of shape.
*
* @details
* Used to calculate the scale factor returned by @ref getPoints when the
* scale factor is calculated for a face.
*
* @note
* This method does a really crazy calculation that I didn't dare to try
* to understand.
*/
unsigned int calcSizeFactor(double lparam) const;

/**
* @brief Calculates scale factor based on size of face.
*
* @details
* Used to calculate the scale factor returned by @ref getPoints when the
* scale factor is calculated for a edge.
*
* @note
* This method does a really crazy calculation that I didn't dare to try
* to understand.
*/
unsigned int calcSizeFactor(double lvparam, double luparam) const;

/**
* @brief Returns default scale factor of 1.
*
* @details
* This is just used to make code more understandable. Other versions
* (overloads) of this function do useful calculations based on faces or
* edges. Used by @ref getPoints if no useful shape information is
* available.
*
* @return always the integer 1
*/
unsigned int calcSizeFactor() const;
double calcSizeFactor(double characLen) const;

const char* getViewProviderName() const override
{
Expand Down Expand Up @@ -227,7 +196,7 @@ class FemExport Constraint: public App::DocumentObject, public App::Suppressible
*/
bool getPoints(std::vector<Base::Vector3d>& points,
std::vector<Base::Vector3d>& normals,
int* scale) const;
double* scale) const;

/**
* @brief Extract properties of cylindrical face.
Expand Down Expand Up @@ -263,7 +232,7 @@ class FemExport Constraint: public App::DocumentObject, public App::Suppressible
/**
* @brief Symbol size factor determined from the size of the shape.
*/
int sizeFactor;
double sizeFactor;

void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop);
boost::signals2::connection connDocChangedObject;
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Fem/App/FemConstraintTransform.cpp
Expand Up @@ -110,7 +110,7 @@ void ConstraintTransform::onChanged(const App::Property* prop)
if (prop == &References) {
std::vector<Base::Vector3d> points;
std::vector<Base::Vector3d> normals;
int scale = 1; // OvG: Enforce use of scale
double scale = 1; // OvG: Enforce use of scale
if (getPoints(points, normals, &scale)) {
std::string transform_type = TransformType.getValueAsString();
if (transform_type == "Cylindrical") {
Expand Down

0 comments on commit 863cb80

Please sign in to comment.