[TD]fix handling of perforated section faces

This commit is contained in:
wandererfan
2023-02-01 16:56:02 -05:00
committed by WandererFan
parent d9afb06676
commit bd25c86973
2 changed files with 112 additions and 30 deletions

View File

@@ -56,7 +56,8 @@
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <Bnd_Box.hxx>
#include <QtConcurrentRun>
#include <ShapeAnalysis.hxx>
#include <ShapeFix_Shape.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
@@ -73,6 +74,8 @@
#include <sstream>
#endif
#include <QtConcurrent>
#include <App/Application.h>
#include <App/Document.h>
#include <Base/BoundBox.h>
@@ -400,18 +403,26 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape& baseShape)
}
// perform cut
BRep_Builder builder;
TopoDS_Compound cutPieces;
builder.MakeCompound(cutPieces);
TopExp_Explorer expl(myShape, TopAbs_SOLID);
for (; expl.More(); expl.Next()) {
const TopoDS_Solid& s = TopoDS::Solid(expl.Current());
BRepAlgoAPI_Cut mkCut(s, m_cuttingTool);
if (!mkCut.IsDone()) {
Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument());
continue;
}
builder.Add(cutPieces, mkCut.Shape());
// BRep_Builder builder;
// TopoDS_Compound cutPieces;
// builder.MakeCompound(cutPieces);
// TopExp_Explorer expl(myShape, TopAbs_SOLID);
// for (; expl.More(); expl.Next()) {
// const TopoDS_Solid& s = TopoDS::Solid(expl.Current());
// BRepAlgoAPI_Cut mkCut(s, m_cuttingTool);
// if (!mkCut.IsDone()) {
// Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument());
// continue;
// }
// builder.Add(cutPieces, mkCut.Shape());
// }
TopoDS_Shape cutPieces = TopoDS_Shape();
BRepAlgoAPI_Cut mkCut(myShape, m_cuttingTool);
if (!mkCut.IsDone()) {
Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument());
} else {
cutPieces = mkCut.Shape();
}
// cutPieces contains result of cutting each subshape in baseShape with tool
@@ -543,6 +554,9 @@ void DrawViewSection::postHlrTasks(void)
requestPaint();
return;
}
if (debugSection()) {
BRepTools::Write(faceIntersections, "DVSFaceIntersections.brep");//debug
}
TopoDS_Shape centeredFaces = TechDraw::moveShape(faceIntersections, m_saveCentroid * -1.0);
@@ -601,10 +615,10 @@ gp_Pln DrawViewSection::getSectionPlane() const
//! case is a compound of individual cuts) with the "effective" (flattened) section plane.
TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shape& shape)
{
// Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument());
// Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument());
if (shape.IsNull()) {
// this shouldn't happen
// Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
return TopoDS_Compound();
}
@@ -637,7 +651,9 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap
//move section faces to line up with cut shape
TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersections)
{
// Base::Console().Message("DVS::alignSectionFaces()\n");
// Base::Console().Message("DVS::alignSectionFaces() - %s - faceIntersection.isnull: %d\n",
// getNameInDocument(),
// faceIntersections.IsNull());
TopoDS_Compound sectionFaces;
TopoDS_Shape centeredShape =
TechDraw::moveShape(faceIntersections, getOriginalCentroid() * -1.0);
@@ -657,7 +673,11 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
// needs to be aligned to paper plane (origin, stdZ);
//project the faces in the shapeToAlign, build new faces from the resulting wires and
//combine everything into a compound of faces
// Base::Console().Message("DVS::mapToPage() - shapeToAlign.null: %d\n", shapeToAlign.IsNull());
// Base::Console().Message("DVS::mapToPage() - shapeToAlign.null: %d\n", shapeToAlign.IsNull());
if (debugSection()) {
BRepTools::Write(shapeToAlign, "DVSShapeToAlign.brep"); //debug
}
BRep_Builder builder;
TopoDS_Compound result;
builder.MakeCompound(result);
@@ -682,24 +702,89 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
faceWires.push_back(cleanWire);
}
//first wire should be the outer boundary of the face
BRepBuilderAPI_MakeFace mkFace(faceWires.front());
int wireCount = faceWires.size();
for (int iWire = 1; iWire < wireCount; iWire++) {
//make holes in the face with the rest of the wires
mkFace.Add(faceWires.at(iWire));
//validate section face wires
std::vector<TopoDS_Wire> goodWires;
constexpr double minWireArea = 0.000001; //arbitrary very small face size
for (auto &wire : faceWires) {
if (wire.IsNull()) {
continue;
}
if (!BRep_Tool::IsClosed(wire)) {
continue; //can not make a face from open wire
}
double area = ShapeAnalysis::ContourArea(wire);
if (area <= minWireArea) {
continue; //can not make a face from wire with no area
}
goodWires.push_back(wire);
}
builder.Add(result, mkFace.Face());
if (goodWires.empty()) {
Base::Console().Warning("DVS::mapToPage - %s - section face has no valid wires.\n",
getNameInDocument());
continue;
}
TopoDS_Shape holeyShape = makeFaceFromWires(goodWires);
if (holeyShape.IsNull()) {
continue;
}
builder.Add(result, TopoDS::Face(holeyShape));
if (debugSection()) {
std::stringstream ss;
ss << "DVSFaceFromWires" << iFace << ".brep";
BRepTools::Write(mkFace.Face(), ss.str().c_str());//debug
BRepTools::Write(holeyShape, ss.str().c_str()); //debug
}
}
return result;
}
//makes a [perforated] face from an outer wire and wires describing the holes. Open wires
//and wires with zero area are assumed to already have been removed.
TopoDS_Shape DrawViewSection::makeFaceFromWires(std::vector<TopoDS_Wire> &inWires)
{
//make sure the largest wire is the first
EdgeWalker eWalker;
std::vector<TopoDS_Wire> goodWires = eWalker.sortWiresBySize(inWires);
// make a face from the good wires
//first good wire should be the outer boundary of the face
TopoDS_Face faceToFix;
TopoDS_Shape orientedShape = goodWires.at(0).Oriented(TopAbs_FORWARD);
TopoDS_Wire orientedWire = TopoDS::Wire(orientedShape);
orientedWire.Orientation(TopAbs_FORWARD);
TopoDS_Face blankFace = BRepBuilderAPI_MakeFace(orientedWire);
int wireCount = goodWires.size();
if (wireCount < 2) {
faceToFix = blankFace;
} else {
//add the holes
BRepBuilderAPI_MakeFace mkFace(blankFace);
for (int iWire = 1; iWire < wireCount; iWire++) {
//make holes in the face with the rest of the wires
orientedShape = goodWires.at(iWire).Oriented(TopAbs_REVERSED);
orientedWire = TopoDS::Wire(orientedShape);
mkFace.Add(orientedWire);
}
if (!mkFace.IsDone()) {
Base::Console().Warning("DVS::makeFaceFromWires - %s - failed to make section face.\n",
getNameInDocument());
return TopoDS_Shape();
}
faceToFix = mkFace.Face();
}
//setting the wire orientation above should generate a valid face, but sometimes
//does not, so we fix the shape to resolve any issues
Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
sfs->Init(faceToFix);
sfs->Perform();
return sfs->Shape();
}
//turn OCC section faces into TD geometry
std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compound topoDSFaces)
{