diff --git a/Cassiopee/OCC/OCC/Atomic/fillHole.cpp b/Cassiopee/OCC/OCC/Atomic/fillHole.cpp index 9da47e2ee..b596669d7 100644 --- a/Cassiopee/OCC/OCC/Atomic/fillHole.cpp +++ b/Cassiopee/OCC/OCC/Atomic/fillHole.cpp @@ -30,14 +30,16 @@ #include "BRepBuilderAPI_MakeFace.hxx" #include "StdFail_NotDone.hxx" #include "BRepFill_Filling.hxx" +#include "ShapeUpgrade_ShapeDivideContinuity.hxx" //===================================================================== -// Remove some faces and rebuild compound +// Fill hole in CAD +// when continuity > 0, you have to add support faces. //===================================================================== PyObject* K_OCC::fillHole(PyObject* self, PyObject* args) { - PyObject* hook; PyObject* listEdges; - if (!PYPARSETUPLE_(args, OO_, &hook, &listEdges)) return NULL; + PyObject* hook; PyObject* listEdges; PyObject* listFaces; E_Int continuity; + if (!PYPARSETUPLE_(args, OOO_ I_, &hook, &listEdges, &listFaces, &continuity)) return NULL; void** packet = NULL; #if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 1) @@ -85,66 +87,111 @@ PyObject* K_OCC::fillHole(PyObject* self, PyObject* args) return NULL; } - // Build face on wire TopoDS_Face F; - try { - BRepBuilderAPI_MakeFace faceMaker(myWire, Standard_False); - //faceMaker.Add(myWire); - F = faceMaker.Face(); + GeomAbs_Shape crit; + if (continuity == 0) crit = GeomAbs_C0; + else if (continuity == 1) crit = GeomAbs_C1; + else if (continuity == 2) crit = GeomAbs_C2; + + // Build face from wire (C0) + if (continuity == 0) + { + try { + BRepBuilderAPI_MakeFace faceMaker(myWire, Standard_False); + //faceMaker.Add(myWire); + F = faceMaker.Face(); - if (not faceMaker.IsDone()) + if (not faceMaker.IsDone()) + { + fail = true; + //PyErr_SetString(PyExc_TypeError, "fillHole: fail to generate face (isDone)."); + //return NULL; + } + } catch (StdFail_NotDone& e) { fail = true; } + if (fail) { - fail = true; - //PyErr_SetString(PyExc_TypeError, "fillHole: fail to generate face (isDone)."); - //return NULL; + PyErr_SetString(PyExc_TypeError, "fillHole: fail to generate face (notDone)."); + return NULL; } - - } catch (StdFail_NotDone& e) { fail = true; } - if (fail) - { - //PyErr_SetString(PyExc_TypeError, "fillHole: fail to generate face (notDone)."); - //return NULL; } - - // try with brepfill - if (fail) + + // build Face with brepfill - for now no success for C1 or C2 + if (continuity > 0) { - BRepFill_Filling filler; - for (E_Int no = 0; no < PyList_Size(listEdges); no++) + try { - PyObject* noEdgeO = PyList_GetItem(listEdges, no); - E_Int noEdge = PyInt_AsLong(noEdgeO); - if (noEdge < 0 && noEdge >= -nEdges) - { - const TopoDS_Edge& E = TopoDS::Edge(edges(-noEdge)); - E.Reversed(); - filler.Add(E, GeomAbs_C1, true); - } - else if (noEdge > 0 && noEdge <= nEdges) + BRepFill_Filling filler; + for (E_Int no = 0; no < PyList_Size(listEdges); no++) { - const TopoDS_Edge& E = TopoDS::Edge(edges(noEdge)); - filler.Add(E, GeomAbs_C1, true); + PyObject* noEdgeO = PyList_GetItem(listEdges, no); + E_Int noEdge = PyInt_AsLong(noEdgeO); + + //PyObject* noFaceO = PyList_GetItem(listFaces, no); // support face + //E_Int noFace = PyInt_AsLong(noFaceO); + //const TopoDS_Face& supportF = TopoDS::Face(surfaces(noFace)); + + if (noEdge < 0 && noEdge >= -nEdges) + { + const TopoDS_Edge& E = TopoDS::Edge(edges(-noEdge)); + E.Reversed(); + //filler.Add(E, supportF, GeomAbs_G1, true); + //filler.Add(E, GeomAbs_G1, true); + filler.Add(E, GeomAbs_C0, true); + } + else if (noEdge > 0 && noEdge <= nEdges) + { + const TopoDS_Edge& E = TopoDS::Edge(edges(noEdge)); + //filler.Add(E, supportF, GeomAbs_G1, true); + //filler.Add(E, GeomAbs_G1, true); + filler.Add(E, GeomAbs_C0, true); + } + else printf("Warning: fillHole: invalid edge.\n"); } - else printf("Warning: fillHole: invalid edge.\n"); + filler.Build(); + if (not filler.IsDone()) { fail = true; } + else { F = filler.Face(); } + } + catch (StdFail_NotDone& e) { fail = true; } + catch (Standard_Failure& e) { fail = true; } + + if (fail) + { + PyErr_SetString(PyExc_TypeError, "fillHole: fail to generate face (notDone)."); + return NULL; } - filler.Build(); - F = filler.Face(); } + + // Add face to shape //ShapeBuild_ReShape reshaper; //reshaper.Add(F); // no add //TopoDS_Shape shc = reshaper.Apply(*shp); + TopoDS_Shape* newshp = NULL; + TopoDS_Compound shc; BRep_Builder aBuilder; aBuilder.MakeCompound(shc); aBuilder.Add(shc, *shp); aBuilder.Add(shc, F); // How can I check face orientation? + // a posteriori continuity improvement - no success for now (unnecessary?) + if (continuity > 0) + { + printf("Info: fillHole: imposing C%d continuity.\n", continuity); + ShapeUpgrade_ShapeDivideContinuity shapeDivider(shc); + shapeDivider.SetBoundaryCriterion(crit); + shapeDivider.SetSurfaceCriterion(crit); + shapeDivider.Perform(Standard_True); + TopoDS_Shape sh = shapeDivider.Result(); + newshp = new TopoDS_Shape(sh); + } + else + newshp = new TopoDS_Shape(shc); + // export delete shp; - TopoDS_Shape* newshp = new TopoDS_Shape(shc); - + // Export packet[0] = newshp; TopTools_IndexedMapOfShape* ptr = (TopTools_IndexedMapOfShape*)packet[1]; diff --git a/Cassiopee/OCC/OCC/OCC.py b/Cassiopee/OCC/OCC/OCC.py index 1a30047a9..9834860a4 100644 --- a/Cassiopee/OCC/OCC/OCC.py +++ b/Cassiopee/OCC/OCC/OCC.py @@ -689,3 +689,48 @@ def meshAllFacesStruct(hook, dedges, faceList=[]): print("STRUCTFAILED on face = %03d_edgeUV.plt"%f) return dfaces, nloct, nofacet + +#============================================================================= +# CAD fixing +#============================================================================= + +# sew a set of faces +# faces: face list numbers +def _sewing(hook, faces, tol=1.e-6): + occ.sewing(hook, faces, tol) + return None + +# add fillet from edges with given radius +def _addFillet(hook, edges, radius, new2OldEdgeMap=[], new2OldFaceMap=[]): + occ.addFillet(hook, edges, radius, new2OldEdgeMap, new2OldFaceMap) + return None + +# edgeMap and faceMap are new2old maps +def _removeFaces(hook, faces, new2OldEdgeMap=[], new2OldFaceMap=[]): + occ.removeFaces(hook, faces, new2OldEdgeMap, new2OldFaceMap) + return None + +# fill hole from edges +# edges: edge list numbers (must be ordered) +def _fillHole(hook, edges, faces=[], continuity=0): + occ.fillHole(hook, edges, faces, continuity) + return None + +# trim two set of surfaces +def _trimFaces(hook, faces1, faces2): + occ.trimFaces(hook, faces1, faces2) + return None + +# Return the number of edges in CAD hook +def getNbEdges(hook): + """Return the number of edges in CAD hook.""" + return occ.getNbEdges(hook) + +# Return the number of faces in CAD hook +def getNbFaces(hook): + """Return the number of faces in CAD hook.""" + return occ.getNbFaces(hook) + +# Return the file and format used to load CAD in hook +def getFileAndFormat(hook): + return occ.getFileAndFormat(hook) diff --git a/Cassiopee/OCC/OCC/PyTree.py b/Cassiopee/OCC/OCC/PyTree.py index f87a46864..aecdcd24a 100644 --- a/Cassiopee/OCC/OCC/PyTree.py +++ b/Cassiopee/OCC/OCC/PyTree.py @@ -1221,7 +1221,6 @@ def _sewing(hook, faces, tol=1.e-6): # add fillet from edges with given radius def _addFillet(hook, edges, radius, new2OldEdgeMap=[], new2OldFaceMap=[]): OCC.occ.addFillet(hook, edges, radius, new2OldEdgeMap, new2OldFaceMap) - print(new2OldEdgeMap, new2OldFaceMap) return None # edgeMap and faceMap are new2old maps @@ -1231,8 +1230,8 @@ def _removeFaces(hook, faces, new2OldEdgeMap=[], new2OldFaceMap=[]): # fill hole from edges # edges: edge list numbers (must be ordered) -def _fillHole(hook, edges): - OCC.occ.fillHole(hook, edges) +def _fillHole(hook, edges, faces=[], continuity=0): + OCC.occ.fillHole(hook, edges, faces, continuity) return None # trim two set of surfaces