// Created on: 2016 // Created by: Eugeny MALTCHIKOV // Copyright (c) 2016 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // This is the implementation of the extension of the 3D offset algorithm // to work in mode Complete and Join Type Intersection. // Currently only the Planar cases are supported. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OFFSET_DEBUG #include #endif typedef NCollection_DataMap BRepOffset_DataMapOfShapeMapOfShape; static void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF, const Handle(BRepAlgo_AsDes)& theAsDes, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, Handle(IntTools_Context)& theCtx, TopTools_MapOfShape& theNewEdges, TopTools_DataMapOfShapeShape& theETrimEInf); static Standard_Boolean GetEdges(const TopoDS_Face& theFace, const Handle(BRepAlgo_AsDes)& theAsDes, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_MapOfShape& theLastInvEdges, const TopTools_IndexedMapOfShape& theInvEdges, Handle(IntTools_Context)& theCtx, const TopTools_MapOfShape& theModifiedEdges, TopoDS_Shape& theEdges, TopTools_IndexedMapOfShape& theInv); static void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace, const TopoDS_Shape& theEdges, TopTools_ListOfShape& theLFImages); static void BuildSplitsOfFace(const TopoDS_Face& theFace, const TopoDS_Shape& theEdges, TopTools_DataMapOfShapeShape& theOrigins, TopTools_ListOfShape& theLFImages); static void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF, const TopTools_MapOfShape& theModifiedEdges, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, Handle(BRepAlgo_AsDes)& theAsDes, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopoDS_Shape& theSolids, TopTools_DataMapOfShapeListOfShape& theSSInterfs); static void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theModifiedEdges, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedMapOfShape& theValidEdges, TopTools_DataMapOfShapeShape& theETrimEInf, Handle(BRepAlgo_AsDes)& theAsDes); static Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF, const TopTools_ListOfShape& theLFImages, const TopoDS_Shape& theCE, const TopTools_IndexedMapOfShape& theMapEInv, const TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_MapOfShape& theMENInv, Handle(BRepAlgo_AsDes)& theAsDes); static void FindInvalidEdges(const TopoDS_Face& theF, const TopTools_ListOfShape& theLFImages, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, const TopTools_DataMapOfShapeShape& theFacesOrigins, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, TopTools_DataMapOfShapeListOfShape& theDMFLVE, TopTools_DataMapOfShapeListOfShape& theDMFLNE, TopTools_DataMapOfShapeListOfShape& theDMFLIE, TopTools_DataMapOfShapeListOfShape& theDMFLVIE, TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm, TopTools_MapOfShape& theMEInverted, TopTools_MapOfShape& theEdgesInvalidByVertex); static void FindInvalidFaces(TopTools_ListOfShape& theLFImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_DataMapOfShapeListOfShape& theDMFLVE, const TopTools_DataMapOfShapeListOfShape& theDMFLIE, const TopTools_ListOfShape& theLENeutral, const TopTools_ListOfShape& theLEValInverted, const TopTools_MapOfShape& theMEInverted, const TopTools_MapOfShape& theEdgesInvalidByVertex, const TopTools_MapOfShape& theMFHoles, TopTools_IndexedMapOfShape& theMFInvInHole, TopTools_ListOfShape& theInvFaces); static void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin, const TopoDS_Face& theFOffset, const TopTools_ListOfShape& theLFImages, const TopTools_MapOfShape& theInvertedEdges, const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm, TopTools_MapOfShape& theMFHoles, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, Handle(IntTools_Context)& theContext); static gp_Vec GetAverageTangent(const TopoDS_Shape& theS, const Standard_Integer theNbP); static Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm, const TopoDS_Face& theFOr, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE, const TopTools_IndexedMapOfShape& theMEdges, TopTools_MapOfShape& theMEInverted); static Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB, const TopTools_ListOfShape& theLCBF, const TopTools_MapOfShape& theMEInverted, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted, BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll); static void GetVerticesOnEdges(const TopoDS_Shape& theCB, const TopTools_MapOfShape& theEdges, TopTools_MapOfShape& theVerticesOnEdges, TopTools_MapOfShape& theAllVertices); static void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_IndexedMapOfShape& theMERemoved); static void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_MapOfShape& theMEInverted, TopTools_IndexedDataMapOfShapeListOfShape& theFImages); static void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theMFToCheckInt, const TopTools_IndexedMapOfShape& theMFInvInHole, const TopoDS_Shape& theFHoles, TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedMapOfShape& theMEInside, TopoDS_Shape& theSolids); static void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_DataMapOfShapeShape& theDMFOr, BOPAlgo_Builder& theBuilder, TopTools_DataMapOfShapeListOfShape& theSSInterfs); static void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV, const TopTools_DataMapOfShapeShape& theDMFImF, const TopTools_IndexedMapOfShape& theMFInv, const TopTools_IndexedMapOfShape& theInvEdges, TopTools_MapOfShape& theMFToRem); static void RemoveValidSplits(const TopTools_MapOfShape& theSpRem, TopTools_IndexedDataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_IndexedMapOfShape& theMERemoved); static void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedDataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_IndexedMapOfShape& theMERemoved); static void FilterEdgesImages(const TopoDS_Shape& theS, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins); static void FilterInvalidFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF, const TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_DataMapOfShapeShape& theArtInvFaces); static void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_DataMapOfShapeListOfShape& theDMFLIE, const TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedMapOfShape& theInvEdges); static void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, TopTools_MapOfShape& theFSelfRebAvoid); static void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theFSelfRebAvoid, const TopoDS_Shape& theSolids, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, Handle(BRepAlgo_AsDes)& theAsDes); static void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theFSelfRebAvoid, const TopoDS_Shape& theSolids, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes); static void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const Standard_Boolean bLookVertToAvoid, TopTools_IndexedDataMapOfShapeListOfShape& theFLE, TopTools_DataMapOfShapeListOfShape& theMDone, TopTools_DataMapOfShapeListOfShape& theDMSF, TopTools_DataMapOfShapeListOfShape& theMEInfETrim, TopTools_DataMapOfShapeListOfShape& theDMVEFull, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv); static void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, const TopTools_DataMapOfShapeListOfShape& theDMVEFull, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theMVRInv); static void FindFacesForIntersection(const TopoDS_Shape& theFInv, const TopTools_IndexedMapOfShape& theME, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_DataMapOfShapeListOfShape& theDMSF, const TopTools_MapOfShape& theMVInvAll, const TopTools_DataMapOfShapeShape& theArtInvFaces, const Standard_Boolean theArtCase, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedMapOfShape& theMFAvoid, TopTools_IndexedMapOfShape& theMFInt, TopTools_IndexedMapOfShape& theMFIntExt, TopTools_ListOfShape& theLFImInt); static void ProcessCommonEdges(const TopTools_ListOfShape& theLEC, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_IndexedMapOfShape& theME, const TopTools_DataMapOfShapeShape& theETrimEInf, const TopTools_DataMapOfShapeListOfShape& theMEInfETrim, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_MapOfShape& theAllInvs, const Standard_Boolean theForceUse, TopTools_IndexedMapOfShape& theMECV, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theDMEETrim, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, TopTools_IndexedMapOfShape& theMEToInt); static void UpdateIntersectedFaces(const TopoDS_Shape& theFInv, const TopoDS_Shape& theFi, const TopoDS_Shape& theFj, const TopTools_ListOfShape& theLFInv, const TopTools_ListOfShape& theLFImi, const TopTools_ListOfShape& theLFImj, const TopTools_ListOfShape& theLFEi, const TopTools_ListOfShape& theLFEj, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_IndexedMapOfShape& theMEToInt); static void IntersectFaces(const TopoDS_Shape& theFInv, const TopoDS_Shape& theFi, const TopoDS_Shape& theFj, const TopTools_ListOfShape& theLFInv, const TopTools_ListOfShape& theLFImi, const TopTools_ListOfShape& theLFImj, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_IndexedMapOfShape& theMECV, TopTools_IndexedMapOfShape& theMEToInt); static void FindOrigins(const TopTools_ListOfShape& theLFIm1, const TopTools_ListOfShape& theLFIm2, const TopTools_IndexedMapOfShape& theME, const TopTools_DataMapOfShapeListOfShape& theOrigins, TopTools_ListOfShape& theLEOr); static void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedMapOfShape& theMFInt, const TopTools_IndexedMapOfShape& theMEInt, const TopTools_DataMapOfShapeListOfShape& theDMEETrim, const TopTools_IndexedMapOfShape& theMSInv, const TopTools_IndexedMapOfShape& theMVE, const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theNewVertsToAvoid, const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theMVBounds, TopTools_DataMapOfShapeListOfShape& theEImages); static void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theMVBounds, BOPAlgo_Builder& theGF, TopTools_MapOfShape& theMEInv); static void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theFLE, const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges, const TopTools_MapOfShape& theMVBounds, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, const TopTools_MapOfShape& theMEInvOnArt, TopTools_MapOfShape& theMECheckExt, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_DataMapOfShapeListOfShape& theEETrim, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes); static void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theEETrim, const TopTools_MapOfShape& theMVBounds, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theMEB, TopTools_MapOfShape& theMVOld, TopTools_MapOfShape& theMENew, TopTools_DataMapOfShapeListOfShape& theDMEOr, TopTools_DataMapOfShapeListOfShape& theMELF); static void IntersectEdges(const BOPCol_ListOfShape& theLA, const TopTools_ListOfShape& theLE, const TopTools_MapOfShape& theMVBounds, const TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMENew, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theModifiedEdges, TopTools_DataMapOfShapeListOfShape& theDMEOr, TopTools_DataMapOfShapeListOfShape& theMELF, TopoDS_Shape& theSplits); static void GetBounds(const TopTools_ListOfShape& theLFaces, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_MapOfShape& theMEB, TopoDS_Shape& theBounds); static void GetBoundsToUpdate(const TopTools_ListOfShape& theLF, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_MapOfShape& theMEB, TopTools_ListOfShape& theLABounds, TopTools_ListOfShape& theLAValid, TopoDS_Shape& theBounds, Handle(BRepAlgo_AsDes)& theAsDes); static void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& theBounds, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theMVOld, const TopTools_MapOfShape& theMENew, const TopTools_DataMapOfShapeListOfShape& theDMEOr, const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_MapOfShape& theMECheckExt, const TopTools_MapOfShape& theMEInvOnArt, Handle(IntTools_Context)& theCtx, TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMEInv); static void FilterSplits(const TopTools_ListOfShape& theLE, const TopTools_MapOfShape& theMEFilter, const Standard_Boolean theIsInv, TopTools_DataMapOfShapeListOfShape& theEImages, TopoDS_Shape& theSplits); static void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_DataMapOfShapeListOfShape& theEETrim, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes); static void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_DataMapOfShapeListOfShape& theEImages, BRepAlgo_Image& theImage); static void UpdateOrigins(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeListOfShape& theOrigins, BOPAlgo_Builder& theGF); static void UpdateImages(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_MapOfShape& theModified); static void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeShape& theETrimEInf, BOPAlgo_Builder& theGF); static Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge, const Handle(IntTools_Context)& theCtx); static void FindCommonParts(const TopTools_ListOfShape& theLS1, const TopTools_ListOfShape& theLS2, TopTools_ListOfShape& theLSC, const TopAbs_ShapeEnum theType = TopAbs_EDGE); static Standard_Integer NbPoints(const TopoDS_Edge& theE); static Standard_Boolean FindShape(const TopoDS_Shape& theSWhat, const TopoDS_Shape& theSWhere, TopoDS_Shape& theRes); static void AppendToList(TopTools_ListOfShape& theL, const TopoDS_Shape& theS); //======================================================================= //function : BuildSplitsOfTrimmedFaces //purpose : Building splits of already trimmed faces //======================================================================= void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF, Handle(BRepAlgo_AsDes)& theAsDes, BRepAlgo_Image& theImage) { TopTools_DataMapOfShapeListOfShape anEImages, anEOrigins; TopTools_IndexedDataMapOfShapeListOfShape aDMFFIm; TopTools_IndexedMapOfShape anEmptyIM; TopTools_DataMapOfShapeListOfShape anEmptyDMSLS; TopTools_DataMapOfShapeShape anEmptyDMSS; TopTools_MapOfShape aNewEdges, anEmptyM; // // firstly it is necessary to fuse all the edges Handle(IntTools_Context) aCtx = new IntTools_Context(); // IntersectTrimmedEdges(theLF, theAsDes, anEImages, anEOrigins, anEmptyDMSLS, aCtx, aNewEdges, anEmptyDMSS); // TopTools_ListIteratorOfListOfShape aItLF(theLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value(); // TopoDS_Shape aCE; TopTools_ListOfShape aLFImages; // Standard_Boolean bFound = GetEdges(aF, theAsDes, anEImages, anEmptyM, anEmptyIM, aCtx, aNewEdges, aCE, anEmptyIM); // split the face by the edges if (!bFound) { if (!theImage.HasImage(aF)) { aLFImages.Append(aF); aDMFFIm.Add(aF, aLFImages); } continue; } // BuildSplitsOfTrimmedFace(aF, aCE, aLFImages); aDMFFIm.Add(aF, aLFImages); } // Fill history for faces and edges FillHistory(aDMFFIm, anEImages, theImage); } //======================================================================= //function : BuildSplitsOfExtendedFaces //purpose : Building splits of not-trimmed offset faces. // For the cases in which invalidity will be found, // these invalidities will be rebuilt. //======================================================================= void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF, Handle(BRepAlgo_AsDes)& theAsDes, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeShape& theETrimEInf, BRepAlgo_Image& theImage) { Handle(IntTools_Context) aCtx = new IntTools_Context(); // images and origins for offset edges TopTools_DataMapOfShapeListOfShape anOEImages, anOEOrigins; TopTools_MapOfShape aNewEdges; // fusing all trimmed offset edges to avoid self-intersections in the splits IntersectTrimmedEdges(theLF, theAsDes, anOEImages, anOEOrigins, theEdgesOrigins, aCtx, aNewEdges, theETrimEInf); // // valid/invalid edges TopTools_IndexedMapOfShape anInvEdges, aValidEdges, anEdgesToAvoid; // inverted edges TopTools_MapOfShape anInvertedEdges; // splits of faces TopTools_IndexedDataMapOfShapeListOfShape aFImages; // found invalid faces TopTools_IndexedDataMapOfShapeListOfShape anInvFaces; // artificially invalid faces - it will be empty here, // but may be filled on the following rebuilding steps TopTools_DataMapOfShapeShape anArtInvFaces; // shapes connections for using in rebuilding TopTools_DataMapOfShapeListOfShape aSSInterfs; // edges to avoid on second steps TopTools_MapOfShape aLastInvEdges; // keep information of already invalid faces to avoid // infinite rebuilding of the same invalid face TopTools_DataMapOfShapeInteger anAlreadyInvFaces; // images of the hole faces of the original faces TopTools_DataMapOfShapeListOfShape aDMFNewHoles; // solid build from the new splits TopoDS_Shape aSolids; // now we can split the faces BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, theAsDes, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages, aDMFNewHoles, aSolids, aSSInterfs); // // Find faces to rebuild if (anInvFaces.Extent()) { TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild; TopTools_MapOfShape aFSelfRebAvoid; FindFacesToRebuild(aFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid); // if (aFToRebuild.Extent()) { // vertices to avoid TopTools_MapOfShape aVAEmpty; RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, aFImages, aDMFNewHoles, theEdgesOrigins, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes); } } // Fill history for faces and edges FillHistory(aFImages, anOEImages, theImage); } //======================================================================= //function : BuildSplitsOfInvFaces //purpose : Rebuilding splits of faces with new intersection edges //======================================================================= void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theModifiedEdges, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedMapOfShape& theValidEdges, TopTools_DataMapOfShapeShape& theETrimEInf, Handle(BRepAlgo_AsDes)& theAsDes) { Standard_Integer aNb = theFToRebuild.Extent(); if (!aNb) { return; } // TopTools_ListOfShape aLF; aNb = theFImages.Extent(); for (Standard_Integer i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theFImages.FindKey(i); aLF.Append(aF); } // // invalid faces TopTools_IndexedDataMapOfShapeListOfShape anInvFaces; // artificially invalid faces TopTools_DataMapOfShapeShape anArtInvFaces; // invalid edges TopTools_IndexedMapOfShape anInvEdges; // inverted edges TopTools_MapOfShape anInvertedEdges; // shapes connection for using in rebuilding process TopTools_DataMapOfShapeListOfShape aSSInterfs; // TopoDS_Shape aSolids; // BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAsDes, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages, theDMFNewHoles, aSolids, aSSInterfs); // if (anInvFaces.Extent()) { TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild; TopTools_MapOfShape aFSelfRebAvoid; FindFacesToRebuild(theFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid); // if (aFToRebuild.Extent()) { RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, theFImages, theDMFNewHoles, theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes); } } } //======================================================================= //function : BuildSplitsOfFaces //purpose : Building the splits of offset faces and // looking for the invalid splits //======================================================================= void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF, const TopTools_MapOfShape& theModifiedEdges, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, Handle(BRepAlgo_AsDes)& theAsDes, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopoDS_Shape& theSolids, TopTools_DataMapOfShapeListOfShape& theSSInterfs) { if (theLF.IsEmpty()) { return; } // BRep_Builder aBB; Standard_Integer i, aNb; // // processed faces TopTools_ListOfShape aLFDone; // extended face - list of neutral edges, i.e. in one splits - valid and in others - invalid TopTools_DataMapOfShapeListOfShape aDMFLNE; // list of valid edges for each face TopTools_DataMapOfShapeListOfShape aDMFLVE; // list of invalid edges for each face TopTools_DataMapOfShapeListOfShape aDMFLIE; // map of valid inverted edges for the face TopTools_DataMapOfShapeListOfShape aDMFLVIE; // map of splits to check for internals TopTools_IndexedMapOfShape aMFToCheckInt; // map of edges created from vertex and marked as invalid TopTools_MapOfShape aMEdgeInvalidByVertex; // connection map from old edges to new ones TopTools_DataMapOfShapeListOfShape aDMEOrLEIm; // Handle(IntTools_Context) aCtx = new IntTools_Context; // build splits of faces TopTools_ListIteratorOfListOfShape aItLF(theLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value(); // TopTools_ListOfShape* pLFIm = theFImages.ChangeSeek(aF); if (pLFIm && pLFIm->IsEmpty()) { continue; } // get edges by which the face should be split TopoDS_Shape aCE; TopTools_IndexedMapOfShape aMapEInv; Standard_Boolean bFound = GetEdges(aF, theAsDes, theOEImages, theLastInvEdges, theEdgesToAvoid, aCtx, theModifiedEdges, aCE, aMapEInv); if (!bFound) { continue; } // #ifdef OFFSET_DEBUG // check the found edges on self-intersection BRepAlgoAPI_Check aChecker(aCE); if (!aChecker.IsValid()) { cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n"; } #endif // build splits TopTools_ListOfShape aLFImages; BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages); // if (aMapEInv.Extent()) { // check if all possible faces are built TopTools_MapOfShape aMENInv; Standard_Boolean bArtificialCase = aLFImages.IsEmpty() || CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes); // // try to build splits using invalid edges TopoDS_Compound aCE1; aBB.MakeCompound(aCE1); aBB.Add(aCE1, aCE); for (i = 1; i <= aMapEInv.Extent(); ++i) { aBB.Add(aCE1, aMapEInv(i)); } // TopTools_ListOfShape aLFImages1; BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1); // // check if the rebuilding has added some new faces to the splits for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();) { Standard_Boolean bAllInv = Standard_True; const TopoDS_Shape& aFIm = aItLFIm.Value(); TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (!aMapEInv.Contains(aE)) { bAllInv = Standard_False; if (!aMENInv.Contains(aE)) { break; } } } // if (!aExpE.More()) { if (bAllInv) { aMFToCheckInt.Add(aFIm); } aLFImages1.Remove(aItLFIm); } else { aItLFIm.Next(); } } // if (bArtificialCase) { if (aLFImages.Extent() == aLFImages1.Extent()) { bArtificialCase = Standard_False; } else { aLFImages = aLFImages1; } } // if (bArtificialCase) { TopTools_ListOfShape aLEInv; // make the face invalid theArtInvFaces.Bind(aF, aCE); // *pLFIm = aLFImages; TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (aMapEInv.Contains(aE)) { theInvEdges.Add(aE); AppendToList(aLEInv, aE); } else { theValidEdges.Add(aE); } } } // aDMFLIE.Bind(aF, aLEInv); aLFDone.Append(aF); // continue; } } // // find invalid edges FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theInvEdges, theValidEdges, aDMFLVE, aDMFLNE, aDMFLIE, aDMFLVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex); // // save the new splits if (!pLFIm) { pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape())); } else { pLFIm->Clear(); } pLFIm->Append(aLFImages); // aLFDone.Append(aF); } // if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty()) { return; } // #ifdef OFFSET_DEBUG // show invalid edges TopoDS_Compound aCEInv1; BRep_Builder().MakeCompound(aCEInv1); Standard_Integer aNbEInv = theInvEdges.Extent(); for (i = 1; i <= aNbEInv; ++i) { const TopoDS_Shape& aE = theInvEdges(i); BRep_Builder().Add(aCEInv1, aE); } // show valid edges TopoDS_Compound aCEVal1; BRep_Builder().MakeCompound(aCEVal1); aNbEInv = theValidEdges.Extent(); for (i = 1; i <= aNbEInv; ++i) { const TopoDS_Shape& aE = theValidEdges(i); BRep_Builder().Add(aCEVal1, aE); } // show inverted edges TopoDS_Compound aCEInverted; BRep_Builder().MakeCompound(aCEInverted); TopTools_MapIteratorOfMapOfShape aItM(theInvertedEdges); for (; aItM.More(); aItM.Next()) { BRep_Builder().Add(aCEInverted, aItM.Value()); } #endif // TopTools_ListOfShape anEmptyList; // invalid faces inside the holes TopTools_IndexedMapOfShape aMFInvInHole; // all hole faces TopoDS_Compound aFHoles; aBB.MakeCompound(aFHoles); // find invalid faces // considering faces containing only invalid edges as invalid aItLF.Initialize(aLFDone); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aF = TopoDS::Face(aItLF.Value()); TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF); // TopTools_ListOfShape aLFInv; Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF); if (bArtificialCase) { aLFInv = aLFImages; } else { // neutral edges TopTools_ListOfShape* pLNE = aDMFLNE.ChangeSeek(aF); if (!pLNE) { pLNE = &anEmptyList; } // valid inverted edges TopTools_ListOfShape* pLIVE = aDMFLVIE.ChangeSeek(aF); if (!pLIVE) { pLIVE = &anEmptyList; } // // find faces inside holes wires TopTools_MapOfShape aMFHoles; const TopoDS_Face& aFOr = TopoDS::Face(theFacesOrigins.Find(aF)); FindFacesInsideHoleWires(aFOr, aF, aLFImages, theInvertedEdges, aDMEOrLEIm, aMFHoles, theDMFNewHoles, aCtx); // TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles); for (; aItMH.More(); aItMH.Next()) { aBB.Add(aFHoles, aItMH.Value()); } // // find invalid faces FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFLVE, aDMFLIE, *pLNE, *pLIVE, theInvertedEdges, aMEdgeInvalidByVertex, aMFHoles, aMFInvInHole, aLFInv); } // if (aLFInv.Extent()) { if (theAlreadyInvFaces.IsBound(aF)) { if (theAlreadyInvFaces.Find(aF) > 2) { if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) { aLFImages.Clear(); } // aLFInv.Clear(); } } theInvFaces.Add(aF, aLFInv); } } // if (theInvFaces.IsEmpty()) { theInvEdges.Clear(); return; } // #ifdef OFFSET_DEBUG // show invalid faces TopoDS_Compound aCFInv1; BRep_Builder().MakeCompound(aCFInv1); Standard_Integer aNbFInv = theInvFaces.Extent(); for (i = 1; i <= aNbFInv; ++i) { const TopTools_ListOfShape& aLFInv = theInvFaces(i); TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv); for (; aItLFInv.More(); aItLFInv.Next()) { const TopoDS_Shape& aFIm = aItLFInv.Value(); BRep_Builder().Add(aCFInv1, aFIm); } } #endif // TopTools_IndexedMapOfShape aMERemoved; // remove invalid splits of faces using inverted edges RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins, theInvFaces, theFImages, aMERemoved); if (theInvFaces.IsEmpty()) { theInvEdges.Clear(); return; } // // remove invalid splits from valid splits RemoveInvalidSplitsFromValid(theInvFaces, theArtInvFaces, theInvertedEdges, theFImages); // // remove inside faces TopTools_IndexedMapOfShape aMEInside; RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs, aMERemoved, aMEInside, theSolids); // // make compound of valid splits TopoDS_Compound aCFIm; aBB.MakeCompound(aCFIm); // aNb = theFImages.Extent(); for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLFIm = theFImages(i); aItLF.Initialize(aLFIm); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); aBB.Add(aCFIm, aFIm); } } // TopTools_IndexedDataMapOfShapeListOfShape aDMEF; TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF); // // filter maps of images and origins FilterEdgesImages(aCFIm, theOEImages, theOEOrigins); // // filter invalid faces FilterInvalidFaces(theFImages, aDMEF, aMEInside, theInvFaces, theArtInvFaces); aNb = theInvFaces.Extent(); if (!aNb) { theInvEdges.Clear(); return; } // #ifdef OFFSET_DEBUG // show invalid faces TopoDS_Compound aCFInv; BRep_Builder().MakeCompound(aCFInv); aNbFInv = theInvFaces.Extent(); for (i = 1; i <= aNbFInv; ++i) { const TopTools_ListOfShape& aLFInv = theInvFaces(i); TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv); for (; aItLFInv.More(); aItLFInv.Next()) { const TopoDS_Shape& aFIm = aItLFInv.Value(); BRep_Builder().Add(aCFInv, aFIm); } } #endif // // filter invalid edges FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFLIE, aMERemoved, theInvEdges); // #ifdef OFFSET_DEBUG // show invalid edges TopoDS_Compound aCEInv; BRep_Builder().MakeCompound(aCEInv); aNbEInv = theInvEdges.Extent(); for (i = 1; i <= aNbEInv; ++i) { const TopoDS_Shape& aE = theInvEdges(i); BRep_Builder().Add(aCEInv, aE); } #endif // theLastInvEdges.Clear(); aNb = theInvEdges.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aE = theInvEdges(i); theEdgesToAvoid.Add(aE); theLastInvEdges.Add(aE); } // aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); if (theAlreadyInvFaces.IsBound(aF)) { theAlreadyInvFaces.ChangeFind(aF)++; } else { theAlreadyInvFaces.Bind(aF, 1); } } } //======================================================================= //function : IntersectTrimmedEdges //purpose : Intersection of the trimmed edges among themselves //======================================================================= void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF, const Handle(BRepAlgo_AsDes)& theAsDes, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, Handle(IntTools_Context)& theCtx, TopTools_MapOfShape& theNewEdges, TopTools_DataMapOfShapeShape& theETrimEInf) { if (theLF.IsEmpty()) { return; } // // get edges to intersect from descendants of the offset faces BOPCol_ListOfShape aLS; // TopTools_ListIteratorOfListOfShape aItLF(theLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value(); // const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF); TopTools_ListIteratorOfListOfShape aItLE(aLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value(); // if (ProcessMicroEdge(aE, theCtx)) { continue; } // if (theNewEdges.Add(aE)) { aLS.Append(aE); } } } // if (aLS.Extent() < 2) { // nothing to intersect return; } // // perform intersection of the edges BOPAlgo_Builder aGFE; aGFE.SetArguments(aLS); aGFE.Perform(); if (aGFE.HasErrors()) { return; } // TopTools_ListOfShape aLA; // fill map with edges images BOPCol_ListIteratorOfListOfShape aIt(aLS); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE); if (aLEIm.IsEmpty()) { continue; } // aLA.Append(aE); // save images theOEImages.Bind(aE, aLEIm); // save origins TopTools_ListIteratorOfListOfShape aItLE(aLEIm); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEIm = aItLE.Value(); TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm); if (!pLEOr) { pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape()); } AppendToList(*pLEOr, aE); } } // UpdateOrigins(aLA, theEdgesOrigins, aGFE); UpdateIntersectedEdges(aLA, theETrimEInf, aGFE); } //======================================================================= //function : GetEdges //purpose : Getting edges from AsDes map to build the splits of faces //======================================================================= Standard_Boolean GetEdges(const TopoDS_Face& theFace, const Handle(BRepAlgo_AsDes)& theAsDes, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_MapOfShape& theLastInvEdges, const TopTools_IndexedMapOfShape& theInvEdges, Handle(IntTools_Context)& theCtx, const TopTools_MapOfShape& theModifiedEdges, TopoDS_Shape& theEdges, TopTools_IndexedMapOfShape& theInv) { // get boundary edges TopTools_MapOfShape aMFBounds; TopExp_Explorer aExp(theFace, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE); if (!pLEIm) { aMFBounds.Add(aE); } else { TopTools_ListIteratorOfListOfShape aItLE(*pLEIm); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEIm = aItLE.Value(); aMFBounds.Add(aEIm); } } } // BRep_Builder aBB; Standard_Boolean bFound(Standard_False), bUpdate(Standard_False); // the resulting edges TopoDS_Compound anEdges; aBB.MakeCompound(anEdges); // Fence map TopTools_MapOfShape aMEFence; // the edges by which the offset face should be split const TopTools_ListOfShape& aLE = theAsDes->Descendant(theFace); TopTools_ListIteratorOfListOfShape aItLE(aLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value()); // if (!bUpdate) { bUpdate = theModifiedEdges.Contains(aE); } // const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE); if (pLEIm) { TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value()); // if (!aMEFence.Add(aEIm)) continue; if (theInvEdges.Contains(aEIm)) { theInv.Add(aEIm); if (!bUpdate) { bUpdate = theLastInvEdges.Contains(aEIm); } continue; } // check for micro edge if (ProcessMicroEdge(aEIm, theCtx)) { continue; } // aBB.Add(anEdges, aEIm); if (!bFound) { bFound = !aMFBounds.Contains(aEIm); } // if (!bUpdate) { bUpdate = theModifiedEdges.Contains(aEIm); } } } else { if (theInvEdges.Contains(aE)) { theInv.Add(aE); if (!bUpdate) { bUpdate = theLastInvEdges.Contains(aE); } continue; } // if (ProcessMicroEdge(aE, theCtx)) { continue; } aBB.Add(anEdges, aE); if (!bFound) { bFound = !aMFBounds.Contains(aE); } } } // theEdges = anEdges; return bFound && bUpdate; } //======================================================================= //function : BuildSplitsOfFace //purpose : Building the splits of offset face //======================================================================= void BuildSplitsOfFace(const TopoDS_Face& theFace, const TopoDS_Shape& theEdges, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_ListOfShape& theLFImages) { theLFImages.Clear(); // // take edges to split the face BOPCol_ListOfShape aLE; TopExp_Explorer aExp(theEdges, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { TopoDS_Edge aE = TopoDS::Edge(aExp.Current()); aE.Orientation(TopAbs_FORWARD); aLE.Append(aE); aE.Orientation(TopAbs_REVERSED); aLE.Append(aE); } // TopoDS_Face aFF = theFace; TopAbs_Orientation anOr = theFace.Orientation(); aFF.Orientation(TopAbs_FORWARD); // // build pcurves for edges on the face BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane(aLE, aFF); // // build splits of faces BOPAlgo_BuilderFace aBF; aBF.SetFace(aFF); aBF.SetShapes(aLE); aBF.Perform(); // const BOPCol_ListOfShape& aLFSp = aBF.Areas(); BOPCol_ListIteratorOfListOfShape aItLF(aLFSp); for (; aItLF.More(); aItLF.Next()) { TopoDS_Shape& aFSp = aItLF.ChangeValue(); aFSp.Orientation(anOr); theLFImages.Append(aFSp); // theFacesOrigins.Bind(aFSp, theFace); } } //======================================================================= //function : BuildSplitsOfFace //purpose : Building the splits of offset face //======================================================================= void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace, const TopoDS_Shape& theEdges, TopTools_ListOfShape& theLFImages) { BOPAlgo_Builder aGF; // aGF.AddArgument(theFace); aGF.AddArgument(theEdges); aGF.Perform(); if (aGF.HasErrors()) { return; } // // splits of the offset shape theLFImages = aGF.Modified(theFace); } //======================================================================= //function : CheckIfArtificial //purpose : Checks if the face is artificially invalid //======================================================================= Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF, const TopTools_ListOfShape& theLFImages, const TopoDS_Shape& theCE, const TopTools_IndexedMapOfShape& theMapEInv, const TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_MapOfShape& theMENInv, Handle(BRepAlgo_AsDes)& theAsDes) { // all boundary edges should be used TopTools_IndexedMapOfShape aMEUsed; TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed); TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed); } // TopTools_IndexedDataMapOfShapeListOfShape aMVE; TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE); // Standard_Integer i, aNb = theMapEInv.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aEInv = theMapEInv(i); TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aVEInv = aExpV.Current(); const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv); if (pLENInv) { TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv); for (; aItLEInv.More(); aItLEInv.Next()) { const TopoDS_Shape& aENInv = aItLEInv.Value(); if (!aMEUsed.Contains(aENInv)) { theMENInv.Add(aENInv); } } } } } // if (theMENInv.IsEmpty()) { return Standard_False; } // TopTools_IndexedMapOfShape aMEFound; TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound); // const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF); TopTools_ListIteratorOfListOfShape aItLE(aLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value()); // if (theOEImages.IsBound(aE)) { Standard_Boolean bChecked = Standard_False; const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE); TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value()); if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) { continue; } // bChecked = Standard_True; if (aMEUsed.Contains(aEIm)) { break; } } // if (bChecked && !aItLEIm.More()) { break; } } else { if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) { break; } } } // return aItLE.More(); } //======================================================================= //function : FindInvalidEdges //purpose : Looking for the invalid edges //======================================================================= void FindInvalidEdges(const TopoDS_Face& theF, const TopTools_ListOfShape& theLFImages, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, const TopTools_DataMapOfShapeShape& theFacesOrigins, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, TopTools_DataMapOfShapeListOfShape& theDMFLVE, TopTools_DataMapOfShapeListOfShape& theDMFLNE, TopTools_DataMapOfShapeListOfShape& theDMFLIE, TopTools_DataMapOfShapeListOfShape& theDMFLVIE, TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm, TopTools_MapOfShape& theMEInverted, TopTools_MapOfShape& theEdgesInvalidByVertex) { // Edge is considered as invalid in the following cases: // 1. Its orientation on the face has changed comparing to the originals edge and face; // 2. The vertices of the edge have changed places comparing to the originals edge and face. // // The edges created from vertices, i.e. as intersection between two faces connected only // by VERTEX, will also be checked on validity. For these edges the correct orientation will // be defined by the edges on the original face adjacent to the connection vertex // original face const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF); // invalid edges TopTools_IndexedMapOfShape aMEInv; // valid edges TopTools_MapOfShape aMEVal; // internal edges TopTools_MapOfShape aMEInt; // // maps for checking the inverted edges TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF; TopTools_IndexedMapOfShape aMEdges; // TopTools_ListIteratorOfListOfShape aItLF(theLFImages); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); // TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); // keep all edges aMEdges.Add(aE); // // keep connection from edges to faces TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE); if (!pLF) { pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape())); } AppendToList(*pLF, aFIm); // // keep connection from vertices to edges TopoDS_Iterator aItV(aE); for (; aItV.More(); aItV.Next()) { const TopoDS_Shape& aV = aItV.Value(); // TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV); if (!pLE) { pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape())); } AppendToList(*pLE, aE); } } } // // the map will be used to find the edges on the original face // adjacent to the same vertex. It will be filled at first necessity; TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr; // aItLF.Initialize(theLFImages); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); // // valid edges for this split TopTools_ListOfShape aLVE; // invalid edges for this split TopTools_ListOfShape aLIE; // TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current(); // if (aEIm.Orientation() == TopAbs_INTERNAL) { aMEInt.Add(aEIm); continue; } // if (!theEdgesOrigins.IsBound(aEIm)) { continue; } // const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm); if (aLEOr.IsEmpty()) { continue; } // Standard_Integer aNbVOr = 0; TopTools_ListIteratorOfListOfShape aItLEO(aLEOr); for (; aItLEO.More(); aItLEO.Next()) { if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) { ++aNbVOr; } } // TopTools_MapOfShape aME, aMV; Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False; Standard_Integer aNbP = NbPoints(aEIm); Standard_Boolean bUseVertex = !aNbVOr ? Standard_False : (aNbVOr == 1 && aDMEF.FindFromKey(aEIm).Extent() == 1 && !theOEOrigins.IsBound(aEIm)); // aItLEO.Initialize(aLEOr); for (; aItLEO.More(); aItLEO.Next()) { const TopoDS_Shape& aSOr = aItLEO.Value(); Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX); // TopoDS_Shape aEOrF; if (bVertex) { // for some cases it is impossible to check the validity of the edge if (!bUseVertex) { continue; } // find edges on the original face adjacent to this vertex if (aDMVEFOr.IsEmpty()) { // fill the map TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr); } // TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr); if (pLEFOr) { TopoDS_Compound aCEOr; BRep_Builder().MakeCompound(aCEOr); TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr); for (; aItLEFOr.More(); aItLEFOr.Next()) { const TopoDS_Shape& aEOr = aItLEFOr.Value(); BRep_Builder().Add(aCEOr, aEOr); } aEOrF = aCEOr; } } else { FindShape(aSOr, aFOr, aEOrF); // TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr); if (!pLEIm) { pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape()); } AppendToList(*pLEIm, aEIm); } // if (aEOrF.IsNull()) { // the edge has not been found continue; } // // Check orientations of the image edge and original edge. // In case the 3d curves are having the same direction the orientations // must be the same. Otherwise the orientations should also be different. // // get average tangent vector for each curve taking into account // the orientations of the edges, i.e. the edge is reversed // the vector is reversed as well gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP); gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP); // aVSum1.Normalize(); aVSum2.Normalize(); // Standard_Real aCos = aVSum1.Dot(aVSum2); if (!bVertex) { if (Abs(aCos) < 0.9999) { continue; } // aME.Add(aEOrF); TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aV = aExpE.Current(); aMV.Add(aV); } } // if (aCos < Precision::Confusion()) { bInvalid = Standard_True; if (bVertex) { theEdgesInvalidByVertex.Add(aEIm); } } bChecked = Standard_True; } // if (!bChecked) { continue; } // Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent(); if ((aNbE > 1) && (aNbV == 2*aNbE)) { continue; } // if (bInvalid) { theInvEdges.Add(aEIm); aLIE.Append(aEIm); aMEInv.Add(aEIm); continue; } // // check if the edge has been inverted Standard_Boolean bInverted = !aNbE ? Standard_False : CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins, theEdgesOrigins, aDMVE, aMEdges, theMEInverted); // if (!bInverted || !aNbVOr) { theValidEdges.Add(aEIm); aLVE.Append(aEIm); aMEVal.Add(aEIm); } } // // valid edges if (aLVE.Extent()) { theDMFLVE.Bind(aFIm, aLVE); } // // invalid edges if (aLIE.Extent()) { theDMFLIE.Bind(aFIm, aLIE); } } // // process invalid edges: // check for the inverted edges TopTools_ListOfShape aLVIE; // fill neutral edges TopTools_ListOfShape aLNE; // Standard_Integer i, aNbEInv = aMEInv.Extent(); for (i = 1; i <= aNbEInv; ++i) { const TopoDS_Shape& aEIm = aMEInv(i); // // neutral edges - on the splits of the same offset face // it is valid for one split and invalid for other if (aMEVal.Contains(aEIm)) { aLNE.Append(aEIm); continue; } // // the inverted images of the origins of invalid edges should also be invalid if (!theMEInverted.Contains(aEIm)) { continue; } // const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm); if (!pLOEOr) { continue; } // TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr); for (; aItLOEOr.More(); aItLOEOr.Next()) { const TopoDS_Shape& aOEOr = aItLOEOr.Value(); const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr); // TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1); for (; aItLEIm1.More(); aItLEIm1.Next()) { const TopoDS_Shape& aEIm1 = aItLEIm1.Value(); if (aMEdges.Contains(aEIm1) && !aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) && theMEInverted.Contains(aEIm1)) { theInvEdges.Add(aEIm1); aLVIE.Append(aEIm1); } } } } // if (aLNE.Extent()) { theDMFLNE.Bind(theF, aLNE); } // if (aLVIE.Extent()) { theDMFLVIE.Bind(theF, aLVIE); } } //======================================================================= //function : FindInvalidFaces //purpose : Looking for the invalid faces by analyzing their invalid edges //======================================================================= void FindInvalidFaces(TopTools_ListOfShape& theLFImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_DataMapOfShapeListOfShape& theDMFLVE, const TopTools_DataMapOfShapeListOfShape& theDMFLIE, const TopTools_ListOfShape& theLENeutral, const TopTools_ListOfShape& theLEValInverted, const TopTools_MapOfShape& theMEInverted, const TopTools_MapOfShape& theEdgesInvalidByVertex, const TopTools_MapOfShape& theMFHoles, TopTools_IndexedMapOfShape& theMFInvInHole, TopTools_ListOfShape& theInvFaces) { // The face should be considered as invalid in the following cases: // 1. It has been reverted, i.e. at least two not connected edges // have changed orientation (i.e. invalid). In this case all edges, // should be invalid for that face, because edges have also been reverted; // 2. All checked edges of the face are invalid for this face; // The face should be removed from the splits in the following cases: // 1. All checked edges of the face are invalid for this one, but valid for // some other face in this list of splits. // The face will be kept in the following cases: // 1. Some of the edges are valid for this face. Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral; Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral; Standard_Integer i, aNbChecked; // // neutral edges TopTools_MapOfShape aMEN; for (TopTools_ListIteratorOfListOfShape aItLE(theLENeutral); aItLE.More(); aItLE.Next()) { aMEN.Add(aItLE.Value()); } // // valid inverted edges TopTools_MapOfShape aMEValInverted; for (TopTools_ListIteratorOfListOfShape aItLE(theLEValInverted); aItLE.More(); aItLE.Next()) { aMEValInverted.Add(aItLE.Value()); } // Standard_Boolean bCheckInverted = (theLFImages.Extent() == 1); // // neutral edges to remove TopTools_IndexedMapOfShape aMENRem; // // faces for post treat TopTools_ListOfShape aLFPT; // TopTools_ListIteratorOfListOfShape aItLF(theLFImages); for (; aItLF.More(); ) { const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); // // valid edges for this split TopTools_MapOfShape aMVE; // invalid edges for this split TopTools_MapOfShape aMIE; // for (i = 0; i < 2; ++i) { TopTools_MapOfShape& aME = !i ? aMVE : aMIE; const TopTools_ListOfShape* pLE = !i ? theDMFLVE.Seek(aFIm) : theDMFLIE.Seek(aFIm); if (pLE) { TopTools_ListIteratorOfListOfShape aItLE(*pLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); aME.Add(aE); } } } // bHasValid = Standard_False; bAllValid = Standard_True; bAllInvalid = Standard_True; bHasReallyInvalid = Standard_False; bAllInvNeutral = Standard_True; aNbChecked = 0; // const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm); TopExp_Explorer aExp(aWIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aEIm = aExp.Current(); // bValid = theValidEdges.Contains(aEIm); bInvalid = theInvEdges.Contains(aEIm); // if (!bValid && !bInvalid) { // edge has not been checked for some reason continue; } // ++aNbChecked; // bInvalidLoc = aMIE.Contains(aEIm); bHasReallyInvalid = bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm); if (bHasReallyInvalid) { break; } // bNeutral = aMEN.Contains(aEIm); bValidLoc = aMVE.Contains(aEIm); // if (!bInvalid && bCheckInverted) { bInvalid = theMEInverted.Contains(aEIm); } // if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) { bHasValid = Standard_True; } // bAllValid = bAllValid && bValidLoc; bAllInvalid = bAllInvalid && bInvalid; bAllInvNeutral = bAllInvNeutral && bAllInvalid && bNeutral; } // if (!aNbChecked) { aItLF.Next(); continue; } // if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) { // remove edges from neutral TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem); // remove face theLFImages.Remove(aItLF); continue; } // if (bHasReallyInvalid || (bAllInvalid && !(bHasValid || bAllValid) && !(bAllInvNeutral && (aNbChecked == 1)))) { theInvFaces.Append(aFIm); if (theMFHoles.Contains(aFIm)) { theMFInvInHole.Add(aFIm); } aItLF.Next(); continue; } // if (theMFHoles.Contains(aFIm)) { // remove edges from neutral TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem); // remove face theLFImages.Remove(aItLF); continue; } // if (!bAllInvNeutral) { aLFPT.Append(aFIm); } else { // remove edges from neutral TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem); } aItLF.Next(); } // if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) { return; } // Standard_Integer aNb = aMENRem.Extent(); for (i = 1; i <= aNb; ++i) { aMEN.Remove(aMENRem(i)); } // // check the splits once more aItLF.Initialize(aLFPT); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); // // valid edges for this split TopTools_MapOfShape aMVE; const TopTools_ListOfShape* pLVE = theDMFLVE.Seek(aFIm); if (pLVE) { TopTools_ListIteratorOfListOfShape aItLE(*pLVE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); aMVE.Add(aE); } } // bHasValid = Standard_False; bAllValid = Standard_True; bAllInvalid = Standard_True; // const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm); TopExp_Explorer aExp(aWIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aEIm = aExp.Current(); // bValid = theValidEdges.Contains(aEIm); bInvalid = theInvEdges.Contains(aEIm); bNeutral = aMEN.Contains(aEIm); bValidLoc = aMVE.Contains(aEIm); // if (!bInvalid && bCheckInverted) { bInvalid = theMEInverted.Contains(aEIm); } // if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) { bHasValid = Standard_True; } // bAllValid = bAllValid && bValidLoc; bAllInvalid = bAllInvalid && bInvalid; } // if (bAllInvalid && !bHasValid && !bAllValid) { theInvFaces.Append(aFIm); } } } //======================================================================= //function : FindFacesInsideHoleWires //purpose : Find faces inside holes wires from the original face //======================================================================= void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin, const TopoDS_Face& theFOffset, const TopTools_ListOfShape& theLFImages, const TopTools_MapOfShape& theInvertedEdges, const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm, TopTools_MapOfShape& theMFHoles, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, Handle(IntTools_Context)& theContext) { if (theLFImages.IsEmpty()) { return; } // // find all hole wires in the original face TopTools_ListOfShape aLHoleWires; const TopoDS_Wire& anOuterWire = BRepTools::OuterWire(theFOrigin); TopExp_Explorer aExpW(theFOrigin, TopAbs_WIRE); for (; aExpW.More(); aExpW.Next()) { const TopoDS_Wire& aHoleWire = TopoDS::Wire(aExpW.Current()); if (!aHoleWire.IsSame(anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL) { aLHoleWires.Append(aHoleWire); } } // if (aLHoleWires.IsEmpty()) { // no holes in the face return; } // TopTools_ListOfShape *pLFNewHoles = theDMFNewHoles.ChangeSeek(theFOrigin); // if (!pLFNewHoles) { pLFNewHoles = theDMFNewHoles.Bound(theFOrigin, TopTools_ListOfShape()); } if (pLFNewHoles->IsEmpty()) { // // find the faces representing holes in the images of the faces: // 1. for each original hole wire try to build its image // 2. build the new planar face from the images // // map vertices and edges of the splits TopTools_IndexedMapOfShape aMESplits; TopTools_ListIteratorOfListOfShape aItLF(theLFImages); for (; aItLF.More(); aItLF.Next()) { TopExp::MapShapes(aItLF.Value(), TopAbs_EDGE, aMESplits); } // TopTools_ListIteratorOfListOfShape aItLW(aLHoleWires); for (; aItLW.More(); aItLW.Next()) { const TopoDS_Wire& aHoleWire = TopoDS::Wire(aItLW.Value()); // find images of all edges of the original wire TopTools_IndexedMapOfShape aMEImWire; TopoDS_Iterator aItE(aHoleWire); for (; aItE.More(); aItE.Next()) { const TopoDS_Shape& aEOr = aItE.Value(); const TopTools_ListOfShape *pLEIm = theDMEOrLEIm.Seek(aEOr); if (!pLEIm || pLEIm->IsEmpty()) { continue; } TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); if (aMESplits.Contains(aEIm)) { aMEImWire.Add(aEIm); } } } // if (aMEImWire.IsEmpty()) { continue; } // // build new planar face using these edges BOPCol_ListOfShape aLE; Standard_Integer i, aNbE = aMEImWire.Extent(); for (i = 1; i <= aNbE; ++i) { aLE.Append(aMEImWire(i).Oriented(TopAbs_FORWARD)); aLE.Append(aMEImWire(i).Oriented(TopAbs_REVERSED)); } // BOPAlgo_BuilderFace aBF; aBF.SetFace(TopoDS::Face(theFOffset.Oriented(TopAbs_FORWARD))); aBF.SetShapes(aLE); aBF.Perform(); // const BOPCol_ListOfShape& aLFNew = aBF.Areas(); if (aLFNew.IsEmpty()) { continue; } // // check if outer edges in the new faces are not inverted // because the inverted edges mean that the hole has been // filled during offset and there will be no faces to remove TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew; TopTools_ListIteratorOfListOfShape aItLFNew(aLFNew); for (; aItLFNew.More(); aItLFNew.Next()) { TopExp::MapShapesAndAncestors(aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew); } // aNbE = aDMEFNew.Extent(); for (i = 1; i <= aNbE; ++i) { if (aDMEFNew(i).Extent() == 1) { const TopoDS_Shape& aE = aDMEFNew.FindKey(i); if (theInvertedEdges.Contains(aE)) { break; } } } // if (i <= aNbE) { continue; } // aItLFNew.Initialize(aLFNew); for (; aItLFNew.More(); aItLFNew.Next()) { pLFNewHoles->Append(aItLFNew.Value()); } } } // // among the splits of the offset face find those that are // located inside the hole faces // TopTools_ListIteratorOfListOfShape aItLF(theLFImages); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value()); // // get the point inside the face and classify it relatively hole faces gp_Pnt aP3D; gp_Pnt2d aP2D; Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(aFIm, aP3D, aP2D, theContext); if (iErr) { continue; } // Standard_Real aTol = BRep_Tool::Tolerance(aFIm); // TopTools_ListIteratorOfListOfShape aItLFNew(*pLFNewHoles); for (; aItLFNew.More(); aItLFNew.Next()) { const TopoDS_Face& aFNew = TopoDS::Face(aItLFNew.Value()); if (theContext->IsValidPointForFace(aP3D, aFNew, aTol)) { // the face is classified as IN theMFHoles.Add(aFIm); break; } } } } //======================================================================= //function : GetAverageTangent //purpose : Computes average tangent vector along the curve //======================================================================= gp_Vec GetAverageTangent(const TopoDS_Shape& theS, const Standard_Integer theNbP) { gp_Vec aVA; TopExp_Explorer aExp(theS, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current(); // Standard_Real aT1, aT2; const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2); // gp_Pnt aP; gp_Vec aV, aVSum; Standard_Real aT = aT1; Standard_Real aDt = (aT2 - aT1) / theNbP; while (aT <= aT2) { aC->D1(aT, aP, aV); aVSum += aV.Normalized(); aT += aDt; } // if (aE.Orientation() == TopAbs_REVERSED) { aVSum.Reverse(); } // aVA += aVSum; } return aVA; } //======================================================================= //function : CheckInverted //purpose : Checks if the edge has been inverted //======================================================================= Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm, const TopoDS_Face& theFOr, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE, const TopTools_IndexedMapOfShape& theMEdges, TopTools_MapOfShape& theMEInverted) { // It is necessary to compare the direction from first vertex // to the last vertex on the original edge with the // same direction on the new edge. If the directions // will be different - the edge has been inverted. // TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge TopoDS_Vertex aVO1, aVO2; // vertices on the original edge // Standard_Integer i; // find vertices of the offset shape TopExp::Vertices(theEIm, aVI1, aVI2); // // find images TopTools_ListOfShape aLEImages; if (theOEOrigins.IsBound(theEIm)) { TopoDS_Wire anImages; BRep_Builder().MakeWire(anImages); // TopTools_MapOfShape aMImFence; const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm); TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr); for (; aItOffset.More(); aItOffset.Next()) { const TopoDS_Shape& aEOffsetOr = aItOffset.Value(); const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr); // TopTools_ListIteratorOfListOfShape aItImages(aLImages); for (; aItImages.More(); aItImages.Next()) { const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value(); if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) { BRep_Builder().Add(anImages, anIm); aLEImages.Append(anIm); } } } // // find alone vertices TopoDS_Vertex aVW1, aVW2; TopTools_IndexedDataMapOfShapeListOfShape aDMImVE; TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE); // TopTools_ListOfShape aLVAlone; Standard_Integer aNb = aDMImVE.Extent(); for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLImE = aDMImVE(i); if (aLImE.Extent() == 1) { aLVAlone.Append(aDMImVE.FindKey(i)); } } // if (aLVAlone.Extent() > 1) { aVW1 = *(TopoDS_Vertex*)&aLVAlone.First(); aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last(); // // check distances const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1); const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1); const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2); // Standard_Real aDist1 = aPI1.SquareDistance(aPW1); Standard_Real aDist2 = aPI1.SquareDistance(aPW2); // if (aDist1 < aDist2) { aVI1 = aVW1; aVI2 = aVW2; } else { aVI1 = aVW2; aVI2 = aVW1; } } } else { aLEImages.Append(theEIm); } // // Find edges connected to these vertices const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1); const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2); // // Find vertices on the original face corresponding to vertices on the offset edge // // find original edges for both lists TopTools_ListOfShape aLOE1, aLOE2; for (i = 0; i < 2; ++i) { const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2; TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2; // TopTools_MapOfShape aMFence; // TopTools_ListIteratorOfListOfShape aItLIE(aLIE); for (; aItLIE.More(); aItLIE.Next()) { const TopoDS_Shape& aEI = aItLIE.Value(); if (theEdgesOrigins.IsBound(aEI)) { const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI); // TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins); for (; aItLOE.More(); aItLOE.Next()) { const TopoDS_Shape& aEO = aItLOE.Value(); if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) { TopoDS_Shape aEOin; if (FindShape(aEO, theFOr, aEOin)) { AppendToList(aLOE, aEO); } } } } } } // if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) { return Standard_False; } // // find vertices common for all edges in the lists for (i = 0; i < 2; ++i) { const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2; TopoDS_Vertex& aVO = !i ? aVO1 : aVO2; // const TopoDS_Shape& aEO = aLOE.First(); TopExp_Explorer aExpV(aEO, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current(); // Standard_Boolean bVertValid = Standard_True; TopTools_ListIteratorOfListOfShape aItLOE(aLOE); for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) { const TopoDS_Shape& aEOx = aItLOE.Value(); TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX); for (; aExpVx.More(); aExpVx.Next()) { const TopoDS_Shape& aVx = aExpVx.Current(); if (aVx.IsSame(aV)) { break; } } // if (!aExpVx.More()) { bVertValid = Standard_False; break; } } // if (bVertValid) { aVO = aV; break; } } } // if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) { return Standard_False; } // // check positions of the offset and original vertices const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1); const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2); const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1); const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2); // gp_Vec aVI(aPI1, aPI2); gp_Vec aVO(aPO1, aPO2); // Standard_Real anAngle = aVI.Angle(aVO); Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4; if (bInverted) { TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEInvr = aItLEIm.Value(); theMEInverted.Add(aEInvr); } } return bInverted; } //======================================================================= //function : CheckInvertedBlock //purpose : Checks if it is possible to remove the block containing // inverted edges //======================================================================= Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB, const TopTools_ListOfShape& theLCBF, const TopTools_MapOfShape& theMEInverted, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted, BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll) { // For possible removal of the block: // 1. There should be more than just one face in the block TopoDS_Iterator aItF(theCB); aItF.Next(); if (!aItF.More()) { return Standard_False; } // // 2. The block should at least contain two connected inverted edges with // different origins (not just two images/splits of the same edge) TopTools_MapOfShape aMECBInv; TopoDS_Compound aCECBInv; BRep_Builder().MakeCompound(aCECBInv); // TopExp_Explorer aExp(theCB, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (theMEInverted.Contains(aE)) { if (aMECBInv.Add(aE)) { BRep_Builder().Add(aCECBInv, aE); } } } // if (aMECBInv.Extent() < 2) { return Standard_False; } // // check that the edges are connected and different TopTools_ListOfShape aLCBE; BOPTools_AlgoTools::MakeConnexityBlocks(aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); // TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE); for (; aItLCBE.More(); aItLCBE.Next()) { const TopoDS_Shape& aCBE = aItLCBE.Value(); // count the unique edges in the block Standard_Integer aNbUnique = 0; TopTools_MapOfShape aMEOrigins; TopoDS_Iterator aItE(aCBE); for (; aItE.More(); aItE.Next()) { const TopoDS_Shape& aE = aItE.Value(); const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); if (!pLEOr) { aMEOrigins.Add(aE); ++aNbUnique; continue; } TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { const TopoDS_Shape& aEOr = aItLEOr.Value(); if (aMEOrigins.Add(aEOr)) { ++aNbUnique; } } } // if (aNbUnique >= 2) { break; } } // if (!aItLCBE.More()) { return Standard_False; } // // 3. the block should not contain inverted edges which vertices // are contained in other blocks // // collect vertices from inverted edges and compare them with // vertices from other blocks TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek(theCB); TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek(theCB); if (!pMVInverted) { pMVInverted = theDMCBVInverted.Bound(theCB, TopTools_MapOfShape()); pMVAll = theDMCBVAll.Bound(theCB, TopTools_MapOfShape()); // GetVerticesOnEdges(theCB, theMEInverted, *pMVInverted, *pMVAll); } // TopTools_ListIteratorOfListOfShape aItLCB1(theLCBF); for (; aItLCB1.More(); aItLCB1.Next()) { const TopoDS_Shape& aCB1 = aItLCB1.Value(); if (aCB1.IsSame(theCB)) { continue; } // // collect vertices from inverted edges TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek(aCB1); TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek(aCB1); if (!pMVInverted1) { pMVInverted1 = theDMCBVInverted.Bound(aCB1, TopTools_MapOfShape()); pMVAll1 = theDMCBVAll.Bound(aCB1, TopTools_MapOfShape()); // GetVerticesOnEdges(aCB1, theMEInverted, *pMVInverted1, *pMVAll1); } // if (pMVInverted->HasIntersection(*pMVAll1)) { return Standard_False; } } // return Standard_True; } //======================================================================= //function : GetVerticesOnEdges //purpose : Get vertices from the given shape belonging to the given edges //======================================================================= void GetVerticesOnEdges(const TopoDS_Shape& theCB, const TopTools_MapOfShape& theEdges, TopTools_MapOfShape& theVerticesOnEdges, TopTools_MapOfShape& theAllVertices) { TopExp_Explorer aExp(theCB, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); Standard_Boolean bOnGivenEdge = theEdges.Contains(aE); for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { theAllVertices.Add(aItV.Value()); if (bOnGivenEdge) { theVerticesOnEdges.Add(aItV.Value()); } } } } //======================================================================= //function : RemoveInvalidSplitsByInvertedEdges //purpose : Looking for the invalid faces containing inverted edges // that can be safely removed //======================================================================= void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_IndexedMapOfShape& theMERemoved) { if (theMEInverted.IsEmpty()) { return; } // // check the faces on regularity, i.e. the splits of the same face // should not be connected only by vertex. Such irregular splits // will have to be rebuilt and cannot be removed. // BRep_Builder aBB; TopTools_IndexedMapOfShape aMEAvoid; TopTools_DataMapOfShapeListOfShape aDMVF; Standard_Integer aNb = theFImages.Extent(), i; for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLFIm = theFImages(i); // TopoDS_Compound aCFIm; aBB.MakeCompound(aCFIm); // TopTools_DataMapOfShapeListOfShape aDMEF; TopTools_ListIteratorOfListOfShape aIt(aLFIm); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aF = aIt.Value(); aBB.Add(aCFIm, aF); // // make a map to use only outer edges TopExp_Explorer aExp(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); // TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE); if (!pLF) { pLF = aDMEF.Bound(aE, TopTools_ListOfShape()); } else { // internal edges should not be used aMEAvoid.Add(aE); } AppendToList(*pLF, aF); } // // fill connection map of the vertices of inverted edges to faces aExp.Init(aF, TopAbs_VERTEX); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aV = aExp.Current(); // TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV); if (!pLF) { pLF = aDMVF.Bound(aV, TopTools_ListOfShape()); } AppendToList(*pLF, aF); } } // // for the splits to be regular they should form only one block TopTools_ListOfShape aLCBF; BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF); if (aLCBF.Extent() == 1) { continue; } // // check if the inverted edges create the irregularity BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll; // TopTools_ListIteratorOfListOfShape aItLCB(aLCBF); for (; aItLCB.More(); aItLCB.Next()) { const TopoDS_Shape& aCB = aItLCB.Value(); // // check if it is possible to remove the block if (!CheckInvertedBlock(aCB, aLCBF, theMEInverted, theOEOrigins, aDMCBVInverted, aDMCBVAll)) { // non of the edges in this block should be removed TopExp::MapShapes(aCB, TopAbs_EDGE, aMEAvoid); continue; } } } // // all edges not included in aMEAvoid can be removed TopTools_MapOfShape aMERem; TopTools_MapIteratorOfMapOfShape aItM(theMEInverted); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aE = aItM.Value(); if (!aMEAvoid.Contains(aE)) { TopoDS_Iterator aIt(aE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aV = aIt.Value(); const TopTools_ListOfShape *pLF = aDMVF.Seek(aV); if (pLF && (pLF->Extent() > 3)) { aMERem.Add(aE); break; } } } } // if (aMERem.IsEmpty()) { return; } // // all invalid faces containing these edges can be removed TopTools_IndexedDataMapOfShapeListOfShape aInvFaces; TopTools_MapOfShape aMFRem; TopTools_IndexedMapOfShape aMFToUpdate; aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); TopTools_ListOfShape& aLFIm = theInvFaces(i); // TopTools_ListIteratorOfListOfShape aIt(aLFIm); for (; aIt.More(); ) { const TopoDS_Shape& aFIm = aIt.Value(); // // to be removed the face should have at least two not connected // inverted edges TopoDS_Compound aCEInv; aBB.MakeCompound(aCEInv); TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (aMERem.Contains(aE)) { aBB.Add(aCEInv, aE); } } // // check connectivity TopTools_ListOfShape aLCBE; BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); // if (aLCBE.Extent() >= 2) { aMFToUpdate.Add(aF); aMFRem.Add(aFIm); aLFIm.Remove(aIt); } else { aIt.Next(); } } // if (aLFIm.Extent()) { aInvFaces.Add(aF, aLFIm); } } // if (aMFRem.IsEmpty()) { return; } // theInvFaces = aInvFaces; // remove from splits aNb = aMFToUpdate.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = aMFToUpdate(i); TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF); // TopTools_ListIteratorOfListOfShape aIt(aLFIm); for (; aIt.More(); ) { const TopoDS_Shape& aFIm = aIt.Value(); if (aMFRem.Contains(aFIm)) { TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved); aLFIm.Remove(aIt); } else { aIt.Next(); } } } } //======================================================================= //function : RemoveInvalidSplitsFromValid //purpose : Removing invalid splits of faces from valid //======================================================================= void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_MapOfShape& theMEInverted, TopTools_IndexedDataMapOfShapeListOfShape& theFImages) { // Decide whether to remove the found invalid faces or not. // The procedure is the following: // 1. Make connexity blocks from invalid faces; // 2. Find free edges in this blocks; // 3. If all free edges are valid for the faces - remove block. // TopTools_MapOfShape aMFence, aMFToRem; TopoDS_Compound aCFInv; BRep_Builder aBB; aBB.MakeCompound(aCFInv); TopTools_ListIteratorOfListOfShape aItLF; // // make compound of invalid faces TopTools_DataMapOfShapeShape aDMIFOF; Standard_Integer i, aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); // artificially invalid faces should not be removed if (theArtInvFaces.IsBound(aF)) { continue; } const TopTools_ListOfShape& aLFInv = theInvFaces(i); aItLF.Initialize(aLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); if (aMFence.Add(aFIm)) { aBB.Add(aCFInv, aFIm); aDMIFOF.Bind(aFIm, aF); } } } // // make connexity blocks TopTools_ListOfShape aLCBInv; BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv); // // analyze each block aItLF.Initialize(aLCBInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aCB = aItLF.Value(); // // if connexity block contains only one face - it should be removed; TopExp_Explorer aExp(aCB, TopAbs_FACE); aExp.Next(); if (aExp.More()) { // check if there are valid images left aExp.Init(aCB, TopAbs_FACE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aFIm = aExp.Current(); const TopoDS_Shape& aF = aDMIFOF.Find(aFIm); // const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF); // if (aLFIm.Extent() == aLFInv.Extent()) { break; } } } // if (!aExp.More()) { aExp.Init(aCB, TopAbs_FACE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aF = aExp.Current(); aMFToRem.Add(aF); } continue; } // // remove faces connected by inverted edges TopTools_IndexedDataMapOfShapeListOfShape aDMEF; TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF); // aExp.Init(aCB, TopAbs_FACE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aFCB = aExp.Current(); // TopExp_Explorer aExpE(aFCB, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aECB = aExpE.Current(); if (aDMEF.FindFromKey(aECB).Extent() > 1) { if (!theMEInverted.Contains(aECB)) { break; } } } // if (!aExpE.More()) { aMFToRem.Add(aFCB); } } } // if (aMFToRem.Extent()) { // remove invalid faces from images aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF); aItLF.Initialize(aLFImages); for (; aItLF.More();) { const TopoDS_Shape& aFIm = aItLF.Value(); if (aMFToRem.Contains(aFIm)) { aLFImages.Remove(aItLF); } else { aItLF.Next(); } } } } } //======================================================================= //function : RemoveInsideFaces //purpose : Looking for the inside faces that can be safely removed //======================================================================= void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theMFToCheckInt, const TopTools_IndexedMapOfShape& theMFInvInHole, const TopoDS_Shape& theFHoles, TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedMapOfShape& theMEInside, TopoDS_Shape& theSolids) { BOPCol_ListOfShape aLS; TopTools_MapOfShape aMFence; TopTools_IndexedMapOfShape aMFInv; TopTools_ListIteratorOfListOfShape aItLF; TopTools_DataMapOfShapeShape aDMFImF; // Standard_Integer i, aNb = theFImages.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theFImages.FindKey(i); // to avoid intersection of the splits of the same // offset faces among themselves make compound of the // splits and use it as one argument TopoDS_Compound aCFImi; BRep_Builder().MakeCompound(aCFImi); // for (Standard_Integer j = 0; j < 2; ++j) { const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i); if (!pLFSp) { continue; } // aItLF.Initialize(*pLFSp); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); if (aMFence.Add(aFIm)) { BRep_Builder().Add(aCFImi, aFIm); aDMFImF.Bind(aFIm, aF); if (!j) { aMFInv.Add(aFIm); } } } } // aLS.Append(aCFImi); } // // to make the solids more complete add for intersection also the faces // consisting only of invalid edges and not included into splits aNb = theMFToCheckInt.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aFSp = theMFToCheckInt(i); if (aMFence.Add(aFSp)) { aLS.Append(aFSp); } } // BOPAlgo_MakerVolume aMV; aMV.SetArguments(aLS); aMV.SetIntersect(Standard_True); aMV.Perform(); // // get shapes connection for using in the rebuilding process // for the cases in which some of the intersection left undetected ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theSSInterfs); // // find faces to remove const TopoDS_Shape& aSols = aMV.Shape(); // TopTools_IndexedDataMapOfShapeListOfShape aDMFS; TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS); // aNb = aDMFS.Extent(); if (!aNb) { return; } // // To use the created solids for classifications, firstly, it is necessary // to check them on validity - the created solids should be complete, // i.e. all faces should be included. // TopTools_MapOfShape aMFToRem; // Check completeness if (aMV.HasDeleted()) { TopTools_IndexedMapOfShape aMEHoles; TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles); // Map edges of the solids to check the connectivity // of the removed invalid splits TopTools_IndexedMapOfShape aMESols; TopExp::MapShapes(aSols, TopAbs_EDGE, aMESols); // perform additional check on faces aNb = theFImages.Extent(); for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLFIm = theFImages(i); if (aLFIm.IsEmpty()) { continue; } const TopoDS_Shape& aF = theFImages.FindKey(i); Standard_Boolean bInvalid = theInvFaces.Contains(aF); // For invalid faces it is allowed to be at least connected // to the solids, otherwise the solids are considered as broken Standard_Boolean bConnected = Standard_False; Standard_Boolean bFaceKept = Standard_False; aItLF.Initialize(aLFIm); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); if (!aMV.IsDeleted(aFIm)) { bFaceKept = Standard_True; continue; } // TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { if (aMEHoles.Contains(aExpE.Current())) { bFaceKept = Standard_True; aMFToRem.Add(aFIm); break; } if (!bFaceKept && bInvalid && !bConnected) bConnected = aMESols.Contains(aExpE.Current()); } } // if (!bFaceKept && !bConnected) { return; } } } // TopTools_IndexedMapOfShape aMEBoundary; aNb = aDMFS.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aFIm = aDMFS.FindKey(i); const TopTools_ListOfShape& aLSol = aDMFS(i); if (aLSol.Extent() > 1) { aMFToRem.Add(aFIm); } else if (aFIm.Orientation() != TopAbs_INTERNAL) { TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary); } } // // update invalid faces with images aNb = aMFInv.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aFInv = aMFInv(i); const TopTools_ListOfShape& aLFInvIm = aMV.Modified(aFInv); TopTools_ListIteratorOfListOfShape aItLFInvIm(aLFInvIm); for (; aItLFInvIm.More(); aItLFInvIm.Next()) { const TopoDS_Shape& aFInvIm = aItLFInvIm.Value(); aMFInv.Add(aFInvIm); } } // // check if the invalid faces inside the holes are really invalid: // check its normal direction - if it has changed relatively the // original face the offset face is invalid and should be kept for rebuilding Standard_Integer aNbFH = theMFInvInHole.Extent(); for (i = 1; i <= aNbFH; ++i) { const TopoDS_Shape& aFInv = theMFInvInHole(i); TopTools_ListOfShape aLFInvIm = aMV.Modified(aFInv); if (aLFInvIm.IsEmpty()) { aLFInvIm.Append(aFInv); } // const TopoDS_Shape *pFOffset = aDMFImF.Seek(aFInv); if (!pFOffset) { continue; } TopTools_ListIteratorOfListOfShape aItLFInv(aLFInvIm); for (; aItLFInv.More(); aItLFInv.Next()) { const TopoDS_Shape& aFInvIm = aItLFInv.Value(); const TopTools_ListOfShape* pLSols = aDMFS.Seek(aFInvIm); if (!pLSols || pLSols->Extent() != 1) { continue; } // const TopoDS_Shape& aFSol = pLSols->First(); // TopoDS_Shape aFx; if (!FindShape(aFInvIm, aFSol, aFx)) { continue; } // if (BRepOffset_Tool::CheckPlanesNormals(TopoDS::Face(aFx), TopoDS::Face(*pFOffset))) { // the normal direction has not changed, thus the face can be removed aMFToRem.Add(aFInvIm); } } } // TopoDS_Compound aSolids; BRep_Builder().MakeCompound(aSolids); TopTools_MapOfShape aMFKeep; // TopExp_Explorer aExpS(aSols, TopAbs_SOLID); for (; aExpS.More(); aExpS.Next()) { const TopoDS_Shape& aSol = aExpS.Current(); // Standard_Boolean bAllInv(Standard_True), bAllRemoved(Standard_True); for (TopExp_Explorer aExpF(aSol, TopAbs_FACE); aExpF.More(); aExpF.Next()) { const TopoDS_Shape& aFS = aExpF.Current(); // if (aFS.Orientation() == TopAbs_INTERNAL) { aMFToRem.Add(aFS); } // bAllRemoved = bAllRemoved && aMFToRem.Contains(aFS); bAllInv = bAllInv && (aMFToRem.Contains(aFS) || aMFInv.Contains(aFS)); } // if (bAllInv && !bAllRemoved) { // remove invalid faces but keep those that have already been marked for removal TopExp_Explorer aExpF(aSol, TopAbs_FACE); for (; aExpF.More(); aExpF.Next()) { const TopoDS_Shape& aFS = aExpF.Current(); // if (aMFToRem.Contains(aFS)) { if (!aMFKeep.Add(aFS)) { aMFKeep.Remove(aFS); } } else { aMFToRem.Add(aFS); } } } else { BRep_Builder().Add(aSolids, aSol); theSolids = aSolids; } } // TopTools_MapIteratorOfMapOfShape aItM(aMFKeep); for (; aItM.More(); aItM.Next()) { aMFToRem.Remove(aItM.Value()); } // Remove the invalid hanging parts external to the solids RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, aMFToRem); // Remove newly found internal and hanging faces RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved); RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved); // // Get inside faces from the removed ones comparing them with boundary edges aNb = theMERemoved.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aE = theMERemoved(i); if (!aMEBoundary.Contains(aE)) { theMEInside.Add(aE); } } } //======================================================================= //function : ShapesConnections //purpose : Looking for the connections between faces not to miss // some necessary intersection //======================================================================= void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_DataMapOfShapeShape& theDMFOr, BOPAlgo_Builder& theBuilder, TopTools_DataMapOfShapeListOfShape& theSSInterfs) { // update invalid edges with images and keep connection to original edge TopTools_DataMapOfShapeListOfShape aDMEOr; Standard_Integer aNb = theInvEdges.Extent(); for (Standard_Integer i = 1; i <= aNb; ++i) { const TopoDS_Shape& aEInv = theInvEdges(i); const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv); if (aLEIm.IsEmpty()) { aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv); continue; } // TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); // TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm); if (!pLEOr) { pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape()); } AppendToList(*pLEOr, aEInv); } } // // get shapes connections for using in the rebuilding process const BOPDS_PDS& pDS = theBuilder.PDS(); // analyze all Face/Face intersections const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF(); Standard_Integer iInt, aNbFF = aFFs.Extent(); for (iInt = 0; iInt < aNbFF; ++iInt) { const BOPDS_InterfFF& aFF = aFFs(iInt); const BOPDS_VectorOfCurve& aVNC = aFF.Curves(); Standard_Integer aNbC = aVNC.Extent(); if (!aNbC) { continue; } // const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1()); const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2()); // const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1); const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2); // if (!pF1 || !pF2) { continue; } // if (pF1->IsSame(*pF2)) { continue; } // Standard_Boolean bInv1 = theInvFaces.Contains(*pF1); Standard_Boolean bInv2 = theInvFaces.Contains(*pF2); // if (!bInv1 && !bInv2) { continue; } // // check if it is real Face/Face intersection TopTools_MapOfShape aMEInt; for (Standard_Integer iC = 0; iC < aNbC; ++iC) { const BOPDS_Curve& aNC = aVNC(iC); const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks(); BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB); for (; aItLPB.More(); aItLPB.Next()) { const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value(); Standard_Integer nEInt; if (aPB->HasEdge(nEInt)) { const TopoDS_Shape& aEInt = pDS->Shape(nEInt); aMEInt.Add(aEInt); } } } // if (aMEInt.IsEmpty()) { continue; } // // check if invalid edges of the face are in the same splits with intersection edges for (Standard_Integer i = 0; i < 2; ++i) { if ((!i && !bInv1) || (i && !bInv2)) { continue; } // const TopoDS_Shape& aF = !i ? *pF1 : *pF2; const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1; const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2; // Standard_Boolean bFound = Standard_False; // TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm); if (aLFIm.IsEmpty()) { aLFIm.Append(aFIm); } // TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFImIm = aItLFIm.Value(); // Standard_Boolean bInv(Standard_False), bInt(Standard_False); TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (!bInv) { bInv = aDMEOr.IsBound(aE); } if (!bInt) { bInt = aMEInt.Contains(aE); } if (bInv && bInt) { break; } } // if (!bInt || !bInv) { continue; } // bFound = Standard_True; // // append opposite face to all invalid edges in the split aExpE.Init(aFImIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE); if (!pLEOr) { continue; } // TopTools_ListIteratorOfListOfShape aItLE(*pLEOr); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEOr = aItLE.Value(); TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr); if (!pLFE) { pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape()); } AppendToList(*pLFE, aFOp); } } } if (bFound) { // save connection between offset faces TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF); if (!pLF) { pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape()); } AppendToList(*pLF, aFOp); } } } } //======================================================================= //function : RemoveHangingParts //purpose : Remove isolated invalid hanging parts //======================================================================= void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV, const TopTools_DataMapOfShapeShape& theDMFImF, const TopTools_IndexedMapOfShape& theMFInv, const TopTools_IndexedMapOfShape& theInvEdges, TopTools_MapOfShape& theMFToRem) { // Map the faces of the result solids to filter them from avoided faces TopTools_IndexedMapOfShape aMFS; TopExp::MapShapes(theMV.Shape(), TopAbs_FACE, aMFS); BRep_Builder aBB; // Build compound of all faces not included into solids TopoDS_Compound aCFHangs; aBB.MakeCompound(aCFHangs); // Tool for getting the splits of faces const BOPCol_DataMapOfShapeListOfShape& aMVIms = theMV.Images(); TopTools_ListIteratorOfListOfShape aItLArgs(theMV.Arguments()); for (; aItLArgs.More(); aItLArgs.Next()) { TopExp_Explorer anExpF(aItLArgs.Value(), TopAbs_FACE); for (; anExpF.More(); anExpF.Next()) { const TopoDS_Shape& aF = anExpF.Current(); const BOPCol_ListOfShape* pLFIm = aMVIms.Seek(aF); if (pLFIm) { TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); if (!aMFS.Contains(aFIm)) aBB.Add(aCFHangs, aFIm); } } else { if (!aMFS.Contains(aF)) aBB.Add(aCFHangs, aF); } } } // Make connexity blocks of all hanging parts and check that they are isolated BOPCol_ListOfShape aLCBHangs; BOPTools_AlgoTools::MakeConnexityBlocks(aCFHangs, TopAbs_EDGE, TopAbs_FACE, aLCBHangs); if (aLCBHangs.IsEmpty()) return; // To be removed, the block should contain invalid splits of offset faces and should // meet one of the following conditions: // 1. The block should not be connected to any invalid parts (Faces or Edges) // contained in solids; // 2. The block should be isolated from other faces, i.e. it should consist of // the splits of the single offset face. // Map the edges and vertices of the result solids to check connectivity // of the hanging blocks to invalid parts contained in solids TopTools_IndexedDataMapOfShapeListOfShape aDMEF, aDMVE; TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_EDGE , TopAbs_FACE, aDMEF); TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aDMVE); // Update invalid edges with intersection results TopTools_MapOfShape aMEInv; Standard_Integer i, aNbE = theInvEdges.Extent(); for (i = 1; i <= aNbE; ++i) { const TopoDS_Shape& aEInv = theInvEdges(i); const BOPCol_ListOfShape *pLEIm = aMVIms.Seek(aEInv); if (pLEIm) { BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) aMEInv.Add(aItLEIm.Value()); } else aMEInv.Add(aEInv); } // Tool for getting the origins of the splits const BOPCol_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins(); BOPCol_ListIteratorOfListOfShape aItLCBH(aLCBHangs); for (; aItLCBH.More(); aItLCBH.Next()) { const TopoDS_Shape& aCBH = aItLCBH.Value(); // Check the block to contain invalid split Standard_Boolean bHasInvalidFace = Standard_False; // Check connectivity to invalid parts Standard_Boolean bIsConnected = Standard_False; TopTools_IndexedMapOfShape aBlockME; TopExp::MapShapes(aCBH, TopAbs_EDGE, aBlockME); // Map to collect all original faces TopTools_MapOfShape aMOffsetF; TopExp_Explorer anExpF(aCBH, TopAbs_FACE); for (; anExpF.More(); anExpF.Next()) { const TopoDS_Shape& aF = anExpF.Current(); // Check block to contain invalid face if (!bHasInvalidFace) bHasInvalidFace = theMFInv.Contains(aF); // Check block for connectivity to invalid parts if (!bIsConnected) { // check edges TopExp_Explorer anExpE(aF, TopAbs_EDGE); for (; anExpE.More() && !bIsConnected; anExpE.Next()) { const TopoDS_Shape& aE = anExpE.Current(); const TopTools_ListOfShape *pLF = aDMEF.Seek(aE); if (pLF) { TopTools_ListIteratorOfListOfShape aItLF(*pLF); for (; aItLF.More() && !bIsConnected; aItLF.Next()) bIsConnected = theMFInv.Contains(aItLF.Value()); } } // check vertices TopExp_Explorer anExpV(aF, TopAbs_VERTEX); for (; anExpV.More() && !bIsConnected; anExpV.Next()) { const TopoDS_Shape& aV = anExpV.Current(); const TopTools_ListOfShape *pLE = aDMVE.Seek(aV); if (pLE) { TopTools_ListIteratorOfListOfShape aItLE(*pLE); for (; aItLE.More() && !bIsConnected; aItLE.Next()) bIsConnected = !aBlockME.Contains(aItLE.Value()) && aMEInv .Contains(aItLE.Value()); } } } // Check block to be isolated const BOPCol_ListOfShape* pLFOr = aMVOrs.Seek(aF); if (pLFOr) { TopTools_ListIteratorOfListOfShape aItLFOr(*pLFOr); for (; aItLFOr.More(); aItLFOr.Next()) { const TopoDS_Shape* pFOffset = theDMFImF.Seek(aItLFOr.Value()); if (pFOffset) aMOffsetF.Add(*pFOffset); } } else { const TopoDS_Shape* pFOffset = theDMFImF.Seek(aF); if (pFOffset) aMOffsetF.Add(*pFOffset); } } Standard_Boolean bRemove = bHasInvalidFace && (!bIsConnected || aMOffsetF.Extent() == 1); if (bRemove) { // remove the block anExpF.Init(aCBH, TopAbs_FACE); for (; anExpF.More(); anExpF.Next()) theMFToRem.Add(anExpF.Current()); } } } //======================================================================= //function : RemoveValidSplits //purpose : Removing valid splits according to results of intersection //======================================================================= void RemoveValidSplits(const TopTools_MapOfShape& theSpRem, TopTools_IndexedDataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_IndexedMapOfShape& theMERemoved) { Standard_Integer i, aNb = theImages.Extent(); if (!aNb) { return; } // for (i = 1; i <= aNb; ++i) { TopTools_ListOfShape& aLSIm = theImages(i); TopTools_ListIteratorOfListOfShape aIt(aLSIm); for (; aIt.More(); ) { const TopoDS_Shape& aSIm = aIt.Value(); if (theSpRem.Contains(aSIm)) { TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved); aLSIm.Remove(aIt); continue; } // // check if all its images are have to be removed const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm); if (aLSImIm.Extent()) { Standard_Boolean bAllRem = Standard_True; TopTools_ListIteratorOfListOfShape aIt1(aLSImIm); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aSImIm = aIt1.Value(); if (theSpRem.Contains(aSImIm)) { TopExp::MapShapes(aSImIm, TopAbs_EDGE, theMERemoved); } else { bAllRem = Standard_False; } } // if (bAllRem) { TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved); aLSIm.Remove(aIt); continue; } } aIt.Next(); } } } //======================================================================= //function : RemoveInvalidSplits //purpose : Removing invalid splits according to the results of intersection //======================================================================= void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedDataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_IndexedMapOfShape& theMERemoved) { Standard_Integer i, aNb = theImages.Extent(); if (!aNb) { return; } // for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aS = theImages.FindKey(i); Standard_Boolean bArt = theArtInvFaces.IsBound(aS); // TopTools_ListOfShape& aLSIm = theImages(i); TopTools_ListIteratorOfListOfShape aIt(aLSIm); for (; aIt.More();) { const TopoDS_Shape& aSIm = aIt.Value(); if (theSpRem.Contains(aSIm)) { TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved); aLSIm.Remove(aIt); continue; } // // check if all its images are have to be removed const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm); if (aLSImIm.IsEmpty()) { aIt.Next(); continue; } // Standard_Boolean bAllRem = Standard_True; TopTools_IndexedMapOfShape aMERemoved; TopTools_ListIteratorOfListOfShape aIt1(aLSImIm); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aSImIm = aIt1.Value(); if (theSpRem.Contains(aSImIm)) { TopExp::MapShapes(aSImIm, TopAbs_EDGE, aMERemoved); } else { bAllRem = Standard_False; } } // if (bAllRem) { aLSIm.Remove(aIt); continue; } // if (bArt) { aIt.Next(); continue; } // // remove the face from invalid if all invalid edges of this face // have been marked for removal TopExp_Explorer aExpE(aSIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aEInv = aExpE.Current(); if (theInvEdges.Contains(aEInv) && !aMERemoved.Contains(aEInv)) { break; } } if (!aExpE.More()) { TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved); aLSIm.Remove(aIt); } else { aIt.Next(); } } } } //======================================================================= //function : FilterEdgesImages //purpose : Updating the maps of images and origins of the offset edges //======================================================================= void FilterEdgesImages(const TopoDS_Shape& theS, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins) { // map edges TopTools_IndexedMapOfShape aME; TopExp::MapShapes(theS, TopAbs_EDGE, aME); // theOEOrigins.Clear(); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(theOEImages); for (; aItDM.More(); aItDM.Next()) { const TopoDS_Shape& aE = aItDM.Key(); TopTools_ListOfShape& aLEIm = aItDM.ChangeValue(); // TopTools_ListIteratorOfListOfShape aIt(aLEIm); for (; aIt.More(); ) { const TopoDS_Shape& aEIm = aIt.Value(); // filter images if (!aME.Contains(aEIm)) { // remove the image // edges with no images left should be kept in the map // to avoid their usage when building the splits of faces aLEIm.Remove(aIt); continue; } // // save origins if (theOEOrigins.IsBound(aEIm)) { AppendToList(theOEOrigins.ChangeFind(aEIm), aE); } else { TopTools_ListOfShape aLOr; aLOr.Append(aE); theOEOrigins.Bind(aEIm, aLOr); } // aIt.Next(); } } } //======================================================================= //function : FilterInvalidFaces //purpose : Filtering of the invalid faces //======================================================================= void FilterInvalidFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF, const TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, TopTools_DataMapOfShapeShape& theArtInvFaces) { // // filter invalid faces, considering faces having only valid // images left with non-free edges as valid // do not remove invalid faces if it creates free edges // TopTools_IndexedDataMapOfShapeListOfShape aReallyInvFaces; TopTools_ListIteratorOfListOfShape aItLF; // Standard_Integer i, aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); const TopTools_ListOfShape& aLFInv = theInvFaces(i); // if (theArtInvFaces.IsBound(aF)) { if (aLFInv.IsEmpty()) { theArtInvFaces.UnBind(aF); } else { aReallyInvFaces.Add(aF, aLFInv); } continue; } // if (aLFInv.IsEmpty()) { continue; } // const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); Standard_Boolean bInvalid = aLFIm.IsEmpty(); // if (!bInvalid) { // check two lists on common splits aItLF.Initialize(aLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFInv = aItLF.Value(); // TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); // if (aFInv.IsSame(aFIm)) { break; } } // if (aItLFIm.More()) { break; } } // bInvalid = aItLF.More(); } // if (!bInvalid) { // check for free edges for (Standard_Integer j = 0; !bInvalid && j < 2; ++j) { const TopTools_ListOfShape& aLI = !j ? aLFIm : aLFInv; aItLF.Initialize(aLI); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); // TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (!theMERemoved.Contains(aE)) { const TopTools_ListOfShape* pLEF = theDMEF.Seek(aE); if (pLEF && pLEF->Extent() == 1) { break; } } } // if (aExp.More()) { break; } } bInvalid = aItLF.More(); } } // if (bInvalid) { aReallyInvFaces.Add(aF, aLFInv); } } // theInvFaces = aReallyInvFaces; } //======================================================================= //function : FilterInvalidEdges //purpose : Filtering the invalid edges according to currently invalid faces //======================================================================= void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const TopTools_DataMapOfShapeListOfShape& theDMFLIE, const TopTools_IndexedMapOfShape& theMERemoved, TopTools_IndexedMapOfShape& theInvEdges) { TopoDS_Compound aCEInv; TopTools_IndexedMapOfShape aMEInv; BRep_Builder aBB; aBB.MakeCompound(aCEInv); TopTools_ListIteratorOfListOfShape aItLF; // Standard_Integer i, aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLFInv = theInvFaces(i); aItLF.Initialize(aLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEInv); // TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (theInvEdges.Contains(aE)) { aBB.Add(aCEInv, aE); } } } } // // remove edges which have been marked for removal TopTools_IndexedMapOfShape aMEInvToAvoid; TopTools_ListOfShape aLCBE; BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); // TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE); for (; aItLCBE.More(); aItLCBE.Next()) { const TopoDS_Shape& aCBE = aItLCBE.Value(); TopExp_Explorer aExpCB(aCBE, TopAbs_EDGE); for (; aExpCB.More(); aExpCB.Next()) { const TopoDS_Shape& aE = aExpCB.Current(); if (!theMERemoved.Contains(aE)) { break; } } // if (!aExpCB.More()) { TopExp::MapShapes(aCBE, TopAbs_EDGE, aMEInvToAvoid); } } // TopTools_IndexedMapOfShape aReallyInvEdges; // aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); if (theArtInvFaces.IsBound(aF)) { const TopTools_ListOfShape& aLEInv = theDMFLIE.Find(aF); aItLF.Initialize(aLEInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aE = aItLF.Value(); if (aMEInv.Contains(aE) && !aMEInvToAvoid.Contains(aE)) { aReallyInvEdges.Add(aE); } } } else { const TopTools_ListOfShape& aLFInv = theInvFaces(i); aItLF.Initialize(aLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (theInvEdges.Contains(aE) && !aMEInvToAvoid.Contains(aE)) { aReallyInvEdges.Add(aE); } } } } } // theInvEdges = aReallyInvEdges; } //======================================================================= //function : FindFacesToRebuild //purpose : Looking for the faces that have to be rebuilt: // 1. Faces close to invalidity // 2. Faces containing some invalid parts //======================================================================= void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, TopTools_MapOfShape& theFSelfRebAvoid) { Standard_Integer i, aNb = theLFImages.Extent(); if (!aNb) { return; } // Standard_Boolean bRebuild; TopTools_ListIteratorOfListOfShape aItLF; TopTools_ListOfShape aLEValid; TopTools_MapOfShape aMFence, aMEReb, aMFReb; TopExp_Explorer aExp; // TopTools_DataMapOfShapeListOfShape aDMFLV; // get edges from invalid faces aNb = theInvFaces.Extent(); for (i = 1; i <= aNb; i++) { const TopoDS_Shape& aF = theInvFaces.FindKey(i); aMFence.Clear(); TopTools_ListOfShape aLVAvoid; const TopTools_ListOfShape& aLFIm = theInvFaces(i); aItLF.Initialize(aLFIm); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); aExp.Init(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); aMEReb.Add(aE); if (theInvEdges.Contains(aE)) { TopExp_Explorer aExpV(aE, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); if (aMFence.Add(aV)) { aLVAvoid.Append(aV); aMEReb.Add(aV); } } } } } // if (aLVAvoid.Extent()) { aDMFLV.Bind(aF, aLVAvoid); } // const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aF); if (pLF) { TopTools_ListIteratorOfListOfShape aItLFE(*pLF); for (; aItLFE.More(); aItLFE.Next()) { const TopoDS_Shape& aFE = aItLFE.Value(); aMFReb.Add(aFE); } } } // // get face to rebuild aNb = theLFImages.Extent(); for (i = 1; i <= aNb; i++) { const TopoDS_Shape& aF = theLFImages.FindKey(i); const TopTools_ListOfShape& aLFIm = theLFImages(i); TopTools_MapOfShape aMVAvoid; if (aDMFLV.IsBound(aF)) { const TopTools_ListOfShape& aLVAvoid = aDMFLV.Find(aF); TopTools_ListIteratorOfListOfShape aItLV(aLVAvoid); for (; aItLV.More(); aItLV.Next()) { const TopoDS_Shape& aV = aItLV.Value(); aMVAvoid.Add(aV); } } // bRebuild = aMFReb.Contains(aF); aLEValid.Clear(); aMFence.Clear(); // aItLF.Initialize(aLFIm); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); aExp.Init(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Edge& anEIm = TopoDS::Edge(aExp.Current()); if (!theInvEdges.Contains(anEIm)) { if (aMFence.Add(anEIm)) { aLEValid.Append(anEIm); } } // if (!bRebuild) { bRebuild = aMEReb.Contains(anEIm); } // if (!bRebuild) { // check vertices TopExp_Explorer aExpV(anEIm, TopAbs_VERTEX); for (; aExpV.More() && !bRebuild; aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); if (!aMVAvoid.Contains(aV)) { bRebuild = aMEReb.Contains(aV); } } } } } // if (!bRebuild) { bRebuild = aLFIm.Extent() && theInvFaces.Contains(aF); if (bRebuild) { theFSelfRebAvoid.Add(aF); } } // if (bRebuild) { theFToRebuild.Add(aF, aLEValid); } } } //======================================================================= //function : RebuildFaces //purpose : Rebuilding of the faces //======================================================================= void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theFSelfRebAvoid, const TopoDS_Shape& theSolids, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theDMFNewHoles, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeShape& theFacesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theLastInvEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeInteger& theAlreadyInvFaces, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, Handle(BRepAlgo_AsDes)& theAsDes) { TopTools_MapOfShape aModifiedEdges; // // 1. Intersect faces IntersectFaces(theFToRebuild, theFSelfRebAvoid, theSolids, theSSInterfs, theFImages, theEdgesOrigins, theOEImages, theOEOrigins, theInvEdges, theValidEdges, theInvertedEdges, theEdgesToAvoid, theInvFaces, theArtInvFaces, theVertsToAvoid, theETrimEInf, aModifiedEdges, theAsDes); // // 2. Repeat steps to build the correct faces BuildSplitsOfInvFaces(theFToRebuild, aModifiedEdges, theFImages, theDMFNewHoles, theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, theVertsToAvoid, theAlreadyInvFaces, theValidEdges, theETrimEInf, theAsDes); } //======================================================================= //function : IntersectFaces //purpose : Intersection of the faces that should be rebuild // to resolve all invalidities //======================================================================= void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_MapOfShape& theFSelfRebAvoid, const TopoDS_Shape& theSolids, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedDataMapOfShapeListOfShape& theFImages, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_IndexedMapOfShape& theInvEdges, TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes) { Standard_Integer aNbFR = theFToRebuild.Extent(); if (!aNbFR) { return; } // Standard_Integer i, j, k, aNbInv; TopTools_ListIteratorOfListOfShape aItLF, aItLE; // // get vertices from invalid edges TopTools_MapOfShape aMVInv, aMVInvAll; aNbInv = theInvEdges.Extent(); for (i = 1; i <= aNbInv; ++i) { const TopoDS_Shape& aEInv = theInvEdges(i); Standard_Boolean bValid = theValidEdges.Contains(aEInv); for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next()) { const TopoDS_Shape& aV = aExp.Current(); aMVInvAll.Add(aV); if (!bValid) { aMVInv.Add(aV); } } } // Standard_Boolean bLookVertToAvoid = (aMVInv.Extent() > 0); // TopTools_DataMapOfShapeListOfShape aDMSF, aMDone, aMEInfETrim, aDMVEFull; TopTools_IndexedDataMapOfShapeListOfShape aFLE, aDMEFInv; // // Add all faces to rebuild to outgoing map , // plus link edges and vertices to the faces to // define intersection faces PrepareFacesForIntersection(theFToRebuild, theFImages, theInvFaces, theArtInvFaces, bLookVertToAvoid, aFLE, aMDone, aDMSF, aMEInfETrim, aDMVEFull, theETrimEInf, aDMEFInv); // Find vertices to avoid while trimming the edges. // These vertices are taken from the invalid edges common between // splits of different invalid, but not artificially, faces. // Additional condition for these vertices is that all // edges adjacent to this vertex must be either invalid // or contained in invalid faces TopTools_MapOfShape aMVRInv = theVertsToAvoid; FindVerticesToAvoid(aDMEFInv, theInvEdges, theValidEdges, theInvertedEdges, aDMVEFull, theOEImages, theOEOrigins, aMVRInv); // // The faces should be intersected selectively - // intersect only faces neighboring to the same invalid face // and connected to its invalid edges; // when dealing with artificially invalid faces for intersection to be // complete we need to use not only invalid edges, but also the // edges connected to invalid ones // find blocks of artificially invalid faces TopTools_DataMapOfShapeShape aDMFImF; TopoDS_Compound aCFArt; BRep_Builder().MakeCompound(aCFArt); TopTools_DataMapIteratorOfDataMapOfShapeShape aItM(theArtInvFaces); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aF = aItM.Key(); const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF); aItLF.Initialize(aLFInv); for (; aItLF.More(); aItLF.Next()) { BRep_Builder().Add(aCFArt, aItLF.Value()); aDMFImF.Bind(aItLF.Value(), aF); } } // // make connexity blocks TopTools_ListOfShape aLCBArt; BOPTools_AlgoTools::MakeConnexityBlocks(aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt); // // alone edges TopTools_MapOfShape aMEAlone, aMEInvOnArt; // TopTools_ListIteratorOfListOfShape aItLCBArt(aLCBArt); for (; aItLCBArt.More(); aItLCBArt.Next()) { const TopoDS_Shape& aCB = aItLCBArt.Value(); // // check if aCB contains splits of only one offset face TopTools_MapOfShape aMFArt; TopExp_Explorer aExpF(aCB, TopAbs_FACE); for (; aExpF.More(); aExpF.Next()) { aMFArt.Add(aDMFImF.Find(aExpF.Current())); } // Standard_Boolean bAlone = (aMFArt.Extent() == 1); // // vertices on invalid edges TopTools_MapOfShape aMVEInv; TopTools_MapOfShape aMFence; // edges that should not be marked as alone - edges having same origins as invalid ones TopTools_MapOfShape aMEAvoid; // map to find alone edges by looking for free vertices TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal; // TopExp_Explorer aExpE(aCB, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); if (theInvEdges.Contains(aE)) { aMEInvOnArt.Add(aE); for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { aMVEInv.Add(aItV.Value()); } // if (bAlone) { const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); if (pLEOr) { TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { TopTools_ListIteratorOfListOfShape aItLEIm(theOEImages.Find(aItLEOr.Value())); for (; aItLEIm.More(); aItLEIm.Next()) { aMEAvoid.Add(aItLEIm.Value()); } } } } continue; } // if (aMFence.Add(aE)) { TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal); } } // // find edges with free vertices Standard_Integer aNbV = aDMVEVal.Extent(); for (i = 1; i <= aNbV; ++i) { const TopoDS_Shape& aV = aDMVEVal.FindKey(i); if (!aMVEInv.Contains(aV)) { continue; } // const TopTools_ListOfShape& aLEV = aDMVEVal(i); if (aLEV.Extent() > 1) { continue; } // const TopoDS_Shape& aE = aLEV.First(); if (aMEAvoid.Contains(aE)) { continue; } // aMEAlone.Add(aE); // // if this alone edge adds nothing to the intersection list // it means that the origin of this edge has been split and we need to // add the neighboring images of the same origins if (aDMSF.Find(aE).Extent() > 1) { continue; } // // check also its vertices TopoDS_Iterator aItE(aE); for (; aItE.More(); aItE.Next()) { const TopoDS_Shape& aVE = aItE.Value(); if (aDMSF.Find(aVE).Extent() > 2) { break; } } // if (aItE.More()) { continue; } // // the edge is useless - look for other images const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); if (!pLEOr) { continue; } // TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { const TopoDS_Shape& aEOr = aItLEOr.Value(); // const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr); TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); // if (aMFence.Contains(aEIm)) { aMEAlone.Add(aEIm); } } } } } // // Get all invalidities from all faces to be used for avoiding // repeated usage of the common edges TopTools_MapOfShape aMAllInvs; aNbInv = theInvFaces.Extent(); for (k = 1; k <= aNbInv; ++k) { TopTools_ListIteratorOfListOfShape aIt(theInvFaces(k)); for (; aIt.More(); aIt.Next()) { TopExp_Explorer aExp(aIt.Value(), TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (theInvEdges.Contains(aE) || aMEAlone.Contains(aE)) { aMAllInvs.Add(aE); TopoDS_Iterator aItV(aE); for (; aItV.More(); aItV.Next()) { aMAllInvs.Add(aItV.Value()); } } } } } // // Bounding vertices of not trimmed edges TopTools_MapOfShape aMVBounds; // TopTools_MapOfShape aMECheckExt; // Save connections between not trimmed edge and its trimmed parts TopTools_DataMapOfShapeListOfShape aDMEETrim; // Splits of the new edges TopTools_DataMapOfShapeListOfShape aEImages; BRep_Builder aBB; // Keep connection between blocks of invalid edges to the lists of // found edges to be intersected for its treatment TopTools_IndexedDataMapOfShapeListOfShape aDMOENEdges; aNbInv = theInvFaces.Extent(); for (k = 1; k <= aNbInv; ++k) { const TopoDS_Shape& aFInv = theInvFaces.FindKey(k); Standard_Boolean bSelfRebAvoid = theFSelfRebAvoid.Contains(aFInv); const TopTools_ListOfShape& aLFInv = theInvFaces(k); // TopTools_ListOfShape aLCB; if (aLFInv.Extent() > 1) { // make compound of invalid faces TopoDS_Compound aCFInv; aBB.MakeCompound(aCFInv); // TopTools_ListIteratorOfListOfShape aIt(aLFInv); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aFIm = aIt.Value(); aBB.Add(aCFInv, aFIm); } // // make connexity blocks BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCB); } else { aLCB = aLFInv; } // Standard_Boolean bArtificial = theArtInvFaces.IsBound(aFInv); TopTools_ListIteratorOfListOfShape aItLCB(aLCB); for (; aItLCB.More(); aItLCB.Next()) { const TopoDS_Shape& aCBInv = aItLCB.Value(); // TopTools_MapOfShape aMEFence; // TopoDS_Compound aCBE; aBB.MakeCompound(aCBE); // TopExp_Explorer aExp(aCBInv, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (theInvEdges.Contains(aE) || (bArtificial && aMEAlone.Contains(aE))) { if (aMEFence.Add(aE)) { aBB.Add(aCBE, aE); } } } // // make connexity blocks of edges TopTools_ListOfShape aLCBE; BOPTools_AlgoTools::MakeConnexityBlocks(aCBE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); // TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE); for (; aItLCBE.More(); aItLCBE.Next()) { const TopoDS_Shape& aCBELoc = aItLCBE.Value(); // // map of edges and vertices of processing invalidity TopTools_IndexedMapOfShape aME; // map of vertices to trim the new edges TopTools_IndexedMapOfShape aMECV; TopExp::MapShapes(aCBELoc, TopAbs_EDGE, aME); aMECV = aME; TopExp::MapShapes(aCBELoc, TopAbs_VERTEX, aME); // // Using the map find chain of faces to be intersected; // // faces for intersection TopTools_IndexedMapOfShape aMFInt; // additional faces for intersection TopTools_IndexedMapOfShape aMFIntExt; // splits of faces for intersection TopTools_ListOfShape aLFInt; // faces to avoid intersection TopTools_IndexedMapOfShape aMFAvoid; // FindFacesForIntersection(aFInv, aME, theFImages, aDMSF, aMVInvAll, theArtInvFaces, bArtificial, theSSInterfs, aMFAvoid, aMFInt, aMFIntExt, aLFInt); if (aMFInt.Extent() < 3) { // nothing to intersect continue; } // // intersect the faces, but do not intersect the invalid ones // among each other (except for the artificially invalid faces) TopTools_IndexedMapOfShape aMEToInt; Standard_Integer aNb = aMFInt.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Face& aFi = TopoDS::Face(aMFInt(i)); if (bSelfRebAvoid && aFi.IsSame(aFInv)) { continue; } // const TopTools_ListOfShape& aLFImi = theFImages.FindFromKey(aFi); // TopTools_ListOfShape& aLFEi = aFLE.ChangeFromKey(aFi); // TopTools_ListOfShape& aLFDone = aMDone.ChangeFind(aFi); // for (j = i + 1; j <= aNb; ++j) { const TopoDS_Face& aFj = TopoDS::Face(aMFInt(j)); if (bSelfRebAvoid && aFj.IsSame(aFInv)) { continue; } // const TopTools_ListOfShape& aLFImj = theFImages.FindFromKey(aFj); // TopTools_ListOfShape& aLFEj = aFLE.ChangeFromKey(aFj); // // if there are some common edges between faces // we should use these edges and do not intersect again. TopTools_ListOfShape aLEC; FindCommonParts(aLFImi, aLFImj, aLEC); // if (aLEC.Extent()) { // no need to intersect if we have common edges between faces Standard_Boolean bForceUse = aMFIntExt.Contains(aFi) || aMFIntExt.Contains(aFj); ProcessCommonEdges(aLEC, theInvEdges, theValidEdges, aME, theETrimEInf, aMEInfETrim, theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt); continue; } // // check if both these faces are invalid and sharing edges if (theInvFaces.Contains(aFi) && theInvFaces.Contains(aFj) && !theArtInvFaces.IsBound(aFi) && !theArtInvFaces.IsBound(aFj)) { continue; } // // check if these two faces have already been treated aItLE.Initialize(aLFDone); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aF = aItLE.Value(); if (aF.IsSame(aFj)) { break; } } // if (aItLE.More()) { // use intersection line obtained on the previous steps // plus, find new origins for these lines UpdateIntersectedFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj, aLFEi, aLFEj, theEdgesOrigins, aMEToInt); continue; } // if (aMFAvoid.Contains(aFi) || aMFAvoid.Contains(aFj)) { continue; } // aLFDone.Append(aFj); aMDone.ChangeFind(aFj).Append(aFi); // IntersectFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj, aLFEi, aLFEj, theEdgesOrigins, aMECV, aMEToInt); } } // // intersect and trim edges for this chain IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV, aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages); // Standard_Integer iE, aNbEToInt = aMEToInt.Extent(); for (iE = 1; iE <= aNbEToInt; ++iE) { const TopoDS_Shape& aEInt = aMEToInt(iE); TopExp_Explorer anExpE(aCBELoc, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { const TopoDS_Shape& aE = anExpE.Current(); TopTools_ListOfShape* pLEToInt = aDMOENEdges.ChangeSeek(aE); if (!pLEToInt) pLEToInt = &aDMOENEdges(aDMOENEdges.Add(aE, TopTools_ListOfShape())); AppendToList(*pLEToInt, aEInt); } } } } } // // filter the obtained edges UpdateValidEdges(theFImages, aFLE, aDMOENEdges, aMVBounds, theSolids, theInvEdges, theInvertedEdges, aMEInvOnArt, aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins, theVertsToAvoid, theETrimEInf, aEImages, aDMEETrim, theModifiedEdges, theAsDes); } //======================================================================= //function : PrepareFacesForIntersection //purpose : Preparation of the maps for analyzing intersections of the faces //======================================================================= void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces, const TopTools_DataMapOfShapeShape& theArtInvFaces, const Standard_Boolean bLookVertToAvoid, TopTools_IndexedDataMapOfShapeListOfShape& theFLE, TopTools_DataMapOfShapeListOfShape& theMDone, TopTools_DataMapOfShapeListOfShape& theDMSF, TopTools_DataMapOfShapeListOfShape& theMEInfETrim, TopTools_DataMapOfShapeListOfShape& theDMVEFull, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv) { Standard_Integer i, aNb = theFToRebuild.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theFToRebuild.FindKey(i); // TopTools_ListOfShape aLE; theFLE.Add(aF, aLE); theMDone.Bind(aF, aLE); // const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); TopTools_ListIteratorOfListOfShape aItLF(aLFIm); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); // save connection to untrimmed face TopTools_ListOfShape *pLF = theDMSF.ChangeSeek(aE); if (!pLF) { pLF = theDMSF.Bound(aE, TopTools_ListOfShape()); } AppendToList(*pLF, aF); // // save connection to untrimmed edge const TopoDS_Shape& aEInf = theETrimEInf.Find(aE); TopTools_ListOfShape *pLETrim = theMEInfETrim.ChangeSeek(aEInf); if (!pLETrim) { pLETrim = theMEInfETrim.Bound(aEInf, TopTools_ListOfShape()); } AppendToList(*pLETrim, aE); // TopExp_Explorer aExpV(aE, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); // save connection to face TopTools_ListOfShape *pLFV = theDMSF.ChangeSeek(aV); if (!pLFV) { pLFV = theDMSF.Bound(aV, TopTools_ListOfShape()); } AppendToList(*pLFV, aF); // if (bLookVertToAvoid) { // save connection to edges TopTools_ListOfShape *pLEV = theDMVEFull.ChangeSeek(aV); if (!pLEV) { pLEV = theDMVEFull.Bound(aV, TopTools_ListOfShape()); } AppendToList(*pLEV, aE); } } } } // if (bLookVertToAvoid) { // get edges of invalid faces (from invalid splits only) const TopTools_ListOfShape *pLFInv = theInvFaces.Seek(aF); if (!pLFInv || theArtInvFaces.IsBound(aF)) { continue; } // aItLF.Initialize(*pLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFInv = aItLF.Value(); TopExp_Explorer aExp(aFInv, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); TopTools_ListOfShape *pLF = theDMEFInv.ChangeSeek(aE); if (!pLF) { pLF = &theDMEFInv(theDMEFInv.Add(aE, TopTools_ListOfShape())); } AppendToList(*pLF, aF); } } } } } //======================================================================= //function : FindVerticesToAvoid //purpose : Looking for the invalid vertices //======================================================================= void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_MapOfShape& theInvertedEdges, const TopTools_DataMapOfShapeListOfShape& theDMVEFull, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theMVRInv) { TopTools_MapOfShape aMFence; Standard_Integer i, aNb = theDMEFInv.Extent(); for (i = 1; i <= aNb; ++i) { const TopTools_ListOfShape& aLFInv = theDMEFInv(i); if (aLFInv.Extent() == 1) { continue; } // const TopoDS_Shape& aE = theDMEFInv.FindKey(i); if (!theInvEdges.Contains(aE) || theValidEdges.Contains(aE)) { continue; } if (!aMFence.Add(aE)) continue; TopTools_IndexedDataMapOfShapeListOfShape aMVEEdges; // Do not check the splitting vertices, but check only the ending ones const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); if (pLEOr) { TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { const TopTools_ListOfShape& aLEIm = theOEImages.Find(aItLEOr.Value()); TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { aMFence.Add(aItLEIm.Value()); TopExp::MapShapesAndAncestors(aItLEIm.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges); } } } else { TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges); } Standard_Integer j, aNbV = aMVEEdges.Extent(); for (j = 1; j <= aNbV; ++j) { if (aMVEEdges(j).Extent() != 1) continue; const TopoDS_Shape& aV = aMVEEdges.FindKey(j); if (!aMFence.Add(aV)) continue; const TopTools_ListOfShape *pLE = theDMVEFull.Seek(aV); if (!pLE) { // isolated vertex theMVRInv.Add(aV); continue; } // // If all edges sharing the vertex are either invalid or // the vertex is connected to at least two inverted edges // mark the vertex to be avoided in the new splits Standard_Integer iNbEInverted = 0; Standard_Boolean bAllEdgesInv = Standard_True; TopTools_ListIteratorOfListOfShape aItLE(*pLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEV = aItLE.Value(); if (theInvertedEdges.Contains(aEV)) ++iNbEInverted; if (bAllEdgesInv) bAllEdgesInv = theInvEdges.Contains(aEV); } if (iNbEInverted > 1 || bAllEdgesInv) { theMVRInv.Add(aV); } } } } //======================================================================= //function : FindFacesForIntersection //purpose : Looking for the faces around each invalidity for intersection //======================================================================= void FindFacesForIntersection(const TopoDS_Shape& theFInv, const TopTools_IndexedMapOfShape& theME, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_DataMapOfShapeListOfShape& theDMSF, const TopTools_MapOfShape& theMVInvAll, const TopTools_DataMapOfShapeShape& theArtInvFaces, const Standard_Boolean theArtCase, const TopTools_DataMapOfShapeListOfShape& theSSInterfs, TopTools_IndexedMapOfShape& theMFAvoid, TopTools_IndexedMapOfShape& theMFInt, TopTools_IndexedMapOfShape& theMFIntExt, TopTools_ListOfShape& theLFImInt) { Standard_Integer i, aNbE = theME.Extent(); // TopTools_IndexedMapOfShape aMShapes; // for (i = 1; i <= aNbE; ++i) { const TopoDS_Shape& aS = theME(i); if (!theDMSF.IsBound(aS)) { continue; } // // in artificial case we intersect the faces which are close to invalidity Standard_Boolean bAvoid = theArtCase ? ((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains(aS)) : Standard_False; // const TopTools_ListOfShape& aLF = theDMSF.Find(aS); TopTools_ListIteratorOfListOfShape aItLF(aLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aF = aItLF.Value(); if (theMFInt.Contains(aF)) { continue; } // if (bAvoid && theArtInvFaces.IsBound(aF)) { theMFAvoid.Add(aF); } // theMFInt.Add(aF); // Standard_Boolean bUse = !aF.IsSame(theFInv); // const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); theLFImInt.Append(aFIm); if (bUse) { TopExp::MapShapes(aFIm, TopAbs_EDGE, aMShapes); } } } } // if (theArtCase) { return; } // const TopTools_ListOfShape* pLFInv = theSSInterfs.Seek(theFInv); if (!pLFInv) { return; } // TopTools_MapOfShape aMF; TopTools_ListIteratorOfListOfShape aItLF(*pLFInv); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aF = aItLF.Value(); aMF.Add(aF); } // // the faces should be unique in each place TopoDS_Compound aCF; BRep_Builder().MakeCompound(aCF); // TopTools_IndexedMapOfShape aMFToAdd; TopTools_DataMapOfShapeShape aDMFOr; // for (i = 1; i <= aNbE; ++i) { const TopoDS_Shape& aS = theME(i); const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aS); if (!pLF) { continue; } // aItLF.Initialize(*pLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aF = aItLF.Value(); if (theMFInt.Contains(aF) || aMFToAdd.Contains(aF) || !aMF.Contains(aF)) { continue; } // // check if the face has some connection to already added for intersection faces const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); TopExp_Explorer aExp(aFIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { if (aMShapes.Contains(aExp.Current())) { break; } } if (aExp.More()) { break; } } if (!aItLFIm.More()) { continue; } // aMFToAdd.Add(aF); aItLFIm.Initialize(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); aDMFOr.Bind(aFIm, aF); BRep_Builder().Add(aCF, aFIm); } } } // if (aMFToAdd.IsEmpty()) { return; } // TopTools_ListOfShape aLCB; BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB); // if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1)) { return; } // TopTools_ListIteratorOfListOfShape aItLCB(aLCB); for (; aItLCB.More(); aItLCB.Next()) { const TopoDS_Shape& aCB = aItLCB.Value(); aMFToAdd.Clear(); TopExp_Explorer aExpF(aCB, TopAbs_FACE); for (; aExpF.More(); aExpF.Next()) { const TopoDS_Shape& aFIm = aExpF.Current(); aMFToAdd.Add(aDMFOr.Find(aFIm)); } // if (aMFToAdd.Extent() == 1) { const TopoDS_Shape& aF = aMFToAdd(1); // theMFInt.Add(aF); theMFIntExt.Add(aF); // const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); theLFImInt.Append(aFIm); } } } } //======================================================================= //function : ProcessCommonEdges //purpose : Analyzing the common edges between splits of offset faces //======================================================================= void ProcessCommonEdges(const TopTools_ListOfShape& theLEC, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_IndexedMapOfShape& theValidEdges, const TopTools_IndexedMapOfShape& theME, const TopTools_DataMapOfShapeShape& theETrimEInf, const TopTools_DataMapOfShapeListOfShape& theMEInfETrim, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_MapOfShape& theAllInvs, const Standard_Boolean theForceUse, TopTools_IndexedMapOfShape& theMECV, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theDMEETrim, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, TopTools_IndexedMapOfShape& theMEToInt) { TopTools_ListOfShape aLEC; // process common edges TopTools_ListIteratorOfListOfShape aItLE(theLEC); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEC = aItLE.Value(); // // check first if common edges are valid if (theInvEdges.Contains(aEC) && !theValidEdges.Contains(aEC)) { continue; } // // common edge should have connection to current invalidity if (theME.Contains(aEC)) { aLEC.Append(aEC); continue; } // TopoDS_Iterator aItV(aEC); for (; aItV.More(); aItV.Next()) { const TopoDS_Shape& aVE = aItV.Value(); if (theME.Contains(aVE)) { aLEC.Append(aEC); break; } } } // Standard_Boolean bUseOnlyInf = aLEC.IsEmpty(); if (bUseOnlyInf) { if (theForceUse) { aLEC = theLEC; } else { aItLE.Initialize(theLEC); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEC = aItLE.Value(); // check if all images of the origin of this edge // are not connected to any invalidity const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC); const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt); TopTools_ListIteratorOfListOfShape aItLVE(aLVE); for (; aItLVE.More(); aItLVE.Next()) { const TopoDS_Shape& aECx = aItLVE.Value(); if (theAllInvs.Contains(aECx) || theInvEdges.Contains(aECx)) { return; } // TopoDS_Iterator aItV(aECx); for (; aItV.More(); aItV.Next()) { if (theAllInvs.Contains(aItV.Value())) { return; } } } // use only one element if (aLEC.IsEmpty()) { aLEC.Append(aEC); } } } } // aItLE.Initialize(aLEC); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEC = aItLE.Value(); // const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC); if (!bUseOnlyInf) { // find the edges of the same original edge // and take their vertices as well const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt); TopTools_ListIteratorOfListOfShape aItLVE(aLVE); for (; aItLVE.More(); aItLVE.Next()) { const TopoDS_Shape& aECx = aItLVE.Value(); // const TopTools_ListOfShape* pLEOr = theOEOrigins.Seek(aECx); if (!pLEOr || (pLEOr->Extent() == 1)) { TopExp::MapShapes(aECx, TopAbs_VERTEX, theMECV); } } // // bind unlimited edge to its trimmed part in face to update maps of // images and origins in the future TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek(aEInt); if (!pLTAdded) { pLTAdded = theDMEETrim.Bound(aEInt, TopTools_ListOfShape()); } AppendToList(*pLTAdded, aEC); } else if (!theForceUse) { theMECheckExt.Add(aEInt); } // AppendToList(theLFEi, aEInt); AppendToList(theLFEj, aEInt); theMEToInt.Add(aEInt); } } //======================================================================= //function : UpdateIntersectedFaces //purpose : Updating the already interfered faces //======================================================================= void UpdateIntersectedFaces(const TopoDS_Shape& theFInv, const TopoDS_Shape& theFi, const TopoDS_Shape& theFj, const TopTools_ListOfShape& theLFInv, const TopTools_ListOfShape& theLFImi, const TopTools_ListOfShape& theLFImj, const TopTools_ListOfShape& theLFEi, const TopTools_ListOfShape& theLFEj, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_IndexedMapOfShape& theMEToInt) { // Find common edges in these two lists TopTools_MapOfShape aMEi; TopTools_ListIteratorOfListOfShape aItLE(theLFEi); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); aMEi.Add(aE); } // // find origins TopTools_IndexedMapOfShape aMEToFindOrigins; TopTools_ListOfShape aLEToFindOrigins; if (!theFi.IsSame(theFInv)) { FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins); } if (!theFj.IsSame(theFInv)) { FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins); } // TopTools_ListOfShape aLEOrInit; aItLE.Initialize(aLEToFindOrigins); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEC = aItLE.Value(); aMEToFindOrigins.Add(aEC); } // FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit); // aItLE.Initialize(theLFEj); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); if (aMEi.Contains(aE)) { theMEToInt.Add(aE); if (aLEOrInit.Extent()) { if (theEdgesOrigins.IsBound(aE)) { TopTools_ListOfShape& aLEOr = theEdgesOrigins.ChangeFind(aE); TopTools_ListIteratorOfListOfShape aItLEOr(aLEOrInit); for (; aItLEOr.More(); aItLEOr.Next()) { const TopoDS_Shape& aEOr = aItLEOr.Value(); AppendToList(aLEOr, aEOr); } } else { theEdgesOrigins.Bind(aE, aLEOrInit); } } } } } //======================================================================= //function : IntersectFaces //purpose : Intersection of the pair of faces //======================================================================= void IntersectFaces(const TopoDS_Shape& theFInv, const TopoDS_Shape& theFi, const TopoDS_Shape& theFj, const TopTools_ListOfShape& theLFInv, const TopTools_ListOfShape& theLFImi, const TopTools_ListOfShape& theLFImj, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_IndexedMapOfShape& theMECV, TopTools_IndexedMapOfShape& theMEToInt) { // intersect faces TopAbs_State aSide = TopAbs_OUT; TopTools_ListOfShape aLInt1, aLInt2; TopoDS_Edge aNullEdge; BRepOffset_Tool::Inter3D(TopoDS::Face(theFi), TopoDS::Face(theFj), aLInt1, aLInt2, aSide, aNullEdge); // if (aLInt1.IsEmpty()) { return; } // // find common vertices for trimming edges TopTools_ListOfShape aLCV; TopTools_ListIteratorOfListOfShape aItLE; FindCommonParts(theLFImi, theLFImj, aLCV, TopAbs_VERTEX); if (aLCV.Extent() > 1) { aItLE.Initialize(aLCV); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aCV = aItLE.Value(); theMECV.Add(aCV); } } // // find origins TopTools_IndexedMapOfShape aMEToFindOrigins; TopTools_ListOfShape aLEToFindOrigins; if (!theFi.IsSame(theFInv)) { FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins); } if (!theFj.IsSame(theFInv)) { FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins); } TopTools_ListOfShape aLEOrInit; aItLE.Initialize(aLEToFindOrigins); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEC = aItLE.Value(); aMEToFindOrigins.Add(aEC); } // FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit); // aItLE.Initialize(aLInt1); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEInt = aItLE.Value(); theLFEi.Append(aEInt); theLFEj.Append(aEInt); // if (aLEOrInit.Extent()) { theEdgesOrigins.Bind(aEInt, aLEOrInit); } // theMEToInt.Add(aEInt); } } //======================================================================= //function : FindOrigins //purpose : Looking for the origin edges //======================================================================= void FindOrigins(const TopTools_ListOfShape& theLFIm1, const TopTools_ListOfShape& theLFIm2, const TopTools_IndexedMapOfShape& theME, const TopTools_DataMapOfShapeListOfShape& theOrigins, TopTools_ListOfShape& theLEOr) { Standard_Integer i; TopTools_MapOfShape aMFence; TopExp_Explorer aExp; TopTools_ListIteratorOfListOfShape aIt, aItLE; // for (i = 0; i < 2; ++i) { const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2; aIt.Initialize(aLF); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aF = aIt.Value(); // aExp.Init(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); // if (theME.Contains(aE) && theOrigins.IsBound(aE)) { const TopTools_ListOfShape& aLEOr = theOrigins.Find(aE); aItLE.Initialize(aLEOr); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEOr = aItLE.Value(); // if (aMFence.Add(aEOr) && (aEOr.ShapeType() == TopAbs_EDGE)) { theLEOr.Append(aEOr); } } // for (; aItLE.More(); aItLE.Next()) { } // if (theME.Contains(aE) && theOrigins.IsBound(aE)) { } // aExp.Init(aF, TopAbs_EDGE); } // for (; aIt.More(); aIt.Next()) { } // for (i = 0; i < 2; ++i) { } //======================================================================= //function : IntersectAndTrimEdges //purpose : Intersection of the new intersection edges among themselves //======================================================================= void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedMapOfShape& theMFInt, const TopTools_IndexedMapOfShape& theMEInt, const TopTools_DataMapOfShapeListOfShape& theDMEETrim, const TopTools_IndexedMapOfShape& theMSInv, const TopTools_IndexedMapOfShape& theMVE, const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theNewVertsToAvoid, const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theMVBounds, TopTools_DataMapOfShapeListOfShape& theEImages) { Standard_Integer i, aNb = theMEInt.Extent(); if (!aNb) { return; } // BOPCol_ListOfShape aLArgs; TopTools_MapOfShape aMFence; TopTools_ListIteratorOfListOfShape aIt, aIt1; TopExp_Explorer aExp; // // get vertices from the splits of intersected faces. // vertices are taken from the edges close to invalidity // TopTools_IndexedDataMapOfShapeListOfShape aDMVE; aNb = theMFInt.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theMFInt(i); const TopTools_ListOfShape& aLE = theFToRebuild.FindFromKey(aF); // aIt.Initialize(aLE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE); // aExp.Init(aE, TopAbs_VERTEX); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aV1 = aExp.Current(); if (!theVertsToAvoid.Contains(aV1) && theMVE.Contains(aV1) && aMFence.Add(aV1)) { aLArgs.Append(aV1); } } } } // aNb = theMSInv.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aV = theMSInv(i); if (aV.ShapeType() != TopAbs_VERTEX) { continue; } // TopTools_ListOfShape *pLVE = aDMVE.ChangeSeek(aV); if (!pLVE) { continue; } // aIt.Initialize(*pLVE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); // aExp.Init(aE, TopAbs_VERTEX); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aV1 = aExp.Current(); if (!theVertsToAvoid.Contains(aV1) && aMFence.Add(aV1)) { aLArgs.Append(aV1); } } } } // // bounding vertices of untrimmed edges TopTools_ListOfShape aLVBounds; // new intersection edges TopTools_ListOfShape aLENew; // get edges to intersect TopTools_ListOfShape aLEInt; // Common intersection edges. Should be intersected separately TopTools_ListOfShape aLCE; // aNb = theMEInt.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aE = theMEInt(i); if (theMECheckExt.Contains(aE)) { // avoid trimming of the intersection edges by additional common edges aLCE.Append(aE); continue; } // if (!theDMEETrim.IsBound(aE)) { aLENew.Append(aE); } // aLEInt.Append(aE); aLArgs.Append(aE); // aExp.Init(aE, TopAbs_VERTEX); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aV = aExp.Current(); aLVBounds.Append(aV); } } // // Intersect Edges BOPAlgo_Builder aGF; aGF.SetArguments(aLArgs); aGF.Perform(); if (aGF.HasErrors()) { return; } // // update vertices to avoid with SD vertices aIt.Initialize(aLVBounds); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aV = aIt.Value(); const TopTools_ListOfShape& aLVIm = aGF.Modified(aV); if (aLVIm.IsEmpty()) { theMVBounds.Add(aV); } else { const TopoDS_Shape& aVIm = aLVIm.First(); theMVBounds.Add(aVIm); } } // // find invalid splits of edges TopTools_MapOfShape aMEInv; GetInvalidEdges(theNewVertsToAvoid, theMVBounds, aGF, aMEInv); // BRep_Builder aBB; // get valid splits to intersect with the commons TopoDS_Compound aCEIm; aBB.MakeCompound(aCEIm); // // remove the splits containing vertices from invalid edges aIt.Initialize(aLEInt); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); // TopTools_ListOfShape aLEIm = aGF.Modified(aE); if (aLEIm.IsEmpty()) { continue; } // aIt1.Initialize(aLEIm); for (; aIt1.More(); ) { const TopoDS_Shape& aEIm = aIt1.Value(); // if (aMEInv.Contains(aEIm)) { aLEIm.Remove(aIt1); } else { aBB.Add(aCEIm, aEIm); aIt1.Next(); } } // if (aLEIm.Extent()) { TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE); if (!pLEIm) { pLEIm = theEImages.Bound(aE, TopTools_ListOfShape()); } pLEIm->Append(aLEIm); } } // if (!aLCE.Extent()) { return; } // // trim common edges by other intersection edges BOPAlgo_Builder aGFCE; aGFCE.SetArguments(aLCE); aGFCE.AddArgument(aCEIm); aGFCE.Perform(); // if (aGFCE.HasErrors()) { return; } // const BOPDS_PDS& pDS = aGFCE.PDS(); TopTools_ListIteratorOfListOfShape aItLCE(aLCE); for (; aItLCE.More(); aItLCE.Next()) { const TopoDS_Shape& aE = aItLCE.Value(); TopTools_ListOfShape aLEIm = aGFCE.Modified(aE); if (aLEIm.IsEmpty()) { continue; } // // check if it's not coincide with some intersection edge BOPDS_ListIteratorOfListOfPaveBlock aItLPB(pDS->PaveBlocks(pDS->Index(aE))); for (; aItLPB.More(); aItLPB.Next()) { if (pDS->IsCommonBlock(aItLPB.Value())) { // find with what it is a common const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock(aItLPB.Value())->PaveBlocks(); BOPDS_ListIteratorOfListOfPaveBlock aItLPBC(aLPBC); for (; aItLPBC.More(); aItLPBC.Next()) { const TopoDS_Shape& aEC = pDS->Shape(aItLPBC.Value()->OriginalEdge()); if (!theMECheckExt.Contains(aEC)) { break; } } if (aItLPBC.More()) { break; } } } if (aItLPB.More()) { // avoid creation of unnecessary splits from commons which // coincide with intersection edges continue; } // // save the images TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE); if (!pLEIm) { pLEIm = theEImages.Bound(aE, TopTools_ListOfShape()); } pLEIm->Append(aLEIm); // // save bounding vertices for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { const TopoDS_Shape& aV = aItV.Value(); const TopTools_ListOfShape& aLVIm = aGFCE.Modified(aV); theMVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First()); } } } //======================================================================= //function : GetInvalidEdges //purpose : Looking for the invalid edges by intersecting with invalid vertices //======================================================================= void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theMVBounds, BOPAlgo_Builder& theGF, TopTools_MapOfShape& theMEInv) { if (theVertsToAvoid.IsEmpty()) { return; } // TopTools_ListIteratorOfListOfShape aIt, aIt1; // get vertices created with intersection edges const TopoDS_Shape& aRes = theGF.Shape(); TopTools_IndexedDataMapOfShapeListOfShape aDMVE; TopExp::MapShapesAndAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aDMVE); // const BOPDS_PDS& pDS = theGF.PDS(); // // find invalid splits of edges // check if the vertex is invalid: // a. it may be the vertex SD with the vertices to avoid // b. or it may be the vertex which is created by the intersection // of only existing edges, i.e. no new intersection edges goes // through this vertex // TopTools_MapOfShape aMVInv; Standard_Integer i, aNb = aDMVE.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Vertex& aV = TopoDS::Vertex(aDMVE.FindKey(i)); if (theMVBounds.Contains(aV)) { continue; } // Standard_Integer nV = pDS->Index(aV); if ((nV >= 0) && !pDS->IsNewShape(nV)) { continue; } // TopTools_MapIteratorOfMapOfShape aItM(theVertsToAvoid); for (; aItM.More(); aItM.Next()) { const TopoDS_Vertex& aVInv = *(TopoDS_Vertex*)&aItM.Value(); Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV(aV, aVInv); if (!iFlag) { aMVInv.Add(aV); break; } } // if (aItM.More()) { const TopTools_ListOfShape& aLVE = aDMVE.FindFromKey(aV); aIt.Initialize(aLVE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); theMEInv.Add(aE); } } } } //======================================================================= //function : UpdateValidEdges //purpose : Making the new splits and updating the maps //======================================================================= void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theFLE, const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges, const TopTools_MapOfShape& theMVBounds, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, const TopTools_MapOfShape& theMEInvOnArt, TopTools_MapOfShape& theMECheckExt, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_MapOfShape& theVertsToAvoid, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_DataMapOfShapeListOfShape& theEETrim, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes) { // update images and origins of edges, plus update AsDes // // new edges TopTools_ListOfShape aLE; // back connection from edges to faces TopTools_DataMapOfShapeListOfShape aMELF; // TopTools_MapOfShape aMETmp; Standard_Integer i, aNb = theFLE.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Face& aF = TopoDS::Face(theFLE.FindKey(i)); // const TopTools_ListOfShape& aLEInt = theFLE(i); TopTools_ListIteratorOfListOfShape aItLE(aLEInt); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); if ((theMECheckExt.Contains(aE) || aMETmp.Contains(aE)) && !theEImages.IsBound(aE)) { theMECheckExt.Remove(aE); aMETmp.Add(aE); continue; } TopTools_ListOfShape* pLF = aMELF.ChangeSeek(aE); if (!pLF) { pLF = aMELF.Bound(aE, TopTools_ListOfShape()); aLE.Append(aE); } pLF->Append(aF); } } // if (aLE.IsEmpty()) { return; } // // bounding edges, that are going to be replaced TopTools_MapOfShape aMEB; // // new intersection edges TopTools_MapOfShape aMENew; // map of old vertices TopTools_MapOfShape aMVOld; // back connection to untrimmed edges TopTools_DataMapOfShapeListOfShape aDMEOr; // // trim the new intersection edges TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt, theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF); // if (theEImages.IsEmpty()) { // No new splits is preserved // update intersection edges and exit UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins, theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes); return; } BRep_Builder aBB; // Make connexity blocks of the invalid edges // and treat each block separately // Compound of all invalid edges to make the blocks TopoDS_Compound aCEAll; aBB.MakeCompound(aCEAll); Standard_Integer aNbE = theOENEdges.Extent(); for (i = 1; i <= aNbE; ++i) aBB.Add(aCEAll, theOENEdges.FindKey(i)); // Separate the edges into blocks TopTools_ListOfShape aLBlocks; BOPTools_AlgoTools::MakeConnexityBlocks(aCEAll, TopAbs_VERTEX, TopAbs_EDGE, aLBlocks); // Perform intersection of the new splits for each block // Intersected splits TopTools_IndexedDataMapOfShapeListOfShape aMBlocksSp; TopTools_ListIteratorOfListOfShape aItLB(aLBlocks); for (; aItLB.More(); aItLB.Next()) { const TopoDS_Shape& aBlock = aItLB.Value(); // Get the list of new edges for the block TopTools_ListOfShape aBlockLENew; { // Fence map TopTools_MapOfShape aMEFence; TopExp_Explorer anExpE(aBlock, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { const TopoDS_Shape& aE = anExpE.Current(); const TopTools_ListOfShape& aLEInt = theOENEdges.FindFromKey(aE); TopTools_ListIteratorOfListOfShape aItLEInt(aLEInt); for (; aItLEInt.More(); aItLEInt.Next()) { if (aMEFence.Add(aItLEInt.Value())) aBlockLENew.Append(aItLEInt.Value()); } } } if (aBlockLENew.IsEmpty()) continue; // Get the splits of new edges to intersect BOPCol_ListOfShape aLSplits; TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE); if (!pLEIm || pLEIm->IsEmpty()) continue; TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) aLSplits.Append(aItLEIm.Value()); } if (aLSplits.IsEmpty()) continue; TopoDS_Shape aCE; if (aLSplits.Extent() > 1) // Intersect the new splits among themselves to avoid self-intersections IntersectEdges(aLSplits, aBlockLENew, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt, theEImages, theModifiedEdges, aDMEOr, aMELF, aCE); else aCE = aLSplits.First(); aMBlocksSp.Add(aCE, aBlockLENew); } // Perform filtering of the edges in two steps: // - Check each block separately using localized bounds // taken only from the splits of faces of the current block; // - Intersect all splits together and filter the splits by all bounds. // FIRST STAGE - separate treatment of the blocks // Valid splits to be preserved on the first stage TopTools_MapOfShape aMEVal; // Blocks of valid edges on the first stage BOPCol_ListOfShape aLValBlocks; // Context for caching the classification tools Handle(IntTools_Context) aCtx = new IntTools_Context; Standard_Integer aNbB = aMBlocksSp.Extent(); for (i = 1; i <= aNbB; ++i) { const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i); const TopTools_ListOfShape& aBlockLENew = aMBlocksSp(i); // Get all participating faces to get the bounds TopTools_ListOfShape aLFaces; TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew); for (; aItLE.More(); aItLE.Next()) { const TopTools_ListOfShape *pLF = aMELF.Seek(aItLE.Value()); if (!pLF) continue; TopTools_ListIteratorOfListOfShape aItLF(*pLF); for (; aItLF.More(); aItLF.Next()) AppendToList(aLFaces, aItLF.Value()); } // Localized bounds of the splits of the offset faces // to filter the new splits of the current block TopoDS_Shape aFilterBounds; GetBounds(aLFaces, theFImages, aMEB, aFilterBounds); // Filter the splits by bounds TopTools_MapOfShape aMEInvLoc; GetInvalidEdgesByBounds(aCE, aFilterBounds, theFImages, theSolids, theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages, theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInvLoc); // Keep only valid edges of the block TopoDS_Compound aCEVal; aBB.MakeCompound(aCEVal); Standard_Boolean bKept = Standard_False; TopExp_Explorer anExpE(aCE, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { const TopoDS_Shape& aESp = anExpE.Current(); if (!aMEInvLoc.Contains(aESp) && aMEVal.Add(aESp)) { aBB.Add(aCEVal, aESp); bKept = Standard_True; } } if (bKept) aLValBlocks.Append(aCEVal); } // Filter the images of edges after the first filtering stage TopoDS_Shape aSplits1; FilterSplits(aLE, aMEVal, Standard_False, theEImages, aSplits1); if (aLValBlocks.IsEmpty()) { // update intersection edges UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins, theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes); return; } // SECOND STAGE - Filter the remaining splits together // Add for intersection already removed new edges using them // as markers for other invalid edges aNbB = aMBlocksSp.Extent(); for (i = 1; i <= aNbB; ++i) { const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i); for (TopExp_Explorer anExp(aCE, TopAbs_EDGE); anExp.More(); anExp.Next()) { const TopoDS_Shape& aEIm = anExp.Current(); if (aMENew.Contains(aEIm) && !aMEVal.Contains(aEIm)) aLValBlocks.Append(aEIm); } } if (aLValBlocks.Extent() > 1) // intersect the new splits among themselves to avoid self-intersections IntersectEdges(aLValBlocks, aLE, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt, theEImages, theModifiedEdges, aDMEOr, aMELF, aSplits1); else aSplits1 = aLValBlocks.First(); // Get all faces to get the bounds from their splits TopTools_ListOfShape aLFaces; for (i = 1; i <= theFImages.Extent(); ++i) aLFaces.Append(theFImages.FindKey(i)); // Bounds of the splits of the offset faces to filter the new splits TopoDS_Shape aFilterBounds; GetBounds(aLFaces, theFImages, aMEB, aFilterBounds); // Filter the splits by intersection with bounds TopTools_MapOfShape aMEInv; GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids, theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages, theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInv); // Filter the images of edges after the second filtering stage // and combine all valid edges into a single compound TopoDS_Shape aSplits; FilterSplits(aLE, aMEInv, Standard_True, theEImages, aSplits); // get bounds to update // we need to update the edges of all the affected faces TopTools_ListOfShape aLF; // prepare the vertices from new splits of edges TopTools_IndexedMapOfShape aMVSp; TopExp::MapShapes(aSplits, TopAbs_VERTEX, aMVSp); // Standard_Integer aNbF = theFImages.Extent(); for (i = 1; i <= aNbF; ++i) { const TopoDS_Shape& aF = theFImages.FindKey(i); if (theFLE.Contains(aF)) { aLF.Append(aF); continue; } // // check the splits of faces to have vertices from splits const TopTools_ListOfShape& aLFIm = theFImages(i); TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm); for (; aItLFIm.More(); aItLFIm.Next()) { const TopoDS_Shape& aFIm = aItLFIm.Value(); // TopExp_Explorer aExpV(aFIm, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); if (aMVSp.Contains(aV)) { break; } } // if (aExpV.More()) { break; } } // if (aItLFIm.More()) { aLF.Append(aF); } } // // get bounds from splits of faces of aLF TopoDS_Shape aBounds; TopTools_ListOfShape aLAValid, aLABounds; GetBoundsToUpdate(aLF, theOEImages, theOEOrigins, aMEB, aLABounds, aLAValid, aBounds, theAsDes); // // intersect valid splits with bounds and update both BOPAlgo_Builder aGF; // The order is important here, because we need to keep the // unmodified edges from the Bounds in the resulting maps. // In case of total coincidence of the edges with the same vertices // the edges in the common block will not be split and no new // edges will be created and the first pave block // will be used as a real pave block. aGF.AddArgument(aBounds); aGF.AddArgument(aSplits); aGF.Perform(); // // update splits UpdateImages(aLE, theEImages, aGF, theModifiedEdges); // // update new intersection edges UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins, theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes); // // update bounds UpdateImages(aLAValid, theOEImages, aGF, theModifiedEdges); UpdateOrigins(aLABounds, theOEOrigins, aGF); UpdateOrigins(aLABounds, theEdgesOrigins, aGF); UpdateIntersectedEdges(aLABounds, theETrimEInf, aGF); // // update the EdgesToAvoid with the splits TopTools_IndexedMapOfShape aNewEdges; const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek(aSplits); if (pSplitsIm) { TopTools_ListIteratorOfListOfShape aItSpIm(*pSplitsIm); for (; aItSpIm.More(); aItSpIm.Next()) { TopExp::MapShapes(aItSpIm.Value(), TopAbs_EDGE, aNewEdges); } } // aNbE = theEdgesToAvoid.Extent(); for (i = 1; i <= aNbE; ++i) { const TopoDS_Shape& aE = theEdgesToAvoid(i); const TopTools_ListOfShape& aLEIm = aGF.Modified(aE); TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); if (!aNewEdges.Contains(aEIm)) { theEdgesToAvoid.Add(aEIm); } } } } //======================================================================= //function : TrimNewIntersectionEdges //purpose : //======================================================================= void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theEETrim, const TopTools_MapOfShape& theMVBounds, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theMEB, TopTools_MapOfShape& theMVOld, TopTools_MapOfShape& theMENew, TopTools_DataMapOfShapeListOfShape& theDMEOr, TopTools_DataMapOfShapeListOfShape& theMELF) { TopTools_ListIteratorOfListOfShape aIt, aIt1; aIt.Initialize(theLE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); // Standard_Boolean bCheckExt = theMECheckExt.Remove(aE); // Standard_Boolean bOld = theEETrim.IsBound(aE); if (bOld) { const TopTools_ListOfShape& aLET = theEETrim.Find(aE); aIt1.Initialize(aLET); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aET = aIt1.Value(); theMEB.Add(aET); TopExp_Explorer aExpV(aET, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); theMVOld.Add(aV); } } } // if (!theEImages.IsBound(aE)) { continue; } // TopTools_ListOfShape& aLEIm = theEImages.ChangeFind(aE); if (aLEIm.IsEmpty()) { theEImages.UnBind(aE); continue; } // TopoDS_Shape aCEIm; TopTools_MapOfShape aMEVBounds; // if (aLEIm.Extent() > 1) { TopTools_IndexedMapOfShape aMV; // fuse these parts BOPAlgo_Builder aGFE; TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); aGFE.AddArgument(aEIm); TopExp::MapShapes(aEIm, TopAbs_VERTEX, aMV); } // // add two bounding vertices of this edge to the operation TopoDS_Vertex aV1, aV2; TopExp::Vertices(TopoDS::Edge(aE), aV1, aV2); // aGFE.AddArgument(aV1); aGFE.AddArgument(aV2); aMV.Add(aV1); aMV.Add(aV2); // aGFE.Perform(); if (!aGFE.HasErrors()) { // get images of bounding vertices to remove splits containing them // in case some of the bounding edges has been interfered // during operation it is necessary to update their images as well Standard_Integer iV, aNbV = aMV.Extent(); for (iV = 1; iV <= aNbV; ++iV) { const TopoDS_Shape& aV = aMV(iV); if (theMVBounds.Contains(aV) || aV.IsSame(aV1) || aV.IsSame(aV2)) { const TopTools_ListOfShape& aLVIm = aGFE.Modified(aV); aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First()); } } // aCEIm = aGFE.Shape(); } } else { aCEIm = aLEIm.First(); } // aLEIm.Clear(); // TopExp_Explorer aExp(aCEIm, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aEIm = aExp.Current(); // // check the split not to contain bounding vertices TopoDS_Iterator aItV(aEIm); for (; aItV.More(); aItV.Next()) { const TopoDS_Shape& aV = aItV.Value(); if (aMEVBounds.Contains(aV) || theMVBounds.Contains(aV)) { break; } } // if (!aItV.More()) { aLEIm.Append(aEIm); // theDMEOr.Bound(aEIm, TopTools_ListOfShape())->Append(aE); } } // if (aLEIm.IsEmpty()) { theEImages.UnBind(aE); } else { const TopTools_ListOfShape& aLFE = theMELF.Find(aE); TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm); if (!pLFEIm) { pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape()); } TopTools_ListIteratorOfListOfShape aItLF(aLFE); for (; aItLF.More(); aItLF.Next()) { AppendToList(*pLFEIm, aItLF.Value()); } // if (bCheckExt) { theMECheckExt.Add(aEIm); } else if (!bOld) { theMENew.Add(aEIm); } } } } } //======================================================================= //function : IntersectEdges //purpose : Intersecting the trimmed edges to avoid self-intersections //======================================================================= void IntersectEdges(const BOPCol_ListOfShape& theLA, const TopTools_ListOfShape& theLE, const TopTools_MapOfShape& theMVBounds, const TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMENew, TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theModifiedEdges, TopTools_DataMapOfShapeListOfShape& theDMEOr, TopTools_DataMapOfShapeListOfShape& theMELF, TopoDS_Shape& theSplits) { BOPAlgo_Builder aGFA; aGFA.SetArguments(theLA); aGFA.Perform(); if (aGFA.HasErrors()) { // just copy input to the result TopoDS_Compound aSp; BRep_Builder aBB; aBB.MakeCompound(aSp); BOPCol_ListIteratorOfListOfShape anIt(theLA); for (; anIt.More(); anIt.Next()) { const TopoDS_Shape& aE = anIt.Value(); aBB.Add(aSp, aE); } theSplits = aSp; return; } // UpdateImages(theLE, theEImages, aGFA, theModifiedEdges); // // compound of valid splits theSplits = aGFA.Shape(); // TopTools_ListIteratorOfListOfShape aIt, aIt1; // prepare list of edges to update TopTools_ListOfShape aLEInput; for (aIt.Initialize(theLA); aIt.More(); aIt.Next()) { TopExp_Explorer anExpE(aIt.Value(), TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) aLEInput.Append(anExpE.Current()); } // update new edges aIt.Initialize(aLEInput); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); if (!theMENew.Contains(aE)) continue; const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE); if (aLEIm.IsEmpty()) continue; theMENew.Remove(aE); aIt1.Initialize(aLEIm); for (; aIt1.More(); aIt1.Next()) theMENew.Add(aIt1.Value()); } // // update edges after intersection for extended checking aIt.Initialize(aLEInput); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE); if (aLEIm.IsEmpty()) { continue; } // if (theMECheckExt.Contains(aE)) { aIt1.Initialize(aLEIm); for (; aIt1.More(); aIt1.Next()) { theMECheckExt.Add(aIt1.Value()); } theMECheckExt.Remove(aE); } // const TopTools_ListOfShape& aLFE = theMELF.Find(aE); aIt1.Initialize(aLEIm); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aEIm = aIt1.Value(); TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm); if (!pLFEIm) { pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape()); } TopTools_ListIteratorOfListOfShape aItLF(aLFE); for (; aItLF.More(); aItLF.Next()) { AppendToList(*pLFEIm, aItLF.Value()); } } } // TopTools_MapOfShape aMEInv; GetInvalidEdges(theVertsToAvoid, theMVBounds, aGFA, aMEInv); if (aMEInv.Extent()) { // update shape TopoDS_Compound aSp; BRep_Builder aBB; aBB.MakeCompound(aSp); TopExp_Explorer aExp(theSplits, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (!aMEInv.Contains(aE)) { aBB.Add(aSp, aE); } } theSplits = aSp; } // // update origins UpdateOrigins(aLEInput, theDMEOr, aGFA); } //======================================================================= //function : GetBounds //purpose : Getting edges from the splits of offset faces //======================================================================= void GetBounds(const TopTools_ListOfShape& theLFaces, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_MapOfShape& theMEB, TopoDS_Shape& theBounds) { BRep_Builder aBB; // Make compound of edges contained in the splits of faces TopoDS_Compound aBounds; aBB.MakeCompound(aBounds); // Fence map TopTools_MapOfShape aMFence; TopTools_ListIteratorOfListOfShape aItLF(theLFaces); for (; aItLF.More(); aItLF.Next()) { const TopTools_ListOfShape* pLFIm = theFImages.Seek(aItLF.Value()); if (!pLFIm) continue; TopTools_ListIteratorOfListOfShape aIt(*pLFIm); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aFIm = aIt.Value(); // TopExp_Explorer aExpE(aFIm, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aEIm = aExpE.Current(); if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) { aBB.Add(aBounds, aEIm); } } } } theBounds = aBounds; } //======================================================================= //function : GetBoundsToUpdate //purpose : Get bounding edges that should be updated //======================================================================= void GetBoundsToUpdate(const TopTools_ListOfShape& theLF, const TopTools_DataMapOfShapeListOfShape& theOEImages, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, const TopTools_MapOfShape& theMEB, TopTools_ListOfShape& theLABounds, TopTools_ListOfShape& theLAValid, TopoDS_Shape& theBounds, Handle(BRepAlgo_AsDes)& theAsDes) { // get all edges TopoDS_Compound aBounds; BRep_Builder aBB; aBB.MakeCompound(aBounds); // TopTools_MapOfShape aMAValid, aMFence; // TopTools_ListIteratorOfListOfShape aItLF(theLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aF = aItLF.Value(); // TopTools_IndexedMapOfShape aMDE; const TopTools_ListOfShape& aLFDes = theAsDes->Descendant(aF); TopTools_ListIteratorOfListOfShape aItLFDes(aLFDes); for (; aItLFDes.More(); aItLFDes.Next()) { const TopoDS_Shape& aED = aItLFDes.Value(); const TopTools_ListOfShape *pLEDIm = theOEImages.Seek(aED); if (!pLEDIm) { aMDE.Add(aED); continue; } // TopTools_ListIteratorOfListOfShape aItLEDIm(*pLEDIm); for (; aItLEDIm.More(); aItLEDIm.Next()) { const TopoDS_Shape& aEDIm = aItLEDIm.Value(); aMDE.Add(aEDIm); } } // Standard_Integer j, aNbE = aMDE.Extent(); for (j = 1; j <= aNbE; ++j) { const TopoDS_Edge& aEIm = TopoDS::Edge(aMDE(j)); // if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) { aBB.Add(aBounds, aEIm); theLABounds.Append(aEIm); } // const TopTools_ListOfShape *pLO = theOEOrigins.Seek(aEIm); if (pLO) { TopTools_ListIteratorOfListOfShape aItLO(*pLO); for (; aItLO.More(); aItLO.Next()) { const TopoDS_Shape& aEO = aItLO.Value(); // if (aMAValid.Add(aEO)) { theLAValid.Append(aEO); } } } else { if (aMAValid.Add(aEIm)) { theLAValid.Append(aEIm); } } } } theBounds = aBounds; } //======================================================================= //function : GetInvalidEdgesByBounds //purpose : Filter new splits by intersection with bounds //======================================================================= void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& theBounds, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theMVOld, const TopTools_MapOfShape& theMENew, const TopTools_DataMapOfShapeListOfShape& theDMEOr, const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_MapOfShape& theMECheckExt, const TopTools_MapOfShape& theMEInvOnArt, Handle(IntTools_Context)& theCtx, TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMEInv) { // map splits to check the vertices of edges TopTools_IndexedDataMapOfShapeListOfShape aDMVE; TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE); // BOPAlgo_Section aSec; aSec.AddArgument(theSplits); aSec.AddArgument(theBounds); // aSec.Perform(); // // invalid vertices TopTools_IndexedMapOfShape aMVInv; // vertices to check additionally by classification relatively to solid TopTools_MapOfShape aMVCheckAdd; // collect parts for removal const BOPDS_PDS& pDS = aSec.PDS(); // // check edge/edge intersections const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE(); Standard_Integer i, aNb = aEEs.Extent(); for (i = 0; i < aNb; ++i) { const BOPDS_InterfEE& aEE = aEEs(i); // const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1()); const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2()); // if (!aEE.HasIndexNew()) { if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) { theMEInv.Add(aE1); } continue; } // if (theInvEdges.Contains(aE2)) { theMEInv.Add(aE1); } // if (theMEInvOnArt.Contains(aE2)) { // avoid checking of the vertices of the split edge intersected by // the invalid edge from artificial face TopoDS_Vertex aV1, aV2; TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2); if (aDMVE.Contains(aV1) && aDMVE.Contains(aV2)) { continue; } } // // add vertices of all images of the edge from splits for checking const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1); TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { const TopoDS_Shape& aEOr = aItLEOr.Value(); // const TopTools_ListOfShape *pLEIm = theEImages.Seek(aEOr); if (!pLEIm) continue; TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); // TopoDS_Iterator aItV(aEIm); for (; aItV.More(); aItV.Next()) { const TopoDS_Shape& aV = aItV.Value(); if (!theMVOld.Contains(aV)) { aMVInv.Add(aV); aMVCheckAdd.Add(aV); } } } } } // // to avoid unnecessary filling of parts due to extra trim of the edges // process Edge/Edge interferences of type EDGE, i.e. common blocks and check // not the bounding vertices of the edges, but check the edge itself // to be lying on some face // // all common blocks are contained in the result of SECTION operation // between sets of edges const TopoDS_Shape& aSecR = aSec.Shape(); // TopTools_IndexedMapOfShape aMSSec; TopExp::MapShapes(aSecR, aMSSec); // const BOPCol_DataMapOfShapeListOfShape& anIm = aSec.Images(); for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); if (aSec.IsDeleted(aE)) { // no common blocks for this edge continue; } // const BOPCol_ListOfShape* pLEIm = anIm.Seek(aE); if (!pLEIm) { // no splits, i.e. completely coincides with some edge from boundary continue; } // BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More(); aItLEIm.Next()) { const TopoDS_Shape& aEIm = aItLEIm.Value(); if (!aMSSec.Contains(aEIm)) { // the edge included in section only partially. // the part not included in section may be excessive // // check vertices of this edge - if one of them is new // the edge might be removed TopoDS_Vertex aV1, aV2; TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2); if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) { // add this edge for checking by making new vertex in the middle of the edge TopoDS_Vertex aV; Standard_Real f, l; const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l); BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion()); // and adding this vertex for checking aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE); aMVInv.Add(aV); break; } } } } // // Add for check also the edges created from common between splits // of offset faces edges not connected to any invalidity. // These edges may also accidentally fill some part. TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aE = aItM.Value(); // // make new vertex in the middle of the edge TopoDS_Vertex aV; Standard_Real f, l; const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l); BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion()); // add this vertex for checking aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE); aMVInv.Add(aV); } // // add for check also the vertices connected only to new or old edges aNb = aDMVE.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aV = aDMVE.FindKey(i); if (theMVOld.Contains(aV)) { continue; } // Standard_Boolean bNew = Standard_False, bOld = Standard_False; const TopTools_ListOfShape& aLEx = aDMVE(i); TopTools_ListIteratorOfListOfShape aIt(aLEx); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); if (theMECheckExt.Contains(aE)) { continue; } // if (theMENew.Contains(aE)) { bNew = Standard_True; } else { bOld = Standard_True; } // if (bNew && bOld) { break; } } // if (!bNew || !bOld) { aMVInv.Add(aV); aMVCheckAdd.Remove(aV); } } // // perform the checking of the vertices Standard_Integer iv, aNbIV = aMVInv.Extent(); for (iv = 1; iv <= aNbIV; ++iv) { const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv)); if (theMVOld.Contains(aV)) { continue; } // const TopTools_ListOfShape* pLEInv = aDMVE.Seek(aV); if (!pLEInv) { continue; } // find faces by the edges to check the vertex TopTools_IndexedMapOfShape aMF; TopTools_ListIteratorOfListOfShape aItLE(*pLEInv); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); const TopTools_ListOfShape& aLF = theMELF.Find(aE); TopTools_ListIteratorOfListOfShape aItLF(aLF); for (; aItLF.More(); aItLF.Next()) { aMF.Add(aItLF.Value()); } } // // check the vertex to belong to some split of the faces Standard_Boolean bInvalid = Standard_True; // Standard_Integer aNbF = aMF.Extent(); for (i = 1; i <= aNbF && bInvalid; ++i) { const TopoDS_Face& aF = TopoDS::Face(aMF(i)); const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); // TopTools_ListIteratorOfListOfShape aItLF(aLFIm); for (; aItLF.More() && bInvalid; aItLF.Next()) { const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value()); TopExp_Explorer aExp(aFIm, TopAbs_VERTEX); for (; aExp.More() && bInvalid; aExp.Next()) { const TopoDS_Shape& aVF = aExp.Current(); bInvalid = !aVF.IsSame(aV); } } // if (bInvalid) { Standard_Real U, V, aTol; Standard_Integer iStatus = theCtx->ComputeVF(aV, aF, U, V, aTol); if (!iStatus) { // classify the point relatively faces gp_Pnt2d aP2d(U, V); aItLF.Initialize(aLFIm); for (; aItLF.More() && bInvalid; aItLF.Next()) { const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value()); bInvalid = !theCtx->IsPointInOnFace(aFIm, aP2d); } } } } // if (bInvalid && aMVCheckAdd.Contains(aV)) { // the vertex is invalid for all faces // check the same vertex for the solids const gp_Pnt& aP = BRep_Tool::Pnt(aV); Standard_Real aTolV = BRep_Tool::Tolerance(aV); // TopExp_Explorer aExpS(theSolids, TopAbs_SOLID); for (; aExpS.More() && bInvalid; aExpS.Next()) { const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current()); BRepClass3d_SolidClassifier& aSC = theCtx->SolidClassifier(aSol); aSC.Perform(aP, aTolV); bInvalid = (aSC.State() == TopAbs_OUT); } } // if (bInvalid) { theVertsToAvoid.Add(aV); aItLE.Initialize(*pLEInv); for (; aItLE.More(); aItLE.Next()) { theMEInv.Add(aItLE.Value()); } } } } //======================================================================= //function : FilterSplits //purpose : Filter the images of edges from the invalid edges //======================================================================= void FilterSplits(const TopTools_ListOfShape& theLE, const TopTools_MapOfShape& theMEFilter, const Standard_Boolean theIsInv, TopTools_DataMapOfShapeListOfShape& theEImages, TopoDS_Shape& theSplits) { TopoDS_Compound aSplits; BRep_Builder().MakeCompound(aSplits); TopTools_MapOfShape aMFence; TopTools_ListIteratorOfListOfShape aItLE(theLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); TopTools_ListOfShape *pLEIm = theEImages.ChangeSeek(aE); if (!pLEIm) continue; TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm); for (; aItLEIm.More();) { const TopoDS_Shape& aEIm = aItLEIm.Value(); if (theMEFilter.Contains(aEIm) == theIsInv) { pLEIm->Remove(aItLEIm); continue; } if (aMFence.Add(aEIm)) BRep_Builder().Add(aSplits, aEIm); aItLEIm.Next(); } if (pLEIm->IsEmpty()) theEImages.UnBind(aE); } theSplits = aSplits; } //======================================================================= //function : UpdateNewIntersectionEdges //purpose : Updating the maps of images and origins of the offset edges //======================================================================= void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, TopTools_DataMapOfShapeListOfShape& theOEOrigins, TopTools_DataMapOfShapeShape& theETrimEInf, TopTools_DataMapOfShapeListOfShape& theEETrim, TopTools_MapOfShape& theModifiedEdges, Handle(BRepAlgo_AsDes)& theAsDes) { TopTools_ListOfShape aLEImEmpty; TopTools_ListIteratorOfListOfShape aIt, aIt1; // update global maps of images and origins with new splits aIt.Initialize(theLE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); // if (!theEImages.IsBound(aE)) { TopTools_ListOfShape* pLET = theEETrim.ChangeSeek(aE); if (!pLET) { continue; } // TopTools_ListIteratorOfListOfShape aItLET(*pLET); for (; aItLET.More();) { const TopoDS_Shape& aET = aItLET.Value(); if (!theInvEdges.Contains(aET) && !theInvertedEdges.Contains(aET)) { pLET->Remove(aItLET); } else { aItLET.Next(); } } // if (pLET->IsEmpty()) { continue; } } // new images const TopTools_ListOfShape& aLENew = theEImages.IsBound(aE) ? theEImages.Find(aE) : aLEImEmpty; // // save connection to untrimmed edge for the next steps aIt1.Initialize(aLENew); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aET = aIt1.Value(); theETrimEInf.Bind(aET, aE); theModifiedEdges.Add(aET); } // // check if it is existing edge if (!theEETrim.IsBound(aE)) { const TopTools_ListOfShape& aLF = theMELF.Find(aE); // the edge is new // add this edge to AsDes aIt1.Initialize(aLF); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aF = aIt1.Value(); theAsDes->Add(aF, aE); } // // add aE to the images theOEImages.Bind(aE, aLENew); theModifiedEdges.Add(aE); // // add to origins TopTools_ListIteratorOfListOfShape aItNew(aLENew); for (; aItNew.More(); aItNew.Next()) { const TopoDS_Shape& aENew = aItNew.Value(); if (theOEOrigins.IsBound(aENew)) { TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew); AppendToList(aEOrigins, aE); } else { TopTools_ListOfShape aEOrigins; aEOrigins.Append(aE); theOEOrigins.Bind(aENew, aEOrigins); } } // // update connection to initial origins if (theEdgesOrigins.IsBound(aE)) { const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aE); aIt1.Initialize(aLENew); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aENew = aIt1.Value(); if (theEdgesOrigins.IsBound(aENew)) { TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew); TopTools_ListIteratorOfListOfShape aItOrInit(aLEOrInit); for (; aItOrInit.More(); aItOrInit.Next()) { const TopoDS_Shape& aEOr = aItOrInit.Value(); AppendToList(aLENewOr, aEOr); } } else { theEdgesOrigins.Bind(aENew, aLEOrInit); } } } // continue; } // // old images const TopTools_ListOfShape& aLEOld = theEETrim.Find(aE); // // list of initial origins TopTools_ListOfShape anInitOrigins; // // it is necessary to replace the old edges with new ones aIt1.Initialize(aLEOld); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aEOld = aIt1.Value(); // if (theOEOrigins.IsBound(aEOld)) { // get its origins const TopTools_ListOfShape& aEOrigins = theOEOrigins.Find(aEOld); // TopTools_ListIteratorOfListOfShape aItOr(aEOrigins); for (; aItOr.More(); aItOr.Next()) { const TopoDS_Shape& aEOr = aItOr.Value(); // theModifiedEdges.Add(aEOr); // TopTools_ListOfShape& aEImages = theOEImages.ChangeFind(aEOr); // // remove old edge from images TopTools_ListIteratorOfListOfShape aItIm(aEImages); for (; aItIm.More(); ) { const TopoDS_Shape& aEIm = aItIm.Value(); if (aEIm.IsSame(aEOld)) { aEImages.Remove(aItIm); } else { aItIm.Next(); } } // // add new images TopTools_ListIteratorOfListOfShape aItNew(aLENew); for (; aItNew.More(); aItNew.Next()) { const TopoDS_Shape& aENew = aItNew.Value(); AppendToList(aEImages, aENew); if (theOEOrigins.IsBound(aENew)) { TopTools_ListOfShape& aENewOrigins = theOEOrigins.ChangeFind(aENew); AppendToList(aENewOrigins, aEOr); } else { TopTools_ListOfShape aENewOrigins; aENewOrigins.Append(aEOr); theOEOrigins.Bind(aENew, aENewOrigins); } } } } else { // add to images theOEImages.Bind(aEOld, aLENew); // theModifiedEdges.Add(aEOld); // // add to origins TopTools_ListIteratorOfListOfShape aItNew(aLENew); for (; aItNew.More(); aItNew.Next()) { const TopoDS_Shape& aENew = aItNew.Value(); if (theOEOrigins.IsBound(aENew)) { TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew); AppendToList(aEOrigins, aEOld); } else { TopTools_ListOfShape aEOrigins; aEOrigins.Append(aEOld); theOEOrigins.Bind(aENew, aEOrigins); } } } // // update connection to initial shape if (theEdgesOrigins.IsBound(aEOld)) { const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aEOld); TopTools_ListIteratorOfListOfShape aItEOrInit(aLEOrInit); for (; aItEOrInit.More(); aItEOrInit.Next()) { const TopoDS_Shape& aEOrInit = aItEOrInit.Value(); AppendToList(anInitOrigins, aEOrInit); } } } // if (anInitOrigins.Extent()) { TopTools_ListIteratorOfListOfShape aItNew(aLENew); for (; aItNew.More(); aItNew.Next()) { const TopoDS_Shape& aENew = aItNew.Value(); if (theEdgesOrigins.IsBound(aENew)) { TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew); TopTools_ListIteratorOfListOfShape aItOrInit(anInitOrigins); for (; aItOrInit.More(); aItOrInit.Next()) { const TopoDS_Shape& aEOr = aItOrInit.Value(); AppendToList(aLENewOr, aEOr); } } else { theEdgesOrigins.Bind(aENew, anInitOrigins); } } } } } //======================================================================= //function : FillHistory //purpose : Saving obtained results in history tools //======================================================================= void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_DataMapOfShapeListOfShape& theEImages, BRepAlgo_Image& theImage) { Standard_Integer i, aNb = theFImages.Extent(); if (!aNb) { return; } // BRep_Builder aBB; TopoDS_Compound aFaces; aBB.MakeCompound(aFaces); // // Fill history for faces for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aF = theFImages.FindKey(i); const TopTools_ListOfShape& aLFImages = theFImages(i); // if (aLFImages.Extent()) { if (theImage.HasImage(aF)) { theImage.Add(aF, aLFImages); } else { theImage.Bind(aF, aLFImages); } } // TopTools_ListIteratorOfListOfShape aItLF(aLFImages); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Shape& aFIm = aItLF.Value(); aBB.Add(aFaces, aFIm); } } // // fill history for edges TopTools_IndexedMapOfShape aMFE; TopExp::MapShapes(aFaces, TopAbs_EDGE, aMFE); // TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(theEImages); for (; aItEIm.More(); aItEIm.Next()) { const TopoDS_Shape& aE = aItEIm.Key(); const TopTools_ListOfShape& aLEIm = aItEIm.Value(); // Standard_Boolean bHasImage = theImage.HasImage(aE); TopTools_ListIteratorOfListOfShape aItLE(aLEIm); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aEIm = aItLE.Value(); if (aMFE.Contains(aEIm)) { if (bHasImage) { theImage.Add(aE, aEIm); } else { theImage.Bind(aE, aEIm); bHasImage = Standard_True; } } } } } //======================================================================= //function : ProcessMicroEdge //purpose : Checking if the edge is micro edge //======================================================================= Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge, const Handle(IntTools_Context)& theCtx) { TopoDS_Vertex aV1, aV2; TopExp::Vertices(theEdge, aV1, aV2); if (aV1.IsNull() || aV2.IsNull()) { return Standard_False; } // Standard_Boolean bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx); if (bMicro && BRepAdaptor_Curve(theEdge).GetType() == GeomAbs_Line) { Standard_Real aLen = BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2)); BRep_Builder().UpdateVertex(aV1, aLen / 2.); BRep_Builder().UpdateVertex(aV2, aLen / 2.); } // return bMicro; } //======================================================================= //function : UpdateOrigins //purpose : Updating origins //======================================================================= void UpdateOrigins(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeListOfShape& theOrigins, BOPAlgo_Builder& theGF) { TopTools_ListIteratorOfListOfShape aItA(theLA); for (; aItA.More(); aItA.Next()) { const TopoDS_Shape& aS = aItA.Value(); // const TopTools_ListOfShape& aLSIm = theGF.Modified(aS); if (aLSIm.IsEmpty()) { continue; } // TopTools_ListOfShape aLSEmpt; TopTools_ListOfShape *pLS = theOrigins.ChangeSeek(aS); if (!pLS) { pLS = &aLSEmpt; pLS->Append(aS); } // TopTools_ListIteratorOfListOfShape aIt(aLSIm); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aSIm = aIt.Value(); // TopTools_ListOfShape *pLSOr = theOrigins.ChangeSeek(aSIm); if (!pLSOr) { // just bind the origins theOrigins.Bind(aSIm, *pLS); } else { // merge two lists TopTools_ListIteratorOfListOfShape aIt1(*pLS); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aS1 = aIt1.Value(); AppendToList(*pLSOr, aS1); } } } } } //======================================================================= //function : UpdateImages //purpose : Updating images of the shapes //======================================================================= void UpdateImages(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeListOfShape& theImages, BOPAlgo_Builder& theGF, TopTools_MapOfShape& theModified) { TopTools_ListIteratorOfListOfShape aIt(theLA); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aS = aIt.Value(); // TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS); if (!pLSIm) { const TopTools_ListOfShape& aLSIm = theGF.Modified(aS); if (aLSIm.Extent()) { theImages.Bind(aS, aLSIm); theModified.Add(aS); } continue; } // TopTools_MapOfShape aMFence; TopTools_ListOfShape aLSImNew; // Standard_Boolean bModified = Standard_False; // // check modifications of the images TopTools_ListIteratorOfListOfShape aIt1(*pLSIm); for (; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aSIm = aIt1.Value(); const TopTools_ListOfShape& aLSIm1 = theGF.Modified(aSIm); if (aLSIm1.IsEmpty()) { if (aMFence.Add(aSIm)) { aLSImNew.Append(aSIm); } } else { TopTools_ListIteratorOfListOfShape aIt2(aLSIm1); for (; aIt2.More(); aIt2.Next()) { const TopoDS_Shape& aSImIm = aIt2.Value(); if (aMFence.Add(aSImIm)) { aLSImNew.Append(aSImIm); } } bModified = Standard_True; } } // if (bModified) { *pLSIm = aLSImNew; theModified.Add(aS); } } } //======================================================================= //function : UpdateIntersectedEdges //purpose : Saving connection from trimmed edges to not trimmed ones //======================================================================= void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA, TopTools_DataMapOfShapeShape& theETrimEInf, BOPAlgo_Builder& theGF) { TopTools_ListIteratorOfListOfShape aItA(theLA); for (; aItA.More(); aItA.Next()) { const TopoDS_Shape& aS = aItA.Value(); // const TopoDS_Shape* pEInf = theETrimEInf.Seek(aS); if (!pEInf) { continue; } // const TopTools_ListOfShape& aLSIm = theGF.Modified(aS); if (aLSIm.IsEmpty()) { continue; } // TopTools_ListIteratorOfListOfShape aIt(aLSIm); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aEIm = aIt.Value(); if (!theETrimEInf.IsBound(aEIm)) { theETrimEInf.Bind(aEIm, *pEInf); } } } } //======================================================================= //function : FindCommonParts //purpose : Looking for the parts of type contained in both lists //======================================================================= void FindCommonParts(const TopTools_ListOfShape& theLS1, const TopTools_ListOfShape& theLS2, TopTools_ListOfShape& theLSC, const TopAbs_ShapeEnum theType) { // map shapes in the first list TopTools_IndexedMapOfShape aMS1; TopTools_ListIteratorOfListOfShape aIt(theLS1); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aS = aIt.Value(); TopExp::MapShapes(aS, theType, aMS1); } // if (aMS1.IsEmpty()) { return; } // TopTools_MapOfShape aMFence; // check for such shapes in the other list aIt.Initialize(theLS2); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aS = aIt.Value(); // TopExp_Explorer aExp(aS, theType); for(; aExp.More(); aExp.Next()) { const TopoDS_Shape& aST = aExp.Current(); // if (aMS1.Contains(aST) && aMFence.Add(aST)) { theLSC.Append(aST); } } } } //======================================================================= //function : NbPoints //purpose : Defines number of sample points to get average direction of the edge //======================================================================= Standard_Integer NbPoints(const TopoDS_Edge& theEdge) { Standard_Integer aNbP; BRepAdaptor_Curve aBAC(theEdge); switch (aBAC.GetType()) { case GeomAbs_Line: aNbP = 1; break; default: aNbP = 11; } // return aNbP; } //======================================================================= //function : FindShape //purpose : Looking for the same sub-shape in the shape //======================================================================= Standard_Boolean FindShape(const TopoDS_Shape& theSWhat, const TopoDS_Shape& theSWhere, TopoDS_Shape& theRes) { Standard_Boolean bFound = Standard_False; TopAbs_ShapeEnum aType = theSWhat.ShapeType(); TopExp_Explorer aExp(theSWhere, aType); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aS = aExp.Current(); if (aS.IsSame(theSWhat)) { theRes = aS; bFound = Standard_True; break; } } return bFound; } //======================================================================= //function : AppendToList //purpose : Add to a list only unique elements //======================================================================= void AppendToList(TopTools_ListOfShape& theList, const TopoDS_Shape& theShape) { TopTools_ListIteratorOfListOfShape aIt(theList); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aS = aIt.Value(); if (aS.IsSame(theShape)) { return; } } theList.Append(theShape); }