1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00
occt/src/BRepOffset/BRepOffset_MakeOffset_1.cxx
kgv b2d1851c43 0029814: Modeling Data - add method TopoDS_Shape::NbChildren() for simple check of sub-shapes number
TopoDS_Shape::NbChildren() - new method has been introduced.
TopoDS_Shape.lxx, TopoDS_TShape.lxx - inline methods have been moved to hxx.
TopoDS_TShape_Flags has been redeclared as enumeration instead of preprocessor macros.

Cyclic dependency between headers TopoDS_Shape.hxx and TopoDS_TShape.hxx eliminated.

Places where TopoDS_Iterator is used only for calculation of number of sub-shapes are updated to use NbChildren() instead
2018-06-14 14:03:09 +03:00

6940 lines
244 KiB
C++

// 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 <BRepOffset_MakeOffset.hxx>
#include <Precision.hxx>
#include <TopoDS.hxx>
#include <BRepAlgo_AsDes.hxx>
#include <BRepAlgo_Image.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepLib.hxx>
#include <BRepTools.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_DataMapOfShapeInteger.hxx>
#include <BRepOffset_Tool.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BOPDS_DS.hxx>
#include <BOPAlgo_PaveFiller.hxx>
#include <BOPAlgo_Builder.hxx>
#include <BOPAlgo_Section.hxx>
#include <BOPAlgo_MakerVolume.hxx>
#include <BOPAlgo_BuilderFace.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <BOPTools_AlgoTools3D.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_ShrunkRange.hxx>
#ifdef OFFSET_DEBUG
#include <BRepAlgoAPI_Check.hxx>
#endif
typedef NCollection_DataMap
<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> 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 TopTools_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
TopTools_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
TopTools_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
TopTools_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
BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
//
// build splits of faces
BOPAlgo_BuilderFace aBF;
aBF.SetFace(aFF);
aBF.SetShapes(aLE);
aBF.Perform();
//
const TopTools_ListOfShape& aLFSp = aBF.Areas();
TopTools_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
TopTools_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 TopTools_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
if (theCB.NbChildren() < 2) {
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)
{
TopTools_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.Length();
for (iInt = 0; iInt < aNbFF; ++iInt) {
const BOPDS_InterfFF& aFF = aFFs(iInt);
const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
Standard_Integer aNbC = aVNC.Length();
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 TopTools_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 TopTools_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
TopTools_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 TopTools_ListOfShape *pLEIm = aMVIms.Seek(aEInv);
if (pLEIm)
{
TopTools_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 TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
TopTools_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 TopTools_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 <aFLE>,
// 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 <aME> 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;
}
//
TopTools_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
TopTools_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
TopTools_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;
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);
}
}
//
// Rebuild the map of edges to avoid, using the intersection results
TopTools_IndexedMapOfShape aMEAvoid;
// GF's data structure
const BOPDS_PDS& pDS = aGF.PDS();
aNbE = theEdgesToAvoid.Extent();
for (i = 1; i <= aNbE; ++i)
{
const TopoDS_Shape& aE = theEdgesToAvoid(i);
const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
// Only untouched and fully coinciding edges should be kept in the avoid map
Standard_Boolean bKeep = aLEIm.IsEmpty();
if (aLEIm.Extent() == 1 && aE.IsSame(aLEIm.First()))
{
const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(pDS->Index(aE));
if (aLPB.Extent() == 1)
{
const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock(aPB);
if (!aCB.IsNull())
{
const BOPDS_ListOfPaveBlock& aLPBCB = aCB->PaveBlocks();
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
for (; aItLPB.More(); aItLPB.Next())
{
if (pDS->PaveBlocks(aItLPB.Value()->OriginalEdge()).Extent() > 1)
break;
}
bKeep = !aItLPB.More();
}
}
}
if (bKeep)
{
// keep the original edge
aMEAvoid.Add(aE);
continue;
}
TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
for (; aItLEIm.More(); aItLEIm.Next())
{
const TopoDS_Shape& aEIm = aItLEIm.Value();
if (!aNewEdges.Contains(aEIm))
aMEAvoid.Add(aEIm);
}
}
theEdgesToAvoid = aMEAvoid;
}
//=======================================================================
//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 TopTools_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);
TopTools_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.Length();
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 TopTools_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 TopTools_ListOfShape* pLEIm = anIm.Seek(aE);
if (!pLEIm) {
// no splits, i.e. completely coincides with some edge from boundary
continue;
}
//
TopTools_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 <theType> 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);
}