Skip to content

Commit

Permalink
Merge pull request #1005 from DLR-SC/rectangle
Browse files Browse the repository at this point in the history
Implemented Fuselage Profile Type: Rectangle (Issue #909)
  • Loading branch information
joergbrech authored Sep 2, 2024
2 parents 28b2dc3 + 571a2ef commit f6f1e4c
Show file tree
Hide file tree
Showing 11 changed files with 1,946 additions and 84 deletions.
154 changes: 154 additions & 0 deletions src/common/tiglcommonfunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#include "CTiglRelativelyPositionedComponent.h"
#include "CTiglProjectPointOnCurveAtAngle.h"
#include "CTiglBSplineAlgorithms.h"
#include "CTiglPointsToBSplineInterpolation.h"
#include "CFunctionToBspline.h"
#include "tiglmathfunctions.h"

#include "Standard_Version.hxx"

Expand Down Expand Up @@ -119,6 +122,7 @@
#include <ShapeAnalysis_FreeBounds.hxx>



#include <list>
#include <algorithm>
#include <cassert>
Expand All @@ -127,6 +131,7 @@

#include "Debugging.h"


namespace
{
struct IsSame
Expand Down Expand Up @@ -1173,6 +1178,155 @@ TopoDS_Wire BuildWireFromEdges(const TopoDS_Shape& edges)
return result;
}

namespace
{
class Circle : public tigl::MathFunc3d
{
public:
Circle(double radius): tigl::MathFunc3d(), m_radius(radius) {}

double valueX(double t) override
{
return 0.;
}

double valueY(double t) override
{
return m_radius*std::cos(t);
}

double valueZ(double t) override
{
return m_radius*std::sin(t);
}

private:
double m_radius;
};
} //anonymos namespace

opencascade::handle<Geom_BSplineCurve> ApproximateArcOfCircleToRationalBSpline(double radius, double uMin, double uMax,
double tol, double y_position, double z_position)
{
if(radius==0){
throw tigl::CTiglError("Invalid geometry. Radius must be != 0.");
}
if(Abs(uMax-uMin)< tol){
throw tigl::CTiglError("Invalid geometry: Curve length must not be Zero.");
}
if(Abs(uMax-uMin)>(2.*M_PI))
{
throw tigl::CTiglError("Invalid geometry: Curve cannot be traversed more than once.");
}

Circle circle(radius);
int degree = 3;

auto curve = tigl::CFunctionToBspline(circle, uMin, uMax, degree, tol).Curve();
curve->Translate(gp_Vec(0.,y_position,z_position));

return curve;
}

TopoDS_Wire BuildWireRectangle(const double heightToWidthRatio, const double cornerRadius, const double tol)
{
if(cornerRadius<0.||cornerRadius>0.5){
throw tigl::CTiglError("Invalid input for corner radius. Must be in range: 0 <= cornerRadius <= 0.5");
}

std::vector<Handle(Geom_BSplineCurve)> curves;

// build half upper line from gp_points
std::vector<gp_Pnt> linePntsUpperRightHalf;
linePntsUpperRightHalf.push_back(gp_Pnt(0.,0.,0.5*heightToWidthRatio));
linePntsUpperRightHalf.push_back(gp_Pnt(0.,0.5-cornerRadius,0.5*heightToWidthRatio));
opencascade::handle<Geom_BSplineCurve> lowerLineRightHalf =
tigl::CTiglPointsToBSplineInterpolation(linePntsUpperRightHalf).Curve();
curves.push_back(lowerLineRightHalf);

if (!(cornerRadius == 0.0)){
//build upper right arc
double y0 = 0.5 - cornerRadius;
double z0 = 0.5 * heightToWidthRatio - cornerRadius;
auto arcCurve = ApproximateArcOfCircleToRationalBSpline(cornerRadius, 0., M_PI/2., tol, y0, z0);
arcCurve->Reverse();
curves.push_back(arcCurve);
}

// build right line from gp_Pnts
std::vector<gp_Pnt> linePnts_right;
linePnts_right.push_back(gp_Pnt(0., 0.5, 0.5 * heightToWidthRatio - cornerRadius));
linePnts_right.push_back(gp_Pnt(0., 0.5, -0.5 * heightToWidthRatio + cornerRadius));
opencascade::handle<Geom_BSplineCurve> rightLine = tigl::CTiglPointsToBSplineInterpolation(linePnts_right).Curve();
curves.push_back(rightLine);

if (!(cornerRadius == 0.0)){
//build lower right arc
double y0 = 0.5 - cornerRadius;
double z0 = - 0.5 * heightToWidthRatio + cornerRadius;
auto arcCurve = ApproximateArcOfCircleToRationalBSpline(cornerRadius, M_PI*(3./2.), M_PI*2., tol, y0, z0);
arcCurve->Reverse();
curves.push_back(arcCurve);
}

// build lower line from gp_points
std::vector<gp_Pnt> linePnts_lower;
linePnts_lower.push_back(gp_Pnt(0.,(0.5-cornerRadius),-0.5*heightToWidthRatio));
linePnts_lower.push_back(gp_Pnt(0.,(-0.5+cornerRadius),-0.5*heightToWidthRatio));
opencascade::handle<Geom_BSplineCurve> lowerLine = tigl::CTiglPointsToBSplineInterpolation(linePnts_lower).Curve();

curves.push_back(lowerLine);

if (!(cornerRadius == 0.)){
// build lower left arc
double y0 = - 0.5 + cornerRadius;
double z0 = -0.5 * heightToWidthRatio + cornerRadius;
auto arcCurve = ApproximateArcOfCircleToRationalBSpline(cornerRadius, M_PI, M_PI*(3./2.), tol, y0, z0);
arcCurve->Reverse();
curves.push_back(arcCurve);
}

//build left line from gp_points
std::vector<gp_Pnt> linePnts_left;
linePnts_left.push_back(gp_Pnt(0.,-0.5,-0.5 * heightToWidthRatio + cornerRadius));
linePnts_left.push_back(gp_Pnt(0.,-0.5,0.5 * heightToWidthRatio - cornerRadius));
opencascade::handle<Geom_BSplineCurve> leftLine = tigl::CTiglPointsToBSplineInterpolation(linePnts_left).Curve();
curves.push_back(leftLine);

if (!(cornerRadius == 0.)) {
// build upper left arc
double y0 = - 0.5 + cornerRadius;
double z0 = 0.5 * heightToWidthRatio - cornerRadius;
auto arcCurve = ApproximateArcOfCircleToRationalBSpline(cornerRadius, M_PI/2., M_PI, tol, y0, z0);
arcCurve->Reverse();
curves.push_back(arcCurve);
}

// build half upper line from gp_points
std::vector<gp_Pnt> linePntsUpperLeftHalf;
linePntsUpperLeftHalf.push_back(gp_Pnt(0.,-(0.5-cornerRadius),0.5*heightToWidthRatio));
linePntsUpperLeftHalf.push_back(gp_Pnt(0.,0.,0.5*heightToWidthRatio));
opencascade::handle<Geom_BSplineCurve> upperLineLeftHalf =
tigl::CTiglPointsToBSplineInterpolation(linePntsUpperLeftHalf).Curve();
curves.push_back(upperLineLeftHalf);

opencascade::handle<Geom_BSplineCurve> curve = tigl::CTiglBSplineAlgorithms::concatCurves(curves);

// workaround for lofting algorithm not working with curves of degree '1' (i.e. concatenated lines)
// if guide curves are involved, the lofter doesn't generate a valid geometry without thowing an error
// This only occurs if the cornerRadius is zero and the profile is a rectangle, which in theory could
// just have degree 1.
if ((curve->Degree())<2){
curve->IncreaseDegree(2);
}

TopoDS_Wire wire;
if (!curve.IsNull()) {
wire = BuildWireFromEdges(BRepBuilderAPI_MakeEdge(curve).Edge());
}
return wire;
}

void BuildWiresFromConnectedEdges(const TopoDS_Shape& shape, TopTools_ListOfShape& wireList)
{
// get list of edges from passed shape
Expand Down
32 changes: 31 additions & 1 deletion src/common/tiglcommonfunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#include <algorithm>
#include "UniquePtr.h"



typedef std::map<std::string, PNamedShape> ShapeMap;

// helper function for std::find
Expand Down Expand Up @@ -270,6 +272,34 @@ TIGL_EXPORT TopoDS_Wire BuildWire(const gp_Pnt& p1, const gp_Pnt& p2);
// Method for building a wire out of the edges from the passed geometry
TIGL_EXPORT TopoDS_Wire BuildWireFromEdges(const TopoDS_Shape& edges);

/**
* @brief ApproximateArcOfCircleToRationalBSpline The result of this function is a non-rational
* B-Spline curve that approximates an arc of circle in the y-z plane.
* Its center is given by the y- and z-position.
* The angle is given in rad.
* The direction of rotation is counter-clockwise, starting with alpha=0 on the positive y-axis, with z=0.
* @param cornerRadius Radius of the circle
* @param uMin Starting parameter in rad. Range: [0,2*Pi]
* @param uMax
* @param tol Tolerance
* @param y_position
* @param z_position
* @return opencascade::handle<Geom_BSplineCurve>
*/
TIGL_EXPORT opencascade::handle<Geom_BSplineCurve> ApproximateArcOfCircleToRationalBSpline(double cornerRadius, double uMin = 0, double uMax = M_PI/4 ,
double tol = 1e-6, double y_position = 0., double z_position = 0.);

/**
* @brief BuildWireRectangle Builds a rectangular wire in (y,z) - plane with width 1, center of coordinate
* system is the center of the rectangle
* @param heightToWidthRatio
* @param cornerRadius
* @param tol
* @return TopoDS_Wire
*/
TIGL_EXPORT TopoDS_Wire BuildWireRectangle(const double heightToWidthRatio, const double cornerRadius=0.0,
const double tol=Precision::Approximation());

// Returns a list of wires built from all connected edges in the passed shape
TIGL_EXPORT void BuildWiresFromConnectedEdges(const TopoDS_Shape& shape, TopTools_ListOfShape& wireList);

Expand Down Expand Up @@ -359,7 +389,7 @@ TIGL_EXPORT double NormalizeAngleDeg(double angleDeg);
// Creates a linear spaces array but with some additional breaking points
// If the breaking points are very close to a point, the point will be replaced
// Else, the breaking point will be inserted
TIGL_EXPORT std::vector<double> LinspaceWithBreaks(double umin, double umax, size_t n_values, const std::vector<double>& breaks);
TIGL_EXPORT std::vector<double> LinspaceWithBreaks(double umin, double umax, size_t n_values, const std::vector<double>& breaks = {});

// Transforms a shape accourding to the given coordinate transformation
TIGL_EXPORT TopoDS_Shape TransformedShape(const tigl::CTiglTransformation& transformationToGlobal, TiglCoordinateSystem cs, const TopoDS_Shape& shape);
Expand Down
Loading

0 comments on commit f6f1e4c

Please sign in to comment.