diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f7e8d7f92b205a37ed6e8e956846fce92f35577..f3b5ce203dfdde2d3a9eccc891ece9979f6bea24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ option(ENABLE_PLUGINS "Build the post-processing plugins" ON) option(ENABLE_POST "Build the post-processing module" ON) option(ENABLE_QT "Build QT GUI" OFF) option(ENABLE_READLINE "Enable Readline in Lua prompt" ON) +option(ENABLE_SALOME "Enable Salome routines for CAD healing" ON) option(ENABLE_SLEPC "Enable SLEPc eigensolvers" ON) option(ENABLE_SOLVER "Enable solver components" ON) option(ENABLE_SWIG "Enable swig" ON) @@ -722,6 +723,12 @@ if(ENABLE_OCC) endif(NOT OCC_CONFIG_H) endif(OCC_INC) endif(NUM_OCC_LIBS EQUAL NUM_OCC_LIBS_REQUIRED) + if(HAVE_OCC AND ENABLE_SALOME) + add_subdirectory(contrib/Salome) + include_directories(contrib/Salome) + add_definitions(-DOCCGEOMETRY) + set_config_option(HAVE_SALOME "Salome") + endif(HAVE_OCC AND ENABLE_SALOME) endif(ENABLE_OCC) if(ENABLE_ACIS) @@ -892,6 +899,8 @@ target_link_libraries(shared ${LINK_LIBRARIES}) # binary targets if(HAVE_FLTK) add_executable(gmsh WIN32 Fltk/Main.cpp ${GMSH_SRC}) + add_executable(gmsh_dynamic EXCLUDE_FROM_ALL Fltk/Main.cpp) + target_link_libraries(gmsh_dynamic shared) elseif(HAVE_QT) qt4_wrap_cpp(GMSH_MOC_SRC ${GMSH_MOC_HDR}) add_executable(gmsh WIN32 Qt/Main.cpp ${GMSH_SRC} ${GMSH_MOC_SRC}) @@ -900,9 +909,6 @@ else(HAVE_FLTK) endif(HAVE_FLTK) target_link_libraries(gmsh ${LINK_LIBRARIES}) -add_executable(gmsh_dynamic EXCLUDE_FROM_ALL Fltk/Main.cpp) -target_link_libraries(gmsh_dynamic shared) - # increase stack to 16Mb on Windows to avoid overflows in recursive # tet classification for large 3D Delaunay grids + force static # linking of system libraries with cygwin/mingw (to ease distribution diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in index 020e34a45059e94cb1dd728c3fdb4953645938d0..0b6e218679788eecc14d30b026fcc88d989c59b5 100644 --- a/Common/GmshConfig.h.in +++ b/Common/GmshConfig.h.in @@ -47,6 +47,7 @@ #cmakedefine HAVE_QT #cmakedefine HAVE_READLINE #cmakedefine HAVE_SLEPC +#cmakedefine HAVE_SALOME #cmakedefine HAVE_SOLVER #cmakedefine HAVE_TAUCS #cmakedefine HAVE_TETGEN diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp index 07b7159db1a06bf9af495eeea3fc81ddb8a3f8cf..2573a9dbd884518adfdd9fc5c32d0fc35c7fc48a 100644 --- a/Fltk/optionWindow.cpp +++ b/Fltk/optionWindow.cpp @@ -1785,7 +1785,7 @@ optionWindow::optionWindow(int deltaFontSize) b->labeltype(FL_NO_LABEL); Fl_Box *b2 = new Fl_Box - (FL_NO_BOX, L + 2 * WB, 2 * WB + 3 * BH + 1, IW, BH, "Open CASCADE model healing options:"); + (FL_NO_BOX, L + 2 * WB, 2 * WB + 3 * BH + 1, IW, BH, "Open CASCADE model healing options (experimental):"); b2->align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT); geo.butt[11] = new Fl_Check_Button @@ -1794,17 +1794,17 @@ optionWindow::optionWindow(int deltaFontSize) geo.butt[11]->callback(geometry_options_ok_cb); geo.butt[12] = new Fl_Check_Button - (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Remove small faces (experimental)"); + (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Remove small faces"); geo.butt[12]->type(FL_TOGGLE_BUTTON); geo.butt[12]->callback(geometry_options_ok_cb); geo.butt[13] = new Fl_Check_Button - (L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Sew faces (experimental)"); + (L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Sew faces"); geo.butt[13]->type(FL_TOGGLE_BUTTON); geo.butt[13]->callback(geometry_options_ok_cb); geo.butt[15] = new Fl_Check_Button - (L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Cut and merge faces (experimental)"); + (L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Cut and merge faces"); geo.butt[15]->type(FL_TOGGLE_BUTTON); geo.butt[15]->callback(geometry_options_ok_cb); diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt index ac5d5e25af266c28ce9a02d70005f263db56e1ca..6c6d16f45df13f6a6eef51b2a21e45da719090f5 100644 --- a/Geo/CMakeLists.txt +++ b/Geo/CMakeLists.txt @@ -21,7 +21,6 @@ set(SRC GModelIO_Mesh.cpp GModelIO_OCC.cpp GModelIO_ACIS.cpp - OCC_Connect.cpp GModelIO_Fourier.cpp GModelIO_CGNS.cpp GModelIO_MED.cpp diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp index 5fcec7c8cb3b1460797887f9d72508f31ac0c2bb..563843c90aebe26048752a2eb0d30aba4a873a00 100644 --- a/Geo/GFace.cpp +++ b/Geo/GFace.cpp @@ -238,7 +238,6 @@ void GFace::setVisibility(char val, bool recursive) std::list<GEdge*>::iterator it = l_edges.begin(); while (it != l_edges.end()){ (*it)->setVisibility(val, recursive); - ++it; } } diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp index a14f35175b0c02b1107dfb841cfb1e52b50df407..74580be408dccc54ffe0f0959c94f49db5144705 100644 --- a/Geo/GModelIO_OCC.cpp +++ b/Geo/GModelIO_OCC.cpp @@ -14,10 +14,13 @@ #include "MElement.h" #include "MLine.h" #include "OpenFile.h" -#include "OCC_Connect.h" #if defined(HAVE_OCC) +#if defined(HAVE_SALOME) +#include "Partition_Spliter.hxx" +#endif + void addSimpleShapes(TopoDS_Shape theShape, TopTools_ListOfShape &theList); void OCC_Internals::buildLists() @@ -39,8 +42,8 @@ void OCC_Internals::buildShapeFromLists(TopoDS_Shape _shape) TopTools_ListOfShape theList; addSimpleShapes(_shape, theList); - TopTools_ListIteratorOfListOfShape itSub1 (theList); - for (; itSub1.More(); itSub1.Next()) B.Add(C,itSub1.Value()); + TopTools_ListIteratorOfListOfShape itSub1(theList); + for (; itSub1.More(); itSub1.Next()) B.Add(C, itSub1.Value()); for(int i = 1; i <= vmap.Extent(); i++) B.Add(C, vmap(i)); for(int i = 1; i <= emap.Extent(); i++) B.Add(C, emap(i)); @@ -49,34 +52,34 @@ void OCC_Internals::buildShapeFromLists(TopoDS_Shape _shape) for(int i = 1; i <= shmap.Extent(); i++) B.Add(C, shmap(i)); for(int i = 1; i <= somap.Extent(); i++) B.Add(C, somap(i)); shape = C; - } void OCC_Internals::addShapeToLists(TopoDS_Shape _shape) { + // Solids TopExp_Explorer exp0, exp1, exp2, exp3, exp4, exp5; for(exp0.Init(_shape, TopAbs_SOLID); exp0.More(); exp0.Next()){ TopoDS_Solid solid = TopoDS::Solid(exp0.Current()); - if(somap.FindIndex(TopoDS::Solid(exp0.Current())) < 1){ - somap.Add(TopoDS::Solid(exp0.Current())); + if(somap.FindIndex(solid) < 1){ + somap.Add(solid); - for(exp1.Init(exp0.Current(), TopAbs_SHELL); exp1.More(); exp1.Next()){ - TopoDS_Shell shell = TopoDS::Shell(exp1.Current().Composed(exp0.Current().Orientation())); + for(exp1.Init(solid, TopAbs_SHELL); exp1.More(); exp1.Next()){ + TopoDS_Shell shell = TopoDS::Shell(exp1.Current()); if(shmap.FindIndex(shell) < 1){ shmap.Add(shell); for(exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()){ - TopoDS_Face face = TopoDS::Face(exp2.Current().Composed(shell.Orientation())); + TopoDS_Face face = TopoDS::Face(exp2.Current()); if(fmap.FindIndex(face) < 1){ fmap.Add(face); for(exp3.Init(exp2.Current(), TopAbs_WIRE); exp3.More(); exp3.Next()){ - TopoDS_Wire wire = TopoDS::Wire(exp3.Current().Composed(face.Orientation())); + TopoDS_Wire wire = TopoDS::Wire(exp3.Current()); if(wmap.FindIndex(wire) < 1){ wmap.Add(wire); for(exp4.Init(exp3.Current(), TopAbs_EDGE); exp4.More(); exp4.Next()){ - TopoDS_Edge edge = TopoDS::Edge(exp4.Current().Composed(wire.Orientation())); + TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if(emap.FindIndex(edge) < 1){ emap.Add(edge); @@ -98,12 +101,12 @@ void OCC_Internals::addShapeToLists(TopoDS_Shape _shape) // Free Shells for(exp1.Init(exp0.Current(), TopAbs_SHELL, TopAbs_SOLID); exp1.More(); exp1.Next()){ - TopoDS_Shape shell = exp1.Current().Composed(exp0.Current().Orientation()); + TopoDS_Shape shell = exp1.Current(); if(shmap.FindIndex(shell) < 1){ shmap.Add(shell); for(exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()){ - TopoDS_Face face = TopoDS::Face(exp2.Current().Composed(shell.Orientation())); + TopoDS_Face face = TopoDS::Face(exp2.Current()); if(fmap.FindIndex(face) < 1){ fmap.Add(face); @@ -207,61 +210,155 @@ void OCC_Internals::healGeometry(double tolerance, bool fixsmalledges, bool fixspotstripfaces, bool sewfaces, bool makesolids, bool connect) { + buildLists(); + TopExp_Explorer exp0, exp1; int nrc = 0, nrcs = 0; + int nrso = somap.Extent(), nrsh = shmap.Extent(), nrf = fmap.Extent(); + int nrw = wmap.Extent(), nre = emap.Extent(), nrv = vmap.Extent(); + for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nrc++; + for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nrcs++; - TopExp_Explorer e; - for(e.Init(shape, TopAbs_COMPOUND); e.More(); e.Next()) nrc++; - for(e.Init(shape, TopAbs_COMPSOLID); e.More(); e.Next()) nrcs++; + Msg::Info("Starting geometry healing procedure (tolerance: %g)", tolerance); - double surfacecont = 0; + { + Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; + rebuild->Apply(shape); + for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ + TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); + if(BRep_Tool::Degenerated(edge)) + rebuild->Remove(edge, false); + } + shape = rebuild->Apply(shape); + } + buildLists(); - for(int i = 1; i <= fmap.Extent(); i++){ + double surfacecont = 0; + for (exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face(exp0.Current()); GProp_GProps system; - BRepGProp::LinearProperties(fmap(i), system); + BRepGProp::SurfaceProperties(face, system); surfacecont += system.Mass(); } - Msg::Info("Healing geometry (tolerance=%g)", tolerance); + { + Msg::Info("- repairing faces"); - if(fixsmalledges){ - Msg::Info("- fixing small edges"); + Handle(ShapeFix_Face) sff; + Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; + rebuild->Apply(shape); + + for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face(exp0.Current()); + sff = new ShapeFix_Face (face); + sff->FixAddNaturalBoundMode() = Standard_True; + sff->FixSmallAreaWireMode() = Standard_True; + sff->Perform(); + + if(sff->Status(ShapeExtend_DONE1) || + sff->Status(ShapeExtend_DONE2) || + sff->Status(ShapeExtend_DONE3) || + sff->Status(ShapeExtend_DONE4) || + sff->Status(ShapeExtend_DONE5)) + { + Msg::Info(" repaired face %d", fmap.FindIndex(face)); + if(sff->Status(ShapeExtend_DONE1)) + Msg::Info(" (some wires are fixed)"); + else if(sff->Status(ShapeExtend_DONE2)) + Msg::Info(" (orientation of wires fixed)"); + else if(sff->Status(ShapeExtend_DONE3)) + Msg::Info(" (missing seam added)"); + else if(sff->Status(ShapeExtend_DONE4)) + Msg::Info(" (small area wire removed)"); + else if(sff->Status(ShapeExtend_DONE5)) + Msg::Info(" (natural bounds added)"); + TopoDS_Face newface = sff->Face(); + + rebuild->Replace(face, newface, Standard_False); + } + } + shape = rebuild->Apply(shape); + } + + { + Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; + rebuild->Apply(shape); + for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ + TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); + if ( BRep_Tool::Degenerated(edge) ) + rebuild->Remove(edge, false); + } + shape = rebuild->Apply(shape); + } + + if (fixsmalledges){ + Msg::Info("- fixing small edges"); + Handle(ShapeFix_Wire) sfw; Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); - for(int i = 1; i <= fmap.Extent(); i++){ - TopExp_Explorer exp1; - for(exp1.Init(fmap(i), TopAbs_WIRE); exp1.More(); exp1.Next()){ + for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face(exp0.Current()); + + for (exp1.Init (face, TopAbs_WIRE); exp1.More(); exp1.Next()){ TopoDS_Wire oldwire = TopoDS::Wire(exp1.Current()); - sfw = new ShapeFix_Wire(oldwire, TopoDS::Face(fmap(i)), tolerance); + sfw = new ShapeFix_Wire (oldwire, face ,tolerance); sfw->ModifyTopologyMode() = Standard_True; - if(sfw->FixSmall(false, tolerance)){ - Msg::Info("Fixed small edge in wire %d", wmap.FindIndex(oldwire)); + sfw->ClosedWireMode() = Standard_True; + + bool replace = false; + replace = sfw->FixReorder() || replace; + replace = sfw->FixConnected() || replace; + + if (sfw->FixSmall(Standard_False, tolerance) && + ! (sfw->StatusSmall(ShapeExtend_FAIL1) || + sfw->StatusSmall(ShapeExtend_FAIL2) || + sfw->StatusSmall(ShapeExtend_FAIL3))){ + Msg::Info(" fixed small edge in wire %d", wmap.FindIndex(oldwire)); + replace = true; + } + else if (sfw->StatusSmall(ShapeExtend_FAIL1)) + Msg::Warning("Failed to fix small edge in wire %d, edge cannot be checked " + "(no 3d curve and no pcurve)", wmap.FindIndex(oldwire)); + else if (sfw->StatusSmall(ShapeExtend_FAIL2)) + Msg::Warning("Failed to fix small edge in wire %d, " + "edge is null-length and has different vertives at begin and " + "end, and lockvtx is True or ModifiyTopologyMode is False", + wmap.FindIndex(oldwire)); + else if (sfw->StatusSmall(ShapeExtend_FAIL3)) + Msg::Warning("Failed to fix small edge in wire, CheckConnected has failed", + wmap.FindIndex(oldwire)); + + replace = sfw->FixEdgeCurves() || replace; + replace = sfw->FixDegenerated() || replace; + replace = sfw->FixSelfIntersection() || replace; + replace = sfw->FixLacking(Standard_True) || replace; + if(replace){ TopoDS_Wire newwire = sfw->Wire(); rebuild->Replace(oldwire, newwire, Standard_False); } - if((sfw->StatusSmall(ShapeExtend_FAIL1)) || - (sfw->StatusSmall(ShapeExtend_FAIL2)) || - (sfw->StatusSmall(ShapeExtend_FAIL3))) - Msg::Info("Failed to fix small edge in wire %d", wmap.FindIndex(oldwire)); } } + shape = rebuild->Apply(shape); { + buildLists(); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); - TopExp_Explorer exp1; - for(exp1.Init(shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ + + for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); - if(vmap.FindIndex(TopExp::FirstVertex(edge)) == - vmap.FindIndex(TopExp::LastVertex(edge))){ + if (vmap.FindIndex(TopExp::FirstVertex (edge)) == + vmap.FindIndex(TopExp::LastVertex (edge))){ GProp_GProps system; BRepGProp::LinearProperties(edge, system); - if(system.Mass() < tolerance){ - Msg::Info("removing degenerated edge %d", emap.FindIndex(edge)); + if (system.Mass() < tolerance){ + Msg::Info(" removing degenerated edge %d from vertex %d to vertex %d", + emap.FindIndex(edge), vmap.FindIndex(TopExp::FirstVertex(edge)), + vmap.FindIndex(TopExp::LastVertex(edge))); rebuild->Remove(edge, false); } } @@ -269,116 +366,179 @@ void OCC_Internals::healGeometry(double tolerance, bool fixsmalledges, shape = rebuild->Apply(shape); } + { + Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; + rebuild->Apply(shape); + for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ + TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); + if(BRep_Tool::Degenerated(edge) ) + rebuild->Remove(edge, false); + } + shape = rebuild->Apply(shape); + } + Handle(ShapeFix_Wireframe) sfwf = new ShapeFix_Wireframe; sfwf->SetPrecision(tolerance); - sfwf->Load(shape); + sfwf->Load (shape); + sfwf->ModeDropSmallEdges() = Standard_True; - if(sfwf->FixSmallEdges()){ - Msg::Info("- fixing wire frames"); - if(sfwf->StatusSmallEdges(ShapeExtend_OK)) - Msg::Info("no small edges found"); - if(sfwf->StatusSmallEdges(ShapeExtend_DONE1)) - Msg::Info("some small edges fixed"); - if(sfwf->StatusSmallEdges(ShapeExtend_FAIL1)) - Msg::Info("failed to fix some small edges"); - } - - if(sfwf->FixWireGaps()){ + if (sfwf->FixWireGaps()){ Msg::Info("- fixing wire gaps"); - if(sfwf->StatusWireGaps(ShapeExtend_OK)) - Msg::Info("no gaps found"); - if(sfwf->StatusWireGaps(ShapeExtend_DONE1)) - Msg::Info("some 2D gaps fixed"); - if(sfwf->StatusWireGaps(ShapeExtend_DONE2)) - Msg::Info("some 3D gaps fixed"); - if(sfwf->StatusWireGaps(ShapeExtend_FAIL1)) - Msg::Info("failed to fix some 2D gaps"); - if(sfwf->StatusWireGaps(ShapeExtend_FAIL2)) - Msg::Info("failed to fix some 3D gaps"); + if (sfwf->StatusWireGaps(ShapeExtend_OK)) + Msg::Info(" no gaps found"); + if (sfwf->StatusWireGaps(ShapeExtend_DONE1)) + Msg::Info(" some 2D gaps fixed"); + if (sfwf->StatusWireGaps(ShapeExtend_DONE2)) + Msg::Info(" some 3D gaps fixed"); + if (sfwf->StatusWireGaps(ShapeExtend_FAIL1)) + Msg::Info(" failed to fix some 2D gaps"); + if (sfwf->StatusWireGaps(ShapeExtend_FAIL2)) + Msg::Info(" failed to fix some 3D gaps"); + } + + sfwf->SetPrecision(tolerance); + + if (sfwf->FixSmallEdges()){ + Msg::Info("- fixing wire frames"); + if (sfwf->StatusSmallEdges(ShapeExtend_OK)) + Msg::Info(" no small edges found"); + if (sfwf->StatusSmallEdges(ShapeExtend_DONE1)) + Msg::Info(" some small edges fixed"); + if (sfwf->StatusSmallEdges(ShapeExtend_FAIL1)) + Msg::Info(" failed to fix some small edges"); } shape = sfwf->Shape(); } - - if(fixspotstripfaces){ + + if (fixspotstripfaces){ Msg::Info("- fixing spot and strip faces"); - Handle(ShapeFix_FixSmallFace) sffsm = new ShapeFix_FixSmallFace; - sffsm->Init(shape); - sffsm->SetPrecision(tolerance); - sffsm->Perform(); + Handle(ShapeFix_FixSmallFace) sffsm = new ShapeFix_FixSmallFace(); + sffsm -> Init (shape); + sffsm -> SetPrecision (tolerance); + sffsm -> Perform(); - shape = sffsm->FixShape(); + shape = sffsm -> FixShape(); } - - if(sewfaces){ - Msg::Info("- sewing faces"); - TopExp_Explorer exp0; + if (sewfaces){ + Msg::Info("- sewing faces"); BRepOffsetAPI_Sewing sewedObj(tolerance); - for(exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()){ - TopoDS_Face face = TopoDS::Face(exp0.Current()); - sewedObj.Add(face); + for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face (exp0.Current()); + sewedObj.Add (face); } sewedObj.Perform(); - if(!sewedObj.SewedShape().IsNull()) + if (!sewedObj.SewedShape().IsNull()) shape = sewedObj.SewedShape(); else - Msg::Info(" not possible"); + Msg::Info(" not possible"); } - if(makesolids){ + { + Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; + rebuild->Apply(shape); + for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){ + TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); + if ( BRep_Tool::Degenerated(edge) ) + rebuild->Remove(edge, false); + } + shape = rebuild->Apply(shape); + } + + if (makesolids){ Msg::Info("- making solids"); - TopExp_Explorer exp0; - BRepBuilderAPI_MakeSolid ms; int count = 0; - for(exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next()){ + for (exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next()){ count++; - ms.Add(TopoDS::Shell(exp0.Current())); + ms.Add (TopoDS::Shell(exp0.Current())); } - if(!count){ - Msg::Info(" not possible (no shells)"); + if (!count){ + Msg::Info(" not possible (no shells)"); } else{ BRepCheck_Analyzer ba(ms); - if(ba.IsValid()){ + if (ba.IsValid ()){ Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - sfs->Init(ms); + sfs->Init (ms); sfs->SetPrecision(tolerance); sfs->SetMaxTolerance(tolerance); sfs->Perform(); shape = sfs->Shape(); - for(exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()){ + for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()){ TopoDS_Solid solid = TopoDS::Solid(exp0.Current()); TopoDS_Solid newsolid = solid; - BRepLib::OrientClosedSolid(newsolid); + BRepLib::OrientClosedSolid (newsolid); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; - // rebuild->Apply(shape); + // rebuild->Apply(shape); rebuild->Replace(solid, newsolid, Standard_False); - TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_COMPSOLID, 1); - // TopoDS_Shape newshape = rebuild->Apply(shape); + TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_COMPSOLID);//, 1); + // TopoDS_Shape newshape = rebuild->Apply(shape); shape = newshape; } } else - Msg::Info(" not possible"); + Msg::Info(" not possible"); } } - if(connect) { - OCC_Connect connect; - for(TopExp_Explorer p(shape,TopAbs_SOLID); p.More(); p.Next()) - connect.Add(p.Current()); - connect.Connect(); - shape=connect; + if (connect){ +#if defined(HAVE_SALOME) + Msg::Info("- running SALOME partition splitter"); + TopExp_Explorer e2; + Partition_Spliter ps; + int count = 0; + + for (e2.Init(shape, TopAbs_SOLID); e2.More(); e2.Next()){ + count++; + ps.AddShape(e2.Current()); + } + + ps.Compute(); + shape = ps.Shape(); + + Msg::Info(" before: %d solids", count); + + count = 0; + for (e2.Init (shape, TopAbs_SOLID); e2.More(); e2.Next()) count++; + Msg::Info(" after : %d solids", count); +#endif } + + double newsurfacecont = 0; + for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face(exp0.Current()); + GProp_GProps system; + BRepGProp::SurfaceProperties(face, system); + newsurfacecont += system.Mass(); + } + + buildLists(); + int nnrc = 0, nnrcs = 0; + int nnrso = somap.Extent(), nnrsh = shmap.Extent(), nnrf = fmap.Extent(); + int nnrw = wmap.Extent(), nnre = emap.Extent(), nnrv = vmap.Extent(); + for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nnrc++; + for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nnrcs++; + + Msg::Info("-----------------------------------"); + Msg::Info("Compounds : %d (%d)", nnrc, nrc); + Msg::Info("Composite solids : %d (%d)", nnrcs, nrcs); + Msg::Info("Solids : %d (%d)", nnrso, nrso); + Msg::Info("Shells : %d (%d)", nnrsh, nrsh); + Msg::Info("Wires : %d (%d)", nnrw, nrw); + Msg::Info("Faces : %d (%d)", nnrf, nrf); + Msg::Info("Edges : %d (%d)", nnre, nre); + Msg::Info("Vertices : %d (%d)", nnrv, nrv ); + Msg::Info("Totol surface area : %g (%g)", newsurfacecont, surfacecont); + Msg::Info("-----------------------------------"); } void OCC_Internals::loadBREP(const char *fn) @@ -480,7 +640,8 @@ GEdge *OCC_Internals::addEdgeToModel(GModel *model, TopoDS_Edge edge) return getOCCEdgeByNativePtr(model,edge); } -GFace* OCC_Internals::addFaceToModel(GModel *model, TopoDS_Face face){ +GFace* OCC_Internals::addFaceToModel(GModel *model, TopoDS_Face face) +{ GFace *gf = getOCCFaceByNativePtr(model,face); if (gf) return gf; addShapeToLists(face); @@ -489,8 +650,8 @@ GFace* OCC_Internals::addFaceToModel(GModel *model, TopoDS_Face face){ return getOCCFaceByNativePtr(model,face); } -GRegion* OCC_Internals::addRegionToModel(GModel *model, TopoDS_Solid region){ - +GRegion* OCC_Internals::addRegionToModel(GModel *model, TopoDS_Solid region) +{ GRegion *gr = getOCCRegionByNativePtr(model,region); if (gr) return gr; addShapeToLists(region); @@ -563,7 +724,6 @@ void addSimpleShapes(TopoDS_Shape theShape, TopTools_ListOfShape &theList) } } - void OCC_Internals::applyBooleanOperator(TopoDS_Shape tool, const BooleanOperator &op) { if (tool.IsNull()) return; diff --git a/Geo/OCC_Connect.cpp b/Geo/OCC_Connect.cpp deleted file mode 100644 index c34686ef84756558bd10e1456a9a09252a4001b3..0000000000000000000000000000000000000000 --- a/Geo/OCC_Connect.cpp +++ /dev/null @@ -1,1069 +0,0 @@ -// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to <gmsh@geuz.org>. -// -// Contributed by Mark van Doesburg, Technolution B.V. - -#include "OCC_Connect.h" - -#include <vector> -#include <list> -#include <deque> -#include <iostream> -#include <iterator> - -#if defined(HAVE_OCC) - -#include <Standard_Version.hxx> - -#include <TopoDS.hxx> -#include <TopoDS_Vertex.hxx> -#include <TopoDS_Solid.hxx> -#include <TopoDS_Compound.hxx> - -#include <TopExp.hxx> -#include <TopExp_Explorer.hxx> -#include <TopOpeBRep_Point2d.hxx> -#include <TopOpeBRep_ShapeIntersector.hxx> -#include <TopTools.hxx> - -#include <BRepTools.hxx> -#include <BRepTools_ReShape.hxx> -#include <BRepTools_WireExplorer.hxx> -#include <BRepBuilderAPI_MakeVertex.hxx> -#include <BRepBuilderAPI_MakeWire.hxx> -#include <BRepExtrema_ExtCC.hxx> -#include <BRepExtrema_ExtCF.hxx> -#include <BRepExtrema_ExtFF.hxx> -#include <BRepExtrema_ExtPF.hxx> -#include <BRepExtrema_ExtPC.hxx> -#include <BRep_Tool.hxx> -#include <BRepClass_FaceClassifier.hxx> - -#include <IntTools_Context.hxx> - -#include <BRepExtrema_DistShapeShape.hxx> -#include <BRepOffsetAPI_NormalProjection.hxx> -#include <BRepTopAdaptor_FClass2d.hxx> -#include <BRepTools_Substitution.hxx> -#include <BRepAlgo_Loop.hxx> - -#include <BRep_TEdge.hxx> -#include <TopoDS_TShape.hxx> -#include <ShapeFix_Edge.hxx> -#include <Geom_Surface.hxx> -#include <gce_MakeScale.hxx> -#include <BRepBuilderAPI_GTransform.hxx> -#include <BRepBuilderAPI_Transform.hxx> - - -//////////////////////////////////////////////////////////////////////////////// -// Printing routines -//////////////////////////////////////////////////////////////////////////////// - -static inline ostream &operator <<(ostream &o,const TopAbs_ShapeEnum &A) -{ - switch(A) { - case TopAbs_COMPOUND: return o << "COMPOUND"; - case TopAbs_COMPSOLID: return o << "COMPSOLID"; - case TopAbs_SOLID: return o << "SOLID"; - case TopAbs_SHELL: return o << "SHELL"; - case TopAbs_FACE: return o << "FACE"; - case TopAbs_WIRE: return o << "WIRE"; - case TopAbs_EDGE: return o << "EDGE"; - case TopAbs_VERTEX: return o << "VERTEX"; - case TopAbs_SHAPE: return o << "SHAPE"; - default: return o << "Unknown"; - } -} - -static inline ostream &operator <<(ostream &o,const TopAbs_State &A) -{ - switch(A) { - case TopAbs_IN: return o << "IN"; - case TopAbs_OUT: return o << "OUT"; - case TopAbs_ON: return o << "ON"; - case TopAbs_UNKNOWN: return o << "UNKNOWN"; - default: return o << "Unknown"; - } -} - -static inline ostream &operator <<(ostream &o,const gp_Pnt &p) -{ - return o << "(" << p.Coord(1) << "," << p.Coord(2) << "," << p.Coord(3) << ")"; -} - -static inline ostream &operator <<(ostream &o,const TopOpeBRep_P2Dstatus &A) -{ - switch(A) { - case TopOpeBRep_P2DUNK: return o << "P2DUNK"; - case TopOpeBRep_P2DINT: return o << "P2DINT"; - case TopOpeBRep_P2DSGF: return o << "P2DSGF"; - case TopOpeBRep_P2DSGL: return o << "P2DSGL "; - case TopOpeBRep_P2DNEW: return o << "P2DNEW "; - default: return o << "Unknown"; - } -} - -template <typename T> -static inline std::ostream &operator<<(std::ostream &out, std::set<T> const &a) -{ - std::copy(a.begin(),a.end(),std::ostream_iterator<T>(out," ")); - return out; -} - -bool OCC_Connect::LessThanIntegerSet::operator()(std::set<int> const &a, - std::set<int> const &b) const -{ - std::set<int>::const_iterator pa=a.begin(), pb=b.begin(); - for(; pa!=a.end() && pb!=b.end(); pa++, pb++ ) { - if(*pa<*pb) - return 1; - if(*pb<*pa) - return 0; - } - if(pb!=b.end()) - return 1; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// OCC_Connect -//////////////////////////////////////////////////////////////////////////////// - -int OCC_Connect::SaveBRep(char const *name) -{ - gp_Pnt center(0,0,0); - gce_MakeScale transform(center, 0.001); - BRepBuilderAPI_Transform scale(assembly.front(), transform.Value()); - BRep_Builder BB; - TopoDS_Compound compound; - BB.MakeCompound(compound); - TopTools_ListOfShape p; - for(p=scale.Modified(assembly.front()); - !p.IsEmpty(); - p.RemoveFirst() - ) - BB.Add(compound,p.First()); - BRepTools::Write(compound, (char*)name); - return 1; -} - -void OCC_Connect::Dump(ostream &out) const -{ - BRepTools::Dump(assembly.front(),out); -} - -void OCC_Connect::Connect(void) -{ - while(assembly.size()>1) { - TopoDS_Compound result; - BRep_Builder BB; - BB.MakeCompound(result); - Intersect(BB,result,assembly.front(),assembly.back()); - assembly.pop_front(); - assembly.pop_back(); - assembly.push_back(result); - } -} - -void OCC_Connect::Collect(void) -{ - TopoDS_Compound result; - BRep_Builder BB; - BB.MakeCompound(result); - while(assembly.size()>0) { - if(verbose&Cutting) - cout << "Adding item\n"; - BB.Add(result,assembly.front()); - assembly.pop_front(); - } - assembly.push_back(result); -} - -void OCC_Connect::FaceCutters::Add(TopoDS_Edge const &edge) -{ - edges.push_back(edge); - rebuilt=0; -} - -int OCC_Connect::FaceCutters::FindConnectedEdge(int v, - std::vector<int> &done, - std::vector<std::vector<int> > &v_edge -) { - int re_used=-1; - for(std::vector<int>::iterator p=v_edge[v].begin();p!=v_edge[v].end(); p++){ - if(done[*p]) { - re_used=*p; - continue; - } - return *p; // Found an unused edge - } - return re_used; -} - -void dump(std::vector<std::pair<int,int> > const &e2v, std::ostream &out, - const char *name="name") -{ - out << "graph " << name << " {\n"; - for(unsigned int e = 0; e < e2v.size(); e++) { - out << " " << e2v[e].first << " -- " << e2v[e].second << "[label=" << e+1 << "]\n"; - } - out << "}\n"; -} - -void FinishEdge(int edge, - std::vector<std::set<int> > &v2e, - std::vector<std::pair<int,int> > &e2v) -{ - int verbose=0; - if(verbose) - std::cout << "Finishing edge " << edge << "\n"; - - int fv=e2v[edge].first; - v2e[fv].erase(edge); - while(v2e[fv].size()>1) { - std::set<int>::iterator e=v2e[fv].begin(); - int nv=v2e.size(); - v2e.push_back(std::set<int>()); - v2e[nv].insert(*e); - if(e2v[*e].first==fv) - e2v[*e].first=nv; - else - e2v[*e].second=nv; - if(verbose) - std::cout << "Created vertex " << nv << "(" << fv << "), edge[" << *e - << "]=" << e2v[*e].first << " " << e2v[*e].second << "\n"; - v2e[fv].erase(*e); - } - - int sv=e2v[edge].second; - v2e[sv].erase(edge); - while(v2e[sv].size()>1) { - std::set<int>::iterator e=v2e[sv].begin(); - int nv=v2e.size(); - v2e.push_back(std::set<int>()); - v2e[nv].insert(*e); - if(e2v[*e].first==sv) - e2v[*e].first=nv; - else - e2v[*e].second=nv; - if(verbose) - std::cout << "Created vertex " << nv << "(" << sv << "), edge[" << *e << - "]=" << e2v[*e].first << " " << e2v[*e].second << "\n"; - v2e[sv].erase(*e); - } -} - -void OCC_Connect::FaceCutters::Build(TopoDS_Face const &face, - TopoDS_Shape &result, int verbose) -{ - clear(); - - /* First we create some data structures to access the topology */ - TopTools_IndexedMapOfShape vertices; - std::vector<std::pair<int,int> > e2v; - for(unsigned int i = 0; i < edges.size(); i++) { - TopExp::MapShapes(edges[i],TopAbs_VERTEX,vertices); - TopoDS_Vertex v1, v2; - TopExp::Vertices(edges[i],v1,v2); - std::pair<int,int> t(vertices.FindIndex(v1),vertices.FindIndex(v2)); - e2v.push_back(t); - } - - std::vector<std::set<int> > v2e; - for(unsigned int e = 0; e < e2v.size(); e++) { - if(e2v[e].first >= (int)v2e.size()) - v2e.resize(e2v[e].first+1); - v2e[e2v[e].first].insert(e); - if(e2v[e].second >= (int)v2e.size()) - v2e.resize(e2v[e].second+1); - v2e[e2v[e].second].insert(e); - } - - std::set<int> open, odd; - for(unsigned int i = 0; i < v2e.size(); i++) { - if(v2e[i].size()==0) - continue; - else if(v2e[i].size()==1) - open.insert(i); - else if(v2e[i].size()&1) - odd.insert(i); - } - - if(open.size()&1) - std::cerr << "Inconsistent open loops\n"; - if(odd.size()&1) - std::cerr << "Inconsistent odd loops\n"; - - for(;;) { - int open_mode = -1; - std::set<int> current_vertices; - for(unsigned int start = 0; start < v2e.size(); start++) { - if(v2e[start].size()==1) { - if(verbose&Cutting) - std::cout << "start open at " << start << "\n"; - current_vertices.insert(start); - open_mode=1; - break; - } - } - if(!current_vertices.size()) { - for(unsigned int start = 0; start < v2e.size(); start++) { - if(v2e[start].size()) { - if(verbose&Cutting) - std::cout << "start closed at " << start << "\n"; - current_vertices.insert(start); - open_mode=0; - break; - } - } - } - if(!current_vertices.size()) - break; - - std::map<int,std::deque<int> > wires; - std::set<int> processed_edges; - do { - std::set<int> next_vertices; - for(std::set<int>::iterator v=current_vertices.begin(); - v!=current_vertices.end(); - v++ - ) { - for(std::set<int>::iterator e=v2e[*v].begin() ; - e!=v2e[*v].end(); - e++ - ) { - if(processed_edges.count(*e)) - continue; - - int other=e2v[*e].first==*v? - e2v[*e].second:e2v[*e].first; - - if(open_mode) { - if(v2e[other].size()==1) { - // Other is open end too, finish wire. - wires[*v].push_back(*e); - std::deque<int>::const_iterator p; - BRepBuilderAPI_MakeWire wire; - if(verbose&Cutting) - std::cout << "CUT Open wire:"; - for(p=wires[*v].begin(); - p!=wires[*v].end(); - p++ - ) { - FinishEdge(*p, v2e, e2v); - wire.Add(edges[*p]); - if(verbose&Cutting) - std::cout << ' ' << (*p)+1; - } - if(verbose&Cutting) - std::cout << "\n"; - push_back(wire); - goto next_vertex; - } - } else { - if( current_vertices.count(other) || - next_vertices.count(other) - ) { - if(verbose&Cutting) - std::cout << "CUT Closed wire:"; - wires[*v].push_back(*e); - while(wires[other].front() - ==wires[*v].front() - ) { - wires[other].pop_front(); - wires[*v].pop_front(); - } - - BRepBuilderAPI_MakeWire wire; - std::deque<int>::const_iterator p; - for(p=wires[other].begin(); - p!=wires[other].end(); - p++ - ) { - FinishEdge(*p, v2e, e2v); - wire.Add(edges[*p]); - if(verbose&Cutting) - std::cout << ' ' << (*p)+1; - } - std::deque<int>::reverse_iterator rp; - for(rp=wires[*v].rbegin(); - rp!=wires[*v].rend(); - rp++ - ) { - FinishEdge(*rp, v2e, e2v); - wire.Add(edges[*rp]); - if(verbose&Cutting) - std::cout << ' ' << (*rp)+1; - } - if(verbose&Cutting) - std::cout << "\n"; - push_back(wire); - goto next_vertex; - } - } - if(current_vertices.count(other)==0) { - wires[other]=wires[*v]; - wires[other].push_back(*e); - processed_edges.insert(*e); - next_vertices.insert(other); - } - } - } - current_vertices=next_vertices; - } while(current_vertices.size()); - next_vertex: ; - } - - if(size()>1 && verbose&CuttingIntermediate) { - if(verbose&Cutting) - std::cout << "Saving multiple cuts\n"; - BRep_Builder BB; - TopoDS_Compound compound; - BB.MakeCompound(compound); - for(unsigned int i = 0; i < edges.size(); i++) - BB.Add(compound,edges[i]); - BRepTools::Write(compound,"cutter.brep"); - ofstream out("cutter.dot",ios::trunc|ios::out); - dump(e2v,out); - } -} - -inline OCC_Connect::cutmap_t OCC_Connect::SelectCuttingEdges( - TopTools_IndexedMapOfShape &edges, - TopTools_IndexedMapOfShape &faces) -{ - cutmap_t cutters; - for(int face=1;face<=faces.Extent();face++) { - for(int edge=1;edge<=edges.Extent();edge++) { - TopoDS_Edge c_edge=TopoDS::Edge(edges(edge)); - TopoDS_Face c_face=TopoDS::Face(faces(face)); - - if(BRep_Tool::Degenerated(c_edge)) { - if(verbose&CuttingReject) - cout << "Rejected(" << __LINE__ << ") edge " << edge - << " in face " << face << endl; - continue; - } - - TopTools_IndexedMapOfShape already_there; - TopExp::MapShapes(c_face,TopAbs_EDGE,already_there); - if(already_there.Contains(c_edge)) { - if(verbose&CuttingReject) - cout << "Rejected(" << __LINE__ << ") edge " << edge - << " in face " << face << endl; - continue; - } - - BRepExtrema_DistShapeShape dist(c_edge,c_face); - double tol=BRep_Tool::Tolerance(c_face); - if(dist.Value()>tol) { - if(verbose&CuttingReject) - cout << "Rejected(" << __LINE__ << ") edge " << edge - << " in face " << face << endl; - continue; - } - - Standard_Real s, e; - Handle(Geom_Curve) c3d=BRep_Tool::Curve(c_edge,s,e); - if(c3d.IsNull()) { - if(verbose&CuttingReject) - cout << "Rejected(" << __LINE__ << ") edge " << edge - << " in face " << face << endl; - continue; - } - - // FIXME, checking only the middle may be a bit optimistic. - TopoDS_Vertex vm=BRepBuilderAPI_MakeVertex(c3d->Value((s+e)/2)); - BRepExtrema_DistShapeShape dist_mf(vm,c_face); - if(dist_mf.Value()>tol) { - if(verbose&CuttingReject) - cout << "Rejected(" << __LINE__ << ") edge " << edge - << " in face " << face << endl; - continue; - } - - if(verbose&Cutting) - cout << "Accepted edge " << edge << " in face " << face << endl; - - // Add missing PCurve if necessary - Handle_Geom2d_Curve c=BRep_Tool::CurveOnSurface(c_edge,c_face,s,e); - if(c.IsNull()) { - if(verbose&Cutting) - cout << "Adding missing PCurve\n"; - ShapeFix_Edge().FixAddPCurve(c_edge,c_face,false,1e-7); - } - cutters[face].Add(c_edge); - } - } - return cutters; -} - -void OCC_Connect::Intersect(BRep_Builder &BB, TopoDS_Shape &target, - TopoDS_Shape &shape, TopoDS_Shape &tool) -{ - /*************************************************************************** - We start by splitting edges at all the edge-edge intersections. - This may generate new vertices and edges. - ***************************************************************************/ - MergeVertices(shape,tool); - LocOpe_SplitShape splitter1(shape); - LocOpe_SplitShape splitter2(tool); - TopOpeBRep_ShapeIntersector intersector; - for(intersector.InitIntersection(shape,tool); - intersector.MoreIntersection(); - intersector.NextIntersection() - ) { - if(verbose&Cutting) { - cout << "++++++++++++++++++++++++++++++++++++++++" - "++++++++++++++++++++++++++++++++++++++++\n"; - intersector.DumpCurrent(1); cout << " --> "; - intersector.DumpCurrent(2); cout << '\n'; - } - - TopOpeBRep_EdgesIntersector &ee=intersector.ChangeEdgesIntersector(); - if( intersector.CurrentGeomShape(1).ShapeType()==TopAbs_EDGE && - intersector.CurrentGeomShape(2).ShapeType()==TopAbs_EDGE - ) { - for(ee.InitPoint(); ee.MorePoint(); ee.NextPoint()) { - TopOpeBRep_Point2d const &p=ee.Point(); - if(verbose&Cutting) - cout << "point loop " << p.Parameter(1) << '\n'; - TopoDS_Vertex vertex; - if(p.IsVertex(1)) - vertex=p.Vertex(1); - else if(p.IsVertex(2)) - vertex=p.Vertex(2); - else - vertex=BRepBuilderAPI_MakeVertex(p.Value()); - if(!p.IsVertex(1)) { - TopoDS_Edge edge=TopoDS::Edge(ee.Edge(1)); - if(!splitter1.CanSplit(edge)) { - if(verbose&Cutting) - cout << "Cannot split 1\n";; - } else { - if(verbose&Cutting) - cout << "splitting model 1\n"; - try { splitter1.Add(vertex,p.Parameter(1),edge); } - catch(Standard_ConstructionError c) { - if(verbose&Cutting) - cout << "Ooops \n"; - } - } - } - if(!p.IsVertex(2)) { - TopoDS_Edge edge=TopoDS::Edge(ee.Edge(2)); - if(!splitter2.CanSplit(edge)) { - if(verbose&Cutting) - cout << "Cannot split 2\n";; - } else { - if(verbose&Cutting) - cout << "splitting model 2\n"; - try { splitter2.Add(vertex,p.Parameter(2),edge); } - catch(Standard_ConstructionError c) { - if(verbose&Cutting) - cout << "Ooops \n"; - } - } - } - } - } - } - - /*************************************************************************** - Not all intersections seem to be caught, this is an attempt to catch - some missing intersections. FIXME, this is almost certainly incomplete. - ***************************************************************************/ - TopTools_IndexedMapOfShape edges, faces, vertices; - vertices.Clear(); - TopExp::MapShapes(shape,TopAbs_VERTEX,vertices); - TopExp::MapShapes(tool,TopAbs_VERTEX,vertices); - - edges.Clear(); - TopExp::MapShapes(shape,TopAbs_EDGE,edges); - for(int e=1; e<=edges.Extent(); e++) { - TopoDS_Edge edge=TopoDS::Edge(edges(e)); - TopoDS_Vertex o1, o2; - TopExp::Vertices(edge,o1,o2); - int skip1=vertices.FindIndex(o1); - int skip2=vertices.FindIndex(o2); - for(int v=1; v<=vertices.Extent(); v++) { - if(v==skip1 || v==skip2) - continue; - TopoDS_Vertex vertex=TopoDS::Vertex(vertices(v)); - BRepExtrema_ExtPC distance(vertex,edge); - if(!distance.IsDone()) - continue; - double tolerance=std::max(BRep_Tool::Tolerance(edge), - BRep_Tool::Tolerance(vertex)); - for(int i=1;i<=distance.NbExt();i++) { -#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) - double value = distance.Value(i); -#else - double value = distance.SquareDistance(i); -#endif - if(value<tolerance) { - try { - // No idea why this can fail - splitter1.Add(vertex,distance.Parameter(i),edge); - } - catch(Standard_ConstructionError c) { - if(verbose&Cutting) { - cout << "Adding vertex to edge failed\n"; - TopoDS_Vertex v1, v2; - TopExp::Vertices(edge,v1,v2); - if(BRepTools::Compare(v1,vertex)) - cout << "Merge v1\n"; - if(BRepTools::Compare(v2,vertex)) - cout << "Merge v2\n"; - double d1=BRep_Tool::Pnt(v1).Distance( - BRep_Tool::Pnt(vertex)); - double d2=BRep_Tool::Pnt(v2).Distance( - BRep_Tool::Pnt(vertex)); - cout << "Adding " << i << " to edge " << e - << " distance=" << value - << " parameter=" << distance.Parameter(i) - << " point=" << distance.Point(i) - << " dv1=" << d1 - << " dv2=" << d2 - << endl; - BRepTools::Dump(vertex,cout); - BRepTools::Dump(edge,cout); - } - } - } - } - } - } - - edges.Clear(); - TopExp::MapShapes(tool,TopAbs_EDGE,edges); - for(int e=1; e<=edges.Extent(); e++) { - TopoDS_Edge edge=TopoDS::Edge(edges(e)); - TopoDS_Vertex o1, o2; - TopExp::Vertices(edge,o1,o2); - int skip1=vertices.FindIndex(o1); - int skip2=vertices.FindIndex(o2); - for(int v=1; v<=vertices.Extent(); v++) { - if(v==skip1 || v==skip2) - continue; - TopoDS_Vertex vertex=TopoDS::Vertex(vertices(v)); - BRepExtrema_ExtPC distance(vertex,edge); - if(!distance.IsDone()) - continue; - double tolerance=std::max(BRep_Tool::Tolerance(edge), - BRep_Tool::Tolerance(vertex)); - for(int i=1;i<=distance.NbExt();i++) { -#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) - double value = distance.Value(i); -#else - double value = distance.SquareDistance(i); -#endif - if(value<tolerance) { - try { - splitter2.Add(vertex,distance.Parameter(i),edge); - } - catch(Standard_ConstructionError c) { - if(verbose&Cutting) { - cout << "Adding vertex to edge failed\n"; - TopoDS_Vertex v1, v2; - TopExp::Vertices(edge,v1,v2); - if(BRepTools::Compare(v1,vertex)) - cout << "Merge v1\n"; - if(BRepTools::Compare(v2,vertex)) - cout << "Merge v2\n"; - double d1=BRep_Tool::Pnt(v1).Distance( - BRep_Tool::Pnt(vertex)); - double d2=BRep_Tool::Pnt(v2).Distance( - BRep_Tool::Pnt(vertex)); - cout << "Adding " << i << " to edge " << e - << " distance=" << value - << " parameter=" << distance.Parameter(i) - << " point=" << distance.Point(i) - << " dv1=" << d1 - << " dv2=" << d2 - << endl; - BRepTools::Dump(vertex,cout); - BRepTools::Dump(edge,cout); - } - } - } - } - } - } - - /*************************************************************************** - We need the shapes with all the edge-edge intersections to split - all the faces. All vertices and edges which can be merged, will - be merged. - ***************************************************************************/ - TopoDS_Compound intermediate1; - BB.MakeCompound(intermediate1); - for(TopTools_ListIteratorOfListOfShape p(splitter1.DescendantShapes(shape)); - p.More(); - p.Next() - ) { - BB.Add(intermediate1,p.Value()); - } - TopoDS_Compound intermediate2; - BB.MakeCompound(intermediate2); - for(TopTools_ListIteratorOfListOfShape p(splitter2.DescendantShapes(tool)); - p.More(); - p.Next() - ) { - BB.Add(intermediate2,p.Value()); - } - if(verbose&Cutting) { - cout << "Before merging vertices and edges\n"; - TopoDS_Compound t; - BB.MakeCompound(t); - BB.Add(t,intermediate1); - BB.Add(t,intermediate2); - PrintItemCount(t); - } - MergeVertices(intermediate1,intermediate2); - MergeEdges(intermediate1,intermediate2); - if(verbose&Cutting) { - cout << "After merging vertices and edges\n"; - TopoDS_Compound t; - BB.MakeCompound(t); - BB.Add(t,intermediate1); - BB.Add(t,intermediate2); - PrintItemCount(t); - } - - // Create the result - TopoDS_Compound result; - BB.MakeCompound(result); - BB.Add(result,intermediate1); - BB.Add(result,intermediate2); - - // Add any missing PCurves - for(TopExp_Explorer face(result,TopAbs_FACE); face.More(); face.Next()) { - for(TopExp_Explorer edge(face.Current(),TopAbs_EDGE); - edge.More(); - edge.Next() - ) { - Standard_Real s, e; - TopoDS_Edge c_edge=TopoDS::Edge(edge.Current()); - TopoDS_Face c_face=TopoDS::Face(face.Current()); - Handle_Geom2d_Curve c=BRep_Tool::CurveOnSurface(c_edge,c_face,s,e); - if(c.IsNull()) { - if(verbose&Cutting) - cout << "Adding missing PCurve\n"; - ShapeFix_Edge().FixAddPCurve(c_edge,c_face,false,1e-7); - } - } - } - - /*************************************************************************** - We determine which edges/wires are going to cut a face. To do this - we create a map of FaceCutters which is indexed by the face number - in the faces map. The FaceCutters generate the correct cutting wires. - ***************************************************************************/ - int retry; -do { - if(verbose&Cutting) - std::cout << "STARTED CUTTING\n"; - retry=0; - edges.Clear(); TopExp::MapShapes(result,TopAbs_EDGE,edges); - faces.Clear(); TopExp::MapShapes(result,TopAbs_FACE,faces); - cutmap_t cutters=SelectCuttingEdges(edges,faces); - - /*************************************************************************** - Apply all face splits stored in the map. - ***************************************************************************/ - int cut_count=0; - LocOpe_SplitShape splitter(result); - for(cutmap_t::iterator f=cutters.begin(); f!=cutters.end(); f++) { - TopoDS_Face const &face=TopoDS::Face(faces(f->first)); - FaceCutters &cutter=f->second; - cut_count+=cutter.size(); - if(verbose&Cutting) { - cout << "Cutting face " << f->first << " *************************\n"; - BRepTools::Dump(face,cout); - } - cutter.Build(face,result,verbose); - for(FaceCutters::iterator p=cutter.begin(); p!=cutter.end(); p++) { - TopTools_IndexedMapOfShape edges; - TopExp::MapShapes(*p,TopAbs_EDGE,edges); - if(edges.Extent()<3 && BRep_Tool::IsClosed(*p)) { - // FIXME This doesn't work. - cout << "IGNORED Closed wire with less than three edges\n"; - continue; - } - //BRepTools::Dump(*p,cout); - try { - splitter.Add(*p,face); - } - catch(Standard_ConstructionError c) { - cout << "splitting the face failed\n"; - retry=1; - } - } - } - if(verbose&Cutting) - cout << cut_count << " cuts in " << cutters.size() << " faces\n"; - - // Create the final shape with the cutted faces. - TopoDS_Compound cutted; - BB.MakeCompound(cutted); - int count=0; - for(TopTools_ListIteratorOfListOfShape p(splitter.DescendantShapes(result)); - p.More(); - p.Next() - ) { - if(++count==1) { - if(verbose&Cutting) { - cout << "--------- " << count << " ---------------------------\n"; - BRepTools::Dump(p.Value(),cout); - } - BB.Add(cutted,p.Value()); - } - } - MergeFaces(cutted); - result=cutted; -} while(0 && retry); - target=result; -} - -void OCC_Connect::MergeVertices(TopoDS_Shape &shape1,TopoDS_Shape &shape2) const -{ - TopTools_IndexedMapOfShape imap, omap; - TopExp::MapShapes(shape1,TopAbs_VERTEX,imap); - TopExp::MapShapes(shape2,TopAbs_VERTEX,imap); - BRepTools_ReShape replacer; - for(int i=0;i<imap.Extent();i++) { - for(int j=0;j<omap.Extent();j++) { - TopoDS_Vertex orig=TopoDS::Vertex(imap(i+1)); - TopoDS_Vertex repl=TopoDS::Vertex(omap(j+1)); - if(BRepTools::Compare(orig,repl)) { - repl.Orientation(orig.Orientation()); - replacer.Replace(orig,repl); - // FIXME, tolerance and point should be updated - goto skip; - } - } - omap.Add(imap(i+1)); - skip:; - } - TopoDS_Shape t=shape1; - shape1=replacer.Apply(t); - t=shape2; - shape2=replacer.Apply(t); -} - -bool OCC_Connect::CanMergeCurve(TopoDS_Edge edge1,TopoDS_Edge edge2) const -{ - if(BRep_Tool::Degenerated(edge1) && BRep_Tool::Degenerated(edge2)) - return 1; - - double tol=1e-7; - - Standard_Real s,e; - Handle(Geom_Curve) curve=BRep_Tool::Curve(edge1,s,e); - for(Standard_Real i=s;i<=e;i+=(e-s)/10) { - TopoDS_Vertex v=BRepBuilderAPI_MakeVertex(curve->Value(i)); - double dist=BRepExtrema_DistShapeShape(edge2,v).Value(); - if(dist>tol) - return 0; - } - return 1; -} - -void OCC_Connect::MergeEdges(TopoDS_Shape &shape1, TopoDS_Shape &shape2) const -{ - TopTools_IndexedMapOfShape imap, omap; - TopExp::MapShapes(shape1,TopAbs_EDGE,imap); - TopExp::MapShapes(shape2,TopAbs_EDGE,imap); - BRepTools_ReShape replacer; - for(int i=0;i<imap.Extent();i++) { - for(int j=0;j<omap.Extent();j++) { - TopoDS_Edge orig=TopoDS::Edge(imap(i+1)); - TopoDS_Edge repl=TopoDS::Edge(omap(j+1)); - - TopoDS_Vertex o1, o2, r1, r2; - TopExp::Vertices(orig,o1,o2,true); - TopExp::Vertices(repl,r1,r2,true); - - if(o1.IsSame(o2)) { - if(!BRep_Tool::Degenerated(orig)) { - if(verbose&Cutting) { - cout << "Same vertex in edge\n"; - BRepTools::Dump(orig,cout); - } - replacer.Remove(orig); - goto skip; - } else if(o1.IsSame(r1) && o1.IsSame(r2) - && CanMergeCurve(orig,repl) - ) { - if(verbose&Cutting) { - cout << "Degenerated edge, replace " << i+1 - << " with " << j+1 << '\n'; - BRepTools::Dump(orig,cout); - BRepTools::Dump(repl,cout); - } - // FIXME, update tolerance - BRepTools::Dump(repl.Complemented(),cout); - replacer.Replace(orig,repl.Complemented()); - goto skip; - } - cout << i+1 << " Degenerated\n"; - } - if(o1.IsSame(r1) && o2.IsSame(r2) && CanMergeCurve(orig,repl)) { - if(verbose&Cutting) { - cout << "Same order of vertices, replace " << i+1 - << " with " << j+1 << '\n'; - BRepTools::Dump(orig,cout); - BRepTools::Dump(repl,cout); - } - // FIXME, update tolerance - replacer.Replace(orig,repl); - goto skip; - } - if(o1.IsSame(r2) && o2.IsSame(r1) && CanMergeCurve(orig,repl)) { - if(verbose&Cutting) { - cout << "Reversed order of vertices, replace " << i+1 - << " with " << j+1 << '\n'; - BRepTools::Dump(orig,cout); - BRepTools::Dump(repl,cout); - } - // FIXME, update tolerance - replacer.Replace(orig,repl.Complemented()); - goto skip; - } - } - if(verbose&Cutting) - cout << "Adding " << i+1 << " as " << omap.Extent()+1<<" to keep map\n"; - omap.Add(imap(i+1)); - skip:; - } - TopoDS_Shape t=shape1; - shape1=replacer.Apply(t); - t=shape2; - shape2=replacer.Apply(t); -} - -bool OCC_Connect::CanMergeFace(TopoDS_Face face1,TopoDS_Face face2) const -{ - // FIXME, this really does not work. - return 1; - - //double tol=1e-7; - - Handle(Geom_Surface) surface=BRep_Tool::Surface(face1); - Standard_Real u1, u2, v1, v2; - surface->Bounds(u1,u2,v1,v2); - cout << "u1=" << u1 << " u2=" << u2 << " v1=" << v1 << " v2=" << v2 << endl; - for(Standard_Real u=u1+(u2-u1)/10;u<u2;u+=(u2-u1)/10) { - for(Standard_Real v=v1+(v2-v1)/10;v<v2;v+=(v2-v1)/10) { - TopoDS_Vertex vtx=BRepBuilderAPI_MakeVertex(surface->Value(u,v)); - BRepExtrema_DistShapeShape dss(face2,vtx); - dss.Perform(); -#if 0 - double dist=dss.Value(); - if(dist>tol) { - cout << "Distance=" << dist << " v=" << v << " u=" << u - << " pnt=" << surface->Value(u,v) << endl; - BRepTools::Dump(face2,cout); - return 0; - } -#else - dss.Dump(cout); -#endif - } - } - return 1; -} - -void OCC_Connect::MergeFaces(TopoDS_Shape &shape) const -{ - /*************************************************************************** - We must find faces which are the same. Since all edges are already - merged, we know that faces which can be merged have identical edges. - ***************************************************************************/ - TopTools_IndexedMapOfShape faces, edges; - TopExp::MapShapes(shape,TopAbs_FACE,faces); - TopExp::MapShapes(shape,TopAbs_EDGE,edges); - mapping_t mapping; - for(int i=0;i<faces.Extent();i++) { - std::set<int> face_edges; - for(TopExp_Explorer p(faces(i+1),TopAbs_EDGE); p.More(); p.Next()) { - int edge=edges.FindIndex(p.Current()); - if(BRep_Tool::Degenerated(TopoDS::Edge(edges(edge)))) { - cout << "Degenerate edge " << edge << " inserted a 0\n"; - face_edges.insert(0); - } else - face_edges.insert(edge); - } - mapping[face_edges].insert(i+1); - } - - if(verbose&Cutting) { - for(mapping_t::iterator p=mapping.begin(); p!=mapping.end(); p++) - cout << "edges [ " << p->first << "] in face" - << (p->second.size()<2? " ":"s ") << "[ " << p->second << "]\n"; - } - - /*************************************************************************** - If two faces have an identical set of edges, they can be merged - when the planes are never seperated by more than the tolerance. - ***************************************************************************/ - BRepTools_ReShape replacer; - for(mapping_t::iterator p=mapping.begin(); p!=mapping.end(); p++) { - if(p->second.size()<2) - continue; - std::vector<int> uniq; - for(std::set<int>::iterator q=p->second.begin(); - q!=p->second.end(); - q++ - ) { - for(std::vector<int>::iterator r=uniq.begin(); r!=uniq.end(); r++) { - TopoDS_Face orig=TopoDS::Face(faces(*q)); - TopoDS_Face repl=TopoDS::Face(faces(*r)); - if(verbose&Cutting) - cout << "Check face " << *q << " and " << *r << endl; - if(CanMergeFace(orig,repl)) { - if(verbose&Cutting) { - cout << "replace face " << *q << " with " << *r << '\n'; - } - repl.Orientation(orig.Orientation()); - replacer.Replace(orig,repl); - // FIXME, tolerance should be updated - goto skip; - } - } - uniq.push_back(*q); - skip:; - } - } - - TopoDS_Shape t=shape; - shape=replacer.Apply(t); -} - -void OCC_Connect::PrintItemCount(TopoDS_Shape const &shape) const -{ - TopTools_IndexedMapOfShape imap; - TopExp::MapShapes(shape,TopAbs_VERTEX,imap); - cout << "Input map contains " << imap.Extent() << " vertices\n"; - imap.Clear(); - TopExp::MapShapes(shape,TopAbs_EDGE,imap); - cout << "Input map contains " << imap.Extent() << " edges\n"; - imap.Clear(); - TopExp::MapShapes(shape,TopAbs_FACE,imap); - cout << "Input map contains " << imap.Extent() << " faces\n"; - imap.Clear(); - TopExp::MapShapes(shape,TopAbs_SOLID,imap); - cout << "Input map contains " << imap.Extent() << " solids\n"; - imap.Clear(); - TopExp::MapShapes(shape,TopAbs_COMPSOLID,imap); - cout << "Input map contains " << imap.Extent() << " compsolids\n"; - imap.Clear(); - TopExp::MapShapes(shape,TopAbs_COMPOUND,imap); - cout << "Input map contains " << imap.Extent() << " compounds\n"; -} - -#endif diff --git a/Geo/OCC_Connect.h b/Geo/OCC_Connect.h deleted file mode 100644 index 1843f20e328d1807281b0b105f17904998bcc85e..0000000000000000000000000000000000000000 --- a/Geo/OCC_Connect.h +++ /dev/null @@ -1,87 +0,0 @@ -// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to <gmsh@geuz.org>. -// -// Contributed by Mark van Doesburg, Technolution B.V. - -#ifndef _OCC_CONNECT_H_ -#define _OCC_CONNECT_H_ - -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <deque> -#include <map> -#include <vector> -#include <set> - -#include "GmshConfig.h" - -#if defined(HAVE_OCC) - -#if !defined(HAVE_NO_OCC_CONFIG_H) -#include <config.h> -#endif - -#include <TopoDS_Shape.hxx> -#include <TopoDS_Edge.hxx> -#include <TopoDS_Wire.hxx> -#include <TopoDS_Face.hxx> -#include <TopTools_IndexedMapOfShape.hxx> - -#include <BRep_Builder.hxx> -#include <LocOpe_SplitShape.hxx> - -//////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////// -class OCC_Connect { - struct LessThanIntegerSet { - bool operator()(std::set<int> const &a, std::set<int> const &b) const; - }; - typedef std::map<std::set<int>,std::set<int>,LessThanIntegerSet> mapping_t; - - class FaceCutters:public std::vector<TopoDS_Wire> { - std::vector<TopoDS_Edge> edges; - int rebuilt; - public: - FaceCutters(void) { rebuilt=0; } - void Build(TopoDS_Face const &,TopoDS_Shape&,int); - void Add(TopoDS_Edge const&); - private: - int FindConnectedEdge(int v, std::vector<int> &done, - std::vector<std::vector<int> > &v_edge); - }; - typedef std::map<int,FaceCutters> cutmap_t; - - std::deque<TopoDS_Shape> assembly; -protected: - int verbose; - -public: - enum Verbose { Cutting=1, CuttingReject=4, CuttingIntermediate=8 }; - OCC_Connect(int v=0) { verbose=v; } - int SaveBRep(char const *); - void Connect(void); - void Collect(void); - void Add(TopoDS_Shape const &a) { assembly.push_back(a); } - void Dump(std::ostream &) const; - operator TopoDS_Shape(void) { return assembly.front(); } -private: - void MergeVertices(TopoDS_Shape&,TopoDS_Shape&) const; - void MergeEdges(TopoDS_Shape&,TopoDS_Shape&) const; - void MergeFaces(TopoDS_Shape&) const; - void PerformBoolean(union tree*); - void Intersect(BRep_Builder &BB, TopoDS_Shape &target, - TopoDS_Shape &shape, TopoDS_Shape &tool); - bool CanMergeCurve(TopoDS_Edge edge1,TopoDS_Edge edge2) const; - bool CanMergeFace(TopoDS_Face face1,TopoDS_Face face2) const; - void PrintItemCount(TopoDS_Shape const &shape) const; - cutmap_t SelectCuttingEdges(TopTools_IndexedMapOfShape &edges, - TopTools_IndexedMapOfShape &faces); -}; - -#endif - -#endif diff --git a/contrib/Salome/CMakeLists.txt b/contrib/Salome/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..578733af52b1a35b35114931c0185d1ba2bc8e42 --- /dev/null +++ b/contrib/Salome/CMakeLists.txt @@ -0,0 +1,16 @@ +# Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle +# +# See the LICENSE.txt file for license information. Please report all +# bugs and problems to <gmsh@geuz.org>. + +set(SRC + Partition_Inter2d.cxx + Partition_Inter3d.cxx + Partition_Loop.cxx + Partition_Loop2d.cxx + Partition_Loop3d.cxx + Partition_Spliter.cxx +) + +file(GLOB_RECURSE HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.hxx) +append_gmsh_src(contrib/Salome "${SRC};${HDR}") diff --git a/contrib/Salome/Partition_Inter2d.cxx b/contrib/Salome/Partition_Inter2d.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4634b32daf1be828659009e20d55840ee5df5edb --- /dev/null +++ b/contrib/Salome/Partition_Inter2d.cxx @@ -0,0 +1,679 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R& D, LEG, PRINCIPIA R& D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter2d.cxx +// Author : Benedicte MARTIN +// Module : GEOM +// $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter2d.cxx,v 1.5 2008/03/31 14:20:28 wabro Exp $ + +#include "Partition_Inter2d.ixx" + +//#include "utilities.h" + +#include <BRepAdaptor_Curve.hxx> +#include <BRepAlgo_AsDes.hxx> +#include <BRepLib_MakeVertex.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> +#include <Geom_Surface.hxx> +#include <Precision.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> +#include <TopOpeBRepDS_Transition.hxx> +#include <TopOpeBRep_EdgesIntersector.hxx> +#include <TopOpeBRep_Point2d.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Vertex.hxx> +#include <gp_Pnt.hxx> + +#ifdef DEB +static Standard_Boolean TestEdges = 0; +static Standard_Integer NbF2d = 0; +static Standard_Integer NbE2d = 0; +#endif + +//======================================================================= +//function : getOtherShape +//purpose : +//======================================================================= + +static TopoDS_Shape getOtherShape(const TopoDS_Shape& theS, + const TopTools_ListOfShape& theSList) +{ + TopTools_ListIteratorOfListOfShape anIt( theSList ); + for ( ; anIt.More(); anIt.Next() ) + if (!theS.IsSame( anIt.Value() )) + return anIt.Value(); + + return TopoDS_Shape(); +} + +//======================================================================= +//function : findVOnE +//purpose : on theE, find a vertex close to theV, such that an edge +// passing through it is an itersection of theF1 and theF2. +// theE intersects theE2 at theV +//======================================================================= + +static Standard_Boolean findVOnE(const TopoDS_Vertex & theV, + const TopoDS_Edge& theE, + const TopoDS_Edge& theE2, + const TopoDS_Shape& theF1, + const TopoDS_Shape& theF2, + const Handle(BRepAlgo_AsDes)& theAsDes, + TopoDS_Vertex & theFoundV) +{ + Standard_Real MinDist2 = ::RealLast(); + gp_Pnt P; + + // check all vertices on theE + const TopTools_ListOfShape& aVList = theAsDes->Descendant( theE ); + TopTools_ListIteratorOfListOfShape anIt( aVList ); + if (anIt.More()) + P = BRep_Tool::Pnt( theV ); + for ( ; anIt.More(); anIt.Next() ) + { + // check by distance + TopoDS_Vertex & V = TopoDS::Vertex( anIt.Value() ); + Standard_Real dist2 = P.SquareDistance( BRep_Tool::Pnt( V )); + if (dist2 < MinDist2) + MinDist2 = dist2; + else + continue; + + // V is a candidate if among edges passing through V there is one + // which is an intersection of theF1 and theF2 + TopTools_ListIteratorOfListOfShape anEIt( theAsDes->Ascendant( V )); + Standard_Boolean isOk = Standard_False; + for ( ; !isOk && anEIt.More(); anEIt.Next() ) + { + const TopoDS_Shape & E2 = anEIt.Value(); + if ( theE2.IsSame( E2 )) + continue; + const TopTools_ListOfShape & aFList = theAsDes->Ascendant( E2 ); + if (aFList.IsEmpty()) + continue; + if ( theF1.IsSame( aFList.First() )) + isOk = theF2.IsSame( aFList.Last() ); + else + isOk = theF2.IsSame( aFList.First() ) && theF1.IsSame( aFList.Last() ); + } + if (isOk) + theFoundV = V; + } + + if (theFoundV.IsNull()) + return Standard_False; + + // check that MinDist2 is not too large + Standard_Real f, l; + TopLoc_Location L; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theE, L, f, l ); + gp_Pnt P1 = aCurve->Value( f ); + gp_Pnt P2 = aCurve->Value( 0.3 * f + 0.7 * l ); + //gp_Pnt P2 = aCurve->Value( 0.5 * ( f + l )); + if (MinDist2 > P1.SquareDistance( P2 )) + return Standard_False; + +#ifdef DEB + MESSAGE("findVOnE: found MinDist = " << sqrt (MinDist2)); +#endif + + return Standard_True; +} + +//======================================================================= +//function : AddVonE +//purpose : Put V in AsDes as intersection of E1 and E2. +// Check that vertex equal to V already exists on one +// of edges, in such a case, V is not added but +// existing vertex is updated to be on E1 and E2 and +// is returned insead of V. +//======================================================================= + +TopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV, + const TopoDS_Edge& E1, + const TopoDS_Edge& E2, + const Handle(BRepAlgo_AsDes)& AsDes, + const TopoDS_Face& theF) + +{ + //------------------------------------------------------------- + // test if the points of intersection already exist. If not, + // add as descendants of the edges. + // nb: theses points are only vertices of intersection. + //------------------------------------------------------------- + const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1); + const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2); + gp_Pnt P1,P2; + TopoDS_Vertex V1,V2; + TopTools_ListIteratorOfListOfShape it; + BRep_Builder B; + TopAbs_Orientation O1,O2; + Standard_Real U1,U2; + Standard_Real Tol,Tol1,Tol2; + Standard_Boolean OnE1,OnE2; + + TopoDS_Vertex V = theV; + + U1 = BRep_Tool::Parameter(V,E1); + U2 = BRep_Tool::Parameter(V,E2); + O1 = V.Orientation(); + O2 = O1; + P1 = BRep_Tool::Pnt(V); + Tol = BRep_Tool::Tolerance( V ); + OnE1 = OnE2 = Standard_False; + + //----------------------------------------------------------------- + // Search if the point of intersection is a vertex of E1. + //----------------------------------------------------------------- + for (it.Initialize(VOnE1); it.More(); it.Next()) { + const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() ); + if (V.IsSame( CV )) { + V1 = V; + OnE1 = Standard_True; + break; + } + P2 = BRep_Tool::Pnt( CV ); + Tol1 = 1.1*(Tol + BRep_Tool::Tolerance( CV )); + if (P1.SquareDistance(P2) <= Tol1*Tol1) { + V = CV; + V1 = V; + OnE1 = Standard_True; + break; + } + } + if (OnE1) { + //----------------------------------------------------------------- + // Search if the vertex found is still on E2. + //----------------------------------------------------------------- + for (it.Initialize(VOnE2); it.More(); it.Next()) { + if (V.IsSame( it.Value() )) { + OnE2 = Standard_True; + V2 = V; + break; + } + } + } + if (!OnE2) { + for (it.Initialize(VOnE2); it.More(); it.Next()) { + //----------------------------------------------------------------- + // Search if the point of intersection is a vertex of E2. + //----------------------------------------------------------------- + const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() ); + P2 = BRep_Tool::Pnt( CV ); + Tol2 = 1.1*(Tol + BRep_Tool::Tolerance( CV )); + if (P1.SquareDistance(P2) <= Tol2*Tol2) { + V = CV; + V2 = V; + OnE2 = Standard_True; + break; + } + } + } + + + if (!OnE1 && !OnE2 && !theF.IsNull()) + { + // if 3 faces intersects each others, 3 new edges on them must pass + // through one vertex but real intersection points of each + // pair of edges are sometimes more far than a tolerance. + // Try to analitically find vertices that E1 and E2 must pass trough + + TopoDS_Shape F1 = getOtherShape( theF, AsDes->Ascendant( E1 )); + TopoDS_Shape F2 = getOtherShape( theF, AsDes->Ascendant( E2 )); + if (!F1.IsNull() && !F2.IsNull() && !F1.IsSame( F2 )) + { + OnE1 = findVOnE ( theV, E1, E2, F1, F2, AsDes, V1 ); + OnE2 = findVOnE ( theV, E2, E1, F1, F2, AsDes, V2 ); + if (OnE2) V = V2; + if (OnE1) V = V1; + } + } + + if (OnE1 && OnE2) { + if (!V1.IsSame(V2)) { + // replace V1 with V2 on all edges V1 is on + Standard_Real UV1; + TopoDS_Edge EWE1; + TopoDS_Vertex VI; + const TopTools_ListOfShape& EdgeWithV1 = AsDes->Ascendant(V1); + + for (it.Initialize(EdgeWithV1); it.More(); it.Next()) { + EWE1 = TopoDS::Edge(it.Value()); + VI = V1; + VI.Orientation(TopAbs_INTERNAL); + UV1 = BRep_Tool::Parameter(VI,EWE1); + VI = V2; + VI.Orientation(TopAbs_INTERNAL); + B.UpdateVertex( VI, UV1, EWE1, GetTolerance( VI, UV1, EWE1, AsDes)); + } + AsDes->Replace(V1,V2); + V = V2; + } + } + + // add existing vertices instead of new ones + if (!OnE1) { + if (OnE2) { + V.Orientation(TopAbs_INTERNAL); + B.UpdateVertex (V, U1, E1, GetTolerance( V, U1, E1, AsDes)); + } + V.Orientation(O1); + AsDes->Add(E1,V); + } + if (!OnE2) { + if (OnE1) { + V.Orientation(TopAbs_INTERNAL); + B.UpdateVertex (V, U2, E2, GetTolerance( V, U2, E2, AsDes )); + } + V.Orientation(O2); + AsDes->Add(E2,V); + } + + return V; +} + +//======================================================================= +//function : FindEndVertex +//purpose : Returns a vertex from <VertList> having parameter on +// <E> closest to <f> or <l>. <isFirst> is True if +// found vertex is closer to <f>. <DU> returns parameter +// difference. +//======================================================================= + +TopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV, + const Standard_Real f, + const Standard_Real l, + const TopoDS_Edge& E, + Standard_Boolean& isFirst, + Standard_Real& minDU) +{ + TopoDS_Vertex endV; + Standard_Real U, endU, min; + minDU = 1.e10; + + TopTools_ListIteratorOfListOfShape it; + it.Initialize(LV); + for (; it.More(); it.Next()) { + const TopoDS_Vertex& v = TopoDS::Vertex(it.Value()); + U = BRep_Tool::Parameter(v, E); + min = Min( Abs(U-f), Abs(U-l) ); + if (min < minDU) { + endV = v; + endU = U; + minDU = min; + } + } + if (Abs(endU-f) < Abs(endU-l)) + isFirst = Standard_True; + else + isFirst = Standard_False; + + return endV; +} + +//======================================================================= +//function : treatClosed +//purpose : add second vertex to closed edge. Vertex is one of <LV1> +//======================================================================= + +static void treatClosed (const TopoDS_Edge& E1, + const Standard_Real f, + const Standard_Real l, + TopTools_ListOfShape& LV1, + TopTools_ListOfShape& /*LV2*/) +{ + Standard_Boolean isFirst=0; + Standard_Real minDU = 1.e10; + TopoDS_Vertex endV; + endV = Partition_Inter2d::FindEndVertex(LV1, f,l, E1, isFirst,minDU); + + if (minDU > Precision::PConfusion()) + return; // not end point + + Standard_Real newU; + if (isFirst) + newU = f + (l - f); + else + newU = l - (l - f); + + // update end parameter + BRep_Builder B; + endV.Orientation(TopAbs_INTERNAL); + B.UpdateVertex(endV,newU,E1,BRep_Tool::Tolerance(endV)); +} + +//======================================================================= +//function : EdgesPartition +//purpose : +//======================================================================= + +static void EdgesPartition(const TopoDS_Face& F, + const TopoDS_Edge& E1, + const TopoDS_Edge& E2, + const Handle(BRepAlgo_AsDes)& AsDes, + const TopTools_MapOfShape& NewEdges, + const Standard_Boolean WithOri) +{ + + Standard_Real f[3],l[3]; + Standard_Real MilTol2; + Standard_Real Tol = Max (BRep_Tool::Tolerance(E1), + BRep_Tool::Tolerance(E2)); + MilTol2 = Tol * Tol * 10; + + BRep_Tool::Range(E1, f[1], l[1]); + BRep_Tool::Range(E2, f[2], l[2]); + + BRepAdaptor_Curve CE1(E1,F); + BRepAdaptor_Curve CE2(E2,F); + + TopoDS_Edge EI[3]; EI[1] = E1; EI[2] = E2; + TopTools_ListOfShape LV1; // new vertices at intersections on E1 + TopTools_ListOfShape LV2; // ... on E2 + BRep_Builder B; + + // if E1 and E2 are results of intersection of F and two connex faces then + // no need to intersect edges, they can contact by vertices only + // (encounted an exception in TopOpeBRep_EdgesIntersector in such a case) + Standard_Boolean intersect = Standard_True; + TopTools_IndexedMapOfShape ME; + TopExp::MapShapes(F, TopAbs_EDGE, ME); + if (!ME.Contains(E1) && ! ME.Contains(E2)) { // if E1 and E2 are new on F + TopoDS_Shape F1, F2; + const TopTools_ListOfShape& LF1 = AsDes->Ascendant( E1 ); + F1 = F.IsSame( LF1.First() ) ? LF1.Last() : LF1.First(); + const TopTools_ListOfShape& LF2 = AsDes->Ascendant( E2 ); + F2 = F.IsSame( LF2.First() ) ? LF2.Last() : LF2.First(); + if (!F.IsSame(F2) && !F.IsSame(F1) ) { + TopExp_Explorer exp(F2, TopAbs_EDGE); + TopExp::MapShapes(F1, TopAbs_EDGE, ME); + for (; exp.More(); exp.Next()) { + if (ME.Contains( exp.Current())) { + intersect = Standard_False; + break; + } + } + } + } + + if (intersect) { + //------------------------------------------------------ + // compute the points of Intersection in 2D + //----------------------------------------------------- + // i.e. fill LV1 and LV2 + TopOpeBRep_EdgesIntersector EInter; + EInter.SetFaces(F,F); + Standard_Real TolDub = 1.e-7; + EInter.ForceTolerances(TolDub,TolDub); + Standard_Boolean reducesegments = Standard_False; + EInter.Perform (E1,E2,reducesegments); + + Standard_Boolean rejectreducedsegmentpoints = Standard_False; + EInter.InitPoint(rejectreducedsegmentpoints); + for ( ; EInter.MorePoint(); EInter.NextPoint() ) + { + const TopOpeBRep_Point2d& P2D = EInter.Point(); + const gp_Pnt& P = P2D.Value(); + TopoDS_Vertex V = BRepLib_MakeVertex(P); + + //------------------------- + // control the point found. + //------------------------- + gp_Pnt P1 = CE1.Value(P2D.Parameter(1)); + gp_Pnt P2 = CE2.Value(P2D.Parameter(2)); + Standard_Real sqd1 = P1.SquareDistance(P); + Standard_Real sqd2 = P2.SquareDistance(P); + if (sqd1 > MilTol2 || sqd2 > MilTol2 ) + continue; + + // add a new vertex to the both edges + Standard_Real toler = Max( Tol, sqrt( Max( sqd1, sqd2 ))); + Standard_Integer i; + for (i = 1; i <= 2; i++) { + Standard_Real U = P2D.Parameter(i); + V.Orientation(TopAbs_INTERNAL); + B.UpdateVertex( V,U,EI[i], toler); + TopAbs_Orientation OO = TopAbs_REVERSED; + if (WithOri) { + if (P2D.IsVertex(i)) + OO = P2D.Vertex(i).Orientation(); + else if (P2D.Transition(i).Before() == TopAbs_OUT) { + OO = TopAbs_FORWARD; + } + V.Orientation(OO); + if (i == 1) LV1.Append(V); + else LV2.Append(V); + } + } + } + } // if (intersect) + + //---------------------------------- + // Test the extremities of the edges. + //---------------------------------- + // add to LV* vertices for vertex-vertex closeness + Standard_Real U1,U2; + Standard_Real TolConf2, TolConf; + TopoDS_Vertex V1[2],V2[2]; + TopExp::Vertices(E1,V1[0],V1[1]); + TopExp::Vertices(E2,V2[0],V2[1]); + + Standard_Integer i,j,k; + for (j = 0; j < 2; j++) { + if (V1[j].IsNull()) continue; + for ( k = 0; k < 2; k++) { + if (V2[k].IsNull()) continue; + gp_Pnt P1 = BRep_Tool::Pnt(V1[j]); + gp_Pnt P2 = BRep_Tool::Pnt(V2[k]); + TolConf = BRep_Tool::Tolerance(V1[j]) + BRep_Tool::Tolerance(V2[k]); + TolConf = Max (Tol, TolConf); + TolConf2 = TolConf * TolConf; + if (!intersect) + TolConf2 *= 100; +#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) + Standard_Real SqDist = P1.Value(P2); +#else + Standard_Real SqDist = P1.SquareDistance(P2); +#endif + if (SqDist <= TolConf2) { + TopoDS_Vertex V = BRepLib_MakeVertex(P1); + V.Orientation(TopAbs_INTERNAL); + U1 = (j == 0) ? f[1] : l[1]; + U2 = (k == 0) ? f[2] : l[2]; + B.UpdateVertex(V,U1,E1,TolConf); + B.UpdateVertex(V,U2,E2,TolConf); + LV1.Prepend(V.Oriented(V1[j].Orientation())); + LV2.Prepend(V.Oriented(V2[k].Orientation())); + } + } + } + + Standard_Boolean AffichPurge = Standard_False; + + if ( LV1.IsEmpty()) return; + + //---------------------------------- + // Purge of all the vertices. + //---------------------------------- + // remove one of close vertices + TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1; + gp_Pnt P1,P2; + Standard_Boolean Purge = Standard_True; + + while (Purge) { + i = 1; + Purge = Standard_False; + for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); + it1LV1.More(); + it1LV1.Next(),it1LV2.Next()) { + j = 1; + it2LV1.Initialize(LV1); + while (j < i) { + const TopoDS_Vertex& VE1 = TopoDS::Vertex(it1LV1.Value()); + const TopoDS_Vertex& VE2 = TopoDS::Vertex(it2LV1.Value()); + Standard_Real Tol1 = BRep_Tool::Tolerance( VE1 ); + Standard_Real Tol2 = BRep_Tool::Tolerance( VE2 ); + P1 = BRep_Tool::Pnt( VE1 ); + P2 = BRep_Tool::Pnt( VE2 ); + if (P1.IsEqual(P2, Tol1 + Tol2)) { + LV1.Remove(it1LV1); + LV2.Remove(it1LV2); + Purge = Standard_True; + break; + } + j++; + it2LV1.Next(); + } + if (Purge) break; + i++; + } + } + + // care of new closed edges, they always intersect with seam at end + if (V1[0].IsSame( V1[1] ) && NewEdges.Contains(E1) ) + treatClosed (E1, f[1], l[1], LV1, LV2); + if (V2[0].IsSame( V2[1] ) && NewEdges.Contains(E2) ) + treatClosed (E2, f[2], l[2], LV2, LV1); + + //---------------- + // Stocking vertex + //---------------- + + for ( it1LV1.Initialize( LV1 ); it1LV1.More(); it1LV1.Next()) + Partition_Inter2d::AddVonE (TopoDS::Vertex( it1LV1.Value()), + E1, E2, AsDes, F); +} + +//======================================================================= +//function : CompletPart2d +//purpose : Computes the intersections between the edges stored +// is AsDes as descendants of <F> . Intersections is computed +// between two edges if one of them is bound in NewEdges. +//======================================================================= + +void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)& AsDes, + const TopoDS_Face& F, + const TopTools_MapOfShape& NewEdges) +{ + +#ifdef DEB + NbF2d++; + NbE2d = 0; +#endif + + //Do not intersect the edges of a face + TopTools_IndexedMapOfShape EdgesOfFace; + TopExp::MapShapes( F, TopAbs_EDGE , EdgesOfFace); + + //------------------------------------------------------------------- + // compute the intersection2D on the faces touched by the intersection3D + //------------------------------------------------------------------- + TopTools_ListIteratorOfListOfShape it1LE ; + TopTools_ListIteratorOfListOfShape it2LE ; + + //----------------------------------------------- + // Intersection edge-edge. + //----------------------------------------------- + const TopTools_ListOfShape& LE = AsDes->Descendant(F); + TopoDS_Vertex V1,V2; + Standard_Integer j, i = 1; + + TopoDS_Face FF = F; + FF.Orientation(TopAbs_FORWARD); + + for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) { + const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value()); + j = 1; + it2LE.Initialize(LE); + + while (j < i && it2LE.More()) { + const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value()); + //---------------------------------------------------------- + // Intersections of the new edges obtained by intersection + // between them and with the restrictions edges + //---------------------------------------------------------- + if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) && + (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) { + EdgesPartition(FF,E1,E2,AsDes,NewEdges,Standard_True); + } + it2LE.Next(); + j++; + } + i++; + } +} + +//======================================================================= +//function : GetTolerance +//purpose : Returns tolerance theV must have atfer its +// addition to theE with theU parameter. theAsDes is +// used to find pcurves of theE +//======================================================================= + +Standard_Real Partition_Inter2d::GetTolerance + (const TopoDS_Vertex & theV, + const Standard_Real theU, + const TopoDS_Edge & theE, + const Handle(BRepAlgo_AsDes)& theAsDes) +{ + Standard_Real aTol = BRep_Tool::Tolerance( theV ); + gp_Pnt aPnt = BRep_Tool::Pnt( theV ); + + // check point on 3D curve + Standard_Real f,l; + Handle(Geom_Curve) C = BRep_Tool::Curve( theE, f, l ); + if (!C.IsNull()) + aTol = Max ( aTol, aPnt.Distance( C->Value( theU ))); + + // check points on pcurves + const TopTools_ListOfShape& aFList = theAsDes->Ascendant( theE ); + TopTools_ListIteratorOfListOfShape aFIt( aFList ); + for ( ; aFIt.More(); aFIt.Next() ) + { + const TopoDS_Face& F = TopoDS::Face( aFIt.Value() ); + Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( theE, F, f, l ); + if (!pcurve.IsNull()) + { + gp_Pnt2d aPnt2d = pcurve->Value( theU ); + TopLoc_Location L; + Handle(Geom_Surface) S = BRep_Tool::Surface( F, L ); + gp_Pnt aPntOnS = S->Value( aPnt2d.X(), aPnt2d.Y() ); + if (!L.IsIdentity()) + aPntOnS.Transform( L.Transformation() ); + aTol = Max ( aTol, aPnt.Distance( aPntOnS )); + } + } + + return aTol; +} + +#endif diff --git a/contrib/Salome/Partition_Inter2d.hxx b/contrib/Salome/Partition_Inter2d.hxx new file mode 100644 index 0000000000000000000000000000000000000000..cfd4a9ac0aa4db3e23ff3669a99b9546c71138f4 --- /dev/null +++ b/contrib/Salome/Partition_Inter2d.hxx @@ -0,0 +1,110 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter2d.hxx +// Module : GEOM + +#ifndef _Partition_Inter2d_HeaderFile +#define _Partition_Inter2d_HeaderFile + +#ifndef _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _Standard_Real_HeaderFile +#include <Standard_Real.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopoDS_Face; +class TopTools_MapOfShape; +class TopoDS_Vertex; +class TopTools_ListOfShape; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Inter2d { + +public: + + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // Methods PUBLIC + // + static void CompletPart2d(const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F,const TopTools_MapOfShape& NewEdges) ; + static TopoDS_Vertex FindEndVertex(const TopTools_ListOfShape& VertList,const Standard_Real f,const Standard_Real l,const TopoDS_Edge& E,Standard_Boolean& First,Standard_Real& DU) ; + static TopoDS_Vertex AddVonE(const TopoDS_Vertex& V,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F) ; + static Standard_Real GetTolerance(const TopoDS_Vertex& theV,const Standard_Real theU,const TopoDS_Edge& theE,const Handle(BRepAlgo_AsDes)& theAsDes) ; + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + + + // Fields PRIVATE + // + + +}; + + + + + +// other Inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Inter2d.ixx b/contrib/Salome/Partition_Inter2d.ixx new file mode 100644 index 0000000000000000000000000000000000000000..2587287415fe3661a78f06587fb4cf4f3decca80 --- /dev/null +++ b/contrib/Salome/Partition_Inter2d.ixx @@ -0,0 +1,37 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter2d.ixx +// Module : GEOM + +//using namespace std; +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +#include <climits> +#include "Partition_Inter2d.jxx" + + + + diff --git a/contrib/Salome/Partition_Inter2d.jxx b/contrib/Salome/Partition_Inter2d.jxx new file mode 100644 index 0000000000000000000000000000000000000000..8c3ef7d49501d455279d52a5d6bd9f14ae2824b8 --- /dev/null +++ b/contrib/Salome/Partition_Inter2d.jxx @@ -0,0 +1,47 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter2d.jxx +// Module : GEOM + +#ifndef _BRepAlgo_AsDes_HeaderFile +#include <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopoDS_Vertex_HeaderFile +#include <TopoDS_Vertex.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Inter2d_HeaderFile +#include "Partition_Inter2d.hxx" +#endif diff --git a/contrib/Salome/Partition_Inter3d.cxx b/contrib/Salome/Partition_Inter3d.cxx new file mode 100644 index 0000000000000000000000000000000000000000..db6da22ec812c08ef409a108c6ff53c555c4a972 --- /dev/null +++ b/contrib/Salome/Partition_Inter3d.cxx @@ -0,0 +1,950 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter3d.cxx +// Author : Benedicte MARTIN +// Module : GEOM +// $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter3d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ + +//using namespace std; +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +//using namespace std; +#include <climits> + +#include "Partition_Inter2d.hxx" +#include "Partition_Inter3d.ixx" +//#include "utilities.h" + +#include <BRepAlgo_AsDes.hxx> +#include <BRepAlgo_Image.hxx> +#include <BRepLib.hxx> +#include <BRepOffset_Tool.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> + +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +#include <TopOpeBRepTool_BoxSort.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Compound.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Face.hxx> +#include <TopoDS_Vertex.hxx> + +#ifdef DEB +#include <DBRep.hxx> +#endif + +#include <BRepLib_MakeVertex.hxx> +#include <BRepTools.hxx> +#include <Extrema_ExtPS.hxx> +#include <Extrema_POnSurf.hxx> +#include <Geom2dAPI_ProjectPointOnCurve.hxx> +#include <Geom2d_Curve.hxx> +#include <GeomAPI_ProjectPointOnCurve.hxx> +#include <GeomAdaptor_Surface.hxx> +#include <Geom_Curve.hxx> +#include <Geom_RectangularTrimmedSurface.hxx> +#include <Geom_SphericalSurface.hxx> +#include <Geom_Surface.hxx> +#include <Geom_TrimmedCurve.hxx> +#include <Precision.hxx> +#include <TColStd_MapOfInteger.hxx> +#include <TopOpeBRepBuild_Builder.hxx> +#include <TopOpeBRepDS_BuildTool.hxx> +#include <TopOpeBRepDS_CurveExplorer.hxx> +#include <TopOpeBRepDS_HDataStructure.hxx> +#include <TopOpeBRepDS_Interference.hxx> +#include <TopOpeBRepDS_PointIterator.hxx> +#include <TopOpeBRepDS_Transition.hxx> +#include <TopOpeBRepTool_CurveTool.hxx> +#include <TopOpeBRepTool_GeomTool.hxx> +#include <TopOpeBRepTool_OutCurveType.hxx> +#include <TopOpeBRep_DSFiller.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> +#include <stdio.h> + +//======================================================================= +//function : Partition_Inter3d +//purpose : +//======================================================================= + +Partition_Inter3d::Partition_Inter3d() +{ +} +//======================================================================= +//function : Partition_Inter3d +//purpose : +//======================================================================= + +Partition_Inter3d::Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes) + :myAsDes(AsDes) +{ + mySectionEdgesAD = new BRepAlgo_AsDes; +} + +//======================================================================= +//function : CompletPart3d +//purpose : FaceShapeMap is just to know the shape a face belongs to +//======================================================================= + +void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1, + const TopTools_DataMapOfShapeShape& FaceShapeMap) +{ + if (myAsDes.IsNull()) + myAsDes = new BRepAlgo_AsDes; + + TopTools_ListIteratorOfListOfShape it; + + //--------------------------------------------------------------- + // Construction of bounding boxes. + //--------------------------------------------------------------- + + BRep_Builder B; + TopoDS_Compound CompOS; + B.MakeCompound(CompOS); + for (it.Initialize(SetOfFaces1); it.More(); it.Next()) + B.Add(CompOS, it.Value()); + + TopOpeBRepTool_BoxSort BOS; + BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE); + + for (it.Initialize(SetOfFaces1); it.More(); it.Next()) { + TopoDS_Face F1 = TopoDS::Face(it.Value()); + + // avoid intersecting faces of one shape + TopoDS_Shape S1; + if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1); + + // to filter faces sharing an edge + TopTools_IndexedMapOfShape EM; + TopExp::MapShapes( F1, TopAbs_EDGE, EM); + + TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1); + for (; itLI.More(); itLI.Next()) { + TopoDS_Face F2 = TopoDS::Face(BOS.TouchedShape(itLI)); + if (F1.IsSame(F2) || IsDone(F1,F2)) + continue; + + TopoDS_Shape S2; + if (FaceShapeMap.IsBound(F2)) S2 = FaceShapeMap.Find(F2); + if (!S1.IsNull() && S1.IsSame(S2)) + continue; // descendants of one shape + + TopExp_Explorer expE (F2, TopAbs_EDGE); + for ( ; expE.More(); expE.Next()) + if (EM.Contains( expE.Current() )) + break; + if (expE.More()) + { + // faces have a common edge, check if they are a tool and a face + // generated by the tool in another shape; in that case they are + // to be intersected + TopLoc_Location L1, L2; + Handle(Geom_Surface) S1 = BRep_Tool::Surface( F1, L1 ); + Handle(Geom_Surface) S2 = BRep_Tool::Surface( F2, L2 ); + if ( S1 != S2 || L1 != L2 ) + continue; + } + + F1.Orientation(TopAbs_FORWARD); + F2.Orientation(TopAbs_FORWARD); + FacesPartition(F1,F2); + } + + // mark as modified a face which has at least one new edge + if (!myAsDes->HasDescendant( F1 )) + continue; + TopTools_ListIteratorOfListOfShape itE (myAsDes->Descendant( F1 )); + for ( ; itE.More(); itE.Next()) { + if (myNewEdges.Contains( itE.Value())) { + myTouched.Add( F1 ); + break; + } + } + } +} + +//======================================================================= +//function : PutInBounds +//purpose : +//======================================================================= + +static void PutInBounds (const TopoDS_Face& F, + const TopoDS_Edge& E, + Handle(Geom2d_Curve)& C2d) +{ + Standard_Real umin,umax,vmin,vmax; + Standard_Real f,l; + BRep_Tool::Range(E,f,l); + + TopLoc_Location L; // Recup S avec la location pour eviter la copie. + Handle (Geom_Surface) S = BRep_Tool::Surface(F,L); + + if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { + S = (*(Handle_Geom_RectangularTrimmedSurface*)&S)->BasisSurface(); + } + if (!S->IsUPeriodic() && !S->IsVPeriodic()) + return; + + BRepTools::UVBounds(F,umin,umax,vmin,vmax); + + gp_Pnt2d Pf = C2d->Value(f); + gp_Pnt2d Pl = C2d->Value(l); + const Standard_Real Um = 0.34*f + 0.66*l; + gp_Pnt2d Pm = C2d->Value( Um ); + + // sometimes on shpere, pcurve is out of domain by V though S is + // UPeriodic, sometimes it is in domain but nontheless it has + // wrong position. + // Check pcurve position by 3D point + if (S->IsKind(STANDARD_TYPE( Geom_SphericalSurface ))) + { + // get point on the surface + gp_Pnt Ps = S->Value( Pm.X(), Pm.Y() ); + // get point on the edge + Handle(Geom_Curve) C = BRep_Tool::Curve( E, f, l ); + gp_Pnt Pc = C->Value( Um ); + // compare points + Standard_Real TolE = BRep_Tool::Tolerance( E ); + if ( Pc.SquareDistance( Ps ) * 0.95 < TolE * TolE ) + return; // OK + + // find good UV for Pc: project Pc on S + GeomAdaptor_Surface SA (S); + Extrema_ExtPS anExtPS (Pc, SA, + SA.UResolution( TolE ), SA.VResolution( TolE )); + if (anExtPS.IsDone()) + { + Standard_Integer i, nbExt = anExtPS.NbExt(); + Extrema_POnSurf aPOnSurf; + for (i = 1; i <= nbExt; ++i ) + if (anExtPS.SquareDistance( i ) <= TolE) { + aPOnSurf = anExtPS.Point( i ); + break; + } + if (i <= nbExt) { + // a point found + Standard_Real u, v; + aPOnSurf.Parameter( u, v ); + gp_Pnt2d aGoodPm ( u, v ); + C2d->Translate( Pm , aGoodPm ); + } + } + } + + //--------------- + // Recadre en U. + //--------------- + if (S->IsUPeriodic()) { + Standard_Real period = S->UPeriod(); + Standard_Real eps = period*1.e-6; + Standard_Real minC = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X()); + Standard_Real maxC = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X()); + Standard_Real du = 0.; + if (minC< umin - eps) { + du = (int((umin - minC)/period) + 1)*period; + } + if (minC > umax + eps) { + du = -(int((minC - umax)/period) + 1)*period; + } + if (du != 0) { + gp_Vec2d T1(du,0.); + C2d->Translate(T1); + minC += du; maxC += du; + } + // Ajuste au mieux la courbe dans le domaine. + if (maxC > umax +100*eps) { + Standard_Real d1 = maxC - umax; + Standard_Real d2 = umin - minC + period; + if (d2 < d1) du =-period; + if ( du != 0.) { + gp_Vec2d T2(du,0.); + C2d->Translate(T2); + } + } + } + //------------------ + // Recadre en V. + //------------------ + if (S->IsVPeriodic()) { + Standard_Real period = S->VPeriod(); + Standard_Real eps = period*1.e-6; + Standard_Real minC = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y()); + Standard_Real maxC = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y()); + Standard_Real dv = 0.; + if (minC< vmin - eps) { + dv = (int((vmin - minC)/period) + 1)*period; + } + if (minC > vmax + eps) { + dv = -(int((minC - vmax)/period) + 1)*period; + } + if (dv != 0) { + gp_Vec2d T1(0.,dv); + C2d->Translate(T1); + minC += dv; maxC += dv; + } + // Ajuste au mieux la courbe dans le domaine. + if (maxC > vmax +100*eps) { + Standard_Real d1 = maxC - vmax; + Standard_Real d2 = vmin - minC + period; + if (d2 < d1) dv =-period; + if ( dv != 0.) { + gp_Vec2d T2(0.,dv); + C2d->Translate(T2); + } + } + } +} + +//======================================================================= +//function : Inter3D +//purpose : +//======================================================================= + +void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, + const TopoDS_Face& F2, + TopTools_ListOfShape& L) +{ + BRep_Builder B; + + // fill the data Structure + Handle(TopOpeBRepDS_HDataStructure) DatStr = new TopOpeBRepDS_HDataStructure(); + TopOpeBRep_DSFiller DSFiller; + DSFiller.Insert(F1,F2,DatStr); + + // define the GeomTool used by the DSFiller : + // compute BSpline of degree 1 on intersection curves. + Standard_Real tol3dAPPROX = 1e-7; + Standard_Real tol2dAPPROX = 1e-7; + TopOpeBRepTool_GeomTool GT2 (TopOpeBRepTool_APPROX); + GT2.SetTolerances(tol3dAPPROX,tol2dAPPROX); + TopOpeBRepDS_BuildTool BT(GT2); + + // Perform Section + TopOpeBRepBuild_Builder TopB(BT); + TopB.Perform(DatStr); + + // =============== + // Store new edges + // =============== + + L.Clear(); + TopOpeBRepDS_CurveExplorer cex(DatStr->DS()); + for (; cex.More(); cex.Next()) { + const TopOpeBRepDS_Curve& CDS = cex.Curve(); + Standard_Integer ic = cex.Index(); + Handle(Geom2d_Curve) pc1 = CDS.Curve1(); + Handle(Geom2d_Curve) pc2 = CDS.Curve2(); + + TopTools_ListIteratorOfListOfShape itLE = TopB.NewEdges(ic); + while (itLE.More()) { + TopoDS_Edge E = TopoDS::Edge(itLE.Value()); + + PutInBounds (F1,E,pc1); + PutInBounds (F2,E,pc2); + + B.UpdateEdge (E,pc1,F1,0.); + B.UpdateEdge (E,pc2,F2,0.); + + L.Append (E); + + itLE.Next(); + if (itLE.More()) { + pc1 = Handle(Geom2d_Curve)::DownCast(pc1->Copy()); + pc2 = Handle(Geom2d_Curve)::DownCast(pc2->Copy()); + } + } + } + + // ======================== + // store same domain faces + // ======================== + + + if ( DatStr->HasSameDomain( F1 )) + { + TopTools_ListOfShape emptyList; + if (!mySameDomainFM.IsBound(F1)) + mySameDomainFM.Bind(F1,emptyList); + if (!mySameDomainFM.IsBound(F2)) + mySameDomainFM.Bind(F2,emptyList); + mySameDomainFM(F1).Append(F2); + mySameDomainFM(F2).Append(F1); + } + + // ==================== + // Store section edges + // ==================== + + const TopOpeBRepDS_DataStructure& DS = DatStr->DS(); + Standard_Integer j,i,nse = DS.NbSectionEdges(); + if (nse == 0) return; + + + TopoDS_Vertex V, sdeV1, sdeV2; + TopTools_MapOfShape MV; + TopTools_ListOfShape LSE; // list of section edges + TopoDS_Face dummyF; + + for (i = 1; i <= nse; i++) + { + const TopoDS_Edge & se = DS.SectionEdge(i); + if (! TopB.IsSplit(se,TopAbs_ON)) + continue; + LSE.Append( se ); + + // add vertices where section edges interferes with other + // edges as its descendant in myAsDes + + TopoDS_Edge sde, oe; // same domain, other edge + if (DatStr->HasSameDomain(se)) { + sde = TopoDS::Edge( DatStr->SameDomain(se).Value() ); + TopExp::Vertices( sde, sdeV1, sdeV2); + } + TColStd_MapOfInteger MIV; // indices of added edges + TopOpeBRepDS_PointIterator itP (DS.ShapeInterferences( se )); + itP.SupportKind( TopOpeBRepDS_EDGE ); + // loop on intersections of se + for (; itP.More(); itP.Next()) { + oe = TopoDS::Edge( DS.Shape( itP.Support())); + if (itP.IsVertex()) { + // there is a vertex at intersection + if ( !MIV.Add( itP.Current() )) + continue; + V = TopoDS::Vertex( DS.Shape( itP.Current())); + if ( !sde.IsNull() && (V.IsSame(sdeV1) || V.IsSame(sdeV2)) ) + oe = sde; + V = ReplaceSameDomainV( V , oe ); + V.Orientation( TopAbs_INTERNAL); + B.UpdateVertex( V, itP.Parameter(), se, 0.); // AddVonE() sets real U + } + else { + // create a new vertex at the intersection point + const TopOpeBRepDS_Point& DSP = DS.Point( itP.Current()); + V = BRepLib_MakeVertex( DSP.Point() ); + V.Orientation( TopAbs_INTERNAL); + B.UpdateVertex( V, itP.Parameter(), se, DSP.Tolerance()); + // make V be on the other edge + TopOpeBRepDS_PointIterator itOP (DS.ShapeInterferences( oe )); + for (; itOP.More(); itOP.Next()) { + const TopOpeBRepDS_Point& ODSP = DS.Point( itOP.Current()); + if ( DSP.IsEqual (ODSP)) { + B.UpdateVertex( V, itOP.Parameter(), TopoDS::Edge(oe), ODSP.Tolerance()); + break; + } + } + } + // add V on the both intersecting edges + TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes,dummyF); + if (!addedV.IsSame( V )) + mySameDomainVM.Bind (V, addedV); // equal vertex is already there + + MV.Add( addedV ); // to ease storage of vertices of ON splits + } + } + + // add section edge to the face it intersects and find + // splits ON that do not have same domain pair + + TopB.SplitSectionEdges(); // let TopB find ON splits + + TopTools_MapOfShape SPM; // map of ON splits + TopTools_IndexedMapOfShape ME[2]; + TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]); + TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]); + + TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE); + while ( itLSE.More() ) { + + TopoDS_Edge se = TopoDS::Edge( itLSE.Value() ); + + // move itLSE to the next se + Standard_Integer ancRank = DS.AncestorRank(se); + if (ME[ancRank-1].Contains( se )) + { + LSE.Remove( itLSE ); // se is an edge of face it intersects + continue; + } + else + { + itLSE.Next(); + } + + const TopoDS_Face& F = (ancRank == 1) ? F2 : F1; + + // add se to face but dont add twice + TopTools_ListIteratorOfListOfShape itE( myAsDes->Descendant( F )); + if (myAsDes->HasDescendant( F )) { + for ( ; itE.More(); itE.Next()) + if (se.IsSame( itE.Value() )) + break; + } + if (!itE.More()) + { + myAsDes->Add( F, se ); + + // check se pcurve on F + Standard_Real tol, f,l, umin=1e100, umax=-1e100; + Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( se, F, f,l); + if (pc.IsNull()) { + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) { + const TopoDS_Edge& E = TopoDS::Edge ( itSP.Value()); + BRep_Tool::Range(E, f, l); + umin = Min( umin, f); + umax = Max( umax, l); + } + Handle(Geom_Curve) C3d = BRep_Tool::Curve( se, f, l); + if (umin < umax) // sometimes umin == umax for closed edge + C3d = new Geom_TrimmedCurve( C3d, umin, umax); + pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol); + if (pc.IsNull()) { + //MESSAGE (" CANT BUILD PCURVE "); + } + B.UpdateEdge( se, pc, F, tol); + } + } + + // to detect splits that do not have same domain pair + // ie which split a face into parts and not pass by its boundary + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) { + const TopoDS_Shape& SP = itSP.Value(); + if (!SPM.Add( SP )) + SPM.Remove( SP ); + } + } + + // store vertices of ON splits and bind section edges to faces + + for (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next()) + { + const TopoDS_Shape& se = itLSE.Value(); + + Standard_Integer ancRank = DS.AncestorRank(se); + TopoDS_Face F = (ancRank == 1) ? F2 : F1; + + // add vertices of ON splits which have no same domain pair + Standard_Boolean added = Standard_False; + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) + { + if (!SPM.Contains( itSP.Value() )) + continue; + + const TopoDS_Edge& S = TopoDS::Edge ( itSP.Value()); + + added = Standard_True; + mySectionEdgesAD->Add( F, se ); + + TopoDS_Vertex VS[2]; + TopExp::Vertices (S, VS[0], VS[1]); + for (j=0; j<2; ++j) + { + if (mySameDomainVM.IsBound( VS[j] )) + VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] )); + if ( !MV.Contains( VS[j] )) { + // find equal vertex on se - point interference + gp_Pnt P1 = BRep_Tool::Pnt( VS[j] ); + TopTools_ListIteratorOfListOfShape itV( myAsDes->Descendant(se) ); + for (; itV.More(); itV.Next()) { + V = TopoDS::Vertex( itV.Value() ); + if ( V.IsSame( VS[j] )) + break; + gp_Pnt P2 = BRep_Tool::Pnt( V ); + if (P1.IsEqual( P2, Precision::Confusion())) { + mySameDomainVM.Bind (VS[j], V); + VS[j] = V; + break; + } + } + if (!itV.More()) // no interferences with edges + myAsDes->Add( se, VS[j]); + } + + // add ends of ON splits to F in order to detect later + // if a split is on face in IsSplitOn() + mySectionEdgesAD->Add( F, VS[j]); + } + // in the descendants of F, first go ends of an ON split and + // then a split itself + mySectionEdgesAD->Add( F, S ); + } + if (!added) + mySectionEdgesAD->Add( F, se ); + + myNewEdges.Add( se ); + } +} + +//======================================================================= +//function : FacesPartition +//purpose : +//======================================================================= + +void Partition_Inter3d::FacesPartition(const TopoDS_Face& F1, + const TopoDS_Face& F2) + //(const TopTools_DataMapOfShapeListOfShape& /*SetOfFaces2*/) +{ + TopTools_ListOfShape LInt; + + Inter3D (F1,F2,LInt); + + StorePart3d (F1,F2,LInt); +} + +//======================================================================= +//function : SetDone +//purpose : +//======================================================================= + +void Partition_Inter3d::SetDone(const TopoDS_Face& F1, + const TopoDS_Face& F2) +{ + if (!myDone.IsBound(F1)) { + TopTools_ListOfShape emptyList; + myDone.Bind(F1,emptyList); + } + myDone(F1).Append(F2); + if (!myDone.IsBound(F2)) { + TopTools_ListOfShape emptyList; + myDone.Bind(F2,emptyList); + } + myDone(F2).Append(F1); +} + +//======================================================================= +//function : IsDone +//purpose : +//======================================================================= + +Standard_Boolean Partition_Inter3d::IsDone(const TopoDS_Face& F1, + const TopoDS_Face& F2) + + const +{ + if (myDone.IsBound(F1)) { + TopTools_ListIteratorOfListOfShape it (myDone(F1)); + for (; it.More(); it.Next()) { + if (it.Value().IsSame(F2)) return Standard_True; + } + } + return Standard_False; +} + +//======================================================================= +//function : StorePart3d +//purpose : +//======================================================================= + +void Partition_Inter3d::StorePart3d(const TopoDS_Face& F1, + const TopoDS_Face& F2, + const TopTools_ListOfShape& LInt) +{ + if (!LInt.IsEmpty()) { + myAsDes->Add( F1,LInt); + myAsDes->Add( F2,LInt); + + TopTools_ListIteratorOfListOfShape it(LInt); + for (; it.More(); it.Next()) { + + TopoDS_Edge E = TopoDS::Edge(it.Value()); + + BRep_Builder B; + B.SameParameter(E,Standard_False); + BRepLib::SameParameter(E,1.0e-7); + + myNewEdges.Add(E); + } + } + SetDone(F1,F2); +} + +//======================================================================= +//function : TouchedFaces +//purpose : +//======================================================================= + +TopTools_MapOfShape& Partition_Inter3d::TouchedFaces() +{ + return myTouched; +} + +//======================================================================= +//function : AsDes +//purpose : +//======================================================================= + +Handle(BRepAlgo_AsDes) Partition_Inter3d::AsDes() const +{ + return myAsDes; +} + +//======================================================================= +//function : NewEdges +//purpose : +//======================================================================= + +TopTools_MapOfShape& Partition_Inter3d::NewEdges() +{ + return myNewEdges; +} + +//======================================================================= +//function : Affiche +//purpose : +//======================================================================= + +void Partition_Inter3d::Affiche(const TopTools_ListOfShape& SetOfFaces) const +{ +#ifdef DEB + char PSection[1024]; + char *section=PSection; + Standard_Integer i = 0; + Standard_Real j=1; + TopTools_ListOfShape aList; + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(SetOfFaces); it.More(); it.Next()) { + const TopoDS_Shape& OS = it.Value(); + aList=myAsDes->Descendant(OS); + MESSAGE ( " the number of items stored in the list " << j << " : " << aList.Extent() ) + j++; + TopTools_ListIteratorOfListOfShape itaList; + for (itaList.Initialize(aList); itaList.More(); itaList.Next()) { + const TopoDS_Shape& SS = itaList.Value(); + i++; + sprintf(PSection,"section_%d",i); + DBRep::Set(section,SS); + } + } +#endif +} + +//======================================================================= +//function : SameDomain +//purpose : +//======================================================================= + +const TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) const +{ + if (mySameDomainFM.IsBound( F )) + return mySameDomainFM (F); + + static TopTools_ListOfShape emptyList; + return emptyList; +} + +//======================================================================= +//function : HasSameDomainF +//purpose : Return true if F has same domain faces +//======================================================================= + +Standard_Boolean Partition_Inter3d::HasSameDomainF(const TopoDS_Shape& F) const +{ + return mySameDomainFM.IsBound( F ); +} + +//======================================================================= +//function : IsSameDomain +//purpose : Return true if F1 and F2 are same domain faces +//======================================================================= + +Standard_Boolean Partition_Inter3d::IsSameDomainF(const TopoDS_Shape& F1, + const TopoDS_Shape& F2) const +{ + if (mySameDomainFM.IsBound( F1 )) { + TopTools_ListIteratorOfListOfShape it (mySameDomainFM( F1 )); + for (; it.More(); it.Next()) + if (F2.IsSame( it.Value())) + return Standard_True; + } + return F1.IsSame( F2 ); +} + +//======================================================================= +//function : ReplaceSameDomainV +//purpose : return same domain vertex of V if it was replaced +// and make this vertex to be on E too, else return V +//======================================================================= + +TopoDS_Vertex Partition_Inter3d::ReplaceSameDomainV(const TopoDS_Vertex& V, + const TopoDS_Edge& E) const +{ + TopoDS_Vertex SDV = V; + if (mySameDomainVM.IsBound( V )) { + + TopoDS_Vertex V1,V2; + TopExp::Vertices(E,V1,V2); + Standard_Boolean isClosed = V1.IsSame( V2 ) && V.IsSame(V1); + + SDV = TopoDS::Vertex( mySameDomainVM(V) ); + Standard_Real tol = BRep_Tool::Tolerance( V ); + BRep_Builder B; + SDV.Orientation( V.Orientation()); + + if (isClosed) { + Standard_Real f, l; + BRep_Tool::Range (E, f, l); + Standard_Boolean isFirst = IsEqual( BRep_Tool::Parameter(V,E), f ); + B.UpdateVertex(SDV, (isFirst ? f : l), E, tol); + SDV.Reverse(); + B.UpdateVertex(SDV, (isFirst ? l : f), E, tol); + } + else + B.UpdateVertex (SDV, BRep_Tool::Parameter(V,E), E, tol); + + } + return SDV; +} + +//======================================================================= +//function : SectionEdgesAD +//purpose : +//======================================================================= + +Handle(BRepAlgo_AsDes) Partition_Inter3d::SectionEdgesAD() const +{ + return mySectionEdgesAD; +} + +//======================================================================= +//function : IsSectionEdge +//purpose : return True if E is an edge of a face and it +// intersects an other face +//======================================================================= + +Standard_Boolean + Partition_Inter3d::IsSectionEdge(const TopoDS_Edge& E) const +{ + return mySectionEdgesAD->HasAscendant(E); +} + +//======================================================================= +//function : HasSectionEdge +//purpose : return True if an edge of F intersects an other +// face or F is intersected by edge of an other face +//======================================================================= + +Standard_Boolean + Partition_Inter3d::HasSectionEdge(const TopoDS_Face& F) const +{ + return mySectionEdgesAD->HasDescendant(F); +} + +//======================================================================= +//function : IsSplitOn +//purpose : return True if NewE is split of OldE on F +//======================================================================= + +Standard_Boolean + Partition_Inter3d::IsSplitOn(const TopoDS_Edge& NewE, + const TopoDS_Edge& OldE, + const TopoDS_Face& F) const +{ + if (! mySectionEdgesAD->HasDescendant(F)) + return Standard_False; + + TopTools_ListIteratorOfListOfShape itE ( mySectionEdgesAD->Descendant(F) ); + for ( ; itE.More(); itE.Next()) { + if ( itE.Value().ShapeType() != TopAbs_EDGE || + ! OldE.IsSame ( itE.Value() )) + continue; + // an edge encountered, its vertices and a split come next + itE.Next(); + if (!itE.More()) break; + const TopoDS_Shape& V3 = itE.Value(); + if (V3.ShapeType() != TopAbs_VERTEX) continue; + itE.Next(); + if (!itE.More()) break; + const TopoDS_Shape& V4 = itE.Value(); + if (V4.ShapeType() != TopAbs_VERTEX) continue; + + TopoDS_Vertex V1, V2; + TopExp::Vertices( OldE, V1, V2); + + if ( V1.IsSame(V2) && + (V1.IsSame(V3) || V1.IsSame(V4)) ) { + // closed old edge; use the split for the test + itE.Next(); + if (!itE.More()) break; + const TopoDS_Edge& split = TopoDS::Edge( itE.Value() ); + // check distance at middle point of NewE + Standard_Real f1,l1, f2,l2; + Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface( split, F ,f1,l1); + if (!PC1.IsNull()) { + Handle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(NewE, F ,f2,l2); + gp_Pnt2d P = PC2->Value( 0.5*(f2+l2) ); + Geom2dAPI_ProjectPointOnCurve proj (P, PC1, f1, l1); + if (proj.NbPoints() && + proj.LowerDistance() <= Precision::Confusion()) + return Standard_True; + } + else { + Handle(Geom_Curve) C1 = BRep_Tool::Curve( split ,f1,l1); + Handle(Geom_Curve) C2 = BRep_Tool::Curve( NewE ,f2,l2); + gp_Pnt P = C2->Value( 0.5*(f2+l2) ); + GeomAPI_ProjectPointOnCurve proj (P, C1, f1, l1); + if (proj.NbPoints() && + proj.LowerDistance() <= Precision::Confusion()) + return Standard_True; + } + } + else { + Standard_Real u3 = BRep_Tool::Parameter( TopoDS::Vertex(V3), OldE); + Standard_Real u4 = BRep_Tool::Parameter( TopoDS::Vertex(V4), OldE); + + Standard_Real f,l, u; + BRep_Tool::Range( NewE, f,l); + u = 0.5*(f+l); + f = Min(u3,u4); + l = Max(u3,u4); + + if (u <= l && u >= f) + return Standard_True; + } + } + return Standard_False; +} + +//======================================================================= +//function : SectionEdgeFaces +//purpose : return faces cut by section edge +//======================================================================= + +const TopTools_ListOfShape& + Partition_Inter3d::SectionEdgeFaces(const TopoDS_Edge& SecE) const +{ + return mySectionEdgesAD->Ascendant( SecE ); +} + +#endif diff --git a/contrib/Salome/Partition_Inter3d.hxx b/contrib/Salome/Partition_Inter3d.hxx new file mode 100644 index 0000000000000000000000000000000000000000..d8be2c59837514d5a5dd8cd0b5846ab8513a4654 --- /dev/null +++ b/contrib/Salome/Partition_Inter3d.hxx @@ -0,0 +1,143 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter3d.hxx +// Module : GEOM + +#ifndef _Partition_Inter3d_HeaderFile +#define _Partition_Inter3d_HeaderFile + +#ifndef _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopTools_ListOfShape; +class TopTools_DataMapOfShapeShape; +class TopoDS_Face; +class TopTools_MapOfShape; +class TopoDS_Shape; +class TopoDS_Vertex; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Inter3d { + +public: + + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // Methods PUBLIC + // + Partition_Inter3d(); + Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes); + void CompletPart3d(const TopTools_ListOfShape& SetOfFaces1,const TopTools_DataMapOfShapeShape& FaceShapeMap) ; + void FacesPartition(const TopoDS_Face& F1,const TopoDS_Face& F2) ; + Standard_Boolean IsDone(const TopoDS_Face& F1,const TopoDS_Face& F2) const; + TopTools_MapOfShape& TouchedFaces() ; + Handle_BRepAlgo_AsDes AsDes() const; + TopTools_MapOfShape& NewEdges() ; + Standard_Boolean HasSameDomainF(const TopoDS_Shape& F) const; + Standard_Boolean IsSameDomainF(const TopoDS_Shape& F1,const TopoDS_Shape& F2) const; + const TopTools_ListOfShape& SameDomain(const TopoDS_Face& F) const; + TopoDS_Vertex ReplaceSameDomainV(const TopoDS_Vertex& V,const TopoDS_Edge& E) const; + Handle_BRepAlgo_AsDes SectionEdgesAD() const; + Standard_Boolean IsSectionEdge(const TopoDS_Edge& E) const; + Standard_Boolean HasSectionEdge(const TopoDS_Face& F) const; + Standard_Boolean IsSplitOn(const TopoDS_Edge& NewE,const TopoDS_Edge& OldE,const TopoDS_Face& F) const; + const TopTools_ListOfShape& SectionEdgeFaces(const TopoDS_Edge& SecE) const; + + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + void Inter3D(const TopoDS_Face& F1,const TopoDS_Face& F2,TopTools_ListOfShape& LInt) ; + void StorePart3d(const TopoDS_Face& F1,const TopoDS_Face& F2,const TopTools_ListOfShape& LInt1) ; + void SetDone(const TopoDS_Face& F1,const TopoDS_Face& F2) ; + void Affiche(const TopTools_ListOfShape& SetOfFaces) const; + + + // Fields PRIVATE + // + Handle_BRepAlgo_AsDes myAsDes; + TopTools_DataMapOfShapeListOfShape myDone; + TopTools_MapOfShape myTouched; + TopTools_MapOfShape myNewEdges; + Handle_BRepAlgo_AsDes mySectionEdgesAD; + TopTools_DataMapOfShapeListOfShape mySameDomainFM; + TopTools_DataMapOfShapeShape mySameDomainVM; + + +}; + + + + + +// other Inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Inter3d.ixx b/contrib/Salome/Partition_Inter3d.ixx new file mode 100644 index 0000000000000000000000000000000000000000..0775cc99c9259f7e8b85677f916546c9fd6aca20 --- /dev/null +++ b/contrib/Salome/Partition_Inter3d.ixx @@ -0,0 +1,31 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter3d.ixx +// Module : GEOM + +#include "Partition_Inter3d.jxx" + + + + diff --git a/contrib/Salome/Partition_Inter3d.jxx b/contrib/Salome/Partition_Inter3d.jxx new file mode 100644 index 0000000000000000000000000000000000000000..5804ba81e831c0a636bd6a8965e01f4011455ed6 --- /dev/null +++ b/contrib/Salome/Partition_Inter3d.jxx @@ -0,0 +1,53 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Inter3d.jxx +// Module : GEOM + +#ifndef _BRepAlgo_AsDes_HeaderFile +#include <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopoDS_Vertex_HeaderFile +#include <TopoDS_Vertex.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Inter3d_HeaderFile +#include "Partition_Inter3d.hxx" +#endif diff --git a/contrib/Salome/Partition_Loop.cxx b/contrib/Salome/Partition_Loop.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d293060e82061d969c9d44671f510174227c6fb3 --- /dev/null +++ b/contrib/Salome/Partition_Loop.cxx @@ -0,0 +1,478 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Loop.cxx +// Author : Benedicte MARTIN +// Module : GEOM +// $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ + +//using namespace std; +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +//using namespace std; +#include <cstdio> +#include <climits> + +#include "Partition_Loop.ixx" + +//#include "utilities.h" + +#include <BRep_Builder.hxx> +#include <BRepAlgo_FaceRestrictor.hxx> +#include <BRep_Tool.hxx> + +#include <Geom2d_Curve.hxx> +#include <Geom_Surface.hxx> + +#include <TopTools_SequenceOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfOrientedShape.hxx> +#include <TopTools_DataMapOfShapeShape.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> + +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> + +#include <TopoDS.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> +#include <TopoDS_Iterator.hxx> + +#include <Precision.hxx> +#include <BRep_TVertex.hxx> +#include <BRep_TEdge.hxx> + +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +static char* name = new char[100]; +static int nbe = 0; + +//======================================================================= +//function : Partition_Loop +//purpose : +//======================================================================= +Partition_Loop::Partition_Loop() +{ +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void Partition_Loop::Init(const TopoDS_Face& F) +{ + myConstEdges.Clear(); + myNewWires .Clear(); + myNewFaces .Clear(); + myFace = F; +} + +//======================================================================= +//function : AddConstEdge +//purpose : +//======================================================================= +void Partition_Loop::AddConstEdge (const TopoDS_Edge& E) +{ + myConstEdges.Append(E); +} + + +//======================================================================= +//function : FindDelta +//purpose : +//======================================================================= +static Standard_Real FindDelta(TopTools_ListOfShape& LE, + const TopoDS_Face& F) +{ + Standard_Real dist, f, l; + Standard_Real d = Precision::Infinite(); + TopTools_ListIteratorOfListOfShape itl; + + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l); + gp_Pnt2d p = C->Value(f); + gp_Pnt2d pp = C->Value(l); + Standard_Real d1 = p.Distance(pp); + if (d1<d) { d=d1;} + } + dist = d ; + return dist; +} + +//======================================================================= +//function : SelectEdge +//purpose : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>. +// <NE> Is erased of the list. If <CE> is too in the list <LE> +// with the same orientation, it's erased of the list +//======================================================================= +static Standard_Boolean SelectEdge(const TopoDS_Face& F, + const TopoDS_Edge& CE, + const TopoDS_Vertex& CV, + TopoDS_Edge& NE, + TopTools_ListOfShape& LE) +{ + TopTools_ListIteratorOfListOfShape itl; + NE.Nullify(); + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + if (itl.Value().IsEqual(CE)) { + LE.Remove(itl); + break; + } + } + + if (LE.Extent() > 1) { + //-------------------------------------------------------------- + // Several possible edges. + // - Test the edges differents of CE + //-------------------------------------------------------------- + Standard_Real cf, cl, f, l; + TopoDS_Face FForward = F; + Handle(Geom2d_Curve) Cc, C; + FForward.Orientation(TopAbs_FORWARD); + + Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl); + Standard_Real dist,distmin = 100*BRep_Tool::Tolerance(CV); + Standard_Real uc,u; + if (CE.Orientation () == TopAbs_FORWARD) uc = cl; + else uc = cf; + + gp_Pnt2d P2,PV = Cc->Value(uc); + + Standard_Real delta = FindDelta(LE,FForward); + + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + if (!E.IsSame(CE)) { + C = BRep_Tool::CurveOnSurface(E,FForward,f,l); + if (E.Orientation () == TopAbs_FORWARD) u = f; + else u = l; + P2 = C->Value(u); + dist = PV.Distance(P2); + if (dist <= distmin){ + distmin = dist; + } + + } + } + + Standard_Real anglemax = - PI; + TopoDS_Edge SelectedEdge; + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + if (!E.IsSame(CE)) { + C = BRep_Tool::CurveOnSurface(E,FForward,f,l); + if (E.Orientation () == TopAbs_FORWARD) u = f; + else u = l; + P2 = C->Value(u); + dist = PV.Distance(P2); + if (dist <= distmin + (1./3)*delta){ + gp_Pnt2d PC, P; + gp_Vec2d CTg1, CTg2, Tg1, Tg2; + Cc->D2(uc, PC, CTg1, CTg2); + C->D2(u, P, Tg1, Tg2); + + Standard_Real angle; + + if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) { + angle = CTg1.Angle(Tg1.Reversed()); + } + else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) { + angle = (CTg1.Reversed()).Angle(Tg1); + } + else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) { + angle = CTg1.Angle(Tg1); + } + else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) { + angle = (CTg1.Reversed()).Angle(Tg1.Reversed()); + } + if (angle >= anglemax) { + anglemax = angle ; + SelectedEdge = E; + } + } + } + } + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + if (E.IsEqual(SelectedEdge)) { + NE = TopoDS::Edge(E); + LE.Remove(itl); + break; + } + } + } + else if (LE.Extent() == 1) { + NE = TopoDS::Edge(LE.First()); + LE.RemoveFirst(); + } + else { + return Standard_False; + } + return Standard_True; +} + +//======================================================================= +//function : SamePnt2d +//purpose : +//======================================================================= +static Standard_Boolean SamePnt2d(TopoDS_Vertex V, + TopoDS_Edge& E1, + TopoDS_Edge& E2, + TopoDS_Face& F) +{ + Standard_Real f1,f2,l1,l2; + gp_Pnt2d P1,P2; + TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD); + TopoDS_Face FF = TopoDS::Face(aLocalF); + Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1); + Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2); + if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1); + else P1 = C1->Value(l1); + + if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2); + else P2 = C2->Value(f2); + Standard_Real Tol = 100*BRep_Tool::Tolerance(V); + Standard_Real Dist = P1.Distance(P2); + return Dist < Tol; +} + +//======================================================================= +//function : PurgeNewEdges +//purpose : +//======================================================================= +static void PurgeNewEdges(TopTools_ListOfShape& ConstEdges, + const TopTools_MapOfOrientedShape& UsedEdges) +{ + TopTools_ListIteratorOfListOfShape it(ConstEdges); + while ( it.More()) { + const TopoDS_Shape& NE = it.Value(); + if (!UsedEdges.Contains(NE)) { + ConstEdges.Remove(it); + } + else { + it.Next(); + } + } +} + +//======================================================================= +//function : StoreInMVE +//purpose : +//======================================================================= +static void StoreInMVE (const TopoDS_Face& F, + TopoDS_Edge& E, + TopTools_DataMapOfShapeListOfShape& MVE ) + +{ + TopoDS_Vertex V1, V2; + TopTools_ListOfShape Empty; + + TopExp::Vertices(E,V1,V2); + if (!MVE.IsBound(V1)) { + MVE.Bind(V1,Empty); + } + MVE(V1).Append(E); + + if (!MVE.IsBound(V2)) { + MVE.Bind(V2,Empty); + } + MVE(V2).Append(E); +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void Partition_Loop::Perform() +{ + + TopTools_DataMapOfShapeListOfShape MVE; + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit, Mapit1; + TopTools_ListIteratorOfListOfShape itl; + TopoDS_Vertex V1,V2; + + //----------------------------------- + // Construction map vertex => edges + //----------------------------------- + for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) { + TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + StoreInMVE(myFace,E,MVE); + } + + //---------------------------------------------- + // Construction of all the wires and of all the new faces. + //---------------------------------------------- + TopTools_MapOfOrientedShape UsedEdges; + + while (!MVE.IsEmpty()) { + TopoDS_Vertex VF,CV; + TopoDS_Edge CE,NE,EF; + TopoDS_Wire NW; + BRep_Builder B; + Standard_Boolean End= Standard_False; + + B.MakeWire(NW); + //-------------------------------- + // EF first edge. + //-------------------------------- + Mapit.Initialize(MVE); + EF = CE = TopoDS::Edge(Mapit.Value().First()); + + TopExp::Vertices(CE,V1,V2); + //-------------------------------- + // VF first vertex + //-------------------------------- + if (CE.Orientation() == TopAbs_FORWARD) { + CV = VF = V1; + } + else { + CV = VF = V2; + } + if (!MVE.IsBound(CV)) continue; + for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { + if (itl.Value().IsEqual(CE)) { + MVE(CV).Remove(itl); + break; + } + } + + int i = 0; + while (!End) { + //------------------------------- + // Construction of a wire. + //------------------------------- + TopExp::Vertices(CE,V1,V2); + if (!CV.IsSame(V1)) CV = V1; else CV = V2; + B.Add (NW,CE); + UsedEdges.Add(CE); + + //-------------- + // stop test + //-------------- + if (!MVE.IsBound(CV) || MVE(CV).IsEmpty() || CV.IsSame(VF) ) { + if (CV.IsSame(VF)) { + if (MVE(CV).Extent() == 1 ) MVE.UnBind(CV); + else { + for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { + if (itl.Value().IsEqual(CE)) { + MVE(CV).Remove(itl); + break; + } + } + } + } + End=Standard_True; + } + + //-------------- + // select edge + //-------------- + else { + Standard_Boolean find = SelectEdge(myFace,CE,CV,NE,MVE(CV)); + if (find) { + CE=NE; + if (MVE(CV).IsEmpty()) MVE.UnBind(CV); + if (CE.IsNull() ) { + //MESSAGE ( " CE is NULL !!! " ) + End=Standard_True; + } + } + else { + //MESSAGE ( " edge doesn't exist " ) + End=Standard_True; + } + } + } + + //----------------------------- + // Test if the wire is closed + //----------------------------- + if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace)) { + } + else{ + //MESSAGE ( "wire not closed" ) + } + myNewWires.Append (NW); + } + + PurgeNewEdges(myConstEdges,UsedEdges); + +} + + +//======================================================================= +//function : NewWires +//purpose : +//======================================================================= +const TopTools_ListOfShape& Partition_Loop::NewWires() const +{ + return myNewWires; +} + +//======================================================================= +//function : NewFaces +//purpose : +//======================================================================= +const TopTools_ListOfShape& Partition_Loop::NewFaces() const +{ + return myNewFaces; +} + +//======================================================================= +//function : WiresToFaces +//purpose : +//======================================================================= +void Partition_Loop::WiresToFaces() +{ + if (!myNewWires.IsEmpty()) { + BRepAlgo_FaceRestrictor FR; + + TopAbs_Orientation OriF = myFace.Orientation(); + TopoDS_Shape aLocalS = myFace.Oriented(TopAbs_FORWARD); + + FR.Init (TopoDS::Face(aLocalS),Standard_False); + TopTools_ListIteratorOfListOfShape it(myNewWires); + for (; it.More(); it.Next()) { + FR.Add(TopoDS::Wire(it.Value())); + } + + FR.Perform(); + + if (FR.IsDone()) { + for (; FR.More(); FR.Next()) { + myNewFaces.Append(FR.Current().Oriented(OriF)); + } + } + } +} + + +#endif diff --git a/contrib/Salome/Partition_Loop.hxx b/contrib/Salome/Partition_Loop.hxx new file mode 100644 index 0000000000000000000000000000000000000000..56e05e260bf5c0486f9e66943f87090800fbf52d --- /dev/null +++ b/contrib/Salome/Partition_Loop.hxx @@ -0,0 +1,118 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Loop.hxx +// Module : GEOM + +#ifndef _Partition_Loop_HeaderFile +#define _Partition_Loop_HeaderFile + +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#endif +class TopoDS_Face; +class TopoDS_Edge; +class TopTools_ListOfShape; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Loop { + +public: + + inline void* operator new(size_t,void* anAddress) + { + return anAddress; + } + inline void* operator new(size_t size) + { + return Standard::Allocate(size); + } + inline void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // inline void operator delete(void *anAddress, size_t size) + // { + // if (anAddress) Standard::Free((Standard_Address&)anAddress,size); + // } + // Methods PUBLIC + // + Partition_Loop(); + void Init(const TopoDS_Face& F) ; + void AddConstEdge(const TopoDS_Edge& E) ; + void Perform() ; + const TopTools_ListOfShape& NewWires() const; + void WiresToFaces() ; + const TopTools_ListOfShape& NewFaces() const; + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + + + // Fields PRIVATE + // + TopoDS_Face myFace; + TopTools_ListOfShape myConstEdges; + TopTools_ListOfShape myNewWires; + TopTools_ListOfShape myNewFaces; + + +}; + + + + + +// other inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Loop.ixx b/contrib/Salome/Partition_Loop.ixx new file mode 100644 index 0000000000000000000000000000000000000000..1c40e72540c987da0b82df3b8754ea72add677d1 --- /dev/null +++ b/contrib/Salome/Partition_Loop.ixx @@ -0,0 +1,31 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Loop.ixx +// Module : GEOM + +#include "Partition_Loop.jxx" + + + + diff --git a/contrib/Salome/Partition_Loop.jxx b/contrib/Salome/Partition_Loop.jxx new file mode 100644 index 0000000000000000000000000000000000000000..dd86f05c3d83bea2f5f581673fa79f67bc153a14 --- /dev/null +++ b/contrib/Salome/Partition_Loop.jxx @@ -0,0 +1,41 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Loop.jxx +// Module : GEOM + +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Partition_Loop_HeaderFile +#include "Partition_Loop.hxx" +#endif diff --git a/contrib/Salome/Partition_Loop2d.cxx b/contrib/Salome/Partition_Loop2d.cxx new file mode 100644 index 0000000000000000000000000000000000000000..71dcce2919cd892b9d2c85e8cca3f8b53e0bd3e4 --- /dev/null +++ b/contrib/Salome/Partition_Loop2d.cxx @@ -0,0 +1,1156 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R& D +// +// +// +// File : Partition_Loop2d.cxx +// Author : Benedicte MARTIN +// Module : GEOM +// $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop2d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ + +//using namespace std; +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +//using namespace std; +#include <climits> +#include "Partition_Loop2d.ixx" + +//#include "utilities.h" +#include <stdio.h> + +#include <BRepAdaptor_Curve2d.hxx> +#include <BRepAdaptor_Surface.hxx> +#include <BRepAlgo_AsDes.hxx> +#include <BRepAlgo_FaceRestrictor.hxx> +#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) +#include <BRepOffset_DataMapOfShapeReal.hxx> +#else +#include <TopTools_DataMapOfShapeReal.hxx> +#endif +#include <BRepTopAdaptor_FClass2d.hxx> +#include <BRep_Builder.hxx> +#include <BRep_Tool.hxx> +#include <Geom2dInt_GInter.hxx> +#include <Geom2d_Curve.hxx> +#include <IntRes2d_IntersectionPoint.hxx> +#include <Precision.hxx> +#include <TColStd_MapOfInteger.hxx> +#include <TColStd_SequenceOfReal.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> +#include <TopTools_DataMapOfShapeInteger.hxx> +#include <TopTools_DataMapOfShapeShape.hxx> +#include <TopTools_IndexedMapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_MapOfOrientedShape.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_SequenceOfShape.hxx> +#include <TopoDS.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> + +//======================================================================= +//function : Partition_Loop2d +//purpose : +//======================================================================= + +Partition_Loop2d::Partition_Loop2d() +{ +} + +//======================================================================= +//function : Init +//purpose : Init with <F> the set of edges must have +// pcurves on <F>. +//======================================================================= + +void Partition_Loop2d::Init(const TopoDS_Face& F) +{ + myConstEdges.Clear(); + myNewWires .Clear(); + myNewFaces .Clear(); + myFace = F; + myFaceOri = myFace.Orientation(); + myFace.Orientation( TopAbs_FORWARD ); +} + +//======================================================================= +//function : AddConstEdge +//purpose : Add <E> as unique edge in the result. +//======================================================================= + +void Partition_Loop2d::AddConstEdge (const TopoDS_Edge& E) +{ +#ifdef DEB + Standard_Real f,l; + Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); + if (pc.IsNull()) { + INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE"); + } else +#endif + { + myConstEdges.Append(E); + } +} + +void Partition_Loop2d::AddSectionEdge (const TopoDS_Edge& E) +{ +#ifdef DEB + Standard_Real f,l; + Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); + if (pc.IsNull()) + pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); + gp_Vec2d Tg1; + gp_Pnt2d PC; + pc->D1(0.5*(f+l), PC, Tg1); + if (Tg1.Magnitude() <= gp::Resolution()) { + MESSAGE (""); + } + if (pc.IsNull()) { + INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE"); + } else +#endif + { + myConstEdges.Append(E); + myConstEdges.Append(E.Reversed()); + mySectionEdges.Add( E ); + } +} + +//======================================================================= +//function : preciseU +//purpose : find u such that the 3D point on theE is just out of tolerance +// of theV +//======================================================================= + +static Standard_Real preciseU (const BRepAdaptor_Surface& theSurf, + const TopoDS_Edge& theE, + const TopoDS_Vertex& theV, + const Handle(Geom2d_Curve)& theC, + const Standard_Boolean theFirstEnd) +{ + Standard_Boolean isForward = ( theE.Orientation () == TopAbs_FORWARD ); + if (theFirstEnd) isForward = !isForward; + + // find the first point in 2d and 3d + Standard_Real f,l; + BRep_Tool::Range( theE, f, l ); + Standard_Real u0 = isForward ? l : f; + gp_Pnt2d aP2d0 = theC->Value( u0 ); + gp_Pnt aPnt0 = theSurf.Value( aP2d0.X(), aP2d0.Y() ); + + // shift in 2d and 3d + Standard_Real du = ( l - f ) / 100, du3d = 0; + if (isForward) + du = -du; + + // target parameter + Standard_Real u; + + while (du3d < ::RealSmall()) + { + // u for test + u = u0 + du; + du *= 10; // for the next iteration: increase du untill du3d is large enough + + // find out how u is far from u0 in 3D + gp_Pnt2d aP2d = theC->Value( u ); + gp_Pnt aPnt = theSurf.Value( aP2d.X(), aP2d.Y() ); + du3d = aPnt0.Distance( aPnt ); + } + + // find u such that the 3D point is just out of tolerance of theV + Standard_Real tolV = BRep_Tool::Tolerance( theV ) + Precision::Confusion(); + u = u0 + du * tolV / du3d; + + // check that u is within the range + if ( isForward ? (u < f) : (u > l) ) + u = u0 + du; + + return u; +} + +//======================================================================= +//function : SelectEdge +//purpose : Find in the list <LE> the edge <NE> connected with <CE> by +// the vertex <CV>. +// <NE> is removed from the list. If <CE> is in <LE> +// with the same orientation, it's removed from the list +//======================================================================= + +static Standard_Boolean SelectEdge(const BRepAdaptor_Surface& Surf, + const TopoDS_Edge& CE, + const TopoDS_Vertex& CV, + TopoDS_Edge& NE, + const TopTools_ListOfShape& LE) +{ + NE.Nullify(); + + if (LE.Extent() > 1) { + //-------------------------------------------------------------- + // Several possible edges. + // - Test the edges differents of CE + //-------------------------------------------------------------- + TopoDS_Face FForward = Surf.Face(); + TopoDS_Edge aPrevNE; + + gp_Vec2d CTg1, Tg1, CTg2, Tg2; + gp_Pnt2d PC, P; + + Standard_Real f, l; + Handle(Geom2d_Curve) Cc, C; + Cc = BRep_Tool::CurveOnSurface(CE,FForward,f,l); + + Standard_Boolean isForward = ( CE.Orientation () == TopAbs_FORWARD ); + Standard_Real uc, u, du = Precision::PConfusion(); + uc = isForward ? ( l - du ) : ( f + du ); + Cc->D1(uc, PC, CTg1); + if (!isForward) CTg1.Reverse(); + + Standard_Real anglemin = 3 * PI, tolAng = 1.e-8; + + // select an edge whose first derivative is most left of CTg1 + // ie an angle between Tg1 and CTg1 is least + TopTools_ListIteratorOfListOfShape itl; + for ( itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + if (E.IsSame(CE)) + continue; + if (! CV.IsSame( TopExp::FirstVertex( E, Standard_True ))) + continue; + + isForward = ( E.Orientation () == TopAbs_FORWARD ); + + // get E curve + C = BRep_Tool::CurveOnSurface(E,FForward,f,l); + // get the first derivative Tg1 + u = isForward ? ( f + du ) : ( l - du ); + C->D1(u, P, Tg1); + if (!isForward) Tg1.Reverse(); + + // -PI < angle < PI + Standard_Real angle = Tg1.Angle(CTg1); + + if (PI - Abs(angle) <= tolAng) + { + // an angle is too close to PI; assure that an angle sign really + // reflects an edge position: +PI - an edge is worst, + // -PI - an edge is best. + u = preciseU( Surf, CE, CV, Cc, Standard_False); + gp_Vec2d CTg; + Cc->D1(u, PC, CTg); + if (CE.Orientation() == TopAbs_REVERSED) CTg.Reverse(); + + u = preciseU( Surf, E, CV, C, Standard_True); + C->D1(u, P, Tg1); + if (!isForward) Tg1.Reverse(); + + angle = Tg1.Angle(CTg); + } + + Standard_Boolean isClose = ( Abs( angle - anglemin ) <= tolAng ); + if (angle <= anglemin) { + if (isClose) + aPrevNE = NE; + else + aPrevNE.Nullify(); + anglemin = angle ; + NE = E; + } + else + if (isClose) + aPrevNE = E; + + } + if (!aPrevNE.IsNull()) { + // select one of close edges, the most left one. + Cc = BRep_Tool::CurveOnSurface( NE, FForward, f, l ); + uc = preciseU( Surf, NE, CV, Cc, Standard_True); + Cc->D1(uc, PC, CTg1); + if (NE.Orientation() != TopAbs_FORWARD) CTg1.Reverse(); + + u = preciseU( Surf, aPrevNE, CV, C, Standard_True); + C->D1(u, P, Tg1); + if (aPrevNE.Orientation() != TopAbs_FORWARD) Tg1.Reverse(); + + if ( Tg1.Angle(CTg1) < 0) + NE = aPrevNE; + } + } + else if (LE.Extent() == 1) { + NE = TopoDS::Edge(LE.First()); + } + else { + return Standard_False; + } + return !NE.IsNull(); +} + +//======================================================================= +//function : SamePnt2d +//purpose : +//======================================================================= + +static Standard_Boolean SamePnt2d(const TopoDS_Vertex& V1, + const TopoDS_Edge& E1, + const TopoDS_Vertex& V2, + const TopoDS_Edge& E2, + const TopoDS_Face& F) +{ + Standard_Real f1,f2,l1,l2; + Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,F,f1,l1); + Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,F,f2,l2); + + gp_Pnt2d P1 = C1->Value( BRep_Tool::Parameter(V1,E1)); + gp_Pnt2d P2 = C2->Value( BRep_Tool::Parameter(V2,E2)); + + Standard_Real Tol = 100 * BRep_Tool::Tolerance(V1); + Standard_Real Dist = P1.Distance(P2); + return Dist < Tol; +} + + +//======================================================================= +//function : StoreInMVE +//purpose : +//======================================================================= + +static void StoreInMVE (const TopoDS_Face& /*F*/, + TopoDS_Edge& E, + TopTools_DataMapOfShapeListOfShape& MVE ) + +{ + TopoDS_Vertex V1, V2; + TopTools_ListOfShape Empty; + + TopExp::Vertices(E,V1,V2); + if (!MVE.IsBound(V1)) { + MVE.Bind(V1,Empty); + } + MVE(V1).Append(E); + + if (!MVE.IsBound(V2)) { + MVE.Bind(V2,Empty); + } + MVE(V2).Append(E); +} + +//======================================================================= +//function : RemoveFromMVE +//purpose : +//======================================================================= + +static void RemoveFromMVE(const TopoDS_Edge& E, + TopTools_DataMapOfShapeListOfShape& MVE) +{ + TopTools_ListIteratorOfListOfShape itl; + TopoDS_Vertex V1,V2; + TopExp::Vertices (E,V1,V2); + if (MVE.IsBound(V1)) + for ( itl.Initialize(MVE(V1)); itl.More(); itl.Next()) { + if (itl.Value().IsEqual(E)) { + MVE(V1).Remove(itl); + break; + } + } + if (MVE.IsBound(V2)) + for ( itl.Initialize(MVE(V2)); itl.More(); itl.Next()) { + if (itl.Value().IsEqual(E)) { + MVE(V2).Remove(itl); + break; + } + } +} +//======================================================================= +//function : addConnected +//purpose : add to <EM> all edges reachable from <E> +//======================================================================= + +static void addConnected(const TopoDS_Shape& E, + TopTools_MapOfShape& EM, + TopTools_MapOfShape& VM, + const TopTools_DataMapOfShapeListOfShape& MVE) +{ + // Loop on vertices of E + TopoDS_Iterator itV ( E ); + for ( ; itV.More(); itV.Next()) { + + if ( ! VM.Add ( itV.Value() )) continue; + + // Loop on edges sharing V + TopTools_ListIteratorOfListOfShape itE( MVE( itV.Value() ) ); + for (; itE.More(); itE.Next()) { + if ( EM.Add( itE.Value() )) + addConnected ( itE.Value(), EM, VM, MVE ); + } + } +} +//======================================================================= +//function : canPassToOld +//purpose : +//======================================================================= + +// static Standard_Boolean canPassToOld (const TopoDS_Shape& V, +// TopTools_MapOfShape& UsedShapesMap, +// const TopTools_DataMapOfShapeListOfShape& MVE, +// const TopTools_MapOfShape& SectionEdgesMap) +// { +// TopTools_ListIteratorOfListOfShape itE( MVE(V) ); +// // Loop on edges sharing V +// for (; itE.More(); itE.Next()) { +// if ( !UsedShapesMap.Add( itE.Value() )) +// continue; // already checked + +// if ( !SectionEdgesMap.Contains( itE.Value() )) +// return Standard_True; // WE PASSED + +// TopoDS_Iterator itV( itE.Value() ); +// // Loop on vertices of an edge +// for (; itV.More(); itV.Next()) { +// if ( !UsedShapesMap.Add( itV.Value() )) +// continue; // already checked +// else +// return canPassToOld( itV.Value(), UsedShapesMap, MVE, SectionEdgesMap); +// } +// } +// return Standard_False; +// } + +//======================================================================= +//function : MakeDegenAndSelect +//purpose : Find parameter of intersection of <CE> with <DE> and +// select an edge with its parameter closest to found one. +// Return new degenerated edge trimming <DE> by found parameters +//======================================================================= + +static TopoDS_Edge MakeDegenAndSelect(const TopoDS_Edge& CE, + const TopoDS_Vertex& CV, + TopoDS_Edge& NE, + TopTools_SequenceOfShape& EdgesSeq, + TColStd_SequenceOfReal& USeq, + const TopoDS_Edge& DE) +{ + if (EdgesSeq.Length() < 3) { + if (CE == EdgesSeq.First()) + NE = TopoDS::Edge( EdgesSeq.Last() ); + else + NE = TopoDS::Edge( EdgesSeq.First() ); + return DE; + } + + // find parameter on DE where it intersects CE + + Standard_Real U1; + Standard_Integer i, nb = EdgesSeq.Length(); + for (i=1; i<= nb; ++i) { + if (CE == EdgesSeq(i)) { + U1 = USeq(i); + break; + } + } + + // select NE with param closest to U1 thus finding U2 for a new degen edge + + Standard_Real U2, dU, dUmin = 1.e100; + Standard_Boolean isReversed = ( DE.Orientation() == TopAbs_REVERSED ); + for (i=1; i<= nb; ++i) { + dU = USeq(i) - U1; + if (isReversed ? (dU > 0) : (dU < 0)) + continue; + dU = Abs( dU ); + if ( dU > dUmin || IsEqual( dU, 0.)) + continue; + const TopoDS_Edge& E = TopoDS::Edge ( EdgesSeq(i) ); + if ( ! CV.IsSame( TopExp::FirstVertex( E , Standard_True ))) + continue; + NE = E; + dUmin = dU + Epsilon(dU); + U2 = USeq(i); + } + + // make a new degenerated edge + TopoDS_Edge NewDegen = TopoDS::Edge ( DE.EmptyCopied() ); + + Standard_Real Tol = BRep_Tool::Tolerance( CV ); + TopoDS_Vertex V = CV; + + BRep_Builder B; + V.Orientation( NewDegen.Orientation() ); + B.UpdateVertex( V, U1, NewDegen, Tol); + B.Add ( NewDegen , V ); + + V.Reverse(); + B.UpdateVertex( V, U2, NewDegen, Tol); + B.Add ( NewDegen , V ); + + return NewDegen; +} + +//======================================================================= +//function : prepareDegen +//purpose : Intersect <DegEdge> with edges bound to its vertex in <MVE> +// and store intersection parameter on <DegEdge> in +// <USeq> as well as the edges them-self in <EdgesSeq>. +// Bind <DegEdgeIndex> to vertex of <DegEdge> in <MVDEI> +//======================================================================= + +static void prepareDegen (const TopoDS_Edge& DegEdge, + const TopoDS_Face& F, + const TopTools_DataMapOfShapeListOfShape& MVE, + TopTools_SequenceOfShape& EdgesSeq, + TColStd_SequenceOfReal& USeq, + TopTools_DataMapOfShapeInteger& MVDEI, + const Standard_Integer DegEdgeIndex) +{ + const TopoDS_Vertex& V = TopExp::FirstVertex ( DegEdge ); + MVDEI.Bind ( V, DegEdgeIndex ); + + const TopTools_ListOfShape& EdgesList = MVE ( V ); + // if only 2 edges come to degenerated one, no pb in selection and + // no need to intersect them, just simulate asked data + Standard_Boolean doIntersect = ( EdgesList.Extent() > 2 ); + + BRepAdaptor_Curve2d DC, C; + Geom2dInt_GInter InterCC; + Standard_Real Tol = Precision::PConfusion(); + if ( doIntersect ) + DC.Initialize( DegEdge, F ); + + // avoid intersecting twice the same edge +#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) + BRepOffset_DataMapOfShapeReal EUMap ( EdgesList.Extent() ); +#else + TopTools_DataMapOfShapeReal EUMap ( EdgesList.Extent() ); +#endif + + Standard_Real U, f, l; + BRep_Tool::Range (DegEdge, f, l); + + TopTools_ListIteratorOfListOfShape itE (EdgesList); + for (; itE.More(); itE.Next()) { + + const TopoDS_Edge& E = TopoDS::Edge ( itE.Value() ); + + if ( !doIntersect) { + U = 0.; // it won't be used + } + else if ( BRep_Tool::IsClosed( E, F )) { + // seam edge: select U among f and l + Standard_Boolean first = Standard_True; + if ( V.IsSame ( TopExp::FirstVertex( E, Standard_True ) )) + first = Standard_False; + if ( DegEdge.Orientation() == TopAbs_REVERSED ) + first = !first; + U = first ? f : l; + } + else if ( EUMap.IsBound( E ) ) { + // same edge already bound + U = EUMap( E ); + } + else { + // intersect 2d curves + C.Initialize( E, F ); + InterCC.Perform ( DC, C , Tol, Tol ); + if (! InterCC.IsDone() || InterCC.NbPoints() == 0) { + //MESSAGE ( "NO 2d INTERSECTION ON DEGENERATED EDGE" ); + continue; + } + // hope there is only one point of intersection + U = InterCC.Point( 1 ).ParamOnFirst(); + } + USeq.Append ( U ); + EdgesSeq.Append ( E ); + } +} +//======================================================================= +//function : Perform +//purpose : Make loops. +//======================================================================= + +void Partition_Loop2d::Perform() +{ + + Standard_Integer NbConstEdges = myConstEdges.Extent(); + TopTools_DataMapOfShapeListOfShape MVE(NbConstEdges) , MVE2(NbConstEdges); + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit; + TopTools_ListIteratorOfListOfShape itl; + TopoDS_Vertex V1,V2; + BRepAdaptor_Surface Surface ( myFace, Standard_False ); + + // degenerated edges and parameters of their 2d intersection with other edges + TopoDS_Edge DE [2]; + TopTools_SequenceOfShape SEID [2]; // seq of edges intersecting degenerated + TColStd_SequenceOfReal SeqU [2]; // n-th U corresponds to n-th edge in SEID + TopTools_DataMapOfShapeInteger MVDEI(2); // map vertex - degenerated edge index + Standard_Integer iDeg = 0; // index of degenerated edge [0,1] + + //--------------------------------------------------------- + // Construction map vertex => edges, find degenerated edges + //--------------------------------------------------------- + for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) { + TopoDS_Edge& E = TopoDS::Edge(itl.Value()); + if ( BRep_Tool::Degenerated( E )) { + if (DE[0].IsNull()) DE[0] = E; + else DE[1] = E; + } + else + StoreInMVE(myFace,E,MVE); + } + + // fill data for degenerated edges + if ( ! DE[0].IsNull() ) + prepareDegen ( DE[0], myFace, MVE, SEID[0], SeqU[0], MVDEI, 0); + if ( ! DE[1].IsNull() ) + prepareDegen ( DE[1], myFace, MVE, SEID[1], SeqU[1], MVDEI, 1); + + + // to detect internal wires + Standard_Boolean isInternCW = 0; + MVE2 = MVE; + + + //------------------------------ + // Construction of all the wires + //------------------------------ + // first, we collect wire edges in WEL list looking for same edges that + // will be then removed possibly exploding a wire into parts; + // second, build wire(s) + + while (!MVE.IsEmpty()) { + + TopoDS_Vertex VF,CV; + TopoDS_Edge CE,NE,EF; + TopoDS_Wire NW; + BRep_Builder B; + Standard_Boolean End = Standard_False; + TopTools_ListOfShape WEL; + + Mapit.Initialize(MVE); + if (Mapit.Value().IsEmpty()) { + MVE.UnBind(Mapit.Key()); + continue; + } + + // EF first edge. + EF = CE = TopoDS::Edge(Mapit.Value().First()); + // VF first vertex + VF = TopExp::FirstVertex( CE, Standard_True); + + isInternCW = Standard_True; + + TopTools_MapOfShape addedEM (NbConstEdges); // map of edges added to WEL + TopTools_MapOfShape doubleEM (NbConstEdges); // edges encountered twice in WEL + + //------------------------------- + // Construction of a wire. + //------------------------------- + while (!End) { + + // only a seam is allowed twice in a wire, the others should be removed + if (addedEM.Add ( CE ) || BRep_Tool::IsClosed( CE, myFace ) ) + WEL.Append( CE ); + else { + doubleEM.Add( CE ); + RemoveFromMVE (CE,MVE2); + TopoDS_Edge CERev = CE; + CERev.Reverse(); + RemoveFromMVE (CERev,MVE2); + } + + RemoveFromMVE (CE,MVE); + + CV = TopExp::LastVertex( CE, Standard_True); + + if (isInternCW && !mySectionEdges.Contains(CE)) + // wire is internal if all edges are section ones + isInternCW = Standard_False; + + if (MVDEI.IsBound( CV )) { // CE comes to the degeneration + iDeg = MVDEI( CV ); + TopoDS_Edge NewDegen; + NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]); + WEL.Append( NewDegen ); + CE = NE; + End = CV.IsSame( VF ); + continue; + } + + //-------------- + // stop test + //-------------- + if (MVE(CV).IsEmpty()) { + End=Standard_True; + MVE.UnBind(CV); + } + else if (CV.IsSame(VF) && SamePnt2d(CV,CE, VF,EF, myFace) ) { + End = Standard_True; + } + else { + //---------------------------- + // select new current edge + //---------------------------- + if (! SelectEdge (Surface,CE,CV,NE,MVE(CV))) { + //MESSAGE ( " NOT CLOSED WIRE " ); + End=Standard_True; + } + else + CE = NE; + } + } // while ( !End ) + + + // WEL is built, built wire(s) + + + itl.Initialize( WEL ); + if ( doubleEM.IsEmpty()) { // no double edges + B.MakeWire( NW ); + for (; itl.More(); itl.Next()) + B.Add ( NW, itl.Value()); + if (isInternCW) myInternalWL.Append(NW); + else myNewWires.Append (NW); + } + + else { + // remove double and degenerated edges from WEL + while (itl.More()) { + const TopoDS_Edge& E = TopoDS::Edge ( itl.Value() ); + if ( doubleEM.Contains( E ) || BRep_Tool::Degenerated( E )) + WEL.Remove( itl ); + else + itl.Next(); + } + if ( WEL.IsEmpty()) + continue; + // remove double edges from SEID and SeqU + Standard_Integer i,j; + for (j=0; j<2; ++j) { + for (i=1; i<=SEID[j].Length(); ++i) { + if (doubleEM.Contains( SEID[j].Value(i))) { + SEID[j].Remove( i ); + SeqU[j].Remove( i-- ); + } + } + } + // removal of doulbe edges can explode a wire into parts, + // make new wires of them. + // A Loop like previous one but without 2d check + while ( !WEL.IsEmpty() ) { + CE = TopoDS::Edge( WEL.First() ); + WEL.RemoveFirst(); + B.MakeWire( NW ); + VF = TopExp::FirstVertex ( CE, Standard_True); + + End = Standard_False; + while ( !End) { + B.Add( NW, CE ); + CV = TopExp::LastVertex ( CE, Standard_True); + + if (MVDEI.IsBound( CV )) { // CE comes to the degeneration + iDeg = MVDEI( CV ); + TopoDS_Edge NewDegen; + NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]); + B.Add( NW, NewDegen ); + End = CV.IsSame( VF ); + CE = NE; + if (!NE.IsNull()) { // remove NE from WEL + for (itl.Initialize( WEL ); itl.More(); itl.Next()) + if ( NE == itl.Value()) { + WEL.Remove( itl ); + break; + } + } + } // end degeneration + + else { + if (CV.IsSame( VF )) { + End = Standard_True; + continue; + } + // edges in WEL most often are well ordered + // so try to iterate until the End + Standard_Boolean add = Standard_False; + itl.Initialize(WEL); + while ( itl.More() && !End) { + NE = TopoDS::Edge( itl.Value() ); + if ( CV.IsSame( TopExp::FirstVertex( NE, Standard_True ))) { + WEL.Remove( itl ); + if (add) + B.Add( NW, CE ); + CE = NE; + add = Standard_True; + CV = TopExp::LastVertex( CE, Standard_True); + if (MVDEI.IsBound( CV ) || CV.IsSame( VF )) + break; + } + else + itl.Next(); + } + if (!add) + End = Standard_True; + } + } // !End + + myInternalWL.Append( NW ); + } + } // end building new wire(s) from WEL + + } // end Loop on MVE + + // all wires are built + + + // ============================================================ + // select really internal wires i.e. those from which we can`t + // pass to an old (not section) edge + // ============================================================ + + Standard_Integer nbIW = myInternalWL.Extent(); + if (nbIW == 0) + return; + + if ( myNewWires.Extent() != 1 && nbIW > 1) { + TopTools_MapOfShape outerEM (NbConstEdges); // edges connected to non-section ones + TopTools_MapOfShape visitedVM (NbConstEdges); + for ( itl.Initialize( myConstEdges ); itl.More(); itl.Next()) { + if ( ! mySectionEdges.Contains( itl.Value() )) + addConnected (itl.Value(), outerEM, visitedVM, MVE2); + } + // if an edge of a wire is in <outerEM>, the wire is not internal + TopExp_Explorer expIWE; + TopTools_ListIteratorOfListOfShape itIW ( myInternalWL ); + while (itIW.More()) { + expIWE.Init ( itIW.Value() , TopAbs_EDGE ); + if ( outerEM.Contains( expIWE.Current() )) { + myNewWires.Append ( itIW.Value() ); + myInternalWL.Remove( itIW ); // == itIW.Next() + } + else + itIW.Next(); + } + } +} +//======================================================================= +//function : isHole +//purpose : +//======================================================================= + +static Standard_Boolean isHole (const TopoDS_Wire& W, + const TopoDS_Face& F) +{ + BRep_Builder B; + TopoDS_Shape newFace = F.EmptyCopied(); + B.Add(newFace,W.Oriented(TopAbs_FORWARD)); + BRepTopAdaptor_FClass2d classif (TopoDS::Face(newFace), + Precision::PConfusion()); + return (classif.PerformInfinitePoint() == TopAbs_IN); +} + +//======================================================================= +//function : IsInside +//purpose : check if W1 is inside W2. Suppose W2 is not a hole !!!! +//======================================================================= + +static Standard_Boolean isInside(const TopoDS_Face& F, + const TopoDS_Wire& W1, + const TopoDS_Wire& W2) +{ + // make a face with wire W2 + BRep_Builder B; + TopoDS_Shape aLocalShape = F.EmptyCopied(); + TopoDS_Face newFace = TopoDS::Face(aLocalShape); + B.Add(newFace,W2); + + // get any 2d point of W1 + TopExp_Explorer exp(W1,TopAbs_EDGE); + if (BRep_Tool::Degenerated( TopoDS::Edge( exp.Current() ))) + exp.Next(); + const TopoDS_Edge& e = TopoDS::Edge(exp.Current()); + Standard_Real f,l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(e,F,f,l); + gp_Pnt2d pt2d(C2d->Value( 0.5 * ( f + l ))); + + BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion()); + return (classif.Perform(pt2d) == TopAbs_IN); +} + +//======================================================================= +//function : NewWires +//purpose : Returns the list of wires performed. +// can be an empty list. +//======================================================================= + +const TopTools_ListOfShape& Partition_Loop2d::NewWires() const +{ + return myNewWires; +} + +//======================================================================= +//function : NewFaces +//purpose : Returns the list of faces. +//Warning : The method <WiresToFaces> as to be called before. +// can be an empty list. +//======================================================================= + +const TopTools_ListOfShape& Partition_Loop2d::NewFaces() const +{ + return myNewFaces; +} + +//======================================================================= +//function : findEqual +//purpose : move wires form <WL> to <EqWL> pairs of wires build of the same edges +//======================================================================= + +static void findEqual (TopTools_ListOfShape& WL, + TopTools_DataMapOfShapeShape& EqWM, + const TopoDS_Face& F) +{ + TopTools_ListIteratorOfListOfShape it1, it2; + Standard_Integer i,j; + TColStd_MapOfInteger IndMap; + for (it1.Initialize(WL), i=1; it1.More(); it1.Next(), i++) { + + if (IndMap.Contains(i)) continue; + const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value()); + + for (it2.Initialize(WL), j=1; it2.More(); it2.Next(), j++) { + + if (j <= i || IndMap.Contains(j)) continue; + + TopTools_IndexedMapOfShape EdgesMap; + TopExp::MapShapes (Wire1, TopAbs_EDGE, EdgesMap); + + const TopoDS_Shape& Wire2 = it2.Value(); + TopoDS_Iterator itE ( Wire2); + for (; itE.More(); itE.Next()) { + if ( !EdgesMap.Contains( itE.Value()) ) + break; + } + if (!itE.More()) { // all edges are same + if (isHole( Wire1, F)) { + EqWM.Bind ( Wire1, Wire2 ); + } + else { + EqWM.Bind ( Wire2, Wire1 ); + } + IndMap.Add(i); + IndMap.Add(j); + break; + } + } + } + // clear WL + it1.Initialize(WL); + i=1; + while (it1.More()) { + if (IndMap.Contains(i)) + WL.Remove(it1); // next node becomes current and with Next() we would miss it + else + it1.Next(); + i++; + } +} + +//======================================================================= +//function : classify +//purpose : bind to a wire a list of internal wires +//======================================================================= + +static void classify(const TopTools_DataMapOfShapeShape& EqWM, + BRepAlgo_AsDes& OuterInner, + const TopoDS_Face& F) +{ + TopTools_DataMapIteratorOfDataMapOfShapeShape it1, it2; + + for (it1.Initialize(EqWM); it1.More(); it1.Next()) { + // find next after it1.Value() + for (it2.Initialize(EqWM); it2.More(); it2.Next()) + if (it1.Value().IsSame( it2.Value() )) + { + it2.Next(); + break; + } + for ( ; it2.More(); it2.Next()) { + const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value() ); + const TopoDS_Wire& Wire2 = TopoDS::Wire( it2.Value() ); + if (isInside(F, Wire1, Wire2)) + OuterInner.Add (Wire2, Wire1); + else if (isInside(F, Wire2, Wire1)) + OuterInner.Add (Wire1, Wire2); + } + } +} +//======================================================================= +//function : WiresToFaces +//purpose : Build faces from the wires result. +// <EdgeImage> serves to find original edge by new +// one. <Section> contains edges resulting from face +// intersections +//======================================================================= + +void Partition_Loop2d::WiresToFaces(const BRepAlgo_Image& ) +{ + Standard_Integer nbW = myNewWires.Extent() + myInternalWL.Extent(); + if (nbW==0) + return; + + BRepAlgo_FaceRestrictor FR; + FR.Init (myFace,Standard_False); + + // FaceRestrictor is instable in rather simple cases + // (ex. a single face of bellecoque.brep splited by 10 planes: + // sometimes 1-2 faces are missing ). + // So we use it as less as possible: no holes -> make faces by hands + + + // are there holes in myFace ? + Standard_Boolean hasOldHoles = Standard_False; + TopoDS_Iterator itOldW (myFace); + if ( itOldW.More()) { + const TopoDS_Wire& FirstOldWire = TopoDS::Wire( itOldW.Value() ); + itOldW.Next(); + hasOldHoles = itOldW.More() || isHole( FirstOldWire, myFace); + } + if (myInternalWL.IsEmpty() && !hasOldHoles) { + // each wire bounds one face + BRep_Builder B; + TopTools_ListIteratorOfListOfShape itNW (myNewWires); + for (; itNW.More(); itNW.Next()) { + TopoDS_Face NF = TopoDS::Face ( myFace.EmptyCopied() ); + B.Add ( NF, itNW.Value() ); + NF.Orientation( myFaceOri); + myNewFaces.Append ( NF ); + } + return; + } + + // FaceRestrictor can't classify wires build on all the same edges + // and gives incorrect result in such cases (ex. a plane cut into 2 parts by cylinder) + // We must make faces of equal wires separately. One of equal wires makes a + // hole in a face and should come together with outer wires of face. + // The other of a wires pair bounds a face that may have holes in turn. + + // Find equal wires among internal wires + TopTools_DataMapOfShapeShape EqWM; // key is a hole part of a pair of equal wires + findEqual (myInternalWL, EqWM, myFace); + + if (!EqWM.IsEmpty()) { // there are equal wires + + if (hasOldHoles) + myInternalWL.Append( myNewWires ); // an old wire can be inside an equal wire + + // classify equal wire pairs + BRepAlgo_AsDes OuterInner; + classify (EqWM,OuterInner,myFace); + + // make face of most internal of equal wires and its inner wires + while ( !EqWM.IsEmpty()) { + + TopTools_ListOfShape prevHolesL; // list of hole-part of previous most internal equal wires + + // find most internal wires among pairs (key - hole, value - outer part) + TopTools_DataMapIteratorOfDataMapOfShapeShape it(EqWM); + Standard_Integer nbEqW = EqWM.Extent(); // protection against infinite loop + for ( ; it.More(); it.Next()) { + + TopoDS_Wire outerW = TopoDS::Wire ( it.Value() ); + if ( OuterInner.HasDescendant( outerW ) && // has internal + ! OuterInner.Descendant( outerW ).IsEmpty() ) + continue; + + FR.Add( outerW ); + + // add internal wires that are inside of outerW + TopTools_ListIteratorOfListOfShape itIW (myInternalWL); + while ( itIW.More()) { + TopoDS_Wire IW = TopoDS::Wire ( itIW.Value() ); + if ( isInside (myFace, IW, outerW)) { + FR.Add (IW); + myInternalWL.Remove( itIW ); // == itIW.Next() !!! + } + else + itIW.Next(); + } + + // the hole-part of current pair of equal wires will be in the next new face + prevHolesL.Append ( it.Key() ); + + } // Loop on map of equal pairs searching for innermost wires + + // make faces + FR.Perform(); + if (FR.IsDone()) { + for (; FR.More(); FR.Next()) + myNewFaces.Append(FR.Current()); + } + + FR.Clear(); + + // add hole-parts to FaceRestrictor, + // remove them from the EqWM, + // remove found wires as internal of resting classified wires + Standard_Boolean clearOuterInner = ( prevHolesL.Extent() < EqWM.Extent() ); + TopTools_ListIteratorOfListOfShape itPrev (prevHolesL); + for (; itPrev.More(); itPrev.Next()) { + TopoDS_Wire& Hole = TopoDS::Wire ( itPrev.Value() ); + FR.Add ( Hole ); + if (clearOuterInner) { + const TopoDS_Wire& outerW = TopoDS::Wire ( EqWM.Find( Hole ) ); + // Loop on wires including outerW + TopTools_ListIteratorOfListOfShape itO( OuterInner.Ascendant( outerW )); + for (; itO.More(); itO.Next()) { + TopTools_ListOfShape& innerL = OuterInner.ChangeDescendant( itO.Value() ); + TopTools_ListIteratorOfListOfShape itI (innerL); + // Loop on internal wires of current including wire + for (; itI.More(); itI.Next()) + if ( outerW.IsSame( itI.Value() )) { + innerL.Remove( itI ); break; + } + } + } + EqWM.UnBind ( Hole ); + } + + if (nbEqW == EqWM.Extent()) + { + // error: pb with wires classification +#ifdef DEB + MESSAGE("Partition_Loop2d::WiresToFaces(), pb with wires classification"); +#endif + break; + } + + } // while (!EqWM.IsEmpty) + + } // if !EqWM.IsEmpty() + + myNewWires.Append ( myInternalWL ); + + TopTools_ListIteratorOfListOfShape itW (myNewWires); + for (; itW.More(); itW.Next()) { + TopoDS_Wire& W = TopoDS::Wire ( itW.Value() ); + FR.Add(W); + } + FR.Perform(); + for (; FR.IsDone() && FR.More(); FR.Next()) + myNewFaces.Append(FR.Current()); + + + TopTools_ListIteratorOfListOfShape itNF (myNewFaces); + for (; itNF.More(); itNF.Next()) + itNF.Value().Orientation( myFaceOri ); +} + +#endif diff --git a/contrib/Salome/Partition_Loop2d.hxx b/contrib/Salome/Partition_Loop2d.hxx new file mode 100644 index 0000000000000000000000000000000000000000..bdf1c2531df5ddb654088ca314ff6fe9c13f66db --- /dev/null +++ b/contrib/Salome/Partition_Loop2d.hxx @@ -0,0 +1,106 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop2d.hxx +// Module : GEOM + +#ifndef _Partition_Loop2d_HeaderFile +#define _Partition_Loop2d_HeaderFile + +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopAbs_Orientation_HeaderFile +#include <TopAbs_Orientation.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +class TopoDS_Face; +class TopoDS_Edge; +class TopTools_ListOfShape; +class BRepAlgo_Image; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Loop2d { + +public: + + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // Methods PUBLIC + // + Partition_Loop2d(); + void Init(const TopoDS_Face& F) ; + void AddConstEdge(const TopoDS_Edge& E) ; + void AddSectionEdge(const TopoDS_Edge& E) ; + void Perform() ; + const TopTools_ListOfShape& NewWires() const; + void WiresToFaces(const BRepAlgo_Image& EdgeImage) ; + const TopTools_ListOfShape& NewFaces() const; + + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + + + // Fields PRIVATE + // + TopoDS_Face myFace; + TopAbs_Orientation myFaceOri; + TopTools_ListOfShape myConstEdges; + TopTools_ListOfShape myNewWires; + TopTools_ListOfShape myNewFaces; + TopTools_ListOfShape myInternalWL; + TopTools_MapOfShape mySectionEdges; + + +}; + + + + + +// other Inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Loop2d.ixx b/contrib/Salome/Partition_Loop2d.ixx new file mode 100644 index 0000000000000000000000000000000000000000..2d35fd5c711b05df86cf40de88ec2d3c356b4998 --- /dev/null +++ b/contrib/Salome/Partition_Loop2d.ixx @@ -0,0 +1,14 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop2d.ixx +// Module : GEOM + +#include "Partition_Loop2d.jxx" + + + + diff --git a/contrib/Salome/Partition_Loop2d.jxx b/contrib/Salome/Partition_Loop2d.jxx new file mode 100644 index 0000000000000000000000000000000000000000..555c16c809d26712d52dba2a8ef0523eadf05262 --- /dev/null +++ b/contrib/Salome/Partition_Loop2d.jxx @@ -0,0 +1,24 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop2d.jxx +// Module : GEOM + +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _BRepAlgo_Image_HeaderFile +#include <BRepAlgo_Image.hxx> +#endif +#ifndef _Partition_Loop2d_HeaderFile +#include "Partition_Loop2d.hxx" +#endif diff --git a/contrib/Salome/Partition_Loop3d.cxx b/contrib/Salome/Partition_Loop3d.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b58457f7bc58b46f1156ba7cc81291f71224cef8 --- /dev/null +++ b/contrib/Salome/Partition_Loop3d.cxx @@ -0,0 +1,360 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.cxx +// Module : GEOM + +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +//using namespace std; +#include <climits> +#include "Partition_Loop3d.ixx" + +#include <TopExp_Explorer.hxx> +#include <TopExp.hxx> +#include <BRep_Builder.hxx> +#include <TopTools_MapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopoDS_Shell.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <gp_Vec.hxx> +#include <gp_Pnt.hxx> +#include <Geom2d_Curve.hxx> +#include <BRep_Tool.hxx> +#include <Geom_Surface.hxx> +#include <gp_Pnt2d.hxx> +#include <gp_Vec2d.hxx> +#include <gp_Dir2d.hxx> +#include <Geom_Curve.hxx> + +//======================================================================= +//function : Partition_Loop3d +//purpose : +//======================================================================= + +Partition_Loop3d::Partition_Loop3d() +{ +} + +//======================================================================= +//function : AddConstFaces +//purpose : Add faces of <S> as unique faces in the result. +//======================================================================= + +void Partition_Loop3d::AddConstFaces(const TopoDS_Shape& S) +{ + TopExp_Explorer FaceExp(S, TopAbs_FACE); + for (; FaceExp.More(); FaceExp.Next()) + myFaces.Append( FaceExp.Current() ); + + TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, myEFMap); +} + +//======================================================================= +//function : AddSectionFaces +//purpose : Add faces of <S> as double faces in the result. +//======================================================================= + +void Partition_Loop3d::AddSectionFaces(const TopoDS_Shape& S) +{ + AddConstFaces( S ); + AddConstFaces( S.Reversed() ); +} + +//======================================================================= +//function : MakeShells +//purpose : Make and return shells. +// <AvoidFacesMap> can contain faces that must not be +// added to result shells. +//======================================================================= + +const TopTools_ListOfShape& + Partition_Loop3d::MakeShells (const TopTools_MapOfOrientedShape& AvoidFacesMap) +{ + myNewShells.Clear(); + + BRep_Builder Builder; + TopTools_MapOfShape CheckedEdgesMap; + TopTools_MapOfOrientedShape AddedFacesMap; + + TopTools_ListIteratorOfListOfShape itF (myFaces); + for (; itF.More(); itF.Next()) + { + const TopoDS_Shape& FF = itF.Value(); + if (AvoidFacesMap.Contains( FF ) || + ! AddedFacesMap.Add( FF ) ) + continue; + + // make a new shell + TopoDS_Shell Shell; + Builder.MakeShell(Shell); + Builder.Add(Shell,FF); + + // clear the maps from shapes added to previous Shell + TopTools_MapIteratorOfMapOfShape itEM (CheckedEdgesMap); + for (; itEM.More(); itEM.Next()) { + TopTools_ListOfShape& FL = myEFMap.ChangeFromKey( itEM.Key()); + TopTools_ListIteratorOfListOfShape it (FL); + while ( it.More()) { + if (AddedFacesMap.Contains( it.Value())) + FL.Remove( it ); + else + it.Next(); + } + } + CheckedEdgesMap.Clear(); + + + // loop on faces added to Shell; add their neighbor faces to Shell and so on + TopoDS_Iterator itAddedF (Shell); + for (; itAddedF.More(); itAddedF.Next()) + { + const TopoDS_Face& F = TopoDS::Face (itAddedF.Value()); + + // loop on edges of F; find a good neighbor face of F by E + TopExp_Explorer EdgeExp(F, TopAbs_EDGE); + for (; EdgeExp.More(); EdgeExp.Next()) + { + const TopoDS_Edge& E = TopoDS::Edge( EdgeExp.Current()); + if (! CheckedEdgesMap.Add( E )) + continue; + + // candidate faces list + const TopTools_ListOfShape& FL = myEFMap.ChangeFromKey(E); + if (FL.IsEmpty()) + continue; + // select one of neighbors + TopoDS_Face SelF; + if (FL.Extent() == 2) { + if (! F.IsSame( FL.First() )) + SelF = TopoDS::Face( FL.First() ); + else if (!F.IsSame( FL.Last() )) + SelF = TopoDS::Face( FL.Last() ); + } + else { + // check if a face already added to Shell shares E + TopTools_ListIteratorOfListOfShape it (FL); + Standard_Boolean found = Standard_False; + for (; !found && it.More(); it.Next()) + if (F != it.Value()) + found = AddedFacesMap.Contains( it.Value() ); + if (found) + continue; + // select basing on geometrical check + Standard_Boolean GoodOri, inside; + Standard_Real dot, MaxDot = -100; + TopTools_ListOfShape TangFL; // tangent faces + for ( it.Initialize( FL ) ; it.More(); it.Next()) { + const TopoDS_Face& NeighborF = TopoDS::Face( it.Value()); + if (NeighborF.IsSame( F )) + continue; + inside = Partition_Loop3d::IsInside( E, F, NeighborF, 1, dot, GoodOri); + if (!GoodOri) + continue; + if (!inside) + dot = -dot - 3; + if (dot < MaxDot) + continue; + if ( IsEqual( dot, MaxDot)) + TangFL.Append(SelF); + else + TangFL.Clear(); + MaxDot = dot; + SelF = NeighborF; + } + if (!TangFL.IsEmpty()) { + for (it.Initialize( TangFL ); it.More(); it.Next()) { + const TopoDS_Face& NeighborF = TopoDS::Face( it.Value()); + if (Partition_Loop3d:: IsInside( E, SelF , NeighborF, 0, dot, GoodOri)) + SelF = NeighborF; + } + } + } + if (!SelF.IsNull() && + AddedFacesMap.Add( SelF ) && + !AvoidFacesMap.Contains( SelF )) + Builder.Add( Shell, SelF); + + } // loop on edges of F + + } // loop on the faces added to Shell + + // Shell is complete + myNewShells.Append( Shell ); + + } // loop on myFaces + + + // prepare to the next call + myFaces.Clear(); + myEFMap.Clear(); + + return myNewShells; +} + + + +//======================================================================= +//function : Normal +//purpose : +//======================================================================= + +gp_Vec Partition_Loop3d::Normal(const TopoDS_Edge& E, + const TopoDS_Face& F) +{ + gp_Vec Norm, V1, V2; + Standard_Real First, Last; + gp_Pnt Ps; + + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last); + Handle(Geom_Surface) Sf = BRep_Tool::Surface(F); + + gp_Pnt2d p = C2d->Value( 0.5*(First+Last) ); + Sf->D1(p.X(), p.Y(), Ps, V1, V2); + Norm = V1.Crossed(V2); + + if (F.Orientation() == TopAbs_REVERSED ) + Norm.Reverse(); + + return Norm; +} + +//======================================================================= +//function : NextNormal +//purpose : find normal to F at point a little inside F near the middle of E +//warning : E must be properly oriented in F. +//======================================================================= + +static gp_Vec NextNormal(const TopoDS_Edge& E, + const TopoDS_Face& F) +{ + Standard_Real First, Last; + + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last); + Handle(Geom_Surface) Sf = BRep_Tool::Surface(F); + + gp_Pnt2d p; + gp_Vec2d v; + C2d->D1( 0.5*(First+Last), p, v); + if (E.Orientation() != F.Orientation()) + v.Reverse(); + gp_Dir2d dir( -v.Y(), v.X() ); // dir inside F + + Standard_Real duv = 1e-6; // this is not Ok and may give incorrect result if + // resolutionUV of compared faces is very different. To have a good result, + //it is necessary to get normal to faces at points equidistant from E in 3D + + p.SetX( p.X() + dir.X()*duv ); + p.SetY( p.Y() + dir.Y()*duv ); + + gp_Pnt Ps; + gp_Vec Norm, V1, V2, VV1, VV2; + Sf->D1( p.X(), p.Y(), Ps, V1, V2); + Norm = V1.Crossed(V2); + + if (F.Orientation() == TopAbs_REVERSED ) + Norm.Reverse(); + + return Norm; +} + + +//======================================================================= +//function : FindEinF +//purpose : find E in F +//======================================================================= + +static TopoDS_Edge FindEinF(const TopoDS_Edge& E, + const TopoDS_Face& F) +{ + TopExp_Explorer expl (F, TopAbs_EDGE); + for (; expl.More(); expl.Next()) + if( E.IsSame( expl.Current() )) + return TopoDS::Edge(expl.Current()); + TopoDS_Edge nullE; + return nullE; +} + +//======================================================================= +//function : IsInside +//purpose : check if <F2> is inside <F1> by edge <E>. +// if <CountDot>, compute <Dot>: scalar production of +// normalized vectors pointing inside faces, and +// check if faces are oriented well for sewing +//======================================================================= + +Standard_Boolean Partition_Loop3d::IsInside(const TopoDS_Edge& E, + const TopoDS_Face& F1, + const TopoDS_Face& F2, + const Standard_Boolean CountDot, + Standard_Real& Dot, + Standard_Boolean& GoodOri) +{ + Standard_Real f, l; + gp_Pnt P; + gp_Vec Vc1, Vc2, Vin1, Vin2, Nf1, Nf2; + Handle(Geom_Curve) Curve = BRep_Tool::Curve(E,f,l); + Curve->D1( 0.5*(f + l), P, Vc2); + TopoDS_Edge E1, E2 = FindEinF (E, F2); + if (E2.Orientation() == TopAbs_REVERSED ) Vc2.Reverse(); + + Nf1 = Normal(E,F1); + Nf2 = Normal(E,F2); + + Standard_Real sin = + Nf1.CrossSquareMagnitude(Nf2) / Nf1.SquareMagnitude() / Nf2.SquareMagnitude(); + Standard_Boolean tangent = sin < 0.001; + + Standard_Boolean inside = 0; + if (tangent) { + E1 = FindEinF (E, F1); + gp_Vec NNf1 = NextNormal(E1,F1); + gp_Vec NNf2 = NextNormal(E2,F2); + Vin2 = NNf2.Crossed(Vc2); + inside = Vin2 * NNf1 < 0; + } + else { + Vin2 = Nf2.Crossed(Vc2); + inside = Vin2 * Nf1 < 0; + } + + if (!CountDot) return inside; + + if (tangent) + Vin2 = Nf2.Crossed(Vc2); + else + E1 = FindEinF (E, F1); + + Vc1 = Vc2; + if (E1.Orientation() != E2.Orientation()) + Vc1.Reverse(); + Vin1 = Nf1.Crossed(Vc1); + + if (tangent) { + Standard_Real N1N2 = Nf1 * Nf2; + GoodOri = (Vin2 * Vin1 < 0) ? N1N2 > 0 : N1N2 < 0; + } + else { + Standard_Real V1N2 = Vin1 * Nf2; + GoodOri = ( inside ? V1N2 <= 0 : V1N2 >= 0); + } + + Vin1.Normalize(); + Vin2.Normalize(); + + Dot = Vin2 * Vin1; + + return inside; +} + + +#endif diff --git a/contrib/Salome/Partition_Loop3d.hxx b/contrib/Salome/Partition_Loop3d.hxx new file mode 100644 index 0000000000000000000000000000000000000000..7f08d74eb7ff84cee88a44210db55293bf404ba5 --- /dev/null +++ b/contrib/Salome/Partition_Loop3d.hxx @@ -0,0 +1,104 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.hxx +// Module : GEOM + +#ifndef _Partition_Loop3d_HeaderFile +#define _Partition_Loop3d_HeaderFile + +//using namespace std; + +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_IndexedDataMapOfShapeListOfShape_HeaderFile +#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +#ifndef _Standard_Real_HeaderFile +#include <Standard_Real.hxx> +#endif +class TopoDS_Shape; +class TopTools_ListOfShape; +class TopTools_MapOfOrientedShape; +class TopoDS_Edge; +class TopoDS_Face; +class gp_Vec; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Loop3d { + +public: + + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // Methods PUBLIC + // + Partition_Loop3d(); + void AddConstFaces(const TopoDS_Shape& S) ; + void AddSectionFaces(const TopoDS_Shape& S) ; + const TopTools_ListOfShape& MakeShells(const TopTools_MapOfOrientedShape& AvoidFacesMap) ; + static Standard_Boolean IsInside(const TopoDS_Edge& E,const TopoDS_Face& F1,const TopoDS_Face& F2,const Standard_Boolean CountDot,Standard_Real& Dot,Standard_Boolean& GoodOri) ; + static gp_Vec Normal(const TopoDS_Edge& E,const TopoDS_Face& F) ; + + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + + + // Fields PRIVATE + // + TopTools_ListOfShape myNewShells; + TopTools_ListOfShape myFaces; + TopTools_IndexedDataMapOfShapeListOfShape myEFMap; + + +}; + + + + + +// other Inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Loop3d.ixx b/contrib/Salome/Partition_Loop3d.ixx new file mode 100644 index 0000000000000000000000000000000000000000..a661b3242dafae68300a92a3cf42e7074ce5aeb0 --- /dev/null +++ b/contrib/Salome/Partition_Loop3d.ixx @@ -0,0 +1,14 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.ixx +// Module : GEOM + +#include "Partition_Loop3d.jxx" + + + + diff --git a/contrib/Salome/Partition_Loop3d.jxx b/contrib/Salome/Partition_Loop3d.jxx new file mode 100644 index 0000000000000000000000000000000000000000..9b654f41bb1a23a11c80d65fe9128e5a5830798d --- /dev/null +++ b/contrib/Salome/Partition_Loop3d.jxx @@ -0,0 +1,30 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Loop3d.jxx +// Module : GEOM + +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfOrientedShape_HeaderFile +#include <TopTools_MapOfOrientedShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _TopoDS_Face_HeaderFile +#include <TopoDS_Face.hxx> +#endif +#ifndef _gp_Vec_HeaderFile +#include <gp_Vec.hxx> +#endif +#ifndef _Partition_Loop3d_HeaderFile +#include "Partition_Loop3d.hxx" +#endif diff --git a/contrib/Salome/Partition_Spliter.cxx b/contrib/Salome/Partition_Spliter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..87639d2b344b41cde3b4449cb00afb91012ce363 --- /dev/null +++ b/contrib/Salome/Partition_Spliter.cxx @@ -0,0 +1,2175 @@ +#ifdef OCCGEOMETRY + +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Spliter.cxx +// Author : Benedicte MARTIN +// Module : GEOM +// $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Spliter.cxx,v 1.7 2008/03/31 14:20:28 wabro Exp $ + +#if !defined(HAVE_NO_OCC_CONFIG_H) +#include <config.h> +#endif + +//using namespace std; +#include <climits> +#include "Partition_Inter2d.hxx" +#include "Partition_Inter3d.hxx" +#include "Partition_Loop2d.hxx" +#include "Partition_Loop3d.hxx" +#include "Partition_Spliter.ixx" + +//#include "utilities.h" + +#include <Precision.hxx> +#include <TopAbs_Orientation.hxx> +#include <TopExp.hxx> +#include <TopExp_Explorer.hxx> + +#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> +#include <TopTools_DataMapOfShapeListOfShape.hxx> +#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> +#include <TopTools_IndexedMapOfShape.hxx> +#include <TopTools_ListIteratorOfListOfShape.hxx> +#include <TopTools_ListOfShape.hxx> +#include <TopTools_MapIteratorOfMapOfShape.hxx> +#include <TopTools_SequenceOfShape.hxx> + +#include <Geom2d_Curve.hxx> +#include <Geom_Curve.hxx> +#include <Geom_Surface.hxx> +#include <Geom_TrimmedCurve.hxx> +#include <gp_Pnt.hxx> +#include <gp_Pnt2d.hxx> +#include <gp_Vec.hxx> + +#include <TopoDS.hxx> +#include <TopoDS_Compound.hxx> +#include <TopoDS_Edge.hxx> +#include <TopoDS_Face.hxx> +#include <TopoDS_Iterator.hxx> +#include <TopoDS_Shell.hxx> +#include <TopoDS_Solid.hxx> +#include <TopoDS_Vertex.hxx> +#include <TopoDS_Wire.hxx> + +#include <BRepBndLib.hxx> +#include <BRepClass3d_SolidClassifier.hxx> +#include <BRepLib.hxx> +#include <BRep_Tool.hxx> + +#include <Extrema_ExtPC.hxx> +#include <GeomAdaptor_Curve.hxx> +#include <TopOpeBRepTool_CurveTool.hxx> + +#ifdef DEB +//# define PART_PERF +#endif + +#ifdef PART_PERF +# include <OSD_Chronometer.hxx> +#endif + +//======================================================================= +//function : isClosed +//purpose : check id a shape is closed, ie is a solid or a closed shell +//======================================================================= + +static Standard_Boolean isClosed(const TopoDS_Shape& theShape) +{ + Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID); + + if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) { + TopTools_IndexedDataMapOfShapeListOfShape MEF; + TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF); + for (Standard_Integer i=1; isClosed && i<=MEF.Extent(); ++i) + isClosed = ( MEF(i).Extent() != 1 ); + } + + return isClosed; +} + +//======================================================================= +//function : Partition_Spliter +//purpose : constructor +//======================================================================= + +Partition_Spliter::Partition_Spliter() +{ + myAsDes = new BRepAlgo_AsDes; + Clear(); +} + +//======================================================================= +//function : AddTool +//purpose : add cutting tool that will _NOT_ be in result +//======================================================================= + +void Partition_Spliter::AddTool(const TopoDS_Shape& S) +{ + if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid + TopoDS_Iterator it (S); + for (; it.More(); it.Next()) + { + AddTool( it.Value()); + myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape + } + return; + } + + for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next()) + { + myMapTools.Add(exp.Current()); + myFaceShapeMap.Bind( exp.Current(), S ); + } + if (isClosed( S )) + myClosedShapes.Add( S ); +} + +//======================================================================= +//function : AddShape +//purpose : add object Shape to be splited +//======================================================================= + +void Partition_Spliter::AddShape(const TopoDS_Shape& S) +{ + if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid + TopoDS_Iterator it (S); + for (; it.More(); it.Next()) + { + AddShape( it.Value()); + myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape + } + return; + } + + TopExp_Explorer exp(S,TopAbs_FACE); + if (!exp.More()) { // do not split edges and vertices + //myBuilder.Add( myShape, S ); + return; + } + + Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S + for (; exp.More(); exp.Next()) { + const TopoDS_Shape & aFace = exp.Current(); + if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object + myFaceShapeMap.Bind( aFace, S ); + if (myMapFaces.Add( aFace )) + myImagesFaces.SetRoot( aFace ); + } + + if (nbFacesBefore == myMapFaces.Extent()) + return; + + // solids must be processed before all + if (S.ShapeType() == TopAbs_SOLID) + myListShapes.Prepend(S); + else + myListShapes.Append(S); + + if (isClosed( S )) + myClosedShapes.Add( S ); + +} + +//======================================================================= +//function : Shape +//purpose : return resulting compound +//======================================================================= + +TopoDS_Shape Partition_Spliter::Shape() const +{ + return myShape; +} + +//======================================================================= +//function : Clear +//purpose : clear fields +//======================================================================= + +void Partition_Spliter::Clear() +{ + myDoneStep = TopAbs_SHAPE; + + myListShapes.Clear(); + myMapFaces.Clear(); + myMapTools.Clear(); + myEqualEdges.Clear(); + myNewSection.Clear(); + myClosedShapes.Clear(); + mySharedFaces.Clear(); + myWrappingSolid.Clear(); + myFaceShapeMap.Clear(); + + myInternalFaces.Clear(); + myIntNotClFaces.Clear(); + + myAsDes->Clear(); + myImagesFaces.Clear(); + myImagesEdges.Clear(); + myImageShape.Clear(); + + // myInter3d = Partition_Inter3d(myAsDes); + Partition_Inter3d hinter3d (myAsDes); + myInter3d = hinter3d; + + myAddedFacesMap.Clear(); + +} + +//======================================================================= +//function : Compute +//purpose : produce a result +//======================================================================= + +void Partition_Spliter::Compute(const TopAbs_ShapeEnum Limit) +{ + if ((Limit != TopAbs_SHAPE && myDoneStep == Limit) || + (Limit == TopAbs_SHAPE && myDoneStep == TopAbs_SOLID)) + return; + + myBuilder.MakeCompound( myShape ); + + TopTools_MapIteratorOfMapOfShape it; + TopTools_ListIteratorOfListOfShape itl; + TopExp_Explorer exp; + +#ifdef PART_PERF + OSD_Chronometer aCron; +#endif + + if (myDoneStep > TopAbs_VERTEX) { + + TopTools_ListOfShape aListFaces; + aListFaces = myImagesFaces.Roots(); + for (it.Initialize(myMapTools); it.More(); it.Next()) + aListFaces.Append(it.Key()); + +#ifdef PART_PERF + aCron.Start(); +#endif + + //----------------------------------------------- + // Intersection between faces + //----------------------------------------------- + // result is in myAsDes as a map Face - list of new edges; + // special care is done for section edges, same domain faces and vertices: + // data about them is inside myInter3d + myInter3d.CompletPart3d(aListFaces, myFaceShapeMap); + +#ifdef PART_PERF + MESSAGE("+++ CompletPart3d()"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + //----------------------------------------------- + // Intersection of edges + //----------------------------------------------- + + // add tool faces which must be reconstructed to myMapFaces too + FindToolsToReconstruct(); + +#ifdef PART_PERF + MESSAGE("+++ FindToolsToReconstruct()"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + + // add existing vertices to edges of object faces in myAsDes + TopTools_MapOfShape DoneEM; + for ( it.Initialize(myMapFaces); it.More(); it.Next()) { + const TopoDS_Shape& F = it.Key(); + TopoDS_Face FForward = TopoDS::Face(F.Oriented(TopAbs_FORWARD)); + for (exp.Init(FForward,TopAbs_EDGE); exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge( exp.Current() ); + myAsDes->Add(FForward,E); + if (DoneEM.Add(E)) { + TopoDS_Iterator itV(E); + for (; itV.More(); itV.Next()) { + const TopoDS_Vertex& V = TopoDS::Vertex( itV.Value()); + myAsDes->Add(E, myInter3d.ReplaceSameDomainV( V, E )); + } + } + } + } + + // intersect edges that are descendants of a face in myAsDes + TopTools_MapOfShape& Modif = myInter3d.TouchedFaces(); + for ( it.Initialize(Modif); it.More(); it.Next()) { + const TopoDS_Face& F = TopoDS::Face(it.Key()); + Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges()); + } + // now myAsDes contains also new vertices made at edge intersection as + // descendant of edges both new and old + + myDoneStep = TopAbs_VERTEX; + +#ifdef PART_PERF + MESSAGE("+++ CompletPart2d()"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + } // if (myDoneStep > TopAbs_VERTEX) + + if (Limit == TopAbs_VERTEX) { + // add new vertices to myShape + for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) { + if (! myAsDes->HasDescendant( it.Key() )) + continue; + itl.Initialize( myAsDes->Descendant( it.Key() )); + for (; itl.More(); itl.Next()) + myBuilder.Add ( myShape, itl.Value() ); + } + return; + } + + + if (myDoneStep > TopAbs_EDGE) { + + //----------------------------------------------- + //----------------------------------------------- + // ------- Reconstruction of all the edges.------ + //----------------------------------------------- + //----------------------------------------------- + + // ============== + // cut new edges + // ============== + TopTools_ListOfShape LSE; // all edge splits + for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) { + + TopoDS_Vertex V1,V2; + TopoDS_Edge EE = TopoDS::Edge(it.Key()); + + TopTools_ListOfShape aListV, aListF; + aListV = myAsDes->Descendant(EE); // intersection vertices + aListF = myAsDes->Ascendant(EE); // intersected faces + + if (aListV.IsEmpty()) + continue; // new edge does not intersect any other edge + + // Add end vertices to new edges only if + // one face is Tool and the other is Shape + Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() ); + Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() ); + if (isTool1 || isTool2) + { + TopExp::Vertices(EE,V1,V2); + Standard_Real Tol = Max (BRep_Tool::Tolerance( V1 ), + BRep_Tool::Tolerance( V2 )); + + gp_Pnt P1 = BRep_Tool::Pnt(V1); + gp_Pnt P2 = BRep_Tool::Pnt(V2); + Standard_Boolean AddV1 = Standard_True; + Standard_Boolean AddV2 = Standard_True; + + // add only if there is no intersection at end vertex + for (itl.Initialize(aListV); itl.More(); itl.Next()) { + const TopoDS_Vertex& Ve = TopoDS::Vertex(itl.Value()) ; + Standard_Real Tol2 = Max ( Tol, BRep_Tool::Tolerance( Ve )); + Tol2 *= Tol2; + gp_Pnt P = BRep_Tool::Pnt(Ve); + if (AddV1 && P.SquareDistance(P1) <= Tol2) + AddV1 = Standard_False; + + if (AddV2 && P.SquareDistance(P2) <= Tol2) + AddV2 = Standard_False; + } + + if (AddV1) { + aListV.Append(V1); + myAsDes->Add(EE,V1); + } + + if (AddV2) { + aListV.Append(V2); + myAsDes->Add(EE,V2); + } + } + + // cut new edges + Standard_Integer NbV=aListV.Extent() ; + if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) { + TopTools_ListOfShape LNE; + MakeEdges (EE,aListV, LNE); + myImagesEdges.Bind(EE,LNE); + LSE.Append( LNE ); + } + } + + // ============== + // cut old edges + // ============== + for ( it.Initialize(myMapFaces); it.More(); it.Next()) { + for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) { + const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() ); + if ( myImagesEdges.HasImage( EE )) + continue; + TopTools_ListOfShape LNE; + const TopTools_ListOfShape& aListVV = myAsDes->Descendant(EE); + MakeEdges (EE, aListVV, LNE); + myImagesEdges.Bind(EE,LNE); + LSE.Append( LNE ); + } + } +#ifdef PART_PERF + MESSAGE("+++ Cut Edges"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + + // process same domain section edges + MergeEqualEdges( LSE ); + + myDoneStep = TopAbs_EDGE; + +#ifdef PART_PERF + MESSAGE("+++ MergeEqualEdges()"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + } // if (myDoneStep > TopAbs_EDGE) + + if (Limit == TopAbs_EDGE) { + // add splits of old edges + TopTools_ListIteratorOfListOfShape itNE; + for (itl.Initialize( myListShapes );itl.More();itl.Next()) { + if (myMapTools.Contains( itl.Value() )) + continue; // skip tool faces + for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) { + itNE.Initialize( myImagesEdges.Image( exp.Current() )); + for ( ; itNE.More(); itNE.Next()) + myBuilder.Add ( myShape, itNE.Value() ); + } + } + // add splits of new edges + for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) { + itNE.Initialize( myImagesEdges.Image( it.Key() )); + for (; itNE.More(); itNE.Next()) + myBuilder.Add ( myShape, itNE.Value() ); + } + return; + } + + + //----------------------------------------------- + // split faces + //----------------------------------------------- + + if (myDoneStep > TopAbs_FACE) { + + for (itl.Initialize(myListShapes);itl.More();itl.Next()) { + TopoDS_Shape FacesComp = MakeFaces ( itl.Value()); + // there is a cunning here: myImagesFaces keeps faces made by Loop2d + // but some of them may be replaced with splits of same domain face + // and myImageShape keeps ultimate result + myImageShape.Bind( itl.Value(), FacesComp ); + } + + myDoneStep = TopAbs_FACE; +#ifdef PART_PERF + MESSAGE("+++ MakeFaces()"); + aCron.Show( cout ); + aCron.Reset(); + aCron.Start(); +#endif + } + + if (Limit == TopAbs_WIRE || + Limit == TopAbs_FACE) { + for (itl.Initialize(myListShapes);itl.More();itl.Next()) { + if ( myMapTools.Contains( itl.Value() )) + continue; // no result needed for a tool face + const TopoDS_Shape& FacesComp = myImageShape.Image( itl.Value() ).First(); + for ( exp.Init( FacesComp, Limit); exp.More(); exp.Next()) + myBuilder.Add ( myShape, exp.Current()); + } + return; + } + + + //----------------------------------------------- + // split and add solids and shells + //----------------------------------------------- + + Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE || + Limit < TopAbs_SHELL); + for (itl.Initialize(myListShapes);itl.More();itl.Next()) + { + const TopoDS_Shape & S = itl.Value(); + if (S.ShapeType() > TopAbs_SHELL) + continue; + + TopTools_ListOfShape NSL; // new shape list + MakeShells (S , NSL); + if (makeSolids && S.ShapeType() == TopAbs_SOLID ) + MakeSolids( S, NSL ); + + // store new shells or solids + TopTools_ListIteratorOfListOfShape itNSL (NSL); + for ( ; itNSL.More(); itNSL.Next()) + myBuilder.Add (myShape, itNSL.Value()); + } +#ifdef PART_PERF + MESSAGE("+++ MakeShells()"); + aCron.Show( cout ); +#endif + + //----------------------------------------------- + // add split faces + //----------------------------------------------- + + for (itl.Initialize(myListShapes);itl.More();itl.Next()) + { + const TopoDS_Shape & S = itl.Value(); + if (S.ShapeType() != TopAbs_FACE || + myMapTools.Contains( S )) + continue; + TopoDS_Iterator itS( myImageShape.Image(S).First() ); + for (; itS.More(); itS.Next()) + if (! myAddedFacesMap.Contains( itS.Value() )) + myBuilder.Add (myShape, itS.Value()); + } + + myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL; + +} + +//======================================================================= +//function : MakeSolids +//purpose : make solids out of Shells +//======================================================================= + +void Partition_Spliter::MakeSolids(const TopoDS_Shape & theSolid, + TopTools_ListOfShape & theShellList) +{ + // for a solid wrapping other shells or solids without intersection, + // it is necessary to find shells making holes in it + + TopTools_ListOfShape aNewSolids; // result + TopTools_ListOfShape aHoleShells; + TopoDS_Shape anInfinitePointShape; + + Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid ); + if (!isWrapping && !theShellList.IsEmpty()) + { + // check if theSolid initially has internal shells + TopoDS_Iterator aShellExp (theSolid); + aShellExp.Next(); + isWrapping = aShellExp.More(); + } + + TopTools_ListIteratorOfListOfShape aShellIt(theShellList); + for ( ; aShellIt.More(); aShellIt.Next()) + { + const TopoDS_Shape & aShell = aShellIt.Value(); + + // check if a shell is a hole + if (isWrapping && IsInside (anInfinitePointShape, aShell)) + aHoleShells.Append( aShell ); + else + { + // make a solid from a shell + TopoDS_Solid Solid; + myBuilder.MakeSolid( Solid ); + myBuilder.Add (Solid, aShell); + + aNewSolids.Append (Solid); + } + } + + // find an outer shell most close to each hole shell + TopTools_DataMapOfShapeShape aInOutMap; + for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next()) + { + const TopoDS_Shape & aHole = aShellIt.Value(); + TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids); + for ( ; aSolisIt.More(); aSolisIt.Next()) + { + const TopoDS_Shape & aSolid = aSolisIt.Value(); + if (! IsInside( aHole, aSolid )) + continue; + + if ( aInOutMap.IsBound (aHole)) + { + const TopoDS_Shape & aSolid2 = aInOutMap( aHole ); + if ( IsInside( aSolid, aSolid2 )) + { + aInOutMap.UnBind( aHole ); + aInOutMap.Bind ( aHole, aSolid ); + } + } + else + aInOutMap.Bind ( aHole, aSolid ); + } + + // add aHole to a solid + if (aInOutMap.IsBound( aHole )) + myBuilder.Add ( aInOutMap( aHole ), aHole ); + } + + theShellList.Clear(); + theShellList.Append( aNewSolids ); +} + +//======================================================================= +//function : FindFacesInside +//purpose : return compound of faces of other shapes that are +// inside <theShape>. +// <theShape> is an object shape. +// <CheckClosed> makes avoid faces that do not form a +// closed shell +// <All> makes return already added faces +//======================================================================= + +TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape, + const Standard_Boolean CheckClosed, + const Standard_Boolean All) +{ + // ================================================ + // check if internal faces have been already found + // ================================================ + TopExp_Explorer expl; + if (myInternalFaces.IsBound( theShape )) + { + TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape ); + TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape ); + + expl.Init( aIntRemFComp, TopAbs_FACE); + if (CheckClosed || !expl.More()) + return aIntFComp; + + TopoDS_Compound C; + myBuilder.MakeCompound( C ); + // add removed faces + for (; expl.More(); expl.Next()) + myBuilder.Add( C, expl.Current() ); + // add good internal faces + for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next()) + myBuilder.Add( C, expl.Current() ); + return C; + } + + // =================================== + // get data for internal faces search + // =================================== + + // compound of split faces of theShape + const TopoDS_Shape& CSF = myImageShape.Image(theShape).First(); + + TopTools_MapOfShape MSE, MFP; + TopTools_DataMapOfShapeListOfShape DMSEFP; + TopTools_MapIteratorOfMapOfShape itm; + TopTools_ListOfShape EmptyL; + + // MSE filling: map of new section edges of CSF + for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) { + const TopoDS_Shape & resE = expl.Current() ; + if (myNewSection.Contains( resE )) // only new edges + MSE.Add(resE); + } + + // DMEF: map edge of CSF - faces of CSF + TopTools_IndexedDataMapOfShapeListOfShape DMEF; + TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF); + + // Fill + // 1. MFP - a map of faces to process: map of resulting faces except + // those of theShape; we`ll add to C those of them which are inside CSF + // 2. DMSEFP - edge of MSE => faces of MFP + TopTools_ListIteratorOfListOfShape itl; + for (itl.Initialize(myListShapes);itl.More();itl.Next()) { + const TopoDS_Shape& aShape = itl.Value(); + if ( theShape.IsSame( aShape )) continue; + // fill maps + // iterate on split faces of aShape + TopoDS_Iterator itF ( myImageShape.Image(aShape).First() ); + for ( ; itF.More(); itF.Next()) { + const TopoDS_Shape& sf = itF.Value(); + MFP.Add(sf); + // iterate on edges of split faces of aShape, + // add to DMSEFP edges that are new + for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) { + TopoDS_Shape se = expl.Current(); + if ( MSE.Contains(se)) {// section edge + if (!DMSEFP.IsBound(se)) + DMSEFP.Bind(se,EmptyL); + DMSEFP(se).Append(sf); + } + } + } + } + + // add tool faces having section edges on faces of theShape to MFP and DMSEFP; + // such tool faces need not to be reconstructed and so they are not in myListShapes + for (itm.Initialize(myMapTools); itm.More(); itm.Next()) + { + const TopoDS_Shape & aToolFace = itm.Key(); + if (myMapFaces.Contains( aToolFace )) + continue; + MFP.Add(aToolFace); + for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) { + TopoDS_Shape se = expl.Current(); + if ( MSE.Contains( se )) {// section edge + if (!DMSEFP.IsBound( se )) + DMSEFP.Bind( se, EmptyL ); + DMSEFP( se ).Append( aToolFace ); + } + } + } + + + // =========================== + // find faces inside theShape + // =========================== + + Standard_Boolean skipAlreadyAdded = Standard_False; + Standard_Boolean GoodOri, inside; + Standard_Real dot; + TopTools_ListOfShape KeepFaces; + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit; + + // iterate on section edges, check faces of other shapes + // sharing section edges and put internal faces to KeepFaces + for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) { + // a new edge of theShape + const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key()); + // an original edge of which E is a split + const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E )); + // does OrigE itself splits a face + Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE ); + + // split faces of other shapes sharing E + TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E); + itl.Initialize( LSF ); + while (itl.More()) { + // a split faces of other shape + TopoDS_Face aFace1 = TopoDS::Face(itl.Value()); + // remove aFace1 form DMSEFP and MFP + LSF.Remove( itl ); // == itl.Next(); + if (!MFP.Remove( aFace1 )) + continue; // was not is MFP ( i.e already checked) + // check if aFace1 was already added to 2 shells + if (!All && + myAddedFacesMap.Contains( aFace1 ) && + myAddedFacesMap.Contains( aFace1.Reversed() )) { + skipAlreadyAdded = Standard_True; + continue; + } + + // find another face which originates from the same face as aFace1: + // usually aFace2 is internal if aFace1 is not and vice versa + + TopoDS_Shape anOrigFace = aFace1; + if (myImagesFaces.IsImage(aFace1)) + anOrigFace = myImagesFaces.Root(aFace1); + TopoDS_Shape aFace2; + if ( !isSectionE ) { + while (itl.More()) { + aFace2 = itl.Value(); + if (!MFP.Contains( aFace2 )) { + LSF.Remove( itl ); + continue; + } + if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 ))) + break; + itl.Next(); + } + if (itl.More()) { // aFace2 found, remove it from maps + LSF.Remove( itl ); + MFP.Remove(aFace2); + } + else + aFace2.Nullify(); + itl.Initialize( LSF ); + } + + // check that anOrigFace is not same domain with CSF faces it intersects + + const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E + const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First()); + const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last()); + Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 ); + Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 ); + if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) { + sameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1); + if (origF1 == origF2) + sameDom2 = sameDom1; + else + myInter3d.IsSameDomainF( anOrigFace, origF2); + } + if (sameDom1 && sameDom2) + continue; + if ((sameDom1 || sameDom2)) { + inside = Partition_Loop3d::IsInside (E, + TopoDS::Face(FL.First()), + TopoDS::Face(FL.Last()), + 1, dot, GoodOri); + if (inside || (dot + Precision::Angular() >= 1.0)) + continue; // E is convex between origF1 and origF2 or they are tangent + } + + + // keep one of found faces + + //face of CSF sharing E + const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First(); + // analyse aFace1 state + inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1, + 1, dot, GoodOri); + if (inside && isSectionE) + { + // aFace1 must be tested with both adjacent faces of CSF + const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last(); + if (aShapeFace2 != aShapeFace) + inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1, + 1, dot, GoodOri); + } + + // store internal face + if (inside) + KeepFaces.Append(aFace1); + + else if (!aFace2.IsNull()) + { + if (dot + Precision::Angular() >= 1.0) + { + // aFace2 state is not clear, it will be analysed alone, + // put it back to the maps + MFP.Add( aFace2 ); + LSF.Append( aFace2 ); + } + else + KeepFaces.Append(aFace2); + } + } + } + + // =================================================== + // add not distributed faces connected with KeepFaces + // =================================================== + + // ultimate list of internal faces + TopTools_ListOfShape KeptFaces; + + // add to MFP not split tool faces as well, they may be connected with + // tool faces interfering with theShape + for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) { + const TopoDS_Shape& aToolFace = itm.Key(); + if (!myImageShape.HasImage(aToolFace)) + MFP.Add (aToolFace); + } + + if (MFP.IsEmpty()) + KeptFaces.Append (KeepFaces); + + while (!KeepFaces.IsEmpty()) + { + // KeepEdges : map of edges of faces kept last time + TopTools_IndexedMapOfShape KeepEdges; + for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) { + TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges); + KeptFaces.Append( itl.Value() ); + } + + KeepFaces.Clear(); + + // keep faces connected with already kept faces by KeepEdges + for ( itm.Initialize(MFP); itm.More(); itm.Next() ) { + const TopoDS_Shape& FP = itm.Key(); + for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) { + const TopoDS_Shape& se = expl.Current(); + if (!MSE.Contains(se) && KeepEdges.Contains(se) ) { + KeepFaces.Append(FP); + MFP.Remove(FP); + break; + } + } + } + } + + // =============================================================== + // here MFP contains faces outer of theShape and those of shapes + // which do not interfere with theShape at all and between which + // there may be those wrapped by theShape and whose faces may be + // needed to be returned as well + // =============================================================== + + Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID); + if (All || isSolid) // All is for sub-result removal + { + // loop on not used faces; checked faces will be removed from MFP + // during the loop + for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) { + const TopoDS_Shape & aFace = itm.Key(); + + // a shape which aFace originates from + TopoDS_Shape anOrigShape = GetOriginalShape( aFace ); + + // find out if all split faces of anOrigShape are not in MFP + // and by the way remove them from MFP + Standard_Boolean isAllOut = Standard_True; + TopoDS_Shape aSplitFaces = anOrigShape; + if (myImageShape.HasImage(anOrigShape)) + aSplitFaces = myImageShape.Image(anOrigShape).First(); + + TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept + for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next()) + { + const TopoDS_Shape & aSpFace = expl.Current(); + // a tool face which became object has image but the whole tool shape has not + if (myImageShape.HasImage( aSpFace )) + { + TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE ); + for ( ; exF.More(); exF.Next() ) + { + aSplitFaceL.Append( exF.Current() ); + if ( ! MFP.Remove( exF.Current() ) && isAllOut ) + // a shared face might be removed from MFP during a prev loop + isAllOut = mySharedFaces.Contains( exF.Current() ); + } + } + else + { + aSplitFaceL.Append( aSpFace ); + if ( ! MFP.Remove( aSpFace ) && isAllOut) + // a shared face might be removed from MFP during a prev loop + isAllOut = mySharedFaces.Contains( aSpFace ); + } + } + itm.Initialize( MFP ); // iterate remaining faces + if ( !isAllOut ) + continue; + + // classify anOrigShape against theShape + if (IsInside (anOrigShape, theShape)) + { + if (isSolid && myClosedShapes.Contains( anOrigShape )) + // to make a special care at solid reconstruction + myWrappingSolid.Add ( theShape ); + + // keep faces of an internal shape anOrigShape + KeptFaces.Append( aSplitFaceL ); + } + } + } + + // ==================================================== + // check if kept faces form a shell without free edges + // ==================================================== + + DMEF.Clear(); // edge - kept faces + MFP.Clear(); // reuse it for wrong faces + if (CheckClosed) { + for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) + TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF); + + Standard_Integer i, nb = DMEF.Extent(); + Standard_Boolean isClosed = Standard_False; + while (!isClosed) { + isClosed = Standard_True; + for (i=1; isClosed && i<=nb; ++i) { + const TopoDS_Shape& E = DMEF.FindKey( i ); + if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) && + ! MSE.Contains( E )) + isClosed = ( DMEF(i).Extent() != 1 ); + } + if (!isClosed) { + const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face + MFP.Add( F ); + // remove bad face from DMEF + for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) { + const TopoDS_Shape& E = expl.Current(); + TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E ); + for (itl.Initialize( FL ); itl.More(); itl.Next() ) { + if ( F.IsSame( itl.Value() )) { + FL.Remove( itl ); + break; + } + } + } + } + } + } + + // ============== + // make a result + // ============== + + TopoDS_Compound C; + // compound of removed internal faces + TopoDS_Compound CNotCl; + + myBuilder.MakeCompound(C); + myBuilder.MakeCompound(CNotCl); + + // add to compounds + for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) + { + TopoDS_Shape & aIntFace = itl.Value(); + if (! MFP.Contains( aIntFace )) + myBuilder.Add( C, aIntFace); + else + myBuilder.Add( CNotCl, aIntFace); + } + + if (!skipAlreadyAdded && CheckClosed) + { + myInternalFaces.Bind( theShape, C ); + myIntNotClFaces.Bind( theShape, CNotCl ); + } + + return C; +} + +//======================================================================= +//function : MakeShell +//purpose : split S into compound of shells +//======================================================================= + +void Partition_Spliter::MakeShells(const TopoDS_Shape& S, + TopTools_ListOfShape& NS) +{ + Partition_Loop3d ShellMaker; + // get compound of split faces of S + const TopoDS_Shape& FacesComp = myImageShape.Image(S).First(); + ShellMaker.AddConstFaces( FacesComp ); + // add split faces inside S + if (myClosedShapes.Contains( S )) { + TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True); + ShellMaker.AddSectionFaces( InternalFacesComp ); + } + + NS = ShellMaker.MakeShells( myAddedFacesMap ); + + // Add faces added to new shell to myAddedFacesMap: + // avoid rebuilding twice commont part of 2 solids. + TopTools_ListIteratorOfListOfShape itS(NS); + while ( itS.More()) { + TopExp_Explorer expF (itS.Value(), TopAbs_FACE); + for (; expF.More(); expF.Next()) + myAddedFacesMap.Add (expF.Current()); + + itS.Next(); + } +} + +//======================================================================= +//function : findEqual +//purpose : compare edges of EL1 against edges of EL2, +// Result is in EMM binding EL1 edges to list of equal edges. +// Edges are considered equall only if they have same vertices. +// <addSame>==True makes consider same edges as equal +// Put in <AllEqMap> all equal edges +//======================================================================= + +static void findEqual (const TopTools_ListOfShape& EL1, + const TopTools_ListOfShape& EL2, + const Standard_Boolean addSame, + TopTools_DataMapOfShapeListOfShape& EEM, + TopTools_MapOfShape& AllEqMap) +{ + // map vertices to edges for EL2 + TopTools_DataMapOfShapeListOfShape VEM; + TopTools_ListIteratorOfListOfShape itE1, itE2(EL2); + TopoDS_Iterator itV; + TopTools_ListOfShape emptyL; + for (; itE2.More(); itE2.Next()) { + for (itV.Initialize( itE2.Value() ); itV.More(); itV.Next()) { + const TopoDS_Shape& V = itV.Value(); + if (! VEM.IsBound( V ) ) + VEM.Bind( V, emptyL); + VEM( V ).Append( itE2.Value()); + } + } + + gp_Vec D1, D2; + gp_Pnt P; + Standard_Real f,l,u,tol; + Handle(Geom_Curve) C1, C2; + Extrema_ExtPC Extrema; + TopoDS_Vertex V1, V2, V3, V4; + + AllEqMap.Clear(); + + for (itE1.Initialize(EL1); itE1.More(); itE1.Next()) { + const TopoDS_Edge& E1 = TopoDS::Edge( itE1.Value()); + if (BRep_Tool::Degenerated( E1 ) || AllEqMap.Contains (E1)) + continue; + TopExp::Vertices( E1, V1, V2 ); + + if (VEM.IsBound(V1)) + itE2.Initialize( VEM(V1) ); + for (; itE2.More(); itE2.Next()) { + const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value()); + if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2)) + continue; + + if (E1.IsSame(E2)) { + if (!addSame) + continue; + } + else { + TopExp::Vertices( E2, V3, V4); + if (!V2.IsSame(V4) && !V2.IsSame(V3)) + continue; + // E1 and E2 have same vertices + // check D1 at end points. + C2 = BRep_Tool::Curve( E2, f,l); + C1 = BRep_Tool::Curve( E1, f,l); + u = BRep_Tool::Parameter(V1,E1); + C1->D1(u, P, D1); + u = BRep_Tool::Parameter(V1.IsSame(V3) ? V3 : V4, E2); + C2->D1(u, P, D2); + D1.Normalize(); D2.Normalize(); + if (Abs(D1*D2) + Precision::Angular() < 1.0) + continue; + if (! V1.IsSame(V2)) { + u = BRep_Tool::Parameter(V2,E1); + C1->D1(u, P, D1); + u = BRep_Tool::Parameter(V2.IsSame(V3) ? V3 : V4, E2); + C2->D1(u, P, D2); + D1.Normalize(); D2.Normalize(); + if (Abs(D1*D2) + Precision::Angular() < 1.0) + continue; + } + // check distance at a couple of internal points + tol = Max(BRep_Tool::Tolerance(E1), + BRep_Tool::Tolerance(E2)); + GeomAdaptor_Curve AC1(C1); + Extrema.Initialize(AC1,f,l); + Standard_Boolean ok = Standard_True, hasMin = Standard_False; + BRep_Tool::Range( E2, f, l); + Standard_Integer i=1, nbi=3; + for (; i<nbi && ok; ++i) { + Extrema.Perform( C2->Value( f+(l-f)*i/nbi )); + Standard_Integer j=1, nbj=Extrema.NbExt(); + for (; j<=nbj && ok; ++j) { + if (Extrema.IsMin(j)) { + hasMin = Standard_True; +#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5) + ok = Extrema.Value(j) <= tol; +#else + ok = Extrema.SquareDistance(j) <= tol; +#endif + } + } + } + if ( !hasMin || !ok) + continue; + } + // bind E2 to E1 in EEM + if (!EEM.IsBound(E1)) { + EEM.Bind (E1, emptyL); + AllEqMap.Add (E1); + } + EEM(E1).Append(E2); + AllEqMap.Add (E2); + } + } +} + +//======================================================================= +//function : MakeFaces +//purpose : split faces of S, return compound of new faces +//======================================================================= + +TopoDS_Shape Partition_Spliter::MakeFaces (const TopoDS_Shape& S) +{ + TopoDS_Compound C; + myBuilder.MakeCompound(C); + + TopTools_ListIteratorOfListOfShape itl, itNE; + + TopExp_Explorer exp(S,TopAbs_FACE); + for (; exp.More(); exp.Next()) { + + const TopoDS_Face& F = TopoDS::Face(exp.Current()); + + TopTools_ListOfShape LNF; + + if (myImagesFaces.HasImage( F )) { + myImagesFaces.LastImage( F, LNF ); + TopAbs_Orientation oriF = F.Orientation(); + for ( itl.Initialize( LNF ); itl.More(); itl.Next()) + itl.Value().Orientation( oriF ); + } + else { + + Partition_Loop2d loops; + loops.Init(F); + + TopTools_IndexedMapOfShape EM; + TopExp::MapShapes( F, TopAbs_EDGE, EM); + + TopTools_MapOfShape AddedEqualM, EqualSeamM; + Standard_Boolean needRebuild = Standard_False; + + // add splits to loops + + // LE: old edges + new not splitted edges + const TopTools_ListOfShape& LE = myAsDes->Descendant(F); + for (itl.Initialize(LE); itl.More(); itl.Next()) { + const TopoDS_Edge& E = TopoDS::Edge( itl.Value() ); + + Standard_Boolean isSectionE = myInter3d.IsSectionEdge(E); + Standard_Boolean isNewE = !EM.Contains( E ); + + // LSE: list of split edges + TopTools_ListOfShape LSE; + myImagesEdges.LastImage(E,LSE); // splits of E or E itself + + for (itNE.Initialize(LSE); itNE.More(); itNE.Next()) { + + TopoDS_Edge NE = TopoDS::Edge( itNE.Value() ); + Standard_Boolean isSameE = NE.IsSame ( E ); + + if ( isNewE || isSectionE || !isSameE) { + if (AddedEqualM.Contains( NE )) { + // a seam must be twice in a loop + if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE )) + continue; + } + + if (isNewE) { + if (isSectionE) { + if ( ! myInter3d.IsSplitOn( NE, E, F) ) + continue; + } + else { + TopoDS_Vertex V1,V2; + TopExp::Vertices(NE,V1,V2); + const TopTools_ListOfShape& EL1 = myAsDes->Ascendant(V1); + const TopTools_ListOfShape& EL2 = myAsDes->Ascendant(V2); + if ( EL1.Extent() < 2 && EL2.Extent() < 2 ) + continue; + } + } + else { + NE.Orientation( E.Orientation()); + if (!isSameE) { + // orient NE because it may be a split of other edge + Standard_Real f,l,u; + Handle(Geom_Curve) C3d = BRep_Tool::Curve( E,f,l ); + Handle(Geom_Curve) NC3d = BRep_Tool::Curve( NE,f,l); + if ( C3d != NC3d) { + gp_Vec D1, ND1; gp_Pnt P; + TopoDS_Vertex V = TopExp::FirstVertex(NE); + u = BRep_Tool::Parameter(V,NE); + NC3d->D1 (u, P, ND1); + u = BRep_Tool::Parameter(V,E); + C3d ->D1 (u, P, D1); + if (ND1.Dot(D1) < 0) + NE.Reverse(); + } + } + } + if (myEqualEdges.Contains( NE )) + AddedEqualM.Add( NE ); + + needRebuild = Standard_True; + } + + if (isNewE || isSectionE) + myNewSection.Add( NE ); + + if (isNewE) + loops.AddSectionEdge(NE); + else + loops.AddConstEdge(NE); + } + } + + //------------------- + // Build the faces. + //------------------- + + if (needRebuild) { + + loops.Perform(); + loops.WiresToFaces(myImagesEdges); + + LNF = loops.NewFaces(); + + myImagesFaces.Bind(F,LNF); + + // replace the result faces that have already been built + // during same domain faces reconstruction done earlier + if (myInter3d.HasSameDomainF( F )) + { + // build map edge to same domain faces: EFM + TopTools_IndexedDataMapOfShapeListOfShape EFM; + TopTools_MapOfShape SDFM; // avoid doubling + itl.Initialize( myInter3d.SameDomain( F )); + for (; itl.More(); itl.Next()) { + if ( !myImagesFaces.HasImage( itl.Value() )) + continue; + // loop on splits of a SD face + TopTools_ListIteratorOfListOfShape itNF; + itNF.Initialize (myImagesFaces.Image( itl.Value() )); + for ( ; itNF.More(); itNF.Next()) { + TopoDS_Shape SDF = itNF.Value(); + if (myImagesFaces.HasImage( SDF )) // already replaced + SDF = myImagesFaces.Image( SDF ).First(); + if (SDFM.Add (SDF)) + TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM); + } + } + // do replace faces in the LNF + TopTools_ListOfShape LOF; + if ( !EFM.IsEmpty() ) + itl.Initialize( LNF ); + while (itl.More()) { + const TopoDS_Shape& NF = itl.Value(); + TopExp_Explorer expE ( NF, TopAbs_EDGE ); + const TopoDS_Edge& E = TopoDS::Edge (expE.Current()); + if (EFM.Contains( E )) { + const TopTools_ListOfShape& SDFL = EFM.FindFromKey( E ); + TopoDS_Shape SDF = SDFL.First(); + Standard_Boolean GoodOri; + Standard_Real dot; + Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF), + 1, dot, GoodOri); + if (dot < 0) + { + // NF and SDF are on different side of E + if (SDFL.Extent() == 1) { + itl.Next(); + continue; + } + else + SDF = SDFL.Last(); // next face must be on the same side + } + gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF )); + gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF )); + if (V1*V2 < 0) + SDF.Reverse(); + + if (!myImagesFaces.HasImage( NF )) + myImagesFaces.Bind( NF, SDF ); + + // mySharedFaces is used in FindFacesInside() + mySharedFaces.Add( SDF ); + + LOF.Prepend ( SDF ); + LNF.Remove (itl); + } + else + itl.Next(); + } + + LNF.Append (LOF); + } + } // if (needRebuild) + + else { + LNF.Append( F ); + myImagesFaces.Bind(F,LNF); + } + } // if (myImagesFaces.HasImage( F )) + + // fill the resulting compound + for (itl.Initialize(LNF); itl.More(); itl.Next()) + myBuilder.Add ( C, itl.Value()); + + } // loop on faces of S + + return C; +} + + +//======================================================================= +//function : Tri +//purpose : +//======================================================================= + +static void Tri(const TopoDS_Edge& E, + TopTools_SequenceOfShape& Seq, + const Partition_Inter3d & theInter3d) +{ + Standard_Boolean Invert = Standard_True; + Standard_Real U1,U2; + TopoDS_Vertex V1,V2; + + while (Invert) { + Invert = Standard_False; + for ( Standard_Integer i = 1; i < Seq.Length(); i++) { + + V1 = TopoDS::Vertex(Seq.Value(i)); + V2 = TopoDS::Vertex(Seq.Value(i+1)); + + V1.Orientation(TopAbs_INTERNAL); + V2.Orientation(TopAbs_INTERNAL); + + U1 = BRep_Tool::Parameter(V1,E); + U2 = BRep_Tool::Parameter(V2,E); + + if (IsEqual(U1,U2)) { + if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 )) + Seq.Remove(i+1); // remove V2 + else + Seq.Remove(i); + i--; + continue; + } + if (U2 < U1) { + Seq.Exchange(i,i+1); + Invert = Standard_True; + } + } + } +} + +//======================================================================= +//function : MakeEdges +//purpose : cut E by vertices VOnE, return list of new edges NE +//======================================================================= + +void Partition_Spliter::MakeEdges (const TopoDS_Edge& E, + const TopTools_ListOfShape& VOnE, + TopTools_ListOfShape& NE ) const +{ + TopoDS_Edge WE = E; + WE.Orientation(TopAbs_FORWARD); + + Standard_Real U1,U2, f, l; + TopoDS_Vertex V1,V2,VF,VL; + + BRep_Tool::Range(WE,f,l); + TopExp::Vertices(WE,VF,VL); + + if (VOnE.Extent() < 3) { // do not rebuild not cut edge + if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) || + VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ) ) { + NE.Append( E ); + return; + } + } + + TopTools_SequenceOfShape SV; + TopTools_ListIteratorOfListOfShape itv(VOnE); + TopTools_MapOfOrientedShape VM( VOnE.Extent() ); + for (; itv.More(); itv.Next()) + if ( VM.Add( itv.Value() )) + SV.Append(itv.Value()); + + Tri( WE, SV, myInter3d ); + + if (SV.Length() < 3) { // do not rebuild not cut edge + if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) || + VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() ) ) { + NE.Append( E ); + return; + } + } + + Standard_Integer iVer, NbVer = SV.Length(); + + + //---------------------------------------------------------------- + // Construction of the new edges . + //---------------------------------------------------------------- + + if (VF.IsSame(VL)) { // closed edge + if (NbVer==1) + SV.Append( SV.First() ); + else if (!SV.First().IsSame(SV.Last())) { + Standard_Boolean isFirst=0; + Standard_Real minDU = 1.e10; + TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU); + if (endV.IsSame(SV.First())) + SV.Append(endV); + else if (endV.IsSame(SV.Last())) + SV.Prepend(endV); + //else + //MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE"); + } + NbVer = SV.Length(); + } + + for (iVer=1; iVer < NbVer; iVer++) { + V1 = TopoDS::Vertex(SV(iVer)); + V2 = TopoDS::Vertex(SV(iVer+1)); + + TopoDS_Shape NewEdge = WE.EmptyCopied(); + V1.Orientation(TopAbs_FORWARD); + myBuilder.Add (NewEdge,V1); + V2.Orientation(TopAbs_REVERSED); + myBuilder.Add (NewEdge,V2); + + if (iVer==1) + U1 = f; + else { + V1.Orientation(TopAbs_INTERNAL); + U1=BRep_Tool::Parameter(V1,WE); + } + if (iVer+1 == NbVer) + U2 = l; + else { + V2.Orientation(TopAbs_INTERNAL); + U2=BRep_Tool::Parameter(V2,WE); + } + if (Abs(U1-U2) <= Precision::PConfusion()) { + //MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES"); + continue; + } + TopoDS_Edge EE=TopoDS::Edge(NewEdge); + myBuilder.Range (EE,U1,U2); + + TopoDS_Edge NEdge = TopoDS::Edge(NewEdge); + myBuilder.SameParameter(NEdge,Standard_False); + + Standard_Real tol = 1.0e-2; + Standard_Boolean flag = BRep_Tool::SameParameter(NEdge); + if (!flag) { + BRepLib::SameParameter(NEdge,tol); + } + NE.Append(NEdge.Oriented(E.Orientation())); + } +} + +//======================================================================= +//function : MergeEqualEdges +//purpose : find equal edges, choose ones to keep and make +// them have pcurves on all faces they are shared by +//======================================================================= + +void Partition_Spliter::MergeEqualEdges (const TopTools_ListOfShape& LSE) +{ + // find equal edges + // map: edge - equal edges + TopTools_DataMapOfShapeListOfShape EEM( LSE.Extent() ); + findEqual (LSE, LSE, 0, EEM, myEqualEdges); + + TopTools_ListOfShape EEL; // list of equal edges + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itM (EEM); + for ( ; itM.More(); itM.Next()) { + EEL = itM.Value(); + EEL.Append( itM.Key() ); + + // choose an edge to keep, section edges have priority + TopoDS_Edge EKeep; + TopTools_ListIteratorOfListOfShape itEE (EEL); + for (; itEE.More(); itEE.Next()) { + EKeep = TopoDS::Edge( itEE.Value() ); + const TopoDS_Edge& EKeepOrig = TopoDS::Edge( myImagesEdges.Root( EKeep )); + if (myInter3d.IsSectionEdge( EKeepOrig )) + break; + } + + // update edge images and build pcurves + Standard_Real f,l, tol; + for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) { + const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() ); + if ( E.IsSame( EKeep )) + continue; + + // 1. build pcurves of the kept edge on faces where replaced edges exist + const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E )); + TopTools_ListOfShape FL; + FL = myAsDes->Ascendant( EReplOrig ); + Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1; + // add faces where the replaced edge is a section edge + if (myInter3d.IsSectionEdge( EReplOrig )) { + TopTools_ListIteratorOfListOfShape seIt; + seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig )); + for ( ; seIt.More(); seIt.Next()) + FL.Append( seIt.Value() ); + } + // loop on faces + TopTools_ListIteratorOfListOfShape itF (FL); + for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) { + const TopoDS_Face& F = TopoDS::Face( itF.Value()); + + Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l); + if (pc.IsNull()) { + Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l); + C3d = new Geom_TrimmedCurve( C3d, f,l); + pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol); + if (pc.IsNull()) { + //MESSAGE (" CANT BUILD PCURVE "); + } + myBuilder.UpdateEdge( EKeep, pc, F, tol); + } + + if (iFace >= iFirstSectionFace || + !BRep_Tool::IsClosed( EReplOrig, F )) + continue; + + // build the second pcurve for a seam + TopoDS_Vertex V = TopExp::FirstVertex( EKeep ); + Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep ); + Standard_Real Urepl = BRep_Tool::Parameter( V, E ); + + TopoDS_Edge EReplRev = E; + EReplRev.Reverse(); + Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l); + Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l); + + gp_Pnt2d p1r, p2r, pk; + p1r = pcRepl1->Value( Urepl ); + p2r = pcRepl2->Value( Urepl ); + pk = pc->Value( Ukeep ); + + // suppose that pk is equal to either p1r or p2r + Standard_Boolean isUPeriod = + ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() )); + Standard_Boolean is1Equal; + if (isUPeriod) + is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() )); + else + is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() )); + + Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast + ( pc->Translated( pk, is1Equal ? p2r : p1r ) ); + + if (E.Orientation() == TopAbs_REVERSED) + is1Equal = !is1Equal; + + if (is1Equal) + myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol); + else + myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol); + + } // loop on a Faces where a replaced edge exists + + + // 2. update edge images according to replacement + if (myImagesEdges.HasImage( E )) + myImagesEdges.Remove( E ); + myImagesEdges.Bind( E, EKeep ); + + } // loop on a list of equal edges EEL + } // loop on a map of equal edges EEM +} + +//======================================================================= +//function : KeepShapesInside +//purpose : remove shapes that are outside of S from resul +//======================================================================= + +void Partition_Spliter::KeepShapesInside (const TopoDS_Shape& S) +{ + TopoDS_Iterator it; + if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid + for (it.Initialize( S ); it.More(); it.Next()) + KeepShapesInside( it.Value()); + return; + } + + Standard_Boolean isTool = Standard_False; + if (!myImageShape.HasImage( S )) { + isTool = CheckTool( S ); + if (!isTool) return; + } + + // build map of internal faces + TopTools_IndexedMapOfShape MIF; + TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True); + TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF ); + + TopoDS_Compound C; + myBuilder.MakeCompound(C); + + TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE; + if (!MIF.IsEmpty()) + { + // leave in the result only those shapes having a face in MIF + for (it.Initialize( myShape ); it.More(); it.Next()) { + const TopoDS_Shape & aResShape = it.Value(); + TopExp_Explorer expResF( aResShape, TopAbs_FACE ); + for (; expResF.More(); expResF.Next()) { + if ( MIF.Contains( expResF.Current())) { + myBuilder.Add( C, aResShape ); + if (aResShape.ShapeType() < anInternalShapeType) + anInternalShapeType = aResShape.ShapeType(); + break; + } + } + } + } + + // may be S was not split by internal faces then it is missing + // in myShape, add it + if (!isTool && + (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID)) + { + TopTools_IndexedMapOfShape MSF; // map of split faces of S + TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF); + + // find a shape having all faces in MSF + for (it.Initialize( myShape ); it.More(); it.Next()) { + TopExp_Explorer expResF( it.Value(), TopAbs_FACE ); + for (; expResF.More(); expResF.Next()) { + if (! MSF.Contains( expResF.Current())) + break; + } + if (! expResF.More()) { + myBuilder.Add( C, it.Value() ); + break; + } + } + } + + myShape = C; +} + +//======================================================================= +//function : RemoveShapesInside +//purpose : remove shapes that are inside S from resul +//======================================================================= + +void Partition_Spliter::RemoveShapesInside (const TopoDS_Shape& S) +{ + TopoDS_Iterator it; + if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid + for (it.Initialize( S ); it.More(); it.Next()) + RemoveShapesInside( it.Value()); + return; + } + Standard_Boolean isTool = Standard_False; + if (!myImageShape.HasImage( S )) { + isTool = CheckTool( S ); + if (!isTool) return; + } + + TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True); + TopTools_IndexedMapOfShape MIF; // map of internal faces + TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF); + + if (MIF.IsEmpty()) return; + + // add to MIF split faces of S + if (myImageShape.HasImage(S)) + TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF); + + // leave in the result only those shapes not having all face in MIF + + TopoDS_Compound C; + myBuilder.MakeCompound(C); + + // RMF : faces of removed shapes that encounter once + TopTools_MapOfShape RFM; + + for (it.Initialize( myShape ); it.More(); it.Next()) { + + TopExp_Explorer expResF( it.Value(), TopAbs_FACE ); + for (; expResF.More(); expResF.Next()) + if (!MIF.Contains( expResF.Current())) + break; + + if (expResF.More()) + // add shape to result + myBuilder.Add( C, it.Value() ); + else + // add faces of a removed shape to RFM + for (expResF.ReInit(); expResF.More(); expResF.Next()) { + const TopoDS_Shape& F = expResF.Current(); + if ( ! RFM.Remove ( F )) + RFM.Add( F ); + } + } + + if (!isTool) { + + // rebuild S, it must remain in the result + + Standard_Boolean isClosed = Standard_False; + switch (S.ShapeType()) { + case TopAbs_SOLID : + isClosed = Standard_True; break; + case TopAbs_SHELL: { + TopTools_IndexedDataMapOfShapeListOfShape MEF; + TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF); + Standard_Integer i; + for (i=1; isClosed && i<=MEF.Extent(); ++i) + isClosed = ( MEF(i).Extent() != 1 ); + break; + } + default: + isClosed = Standard_False; + } + if (isClosed) { + + // add to a new shape external faces of removed shapes, ie those in RFM + + TopoDS_Shell Shell; + myBuilder.MakeShell( Shell ); + + // exclude redundant internal face with edges encounterd only once + TopTools_IndexedDataMapOfShapeListOfShape MEF; + TopTools_MapIteratorOfMapOfShape itF (RFM); + for ( ; itF.More(); itF.Next()) + TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF); + + // add only faces forming a closed shell + for (itF.Reset() ; itF.More(); itF.Next()) + { + TopExp_Explorer expE (itF.Key(), TopAbs_EDGE); + for (; expE.More(); expE.Next()) + if (MEF.FindFromKey(expE.Current()).Extent() == 1) + break; + if (!expE.More()) + myBuilder.Add( Shell, itF.Key()); + } + + if (S.ShapeType() == TopAbs_SOLID) { + TopoDS_Solid Solid; + myBuilder.MakeSolid( Solid ); + myBuilder.Add (Solid, Shell); + myBuilder.Add (C, Solid); + } + else + myBuilder.Add (C, Shell); + } + else { + if (myImageShape.HasImage( S )) { + for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next()) + myBuilder.Add (C, it.Value()); + } + } + } + + myShape = C; +} + +//======================================================================= +//function : CheckTool +//purpose : Return True if <S> is a tool shape. Prepare tool +// faces of <S> for the search of internal faces. +//======================================================================= + +Standard_Boolean Partition_Spliter::CheckTool(const TopoDS_Shape& S) +{ + // suppose S has not an image + + Standard_Boolean isTool = Standard_False; + TopoDS_Compound C; + myBuilder.MakeCompound( C ); + + TopExp_Explorer expF( S, TopAbs_FACE); + for (; expF.More(); expF.Next()) { + + const TopoDS_Face& F = TopoDS::Face( expF.Current() ); + if (myMapTools.Contains( F )) + isTool = Standard_True; + else + continue; + + if (myImagesFaces.HasImage( F )) { + // F has been reconstructed + TopAbs_Orientation Fori = F.Orientation(); + TopTools_ListOfShape LNF; + myImagesFaces.LastImage( F, LNF); + TopTools_ListIteratorOfListOfShape itF (LNF); + for ( ; itF.More(); itF.Next()) + myBuilder.Add( C, itF.Value().Oriented(Fori) ); + continue; + } + + Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F ); + Standard_Boolean hasNewE = myAsDes->HasDescendant( F ); + if (!hasSectionE && !hasNewE) + { + // F intersects nothing + myBuilder.Add( C, F ); + continue; + } + + // make an image for F + + TopoDS_Face NF = F; + NF.Orientation(TopAbs_FORWARD); + NF = TopoDS::Face( NF.EmptyCopied() ); // make a copy + TopoDS_Wire NW; + myBuilder.MakeWire( NW ); + + // add edges, as less as possible + TopTools_ListOfShape NEL; + TopTools_ListIteratorOfListOfShape itNE; + if (hasSectionE) { + // add section edges + TopExp_Explorer expE; + for ( ; expE.More(); expE.Next()) { + if (! myImagesEdges.HasImage( expE.Current() )) + continue; + myImagesEdges.LastImage( expE.Current(), NEL ); + for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) + myBuilder.Add ( NW, itNE.Value()); + } + } + if (hasNewE) { + // add new adges + NEL = myAsDes->Descendant( F ); + for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) { + TopTools_ListOfShape SEL; // splits + myImagesEdges.LastImage( itNE.Value(), SEL ); + TopTools_ListIteratorOfListOfShape itSE (SEL); + for ( ; itSE.More(); itSE.Next()) + myBuilder.Add ( NW, itSE.Value()); + } + } + myBuilder.Add( NF, NW ); + myBuilder.Add (C, NF); + + NF.Orientation( F.Orientation() ); // NF is most probably invalid + myImagesFaces.Bind (F, NF); + } + if (isTool) + myImageShape.Bind (S, C); + + return isTool; +} + +//======================================================================= +//function : IsInside +//purpose : Return True if the first vertex of S1 inside S2. +// If S1.IsNull(), check infinite point against S2. +//======================================================================= + +Standard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1, + const TopoDS_Shape& theS2) +{ + BRepClass3d_SolidClassifier aClassifier( theS2 ); + + TopExp_Explorer expl( theS1, TopAbs_VERTEX ); + if (!expl.More()) + aClassifier.PerformInfinitePoint( ::RealSmall()); + else + { + const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() ); + aClassifier.Perform (BRep_Tool::Pnt( aVertex ), + BRep_Tool::Tolerance( aVertex )); + } + + return ( aClassifier.State() == TopAbs_IN ); +} + +//======================================================================= +//function : GetOriginalShape +//purpose : Return the shape aShape originates from. aShape +// should be a face or more complex result shape +//======================================================================= + +TopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const +{ + TopoDS_Shape anOrigShape; + + TopExp_Explorer expl( theShape, TopAbs_FACE); + if (expl.More()) + { + + TopoDS_Shape aFace = expl.Current(); + if (myImagesFaces.IsImage( aFace )) + aFace = myImagesFaces.Root( aFace ); + anOrigShape = myFaceShapeMap.Find( aFace ); + } + return anOrigShape; +} + +//======================================================================= +//function : FindToolsToReconstruct +//purpose : find and store as objects tools which interfere +// with solids or are inside solids without +// an interference +//======================================================================= + +void Partition_Spliter::FindToolsToReconstruct() +{ + if (myMapTools.IsEmpty()) + return; + + Standard_Integer nbFoundTools = 0; + + // build edge - face map in order to detect interference with section edges + TopTools_IndexedDataMapOfShapeListOfShape EFM; + TopTools_MapIteratorOfMapOfShape aMapIt; + for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next()) + TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM); + for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next()) + TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM); + + TopTools_MapOfShape aCurrentSolids, aCheckedShapes; + + // faces cut by new edges + TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces(); + + // keep solids interfering with each other in aCurrentSolids map + // and add tool faces intersecting solids as object shapes + + TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE; + for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) { + TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID); + for (; expSo.More(); expSo.Next()) { + + // check if a solid has been already processed + const TopoDS_Shape & aSo = expSo.Current(); + if (!aCheckedShapes.Add( aSo )) + continue; + aCurrentSolids.Add( aSo ); + + // faces to check + TopTools_ListOfShape aFacesToCheck; + TopExp_Explorer exp( aSo, TopAbs_FACE ); + for ( ; exp.More(); exp.Next()) + aFacesToCheck.Append ( exp.Current()); + + // add other shapes interefering with a solid. + // iterate faces to check while appending new ones + for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next()) + { + const TopoDS_Shape& aCheckFace = itCF.Value(); +// if (!aCheckedShapes.Add( aCheckFace )) +// continue; + + // find faces interfering with aCheckFace + TopTools_ListOfShape anIntFaces; + + // ** 1. faces intersecting aCheckFace with creation of new edges on it + if ( myAsDes->HasDescendant( aCheckFace )) + { + // new edges on aCheckFace + const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace ); + for (itE.Initialize( NEL); itE.More(); itE.Next()) + { + const TopoDS_Shape & aNewEdge = itE.Value(); + if (!aCheckedShapes.Add( aNewEdge )) + continue; + + // faces interfering by aNewEdge + itF.Initialize (myAsDes->Ascendant( aNewEdge )); + for (; itF.More(); itF.Next()) + if (aCheckFace != itF.Value()) + anIntFaces.Append( itF.Value() ); + + // ** 2. faces having section edge aNewEdge on aFacesToCheck + if (EFM.Contains( aNewEdge)) + { + itF.Initialize ( EFM.FindFromKey (itE.Value())); + for (; itF.More(); itF.Next()) + if (aCheckFace != itF.Value()) + anIntFaces.Append( itF.Value() ); + } + } + } + + // ** 3. faces cut by edges of aCheckFace + TopExp_Explorer expE (aCheckFace, TopAbs_EDGE); + for ( ; expE.More(); expE.Next()) + { + const TopoDS_Shape & aCheckEdge = expE.Current(); + if (aCheckedShapes.Add( aCheckEdge ) && + myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge ))) + { + itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge ))); + for (; itF.More(); itF.Next()) + if (aCheckFace != itF.Value()) + anIntFaces.Append( itF.Value() ); + } + } + + // process faces interfering with aCheckFace and shapes they + // belong to + for (itF.Initialize (anIntFaces); itF.More(); itF.Next()) + { + const TopoDS_Shape & F = itF.Value(); + if (! aCheckedShapes.Add( F )) + continue; + + Standard_Boolean isTool = myMapTools.Contains( F ); + if (isTool && + myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID ) + { + // a tool interfering with a solid + if (aSectionFaces.Contains( F )) + AddShape( F ); + ++ nbFoundTools; + if (nbFoundTools == myMapTools.Extent()) + return; + } + + const TopoDS_Shape & S = myFaceShapeMap( F ); + if (aCheckedShapes.Add( S )) + { + // a new shape interefering with aCurrentSolids is found + if (!isTool && S.ShapeType() == TopAbs_SOLID) + aCurrentSolids.Add ( S ); + // add faces to aFacesToCheck list + for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next()) + aFacesToCheck.Append ( exp.Current() ); + } + } + } // loop on aFacesToCheck + + // Here aCurrentSolids contains all solids interfering with each other. + // aCheckedShapes contains all faces belonging to shapes included + // in or interfering with aCurrentSolids or previously checked solids. + // Test if tool faces that do not interefere with other shapes are + // wrapped by any of aCurrentSolids + + TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids); + for ( ; aSolidIt.More(); aSolidIt.Next()) + { + const TopoDS_Shape & aSolid = aSolidIt.Key(); + TopTools_MapOfShape aCheckedTools( myMapTools.Extent() ); + + TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools); + for ( ; aToolIt.More(); aToolIt.Next()) + { + const TopoDS_Shape & aToolFace = aToolIt.Key(); + if (aCheckedShapes.Contains( aToolFace ) || // already found + aCheckedTools.Contains( aToolFace )) // checked against aSolid + continue; + + const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace ); + TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE ); + + Standard_Boolean isInside = IsInside( aToolShape, aSolid ); + for ( ; aToolFaceIt.More(); aToolFaceIt.Next() ) + { + const TopoDS_Shape & aTool = aToolFaceIt.Current(); + aCheckedTools.Add( aTool ); + if (isInside) + { + if (aSectionFaces.Contains( aTool )) + AddShape( aTool ); + ++ nbFoundTools; + if (nbFoundTools == myMapTools.Extent()) + return; + aCheckedShapes.Add( aTool ); + } + } + } + } + + } // loop on solid shapes + } +} + +#endif diff --git a/contrib/Salome/Partition_Spliter.hxx b/contrib/Salome/Partition_Spliter.hxx new file mode 100644 index 0000000000000000000000000000000000000000..f29917a3e144edcf2b8f03d7476b13cb86b3ecdd --- /dev/null +++ b/contrib/Salome/Partition_Spliter.hxx @@ -0,0 +1,150 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 CEA/DEN, EDF R&D +// +// +// +// File : Partition_Spliter.hxx +// Module : GEOM + +#ifndef _Partition_Spliter_HeaderFile +#define _Partition_Spliter_HeaderFile + +#ifndef _TopAbs_ShapeEnum_HeaderFile +#include <TopAbs_ShapeEnum.hxx> +#endif +#ifndef _TopoDS_Compound_HeaderFile +#include <TopoDS_Compound.hxx> +#endif +#ifndef _BRep_Builder_HeaderFile +#include <BRep_Builder.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopTools_MapOfShape_HeaderFile +#include <TopTools_MapOfShape.hxx> +#endif +#ifndef _TopTools_DataMapOfShapeShape_HeaderFile +#include <TopTools_DataMapOfShapeShape.hxx> +#endif +#ifndef _Handle_BRepAlgo_AsDes_HeaderFile +#include <Handle_BRepAlgo_AsDes.hxx> +#endif +#ifndef _BRepAlgo_Image_HeaderFile +#include <BRepAlgo_Image.hxx> +#endif +#ifndef _Partition_Inter3d_HeaderFile +#include "Partition_Inter3d.hxx" +#endif +#ifndef _TopTools_MapOfOrientedShape_HeaderFile +#include <TopTools_MapOfOrientedShape.hxx> +#endif +#ifndef _Standard_Boolean_HeaderFile +#include <Standard_Boolean.hxx> +#endif +class BRepAlgo_AsDes; +class TopoDS_Shape; +class TopTools_ListOfShape; +class TopoDS_Edge; + + +#ifndef _Standard_HeaderFile +#include <Standard.hxx> +#endif +#ifndef _Standard_Macro_HeaderFile +#include <Standard_Macro.hxx> +#endif + +class Partition_Spliter { + +public: + + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + // Methods PUBLIC + // + Partition_Spliter(); + void AddShape(const TopoDS_Shape& S) ; + void AddTool(const TopoDS_Shape& S) ; + void Compute(const TopAbs_ShapeEnum Limit = TopAbs_SHAPE) ; + void KeepShapesInside(const TopoDS_Shape& S) ; + void RemoveShapesInside(const TopoDS_Shape& S) ; + TopoDS_Shape Shape() const; + void Clear() ; + + + + + +protected: + + // Methods PROTECTED + // + + + // Fields PROTECTED + // + + +private: + + // Methods PRIVATE + // + void MakeSolids(const TopoDS_Shape& Solid,TopTools_ListOfShape& Shells) ; + void MakeShells(const TopoDS_Shape& S,TopTools_ListOfShape& NS) ; + TopoDS_Shape MakeFaces(const TopoDS_Shape& S) ; + void MakeEdges(const TopoDS_Edge& E,const TopTools_ListOfShape& VOnE,TopTools_ListOfShape& NE) const; + TopoDS_Shape FindFacesInside(const TopoDS_Shape& S,const Standard_Boolean CheckClosed = Standard_False,const Standard_Boolean All = Standard_False) ; + Standard_Boolean CheckTool(const TopoDS_Shape& S) ; + void MergeEqualEdges(const TopTools_ListOfShape& LE) ; + static Standard_Boolean IsInside(const TopoDS_Shape& S1,const TopoDS_Shape& S2) ; + TopoDS_Shape GetOriginalShape(const TopoDS_Shape& aShape) const; + void FindToolsToReconstruct() ; + + + // Fields PRIVATE + // + TopAbs_ShapeEnum myDoneStep; + TopoDS_Compound myShape; + BRep_Builder myBuilder; + TopTools_ListOfShape myListShapes; + TopTools_MapOfShape myMapFaces; + TopTools_MapOfShape myMapTools; + TopTools_MapOfShape myEqualEdges; + TopTools_MapOfShape myNewSection; + TopTools_MapOfShape myClosedShapes; + TopTools_MapOfShape mySharedFaces; + TopTools_MapOfShape myWrappingSolid; + TopTools_DataMapOfShapeShape myFaceShapeMap; + TopTools_DataMapOfShapeShape myInternalFaces; + TopTools_DataMapOfShapeShape myIntNotClFaces; + Handle_BRepAlgo_AsDes myAsDes; + BRepAlgo_Image myImagesFaces; + BRepAlgo_Image myImagesEdges; + BRepAlgo_Image myImageShape; + Partition_Inter3d myInter3d; + TopTools_MapOfOrientedShape myAddedFacesMap; + + +}; + + + + + +// other Inline functions and methods (like "C++: function call" methods) +// + + +#endif diff --git a/contrib/Salome/Partition_Spliter.ixx b/contrib/Salome/Partition_Spliter.ixx new file mode 100644 index 0000000000000000000000000000000000000000..ee825946855db633d7899ef2c280a9ef1858dab1 --- /dev/null +++ b/contrib/Salome/Partition_Spliter.ixx @@ -0,0 +1,31 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Spliter.ixx +// Module : GEOM + +#include "Partition_Spliter.jxx" + + + + diff --git a/contrib/Salome/Partition_Spliter.jxx b/contrib/Salome/Partition_Spliter.jxx new file mode 100644 index 0000000000000000000000000000000000000000..bf8622c93a6b74b3a14c6b91cf438e4d12cb347e --- /dev/null +++ b/contrib/Salome/Partition_Spliter.jxx @@ -0,0 +1,41 @@ +// GEOM PARTITION : partition algorithm +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File : Partition_Spliter.jxx +// Module : GEOM + +#ifndef _BRepAlgo_AsDes_HeaderFile +#include <BRepAlgo_AsDes.hxx> +#endif +#ifndef _TopoDS_Shape_HeaderFile +#include <TopoDS_Shape.hxx> +#endif +#ifndef _TopTools_ListOfShape_HeaderFile +#include <TopTools_ListOfShape.hxx> +#endif +#ifndef _TopoDS_Edge_HeaderFile +#include <TopoDS_Edge.hxx> +#endif +#ifndef _Partition_Spliter_HeaderFile +#include "Partition_Spliter.hxx" +#endif