[TD]fix vertical alignment of section pieces

This commit is contained in:
wandererfan
2022-11-11 14:46:58 -05:00
committed by WandererFan
parent 3eaad09ed1
commit 0bf5d67906
2 changed files with 62 additions and 44 deletions

View File

@@ -337,14 +337,16 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
{
// Base::Console().Message("DCS::makeAlignedPieces()\n");
std::vector<TopoDS_Shape> pieces;
std::vector<double> pieceXSize;//size in sectionCS.XDirection (width)
std::vector<double> pieceYSize;//size in sectionCS.Direction (depth)
std::vector<double> pieceZSize;//size in sectionCS.YDirection (height)
std::vector<double> pieceDirections;
//make a "real" CS from the section projection CS
std::vector<double> pieceXSizeAll; //size in sectionCS.XDirection (width)
std::vector<double> pieceYSizeAll; //size in sectionCS.Direction (depth)
std::vector<double> pieceZSizeAll; //size in sectionCS.YDirection (height)
//make a CS from the section CS ZX plane to allow piece positioning (left-right)
//with the section view vertical centerline and (in-out, forward-backward) with
//the effective section plane for cut surface identification.
gp_Ax3 alignedCS(gp_Pnt(0.0, 0.0, 0.0),
getSectionCS().YDirection(), //up and down
getSectionCS().XDirection());//left to right
getSectionCS().YDirection(), //section up and down >> alignedCS.z
getSectionCS().XDirection());//section left to right >> alignedCS.x
gp_Ax3 stdCS; //OXYZ
gp_Vec gProjectionUnit = gp_Vec(getSectionCS().Direction());
@@ -357,22 +359,22 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
throw Base::RuntimeError("Profile is parallel to Section Normal");
}
bool isVertical = true;
bool isProfileVertical = true;
if (fabs(gProfileVec.Dot(gp::OY().Direction().XYZ())) != 1.0) {
//profile is not parallel with stdY (paper space Up).
//this test is not good enough for "vertical-ish" diagonal profiles
isVertical = false;
isProfileVertical = false;
}
double leftToRight = 1.0;//profile vector points to right, so we move to right
double horizReverser = 1.0;//profile vector points to right, so we move to right
if (gProfileVec.Dot(gp_Vec(gp::OX().Direction().XYZ())) < 0.0) {
//profileVec does not point towards stdX (right in paper space)
leftToRight = -1.0;
horizReverser = -1.0;
}
double topToBottom = 1.0;//profile vector points to top, so we move to top
double verticalReverser = 1.0;//profile vector points to top, so we move to top
if (gProfileVec.Dot(gp_Vec(gp::OY().Direction().XYZ())) < 0.0) {
//profileVec does not point towards stdY (up in paper space)
topToBottom = -1.0;
verticalReverser = -1.0;
}
gp_Vec rotateAxis = getSectionCS().Direction().Crossed(gProfileVec);
@@ -401,9 +403,6 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
continue;
}
double faceAngle =
gp_Vec(getSectionCS().Direction().Reversed()).AngleWithRef(segmentNormal, rotateAxis);
//move intersection shape to the origin
gp_Trsf xPieceCenter;
xPieceCenter.SetTranslation(gp_Vec(findCentroid(intersect).XYZ()) * -1.0);
@@ -411,6 +410,8 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
TopoDS_Shape pieceCentered = mkTransXLate.Shape();
//rotate the intersection so interesting face is aligned with paper plane
double faceAngle =
gp_Vec(getSectionCS().Direction().Reversed()).AngleWithRef(segmentNormal, rotateAxis);
gp_Ax1 faceAxis(gp_Pnt(0.0, 0.0, 0.0), rotateAxis);
gp_Ax3 pieceCS;//XYZ tipped so face is aligned with sectionCS
pieceCS.Rotate(faceAxis, faceAngle);
@@ -434,22 +435,24 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
BRepBndLib::AddOptimal(pieceAligned, shapeBox);
double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
shapeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
double pieceWidth(xMax - xMin);
double pieceDepth(yMax - yMin);
double pieceHeight(zMax - zMin);
pieceXSize.push_back(pieceWidth);
pieceYSize.push_back(pieceDepth);
pieceZSize.push_back(pieceHeight);
double pieceXSize(xMax - xMin);
double pieceYSize(yMax - yMin);
double pieceZSize(zMax - zMin);
pieceXSizeAll.push_back(pieceXSize);
pieceYSizeAll.push_back(pieceYSize);
pieceZSizeAll.push_back(pieceZSize);
//now we need to move the piece so that the interesting face is coincident
//with the paper plane
gp_Vec depthVector(gp::OY().Direction().XYZ() * pieceDepth / 2.0);//move "back"
//only aligned to paper plane
gp_Vec netDisplacement = -1.0 * gp_Vec(findCentroid(pieceAligned).XYZ()) + depthVector;
//if we are going to space along X, we need to bring the pieces into alignment
//with the XY plane.
gp_Vec xyDisplacement = isVertical ? gp_Vec(0.0, 0.0, 0.0) : gp_Vec(gp::OZ().Direction());
xyDisplacement = xyDisplacement * topToBottom * pieceHeight / 2.0;
//yVector is movement of cut face to paperPlane (XZ)
gp_Vec yVector(gp::OY().Direction().XYZ() * pieceYSize / 2.0);//move "back"
gp_Vec netDisplacement = -1.0 * gp_Vec(findCentroid(pieceAligned).XYZ()) + yVector;
//if we are going to space along X, we need to bring the pieces back into alignment
//with the XY plane. If we are stacking the pieces along Z, we don't want a vertical adjustment.
gp_Vec xyDisplacement = isProfileVertical ? gp_Vec(0.0, 0.0, 0.0) : gp_Vec(gp::OZ().Direction());
double dot = gp_Vec(gp::OZ().Direction()).Dot(alignedCS.Direction());
xyDisplacement = xyDisplacement * dot * (pieceZSize / 2.0);
netDisplacement = netDisplacement + xyDisplacement;
gp_Trsf xPieceDisplace;
@@ -472,17 +475,17 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
}
//space the pieces "horizontally" (stdX) or "vertically" (stdZ)
double movementReverser = isVertical ? topToBottom : leftToRight;
double movementReverser = isProfileVertical ? verticalReverser : horizReverser;
//TODO: non-cardinal profiles!
gp_Vec movementAxis = isVertical ? gp_Vec(gp::OZ().Direction()) : gp_Vec(gp::OX().Direction());
gp_Vec movementAxis = isProfileVertical ? gp_Vec(gp::OZ().Direction()) : gp_Vec(gp::OX().Direction());
gp_Vec gMovementVector = movementAxis * movementReverser;
int stopAt = pieces.size();
double distanceToMove = 0.0;
for (int iPiece = 0; iPiece < stopAt; iPiece++) {
double pieceSize = pieceXSize.at(iPiece);
if (isVertical) {
pieceSize = pieceZSize.at(iPiece);
double pieceSize = pieceXSizeAll.at(iPiece);
if (isProfileVertical) {
pieceSize = pieceZSizeAll.at(iPiece);
}
double myDistanceToMove = distanceToMove + pieceSize / 2.0;
gp_Trsf xPieceDistribute;
@@ -496,14 +499,17 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for (auto &piece : pieces) { builder.Add(comp, piece); }
for (auto &piece : pieces) {
builder.Add(comp, piece);
}
//center the compound along SectionCS XDirection
Base::Vector3d centerVector = DU::toVector3d(gMovementVector) * distanceToMove / -2.0;
TopoDS_Shape centeredCompound = moveShape(comp, centerVector);
if (debugSection()) {
BRepTools::Write(centeredCompound, "DCSfinCenteredCompound.brep");//debug
BRepTools::Write(centeredCompound, "DCSmap40CenteredCompound.brep");//debug
}
//realign with SectionCS
gp_Trsf xPieceAlign;
xPieceAlign.SetTransformation(alignedCS, stdCS);
@@ -511,7 +517,7 @@ TopoDS_Shape DrawComplexSection::makeAlignedPieces(const TopoDS_Shape &rawShape,
TopoDS_Shape alignedCompound = mkTransAlign.Shape();
if (debugSection()) {
BRepTools::Write(alignedCompound, "DCSAlignedResult.brep");//debug
BRepTools::Write(alignedCompound, "DCSmap50AlignedCompound.brep");//debug
}
return alignedCompound;
@@ -633,6 +639,7 @@ TopoDS_Shape DrawComplexSection::getShapeToIntersect()
TopoDS_Wire DrawComplexSection::makeProfileWire(App::DocumentObject *toolObj)
{
// Base::Console().Message("DCS::makeProfileWire()\n");
TopoDS_Shape toolShape = Part::Feature::getShape(toolObj);
if (toolShape.IsNull()) {
return TopoDS_Wire();
@@ -651,6 +658,7 @@ TopoDS_Wire DrawComplexSection::makeProfileWire(App::DocumentObject *toolObj)
gp_Vec DrawComplexSection::makeProfileVector(TopoDS_Wire profileWire)
{
// Base::Console().Message("DCS::makeProfileVector()\n");
TopoDS_Vertex tvFirst, tvLast;
TopExp::Vertices(profileWire, tvFirst, tvLast);
gp_Pnt gpFirst = BRep_Tool::Pnt(tvFirst);
@@ -870,6 +878,7 @@ gp_Vec DrawComplexSection::projectVector(const gp_Vec& vec) const
//static
gp_Vec DrawComplexSection::projectVector(const gp_Vec& vec, gp_Ax2 sectionCS)
{
// Base::Console().Message("DCS::projectVector(%s, CS)\n", DU::formatVector(vec).c_str());
HLRAlgo_Projector projector( sectionCS );
gp_Pnt2d prjPnt;
projector.Project(gp_Pnt(vec.XYZ()), prjPnt);
@@ -981,6 +990,11 @@ bool DrawComplexSection::canBuild(gp_Ax2 sectionCS, App::DocumentObject* profile
if (!isProfileObject(profileObject)) {
return false;
}
TopoDS_Shape shape = Part::Feature::getShape(profileObject);
if (BRep_Tool::IsClosed(shape)) {
//closed profiles don't have a profile vector but should always make a section?
return true;
}
gp_Vec gProfileVec = makeProfileVector(makeProfileWire(profileObject));
gProfileVec = projectVector(gProfileVec, sectionCS).Normalized();
double dot = fabs(gProfileVec.Dot(sectionCS.Direction()));

View File

@@ -1012,16 +1012,20 @@ bool DrawViewPart::hasGeometry(void) const
//in the derived view.
gp_Ax2 DrawViewPart::localVectorToCS(const Base::Vector3d localUnit) const
{
// Base::Console().Message("DVP::localVectorToCS(%s)\n", DU::formatVector((localUnit)).c_str());
double angle = atan2(localUnit.y, localUnit.x); //radians
gp_Ax1 rotateAxisDir(gp_Pnt(0.0, 0.0, 0.0), getProjectionCS().Direction());
gp_Vec gNewDirection = getProjectionCS().XDirection().Rotated(rotateAxisDir, angle);
gp_Vec crossDirs = getProjectionCS().Direction().Crossed(gNewDirection);
gp_Vec gNewX = getProjectionCS().XDirection();
gp_Vec triple = crossDirs.Crossed(getProjectionCS().XDirection());
if (!DU::fpCompare(triple.Magnitude(), 0.0, EWTOLERANCE)) {
gNewX = triple;
gp_Vec gOldX = getProjectionCS().XDirection();
gp_Vec gNewDirection = gOldX.Rotated(rotateAxisDir, angle);
gp_Vec gNewY = getProjectionCS().Direction();
gp_Vec gNewX = (gNewDirection.Crossed(gNewY).Reversed());
if (gNewX.IsParallel(gOldX, EWTOLERANCE)) {
//if the X directions are parallel, the view is rotating around X, so
//we should use the original X to prevent unwanted mirroring.
//There might be a better choice of tolerance than EWTOLERANCE
gNewX = gOldX;
}
return { gp_Pnt(0.0, 0.0, 0.0), gp_Dir(gNewDirection), gp_Dir(gNewX) };
}