mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
This patch turns off some not needed modes of fix in the called ShapeFix_Face algorithm. It stores pcurves on planes in the edges to avoid repeated computation of the same pcurves many times (it is done only when SafeInputMode is false). It avoids unnecessary replace/apply actions in the modification context. It removes the code that makes decomposition of surface of the face on several faces. The new command buildpcurvesonplane has been added, which builds and stores pcurves of edges on planar faces. This is useful for investigations how presence of pcurves on planes influence performance of algorithms. Make drawing of dimension line in snowflake test independent on the order of vertices in the result.
6424 lines
226 KiB
C++
6424 lines
226 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 <BOPCol_ListOfShape.hxx>
|
|
#include <BOPCol_DataMapOfShapeShape.hxx>
|
|
#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
|
|
|
|
#include <BOPTools.hxx>
|
|
#include <BOPTools_AlgoTools3D.hxx>
|
|
#include <BOPTools_AlgoTools.hxx>
|
|
#include <BOPTools_AlgoTools2D.hxx>
|
|
|
|
#include <IntTools_Context.hxx>
|
|
#include <IntTools_ShrunkRange.hxx>
|
|
|
|
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 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,
|
|
TopTools_DataMapOfShapeListOfShape& theDMVEFull,
|
|
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_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_ListOfShape& theLENew,
|
|
BOPCol_ListOfShape& theLA,
|
|
TopTools_DataMapOfShapeListOfShape& theDMEOr,
|
|
TopTools_DataMapOfShapeListOfShape& theMELF);
|
|
|
|
static
|
|
void IntersectEdges(const BOPCol_ListOfShape& theLA,
|
|
const TopTools_ListOfShape& theLE,
|
|
const TopTools_ListOfShape& theLENew,
|
|
const TopTools_MapOfShape& theMVBounds,
|
|
const TopTools_MapOfShape& theVertsToAvoid,
|
|
TopTools_MapOfShape& theMECheckExt,
|
|
TopTools_DataMapOfShapeListOfShape& theEImages,
|
|
TopTools_MapOfShape& theModifiedEdges,
|
|
TopTools_DataMapOfShapeListOfShape& theDMEOr,
|
|
TopTools_DataMapOfShapeListOfShape& theMELF,
|
|
TopTools_MapOfShape& theMENew,
|
|
TopoDS_Shape& theSplits);
|
|
|
|
static
|
|
void GetBounds(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,
|
|
TopTools_MapOfShape& theVertsToAvoid,
|
|
TopTools_MapOfShape& theMEInv);
|
|
|
|
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;
|
|
}
|
|
//
|
|
// build splits
|
|
TopTools_ListOfShape aLFImages;
|
|
BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages);
|
|
//
|
|
if (aMapEInv.Extent()) {
|
|
// check if all possible faces are built
|
|
TopTools_MapOfShape aMENInv;
|
|
Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
|
|
CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes);
|
|
//
|
|
// try to build splits using invalid edges
|
|
TopoDS_Compound aCE1;
|
|
aBB.MakeCompound(aCE1);
|
|
aBB.Add(aCE1, aCE);
|
|
for (i = 1; i <= aMapEInv.Extent(); ++i) {
|
|
aBB.Add(aCE1, aMapEInv(i));
|
|
}
|
|
//
|
|
TopTools_ListOfShape aLFImages1;
|
|
BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1);
|
|
//
|
|
// check if the rebuilding has added some new faces to the splits
|
|
for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();)
|
|
{
|
|
Standard_Boolean bAllInv = Standard_True;
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aE = aExpE.Current();
|
|
if (!aMapEInv.Contains(aE)) {
|
|
bAllInv = Standard_False;
|
|
if (!aMENInv.Contains(aE)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (!aExpE.More()) {
|
|
if (bAllInv) {
|
|
aMFToCheckInt.Add(aFIm);
|
|
}
|
|
aLFImages1.Remove(aItLFIm);
|
|
}
|
|
else {
|
|
aItLFIm.Next();
|
|
}
|
|
}
|
|
//
|
|
if (bArtificialCase) {
|
|
if (aLFImages.Extent() == aLFImages1.Extent()) {
|
|
bArtificialCase = Standard_False;
|
|
}
|
|
else {
|
|
aLFImages = aLFImages1;
|
|
}
|
|
}
|
|
//
|
|
if (bArtificialCase) {
|
|
TopTools_ListOfShape aLEInv;
|
|
// make the face invalid
|
|
theArtInvFaces.Bind(aF, aCE);
|
|
//
|
|
*pLFIm = aLFImages;
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aE = aExpE.Current();
|
|
if (aMapEInv.Contains(aE)) {
|
|
theInvEdges.Add(aE);
|
|
AppendToList(aLEInv, aE);
|
|
}
|
|
else {
|
|
theValidEdges.Add(aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aDMFLIE.Bind(aF, aLEInv);
|
|
aLFDone.Append(aF);
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
// find invalid edges
|
|
FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theOEImages,
|
|
theOEOrigins, theInvEdges, theValidEdges, aDMFLVE, aDMFLNE, aDMFLIE,
|
|
aDMFLVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex);
|
|
//
|
|
// save the new splits
|
|
if (!pLFIm) {
|
|
pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape()));
|
|
}
|
|
else {
|
|
pLFIm->Clear();
|
|
}
|
|
pLFIm->Append(aLFImages);
|
|
//
|
|
aLFDone.Append(aF);
|
|
}
|
|
//
|
|
if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
#ifdef OFFSET_DEBUG
|
|
// show invalid edges
|
|
TopoDS_Compound aCEInv1;
|
|
BRep_Builder().MakeCompound(aCEInv1);
|
|
Standard_Integer aNbEInv = theInvEdges.Extent();
|
|
for (i = 1; i <= aNbEInv; ++i) {
|
|
const TopoDS_Shape& aE = theInvEdges(i);
|
|
BRep_Builder().Add(aCEInv1, aE);
|
|
}
|
|
// show valid edges
|
|
TopoDS_Compound aCEVal1;
|
|
BRep_Builder().MakeCompound(aCEVal1);
|
|
aNbEInv = theValidEdges.Extent();
|
|
for (i = 1; i <= aNbEInv; ++i) {
|
|
const TopoDS_Shape& aE = theValidEdges(i);
|
|
BRep_Builder().Add(aCEVal1, aE);
|
|
}
|
|
// show inverted edges
|
|
TopoDS_Compound aCEInverted;
|
|
BRep_Builder().MakeCompound(aCEInverted);
|
|
TopTools_MapIteratorOfMapOfShape aItM(theInvertedEdges);
|
|
for (; aItM.More(); aItM.Next()) {
|
|
BRep_Builder().Add(aCEInverted, aItM.Value());
|
|
}
|
|
#endif
|
|
//
|
|
TopTools_ListOfShape anEmptyList;
|
|
// invalid faces inside the holes
|
|
TopTools_IndexedMapOfShape aMFInvInHole;
|
|
// all hole faces
|
|
TopoDS_Compound aFHoles;
|
|
aBB.MakeCompound(aFHoles);
|
|
// find invalid faces
|
|
// considering faces containing only invalid edges as invalid
|
|
aItLF.Initialize(aLFDone);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
|
|
TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
|
|
//
|
|
TopTools_ListOfShape aLFInv;
|
|
Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF);
|
|
if (bArtificialCase) {
|
|
aLFInv = aLFImages;
|
|
}
|
|
else {
|
|
// neutral edges
|
|
TopTools_ListOfShape* pLNE = aDMFLNE.ChangeSeek(aF);
|
|
if (!pLNE) {
|
|
pLNE = &anEmptyList;
|
|
}
|
|
// valid inverted edges
|
|
TopTools_ListOfShape* pLIVE = aDMFLVIE.ChangeSeek(aF);
|
|
if (!pLIVE) {
|
|
pLIVE = &anEmptyList;
|
|
}
|
|
//
|
|
// find faces inside holes wires
|
|
TopTools_MapOfShape aMFHoles;
|
|
const TopoDS_Face& aFOr = TopoDS::Face(theFacesOrigins.Find(aF));
|
|
FindFacesInsideHoleWires(aFOr, aF, aLFImages, theInvertedEdges,
|
|
aDMEOrLEIm, aMFHoles, theDMFNewHoles, aCtx);
|
|
//
|
|
TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles);
|
|
for (; aItMH.More(); aItMH.Next()) {
|
|
aBB.Add(aFHoles, aItMH.Value());
|
|
}
|
|
//
|
|
// find invalid faces
|
|
FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFLVE, aDMFLIE,
|
|
*pLNE, *pLIVE, theInvertedEdges, aMEdgeInvalidByVertex,
|
|
aMFHoles, aMFInvInHole, aLFInv);
|
|
}
|
|
//
|
|
if (aLFInv.Extent()) {
|
|
if (theAlreadyInvFaces.IsBound(aF)) {
|
|
if (theAlreadyInvFaces.Find(aF) > 2) {
|
|
if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) {
|
|
aLFImages.Clear();
|
|
}
|
|
//
|
|
aLFInv.Clear();
|
|
}
|
|
}
|
|
theInvFaces.Add(aF, aLFInv);
|
|
}
|
|
}
|
|
//
|
|
if (theInvFaces.IsEmpty()) {
|
|
theInvEdges.Clear();
|
|
return;
|
|
}
|
|
//
|
|
#ifdef OFFSET_DEBUG
|
|
// show invalid faces
|
|
TopoDS_Compound aCFInv1;
|
|
BRep_Builder().MakeCompound(aCFInv1);
|
|
Standard_Integer aNbFInv = theInvFaces.Extent();
|
|
for (i = 1; i <= aNbFInv; ++i) {
|
|
const TopTools_ListOfShape& aLFInv = theInvFaces(i);
|
|
TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
|
|
for (; aItLFInv.More(); aItLFInv.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFInv.Value();
|
|
BRep_Builder().Add(aCFInv1, aFIm);
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
TopTools_IndexedMapOfShape aMERemoved;
|
|
// remove invalid splits of faces using inverted edges
|
|
RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins,
|
|
theInvFaces, theFImages, aMERemoved);
|
|
if (theInvFaces.IsEmpty()) {
|
|
theInvEdges.Clear();
|
|
return;
|
|
}
|
|
//
|
|
// remove invalid splits from valid splits
|
|
RemoveInvalidSplitsFromValid(theInvFaces, theArtInvFaces, theInvertedEdges, theFImages);
|
|
//
|
|
// remove inside faces
|
|
TopTools_IndexedMapOfShape aMEInside;
|
|
RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges,
|
|
aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs,
|
|
aMERemoved, aMEInside, theSolids);
|
|
//
|
|
// make compound of valid splits
|
|
TopoDS_Compound aCFIm;
|
|
aBB.MakeCompound(aCFIm);
|
|
//
|
|
aNb = theFImages.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopTools_ListOfShape& aLFIm = theFImages(i);
|
|
aItLF.Initialize(aLFIm);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLF.Value();
|
|
aBB.Add(aCFIm, aFIm);
|
|
}
|
|
}
|
|
//
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
|
|
TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
|
|
//
|
|
// filter maps of images and origins
|
|
FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
|
|
//
|
|
// filter invalid faces
|
|
FilterInvalidFaces(theFImages, aDMEF, aMEInside, theInvFaces, theArtInvFaces);
|
|
aNb = theInvFaces.Extent();
|
|
if (!aNb) {
|
|
theInvEdges.Clear();
|
|
return;
|
|
}
|
|
//
|
|
#ifdef OFFSET_DEBUG
|
|
// show invalid faces
|
|
TopoDS_Compound aCFInv;
|
|
BRep_Builder().MakeCompound(aCFInv);
|
|
aNbFInv = theInvFaces.Extent();
|
|
for (i = 1; i <= aNbFInv; ++i) {
|
|
const TopTools_ListOfShape& aLFInv = theInvFaces(i);
|
|
TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
|
|
for (; aItLFInv.More(); aItLFInv.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFInv.Value();
|
|
BRep_Builder().Add(aCFInv, aFIm);
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// filter invalid edges
|
|
FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFLIE, aMERemoved, theInvEdges);
|
|
//
|
|
#ifdef OFFSET_DEBUG
|
|
// show invalid edges
|
|
TopoDS_Compound aCEInv;
|
|
BRep_Builder().MakeCompound(aCEInv);
|
|
aNbEInv = theInvEdges.Extent();
|
|
for (i = 1; i <= aNbEInv; ++i) {
|
|
const TopoDS_Shape& aE = theInvEdges(i);
|
|
BRep_Builder().Add(aCEInv, aE);
|
|
}
|
|
#endif
|
|
//
|
|
theLastInvEdges.Clear();
|
|
aNb = theInvEdges.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aE = theInvEdges(i);
|
|
theEdgesToAvoid.Add(aE);
|
|
theLastInvEdges.Add(aE);
|
|
}
|
|
//
|
|
aNb = theInvFaces.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theInvFaces.FindKey(i);
|
|
if (theAlreadyInvFaces.IsBound(aF)) {
|
|
theAlreadyInvFaces.ChangeFind(aF)++;
|
|
}
|
|
else {
|
|
theAlreadyInvFaces.Bind(aF, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IntersectTrimmedEdges
|
|
//purpose : Intersection of the trimmed edges among themselves
|
|
//=======================================================================
|
|
void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
|
|
const Handle(BRepAlgo_AsDes)& theAsDes,
|
|
TopTools_DataMapOfShapeListOfShape& theOEImages,
|
|
TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
|
|
Handle(IntTools_Context)& theCtx,
|
|
TopTools_MapOfShape& theNewEdges,
|
|
TopTools_DataMapOfShapeShape& theETrimEInf)
|
|
{
|
|
if (theLF.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// get edges to intersect from descendants of the offset faces
|
|
BOPCol_ListOfShape aLS;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLF(theLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
|
|
//
|
|
const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
|
|
TopTools_ListIteratorOfListOfShape aItLE(aLE);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
|
|
//
|
|
if (ProcessMicroEdge(aE, theCtx)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (theNewEdges.Add(aE)) {
|
|
aLS.Append(aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aLS.Extent() < 2) {
|
|
// nothing to intersect
|
|
return;
|
|
}
|
|
//
|
|
// perform intersection of the edges
|
|
BOPAlgo_Builder aGFE;
|
|
aGFE.SetArguments(aLS);
|
|
aGFE.Perform();
|
|
if (aGFE.HasErrors()) {
|
|
return;
|
|
}
|
|
//
|
|
TopTools_ListOfShape aLA;
|
|
// fill map with edges images
|
|
BOPCol_ListIteratorOfListOfShape aIt(aLS);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
|
|
if (aLEIm.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
aLA.Append(aE);
|
|
// save images
|
|
theOEImages.Bind(aE, aLEIm);
|
|
// save origins
|
|
TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLE.Value();
|
|
TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm);
|
|
if (!pLEOr) {
|
|
pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLEOr, aE);
|
|
}
|
|
}
|
|
//
|
|
UpdateOrigins(aLA, theEdgesOrigins, aGFE);
|
|
UpdateIntersectedEdges(aLA, theETrimEInf, aGFE);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetEdges
|
|
//purpose : Getting edges from AsDes map to build the splits of faces
|
|
//=======================================================================
|
|
Standard_Boolean GetEdges(const TopoDS_Face& theFace,
|
|
const Handle(BRepAlgo_AsDes)& theAsDes,
|
|
const TopTools_DataMapOfShapeListOfShape& theEImages,
|
|
const TopTools_MapOfShape& theLastInvEdges,
|
|
const TopTools_IndexedMapOfShape& theInvEdges,
|
|
Handle(IntTools_Context)& theCtx,
|
|
const TopTools_MapOfShape& theModifiedEdges,
|
|
TopoDS_Shape& theEdges,
|
|
TopTools_IndexedMapOfShape& theInv)
|
|
{
|
|
// get boundary edges
|
|
TopTools_MapOfShape aMFBounds;
|
|
TopExp_Explorer aExp(theFace, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
|
|
if (!pLEIm) {
|
|
aMFBounds.Add(aE);
|
|
}
|
|
else {
|
|
TopTools_ListIteratorOfListOfShape aItLE(*pLEIm);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLE.Value();
|
|
aMFBounds.Add(aEIm);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
BRep_Builder aBB;
|
|
Standard_Boolean bFound(Standard_False), bUpdate(Standard_False);
|
|
// the resulting edges
|
|
TopoDS_Compound anEdges;
|
|
aBB.MakeCompound(anEdges);
|
|
//
|
|
// 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 (theInvEdges.Contains(aEIm)) {
|
|
theInv.Add(aEIm);
|
|
if (!bUpdate) {
|
|
bUpdate = theLastInvEdges.Contains(aEIm);
|
|
}
|
|
continue;
|
|
}
|
|
// check for micro edge
|
|
if (ProcessMicroEdge(aEIm, theCtx)) {
|
|
continue;
|
|
}
|
|
//
|
|
aBB.Add(anEdges, aEIm);
|
|
if (!bFound) {
|
|
bFound = !aMFBounds.Contains(aEIm);
|
|
}
|
|
//
|
|
if (!bUpdate) {
|
|
bUpdate = theModifiedEdges.Contains(aEIm);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (theInvEdges.Contains(aE)) {
|
|
theInv.Add(aE);
|
|
if (!bUpdate) {
|
|
bUpdate = theLastInvEdges.Contains(aE);
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
if (ProcessMicroEdge(aE, theCtx)) {
|
|
continue;
|
|
}
|
|
aBB.Add(anEdges, aE);
|
|
if (!bFound) {
|
|
bFound = !aMFBounds.Contains(aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
theEdges = anEdges;
|
|
return bFound && bUpdate;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : BuildSplitsOfFace
|
|
//purpose : Building the splits of offset face
|
|
//=======================================================================
|
|
void BuildSplitsOfFace(const TopoDS_Face& theFace,
|
|
const TopoDS_Shape& theEdges,
|
|
TopTools_DataMapOfShapeShape& theFacesOrigins,
|
|
TopTools_ListOfShape& theLFImages)
|
|
{
|
|
theLFImages.Clear();
|
|
//
|
|
// take edges to split the face
|
|
BOPCol_ListOfShape aLE;
|
|
TopExp_Explorer aExp(theEdges, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
|
|
aE.Orientation(TopAbs_FORWARD);
|
|
aLE.Append(aE);
|
|
aE.Orientation(TopAbs_REVERSED);
|
|
aLE.Append(aE);
|
|
}
|
|
//
|
|
TopoDS_Face aFF = theFace;
|
|
TopAbs_Orientation anOr = theFace.Orientation();
|
|
aFF.Orientation(TopAbs_FORWARD);
|
|
//
|
|
// build pcurves for edges on the face
|
|
BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
|
|
//
|
|
// build splits of faces
|
|
BOPAlgo_BuilderFace aBF;
|
|
aBF.SetFace(aFF);
|
|
aBF.SetShapes(aLE);
|
|
aBF.Perform();
|
|
//
|
|
const BOPCol_ListOfShape& aLFSp = aBF.Areas();
|
|
BOPCol_ListIteratorOfListOfShape aItLF(aLFSp);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
TopoDS_Shape& aFSp = aItLF.ChangeValue();
|
|
aFSp.Orientation(anOr);
|
|
theLFImages.Append(aFSp);
|
|
//
|
|
theFacesOrigins.Bind(aFSp, theFace);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : BuildSplitsOfFace
|
|
//purpose : Building the splits of offset face
|
|
//=======================================================================
|
|
void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
|
|
const TopoDS_Shape& theEdges,
|
|
TopTools_ListOfShape& theLFImages)
|
|
{
|
|
BOPAlgo_Builder aGF;
|
|
//
|
|
aGF.AddArgument(theFace);
|
|
aGF.AddArgument(theEdges);
|
|
aGF.Perform();
|
|
if (aGF.HasErrors()) {
|
|
return;
|
|
}
|
|
//
|
|
// splits of the offset shape
|
|
theLFImages = aGF.Modified(theFace);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CheckIfArtificial
|
|
//purpose : Checks if the face is artificially invalid
|
|
//=======================================================================
|
|
Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
|
|
const TopTools_ListOfShape& theLFImages,
|
|
const TopoDS_Shape& theCE,
|
|
const TopTools_IndexedMapOfShape& theMapEInv,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEImages,
|
|
TopTools_MapOfShape& theMENInv,
|
|
Handle(BRepAlgo_AsDes)& theAsDes)
|
|
{
|
|
// all boundary edges should be used
|
|
TopTools_IndexedMapOfShape aMEUsed;
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed);
|
|
TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed);
|
|
}
|
|
//
|
|
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
|
|
TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
|
|
//
|
|
Standard_Integer i, aNb = theMapEInv.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aEInv = theMapEInv(i);
|
|
TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX);
|
|
for (; aExpV.More(); aExpV.Next()) {
|
|
const TopoDS_Shape& aVEInv = aExpV.Current();
|
|
const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv);
|
|
if (pLENInv) {
|
|
TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv);
|
|
for (; aItLEInv.More(); aItLEInv.Next()) {
|
|
const TopoDS_Shape& aENInv = aItLEInv.Value();
|
|
if (!aMEUsed.Contains(aENInv)) {
|
|
theMENInv.Add(aENInv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (theMENInv.IsEmpty()) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
TopTools_IndexedMapOfShape aMEFound;
|
|
TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound);
|
|
//
|
|
const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF);
|
|
TopTools_ListIteratorOfListOfShape aItLE(aLE);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
|
|
//
|
|
if (theOEImages.IsBound(aE)) {
|
|
Standard_Boolean bChecked = Standard_False;
|
|
const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE);
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
|
|
if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) {
|
|
continue;
|
|
}
|
|
//
|
|
bChecked = Standard_True;
|
|
if (aMEUsed.Contains(aEIm)) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (bChecked && !aItLEIm.More()) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return aItLE.More();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindInvalidEdges
|
|
//purpose : Looking for the invalid edges
|
|
//=======================================================================
|
|
void FindInvalidEdges(const TopoDS_Face& theF,
|
|
const TopTools_ListOfShape& theLFImages,
|
|
const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
|
|
const TopTools_DataMapOfShapeShape& theFacesOrigins,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEImages,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
TopTools_IndexedMapOfShape& theInvEdges,
|
|
TopTools_IndexedMapOfShape& theValidEdges,
|
|
TopTools_DataMapOfShapeListOfShape& theDMFLVE,
|
|
TopTools_DataMapOfShapeListOfShape& theDMFLNE,
|
|
TopTools_DataMapOfShapeListOfShape& theDMFLIE,
|
|
TopTools_DataMapOfShapeListOfShape& theDMFLVIE,
|
|
TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
|
|
TopTools_MapOfShape& theMEInverted,
|
|
TopTools_MapOfShape& theEdgesInvalidByVertex)
|
|
{
|
|
// Edge is considered as invalid in the following cases:
|
|
// 1. Its orientation on the face has changed comparing to the originals edge and face;
|
|
// 2. The vertices of the edge have changed places comparing to the originals edge and face.
|
|
//
|
|
// The edges created from vertices, i.e. as intersection between two faces connected only
|
|
// by VERTEX, will also be checked on validity. For these edges the correct orientation will
|
|
// be defined by the edges on the original face adjacent to the connection vertex
|
|
|
|
// original face
|
|
const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
|
|
// invalid edges
|
|
TopTools_IndexedMapOfShape aMEInv;
|
|
// valid edges
|
|
TopTools_MapOfShape aMEVal;
|
|
// internal edges
|
|
TopTools_MapOfShape aMEInt;
|
|
//
|
|
// maps for checking the inverted edges
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
|
|
TopTools_IndexedMapOfShape aMEdges;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
|
|
//
|
|
TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
// keep all edges
|
|
aMEdges.Add(aE);
|
|
//
|
|
// keep connection from edges to faces
|
|
TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE);
|
|
if (!pLF) {
|
|
pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape()));
|
|
}
|
|
AppendToList(*pLF, aFIm);
|
|
//
|
|
// keep connection from vertices to edges
|
|
TopoDS_Iterator aItV(aE);
|
|
for (; aItV.More(); aItV.Next()) {
|
|
const TopoDS_Shape& aV = aItV.Value();
|
|
//
|
|
TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV);
|
|
if (!pLE) {
|
|
pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape()));
|
|
}
|
|
AppendToList(*pLE, aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// the map will be used to find the edges on the original face
|
|
// adjacent to the same vertex. It will be filled at first necessity;
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
|
|
//
|
|
aItLF.Initialize(theLFImages);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
|
|
//
|
|
// valid edges for this split
|
|
TopTools_ListOfShape aLVE;
|
|
// invalid edges for this split
|
|
TopTools_ListOfShape aLIE;
|
|
//
|
|
TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
|
|
//
|
|
if (aEIm.Orientation() == TopAbs_INTERNAL) {
|
|
aMEInt.Add(aEIm);
|
|
continue;
|
|
}
|
|
//
|
|
if (!theEdgesOrigins.IsBound(aEIm)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm);
|
|
if (aLEOr.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Integer aNbVOr = 0;
|
|
TopTools_ListIteratorOfListOfShape aItLEO(aLEOr);
|
|
for (; aItLEO.More(); aItLEO.Next()) {
|
|
if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) {
|
|
++aNbVOr;
|
|
}
|
|
}
|
|
//
|
|
TopTools_MapOfShape aME, aMV;
|
|
Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
|
|
Standard_Integer aNbP = NbPoints(aEIm);
|
|
Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
|
|
(aNbVOr == 1 &&
|
|
aDMEF.FindFromKey(aEIm).Extent() == 1 &&
|
|
!theOEOrigins.IsBound(aEIm));
|
|
//
|
|
aItLEO.Initialize(aLEOr);
|
|
for (; aItLEO.More(); aItLEO.Next()) {
|
|
const TopoDS_Shape& aSOr = aItLEO.Value();
|
|
Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
|
|
//
|
|
TopoDS_Shape aEOrF;
|
|
if (bVertex) {
|
|
// for some cases it is impossible to check the validity of the edge
|
|
if (!bUseVertex) {
|
|
continue;
|
|
}
|
|
// find edges on the original face adjacent to this vertex
|
|
if (aDMVEFOr.IsEmpty()) {
|
|
// fill the map
|
|
TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
|
|
}
|
|
//
|
|
TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr);
|
|
if (pLEFOr) {
|
|
TopoDS_Compound aCEOr;
|
|
BRep_Builder().MakeCompound(aCEOr);
|
|
TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
|
|
for (; aItLEFOr.More(); aItLEFOr.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLEFOr.Value();
|
|
BRep_Builder().Add(aCEOr, aEOr);
|
|
}
|
|
aEOrF = aCEOr;
|
|
}
|
|
}
|
|
else {
|
|
FindShape(aSOr, aFOr, aEOrF);
|
|
//
|
|
TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr);
|
|
if (!pLEIm) {
|
|
pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLEIm, aEIm);
|
|
}
|
|
//
|
|
if (aEOrF.IsNull()) {
|
|
// the edge has not been found
|
|
continue;
|
|
}
|
|
//
|
|
// Check orientations of the image edge and original edge.
|
|
// In case the 3d curves are having the same direction the orientations
|
|
// must be the same. Otherwise the orientations should also be different.
|
|
//
|
|
// get average tangent vector for each curve taking into account
|
|
// the orientations of the edges, i.e. the edge is reversed
|
|
// the vector is reversed as well
|
|
gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP);
|
|
gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP);
|
|
//
|
|
aVSum1.Normalize();
|
|
aVSum2.Normalize();
|
|
//
|
|
Standard_Real aCos = aVSum1.Dot(aVSum2);
|
|
if (!bVertex) {
|
|
if (Abs(aCos) < 0.9999) {
|
|
continue;
|
|
}
|
|
//
|
|
aME.Add(aEOrF);
|
|
TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aV = aExpE.Current();
|
|
aMV.Add(aV);
|
|
}
|
|
}
|
|
//
|
|
if (aCos < Precision::Confusion()) {
|
|
bInvalid = Standard_True;
|
|
if (bVertex) {
|
|
theEdgesInvalidByVertex.Add(aEIm);
|
|
}
|
|
}
|
|
bChecked = Standard_True;
|
|
}
|
|
//
|
|
if (!bChecked) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
|
|
if ((aNbE > 1) && (aNbV == 2*aNbE)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (bInvalid) {
|
|
theInvEdges.Add(aEIm);
|
|
aLIE.Append(aEIm);
|
|
aMEInv.Add(aEIm);
|
|
continue;
|
|
}
|
|
//
|
|
// check if the edge has been inverted
|
|
Standard_Boolean bInverted = !aNbE ? Standard_False :
|
|
CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
|
|
theEdgesOrigins, aDMVE, aMEdges, theMEInverted);
|
|
//
|
|
if (!bInverted || !aNbVOr) {
|
|
theValidEdges.Add(aEIm);
|
|
aLVE.Append(aEIm);
|
|
aMEVal.Add(aEIm);
|
|
}
|
|
}
|
|
//
|
|
// valid edges
|
|
if (aLVE.Extent()) {
|
|
theDMFLVE.Bind(aFIm, aLVE);
|
|
}
|
|
//
|
|
// invalid edges
|
|
if (aLIE.Extent()) {
|
|
theDMFLIE.Bind(aFIm, aLIE);
|
|
}
|
|
}
|
|
//
|
|
// process invalid edges:
|
|
// check for the inverted edges
|
|
TopTools_ListOfShape aLVIE;
|
|
// fill neutral edges
|
|
TopTools_ListOfShape aLNE;
|
|
//
|
|
Standard_Integer i, aNbEInv = aMEInv.Extent();
|
|
for (i = 1; i <= aNbEInv; ++i) {
|
|
const TopoDS_Shape& aEIm = aMEInv(i);
|
|
//
|
|
// neutral edges - on the splits of the same offset face
|
|
// it is valid for one split and invalid for other
|
|
if (aMEVal.Contains(aEIm)) {
|
|
aLNE.Append(aEIm);
|
|
continue;
|
|
}
|
|
//
|
|
// the inverted images of the origins of invalid edges should also be invalid
|
|
if (!theMEInverted.Contains(aEIm)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm);
|
|
if (!pLOEOr) {
|
|
continue;
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr);
|
|
for (; aItLOEOr.More(); aItLOEOr.Next()) {
|
|
const TopoDS_Shape& aOEOr = aItLOEOr.Value();
|
|
const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1);
|
|
for (; aItLEIm1.More(); aItLEIm1.Next()) {
|
|
const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
|
|
if (aMEdges.Contains(aEIm1) &&
|
|
!aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) &&
|
|
theMEInverted.Contains(aEIm1)) {
|
|
theInvEdges.Add(aEIm1);
|
|
aLVIE.Append(aEIm1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aLNE.Extent()) {
|
|
theDMFLNE.Bind(theF, aLNE);
|
|
}
|
|
//
|
|
if (aLVIE.Extent()) {
|
|
theDMFLVIE.Bind(theF, aLVIE);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindInvalidFaces
|
|
//purpose : Looking for the invalid faces by analyzing their invalid edges
|
|
//=======================================================================
|
|
void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
|
|
const TopTools_IndexedMapOfShape& theInvEdges,
|
|
const TopTools_IndexedMapOfShape& theValidEdges,
|
|
const TopTools_DataMapOfShapeListOfShape& theDMFLVE,
|
|
const TopTools_DataMapOfShapeListOfShape& theDMFLIE,
|
|
const TopTools_ListOfShape& theLENeutral,
|
|
const TopTools_ListOfShape& theLEValInverted,
|
|
const TopTools_MapOfShape& theMEInverted,
|
|
const TopTools_MapOfShape& theEdgesInvalidByVertex,
|
|
const TopTools_MapOfShape& theMFHoles,
|
|
TopTools_IndexedMapOfShape& theMFInvInHole,
|
|
TopTools_ListOfShape& theInvFaces)
|
|
{
|
|
// The face should be considered as invalid in the following cases:
|
|
// 1. It has been reverted, i.e. at least two not connected edges
|
|
// have changed orientation (i.e. invalid). In this case all edges,
|
|
// should be invalid for that face, because edges have also been reverted;
|
|
// 2. All checked edges of the face are invalid for this face;
|
|
// The face should be removed from the splits in the following cases:
|
|
// 1. All checked edges of the face are invalid for this one, but valid for
|
|
// some other face in this list of splits.
|
|
// The face will be kept in the following cases:
|
|
// 1. Some of the edges are valid for this face.
|
|
Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
|
|
Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral;
|
|
Standard_Integer i, aNbChecked;
|
|
//
|
|
// neutral edges
|
|
TopTools_MapOfShape aMEN;
|
|
for (TopTools_ListIteratorOfListOfShape aItLE(theLENeutral); aItLE.More(); aItLE.Next())
|
|
{
|
|
aMEN.Add(aItLE.Value());
|
|
}
|
|
//
|
|
// valid inverted edges
|
|
TopTools_MapOfShape aMEValInverted;
|
|
for (TopTools_ListIteratorOfListOfShape aItLE(theLEValInverted); aItLE.More(); aItLE.Next())
|
|
{
|
|
aMEValInverted.Add(aItLE.Value());
|
|
}
|
|
//
|
|
Standard_Boolean bCheckInverted = (theLFImages.Extent() == 1);
|
|
//
|
|
// neutral edges to remove
|
|
TopTools_IndexedMapOfShape aMENRem;
|
|
//
|
|
// faces for post treat
|
|
TopTools_ListOfShape aLFPT;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
|
|
for (; aItLF.More(); ) {
|
|
const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
|
|
//
|
|
// valid edges for this split
|
|
TopTools_MapOfShape aMVE;
|
|
// invalid edges for this split
|
|
TopTools_MapOfShape aMIE;
|
|
//
|
|
for (i = 0; i < 2; ++i) {
|
|
TopTools_MapOfShape& aME = !i ? aMVE : aMIE;
|
|
const TopTools_ListOfShape* pLE = !i ? theDMFLVE.Seek(aFIm) : theDMFLIE.Seek(aFIm);
|
|
if (pLE) {
|
|
TopTools_ListIteratorOfListOfShape aItLE(*pLE);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aE = aItLE.Value();
|
|
aME.Add(aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
bHasValid = Standard_False;
|
|
bAllValid = Standard_True;
|
|
bAllInvalid = Standard_True;
|
|
bHasReallyInvalid = Standard_False;
|
|
bAllInvNeutral = Standard_True;
|
|
aNbChecked = 0;
|
|
//
|
|
const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
|
|
TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aEIm = aExp.Current();
|
|
//
|
|
bValid = theValidEdges.Contains(aEIm);
|
|
bInvalid = theInvEdges.Contains(aEIm);
|
|
//
|
|
if (!bValid && !bInvalid) {
|
|
// edge has not been checked for some reason
|
|
continue;
|
|
}
|
|
//
|
|
++aNbChecked;
|
|
//
|
|
bInvalidLoc = aMIE.Contains(aEIm);
|
|
bHasReallyInvalid = bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
|
|
if (bHasReallyInvalid) {
|
|
break;
|
|
}
|
|
//
|
|
bNeutral = aMEN.Contains(aEIm);
|
|
bValidLoc = aMVE.Contains(aEIm);
|
|
//
|
|
if (!bInvalid && bCheckInverted) {
|
|
bInvalid = theMEInverted.Contains(aEIm);
|
|
}
|
|
//
|
|
if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) {
|
|
bHasValid = Standard_True;
|
|
}
|
|
//
|
|
bAllValid = bAllValid && bValidLoc;
|
|
bAllInvalid = bAllInvalid && bInvalid;
|
|
bAllInvNeutral = bAllInvNeutral && bAllInvalid && bNeutral;
|
|
}
|
|
//
|
|
if (!aNbChecked) {
|
|
aItLF.Next();
|
|
continue;
|
|
}
|
|
//
|
|
if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) {
|
|
// remove edges from neutral
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
|
|
// remove face
|
|
theLFImages.Remove(aItLF);
|
|
continue;
|
|
}
|
|
//
|
|
if (bHasReallyInvalid || (bAllInvalid &&
|
|
!(bHasValid || bAllValid) &&
|
|
!(bAllInvNeutral && (aNbChecked == 1)))) {
|
|
theInvFaces.Append(aFIm);
|
|
if (theMFHoles.Contains(aFIm)) {
|
|
theMFInvInHole.Add(aFIm);
|
|
}
|
|
aItLF.Next();
|
|
continue;
|
|
}
|
|
//
|
|
if (theMFHoles.Contains(aFIm)) {
|
|
// remove edges from neutral
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
|
|
// remove face
|
|
theLFImages.Remove(aItLF);
|
|
continue;
|
|
}
|
|
//
|
|
if (!bAllInvNeutral) {
|
|
aLFPT.Append(aFIm);
|
|
}
|
|
else {
|
|
// remove edges from neutral
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
|
|
}
|
|
aItLF.Next();
|
|
}
|
|
//
|
|
if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer aNb = aMENRem.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
aMEN.Remove(aMENRem(i));
|
|
}
|
|
//
|
|
// check the splits once more
|
|
aItLF.Initialize(aLFPT);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
|
|
//
|
|
// valid edges for this split
|
|
TopTools_MapOfShape aMVE;
|
|
const TopTools_ListOfShape* pLVE = theDMFLVE.Seek(aFIm);
|
|
if (pLVE) {
|
|
TopTools_ListIteratorOfListOfShape aItLE(*pLVE);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aE = aItLE.Value();
|
|
aMVE.Add(aE);
|
|
}
|
|
}
|
|
//
|
|
bHasValid = Standard_False;
|
|
bAllValid = Standard_True;
|
|
bAllInvalid = Standard_True;
|
|
//
|
|
const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
|
|
TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aEIm = aExp.Current();
|
|
//
|
|
bValid = theValidEdges.Contains(aEIm);
|
|
bInvalid = theInvEdges.Contains(aEIm);
|
|
bNeutral = aMEN.Contains(aEIm);
|
|
bValidLoc = aMVE.Contains(aEIm);
|
|
//
|
|
if (!bInvalid && bCheckInverted) {
|
|
bInvalid = theMEInverted.Contains(aEIm);
|
|
}
|
|
//
|
|
if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) {
|
|
bHasValid = Standard_True;
|
|
}
|
|
//
|
|
bAllValid = bAllValid && bValidLoc;
|
|
bAllInvalid = bAllInvalid && bInvalid;
|
|
}
|
|
//
|
|
if (bAllInvalid && !bHasValid && !bAllValid) {
|
|
theInvFaces.Append(aFIm);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindFacesInsideHoleWires
|
|
//purpose : Find faces inside holes wires from the original face
|
|
//=======================================================================
|
|
void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
|
|
const TopoDS_Face& theFOffset,
|
|
const TopTools_ListOfShape& theLFImages,
|
|
const TopTools_MapOfShape& theInvertedEdges,
|
|
const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
|
|
TopTools_MapOfShape& theMFHoles,
|
|
TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
|
|
Handle(IntTools_Context)& theContext)
|
|
{
|
|
if (theLFImages.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// find all hole wires in the original face
|
|
TopTools_ListOfShape aLHoleWires;
|
|
const TopoDS_Wire& anOuterWire = BRepTools::OuterWire(theFOrigin);
|
|
TopExp_Explorer aExpW(theFOrigin, TopAbs_WIRE);
|
|
for (; aExpW.More(); aExpW.Next()) {
|
|
const TopoDS_Wire& aHoleWire = TopoDS::Wire(aExpW.Current());
|
|
if (!aHoleWire.IsSame(anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL) {
|
|
aLHoleWires.Append(aHoleWire);
|
|
}
|
|
}
|
|
//
|
|
if (aLHoleWires.IsEmpty()) {
|
|
// no holes in the face
|
|
return;
|
|
}
|
|
//
|
|
TopTools_ListOfShape *pLFNewHoles = theDMFNewHoles.ChangeSeek(theFOrigin);
|
|
//
|
|
if (!pLFNewHoles) {
|
|
pLFNewHoles = theDMFNewHoles.Bound(theFOrigin, TopTools_ListOfShape());
|
|
}
|
|
if (pLFNewHoles->IsEmpty()) {
|
|
//
|
|
// find the faces representing holes in the images of the faces:
|
|
// 1. for each original hole wire try to build its image
|
|
// 2. build the new planar face from the images
|
|
//
|
|
// map vertices and edges of the splits
|
|
TopTools_IndexedMapOfShape aMESplits;
|
|
TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
TopExp::MapShapes(aItLF.Value(), TopAbs_EDGE, aMESplits);
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLW(aLHoleWires);
|
|
for (; aItLW.More(); aItLW.Next()) {
|
|
const TopoDS_Wire& aHoleWire = TopoDS::Wire(aItLW.Value());
|
|
// find images of all edges of the original wire
|
|
TopTools_IndexedMapOfShape aMEImWire;
|
|
TopoDS_Iterator aItE(aHoleWire);
|
|
for (; aItE.More(); aItE.Next()) {
|
|
const TopoDS_Shape& aEOr = aItE.Value();
|
|
const TopTools_ListOfShape *pLEIm = theDMEOrLEIm.Seek(aEOr);
|
|
if (!pLEIm || pLEIm->IsEmpty()) {
|
|
continue;
|
|
}
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLEIm.Value();
|
|
if (aMESplits.Contains(aEIm)) {
|
|
aMEImWire.Add(aEIm);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMEImWire.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
// build new planar face using these edges
|
|
BOPCol_ListOfShape aLE;
|
|
Standard_Integer i, aNbE = aMEImWire.Extent();
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
aLE.Append(aMEImWire(i).Oriented(TopAbs_FORWARD));
|
|
aLE.Append(aMEImWire(i).Oriented(TopAbs_REVERSED));
|
|
}
|
|
//
|
|
BOPAlgo_BuilderFace aBF;
|
|
aBF.SetFace(TopoDS::Face(theFOffset.Oriented(TopAbs_FORWARD)));
|
|
aBF.SetShapes(aLE);
|
|
aBF.Perform();
|
|
//
|
|
const BOPCol_ListOfShape& aLFNew = aBF.Areas();
|
|
if (aLFNew.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
// check if outer edges in the new faces are not inverted
|
|
// because the inverted edges mean that the hole has been
|
|
// filled during offset and there will be no faces to remove
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew;
|
|
TopTools_ListIteratorOfListOfShape aItLFNew(aLFNew);
|
|
for (; aItLFNew.More(); aItLFNew.Next()) {
|
|
TopExp::MapShapesAndAncestors(aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew);
|
|
}
|
|
//
|
|
aNbE = aDMEFNew.Extent();
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
if (aDMEFNew(i).Extent() == 1) {
|
|
const TopoDS_Shape& aE = aDMEFNew.FindKey(i);
|
|
if (theInvertedEdges.Contains(aE)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (i <= aNbE) {
|
|
continue;
|
|
}
|
|
//
|
|
aItLFNew.Initialize(aLFNew);
|
|
for (; aItLFNew.More(); aItLFNew.Next()) {
|
|
pLFNewHoles->Append(aItLFNew.Value());
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// among the splits of the offset face find those that are
|
|
// located inside the hole faces
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
|
|
//
|
|
// get the point inside the face and classify it relatively hole faces
|
|
gp_Pnt aP3D;
|
|
gp_Pnt2d aP2D;
|
|
Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(aFIm, aP3D, aP2D, theContext);
|
|
if (iErr) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Real aTol = BRep_Tool::Tolerance(aFIm);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLFNew(*pLFNewHoles);
|
|
for (; aItLFNew.More(); aItLFNew.Next()) {
|
|
const TopoDS_Face& aFNew = TopoDS::Face(aItLFNew.Value());
|
|
if (theContext->IsValidPointForFace(aP3D, aFNew, aTol)) {
|
|
// the face is classified as IN
|
|
theMFHoles.Add(aFIm);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetAverageTangent
|
|
//purpose : Computes average tangent vector along the curve
|
|
//=======================================================================
|
|
gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
|
|
const Standard_Integer theNbP)
|
|
{
|
|
gp_Vec aVA;
|
|
TopExp_Explorer aExp(theS, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
|
|
//
|
|
Standard_Real aT1, aT2;
|
|
const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
|
|
//
|
|
gp_Pnt aP;
|
|
gp_Vec aV, aVSum;
|
|
Standard_Real aT = aT1;
|
|
Standard_Real aDt = (aT2 - aT1) / theNbP;
|
|
while (aT <= aT2) {
|
|
aC->D1(aT, aP, aV);
|
|
aVSum += aV.Normalized();
|
|
aT += aDt;
|
|
}
|
|
//
|
|
if (aE.Orientation() == TopAbs_REVERSED) {
|
|
aVSum.Reverse();
|
|
}
|
|
//
|
|
aVA += aVSum;
|
|
}
|
|
return aVA;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CheckInverted
|
|
//purpose : Checks if the edge has been inverted
|
|
//=======================================================================
|
|
Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
|
|
const TopoDS_Face& theFOr,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEImages,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
|
|
const TopTools_IndexedMapOfShape& theMEdges,
|
|
TopTools_MapOfShape& theMEInverted)
|
|
{
|
|
// It is necessary to compare the direction from first vertex
|
|
// to the last vertex on the original edge with the
|
|
// same direction on the new edge. If the directions
|
|
// will be different - the edge has been inverted.
|
|
//
|
|
TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
|
|
TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
|
|
//
|
|
Standard_Integer i;
|
|
// find vertices of the offset shape
|
|
TopExp::Vertices(theEIm, aVI1, aVI2);
|
|
//
|
|
// find images
|
|
TopTools_ListOfShape aLEImages;
|
|
if (theOEOrigins.IsBound(theEIm)) {
|
|
TopoDS_Wire anImages;
|
|
BRep_Builder().MakeWire(anImages);
|
|
//
|
|
TopTools_MapOfShape aMImFence;
|
|
const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm);
|
|
TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr);
|
|
for (; aItOffset.More(); aItOffset.Next()) {
|
|
const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
|
|
const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItImages(aLImages);
|
|
for (; aItImages.More(); aItImages.Next()) {
|
|
const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
|
|
if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) {
|
|
BRep_Builder().Add(anImages, anIm);
|
|
aLEImages.Append(anIm);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// find alone vertices
|
|
TopoDS_Vertex aVW1, aVW2;
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
|
|
TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
|
|
//
|
|
TopTools_ListOfShape aLVAlone;
|
|
Standard_Integer aNb = aDMImVE.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopTools_ListOfShape& aLImE = aDMImVE(i);
|
|
if (aLImE.Extent() == 1) {
|
|
aLVAlone.Append(aDMImVE.FindKey(i));
|
|
}
|
|
}
|
|
//
|
|
if (aLVAlone.Extent() > 1) {
|
|
aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
|
|
aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
|
|
//
|
|
// check distances
|
|
const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
|
|
const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1);
|
|
const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2);
|
|
//
|
|
Standard_Real aDist1 = aPI1.SquareDistance(aPW1);
|
|
Standard_Real aDist2 = aPI1.SquareDistance(aPW2);
|
|
//
|
|
if (aDist1 < aDist2) {
|
|
aVI1 = aVW1;
|
|
aVI2 = aVW2;
|
|
}
|
|
else {
|
|
aVI1 = aVW2;
|
|
aVI2 = aVW1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
aLEImages.Append(theEIm);
|
|
}
|
|
//
|
|
// Find edges connected to these vertices
|
|
const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1);
|
|
const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2);
|
|
//
|
|
// Find vertices on the original face corresponding to vertices on the offset edge
|
|
//
|
|
// find original edges for both lists
|
|
TopTools_ListOfShape aLOE1, aLOE2;
|
|
for (i = 0; i < 2; ++i) {
|
|
const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
|
|
TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
|
|
//
|
|
TopTools_MapOfShape aMFence;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLIE(aLIE);
|
|
for (; aItLIE.More(); aItLIE.Next()) {
|
|
const TopoDS_Shape& aEI = aItLIE.Value();
|
|
if (theEdgesOrigins.IsBound(aEI)) {
|
|
const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins);
|
|
for (; aItLOE.More(); aItLOE.Next()) {
|
|
const TopoDS_Shape& aEO = aItLOE.Value();
|
|
if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) {
|
|
TopoDS_Shape aEOin;
|
|
if (FindShape(aEO, theFOr, aEOin)) {
|
|
AppendToList(aLOE, aEO);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
// find vertices common for all edges in the lists
|
|
for (i = 0; i < 2; ++i) {
|
|
const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
|
|
TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
|
|
//
|
|
const TopoDS_Shape& aEO = aLOE.First();
|
|
TopExp_Explorer aExpV(aEO, TopAbs_VERTEX);
|
|
for (; aExpV.More(); aExpV.Next()) {
|
|
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current();
|
|
//
|
|
Standard_Boolean bVertValid = Standard_True;
|
|
TopTools_ListIteratorOfListOfShape aItLOE(aLOE);
|
|
for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) {
|
|
const TopoDS_Shape& aEOx = aItLOE.Value();
|
|
TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX);
|
|
for (; aExpVx.More(); aExpVx.Next()) {
|
|
const TopoDS_Shape& aVx = aExpVx.Current();
|
|
if (aVx.IsSame(aV)) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (!aExpVx.More()) {
|
|
bVertValid = Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (bVertValid) {
|
|
aVO = aV;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
// check positions of the offset and original vertices
|
|
const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
|
|
const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2);
|
|
const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1);
|
|
const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2);
|
|
//
|
|
gp_Vec aVI(aPI1, aPI2);
|
|
gp_Vec aVO(aPO1, aPO2);
|
|
//
|
|
Standard_Real anAngle = aVI.Angle(aVO);
|
|
Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4;
|
|
if (bInverted) {
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEInvr = aItLEIm.Value();
|
|
theMEInverted.Add(aEInvr);
|
|
}
|
|
}
|
|
return bInverted;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CheckInvertedBlock
|
|
//purpose : Checks if it is possible to remove the block containing
|
|
// inverted edges
|
|
//=======================================================================
|
|
Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
|
|
const TopTools_ListOfShape& theLCBF,
|
|
const TopTools_MapOfShape& theMEInverted,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
|
|
BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll)
|
|
{
|
|
// For possible removal of the block:
|
|
// 1. There should be more than just one face in the block
|
|
TopoDS_Iterator aItF(theCB);
|
|
aItF.Next();
|
|
if (!aItF.More()) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
// 2. The block should at least contain two connected inverted edges with
|
|
// different origins (not just two images/splits of the same edge)
|
|
TopTools_MapOfShape aMECBInv;
|
|
TopoDS_Compound aCECBInv;
|
|
BRep_Builder().MakeCompound(aCECBInv);
|
|
//
|
|
TopExp_Explorer aExp(theCB, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
if (theMEInverted.Contains(aE)) {
|
|
if (aMECBInv.Add(aE)) {
|
|
BRep_Builder().Add(aCECBInv, aE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMECBInv.Extent() < 2) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
// check that the edges are connected and different
|
|
TopTools_ListOfShape aLCBE;
|
|
BOPTools_AlgoTools::MakeConnexityBlocks(aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
|
|
for (; aItLCBE.More(); aItLCBE.Next()) {
|
|
const TopoDS_Shape& aCBE = aItLCBE.Value();
|
|
// count the unique edges in the block
|
|
Standard_Integer aNbUnique = 0;
|
|
TopTools_MapOfShape aMEOrigins;
|
|
TopoDS_Iterator aItE(aCBE);
|
|
for (; aItE.More(); aItE.Next()) {
|
|
const TopoDS_Shape& aE = aItE.Value();
|
|
const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
|
|
if (!pLEOr) {
|
|
aMEOrigins.Add(aE);
|
|
++aNbUnique;
|
|
continue;
|
|
}
|
|
TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
|
|
for (; aItLEOr.More(); aItLEOr.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLEOr.Value();
|
|
if (aMEOrigins.Add(aEOr)) {
|
|
++aNbUnique;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aNbUnique >= 2) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (!aItLCBE.More()) {
|
|
return Standard_False;
|
|
}
|
|
//
|
|
// 3. the block should not contain inverted edges which vertices
|
|
// are contained in other blocks
|
|
//
|
|
// collect vertices from inverted edges and compare them with
|
|
// vertices from other blocks
|
|
TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek(theCB);
|
|
TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek(theCB);
|
|
if (!pMVInverted) {
|
|
pMVInverted = theDMCBVInverted.Bound(theCB, TopTools_MapOfShape());
|
|
pMVAll = theDMCBVAll.Bound(theCB, TopTools_MapOfShape());
|
|
//
|
|
GetVerticesOnEdges(theCB, theMEInverted, *pMVInverted, *pMVAll);
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLCB1(theLCBF);
|
|
for (; aItLCB1.More(); aItLCB1.Next()) {
|
|
const TopoDS_Shape& aCB1 = aItLCB1.Value();
|
|
if (aCB1.IsSame(theCB)) {
|
|
continue;
|
|
}
|
|
//
|
|
// collect vertices from inverted edges
|
|
TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek(aCB1);
|
|
TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek(aCB1);
|
|
if (!pMVInverted1) {
|
|
pMVInverted1 = theDMCBVInverted.Bound(aCB1, TopTools_MapOfShape());
|
|
pMVAll1 = theDMCBVAll.Bound(aCB1, TopTools_MapOfShape());
|
|
//
|
|
GetVerticesOnEdges(aCB1, theMEInverted, *pMVInverted1, *pMVAll1);
|
|
}
|
|
//
|
|
if (pMVInverted->HasIntersection(*pMVAll1)) {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
//
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetVerticesOnEdges
|
|
//purpose : Get vertices from the given shape belonging to the given edges
|
|
//=======================================================================
|
|
void GetVerticesOnEdges(const TopoDS_Shape& theCB,
|
|
const TopTools_MapOfShape& theEdges,
|
|
TopTools_MapOfShape& theVerticesOnEdges,
|
|
TopTools_MapOfShape& theAllVertices)
|
|
{
|
|
TopExp_Explorer aExp(theCB, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
Standard_Boolean bOnGivenEdge = theEdges.Contains(aE);
|
|
for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
|
|
theAllVertices.Add(aItV.Value());
|
|
if (bOnGivenEdge) {
|
|
theVerticesOnEdges.Add(aItV.Value());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RemoveInvalidSplitsByInvertedEdges
|
|
//purpose : Looking for the invalid faces containing inverted edges
|
|
// that can be safely removed
|
|
//=======================================================================
|
|
void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
|
|
TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
|
TopTools_IndexedMapOfShape& theMERemoved)
|
|
{
|
|
if (theMEInverted.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// check the faces on regularity, i.e. the splits of the same face
|
|
// should not be connected only by vertex. Such irregular splits
|
|
// will have to be rebuilt and cannot be removed.
|
|
//
|
|
BRep_Builder aBB;
|
|
TopTools_IndexedMapOfShape aMEAvoid;
|
|
TopTools_DataMapOfShapeListOfShape aDMVF;
|
|
Standard_Integer aNb = theFImages.Extent(), i;
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopTools_ListOfShape& aLFIm = theFImages(i);
|
|
//
|
|
TopoDS_Compound aCFIm;
|
|
aBB.MakeCompound(aCFIm);
|
|
//
|
|
TopTools_DataMapOfShapeListOfShape aDMEF;
|
|
TopTools_ListIteratorOfListOfShape aIt(aLFIm);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF = aIt.Value();
|
|
aBB.Add(aCFIm, aF);
|
|
//
|
|
// make a map to use only outer edges
|
|
TopExp_Explorer aExp(aF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
//
|
|
TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE);
|
|
if (!pLF) {
|
|
pLF = aDMEF.Bound(aE, TopTools_ListOfShape());
|
|
}
|
|
else {
|
|
// internal edges should not be used
|
|
aMEAvoid.Add(aE);
|
|
}
|
|
AppendToList(*pLF, aF);
|
|
}
|
|
//
|
|
// fill connection map of the vertices of inverted edges to faces
|
|
aExp.Init(aF, TopAbs_VERTEX);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aV = aExp.Current();
|
|
//
|
|
TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV);
|
|
if (!pLF) {
|
|
pLF = aDMVF.Bound(aV, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLF, aF);
|
|
}
|
|
}
|
|
//
|
|
// for the splits to be regular they should form only one block
|
|
TopTools_ListOfShape aLCBF;
|
|
BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
|
|
if (aLCBF.Extent() == 1) {
|
|
continue;
|
|
}
|
|
//
|
|
// check if the inverted edges create the irregularity
|
|
BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLCB(aLCBF);
|
|
for (; aItLCB.More(); aItLCB.Next()) {
|
|
const TopoDS_Shape& aCB = aItLCB.Value();
|
|
//
|
|
// check if it is possible to remove the block
|
|
if (!CheckInvertedBlock(aCB, aLCBF, theMEInverted, theOEOrigins, aDMCBVInverted, aDMCBVAll)) {
|
|
// non of the edges in this block should be removed
|
|
TopExp::MapShapes(aCB, TopAbs_EDGE, aMEAvoid);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// all edges not included in aMEAvoid can be removed
|
|
TopTools_MapOfShape aMERem;
|
|
TopTools_MapIteratorOfMapOfShape aItM(theMEInverted);
|
|
for (; aItM.More(); aItM.Next()) {
|
|
const TopoDS_Shape& aE = aItM.Value();
|
|
if (!aMEAvoid.Contains(aE)) {
|
|
TopoDS_Iterator aIt(aE);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aV = aIt.Value();
|
|
const TopTools_ListOfShape *pLF = aDMVF.Seek(aV);
|
|
if (pLF && (pLF->Extent() > 3)) {
|
|
aMERem.Add(aE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMERem.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// all invalid faces containing these edges can be removed
|
|
TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
|
|
TopTools_MapOfShape aMFRem;
|
|
TopTools_IndexedMapOfShape aMFToUpdate;
|
|
aNb = theInvFaces.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theInvFaces.FindKey(i);
|
|
TopTools_ListOfShape& aLFIm = theInvFaces(i);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aIt(aLFIm);
|
|
for (; aIt.More(); ) {
|
|
const TopoDS_Shape& aFIm = aIt.Value();
|
|
//
|
|
// to be removed the face should have at least two not connected
|
|
// inverted edges
|
|
TopoDS_Compound aCEInv;
|
|
aBB.MakeCompound(aCEInv);
|
|
TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
if (aMERem.Contains(aE)) {
|
|
aBB.Add(aCEInv, aE);
|
|
}
|
|
}
|
|
//
|
|
// check connectivity
|
|
TopTools_ListOfShape aLCBE;
|
|
BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
|
|
//
|
|
if (aLCBE.Extent() >= 2) {
|
|
aMFToUpdate.Add(aF);
|
|
aMFRem.Add(aFIm);
|
|
aLFIm.Remove(aIt);
|
|
}
|
|
else {
|
|
aIt.Next();
|
|
}
|
|
}
|
|
//
|
|
if (aLFIm.Extent()) {
|
|
aInvFaces.Add(aF, aLFIm);
|
|
}
|
|
}
|
|
//
|
|
if (aMFRem.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
theInvFaces = aInvFaces;
|
|
// remove from splits
|
|
aNb = aMFToUpdate.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = aMFToUpdate(i);
|
|
TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aIt(aLFIm);
|
|
for (; aIt.More(); ) {
|
|
const TopoDS_Shape& aFIm = aIt.Value();
|
|
if (aMFRem.Contains(aFIm)) {
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved);
|
|
aLFIm.Remove(aIt);
|
|
}
|
|
else {
|
|
aIt.Next();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RemoveInvalidSplitsFromValid
|
|
//purpose : Removing invalid splits of faces from valid
|
|
//=======================================================================
|
|
void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
|
|
const TopTools_DataMapOfShapeShape& theArtInvFaces,
|
|
const TopTools_MapOfShape& theMEInverted,
|
|
TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
|
|
{
|
|
// Decide whether to remove the found invalid faces or not.
|
|
// The procedure is the following:
|
|
// 1. Make connexity blocks from invalid faces;
|
|
// 2. Find free edges in this blocks;
|
|
// 3. If all free edges are valid for the faces - remove block.
|
|
//
|
|
TopTools_MapOfShape aMFence, aMFToRem;
|
|
TopoDS_Compound aCFInv;
|
|
BRep_Builder aBB;
|
|
aBB.MakeCompound(aCFInv);
|
|
TopTools_ListIteratorOfListOfShape aItLF;
|
|
//
|
|
// make compound of invalid faces
|
|
TopTools_DataMapOfShapeShape aDMIFOF;
|
|
Standard_Integer i, aNb = theInvFaces.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theInvFaces.FindKey(i);
|
|
// artificially invalid faces should not be removed
|
|
if (theArtInvFaces.IsBound(aF)) {
|
|
continue;
|
|
}
|
|
const TopTools_ListOfShape& aLFInv = theInvFaces(i);
|
|
aItLF.Initialize(aLFInv);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLF.Value();
|
|
if (aMFence.Add(aFIm)) {
|
|
aBB.Add(aCFInv, aFIm);
|
|
aDMIFOF.Bind(aFIm, aF);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// make connexity blocks
|
|
TopTools_ListOfShape aLCBInv;
|
|
BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
|
|
//
|
|
// analyze each block
|
|
aItLF.Initialize(aLCBInv);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aCB = aItLF.Value();
|
|
//
|
|
// if connexity block contains only one face - it should be removed;
|
|
TopExp_Explorer aExp(aCB, TopAbs_FACE);
|
|
aExp.Next();
|
|
if (aExp.More()) {
|
|
// check if there are valid images left
|
|
aExp.Init(aCB, TopAbs_FACE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aFIm = aExp.Current();
|
|
const TopoDS_Shape& aF = aDMIFOF.Find(aFIm);
|
|
//
|
|
const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
|
|
const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
|
|
//
|
|
if (aLFIm.Extent() == aLFInv.Extent()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (!aExp.More()) {
|
|
aExp.Init(aCB, TopAbs_FACE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aF = aExp.Current();
|
|
aMFToRem.Add(aF);
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
// remove faces connected by inverted edges
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
|
|
TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
|
|
//
|
|
aExp.Init(aCB, TopAbs_FACE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aFCB = aExp.Current();
|
|
//
|
|
TopExp_Explorer aExpE(aFCB, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aECB = aExpE.Current();
|
|
if (aDMEF.FindFromKey(aECB).Extent() > 1) {
|
|
if (!theMEInverted.Contains(aECB)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (!aExpE.More()) {
|
|
aMFToRem.Add(aFCB);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMFToRem.Extent()) {
|
|
// remove invalid faces from images
|
|
aNb = theInvFaces.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theInvFaces.FindKey(i);
|
|
TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
|
|
aItLF.Initialize(aLFImages);
|
|
for (; aItLF.More();) {
|
|
const TopoDS_Shape& aFIm = aItLF.Value();
|
|
if (aMFToRem.Contains(aFIm)) {
|
|
aLFImages.Remove(aItLF);
|
|
}
|
|
else {
|
|
aItLF.Next();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RemoveInsideFaces
|
|
//purpose : Looking for the inside faces that can be safely removed
|
|
//=======================================================================
|
|
void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
|
TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
|
|
const TopTools_DataMapOfShapeShape& theArtInvFaces,
|
|
const TopTools_IndexedMapOfShape& theInvEdges,
|
|
const TopTools_IndexedMapOfShape& theMFToCheckInt,
|
|
const TopTools_IndexedMapOfShape& theMFInvInHole,
|
|
const TopoDS_Shape& theFHoles,
|
|
TopTools_DataMapOfShapeListOfShape& theSSInterfs,
|
|
TopTools_IndexedMapOfShape& theMERemoved,
|
|
TopTools_IndexedMapOfShape& theMEInside,
|
|
TopoDS_Shape& theSolids)
|
|
{
|
|
BOPCol_ListOfShape aLS;
|
|
TopTools_MapOfShape aMFence;
|
|
TopTools_IndexedMapOfShape aMFInv;
|
|
TopTools_ListIteratorOfListOfShape aItLF;
|
|
TopTools_DataMapOfShapeShape aDMFImF;
|
|
//
|
|
Standard_Integer i, aNb = theFImages.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theFImages.FindKey(i);
|
|
// to avoid intersection of the splits of the same
|
|
// offset faces among themselves make compound of the
|
|
// splits and use it as one argument
|
|
TopoDS_Compound aCFImi;
|
|
BRep_Builder().MakeCompound(aCFImi);
|
|
//
|
|
for (Standard_Integer j = 0; j < 2; ++j) {
|
|
const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i);
|
|
if (!pLFSp) {
|
|
continue;
|
|
}
|
|
//
|
|
aItLF.Initialize(*pLFSp);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLF.Value();
|
|
if (aMFence.Add(aFIm)) {
|
|
BRep_Builder().Add(aCFImi, aFIm);
|
|
aDMFImF.Bind(aFIm, aF);
|
|
if (!j) {
|
|
aMFInv.Add(aFIm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aLS.Append(aCFImi);
|
|
}
|
|
//
|
|
// to make the solids more complete add for intersection also the faces
|
|
// consisting only of invalid edges and not included into splits
|
|
aNb = theMFToCheckInt.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aFSp = theMFToCheckInt(i);
|
|
if (aMFence.Add(aFSp)) {
|
|
aLS.Append(aFSp);
|
|
}
|
|
}
|
|
//
|
|
BOPAlgo_MakerVolume aMV;
|
|
aMV.SetArguments(aLS);
|
|
aMV.SetIntersect(Standard_True);
|
|
aMV.Perform();
|
|
//
|
|
// get shapes connection for using in the rebuilding process
|
|
// for the cases in which some of the intersection left undetected
|
|
ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theSSInterfs);
|
|
//
|
|
// find faces to remove
|
|
const TopoDS_Shape& aSols = aMV.Shape();
|
|
//
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
|
|
TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
|
|
//
|
|
aNb = aDMFS.Extent();
|
|
if (!aNb) {
|
|
return;
|
|
}
|
|
//
|
|
// To use the created solids for classifications, firstly, it is necessary
|
|
// to check them on validity - the created solids should be complete,
|
|
// i.e. all faces should be included.
|
|
//
|
|
TopTools_MapOfShape aMFToRem;
|
|
// Check completeness
|
|
if (aMV.HasDeleted()) {
|
|
TopTools_IndexedMapOfShape aMEHoles;
|
|
TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles);
|
|
//
|
|
// perform additional check on faces
|
|
aNb = theFImages.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopTools_ListOfShape& aLFIm = theFImages(i);
|
|
if (aLFIm.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
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) {
|
|
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 newly found internal faces
|
|
RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
|
|
RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
|
|
//
|
|
// Get inside faces from the removed ones comparing them with boundary edges
|
|
aNb = theMERemoved.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aE = theMERemoved(i);
|
|
if (!aMEBoundary.Contains(aE)) {
|
|
theMEInside.Add(aE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ShapesConnections
|
|
//purpose : Looking for the connections between faces not to miss
|
|
// some necessary intersection
|
|
//=======================================================================
|
|
void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
|
|
const TopTools_IndexedMapOfShape& theInvEdges,
|
|
const TopTools_DataMapOfShapeShape& theDMFOr,
|
|
BOPAlgo_Builder& theBuilder,
|
|
TopTools_DataMapOfShapeListOfShape& theSSInterfs)
|
|
{
|
|
// update invalid edges with images and keep connection to original edge
|
|
TopTools_DataMapOfShapeListOfShape aDMEOr;
|
|
Standard_Integer aNb = theInvEdges.Extent();
|
|
for (Standard_Integer i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aEInv = theInvEdges(i);
|
|
const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv);
|
|
if (aLEIm.IsEmpty()) {
|
|
aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv);
|
|
continue;
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLEIm.Value();
|
|
//
|
|
TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm);
|
|
if (!pLEOr) {
|
|
pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLEOr, aEInv);
|
|
}
|
|
}
|
|
//
|
|
// get shapes connections for using in the rebuilding process
|
|
const BOPDS_PDS& pDS = theBuilder.PDS();
|
|
// analyze all Face/Face intersections
|
|
const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
|
|
Standard_Integer iInt, aNbFF = aFFs.Extent();
|
|
for (iInt = 0; iInt < aNbFF; ++iInt) {
|
|
const BOPDS_InterfFF& aFF = aFFs(iInt);
|
|
const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
|
|
Standard_Integer aNbC = aVNC.Extent();
|
|
if (!aNbC) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1());
|
|
const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2());
|
|
//
|
|
const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1);
|
|
const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2);
|
|
//
|
|
if (!pF1 || !pF2) {
|
|
continue;
|
|
}
|
|
//
|
|
if (pF1->IsSame(*pF2)) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bInv1 = theInvFaces.Contains(*pF1);
|
|
Standard_Boolean bInv2 = theInvFaces.Contains(*pF2);
|
|
//
|
|
if (!bInv1 && !bInv2) {
|
|
continue;
|
|
}
|
|
//
|
|
// check if it is real Face/Face intersection
|
|
TopTools_MapOfShape aMEInt;
|
|
for (Standard_Integer iC = 0; iC < aNbC; ++iC) {
|
|
const BOPDS_Curve& aNC = aVNC(iC);
|
|
const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
|
|
for (; aItLPB.More(); aItLPB.Next()) {
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
|
|
Standard_Integer nEInt;
|
|
if (aPB->HasEdge(nEInt)) {
|
|
const TopoDS_Shape& aEInt = pDS->Shape(nEInt);
|
|
aMEInt.Add(aEInt);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMEInt.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
// check if invalid edges of the face are in the same splits with intersection edges
|
|
for (Standard_Integer i = 0; i < 2; ++i) {
|
|
if ((!i && !bInv1) || (i && !bInv2)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
|
|
const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
|
|
const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
|
|
//
|
|
Standard_Boolean bFound = Standard_False;
|
|
//
|
|
TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm);
|
|
if (aLFIm.IsEmpty()) {
|
|
aLFIm.Append(aFIm);
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFImIm = aItLFIm.Value();
|
|
//
|
|
Standard_Boolean bInv(Standard_False), bInt(Standard_False);
|
|
TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aE = aExpE.Current();
|
|
if (!bInv) {
|
|
bInv = aDMEOr.IsBound(aE);
|
|
}
|
|
if (!bInt) {
|
|
bInt = aMEInt.Contains(aE);
|
|
}
|
|
if (bInv && bInt) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (!bInt || !bInv) {
|
|
continue;
|
|
}
|
|
//
|
|
bFound = Standard_True;
|
|
//
|
|
// append opposite face to all invalid edges in the split
|
|
aExpE.Init(aFImIm, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Shape& aE = aExpE.Current();
|
|
const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE);
|
|
if (!pLEOr) {
|
|
continue;
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLE(*pLEOr);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLE.Value();
|
|
TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr);
|
|
if (!pLFE) {
|
|
pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLFE, aFOp);
|
|
}
|
|
}
|
|
}
|
|
if (bFound) {
|
|
// save connection between offset faces
|
|
TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF);
|
|
if (!pLF) {
|
|
pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLF, aFOp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : 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, aDMVEFull, 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;
|
|
//
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// filter the obtained edges
|
|
UpdateValidEdges(theFImages, aFLE, 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,
|
|
TopTools_DataMapOfShapeListOfShape& theDMVEFull,
|
|
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;
|
|
}
|
|
//
|
|
TopExp_Explorer aExp(aE, TopAbs_VERTEX);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aV = aExp.Current();
|
|
TopTools_ListOfShape *pLE = theDMVEFull.ChangeSeek(aV);
|
|
if (!pLE) {
|
|
theMVRInv.Add(aV);
|
|
continue;
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLE(*pLE);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEV = aItLE.Value();
|
|
if (!theInvEdges.Contains(aEV) && !theDMEFInv.Contains(aEV)) {
|
|
break;
|
|
}
|
|
}
|
|
if (!aItLE.More()) {
|
|
theMVRInv.Add(aV);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindFacesForIntersection
|
|
//purpose : Looking for the faces around each invalidity for intersection
|
|
//=======================================================================
|
|
void FindFacesForIntersection(const TopoDS_Shape& theFInv,
|
|
const TopTools_IndexedMapOfShape& theME,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
|
const TopTools_DataMapOfShapeListOfShape& theDMSF,
|
|
const TopTools_MapOfShape& theMVInvAll,
|
|
const TopTools_DataMapOfShapeShape& theArtInvFaces,
|
|
const Standard_Boolean theArtCase,
|
|
const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
|
|
TopTools_IndexedMapOfShape& theMFAvoid,
|
|
TopTools_IndexedMapOfShape& theMFInt,
|
|
TopTools_IndexedMapOfShape& theMFIntExt,
|
|
TopTools_ListOfShape& theLFImInt)
|
|
{
|
|
Standard_Integer i, aNbE = theME.Extent();
|
|
//
|
|
TopTools_IndexedMapOfShape aMShapes;
|
|
//
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
const TopoDS_Shape& aS = theME(i);
|
|
if (!theDMSF.IsBound(aS)) {
|
|
continue;
|
|
}
|
|
//
|
|
// in artificial case we intersect the faces which are close to invalidity
|
|
Standard_Boolean bAvoid = theArtCase ?
|
|
((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains(aS)) : Standard_False;
|
|
//
|
|
const TopTools_ListOfShape& aLF = theDMSF.Find(aS);
|
|
TopTools_ListIteratorOfListOfShape aItLF(aLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aF = aItLF.Value();
|
|
if (theMFInt.Contains(aF)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (bAvoid && theArtInvFaces.IsBound(aF)) {
|
|
theMFAvoid.Add(aF);
|
|
}
|
|
//
|
|
theMFInt.Add(aF);
|
|
//
|
|
Standard_Boolean bUse = !aF.IsSame(theFInv);
|
|
//
|
|
const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
theLFImInt.Append(aFIm);
|
|
if (bUse) {
|
|
TopExp::MapShapes(aFIm, TopAbs_EDGE, aMShapes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (theArtCase) {
|
|
return;
|
|
}
|
|
//
|
|
const TopTools_ListOfShape* pLFInv = theSSInterfs.Seek(theFInv);
|
|
if (!pLFInv) {
|
|
return;
|
|
}
|
|
//
|
|
TopTools_MapOfShape aMF;
|
|
TopTools_ListIteratorOfListOfShape aItLF(*pLFInv);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aF = aItLF.Value();
|
|
aMF.Add(aF);
|
|
}
|
|
//
|
|
// the faces should be unique in each place
|
|
TopoDS_Compound aCF;
|
|
BRep_Builder().MakeCompound(aCF);
|
|
//
|
|
TopTools_IndexedMapOfShape aMFToAdd;
|
|
TopTools_DataMapOfShapeShape aDMFOr;
|
|
//
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
const TopoDS_Shape& aS = theME(i);
|
|
const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aS);
|
|
if (!pLF) {
|
|
continue;
|
|
}
|
|
//
|
|
aItLF.Initialize(*pLF);
|
|
for (; aItLF.More(); aItLF.Next()) {
|
|
const TopoDS_Shape& aF = aItLF.Value();
|
|
if (theMFInt.Contains(aF) || aMFToAdd.Contains(aF) || !aMF.Contains(aF)) {
|
|
continue;
|
|
}
|
|
//
|
|
// check if the face has some connection to already added for intersection faces
|
|
const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
if (aMShapes.Contains(aExp.Current())) {
|
|
break;
|
|
}
|
|
}
|
|
if (aExp.More()) {
|
|
break;
|
|
}
|
|
}
|
|
if (!aItLFIm.More()) {
|
|
continue;
|
|
}
|
|
//
|
|
aMFToAdd.Add(aF);
|
|
aItLFIm.Initialize(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
aDMFOr.Bind(aFIm, aF);
|
|
BRep_Builder().Add(aCF, aFIm);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (aMFToAdd.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
TopTools_ListOfShape aLCB;
|
|
BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
|
|
//
|
|
if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1)) {
|
|
return;
|
|
}
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
|
|
for (; aItLCB.More(); aItLCB.Next()) {
|
|
const TopoDS_Shape& aCB = aItLCB.Value();
|
|
aMFToAdd.Clear();
|
|
TopExp_Explorer aExpF(aCB, TopAbs_FACE);
|
|
for (; aExpF.More(); aExpF.Next()) {
|
|
const TopoDS_Shape& aFIm = aExpF.Current();
|
|
aMFToAdd.Add(aDMFOr.Find(aFIm));
|
|
}
|
|
//
|
|
if (aMFToAdd.Extent() == 1) {
|
|
const TopoDS_Shape& aF = aMFToAdd(1);
|
|
//
|
|
theMFInt.Add(aF);
|
|
theMFIntExt.Add(aF);
|
|
//
|
|
const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
theLFImInt.Append(aFIm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ProcessCommonEdges
|
|
//purpose : Analyzing the common edges between splits of offset faces
|
|
//=======================================================================
|
|
void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
|
|
const TopTools_IndexedMapOfShape& theInvEdges,
|
|
const TopTools_IndexedMapOfShape& theValidEdges,
|
|
const TopTools_IndexedMapOfShape& theME,
|
|
const TopTools_DataMapOfShapeShape& theETrimEInf,
|
|
const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
|
|
const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
|
|
const TopTools_MapOfShape& theAllInvs,
|
|
const Standard_Boolean theForceUse,
|
|
TopTools_IndexedMapOfShape& theMECV,
|
|
TopTools_MapOfShape& theMECheckExt,
|
|
TopTools_DataMapOfShapeListOfShape& theDMEETrim,
|
|
TopTools_ListOfShape& theLFEi,
|
|
TopTools_ListOfShape& theLFEj,
|
|
TopTools_IndexedMapOfShape& theMEToInt)
|
|
{
|
|
TopTools_ListOfShape aLEC;
|
|
// process common edges
|
|
TopTools_ListIteratorOfListOfShape aItLE(theLEC);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEC = aItLE.Value();
|
|
//
|
|
// check first if common edges are valid
|
|
if (theInvEdges.Contains(aEC) && !theValidEdges.Contains(aEC)) {
|
|
continue;
|
|
}
|
|
//
|
|
// common edge should have connection to current invalidity
|
|
if (theME.Contains(aEC)) {
|
|
aLEC.Append(aEC);
|
|
continue;
|
|
}
|
|
//
|
|
TopoDS_Iterator aItV(aEC);
|
|
for (; aItV.More(); aItV.Next()) {
|
|
const TopoDS_Shape& aVE = aItV.Value();
|
|
if (theME.Contains(aVE)) {
|
|
aLEC.Append(aEC);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
|
|
if (bUseOnlyInf) {
|
|
if (theForceUse) {
|
|
aLEC = theLEC;
|
|
}
|
|
else {
|
|
aItLE.Initialize(theLEC);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEC = aItLE.Value();
|
|
// check if all images of the origin of this edge
|
|
// are not connected to any invalidity
|
|
const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
|
|
const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
|
|
TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
|
|
for (; aItLVE.More(); aItLVE.Next()) {
|
|
const TopoDS_Shape& aECx = aItLVE.Value();
|
|
if (theAllInvs.Contains(aECx) || theInvEdges.Contains(aECx)) {
|
|
return;
|
|
}
|
|
//
|
|
TopoDS_Iterator aItV(aECx);
|
|
for (; aItV.More(); aItV.Next()) {
|
|
if (theAllInvs.Contains(aItV.Value())) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
// use only one element
|
|
if (aLEC.IsEmpty()) {
|
|
aLEC.Append(aEC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aItLE.Initialize(aLEC);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEC = aItLE.Value();
|
|
//
|
|
const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
|
|
if (!bUseOnlyInf) {
|
|
// find the edges of the same original edge
|
|
// and take their vertices as well
|
|
const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
|
|
TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
|
|
for (; aItLVE.More(); aItLVE.Next()) {
|
|
const TopoDS_Shape& aECx = aItLVE.Value();
|
|
//
|
|
const TopTools_ListOfShape* pLEOr = theOEOrigins.Seek(aECx);
|
|
if (!pLEOr || (pLEOr->Extent() == 1)) {
|
|
TopExp::MapShapes(aECx, TopAbs_VERTEX, theMECV);
|
|
}
|
|
}
|
|
//
|
|
// bind unlimited edge to its trimmed part in face to update maps of
|
|
// images and origins in the future
|
|
TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek(aEInt);
|
|
if (!pLTAdded) {
|
|
pLTAdded = theDMEETrim.Bound(aEInt, TopTools_ListOfShape());
|
|
}
|
|
AppendToList(*pLTAdded, aEC);
|
|
}
|
|
else if (!theForceUse) {
|
|
theMECheckExt.Add(aEInt);
|
|
}
|
|
//
|
|
AppendToList(theLFEi, aEInt);
|
|
AppendToList(theLFEj, aEInt);
|
|
theMEToInt.Add(aEInt);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UpdateIntersectedFaces
|
|
//purpose : Updating the already interfered faces
|
|
//=======================================================================
|
|
void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
|
|
const TopoDS_Shape& theFi,
|
|
const TopoDS_Shape& theFj,
|
|
const TopTools_ListOfShape& theLFInv,
|
|
const TopTools_ListOfShape& theLFImi,
|
|
const TopTools_ListOfShape& theLFImj,
|
|
const TopTools_ListOfShape& theLFEi,
|
|
const TopTools_ListOfShape& theLFEj,
|
|
TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
|
|
TopTools_IndexedMapOfShape& theMEToInt)
|
|
{
|
|
// Find common edges in these two lists
|
|
TopTools_MapOfShape aMEi;
|
|
TopTools_ListIteratorOfListOfShape aItLE(theLFEi);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aE = aItLE.Value();
|
|
aMEi.Add(aE);
|
|
}
|
|
//
|
|
// find origins
|
|
TopTools_IndexedMapOfShape aMEToFindOrigins;
|
|
TopTools_ListOfShape aLEToFindOrigins;
|
|
if (!theFi.IsSame(theFInv)) {
|
|
FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
|
|
}
|
|
if (!theFj.IsSame(theFInv)) {
|
|
FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
|
|
}
|
|
//
|
|
TopTools_ListOfShape aLEOrInit;
|
|
aItLE.Initialize(aLEToFindOrigins);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEC = aItLE.Value();
|
|
aMEToFindOrigins.Add(aEC);
|
|
}
|
|
//
|
|
FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
|
|
//
|
|
aItLE.Initialize(theLFEj);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aE = aItLE.Value();
|
|
if (aMEi.Contains(aE)) {
|
|
theMEToInt.Add(aE);
|
|
if (aLEOrInit.Extent()) {
|
|
if (theEdgesOrigins.IsBound(aE)) {
|
|
TopTools_ListOfShape& aLEOr = theEdgesOrigins.ChangeFind(aE);
|
|
TopTools_ListIteratorOfListOfShape aItLEOr(aLEOrInit);
|
|
for (; aItLEOr.More(); aItLEOr.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLEOr.Value();
|
|
AppendToList(aLEOr, aEOr);
|
|
}
|
|
}
|
|
else {
|
|
theEdgesOrigins.Bind(aE, aLEOrInit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IntersectFaces
|
|
//purpose : Intersection of the pair of faces
|
|
//=======================================================================
|
|
void IntersectFaces(const TopoDS_Shape& theFInv,
|
|
const TopoDS_Shape& theFi,
|
|
const TopoDS_Shape& theFj,
|
|
const TopTools_ListOfShape& theLFInv,
|
|
const TopTools_ListOfShape& theLFImi,
|
|
const TopTools_ListOfShape& theLFImj,
|
|
TopTools_ListOfShape& theLFEi,
|
|
TopTools_ListOfShape& theLFEj,
|
|
TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
|
|
TopTools_IndexedMapOfShape& theMECV,
|
|
TopTools_IndexedMapOfShape& theMEToInt)
|
|
{
|
|
// intersect faces
|
|
TopAbs_State aSide = TopAbs_OUT;
|
|
TopTools_ListOfShape aLInt1, aLInt2;
|
|
TopoDS_Edge aNullEdge;
|
|
BRepOffset_Tool::Inter3D(TopoDS::Face(theFi), TopoDS::Face(theFj), aLInt1, aLInt2, aSide, aNullEdge);
|
|
//
|
|
if (aLInt1.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// find common vertices for trimming edges
|
|
TopTools_ListOfShape aLCV;
|
|
TopTools_ListIteratorOfListOfShape aItLE;
|
|
FindCommonParts(theLFImi, theLFImj, aLCV, TopAbs_VERTEX);
|
|
if (aLCV.Extent() > 1) {
|
|
aItLE.Initialize(aLCV);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aCV = aItLE.Value();
|
|
theMECV.Add(aCV);
|
|
}
|
|
}
|
|
//
|
|
// find origins
|
|
TopTools_IndexedMapOfShape aMEToFindOrigins;
|
|
TopTools_ListOfShape aLEToFindOrigins;
|
|
if (!theFi.IsSame(theFInv)) {
|
|
FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
|
|
}
|
|
if (!theFj.IsSame(theFInv)) {
|
|
FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
|
|
}
|
|
TopTools_ListOfShape aLEOrInit;
|
|
aItLE.Initialize(aLEToFindOrigins);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEC = aItLE.Value();
|
|
aMEToFindOrigins.Add(aEC);
|
|
}
|
|
//
|
|
FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
|
|
//
|
|
aItLE.Initialize(aLInt1);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEInt = aItLE.Value();
|
|
theLFEi.Append(aEInt);
|
|
theLFEj.Append(aEInt);
|
|
//
|
|
if (aLEOrInit.Extent()) {
|
|
theEdgesOrigins.Bind(aEInt, aLEOrInit);
|
|
}
|
|
//
|
|
theMEToInt.Add(aEInt);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindOrigins
|
|
//purpose : Looking for the origin edges
|
|
//=======================================================================
|
|
void FindOrigins(const TopTools_ListOfShape& theLFIm1,
|
|
const TopTools_ListOfShape& theLFIm2,
|
|
const TopTools_IndexedMapOfShape& theME,
|
|
const TopTools_DataMapOfShapeListOfShape& theOrigins,
|
|
TopTools_ListOfShape& theLEOr)
|
|
{
|
|
Standard_Integer i;
|
|
TopTools_MapOfShape aMFence;
|
|
TopExp_Explorer aExp;
|
|
TopTools_ListIteratorOfListOfShape aIt, aItLE;
|
|
//
|
|
for (i = 0; i < 2; ++i) {
|
|
const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2;
|
|
aIt.Initialize(aLF);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF = aIt.Value();
|
|
//
|
|
aExp.Init(aF, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
//
|
|
if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
|
|
const TopTools_ListOfShape& aLEOr = theOrigins.Find(aE);
|
|
aItLE.Initialize(aLEOr);
|
|
for (; aItLE.More(); aItLE.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLE.Value();
|
|
//
|
|
if (aMFence.Add(aEOr) && (aEOr.ShapeType() == TopAbs_EDGE)) {
|
|
theLEOr.Append(aEOr);
|
|
}
|
|
} // for (; aItLE.More(); aItLE.Next()) {
|
|
} // if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
|
|
} // aExp.Init(aF, TopAbs_EDGE);
|
|
} // for (; aIt.More(); aIt.Next()) {
|
|
} // for (i = 0; i < 2; ++i) {
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IntersectAndTrimEdges
|
|
//purpose : Intersection of the new intersection edges among themselves
|
|
//=======================================================================
|
|
void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
|
|
const TopTools_IndexedMapOfShape& theMFInt,
|
|
const TopTools_IndexedMapOfShape& theMEInt,
|
|
const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
|
|
const TopTools_IndexedMapOfShape& theMSInv,
|
|
const TopTools_IndexedMapOfShape& theMVE,
|
|
const TopTools_MapOfShape& theVertsToAvoid,
|
|
const TopTools_MapOfShape& theNewVertsToAvoid,
|
|
const TopTools_MapOfShape& theMECheckExt,
|
|
TopTools_MapOfShape& theMVBounds,
|
|
TopTools_DataMapOfShapeListOfShape& theEImages)
|
|
{
|
|
Standard_Integer i, aNb = theMEInt.Extent();
|
|
if (!aNb) {
|
|
return;
|
|
}
|
|
//
|
|
BOPCol_ListOfShape aLArgs;
|
|
TopTools_MapOfShape aMFence;
|
|
TopTools_ListIteratorOfListOfShape aIt, aIt1;
|
|
TopExp_Explorer aExp;
|
|
//
|
|
// get vertices from the splits of intersected faces.
|
|
// vertices are taken from the edges close to invalidity
|
|
//
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
|
|
aNb = theMFInt.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aF = theMFInt(i);
|
|
const TopTools_ListOfShape& aLE = theFToRebuild.FindFromKey(aF);
|
|
//
|
|
aIt.Initialize(aLE);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
|
|
//
|
|
aExp.Init(aE, TopAbs_VERTEX);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aV1 = aExp.Current();
|
|
if (!theVertsToAvoid.Contains(aV1) && theMVE.Contains(aV1) && aMFence.Add(aV1)) {
|
|
aLArgs.Append(aV1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aNb = theMSInv.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aV = theMSInv(i);
|
|
if (aV.ShapeType() != TopAbs_VERTEX) {
|
|
continue;
|
|
}
|
|
//
|
|
TopTools_ListOfShape *pLVE = aDMVE.ChangeSeek(aV);
|
|
if (!pLVE) {
|
|
continue;
|
|
}
|
|
//
|
|
aIt.Initialize(*pLVE);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
//
|
|
aExp.Init(aE, TopAbs_VERTEX);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Shape& aV1 = aExp.Current();
|
|
if (!theVertsToAvoid.Contains(aV1) && aMFence.Add(aV1)) {
|
|
aLArgs.Append(aV1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// bounding vertices of untrimmed edges
|
|
TopTools_ListOfShape aLVBounds;
|
|
// new intersection edges
|
|
TopTools_ListOfShape aLENew;
|
|
// get edges to intersect
|
|
TopTools_ListOfShape aLEInt;
|
|
// Common intersection edges. Should be intersected separetely
|
|
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_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_ListOfShape aLENew;
|
|
TopTools_MapOfShape aMENew;
|
|
// map of old vertices
|
|
TopTools_MapOfShape aMVOld;
|
|
// back connection to untrimmed edges
|
|
TopTools_DataMapOfShapeListOfShape aDMEOr;
|
|
//
|
|
// trim the new intersection edges
|
|
BOPCol_ListOfShape aLA;
|
|
TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt, theEImages,
|
|
aMEB, aMVOld, aLENew, aLA, aDMEOr, aMELF);
|
|
//
|
|
if (aLA.IsEmpty()) {
|
|
// update intersection edges
|
|
UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
|
|
theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
|
|
return;
|
|
}
|
|
//
|
|
TopoDS_Shape aSplits1;
|
|
if (aLA.Extent() > 1) {
|
|
// intersect the new splits among themselves to avoid self-intersections
|
|
IntersectEdges(aLA, aLE, aLENew, theMVBounds, theVertsToAvoid, theMECheckExt,
|
|
theEImages, theModifiedEdges, aDMEOr, aMELF, aMENew, aSplits1);
|
|
}
|
|
else {
|
|
aSplits1 = aLA.First();
|
|
}
|
|
//
|
|
// filter the new splits with bounds
|
|
TopoDS_Shape aFilterBounds;
|
|
GetBounds(theFImages, aMEB, aFilterBounds);
|
|
//
|
|
// intersect splits and bounds and remove those splits which have pure E/E intersection
|
|
TopTools_MapOfShape aMEInv;
|
|
GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids,
|
|
theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
|
|
theMECheckExt, theMEInvOnArt, theVertsToAvoid, aMEInv);
|
|
//
|
|
// get valid edges only
|
|
TopoDS_Shape aSplits;
|
|
if (aMEInv.Extent()) {
|
|
// clear images from found invalid edges
|
|
TopoDS_Compound aSp;
|
|
BRep_Builder().MakeCompound(aSp);
|
|
TopTools_MapOfShape aMFence;
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLE(aLE);
|
|
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 (aMEInv.Contains(aEIm)) {
|
|
pLEIm->Remove(aItLEIm);
|
|
}
|
|
else {
|
|
if (aMFence.Add(aEIm)) {
|
|
BRep_Builder().Add(aSp, aEIm);
|
|
}
|
|
aItLEIm.Next();
|
|
}
|
|
}
|
|
//
|
|
if (pLEIm->IsEmpty()) {
|
|
theEImages.UnBind(aE);
|
|
}
|
|
}
|
|
aSplits = aSp;
|
|
}
|
|
else {
|
|
aSplits = aSplits1;
|
|
}
|
|
//
|
|
// get bounds to update
|
|
// we need to update the edges of all the affected faces
|
|
TopTools_ListOfShape aLF;
|
|
// prepare the vertices from new splits of edges
|
|
TopTools_IndexedMapOfShape aMVSp;
|
|
TopExp::MapShapes(aSplits, TopAbs_VERTEX, aMVSp);
|
|
//
|
|
Standard_Integer aNbF = theFImages.Extent();
|
|
for (i = 1; i <= aNbF; ++i) {
|
|
const TopoDS_Shape& aF = theFImages.FindKey(i);
|
|
if (theFLE.Contains(aF)) {
|
|
aLF.Append(aF);
|
|
continue;
|
|
}
|
|
//
|
|
// check the splits of faces to have vertices from splits
|
|
const TopTools_ListOfShape& aLFIm = theFImages(i);
|
|
TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
|
|
for (; aItLFIm.More(); aItLFIm.Next()) {
|
|
const TopoDS_Shape& aFIm = aItLFIm.Value();
|
|
//
|
|
TopExp_Explorer aExpV(aFIm, TopAbs_VERTEX);
|
|
for (; aExpV.More(); aExpV.Next()) {
|
|
const TopoDS_Shape& aV = aExpV.Current();
|
|
if (aMVSp.Contains(aV)) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (aExpV.More()) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (aItLFIm.More()) {
|
|
aLF.Append(aF);
|
|
}
|
|
}
|
|
//
|
|
// get bounds from splits of faces of aLF
|
|
TopoDS_Shape aBounds;
|
|
TopTools_ListOfShape aLAValid, aLABounds;
|
|
GetBoundsToUpdate(aLF, theOEImages, theOEOrigins, aMEB,
|
|
aLABounds, aLAValid, aBounds, theAsDes);
|
|
//
|
|
// intersect valid splits with bounds and update both
|
|
BOPAlgo_Builder aGF;
|
|
// The order is important here, because we need to keep the
|
|
// unmodified edges from the Bounds in the resulting maps.
|
|
// In case of total coincidence of the edges with the same vertices
|
|
// the edges in the common block will not be split and no new
|
|
// edges will be created and the first pave block
|
|
// will be used as a real pave block.
|
|
aGF.AddArgument(aBounds);
|
|
aGF.AddArgument(aSplits);
|
|
aGF.Perform();
|
|
//
|
|
// update splits
|
|
UpdateImages(aLE, theEImages, aGF, theModifiedEdges);
|
|
//
|
|
// update new intersection edges
|
|
UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
|
|
theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
|
|
//
|
|
// update bounds
|
|
UpdateImages(aLAValid, theOEImages, aGF, theModifiedEdges);
|
|
UpdateOrigins(aLABounds, theOEOrigins, aGF);
|
|
UpdateOrigins(aLABounds, theEdgesOrigins, aGF);
|
|
UpdateIntersectedEdges(aLABounds, theETrimEInf, aGF);
|
|
//
|
|
// update the EdgesToAvoid with the splits
|
|
TopTools_IndexedMapOfShape aNewEdges;
|
|
const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek(aSplits);
|
|
if (pSplitsIm) {
|
|
TopTools_ListIteratorOfListOfShape aItSpIm(*pSplitsIm);
|
|
for (; aItSpIm.More(); aItSpIm.Next()) {
|
|
TopExp::MapShapes(aItSpIm.Value(), TopAbs_EDGE, aNewEdges);
|
|
}
|
|
}
|
|
//
|
|
Standard_Integer aNbE = theEdgesToAvoid.Extent();
|
|
for (i = 1; i <= aNbE; ++i) {
|
|
const TopoDS_Shape& aE = theEdgesToAvoid(i);
|
|
const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLEIm.Value();
|
|
if (!aNewEdges.Contains(aEIm)) {
|
|
theEdgesToAvoid.Add(aEIm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : TrimNewIntersectionEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
|
|
const TopTools_DataMapOfShapeListOfShape& theEETrim,
|
|
const TopTools_MapOfShape& theMVBounds,
|
|
TopTools_MapOfShape& theMECheckExt,
|
|
TopTools_DataMapOfShapeListOfShape& theEImages,
|
|
TopTools_MapOfShape& theMEB,
|
|
TopTools_MapOfShape& theMVOld,
|
|
TopTools_ListOfShape& theLENew,
|
|
BOPCol_ListOfShape& theLA,
|
|
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()) {
|
|
theLA.Append(aEIm);
|
|
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) {
|
|
theLENew.Append(aEIm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IntersectEdges
|
|
//purpose : Intersecting the trimmed edges to avoid self-intersections
|
|
//=======================================================================
|
|
void IntersectEdges(const BOPCol_ListOfShape& theLA,
|
|
const TopTools_ListOfShape& theLE,
|
|
const TopTools_ListOfShape& theLENew,
|
|
const TopTools_MapOfShape& theMVBounds,
|
|
const TopTools_MapOfShape& theVertsToAvoid,
|
|
TopTools_MapOfShape& theMECheckExt,
|
|
TopTools_DataMapOfShapeListOfShape& theEImages,
|
|
TopTools_MapOfShape& theModifiedEdges,
|
|
TopTools_DataMapOfShapeListOfShape& theDMEOr,
|
|
TopTools_DataMapOfShapeListOfShape& theMELF,
|
|
TopTools_MapOfShape& theMENew,
|
|
TopoDS_Shape& theSplits)
|
|
{
|
|
BOPAlgo_Builder aGFA;
|
|
aGFA.SetArguments(theLA);
|
|
aGFA.Perform();
|
|
if (aGFA.HasErrors()) {
|
|
// just copy input to the result
|
|
TopoDS_Compound aSp;
|
|
BRep_Builder aBB;
|
|
aBB.MakeCompound(aSp);
|
|
BOPCol_ListIteratorOfListOfShape anIt(theLA);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const TopoDS_Shape& aE = anIt.Value();
|
|
aBB.Add(aSp, aE);
|
|
}
|
|
theSplits = aSp;
|
|
return;
|
|
}
|
|
//
|
|
UpdateImages(theLE, theEImages, aGFA, theModifiedEdges);
|
|
//
|
|
// compound of valid splits
|
|
theSplits = aGFA.Shape();
|
|
//
|
|
// update new edges
|
|
TopTools_ListIteratorOfListOfShape aIt, aIt1;
|
|
aIt.Initialize(theLENew);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
|
|
if (aLEIm.Extent()) {
|
|
aIt1.Initialize(aLEIm);
|
|
for (; aIt1.More(); aIt1.Next()) {
|
|
const TopoDS_Shape& aEIm = aIt1.Value();
|
|
theMENew.Add(aEIm);
|
|
}
|
|
}
|
|
else {
|
|
theMENew.Add(aE);
|
|
}
|
|
}
|
|
//
|
|
// update edges after intersection for extended checking
|
|
aIt.Initialize(theLA);
|
|
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;
|
|
}
|
|
//
|
|
UpdateOrigins(theLA, theDMEOr, aGFA);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetBounds
|
|
//purpose : Getting edges from the splits of offset faces
|
|
//=======================================================================
|
|
void GetBounds(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
|
|
const TopTools_MapOfShape& theMEB,
|
|
TopoDS_Shape& theBounds)
|
|
{
|
|
// make compound of edges contained in the splits of faces
|
|
TopoDS_Compound aBounds;
|
|
BRep_Builder aBB;
|
|
aBB.MakeCompound(aBounds);
|
|
//
|
|
TopTools_MapOfShape aMFence;
|
|
//
|
|
Standard_Integer i, aNb = theFImages.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopTools_ListOfShape& aLFIm = theFImages(i);
|
|
TopTools_ListIteratorOfListOfShape aIt(aLFIm);
|
|
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,
|
|
TopTools_MapOfShape& theVertsToAvoid,
|
|
TopTools_MapOfShape& theMEInv)
|
|
{
|
|
// map splits to check the vertices of edges
|
|
TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
|
|
TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
|
|
//
|
|
BOPAlgo_Section aSec;
|
|
aSec.AddArgument(theSplits);
|
|
aSec.AddArgument(theBounds);
|
|
//
|
|
aSec.Perform();
|
|
//
|
|
// invalid vertices
|
|
TopTools_IndexedMapOfShape aMVInv;
|
|
// vertices to check additionally by classification relatively to solid
|
|
TopTools_MapOfShape aMVCheckAdd;
|
|
// collect parts for removal
|
|
const BOPDS_PDS& pDS = aSec.PDS();
|
|
//
|
|
// check edge/edge intersections
|
|
const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
|
|
Standard_Integer i, aNb = aEEs.Extent();
|
|
for (i = 0; i < aNb; ++i) {
|
|
const BOPDS_InterfEE& aEE = aEEs(i);
|
|
//
|
|
const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1());
|
|
const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2());
|
|
//
|
|
if (!aEE.HasIndexNew()) {
|
|
if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) {
|
|
theMEInv.Add(aE1);
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
if (theInvEdges.Contains(aE2)) {
|
|
theMEInv.Add(aE1);
|
|
}
|
|
//
|
|
if (theMEInvOnArt.Contains(aE2)) {
|
|
// avoid checking of the vertices of the split edge intersected by
|
|
// the invalid edge from artificial face
|
|
TopoDS_Vertex aV1, aV2;
|
|
TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2);
|
|
if (aDMVE.Contains(aV1) && aDMVE.Contains(aV2)) {
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
// add vertices of all images of the edge from splits for checking
|
|
const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1);
|
|
TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr);
|
|
for (; aItLEOr.More(); aItLEOr.Next()) {
|
|
const TopoDS_Shape& aEOr = aItLEOr.Value();
|
|
//
|
|
const TopTools_ListOfShape& aLEIm = theEImages.Find(aEOr);
|
|
TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLEIm.Value();
|
|
//
|
|
TopoDS_Iterator aItV(aEIm);
|
|
for (; aItV.More(); aItV.Next()) {
|
|
const TopoDS_Shape& aV = aItV.Value();
|
|
if (!theMVOld.Contains(aV)) {
|
|
aMVInv.Add(aV);
|
|
aMVCheckAdd.Add(aV);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// to avoid unnecessary filling of parts due to extra trim of the edges
|
|
// process Edge/Edge interferences of type EDGE, i.e. common blocks and check
|
|
// not the bounding vertices of the edges, but check the edge itself
|
|
// to be lying on some face
|
|
//
|
|
// all common blocks are contained in the result of SECTION operation
|
|
// between sets of edges
|
|
const TopoDS_Shape& aSecR = aSec.Shape();
|
|
//
|
|
TopTools_IndexedMapOfShape aMSSec;
|
|
TopExp::MapShapes(aSecR, aMSSec);
|
|
//
|
|
const BOPCol_DataMapOfShapeListOfShape& anIm = aSec.Images();
|
|
for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
|
|
{
|
|
const TopoDS_Shape& aE = aExp.Current();
|
|
if (aSec.IsDeleted(aE)) {
|
|
// no common blocks for this edge
|
|
continue;
|
|
}
|
|
//
|
|
const BOPCol_ListOfShape* pLEIm = anIm.Seek(aE);
|
|
if (!pLEIm) {
|
|
// no splits, i.e. completely coincides with some edge from boundary
|
|
continue;
|
|
}
|
|
//
|
|
BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm);
|
|
for (; aItLEIm.More(); aItLEIm.Next()) {
|
|
const TopoDS_Shape& aEIm = aItLEIm.Value();
|
|
if (!aMSSec.Contains(aEIm)) {
|
|
// the edge included in section only partially.
|
|
// the part not included in section may be excessive
|
|
//
|
|
// check vertices of this edge - if one of them is new
|
|
// the edge might be removed
|
|
TopoDS_Vertex aV1, aV2;
|
|
TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2);
|
|
if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) {
|
|
// add this edge for checking by making new vertex in the middle of the edge
|
|
TopoDS_Vertex aV;
|
|
Standard_Real f, l;
|
|
const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l);
|
|
BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion());
|
|
// and adding this vertex for checking
|
|
aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
|
|
aMVInv.Add(aV);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Add for check also the edges created from common between splits
|
|
// of offset faces edges not connected to any invalidity.
|
|
// These edges may also accidentally fill some part.
|
|
TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt);
|
|
for (; aItM.More(); aItM.Next()) {
|
|
const TopoDS_Shape& aE = aItM.Value();
|
|
//
|
|
// make new vertex in the middle of the edge
|
|
TopoDS_Vertex aV;
|
|
Standard_Real f, l;
|
|
const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l);
|
|
BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion());
|
|
// add this vertex for checking
|
|
aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
|
|
aMVInv.Add(aV);
|
|
}
|
|
//
|
|
// add for check also the vertices connected only to new or old edges
|
|
aNb = aDMVE.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Shape& aV = aDMVE.FindKey(i);
|
|
if (theMVOld.Contains(aV)) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bNew = Standard_False, bOld = Standard_False;
|
|
const TopTools_ListOfShape& aLEx = aDMVE(i);
|
|
TopTools_ListIteratorOfListOfShape aIt(aLEx);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
if (theMECheckExt.Contains(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (theMENew.Contains(aE)) {
|
|
bNew = Standard_True;
|
|
}
|
|
else {
|
|
bOld = Standard_True;
|
|
}
|
|
//
|
|
if (bNew && bOld) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (!bNew || !bOld) {
|
|
aMVInv.Add(aV);
|
|
aMVCheckAdd.Remove(aV);
|
|
}
|
|
}
|
|
//
|
|
// perform the checking
|
|
Handle(IntTools_Context) aCtx = new IntTools_Context;
|
|
// filter 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 = aCtx->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 = !aCtx->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 = aCtx->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 : 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);
|
|
}
|