[TD]Complex Section - initial implementation

This commit is contained in:
wandererfan
2022-10-10 10:10:42 -04:00
committed by WandererFan
parent 9d32c892f0
commit 5ddc6ce789
39 changed files with 4656 additions and 773 deletions

View File

@@ -23,36 +23,38 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <cstdlib>
# include <cstring>
# include <sstream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <sstream>
# include <boost/regex.hpp>
#include <boost/regex.hpp>
# include <QChar>
# include <QPointF>
# include <QString>
#include <QChar>
#include <QPointF>
#include <QString>
# include <BRep_Builder.hxx>
# include <BRep_Tool.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <BRepLProp_CLProps.hxx>
# include <BRepLProp_CurveTool.hxx>
# include <BRepLProp_SLProps.hxx>
# include <BRepTools.hxx>
# include <GCPnts_AbscissaPoint.hxx>
# include <gp_Ax3.hxx>
# include <gp_Dir.hxx>
# include <gp_Elips.hxx>
# include <gp_Pnt.hxx>
# include <gp_Vec.hxx>
# include <Precision.hxx>
# include <TopExp.hxx>
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepLProp_CLProps.hxx>
#include <BRepLProp_CurveTool.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepTools.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Elips.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#endif
#include <App/Application.h>
@@ -511,6 +513,11 @@ Base::Vector3d DrawUtil::vecRotate(Base::Vector3d vec,
return Base::Vector3d(xForm * (vec));
}
gp_Vec DrawUtil::closestBasis(gp_Vec inVec)
{
return gp_Vec(togp_Dir(closestBasis(toVector3d(inVec))));
}
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
{
Base::Vector3d result(0.0, -1, 0);
@@ -522,11 +529,16 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
Base::Vector3d stdZr(0.0, 0.0, -1.0);
//first check if already a basis
if (checkParallel(v, stdZ) ||
checkParallel(v, stdY) ||
checkParallel(v, stdX)) {
if (v.Dot(stdX) == 1.0 ||
v.Dot(stdY) == 1.0 ||
v.Dot(stdZ) == 1.0) {
return v;
}
if (v.Dot(stdX) == -1.0 ||
v.Dot(stdY) == -1.0 ||
v.Dot(stdZ) == -1.0) {
return -v;
}
//not a basis. find smallest angle with a basis.
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
@@ -537,23 +549,139 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
angleYr = stdYr.GetAngle(v);
angleZr = stdZr.GetAngle(v);
angleMin = angleX;
if (angleY < angleMin) {
return stdY;
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
if (angleX == angleMin) {
return Base::Vector3d(1.0, 0.0, 0.0);
}
if (angleZ < angleMin) {
return stdZ;
if (angleY == angleMin) {
return Base::Vector3d(0.0, 1.0, 0.0);
}
if (angleXr < angleMin) {
return stdXr;
if (angleZ == angleMin) {
return Base::Vector3d(0.0, 0.0, 1.0);
}
if (angleYr < angleMin) {
return stdYr;
if (angleXr == angleMin) {
return Base::Vector3d(1.0, 0.0, 0.0);
}
if (angleZr < angleMin) {
return stdZr;
if (angleYr == angleMin) {
return Base::Vector3d(0.0, 1.0, 0.0);
}
return stdX;
if (angleZr == angleMin) {
return Base::Vector3d(0.0, 0.0, 1.0);
}
//should not get to here
return Base::Vector3d(1.0, 0.0, 0.0);
}
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d vDir, gp_Ax2 coordSys)
{
gp_Dir gDir(vDir.x, vDir.y, vDir.z);
return closestBasis(gDir, coordSys);
}
Base::Vector3d DrawUtil::closestBasis(gp_Dir gDir, gp_Ax2 coordSys)
{
gp_Dir xCS = coordSys.XDirection(); //these are unit vectors?
gp_Dir yCS = coordSys.YDirection();
gp_Dir zCS = coordSys.Direction();
//first check if already a basis
if (gDir.Dot(xCS) == 1.0 ||
gDir.Dot(yCS) == 1.0 ||
gDir.Dot(zCS) == 1.0 ) {
//gDir is parallel with a basis
return Base::Vector3d( gDir.X(), gDir.Y(), gDir.Z()) ;
}
if (gDir.Dot(xCS.Reversed()) == 1.0 ||
gDir.Dot(yCS.Reversed()) == 1.0 ||
gDir.Dot(zCS.Reversed()) == 1.0 ) {
//gDir is anti-parallel with a basis
return Base::Vector3d( -gDir.X(), -gDir.Y(), -gDir.Z());
}
//not a basis. find smallest angle with a basis.
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
angleX = gDir.Angle(xCS);
angleY = gDir.Angle(yCS);
angleZ = gDir.Angle(zCS);
angleXr = gDir.Angle(xCS.Reversed());
angleYr = gDir.Angle(yCS.Reversed());
angleZr = gDir.Angle(zCS.Reversed());
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
if (angleX == angleMin) {
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
}
if (angleY == angleMin) {
return Base::Vector3d(yCS.X(), yCS.Y(), yCS.Z());
}
if (angleZ == angleMin) {
return Base::Vector3d(zCS.X(), zCS.Y(), zCS.Z()) ;
}
if (angleXr == angleMin) {
return Base::Vector3d(-xCS.X(), -xCS.Y(), -xCS.Z());
}
if (angleYr == angleMin) {
return Base::Vector3d(-yCS.X(), -yCS.Y(), -yCS.Z());
}
if (angleZr == angleMin) {
return Base::Vector3d(-zCS.X(), -zCS.Y(), -zCS.Z());
}
//should not get to here
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
}
double DrawUtil::getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape)
{
Base::Vector3d stdX(1.0, 0.0, 0.0);
Base::Vector3d stdY(0.0, 1.0, 0.0);
Base::Vector3d stdZ(0.0, 0.0, 1.0);
Base::Vector3d stdXr(-1.0, 0.0, 0.0);
Base::Vector3d stdYr(0.0, -1.0, 0.0);
Base::Vector3d stdZr(0.0, 0.0, -1.0);
Base::Vector3d vClosestBasis = closestBasis(toVector3d(direction));
Bnd_Box shapeBox;
shapeBox.SetGap(0.0);
BRepBndLib::AddOptimal(shape, shapeBox);
double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
if (shapeBox.IsVoid()) {
//this really shouldn't happen here as null shapes should have been caught
//long before this
Base::Console().Error("DU::getWidthInDirection - shapeBox is void\n");
return 0.0;
}
shapeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
if (vClosestBasis.IsEqual(stdX, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdXr, EWTOLERANCE) ) {
return xMax - xMin;
}
if (vClosestBasis.IsEqual(stdY, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdYr, EWTOLERANCE) ) {
return yMax - yMin;
}
if (vClosestBasis.IsEqual(stdZ, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdZr, EWTOLERANCE) ) {
return zMax - zMin;
}
return 0.0;
}
//based on Function provided by Joe Dowsett, 2014
@@ -873,6 +1001,102 @@ void DrawUtil::encodeXmlSpecialChars(std::string& inoutText)
inoutText.swap(buffer);
}
//Sort edges into nose to tail order. From Part/App/AppPartPy.cpp. gives back a sequence
//of nose to tail edges and a shrunken input sequence of edges (the unconnected left overs)
//struct EdgePoints {
// gp_Pnt v1, v2;
// std::list<TopoDS_Edge>::iterator it;
// TopoDS_Edge edge;
//};
std::list<TopoDS_Edge> DrawUtil::sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
{
tol3d = tol3d * tol3d;
std::list<EdgePoints> edge_points;
TopExp_Explorer xp;
for (std::list<TopoDS_Edge>::iterator it = edges.begin(); it != edges.end(); ++it) {
EdgePoints ep;
xp.Init(*it,TopAbs_VERTEX);
ep.v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
xp.Next();
ep.v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
ep.it = it;
ep.edge = *it;
edge_points.push_back(ep);
}
if (edge_points.empty())
return std::list<TopoDS_Edge>();
std::list<TopoDS_Edge> sorted;
gp_Pnt gpChainFirst, gpChainLast;
gpChainFirst = edge_points.front().v1;
gpChainLast = edge_points.front().v2;
sorted.push_back(edge_points.front().edge);
edges.erase(edge_points.front().it);
edge_points.erase(edge_points.begin());
while (!edge_points.empty()) {
// search for adjacent edge
std::list<EdgePoints>::iterator itEdgePoint;
for (itEdgePoint = edge_points.begin(); itEdgePoint != edge_points.end(); ++itEdgePoint) {
if (itEdgePoint->v1.SquareDistance(gpChainLast) <= tol3d) {
//found a connection from end of chain to start of edge
gpChainLast = itEdgePoint->v2;
sorted.push_back(itEdgePoint->edge);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v2.SquareDistance(gpChainFirst) <= tol3d) {
//found a connection from start of chain to end of edge
gpChainFirst = itEdgePoint->v1;
sorted.push_front(itEdgePoint->edge);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v2.SquareDistance(gpChainLast) <= tol3d) {
//found a connection from end of chain to end of edge
gpChainLast = itEdgePoint->v1;
Standard_Real firstParam, lastParam;
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
firstParam = curve->ReversedParameter(firstParam);
lastParam = curve->ReversedParameter(lastParam);
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
sorted.push_back(edgeReversed);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v1.SquareDistance(gpChainFirst) <= tol3d) {
//found a connection from start of chain to start of edge
gpChainFirst = itEdgePoint->v2;
Standard_Real firstParam, lastParam;
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
firstParam = curve->ReversedParameter(firstParam);
lastParam = curve->ReversedParameter(lastParam);
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
sorted.push_front(edgeReversed);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
}
if ((itEdgePoint == edge_points.end()) || (gpChainLast.SquareDistance(gpChainFirst) <= tol3d)) {
// no adjacent edge found or polyline is closed
return sorted;
}
}
return sorted;
}
// Supplementary mathematical functions
// ====================================
@@ -1367,7 +1591,7 @@ void DrawUtil::dumpCS3(const char* text,
gp_Dir baseX = CS.XDirection();
gp_Dir baseY = CS.YDirection();
gp_Pnt baseOrg = CS.Location();
Base::Console().Message("DU::dumpCSF - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
Base::Console().Message("DU::dumpCS3 - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
DrawUtil::formatVector(baseOrg).c_str(),
DrawUtil::formatVector(baseAxis).c_str(),
DrawUtil::formatVector(baseX).c_str(),