
Wed, 04/26/2023 - 18:02
Forums:
I am trying to understand how the shape healing functions work but I am having a hard time following the documentation.
I am working on a bigger STEP file but I have extracted a single face to analyse it.
I got a simple STEP file with a single face and the wire analysis says that it self intersects.
I declare a shape healing tool ShapeFix_Wire
and call Perform
, however the resulting wire is still self-intersecting.
I have attached the file tmp.stp
and a quick test.cpp
file. Am I doing something wrong? I tried with different precision values and it changes nothing. Any help or tip is appreciated.
/* Copy paste this into a .sh file to build to compile and run
#!/bin/sh -x
OCCT_LIB_DIR="/usr/lib/x86_64-linux-gnu"
OCCT_LIBS="$(ls ${OCCT_LIB_DIR}/libT*.so*)"
OCCT_INCLUDE="-I/usr/include/opencascade"
g++ -std=c++20 -O3 test.cpp ${OCCT_INCLUDE} ${OCCT_LIBS} -Wno-deprecated-enum-enum-conversion
./a.out
*/
#include <iomanip>
#include <iostream>
#include "STEPCAFControl_Reader.hxx"
#include "ShapeAnalysis_Wire.hxx"
#include "ShapeFix_Wire.hxx"
#include "TDF_LabelSequence.hxx"
#include "TDocStd_Document.hxx"
#include "TopAbs_ShapeEnum.hxx"
#include "TopExp_Explorer.hxx"
#include "TopoDS.hxx"
#include "TopoDS_Face.hxx"
#include "TopoDS_Iterator.hxx"
#include "TopoDS_Shape.hxx"
#include "XCAFDoc_DocumentTool.hxx"
#include "XCAFDoc_ShapeTool.hxx"
int main() {
// Load the sample step file into a document and get the OCCT representation
Handle(TDocStd_Document) doc = new TDocStd_Document{"BinXCAF"};
STEPCAFControl_Reader reader;
reader.ReadFile("tmp.stp");
reader.Transfer(doc);
// Grab the tool to manipulate the shapes
Handle(XCAFDoc_ShapeTool) shape_tool =
XCAFDoc_DocumentTool::ShapeTool(doc->Main());
// Grab the labels of root shapes (only one shell in this file)
TDF_LabelSequence labels;
shape_tool->GetFreeShapes(labels);
// Get the shell
TopoDS_Shape shape = shape_tool->GetShape(labels.Value(1));
TopoDS_Iterator it{shape};
// Get the only face in the shell
TopoDS_Face face = TopoDS::Face(it.Value());
// Get the only wire in this face
TopExp_Explorer exp{face, TopAbs_WIRE};
// Cast to an actual wire from a generic shape
TopoDS_Wire wire = TopoDS::Wire(exp.Value());
ShapeAnalysis_Wire wire_analyser{wire, face, 1e-7};
// This returns true as there are self intersections
if (wire_analyser.CheckSelfIntersection()) {
std::cout
<< "This wire is self intersecting. Fix using OCCT Shape Healing\n";
// Build a fixer object with a certain precision
ShapeFix_Wire wire_fixer{wire, face, 1e-7};
wire_fixer.ClosedWireMode() = true;
// Why does this return false? How to investigate further the cause?
std::cout << "Is it fixed? " << std::boolalpha
<< wire_fixer.FixSelfIntersection() << '\n';
// Build a new analyser for the new "fixed" wire and face
ShapeAnalysis_Wire fixed_wire_analyser{wire_fixer.Wire(), wire_fixer.Face(),
1e-7};
// Even the fixed wire is still self intersecting
if (fixed_wire_analyser.CheckSelfIntersection())
std::cout << "Still not fixed\n";
}
}
Attachments:
Thu, 04/27/2023 - 16:29
Also I am not understanding if the variable `wire` (which feels like a reference variable to the underlying geometry) is automatically updated or if `ShapeFix_Wire::Wire()` method produces a deep copy that has to be then used to replace manually the initial wire?
Thu, 04/27/2023 - 16:56
Hello,
The wire_fixer.FixSelfIntersection() function is a crucial part of the healing process. To ensure it functions properly, it is necessary to prepare all the data beforehand. It is recommended to call the "Perform" method for best results.
Additionally, the shape healing process is applied after the StepRead stage automatically.
Deep copy to avoid a lot of problems. Because the topology is a very delicate part.
Best regards, Dmitrii.
Fri, 04/28/2023 - 09:46
Thanks a lot for the answer.
What I meant with my comment is: do
wire
andwire_fixer.Wire()
(after calling perform) point to the same underlying geometry or does aPerform
call create a deep copy of wire that is then return with a call toShapeFix_Wire::Wire()
? You are saying it performs a deep copy right and that I have to useShapeBuilder_ReShape
to swap it into my initial shape?I will certainly investigate more this automatic shape healing process that comes with the reading phase.
Fri, 04/28/2023 - 10:15
As far as I know, a copy is actually made there. But there are times when the original is modified.
We use XSAlgo::AlgoContainer::ProcessShape and then XSAlgo::AlgoContainer::MergeTransferInfo to merge transfer history.
Fixer has the own history(look like a ReShape) and you are free to use it directly to update each shape in your model.
There an example from DRAW command, whist setting up fixer to fix needed parts and save new shape into new name.
Best regards, Dmitrii.