0032088: Modeling Algorithms - Empty result of offset operation in mode "Complete...
[occt.git] / src / BRepOffset / BRepOffset_MakeOffset_1.cxx
CommitLineData
ecf4f17c 1// Created on: 2016
2// Created by: Eugeny MALTCHIKOV
3// Copyright (c) 2016 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16
17// This is the implementation of the extension of the 3D offset algorithm
18// to work in mode Complete and Join Type Intersection.
19// Currently only the Planar cases are supported.
20
21
22#include <BRepOffset_MakeOffset.hxx>
23
24#include <Precision.hxx>
25#include <TopoDS.hxx>
26
27#include <BRepAlgo_AsDes.hxx>
28#include <BRepAlgo_Image.hxx>
29
30#include <BRep_Builder.hxx>
31#include <BRep_Tool.hxx>
32
f16a6cc5 33#include <BRepLib.hxx>
ecf4f17c 34#include <BRepTools.hxx>
35
36#include <BRepAdaptor_Curve.hxx>
37
38#include <TopExp.hxx>
39#include <TopExp_Explorer.hxx>
40
41#include <TopTools_DataMapOfShapeInteger.hxx>
42
43#include <BRepOffset_Tool.hxx>
44
45#include <BRepClass3d_SolidClassifier.hxx>
46
47#include <BOPDS_DS.hxx>
48
49#include <BOPAlgo_PaveFiller.hxx>
50#include <BOPAlgo_Builder.hxx>
51#include <BOPAlgo_Section.hxx>
52#include <BOPAlgo_MakerVolume.hxx>
a8232603 53#include <BOPAlgo_BuilderFace.hxx>
ecf4f17c 54
1155d05a 55#include <TopTools_ListOfShape.hxx>
56#include <TopTools_DataMapOfShapeShape.hxx>
57#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
2ebb1098 58#include <TopTools_MapOfOrientedShape.hxx>
ecf4f17c 59
ecf4f17c 60#include <BOPTools_AlgoTools3D.hxx>
61#include <BOPTools_AlgoTools.hxx>
a8232603 62#include <BOPTools_AlgoTools2D.hxx>
bea10656 63#include <BOPTools_Set.hxx>
ecf4f17c 64
65#include <IntTools_Context.hxx>
66#include <IntTools_ShrunkRange.hxx>
67
bc4a3867 68#ifdef OFFSET_DEBUG
69#include <BRepAlgoAPI_Check.hxx>
70#endif
71
baaacd46 72typedef NCollection_DataMap
73 <TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeMapOfShape;
9e9b826a 74typedef NCollection_DataMap
75 <TopoDS_Shape, TopTools_IndexedMapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeIndexedMapOfShape;
ecf4f17c 76
77static
78 void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
79 const Handle(BRepAlgo_AsDes)& theAsDes,
80 TopTools_DataMapOfShapeListOfShape& theOEImages,
81 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
82 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
83 Handle(IntTools_Context)& theCtx,
84 TopTools_MapOfShape& theNewEdges,
85 TopTools_DataMapOfShapeShape& theETrimEInf);
86
87static
88 Standard_Boolean GetEdges(const TopoDS_Face& theFace,
89 const Handle(BRepAlgo_AsDes)& theAsDes,
90 const TopTools_DataMapOfShapeListOfShape& theEImages,
91 const TopTools_MapOfShape& theLastInvEdges,
92 const TopTools_IndexedMapOfShape& theInvEdges,
93 Handle(IntTools_Context)& theCtx,
94 const TopTools_MapOfShape& theModifiedEdges,
95 TopoDS_Shape& theEdges,
96 TopTools_IndexedMapOfShape& theInv);
97
a8232603 98static
99 void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
100 const TopoDS_Shape& theEdges,
101 TopTools_ListOfShape& theLFImages);
102
ecf4f17c 103static
104 void BuildSplitsOfFace(const TopoDS_Face& theFace,
105 const TopoDS_Shape& theEdges,
ecf4f17c 106 TopTools_DataMapOfShapeShape& theOrigins,
107 TopTools_ListOfShape& theLFImages);
108
6f04cbb1 109//! Auxiliary structure to contain intersection information
110struct BRepOffset_MakeOffset_InterResults
111{
112 TopTools_DataMapOfShapeListOfShape SSInterfs; //!< Intersection information, used to add pair for intersection
113 NCollection_DataMap <TopoDS_Shape,
114 BRepOffset_DataMapOfShapeMapOfShape,
115 TopTools_ShapeMapHasher> InterPairs; //!< All possible intersection pairs, used to avoid
116 //! some of the intersection
117};
118
ecf4f17c 119static
120 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
121 const TopTools_MapOfShape& theModifiedEdges,
122 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
420b38fd 123 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 124 Handle(BRepAlgo_AsDes)& theAsDes,
125 TopTools_DataMapOfShapeShape& theFacesOrigins,
126 TopTools_DataMapOfShapeListOfShape& theOEImages,
127 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
128 TopTools_MapOfShape& theLastInvEdges,
129 TopTools_IndexedMapOfShape& theEdgesToAvoid,
130 TopTools_IndexedMapOfShape& theInvEdges,
131 TopTools_IndexedMapOfShape& theValidEdges,
132 TopTools_MapOfShape& theInvertedEdges,
133 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
134 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
135 TopTools_DataMapOfShapeShape& theArtInvFaces,
136 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 137 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 138 TopoDS_Shape& theSolids,
6f04cbb1 139 BRepOffset_MakeOffset_InterResults& theIntRes);
ecf4f17c 140
141static
142 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
143 const TopTools_MapOfShape& theModifiedEdges,
bea10656 144 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 145 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 146 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 147 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
148 TopTools_DataMapOfShapeShape& theFacesOrigins,
149 TopTools_DataMapOfShapeListOfShape& theOEImages,
150 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
151 TopTools_MapOfShape& theLastInvEdges,
152 TopTools_IndexedMapOfShape& theEdgesToAvoid,
153 TopTools_MapOfShape& theVertsToAvoid,
154 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
155 TopTools_IndexedMapOfShape& theValidEdges,
156 TopTools_DataMapOfShapeShape& theETrimEInf,
157 Handle(BRepAlgo_AsDes)& theAsDes);
158
159static
160 Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
161 const TopTools_ListOfShape& theLFImages,
162 const TopoDS_Shape& theCE,
163 const TopTools_IndexedMapOfShape& theMapEInv,
164 const TopTools_DataMapOfShapeListOfShape& theOEImages,
165 TopTools_MapOfShape& theMENInv,
166 Handle(BRepAlgo_AsDes)& theAsDes);
167
168static
169 void FindInvalidEdges(const TopoDS_Face& theF,
170 const TopTools_ListOfShape& theLFImages,
171 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
172 const TopTools_DataMapOfShapeShape& theFacesOrigins,
420b38fd 173 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 174 const TopTools_DataMapOfShapeListOfShape& theOEImages,
175 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
176 TopTools_IndexedMapOfShape& theInvEdges,
177 TopTools_IndexedMapOfShape& theValidEdges,
9e9b826a 178 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
179 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
180 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
181 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
0da0275c 182 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
ecf4f17c 183 TopTools_MapOfShape& theMEInverted,
9e9b826a 184 TopTools_MapOfShape& theEdgesInvalidByVertex,
185 TopTools_MapOfShape& theEdgesValidByVertex);
ecf4f17c 186
bea10656 187static
188 void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
189 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
190 const TopTools_DataMapOfShapeShape& theFacesOrigins,
191 const BRepOffset_Analyse* theAnalyse,
192 const TopTools_IndexedMapOfShape& theInvEdges,
193 const TopTools_IndexedMapOfShape& theValidEdges,
194 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
195 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
196 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges);
197
62eafa5a 198static
199 void MakeInvertedEdgesInvalid(const TopTools_ListOfShape& theLFOffset,
200 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
201 const TopTools_MapOfShape& theInvertedEdges,
202 TopTools_IndexedMapOfShape& theInvEdges);
203
ecf4f17c 204static
205 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
206 const TopTools_IndexedMapOfShape& theInvEdges,
207 const TopTools_IndexedMapOfShape& theValidEdges,
9e9b826a 208 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
209 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
210 const TopTools_MapOfShape& theLENeutral,
ecf4f17c 211 const TopTools_MapOfShape& theMEInverted,
212 const TopTools_MapOfShape& theEdgesInvalidByVertex,
9e9b826a 213 const TopTools_MapOfShape& theEdgesValidByVertex,
0da0275c 214 const TopTools_MapOfShape& theMFHoles,
215 TopTools_IndexedMapOfShape& theMFInvInHole,
e08a9b03 216 TopTools_ListOfShape& theInvFaces,
217 TopTools_ListOfShape& theInvertedFaces);
ecf4f17c 218
0da0275c 219static
220 void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
221 const TopoDS_Face& theFOffset,
222 const TopTools_ListOfShape& theLFImages,
223 const TopTools_MapOfShape& theInvertedEdges,
224 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
2ebb1098 225 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
0da0275c 226 TopTools_MapOfShape& theMFHoles,
227 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
228 Handle(IntTools_Context)& theContext);
229
ecf4f17c 230static
231 gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
232 const Standard_Integer theNbP);
233
234static
235 Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
236 const TopoDS_Face& theFOr,
237 const TopTools_DataMapOfShapeListOfShape& theOEImages,
238 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
239 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
ecf4f17c 240 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
241 const TopTools_IndexedMapOfShape& theMEdges,
242 TopTools_MapOfShape& theMEInverted);
243
baaacd46 244static
245 Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
246 const TopTools_ListOfShape& theLCBF,
247 const TopTools_MapOfShape& theMEInverted,
248 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
249 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
250 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll);
251
252static
253 void GetVerticesOnEdges(const TopoDS_Shape& theCB,
254 const TopTools_MapOfShape& theEdges,
255 TopTools_MapOfShape& theVerticesOnEdges,
256 TopTools_MapOfShape& theAllVertices);
ecf4f17c 257
258static
259 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
baaacd46 260 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
ecf4f17c 261 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
262 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
263 TopTools_IndexedMapOfShape& theMERemoved);
264
265static
266 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
267 const TopTools_DataMapOfShapeShape& theArtInvFaces,
268 const TopTools_MapOfShape& theMEInverted,
9e9b826a 269 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
ecf4f17c 270 TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
271
272static
273 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
274 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
275 const TopTools_DataMapOfShapeShape& theArtInvFaces,
276 const TopTools_IndexedMapOfShape& theInvEdges,
e08a9b03 277 const TopTools_MapOfShape& theInvertedEdges,
278 const TopTools_ListOfShape& theInvertedFaces,
ecf4f17c 279 const TopTools_IndexedMapOfShape& theMFToCheckInt,
0da0275c 280 const TopTools_IndexedMapOfShape& theMFInvInHole,
281 const TopoDS_Shape& theFHoles,
6f04cbb1 282 BRepOffset_MakeOffset_InterResults& theIntRes,
ecf4f17c 283 TopTools_IndexedMapOfShape& theMERemoved,
baaacd46 284 TopTools_IndexedMapOfShape& theMEInside,
ecf4f17c 285 TopoDS_Shape& theSolids);
286
287static
288 void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
289 const TopTools_IndexedMapOfShape& theInvEdges,
290 const TopTools_DataMapOfShapeShape& theDMFOr,
291 BOPAlgo_Builder& theBuilder,
292 TopTools_DataMapOfShapeListOfShape& theSSInterfs);
293
bc4a3867 294static
295 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
296 const TopTools_DataMapOfShapeShape& theDMFImF,
297 const TopTools_IndexedMapOfShape& theMFInv,
298 const TopTools_IndexedMapOfShape& theInvEdges,
e08a9b03 299 const TopTools_MapOfShape& theInvertedEdges,
bc4a3867 300 TopTools_MapOfShape& theMFToRem);
301
ecf4f17c 302static
303 void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
304 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
305 BOPAlgo_Builder& theGF,
306 TopTools_IndexedMapOfShape& theMERemoved);
307
308static
309 void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
310 const TopTools_DataMapOfShapeShape& theArtInvFaces,
311 const TopTools_IndexedMapOfShape& theInvEdges,
312 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
313 BOPAlgo_Builder& theGF,
314 TopTools_IndexedMapOfShape& theMERemoved);
315
316static
317 void FilterEdgesImages(const TopoDS_Shape& theS,
318 TopTools_DataMapOfShapeListOfShape& theOEImages,
319 TopTools_DataMapOfShapeListOfShape& theOEOrigins);
320
321static
9e9b826a 322 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
baaacd46 323 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
9e9b826a 324 const TopTools_IndexedMapOfShape& theInvEdges,
baaacd46 325 const TopTools_IndexedMapOfShape& theMERemoved,
ecf4f17c 326 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
327 TopTools_DataMapOfShapeShape& theArtInvFaces);
328
329static
330 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
331 const TopTools_DataMapOfShapeShape& theArtInvFaces,
9e9b826a 332 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
ecf4f17c 333 const TopTools_IndexedMapOfShape& theMERemoved,
334 TopTools_IndexedMapOfShape& theInvEdges);
335
4b59685a 336static
337 void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
338 const TopTools_DataMapOfShapeShape& theArtInvFaces,
339 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
340 const TopTools_IndexedMapOfShape& theValidEdges,
341 TopTools_IndexedMapOfShape& theInvEdges);
342
ecf4f17c 343static
344 void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
345 const TopTools_IndexedMapOfShape& theInvEdges,
346 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
347 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
348 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
349 TopTools_MapOfShape& theFSelfRebAvoid);
350
351static
352 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
353 const TopTools_MapOfShape& theFSelfRebAvoid,
354 const TopoDS_Shape& theSolids,
6f04cbb1 355 const BRepOffset_MakeOffset_InterResults& theIntRes,
bea10656 356 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 357 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 358 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 359 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
360 TopTools_DataMapOfShapeShape& theFacesOrigins,
361 TopTools_DataMapOfShapeListOfShape& theOEImages,
362 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
363 TopTools_MapOfShape& theLastInvEdges,
364 TopTools_IndexedMapOfShape& theEdgesToAvoid,
365 TopTools_IndexedMapOfShape& theInvEdges,
366 TopTools_IndexedMapOfShape& theValidEdges,
367 const TopTools_MapOfShape& theInvertedEdges,
368 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
369 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
370 const TopTools_DataMapOfShapeShape& theArtInvFaces,
371 TopTools_MapOfShape& theVertsToAvoid,
372 TopTools_DataMapOfShapeShape& theETrimEInf,
373 Handle(BRepAlgo_AsDes)& theAsDes);
374
375static
376 void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
377 const TopTools_MapOfShape& theFSelfRebAvoid,
378 const TopoDS_Shape& theSolids,
6f04cbb1 379 const BRepOffset_MakeOffset_InterResults& theIntRes,
ecf4f17c 380 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
381 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
382 TopTools_DataMapOfShapeListOfShape& theOEImages,
383 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
384 TopTools_IndexedMapOfShape& theInvEdges,
385 TopTools_IndexedMapOfShape& theValidEdges,
386 const TopTools_MapOfShape& theInvertedEdges,
387 TopTools_IndexedMapOfShape& theEdgesToAvoid,
388 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
389 const TopTools_DataMapOfShapeShape& theArtInvFaces,
390 TopTools_MapOfShape& theVertsToAvoid,
391 TopTools_DataMapOfShapeShape& theETrimEInf,
392 TopTools_MapOfShape& theModifiedEdges,
393 Handle(BRepAlgo_AsDes)& theAsDes);
394
395static
396 void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
397 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
398 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
399 const TopTools_DataMapOfShapeShape& theArtInvFaces,
400 const Standard_Boolean bLookVertToAvoid,
401 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
402 TopTools_DataMapOfShapeListOfShape& theMDone,
403 TopTools_DataMapOfShapeListOfShape& theDMSF,
404 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
405 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
406 TopTools_DataMapOfShapeShape& theETrimEInf,
407 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv);
408
409static
410 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
411 const TopTools_IndexedMapOfShape& theInvEdges,
412 const TopTools_IndexedMapOfShape& theValidEdges,
bc4a3867 413 const TopTools_MapOfShape& theInvertedEdges,
414 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
415 const TopTools_DataMapOfShapeListOfShape& theOEImages,
416 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
ecf4f17c 417 TopTools_MapOfShape& theMVRInv);
418
419static
420 void FindFacesForIntersection(const TopoDS_Shape& theFInv,
421 const TopTools_IndexedMapOfShape& theME,
422 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
423 const TopTools_DataMapOfShapeListOfShape& theDMSF,
424 const TopTools_MapOfShape& theMVInvAll,
425 const TopTools_DataMapOfShapeShape& theArtInvFaces,
426 const Standard_Boolean theArtCase,
427 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
428 TopTools_IndexedMapOfShape& theMFAvoid,
429 TopTools_IndexedMapOfShape& theMFInt,
430 TopTools_IndexedMapOfShape& theMFIntExt,
431 TopTools_ListOfShape& theLFImInt);
432
433static
434 void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
435 const TopTools_IndexedMapOfShape& theInvEdges,
436 const TopTools_IndexedMapOfShape& theValidEdges,
437 const TopTools_IndexedMapOfShape& theME,
438 const TopTools_DataMapOfShapeShape& theETrimEInf,
439 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
440 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
41aa3c3d 441 const TopTools_MapOfShape& theAllInvs,
ecf4f17c 442 const Standard_Boolean theForceUse,
443 TopTools_IndexedMapOfShape& theMECV,
41aa3c3d 444 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 445 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
446 TopTools_ListOfShape& theLFEi,
447 TopTools_ListOfShape& theLFEj,
448 TopTools_IndexedMapOfShape& theMEToInt);
449
450static
451 void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
452 const TopoDS_Shape& theFi,
453 const TopoDS_Shape& theFj,
454 const TopTools_ListOfShape& theLFInv,
455 const TopTools_ListOfShape& theLFImi,
456 const TopTools_ListOfShape& theLFImj,
457 const TopTools_ListOfShape& theLFEi,
458 const TopTools_ListOfShape& theLFEj,
459 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
460 TopTools_IndexedMapOfShape& theMEToInt);
461
462static
463 void IntersectFaces(const TopoDS_Shape& theFInv,
464 const TopoDS_Shape& theFi,
465 const TopoDS_Shape& theFj,
466 const TopTools_ListOfShape& theLFInv,
467 const TopTools_ListOfShape& theLFImi,
468 const TopTools_ListOfShape& theLFImj,
469 TopTools_ListOfShape& theLFEi,
470 TopTools_ListOfShape& theLFEj,
471 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
472 TopTools_IndexedMapOfShape& theMECV,
473 TopTools_IndexedMapOfShape& theMEToInt);
474
475static
476 void FindOrigins(const TopTools_ListOfShape& theLFIm1,
477 const TopTools_ListOfShape& theLFIm2,
478 const TopTools_IndexedMapOfShape& theME,
479 const TopTools_DataMapOfShapeListOfShape& theOrigins,
480 TopTools_ListOfShape& theLEOr);
481
482static
483 void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
484 const TopTools_IndexedMapOfShape& theMFInt,
485 const TopTools_IndexedMapOfShape& theMEInt,
486 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
487 const TopTools_IndexedMapOfShape& theMSInv,
488 const TopTools_IndexedMapOfShape& theMVE,
489 const TopTools_MapOfShape& theVertsToAvoid,
490 const TopTools_MapOfShape& theNewVertsToAvoid,
41aa3c3d 491 const TopTools_MapOfShape& theMECheckExt,
ecf4f17c 492 TopTools_MapOfShape& theMVBounds,
493 TopTools_DataMapOfShapeListOfShape& theEImages);
494
495static
496 void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
497 const TopTools_MapOfShape& theMVBounds,
498 BOPAlgo_Builder& theGF,
499 TopTools_MapOfShape& theMEInv);
500
41aa3c3d 501static
502 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
ecf4f17c 503 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
dcba2e5c 504 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
ecf4f17c 505 const TopTools_MapOfShape& theMVBounds,
506 const TopoDS_Shape& theSolids,
507 const TopTools_IndexedMapOfShape& theInvEdges,
508 const TopTools_MapOfShape& theInvertedEdges,
a8232603 509 const TopTools_MapOfShape& theMEInvOnArt,
41aa3c3d 510 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 511 TopTools_IndexedMapOfShape& theEdgesToAvoid,
512 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
513 TopTools_DataMapOfShapeListOfShape& theOEImages,
514 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
515 TopTools_MapOfShape& theVertsToAvoid,
516 TopTools_DataMapOfShapeShape& theETrimEInf,
517 TopTools_DataMapOfShapeListOfShape& theEImages,
518 TopTools_DataMapOfShapeListOfShape& theEETrim,
519 TopTools_MapOfShape& theModifiedEdges,
520 Handle(BRepAlgo_AsDes)& theAsDes);
521
522static
523 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
524 const TopTools_DataMapOfShapeListOfShape& theEETrim,
525 const TopTools_MapOfShape& theMVBounds,
41aa3c3d 526 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 527 TopTools_DataMapOfShapeListOfShape& theEImages,
528 TopTools_MapOfShape& theMEB,
529 TopTools_MapOfShape& theMVOld,
dcba2e5c 530 TopTools_MapOfShape& theMENew,
41aa3c3d 531 TopTools_DataMapOfShapeListOfShape& theDMEOr,
532 TopTools_DataMapOfShapeListOfShape& theMELF);
ecf4f17c 533
534static
1155d05a 535 void IntersectEdges(const TopTools_ListOfShape& theLA,
ecf4f17c 536 const TopTools_ListOfShape& theLE,
ecf4f17c 537 const TopTools_MapOfShape& theMVBounds,
538 const TopTools_MapOfShape& theVertsToAvoid,
dcba2e5c 539 TopTools_MapOfShape& theMENew,
41aa3c3d 540 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 541 TopTools_DataMapOfShapeListOfShape& theEImages,
542 TopTools_MapOfShape& theModifiedEdges,
543 TopTools_DataMapOfShapeListOfShape& theDMEOr,
41aa3c3d 544 TopTools_DataMapOfShapeListOfShape& theMELF,
ecf4f17c 545 TopoDS_Shape& theSplits);
546
547static
dcba2e5c 548 void GetBounds(const TopTools_ListOfShape& theLFaces,
549 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
ecf4f17c 550 const TopTools_MapOfShape& theMEB,
551 TopoDS_Shape& theBounds);
552
553static
554 void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
555 const TopTools_DataMapOfShapeListOfShape& theOEImages,
556 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
557 const TopTools_MapOfShape& theMEB,
558 TopTools_ListOfShape& theLABounds,
559 TopTools_ListOfShape& theLAValid,
560 TopoDS_Shape& theBounds,
561 Handle(BRepAlgo_AsDes)& theAsDes);
562
563static
564 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
565 const TopoDS_Shape& theBounds,
ecf4f17c 566 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
567 const TopoDS_Shape& theSolids,
568 const TopTools_IndexedMapOfShape& theInvEdges,
569 const TopTools_MapOfShape& theMVOld,
570 const TopTools_MapOfShape& theMENew,
571 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
41aa3c3d 572 const TopTools_DataMapOfShapeListOfShape& theMELF,
ecf4f17c 573 const TopTools_DataMapOfShapeListOfShape& theEImages,
41aa3c3d 574 const TopTools_MapOfShape& theMECheckExt,
a8232603 575 const TopTools_MapOfShape& theMEInvOnArt,
dcba2e5c 576 Handle(IntTools_Context)& theCtx,
ecf4f17c 577 TopTools_MapOfShape& theVertsToAvoid,
578 TopTools_MapOfShape& theMEInv);
579
dcba2e5c 580static
581 void FilterSplits(const TopTools_ListOfShape& theLE,
582 const TopTools_MapOfShape& theMEFilter,
583 const Standard_Boolean theIsInv,
584 TopTools_DataMapOfShapeListOfShape& theEImages,
585 TopoDS_Shape& theSplits);
586
ecf4f17c 587static
588 void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
589 const TopTools_DataMapOfShapeListOfShape& theMELF,
590 const TopTools_DataMapOfShapeListOfShape& theEImages,
591 const TopTools_IndexedMapOfShape& theInvEdges,
592 const TopTools_MapOfShape& theInvertedEdges,
593 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
594 TopTools_DataMapOfShapeListOfShape& theOEImages,
595 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
596 TopTools_DataMapOfShapeShape& theETrimEInf,
597 TopTools_DataMapOfShapeListOfShape& theEETrim,
598 TopTools_MapOfShape& theModifiedEdges,
599 Handle(BRepAlgo_AsDes)& theAsDes);
600
2ebb1098 601static
602 void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
603
ecf4f17c 604static
605 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
606 const TopTools_DataMapOfShapeListOfShape& theEImages,
607 BRepAlgo_Image& theImage);
608
609static
610 void UpdateOrigins(const TopTools_ListOfShape& theLA,
611 TopTools_DataMapOfShapeListOfShape& theOrigins,
612 BOPAlgo_Builder& theGF);
613
614static
615 void UpdateImages(const TopTools_ListOfShape& theLA,
616 TopTools_DataMapOfShapeListOfShape& theImages,
617 BOPAlgo_Builder& theGF,
618 TopTools_MapOfShape& theModified);
619
620static
621 void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
622 TopTools_DataMapOfShapeShape& theETrimEInf,
623 BOPAlgo_Builder& theGF);
624
625static
626 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
627 const Handle(IntTools_Context)& theCtx);
628
629static
630 void FindCommonParts(const TopTools_ListOfShape& theLS1,
631 const TopTools_ListOfShape& theLS2,
632 TopTools_ListOfShape& theLSC,
633 const TopAbs_ShapeEnum theType = TopAbs_EDGE);
634
635static
636 Standard_Integer NbPoints(const TopoDS_Edge& theE);
637
638static
639 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
640 const TopoDS_Shape& theSWhere,
420b38fd 641 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 642 TopoDS_Shape& theRes);
643
644static
645 void AppendToList(TopTools_ListOfShape& theL,
646 const TopoDS_Shape& theS);
647
e08a9b03 648template <class ContainerType, class FenceMapType>
649static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
650 const TopTools_DataMapOfShapeListOfShape& theImages,
651 ContainerType& theMapOut,
652 FenceMapType* theMFence);
653
654template <class ContainerType>
655static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
656 const TopTools_DataMapOfShapeListOfShape& theImages,
657 ContainerType& theMapOut)
658{
659 TopTools_MapOfShape* aDummy = NULL;
660 return TakeModified (theS, theImages, theMapOut, aDummy);
661}
662
ecf4f17c 663//=======================================================================
664//function : BuildSplitsOfTrimmedFaces
665//purpose : Building splits of already trimmed faces
666//=======================================================================
667void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF,
668 Handle(BRepAlgo_AsDes)& theAsDes,
669 BRepAlgo_Image& theImage)
670{
671 TopTools_DataMapOfShapeListOfShape anEImages, anEOrigins;
672 TopTools_IndexedDataMapOfShapeListOfShape aDMFFIm;
673 TopTools_IndexedMapOfShape anEmptyIM;
674 TopTools_DataMapOfShapeListOfShape anEmptyDMSLS;
675 TopTools_DataMapOfShapeShape anEmptyDMSS;
676 TopTools_MapOfShape aNewEdges, anEmptyM;
677 //
678 // firstly it is necessary to fuse all the edges
679 Handle(IntTools_Context) aCtx = new IntTools_Context();
680 //
681 IntersectTrimmedEdges(theLF, theAsDes, anEImages, anEOrigins, anEmptyDMSLS, aCtx, aNewEdges, anEmptyDMSS);
682 //
683 TopTools_ListIteratorOfListOfShape aItLF(theLF);
684 for (; aItLF.More(); aItLF.Next()) {
685 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
686 //
687 TopoDS_Shape aCE;
688 TopTools_ListOfShape aLFImages;
689 //
690 Standard_Boolean bFound = GetEdges(aF, theAsDes, anEImages, anEmptyM,
691 anEmptyIM, aCtx, aNewEdges, aCE, anEmptyIM);
692 // split the face by the edges
693 if (!bFound) {
694 if (!theImage.HasImage(aF)) {
695 aLFImages.Append(aF);
696 aDMFFIm.Add(aF, aLFImages);
697 }
698 continue;
699 }
700 //
a8232603 701 BuildSplitsOfTrimmedFace(aF, aCE, aLFImages);
ecf4f17c 702 aDMFFIm.Add(aF, aLFImages);
703 }
704 // Fill history for faces and edges
705 FillHistory(aDMFFIm, anEImages, theImage);
706}
707
708//=======================================================================
709//function : BuildSplitsOfExtendedFaces
710//purpose : Building splits of not-trimmed offset faces.
711// For the cases in which invalidity will be found,
712// these invalidities will be rebuilt.
713//=======================================================================
714void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
420b38fd 715 const BRepOffset_Analyse& theAnalyse,
ecf4f17c 716 Handle(BRepAlgo_AsDes)& theAsDes,
717 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
718 TopTools_DataMapOfShapeShape& theFacesOrigins,
719 TopTools_DataMapOfShapeShape& theETrimEInf,
720 BRepAlgo_Image& theImage)
721{
722 Handle(IntTools_Context) aCtx = new IntTools_Context();
723 // images and origins for offset edges
724 TopTools_DataMapOfShapeListOfShape anOEImages, anOEOrigins;
725 TopTools_MapOfShape aNewEdges;
726 // fusing all trimmed offset edges to avoid self-intersections in the splits
727 IntersectTrimmedEdges(theLF, theAsDes, anOEImages, anOEOrigins,
728 theEdgesOrigins, aCtx, aNewEdges, theETrimEInf);
729 //
730 // valid/invalid edges
731 TopTools_IndexedMapOfShape anInvEdges, aValidEdges, anEdgesToAvoid;
732 // inverted edges
733 TopTools_MapOfShape anInvertedEdges;
734 // splits of faces
735 TopTools_IndexedDataMapOfShapeListOfShape aFImages;
736 // found invalid faces
737 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
738 // artificially invalid faces - it will be empty here,
739 // but may be filled on the following rebuilding steps
740 TopTools_DataMapOfShapeShape anArtInvFaces;
741 // shapes connections for using in rebuilding
6f04cbb1 742 BRepOffset_MakeOffset_InterResults aIntRes;
ecf4f17c 743 // edges to avoid on second steps
744 TopTools_MapOfShape aLastInvEdges;
745 // keep information of already invalid faces to avoid
746 // infinite rebuilding of the same invalid face
747 TopTools_DataMapOfShapeInteger anAlreadyInvFaces;
0da0275c 748 // images of the hole faces of the original faces
749 TopTools_DataMapOfShapeListOfShape aDMFNewHoles;
ecf4f17c 750 // solid build from the new splits
751 TopoDS_Shape aSolids;
752 // now we can split the faces
420b38fd 753 BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, &theAnalyse, theAsDes, theFacesOrigins,
ecf4f17c 754 anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges,
0da0275c 755 anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages,
6f04cbb1 756 aDMFNewHoles, aSolids, aIntRes);
ecf4f17c 757 //
758 // Find faces to rebuild
759 if (anInvFaces.Extent()) {
760 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
761 TopTools_MapOfShape aFSelfRebAvoid;
6f04cbb1 762 FindFacesToRebuild(aFImages, anInvEdges, anInvFaces, aIntRes.SSInterfs, aFToRebuild, aFSelfRebAvoid);
ecf4f17c 763 //
764 if (aFToRebuild.Extent()) {
765 // vertices to avoid
766 TopTools_MapOfShape aVAEmpty;
6f04cbb1 767 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aIntRes, &theAnalyse, aFImages, aDMFNewHoles,
0da0275c 768 theEdgesOrigins, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges,
769 anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces,
770 anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes);
ecf4f17c 771 }
772 }
2ebb1098 773
774 // Fill possible gaps in the splits of offset faces to increase possibility of
775 // creating closed volume from these splits
776 FillGaps(aFImages);
777
ecf4f17c 778 // Fill history for faces and edges
779 FillHistory(aFImages, anOEImages, theImage);
780}
781
782//=======================================================================
783//function : BuildSplitsOfInvFaces
784//purpose : Rebuilding splits of faces with new intersection edges
785//=======================================================================
786void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
787 const TopTools_MapOfShape& theModifiedEdges,
bea10656 788 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 789 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 790 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 791 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
792 TopTools_DataMapOfShapeShape& theFacesOrigins,
793 TopTools_DataMapOfShapeListOfShape& theOEImages,
794 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
795 TopTools_MapOfShape& theLastInvEdges,
796 TopTools_IndexedMapOfShape& theEdgesToAvoid,
797 TopTools_MapOfShape& theVertsToAvoid,
798 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
799 TopTools_IndexedMapOfShape& theValidEdges,
800 TopTools_DataMapOfShapeShape& theETrimEInf,
801 Handle(BRepAlgo_AsDes)& theAsDes)
802{
803 Standard_Integer aNb = theFToRebuild.Extent();
804 if (!aNb) {
805 return;
806 }
807 //
808 TopTools_ListOfShape aLF;
809 aNb = theFImages.Extent();
810 for (Standard_Integer i = 1; i <= aNb; ++i) {
811 const TopoDS_Shape& aF = theFImages.FindKey(i);
812 aLF.Append(aF);
813 }
814 //
815 // invalid faces
816 TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
817 // artificially invalid faces
818 TopTools_DataMapOfShapeShape anArtInvFaces;
819 // invalid edges
820 TopTools_IndexedMapOfShape anInvEdges;
821 // inverted edges
822 TopTools_MapOfShape anInvertedEdges;
823 // shapes connection for using in rebuilding process
6f04cbb1 824 BRepOffset_MakeOffset_InterResults aIntRes;
ecf4f17c 825 //
826 TopoDS_Shape aSolids;
827 //
bea10656 828 BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAnalyse, theAsDes, theFacesOrigins,
ecf4f17c 829 theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges,
0da0275c 830 anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages,
6f04cbb1 831 theDMFNewHoles, aSolids, aIntRes);
ecf4f17c 832 //
833 if (anInvFaces.Extent()) {
834 TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
835 TopTools_MapOfShape aFSelfRebAvoid;
6f04cbb1 836 FindFacesToRebuild(theFImages, anInvEdges, anInvFaces, aIntRes.SSInterfs, aFToRebuild, aFSelfRebAvoid);
ecf4f17c 837 //
838 if (aFToRebuild.Extent()) {
6f04cbb1 839 RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aIntRes, theAnalyse, theFImages, theDMFNewHoles,
0da0275c 840 theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
841 theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces,
842 anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes);
ecf4f17c 843 }
844 }
845}
846
847//=======================================================================
848//function : BuildSplitsOfFaces
849//purpose : Building the splits of offset faces and
850// looking for the invalid splits
851//=======================================================================
852void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
853 const TopTools_MapOfShape& theModifiedEdges,
854 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
420b38fd 855 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 856 Handle(BRepAlgo_AsDes)& theAsDes,
857 TopTools_DataMapOfShapeShape& theFacesOrigins,
858 TopTools_DataMapOfShapeListOfShape& theOEImages,
859 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
860 TopTools_MapOfShape& theLastInvEdges,
861 TopTools_IndexedMapOfShape& theEdgesToAvoid,
862 TopTools_IndexedMapOfShape& theInvEdges,
863 TopTools_IndexedMapOfShape& theValidEdges,
864 TopTools_MapOfShape& theInvertedEdges,
865 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
866 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
867 TopTools_DataMapOfShapeShape& theArtInvFaces,
868 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 869 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 870 TopoDS_Shape& theSolids,
6f04cbb1 871 BRepOffset_MakeOffset_InterResults& theIntRes)
ecf4f17c 872{
873 if (theLF.IsEmpty()) {
874 return;
875 }
876 //
877 BRep_Builder aBB;
878 Standard_Integer i, aNb;
879 //
880 // processed faces
881 TopTools_ListOfShape aLFDone;
9e9b826a 882 // extended face - map of neutral edges, i.e. in one split - valid and in other - invalid
883 BRepOffset_DataMapOfShapeMapOfShape aDMFMNE;
884 // map of valid edges for each face
885 BRepOffset_DataMapOfShapeMapOfShape aDMFMVE;
886 // map of invalid edges for each face
887 BRepOffset_DataMapOfShapeIndexedMapOfShape aDMFMIE;
ecf4f17c 888 // map of valid inverted edges for the face
9e9b826a 889 BRepOffset_DataMapOfShapeMapOfShape aDMFMVIE;
ecf4f17c 890 // map of splits to check for internals
891 TopTools_IndexedMapOfShape aMFToCheckInt;
892 // map of edges created from vertex and marked as invalid
893 TopTools_MapOfShape aMEdgeInvalidByVertex;
9e9b826a 894 // map of edges created from vertex and marked as valid
895 TopTools_MapOfShape aMEdgeValidByVertex;
0da0275c 896 // connection map from old edges to new ones
897 TopTools_DataMapOfShapeListOfShape aDMEOrLEIm;
ecf4f17c 898 //
899 Handle(IntTools_Context) aCtx = new IntTools_Context;
900 // build splits of faces
901 TopTools_ListIteratorOfListOfShape aItLF(theLF);
902 for (; aItLF.More(); aItLF.Next()) {
903 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
904 //
905 TopTools_ListOfShape* pLFIm = theFImages.ChangeSeek(aF);
906 if (pLFIm && pLFIm->IsEmpty()) {
907 continue;
908 }
909 // get edges by which the face should be split
910 TopoDS_Shape aCE;
911 TopTools_IndexedMapOfShape aMapEInv;
912 Standard_Boolean bFound =
913 GetEdges(aF, theAsDes, theOEImages, theLastInvEdges,
914 theEdgesToAvoid, aCtx, theModifiedEdges, aCE, aMapEInv);
915 if (!bFound) {
916 continue;
917 }
918 //
bc4a3867 919#ifdef OFFSET_DEBUG
920 // check the found edges on self-intersection
921 BRepAlgoAPI_Check aChecker(aCE);
922 if (!aChecker.IsValid())
923 {
04232180 924 std::cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n";
bc4a3867 925 }
926#endif
ecf4f17c 927 // build splits
928 TopTools_ListOfShape aLFImages;
a8232603 929 BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages);
ecf4f17c 930 //
931 if (aMapEInv.Extent()) {
932 // check if all possible faces are built
933 TopTools_MapOfShape aMENInv;
934 Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
935 CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes);
936 //
937 // try to build splits using invalid edges
938 TopoDS_Compound aCE1;
939 aBB.MakeCompound(aCE1);
940 aBB.Add(aCE1, aCE);
941 for (i = 1; i <= aMapEInv.Extent(); ++i) {
942 aBB.Add(aCE1, aMapEInv(i));
943 }
944 //
945 TopTools_ListOfShape aLFImages1;
a8232603 946 BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1);
ecf4f17c 947 //
b443d536 948 // check if the rebuilding has added some new faces to the splits
45d0af05 949 for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();)
950 {
b443d536 951 Standard_Boolean bAllInv = Standard_True;
ecf4f17c 952 const TopoDS_Shape& aFIm = aItLFIm.Value();
953 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
954 for (; aExpE.More(); aExpE.Next()) {
955 const TopoDS_Shape& aE = aExpE.Current();
b443d536 956 if (!aMapEInv.Contains(aE)) {
957 bAllInv = Standard_False;
958 if (!aMENInv.Contains(aE)) {
959 break;
960 }
ecf4f17c 961 }
962 }
963 //
964 if (!aExpE.More()) {
965 if (bAllInv) {
966 aMFToCheckInt.Add(aFIm);
967 }
968 aLFImages1.Remove(aItLFIm);
969 }
970 else {
971 aItLFIm.Next();
972 }
973 }
974 //
975 if (bArtificialCase) {
976 if (aLFImages.Extent() == aLFImages1.Extent()) {
977 bArtificialCase = Standard_False;
978 }
979 else {
980 aLFImages = aLFImages1;
981 }
982 }
983 //
984 if (bArtificialCase) {
9e9b826a 985 TopTools_IndexedMapOfShape aMEInv;
ecf4f17c 986 // make the face invalid
987 theArtInvFaces.Bind(aF, aCE);
988 //
989 *pLFIm = aLFImages;
990 TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages);
991 for (; aItLFIm.More(); aItLFIm.Next()) {
992 const TopoDS_Shape& aFIm = aItLFIm.Value();
993 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
994 for (; aExpE.More(); aExpE.Next()) {
995 const TopoDS_Shape& aE = aExpE.Current();
996 if (aMapEInv.Contains(aE)) {
997 theInvEdges.Add(aE);
9e9b826a 998 aMEInv.Add (aE);
ecf4f17c 999 }
1000 else {
1001 theValidEdges.Add(aE);
1002 }
1003 }
1004 }
1005 //
9e9b826a 1006 aDMFMIE.Bind(aF, aMEInv);
ecf4f17c 1007 aLFDone.Append(aF);
1008 //
1009 continue;
1010 }
1011 }
1012 //
1013 // find invalid edges
420b38fd 1014 FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theAnalyse, theOEImages,
9e9b826a 1015 theOEOrigins, theInvEdges, theValidEdges, aDMFMVE, aDMFMNE, aDMFMIE,
1016 aDMFMVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex);
ecf4f17c 1017 //
1018 // save the new splits
1019 if (!pLFIm) {
1020 pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape()));
1021 }
1022 else {
1023 pLFIm->Clear();
1024 }
1025 pLFIm->Append(aLFImages);
1026 //
1027 aLFDone.Append(aF);
1028 }
1029 //
9e9b826a 1030 if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty() && aDMFMIE.IsEmpty()) {
ecf4f17c 1031 return;
1032 }
bea10656 1033
1034 // Additional step to find invalid edges by checking unclassified edges
1035 // in the splits of SD faces
1036 FindInvalidEdges (aLFDone, theFImages, theFacesOrigins, theAnalyse,
1037 theInvEdges, theValidEdges, aDMFMIE, aDMFMVE, aDMFMNE);
1038
62eafa5a 1039 // Additional step to mark inverted edges located inside loops
1040 // of invalid edges as invalid as well
1041 MakeInvertedEdgesInvalid(aLFDone, theFImages, theInvertedEdges, theInvEdges);
1042
ecf4f17c 1043#ifdef OFFSET_DEBUG
1044 // show invalid edges
1045 TopoDS_Compound aCEInv1;
1046 BRep_Builder().MakeCompound(aCEInv1);
1047 Standard_Integer aNbEInv = theInvEdges.Extent();
1048 for (i = 1; i <= aNbEInv; ++i) {
1049 const TopoDS_Shape& aE = theInvEdges(i);
1050 BRep_Builder().Add(aCEInv1, aE);
1051 }
baaacd46 1052 // show valid edges
ecf4f17c 1053 TopoDS_Compound aCEVal1;
1054 BRep_Builder().MakeCompound(aCEVal1);
1055 aNbEInv = theValidEdges.Extent();
1056 for (i = 1; i <= aNbEInv; ++i) {
1057 const TopoDS_Shape& aE = theValidEdges(i);
1058 BRep_Builder().Add(aCEVal1, aE);
1059 }
baaacd46 1060 // show inverted edges
1061 TopoDS_Compound aCEInverted;
1062 BRep_Builder().MakeCompound(aCEInverted);
1063 TopTools_MapIteratorOfMapOfShape aItM(theInvertedEdges);
1064 for (; aItM.More(); aItM.Next()) {
1065 BRep_Builder().Add(aCEInverted, aItM.Value());
1066 }
ecf4f17c 1067#endif
2ebb1098 1068
e08a9b03 1069#ifdef OFFSET_DEBUG
1070 // Show all obtained splits of faces
1071 TopoDS_Compound aCFIm1;
1072 BRep_Builder().MakeCompound(aCFIm1);
1073#endif
1074
2ebb1098 1075 // Build Edge-Face connectivity map to find faces which removal
1076 // may potentially lead to creation of the holes in the faces
1077 // preventing from obtaining closed volume in the result
1078 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
1079 const Standard_Integer aNbF = theFImages.Extent();
1080 for (i = 1; i <= aNbF; ++i)
1081 {
1082 TopTools_ListIteratorOfListOfShape itLFIm(theFImages(i));
1083 for (; itLFIm.More(); itLFIm.Next())
e08a9b03 1084 {
2ebb1098 1085 TopExp::MapShapesAndAncestors(itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
e08a9b03 1086#ifdef OFFSET_DEBUG
1087 BRep_Builder().Add(aCFIm1, itLFIm.Value());
1088#endif
1089 }
2ebb1098 1090 }
1091
9e9b826a 1092 TopTools_MapOfShape anEmptyMap;
0da0275c 1093 // invalid faces inside the holes
1094 TopTools_IndexedMapOfShape aMFInvInHole;
1095 // all hole faces
1096 TopoDS_Compound aFHoles;
1097 aBB.MakeCompound(aFHoles);
e08a9b03 1098 // Find the faces containing only the inverted edges and the invalid ones
1099 TopTools_ListOfShape anInvertedFaces;
ecf4f17c 1100 // find invalid faces
1101 // considering faces containing only invalid edges as invalid
1102 aItLF.Initialize(aLFDone);
1103 for (; aItLF.More(); aItLF.Next()) {
0da0275c 1104 const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
ecf4f17c 1105 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
1106 //
1107 TopTools_ListOfShape aLFInv;
1108 Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF);
1109 if (bArtificialCase) {
1110 aLFInv = aLFImages;
1111 }
9e9b826a 1112 else
1113 {
ecf4f17c 1114 // neutral edges
9e9b826a 1115 const TopTools_MapOfShape* pMNE = aDMFMNE.ChangeSeek(aF);
1116 if (!pMNE) {
1117 pMNE = &anEmptyMap;
ecf4f17c 1118 }
0da0275c 1119 // find faces inside holes wires
1120 TopTools_MapOfShape aMFHoles;
1121 const TopoDS_Face& aFOr = TopoDS::Face(theFacesOrigins.Find(aF));
1122 FindFacesInsideHoleWires(aFOr, aF, aLFImages, theInvertedEdges,
2ebb1098 1123 aDMEOrLEIm, anEFMap, aMFHoles, theDMFNewHoles, aCtx);
0da0275c 1124 //
1125 TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles);
1126 for (; aItMH.More(); aItMH.Next()) {
1127 aBB.Add(aFHoles, aItMH.Value());
1128 }
1129 //
1130 // find invalid faces
9e9b826a 1131 FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFMVE, aDMFMIE,
1132 *pMNE, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex,
e08a9b03 1133 aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
ecf4f17c 1134 }
1135 //
1136 if (aLFInv.Extent()) {
1137 if (theAlreadyInvFaces.IsBound(aF)) {
1138 if (theAlreadyInvFaces.Find(aF) > 2) {
1139 if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) {
1140 aLFImages.Clear();
1141 }
1142 //
1143 aLFInv.Clear();
1144 }
1145 }
1146 theInvFaces.Add(aF, aLFInv);
1147 }
1148 }
1149 //
1150 if (theInvFaces.IsEmpty()) {
1151 theInvEdges.Clear();
1152 return;
1153 }
1154 //
1155#ifdef OFFSET_DEBUG
1156 // show invalid faces
1157 TopoDS_Compound aCFInv1;
1158 BRep_Builder().MakeCompound(aCFInv1);
1159 Standard_Integer aNbFInv = theInvFaces.Extent();
1160 for (i = 1; i <= aNbFInv; ++i) {
1161 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1162 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1163 for (; aItLFInv.More(); aItLFInv.Next()) {
1164 const TopoDS_Shape& aFIm = aItLFInv.Value();
1165 BRep_Builder().Add(aCFInv1, aFIm);
1166 }
1167 }
1168#endif
1169 //
1170 TopTools_IndexedMapOfShape aMERemoved;
1171 // remove invalid splits of faces using inverted edges
baaacd46 1172 RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins,
1173 theInvFaces, theFImages, aMERemoved);
ecf4f17c 1174 if (theInvFaces.IsEmpty()) {
1175 theInvEdges.Clear();
1176 return;
1177 }
1178 //
1179 // remove invalid splits from valid splits
9e9b826a 1180 RemoveInvalidSplitsFromValid (theInvFaces, theArtInvFaces, theInvertedEdges,
1181 aDMFMVIE, theFImages);
ecf4f17c 1182 //
1183 // remove inside faces
baaacd46 1184 TopTools_IndexedMapOfShape aMEInside;
e08a9b03 1185 RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, theInvertedEdges,
6f04cbb1 1186 anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles, theIntRes,
0da0275c 1187 aMERemoved, aMEInside, theSolids);
ecf4f17c 1188 //
1189 // make compound of valid splits
1190 TopoDS_Compound aCFIm;
1191 aBB.MakeCompound(aCFIm);
1192 //
1193 aNb = theFImages.Extent();
1194 for (i = 1; i <= aNb; ++i) {
1195 const TopTools_ListOfShape& aLFIm = theFImages(i);
1196 aItLF.Initialize(aLFIm);
1197 for (; aItLF.More(); aItLF.Next()) {
1198 const TopoDS_Shape& aFIm = aItLF.Value();
1199 aBB.Add(aCFIm, aFIm);
1200 }
1201 }
1202 //
baaacd46 1203 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
1204 TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
ecf4f17c 1205 //
1206 // filter maps of images and origins
1207 FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
1208 //
1209 // filter invalid faces
9e9b826a 1210 FilterInvalidFaces(theFImages, aDMEF, theInvEdges, aMEInside, theInvFaces, theArtInvFaces);
ecf4f17c 1211 aNb = theInvFaces.Extent();
1212 if (!aNb) {
1213 theInvEdges.Clear();
1214 return;
1215 }
1216 //
1217#ifdef OFFSET_DEBUG
1218 // show invalid faces
1219 TopoDS_Compound aCFInv;
1220 BRep_Builder().MakeCompound(aCFInv);
1221 aNbFInv = theInvFaces.Extent();
1222 for (i = 1; i <= aNbFInv; ++i) {
1223 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
1224 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
1225 for (; aItLFInv.More(); aItLFInv.Next()) {
1226 const TopoDS_Shape& aFIm = aItLFInv.Value();
1227 BRep_Builder().Add(aCFInv, aFIm);
1228 }
1229 }
1230#endif
1231 //
1232 // filter invalid edges
9e9b826a 1233 FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFMIE, aMERemoved, theInvEdges);
ecf4f17c 1234 //
4b59685a 1235 // Check additionally validity of edges originated from vertices.
1236 CheckEdgesCreatedByVertex (theInvFaces, theArtInvFaces, theEdgesOrigins,
1237 theValidEdges, theEdgesToAvoid);
1238
ecf4f17c 1239#ifdef OFFSET_DEBUG
1240 // show invalid edges
1241 TopoDS_Compound aCEInv;
1242 BRep_Builder().MakeCompound(aCEInv);
1243 aNbEInv = theInvEdges.Extent();
1244 for (i = 1; i <= aNbEInv; ++i) {
1245 const TopoDS_Shape& aE = theInvEdges(i);
1246 BRep_Builder().Add(aCEInv, aE);
1247 }
1248#endif
1249 //
1250 theLastInvEdges.Clear();
1251 aNb = theInvEdges.Extent();
1252 for (i = 1; i <= aNb; ++i) {
1253 const TopoDS_Shape& aE = theInvEdges(i);
1254 theEdgesToAvoid.Add(aE);
1255 theLastInvEdges.Add(aE);
1256 }
1257 //
1258 aNb = theInvFaces.Extent();
1259 for (i = 1; i <= aNb; ++i) {
1260 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
1261 if (theAlreadyInvFaces.IsBound(aF)) {
1262 theAlreadyInvFaces.ChangeFind(aF)++;
1263 }
1264 else {
1265 theAlreadyInvFaces.Bind(aF, 1);
1266 }
1267 }
1268}
1269
1270//=======================================================================
1271//function : IntersectTrimmedEdges
1272//purpose : Intersection of the trimmed edges among themselves
1273//=======================================================================
1274void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
1275 const Handle(BRepAlgo_AsDes)& theAsDes,
1276 TopTools_DataMapOfShapeListOfShape& theOEImages,
1277 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1278 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1279 Handle(IntTools_Context)& theCtx,
1280 TopTools_MapOfShape& theNewEdges,
1281 TopTools_DataMapOfShapeShape& theETrimEInf)
1282{
1283 if (theLF.IsEmpty()) {
1284 return;
1285 }
1286 //
1287 // get edges to intersect from descendants of the offset faces
1155d05a 1288 TopTools_ListOfShape aLS;
ecf4f17c 1289 //
1290 TopTools_ListIteratorOfListOfShape aItLF(theLF);
1291 for (; aItLF.More(); aItLF.Next()) {
1292 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1293 //
1294 const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
1295 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1296 for (; aItLE.More(); aItLE.Next()) {
1297 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1298 //
1299 if (ProcessMicroEdge(aE, theCtx)) {
1300 continue;
1301 }
1302 //
1303 if (theNewEdges.Add(aE)) {
1304 aLS.Append(aE);
1305 }
1306 }
1307 }
1308 //
1309 if (aLS.Extent() < 2) {
1310 // nothing to intersect
1311 return;
1312 }
1313 //
1314 // perform intersection of the edges
1315 BOPAlgo_Builder aGFE;
1316 aGFE.SetArguments(aLS);
1317 aGFE.Perform();
33ba8565 1318 if (aGFE.HasErrors()) {
ecf4f17c 1319 return;
1320 }
1321 //
1322 TopTools_ListOfShape aLA;
1323 // fill map with edges images
1155d05a 1324 TopTools_ListIteratorOfListOfShape aIt(aLS);
ecf4f17c 1325 for (; aIt.More(); aIt.Next()) {
1326 const TopoDS_Shape& aE = aIt.Value();
1327 const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
1328 if (aLEIm.IsEmpty()) {
1329 continue;
1330 }
1331 //
1332 aLA.Append(aE);
1333 // save images
1334 theOEImages.Bind(aE, aLEIm);
1335 // save origins
1336 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
1337 for (; aItLE.More(); aItLE.Next()) {
1338 const TopoDS_Shape& aEIm = aItLE.Value();
1339 TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm);
1340 if (!pLEOr) {
1341 pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape());
1342 }
1343 AppendToList(*pLEOr, aE);
1344 }
1345 }
1346 //
1347 UpdateOrigins(aLA, theEdgesOrigins, aGFE);
1348 UpdateIntersectedEdges(aLA, theETrimEInf, aGFE);
1349}
1350
1351//=======================================================================
1352//function : GetEdges
1353//purpose : Getting edges from AsDes map to build the splits of faces
1354//=======================================================================
1355Standard_Boolean GetEdges(const TopoDS_Face& theFace,
1356 const Handle(BRepAlgo_AsDes)& theAsDes,
1357 const TopTools_DataMapOfShapeListOfShape& theEImages,
1358 const TopTools_MapOfShape& theLastInvEdges,
1359 const TopTools_IndexedMapOfShape& theInvEdges,
1360 Handle(IntTools_Context)& theCtx,
1361 const TopTools_MapOfShape& theModifiedEdges,
1362 TopoDS_Shape& theEdges,
1363 TopTools_IndexedMapOfShape& theInv)
1364{
1365 // get boundary edges
1366 TopTools_MapOfShape aMFBounds;
1367 TopExp_Explorer aExp(theFace, TopAbs_EDGE);
1368 for (; aExp.More(); aExp.Next()) {
1369 const TopoDS_Shape& aE = aExp.Current();
1370 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1371 if (!pLEIm) {
1372 aMFBounds.Add(aE);
1373 }
1374 else {
1375 TopTools_ListIteratorOfListOfShape aItLE(*pLEIm);
1376 for (; aItLE.More(); aItLE.Next()) {
1377 const TopoDS_Shape& aEIm = aItLE.Value();
1378 aMFBounds.Add(aEIm);
1379 }
1380 }
1381 }
1382 //
1383 BRep_Builder aBB;
1384 Standard_Boolean bFound(Standard_False), bUpdate(Standard_False);
1385 // the resulting edges
1386 TopoDS_Compound anEdges;
1387 aBB.MakeCompound(anEdges);
bc4a3867 1388 // Fence map
1389 TopTools_MapOfShape aMEFence;
ecf4f17c 1390 // the edges by which the offset face should be split
1391 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theFace);
1392 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1393 for (; aItLE.More(); aItLE.Next()) {
1394 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1395 //
1396 if (!bUpdate) {
1397 bUpdate = theModifiedEdges.Contains(aE);
1398 }
1399 //
1400 const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
1401 if (pLEIm) {
1402 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
1403 for (; aItLEIm.More(); aItLEIm.Next()) {
1404 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1405 //
bc4a3867 1406 if (!aMEFence.Add(aEIm))
1407 continue;
1408
ecf4f17c 1409 if (theInvEdges.Contains(aEIm)) {
1410 theInv.Add(aEIm);
1411 if (!bUpdate) {
1412 bUpdate = theLastInvEdges.Contains(aEIm);
1413 }
1414 continue;
1415 }
1416 // check for micro edge
1417 if (ProcessMicroEdge(aEIm, theCtx)) {
1418 continue;
1419 }
1420 //
1421 aBB.Add(anEdges, aEIm);
1422 if (!bFound) {
1423 bFound = !aMFBounds.Contains(aEIm);
1424 }
1425 //
1426 if (!bUpdate) {
1427 bUpdate = theModifiedEdges.Contains(aEIm);
1428 }
1429 }
1430 }
1431 else {
1432 if (theInvEdges.Contains(aE)) {
1433 theInv.Add(aE);
1434 if (!bUpdate) {
1435 bUpdate = theLastInvEdges.Contains(aE);
1436 }
1437 continue;
1438 }
1439 //
1440 if (ProcessMicroEdge(aE, theCtx)) {
1441 continue;
1442 }
1443 aBB.Add(anEdges, aE);
1444 if (!bFound) {
1445 bFound = !aMFBounds.Contains(aE);
1446 }
1447 }
1448 }
1449 //
1450 theEdges = anEdges;
1451 return bFound && bUpdate;
1452}
1453
1454//=======================================================================
1455//function : BuildSplitsOfFace
1456//purpose : Building the splits of offset face
1457//=======================================================================
1458void BuildSplitsOfFace(const TopoDS_Face& theFace,
1459 const TopoDS_Shape& theEdges,
ecf4f17c 1460 TopTools_DataMapOfShapeShape& theFacesOrigins,
1461 TopTools_ListOfShape& theLFImages)
a8232603 1462{
1463 theLFImages.Clear();
1464 //
1465 // take edges to split the face
1155d05a 1466 TopTools_ListOfShape aLE;
a8232603 1467 TopExp_Explorer aExp(theEdges, TopAbs_EDGE);
1468 for (; aExp.More(); aExp.Next()) {
1469 TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
1470 aE.Orientation(TopAbs_FORWARD);
1471 aLE.Append(aE);
1472 aE.Orientation(TopAbs_REVERSED);
1473 aLE.Append(aE);
1474 }
1475 //
1476 TopoDS_Face aFF = theFace;
1477 TopAbs_Orientation anOr = theFace.Orientation();
1478 aFF.Orientation(TopAbs_FORWARD);
1479 //
1480 // build pcurves for edges on the face
f16a6cc5 1481 BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
a8232603 1482 //
1483 // build splits of faces
1484 BOPAlgo_BuilderFace aBF;
1485 aBF.SetFace(aFF);
1486 aBF.SetShapes(aLE);
1487 aBF.Perform();
1488 //
1155d05a 1489 const TopTools_ListOfShape& aLFSp = aBF.Areas();
1490 TopTools_ListIteratorOfListOfShape aItLF(aLFSp);
a8232603 1491 for (; aItLF.More(); aItLF.Next()) {
1492 TopoDS_Shape& aFSp = aItLF.ChangeValue();
1493 aFSp.Orientation(anOr);
1494 theLFImages.Append(aFSp);
1495 //
1496 theFacesOrigins.Bind(aFSp, theFace);
1497 }
1498}
1499
1500//=======================================================================
1501//function : BuildSplitsOfFace
1502//purpose : Building the splits of offset face
1503//=======================================================================
1504void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
1505 const TopoDS_Shape& theEdges,
1506 TopTools_ListOfShape& theLFImages)
ecf4f17c 1507{
1508 BOPAlgo_Builder aGF;
1509 //
1510 aGF.AddArgument(theFace);
1511 aGF.AddArgument(theEdges);
1512 aGF.Perform();
33ba8565 1513 if (aGF.HasErrors()) {
ecf4f17c 1514 return;
1515 }
1516 //
1517 // splits of the offset shape
1518 theLFImages = aGF.Modified(theFace);
ecf4f17c 1519}
1520
1521//=======================================================================
1522//function : CheckIfArtificial
1523//purpose : Checks if the face is artificially invalid
1524//=======================================================================
1525Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
1526 const TopTools_ListOfShape& theLFImages,
1527 const TopoDS_Shape& theCE,
1528 const TopTools_IndexedMapOfShape& theMapEInv,
1529 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1530 TopTools_MapOfShape& theMENInv,
1531 Handle(BRepAlgo_AsDes)& theAsDes)
1532{
1533 // all boundary edges should be used
1534 TopTools_IndexedMapOfShape aMEUsed;
1535 TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages);
1536 for (; aItLFIm.More(); aItLFIm.Next()) {
1537 const TopoDS_Shape& aFIm = aItLFIm.Value();
1538 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed);
1539 TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed);
1540 }
1541 //
1542 TopTools_IndexedDataMapOfShapeListOfShape aMVE;
1543 TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
1544 //
1545 Standard_Integer i, aNb = theMapEInv.Extent();
1546 for (i = 1; i <= aNb; ++i) {
1547 const TopoDS_Shape& aEInv = theMapEInv(i);
1548 TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX);
1549 for (; aExpV.More(); aExpV.Next()) {
1550 const TopoDS_Shape& aVEInv = aExpV.Current();
b443d536 1551 const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv);
1552 if (pLENInv) {
1553 TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv);
ecf4f17c 1554 for (; aItLEInv.More(); aItLEInv.Next()) {
1555 const TopoDS_Shape& aENInv = aItLEInv.Value();
b443d536 1556 if (!aMEUsed.Contains(aENInv)) {
1557 theMENInv.Add(aENInv);
1558 }
ecf4f17c 1559 }
1560 }
1561 }
1562 }
1563 //
1564 if (theMENInv.IsEmpty()) {
1565 return Standard_False;
1566 }
1567 //
1568 TopTools_IndexedMapOfShape aMEFound;
1569 TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound);
1570 //
1571 const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF);
1572 TopTools_ListIteratorOfListOfShape aItLE(aLE);
1573 for (; aItLE.More(); aItLE.Next()) {
1574 const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
1575 //
1576 if (theOEImages.IsBound(aE)) {
1577 Standard_Boolean bChecked = Standard_False;
1578 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE);
1579 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
1580 for (; aItLEIm.More(); aItLEIm.Next()) {
1581 const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
1582 if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) {
1583 continue;
1584 }
1585 //
1586 bChecked = Standard_True;
1587 if (aMEUsed.Contains(aEIm)) {
1588 break;
1589 }
1590 }
1591 //
1592 if (bChecked && !aItLEIm.More()) {
1593 break;
1594 }
1595 }
1596 else {
1597 if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) {
1598 break;
1599 }
1600 }
1601 }
1602 //
1603 return aItLE.More();
1604}
1605
1606//=======================================================================
1607//function : FindInvalidEdges
1608//purpose : Looking for the invalid edges
1609//=======================================================================
1610void FindInvalidEdges(const TopoDS_Face& theF,
1611 const TopTools_ListOfShape& theLFImages,
1612 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1613 const TopTools_DataMapOfShapeShape& theFacesOrigins,
420b38fd 1614 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 1615 const TopTools_DataMapOfShapeListOfShape& theOEImages,
1616 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1617 TopTools_IndexedMapOfShape& theInvEdges,
1618 TopTools_IndexedMapOfShape& theValidEdges,
9e9b826a 1619 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
1620 BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
1621 BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
1622 BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
0da0275c 1623 TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
ecf4f17c 1624 TopTools_MapOfShape& theMEInverted,
9e9b826a 1625 TopTools_MapOfShape& theEdgesInvalidByVertex,
1626 TopTools_MapOfShape& theEdgesValidByVertex)
ecf4f17c 1627{
1628 // Edge is considered as invalid in the following cases:
1629 // 1. Its orientation on the face has changed comparing to the originals edge and face;
1630 // 2. The vertices of the edge have changed places comparing to the originals edge and face.
1631 //
1632 // The edges created from vertices, i.e. as intersection between two faces connected only
1633 // by VERTEX, will also be checked on validity. For these edges the correct orientation will
1634 // be defined by the edges on the original face adjacent to the connection vertex
0da0275c 1635
1636 // original face
ecf4f17c 1637 const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
b443d536 1638 // invalid edges
ecf4f17c 1639 TopTools_IndexedMapOfShape aMEInv;
1640 // valid edges
1641 TopTools_MapOfShape aMEVal;
1642 // internal edges
1643 TopTools_MapOfShape aMEInt;
1644 //
1645 // maps for checking the inverted edges
1646 TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
1647 TopTools_IndexedMapOfShape aMEdges;
9e9b826a 1648 // back map from the original shapes to their offset images
1649 TopTools_DataMapOfShapeListOfShape anImages;
ecf4f17c 1650 //
1651 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
1652 for (; aItLF.More(); aItLF.Next()) {
1653 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1654 //
1655 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1656 for (; aExp.More(); aExp.Next()) {
1657 const TopoDS_Shape& aE = aExp.Current();
1658 // keep all edges
1659 aMEdges.Add(aE);
1660 //
1661 // keep connection from edges to faces
1662 TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE);
1663 if (!pLF) {
1664 pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape()));
1665 }
1666 AppendToList(*pLF, aFIm);
1667 //
1668 // keep connection from vertices to edges
1669 TopoDS_Iterator aItV(aE);
1670 for (; aItV.More(); aItV.Next()) {
1671 const TopoDS_Shape& aV = aItV.Value();
1672 //
1673 TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV);
1674 if (!pLE) {
1675 pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape()));
1676 }
1677 AppendToList(*pLE, aE);
1678 }
9e9b826a 1679
1680 // back map from original edges to their offset images
1681 const TopTools_ListOfShape* pLOr = theEdgesOrigins.Seek (aE);
1682 if (!pLOr)
1683 continue;
1684 for (TopTools_ListOfShape::Iterator itOr (*pLOr); itOr.More(); itOr.Next())
1685 {
1686 const TopoDS_Shape& aSOr = itOr.Value();
1687 TopoDS_Shape aSInF;
1688 if (!FindShape (aSOr, aFOr, theAnalyse, aSInF))
1689 continue;
1690 TopTools_ListOfShape* pImages = anImages.ChangeSeek (aSInF);
1691 if (!pImages)
1692 pImages = anImages.Bound (aSInF, TopTools_ListOfShape());
1693 AppendToList (*pImages, aE);
1694 }
ecf4f17c 1695 }
1696 }
1697 //
1698 // the map will be used to find the edges on the original face
1699 // adjacent to the same vertex. It will be filled at first necessity;
1700 TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
1701 //
1702 aItLF.Initialize(theLFImages);
1703 for (; aItLF.More(); aItLF.Next()) {
1704 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
1705 //
1706 // valid edges for this split
9e9b826a 1707 TopTools_MapOfShape aMVE;
ecf4f17c 1708 // invalid edges for this split
9e9b826a 1709 TopTools_IndexedMapOfShape aMIE;
ecf4f17c 1710 //
1711 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
1712 for (; aExp.More(); aExp.Next()) {
1713 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
1714 //
1715 if (aEIm.Orientation() == TopAbs_INTERNAL) {
1716 aMEInt.Add(aEIm);
1717 continue;
1718 }
1719 //
1720 if (!theEdgesOrigins.IsBound(aEIm)) {
1721 continue;
1722 }
1723 //
1724 const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm);
1725 if (aLEOr.IsEmpty()) {
1726 continue;
1727 }
1728 //
1729 Standard_Integer aNbVOr = 0;
1730 TopTools_ListIteratorOfListOfShape aItLEO(aLEOr);
1731 for (; aItLEO.More(); aItLEO.Next()) {
1732 if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) {
1733 ++aNbVOr;
1734 }
1735 }
9e9b826a 1736 if (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1)
1737 continue;
ecf4f17c 1738 //
420b38fd 1739 TopTools_MapOfShape aME, aMV, aMF;
ecf4f17c 1740 Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
420b38fd 1741 Standard_Integer aNbP = NbPoints(aEIm), aNbInv = 0;
b443d536 1742 Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
1743 (aNbVOr == 1 &&
1744 aDMEF.FindFromKey(aEIm).Extent() == 1 &&
1745 !theOEOrigins.IsBound(aEIm));
1746 //
ecf4f17c 1747 aItLEO.Initialize(aLEOr);
1748 for (; aItLEO.More(); aItLEO.Next()) {
1749 const TopoDS_Shape& aSOr = aItLEO.Value();
1750 Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
1751 //
1752 TopoDS_Shape aEOrF;
1753 if (bVertex) {
1754 // for some cases it is impossible to check the validity of the edge
b443d536 1755 if (!bUseVertex) {
ecf4f17c 1756 continue;
1757 }
ecf4f17c 1758 // find edges on the original face adjacent to this vertex
1759 if (aDMVEFOr.IsEmpty()) {
1760 // fill the map
1761 TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
1762 }
1763 //
1764 TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr);
1765 if (pLEFOr) {
1766 TopoDS_Compound aCEOr;
1767 BRep_Builder().MakeCompound(aCEOr);
9e9b826a 1768 // Avoid classification of edges originated from vertices
1769 // located between tangent edges
1770 Standard_Boolean bAllTgt = Standard_True;
ecf4f17c 1771 TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
9e9b826a 1772 gp_Vec aVRef = GetAverageTangent (aItLEFOr.Value(), aNbP);
1773 for (; aItLEFOr.More(); aItLEFOr.Next())
1774 {
ecf4f17c 1775 const TopoDS_Shape& aEOr = aItLEFOr.Value();
1776 BRep_Builder().Add(aCEOr, aEOr);
9e9b826a 1777
1778 gp_Vec aVCur = GetAverageTangent (aEOr, aNbP);
1779 if (!aVRef.IsParallel (aVCur, Precision::Angular()))
1780 bAllTgt = Standard_False;
ecf4f17c 1781 }
9e9b826a 1782 if (!bAllTgt)
1783 aEOrF = aCEOr;
ecf4f17c 1784 }
1785 }
1786 else {
420b38fd 1787 FindShape(aSOr, aFOr, theAnalyse, aEOrF);
0da0275c 1788 //
1789 TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr);
1790 if (!pLEIm) {
1791 pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape());
1792 }
1793 AppendToList(*pLEIm, aEIm);
ecf4f17c 1794 }
1795 //
1796 if (aEOrF.IsNull()) {
1797 // the edge has not been found
1798 continue;
1799 }
9e9b826a 1800
1801 if (bVertex)
1802 {
1803 TopTools_MapOfShape aMVTotal;
1804 Standard_Integer aNbChecked = 0;
1805 // Just check if the original edges sharing the vertex do not share it any more.
1806 for (TopoDS_Iterator it (aEOrF); it.More(); it.Next())
1807 {
1808 const TopoDS_Shape& aEOr = it.Value();
1809 const TopTools_ListOfShape* aLIm = anImages.Seek (aEOr);
1810 if (!aLIm)
1811 continue;
1812 ++aNbChecked;
1813 TopTools_IndexedDataMapOfShapeListOfShape aMVLoc;
1814 for (TopTools_ListOfShape::Iterator itLIM (*aLIm); itLIM.More(); itLIM.Next())
1815 TopExp::MapShapesAndAncestors (itLIM.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVLoc);
1816 for (Standard_Integer i = 1; i <= aMVLoc.Extent(); ++i)
1817 {
1818 if (aMVLoc(i).Extent() > 1 && !aMVTotal.Add (aMVLoc.FindKey (i)))
1819 {
1820 bInvalid = Standard_True;
1821 theEdgesInvalidByVertex.Add(aEIm);
1822 break;
1823 }
1824 }
1825 if (bInvalid)
1826 break;
1827 }
1828 if (!bInvalid && aNbChecked < 2)
1829 continue;
1830 else
1831 theEdgesValidByVertex.Add (aEIm);
1832 }
1833 else
1834 {
1835 //
1836 // Check orientations of the image edge and original edge.
1837 // In case the 3d curves are having the same direction the orientations
1838 // must be the same. Otherwise the orientations should also be different.
1839 //
1840 // get average tangent vector for each curve taking into account
1841 // the orientations of the edges, i.e. the edge is reversed
1842 // the vector is reversed as well
1843 gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP);
1844 gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP);
1845 //
1846 aVSum1.Normalize();
1847 aVSum2.Normalize();
1848 //
1849 Standard_Real aCos = aVSum1.Dot(aVSum2);
ecf4f17c 1850 if (Abs(aCos) < 0.9999) {
1851 continue;
1852 }
1853 //
1854 aME.Add(aEOrF);
1855 TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX);
1856 for (; aExpE.More(); aExpE.Next()) {
1857 const TopoDS_Shape& aV = aExpE.Current();
1858 aMV.Add(aV);
1859 }
420b38fd 1860 if (theAnalyse)
1861 {
1862 for (TopTools_ListOfShape::Iterator itFA (theAnalyse->Ancestors (aEOrF));
1863 itFA.More(); itFA.Next())
1864 aMF.Add (itFA.Value());
1865 }
9e9b826a 1866 //
1867 if (aCos < Precision::Confusion()) {
1868 bInvalid = Standard_True;
1869 aNbInv++;
ecf4f17c 1870 }
1871 }
1872 bChecked = Standard_True;
1873 }
1874 //
1875 if (!bChecked) {
1876 continue;
1877 }
1878 //
9e9b826a 1879 Standard_Boolean bLocalOnly = (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1);
ecf4f17c 1880 Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
420b38fd 1881 if (aNbE > 1 && aNbV == 2*aNbE)
1882 {
1883 Standard_Boolean bSkip = Standard_True;
1884
1885 // Allow the edge to be analyzed if it is:
1886 // * originated from more than two faces
1887 // * unanimously considered valid or invalid
1888 // * not a boundary edge in the splits
1889 if (aMF.Extent () > 2 && (aNbInv == 0 || aNbInv == aNbE))
1890 {
1891 if (theLFImages.Extent() > 2)
1892 {
1893 TopoDS_Iterator itV (aEIm);
1894 for (; itV.More(); itV.Next())
1895 {
1896 TopTools_ListOfShape::Iterator itE (aDMVE.FindFromKey (itV.Value()));
1897 for (; itE.More(); itE.Next())
1898 if (aDMEF.FindFromKey (itE.Value()).Extent() < 2)
1899 break;
1900 if (itE.More())
1901 break;
1902 }
1903 bSkip = itV.More();
1904 }
1905 }
1906 if (bSkip)
1907 continue;
1908 else
1909 bLocalOnly = Standard_True;
ecf4f17c 1910 }
1911 //
1912 if (bInvalid) {
420b38fd 1913 if (!bLocalOnly)
1914 theInvEdges.Add(aEIm);
9e9b826a 1915 aMIE.Add (aEIm);
ecf4f17c 1916 aMEInv.Add(aEIm);
1917 continue;
1918 }
1919 //
1920 // check if the edge has been inverted
420b38fd 1921 Standard_Boolean bInverted = !aNbE || bLocalOnly ? Standard_False :
b443d536 1922 CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
b6725456 1923 theEdgesOrigins, aDMVE, aMEdges, theMEInverted);
ecf4f17c 1924 //
1925 if (!bInverted || !aNbVOr) {
420b38fd 1926 if (!bLocalOnly)
1927 theValidEdges.Add(aEIm);
9e9b826a 1928 aMVE.Add (aEIm);
ecf4f17c 1929 aMEVal.Add(aEIm);
1930 }
1931 }
1932 //
1933 // valid edges
9e9b826a 1934 if (aMVE.Extent())
1935 {
1936 theDMFMVE.Bind (aFIm, aMVE);
ecf4f17c 1937 }
1938 //
1939 // invalid edges
9e9b826a 1940 if (aMIE.Extent())
1941 {
1942 theDMFMIE.Bind (aFIm, aMIE);
ecf4f17c 1943 }
1944 }
1945 //
1946 // process invalid edges:
1947 // check for the inverted edges
9e9b826a 1948 TopTools_MapOfShape aMVIE;
ecf4f17c 1949 // fill neutral edges
9e9b826a 1950 TopTools_MapOfShape aMNE;
ecf4f17c 1951 //
1952 Standard_Integer i, aNbEInv = aMEInv.Extent();
1953 for (i = 1; i <= aNbEInv; ++i) {
1954 const TopoDS_Shape& aEIm = aMEInv(i);
1955 //
1956 // neutral edges - on the splits of the same offset face
1957 // it is valid for one split and invalid for other
9e9b826a 1958 if (aMEVal.Contains(aEIm))
1959 {
1960 aMNE.Add (aEIm);
ecf4f17c 1961 continue;
1962 }
1963 //
1964 // the inverted images of the origins of invalid edges should also be invalid
1965 if (!theMEInverted.Contains(aEIm)) {
1966 continue;
1967 }
1968 //
1969 const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm);
1970 if (!pLOEOr) {
1971 continue;
1972 }
1973 //
1974 TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr);
1975 for (; aItLOEOr.More(); aItLOEOr.Next()) {
1976 const TopoDS_Shape& aOEOr = aItLOEOr.Value();
1977 const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr);
1978 //
1979 TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1);
1980 for (; aItLEIm1.More(); aItLEIm1.Next()) {
1981 const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
1982 if (aMEdges.Contains(aEIm1) &&
1983 !aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) &&
1984 theMEInverted.Contains(aEIm1)) {
1985 theInvEdges.Add(aEIm1);
9e9b826a 1986 aMVIE.Add (aEIm1);
ecf4f17c 1987 }
1988 }
1989 }
1990 }
1991 //
9e9b826a 1992 if (aMNE.Extent())
1993 {
1994 theDMFMNE.Bind (theF, aMNE);
ecf4f17c 1995 }
1996 //
9e9b826a 1997 if (aMVIE.Extent())
1998 {
1999 theDMFMVIE.Bind (theF, aMVIE);
ecf4f17c 2000 }
2001}
2002
bea10656 2003namespace
2004{
2005 static void addAsNeutral (const TopoDS_Shape& theE,
2006 const TopoDS_Shape& theFInv,
2007 const TopoDS_Shape& theFVal,
2008 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2009 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges)
2010 {
2011 TopTools_IndexedMapOfShape* pMEInv = theLocInvEdges.ChangeSeek (theFInv);
2012 if (!pMEInv)
2013 pMEInv = theLocInvEdges.Bound (theFInv, TopTools_IndexedMapOfShape());
2014 pMEInv->Add (theE);
2015
2016 TopTools_MapOfShape* pMEVal = theLocValidEdges.ChangeSeek (theFVal);
2017 if (!pMEVal)
2018 pMEVal = theLocValidEdges.Bound (theFVal, TopTools_MapOfShape());
2019 pMEVal->Add (theE);
2020 }
2021
2022}
2023//=======================================================================
2024//function : FindInvalidEdges
2025//purpose : Additional method to look for invalid faces
2026//=======================================================================
2027void FindInvalidEdges (const TopTools_ListOfShape& theLFOffset,
2028 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2029 const TopTools_DataMapOfShapeShape& theFacesOrigins,
2030 const BRepOffset_Analyse* theAnalyse,
2031 const TopTools_IndexedMapOfShape& theInvEdges,
2032 const TopTools_IndexedMapOfShape& theValidEdges,
2033 BRepOffset_DataMapOfShapeIndexedMapOfShape& theLocInvEdges,
2034 BRepOffset_DataMapOfShapeMapOfShape& theLocValidEdges,
2035 BRepOffset_DataMapOfShapeMapOfShape& theNeutralEdges)
2036{
2037 // 1. Find edges unclassified in faces
2038 // 2. Find SD faces in which the same edge is classified
2039 // 3. Check if the edge is neutral in face in which it wasn't classified
2040
2041 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aMEUnclassified;
2042 TopTools_DataMapOfShapeShape aFSplitFOffset;
2043
2044 // Avoid artificial faces
2045 TopTools_MapOfShape aNewFaces;
2046 if (theAnalyse)
2047 {
2048 TopTools_MapOfShape aMapNewTmp;
2049 for (TopTools_ListOfShape::Iterator it (theAnalyse->NewFaces()); it.More(); it.Next())
2050 aMapNewTmp.Add (it.Value());
2051
2052 for (TopTools_ListOfShape::Iterator it (theLFOffset); it.More(); it.Next())
2053 {
2054 const TopoDS_Shape& aFOffset = it.Value();
2055 const TopoDS_Shape& aFOrigin = theFacesOrigins.Find (aFOffset);
2056 if (aMapNewTmp.Contains (aFOrigin))
2057 aNewFaces.Add (aFOffset);
2058 }
2059 }
2060
2061 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
2062 for (TopTools_ListOfShape::Iterator itLFO (theLFOffset); itLFO.More(); itLFO.Next())
2063 {
2064 const TopoDS_Shape& aF = itLFO.Value();
2065 if (aNewFaces.Contains (aF))
2066 continue;
2067
2068 const TopTools_ListOfShape& aLFImages = theFImages.FindFromKey (aF);
2069 for (TopTools_ListOfShape::Iterator itLF (aLFImages); itLF.More(); itLF.Next())
2070 {
2071 const TopoDS_Shape& aFIm = itLF.Value();
2072
2073 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, anEFMap);
2074
2075 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFIm);
2076 const TopTools_MapOfShape* pMEValid = theLocValidEdges.Seek (aFIm);
2077
2078 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
2079 {
2080 const TopoDS_Shape& aE = expE.Current();
2081 if (theInvEdges.Contains (aE) != theValidEdges.Contains (aE))
2082 {
2083 // edge is classified in some face
2084
2085 if ((!pMEInvalid || !pMEInvalid->Contains (aE)) &&
2086 (!pMEValid || !pMEValid->Contains (aE)))
2087 {
2088 // but not in the current one
2089 TopTools_MapOfShape *pMap = aMEUnclassified.ChangeSeek (aE);
2090 if (!pMap)
2091 pMap = &aMEUnclassified (aMEUnclassified.Add (aE, TopTools_MapOfShape()));
2092 pMap->Add (aFIm);
2093
2094 aFSplitFOffset.Bind (aFIm, aF);
2095 }
2096 }
2097 }
2098 }
2099 }
2100
2101 if (aMEUnclassified.IsEmpty())
2102 return;
2103
2104 // Analyze unclassified edges
2105 const Standard_Integer aNbE = aMEUnclassified.Extent();
2106 for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
2107 {
2108 const TopoDS_Shape& aE = aMEUnclassified.FindKey (iE);
2109 const TopTools_MapOfShape& aMFUnclassified = aMEUnclassified (iE);
2110
2111 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey (aE);
2112
2113 for (TopTools_ListOfShape::Iterator itLF (aLF); itLF.More(); itLF.Next())
2114 {
2115 const TopoDS_Shape& aFClassified = itLF.Value();
2116 if (aMFUnclassified.Contains (aFClassified))
2117 continue;
2118
2119 BOPTools_Set anEdgeSetClass;
2120 anEdgeSetClass.Add (aFClassified, TopAbs_EDGE);
2121
2122 TopoDS_Shape aEClassified;
2123 FindShape (aE, aFClassified, NULL, aEClassified);
2124 TopAbs_Orientation anOriClass = aEClassified.Orientation();
2125
2126 gp_Dir aDNClass;
2127 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aEClassified), TopoDS::Face (aFClassified), aDNClass);
2128
2129 const TopTools_IndexedMapOfShape* pMEInvalid = theLocInvEdges.Seek (aFClassified);
2130 Standard_Boolean isInvalid = pMEInvalid && pMEInvalid->Contains (aE);
2131
2132 for (TopTools_MapOfShape::Iterator itM (aMFUnclassified); itM.More(); itM.Next())
2133 {
2134 const TopoDS_Shape& aFUnclassified = itM.Value();
2135
2136 BOPTools_Set anEdgeSetUnclass;
2137 anEdgeSetUnclass.Add (aFUnclassified, TopAbs_EDGE);
2138
2139 if (anEdgeSetClass.IsEqual (anEdgeSetUnclass))
2140 {
2141 gp_Dir aDNUnclass;
2142 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (TopoDS::Edge (aE), TopoDS::Face (aFUnclassified), aDNUnclass);
2143
2144 Standard_Boolean isSameOri = aDNClass.IsEqual (aDNUnclass, Precision::Angular());
2145
2146 // Among other splits of the same face find those where the edge is contained with different
2147 // orientation
2148 const TopoDS_Shape& aFOffset = aFSplitFOffset.Find (aFUnclassified);
2149 const TopTools_ListOfShape& aLFSplits = theFImages.FindFromKey (aFOffset);
2150 TopTools_ListOfShape::Iterator itLFSp (aLFSplits);
2151 for (; itLFSp.More(); itLFSp.Next())
2152 {
2153 const TopoDS_Shape& aFSp = itLFSp.Value();
2154
2155 if (!aFSp.IsSame (aFUnclassified) && aMFUnclassified.Contains (aFSp))
2156 {
2157 TopoDS_Shape aEUnclassified;
2158 FindShape (aE, aFSp, NULL, aEUnclassified);
2159
2160 TopAbs_Orientation anOriUnclass = aEUnclassified.Orientation();
2161 if (!isSameOri)
2162 anOriUnclass = TopAbs::Reverse (anOriUnclass);
2163
2164 if (anOriClass != anOriUnclass)
2165 {
2166 // make the edge neutral for the face
2167 TopTools_MapOfShape* pMENeutral = theNeutralEdges.ChangeSeek (aFOffset);
2168 if (!pMENeutral)
2169 pMENeutral = theNeutralEdges.Bound (aFOffset, TopTools_MapOfShape());
2170 pMENeutral->Add (aE);
2171
2172 if (isInvalid && isSameOri)
2173 {
2174 // make edge invalid in aFUnclassified and valid in aFSp
2175 addAsNeutral (aE, aFClassified, aFSp, theLocInvEdges, theLocValidEdges);
2176 }
2177 else
2178 {
2179 // make edge invalid in aFSp and valid in aFUnclassified
2180 addAsNeutral (aE, aFSp, aFClassified, theLocInvEdges, theLocValidEdges);
2181 }
2182 }
2183 }
2184 }
2185 if (itLFSp.More())
2186 break;
2187 }
2188 }
2189 }
2190 }
2191}
2192
62eafa5a 2193//=======================================================================
2194//function : MakeInvertedEdgesInvalid
2195//purpose : Makes inverted edges located inside loop of invalid edges, invalid as well
2196//=======================================================================
2197void MakeInvertedEdgesInvalid(const TopTools_ListOfShape& theLFOffset,
2198 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
2199 const TopTools_MapOfShape& theInvertedEdges,
2200 TopTools_IndexedMapOfShape& theInvEdges)
2201{
2202 if (theInvEdges.IsEmpty() || theInvertedEdges.IsEmpty())
2203 return;
2204
2205 // Map all invalid edges
2206 TopoDS_Compound aCBEInv;
2207 BRep_Builder().MakeCompound(aCBEInv);
2208 for (Standard_Integer i = 1; i <= theInvEdges.Extent(); ++i)
2209 {
2210 BRep_Builder().Add(aCBEInv, theInvEdges(i));
2211 }
2212
2213 // Make loops of invalid edges
2214 TopTools_ListOfShape aLCB;
2215 BOPTools_AlgoTools::MakeConnexityBlocks(aCBEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCB);
2216
2217 // Analyze each loop on closeness and use only closed ones
2218 TopTools_DataMapOfShapeShape aDMVCB;
2219
2220 for (TopTools_ListOfShape::Iterator itLCB(aLCB); itLCB.More(); itLCB.Next())
2221 {
2222 const TopoDS_Shape& aCB = itLCB.Value();
2223
2224 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
2225 TopExp::MapShapesAndAncestors(aCB, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
2226 Standard_Boolean isClosed = Standard_True;
2227 for (Standard_Integer iV = 1; iV <= aDMVE.Extent(); ++iV)
2228 {
2229 if (aDMVE(iV).Extent() != 2)
2230 {
2231 isClosed = Standard_False;
2232 break;
2233 }
2234 }
2235 if (!isClosed)
2236 continue;
2237
2238 // Bind loop to each vertex of the loop
2239 for (Standard_Integer iV = 1; iV <= aDMVE.Extent(); ++iV)
2240 {
2241 aDMVCB.Bind(aDMVE.FindKey(iV), aCB);
2242 }
2243 }
2244
2245 // Check if any inverted edges of offset faces are locked inside the loops of invalid edges.
2246 // Make such edges invalid as well.
2247 for (TopTools_ListOfShape::Iterator itLF(theLFOffset); itLF.More(); itLF.Next())
2248 {
2249 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(itLF.Value());
2250 for (TopTools_ListOfShape::Iterator itLFIm(aLFIm); itLFIm.More(); itLFIm.Next())
2251 {
2252 for (TopExp_Explorer expE(itLFIm.Value(), TopAbs_EDGE); expE.More(); expE.Next())
2253 {
2254 const TopoDS_Edge& aE = TopoDS::Edge(expE.Current());
2255 if (!theInvEdges.Contains(aE) && theInvertedEdges.Contains(aE))
2256 {
2257 const TopoDS_Shape* pCB1 = aDMVCB.Seek (TopExp::FirstVertex(aE));
2258 const TopoDS_Shape* pCB2 = aDMVCB.Seek (TopExp::LastVertex(aE));
2259 if (pCB1 && pCB2 && pCB1->IsSame(*pCB2))
2260 {
2261 theInvEdges.Add(aE);
2262 }
2263 }
2264 }
2265 }
2266 }
2267}
2268
ecf4f17c 2269//=======================================================================
2270//function : FindInvalidFaces
2271//purpose : Looking for the invalid faces by analyzing their invalid edges
2272//=======================================================================
2273void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
2274 const TopTools_IndexedMapOfShape& theInvEdges,
2275 const TopTools_IndexedMapOfShape& theValidEdges,
9e9b826a 2276 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
2277 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
2278 const TopTools_MapOfShape& theMENeutral,
ecf4f17c 2279 const TopTools_MapOfShape& theMEInverted,
2280 const TopTools_MapOfShape& theEdgesInvalidByVertex,
9e9b826a 2281 const TopTools_MapOfShape& theEdgesValidByVertex,
0da0275c 2282 const TopTools_MapOfShape& theMFHoles,
2283 TopTools_IndexedMapOfShape& theMFInvInHole,
e08a9b03 2284 TopTools_ListOfShape& theInvFaces,
2285 TopTools_ListOfShape& theInvertedFaces)
ecf4f17c 2286{
2287 // The face should be considered as invalid in the following cases:
2288 // 1. It has been reverted, i.e. at least two not connected edges
2289 // have changed orientation (i.e. invalid). In this case all edges,
2290 // should be invalid for that face, because edges have also been reverted;
2291 // 2. All checked edges of the face are invalid for this face;
2292 // The face should be removed from the splits in the following cases:
2293 // 1. All checked edges of the face are invalid for this one, but valid for
2294 // some other face in this list of splits.
2295 // The face will be kept in the following cases:
2296 // 1. Some of the edges are valid for this face.
2297 Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
e08a9b03 2298 Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
2299 Standard_Boolean bIsInvalidByInverted;
9e9b826a 2300 Standard_Integer aNbChecked;
ecf4f17c 2301 //
e08a9b03 2302 Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
ecf4f17c 2303 //
2304 // neutral edges to remove
2305 TopTools_IndexedMapOfShape aMENRem;
2306 //
2307 // faces for post treat
2308 TopTools_ListOfShape aLFPT;
2309 //
9e9b826a 2310 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
ecf4f17c 2311 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
9e9b826a 2312 for (; aItLF.More(); aItLF.Next())
2313 {
2314 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2315 TopExp::MapShapesAndAncestors (aFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
2316 }
2317
2318 aItLF.Initialize (theLFImages);
ecf4f17c 2319 for (; aItLF.More(); ) {
2320 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2321 //
2322 // valid edges for this split
9e9b826a 2323 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
ecf4f17c 2324 // invalid edges for this split
9e9b826a 2325 const TopTools_IndexedMapOfShape* pMIE = theDMFMIE.Seek (aFIm);
ecf4f17c 2326 //
2327 bHasValid = Standard_False;
2328 bAllValid = Standard_True;
2329 bAllInvalid = Standard_True;
2330 bHasReallyInvalid = Standard_False;
2331 bAllInvNeutral = Standard_True;
e08a9b03 2332 bIsInvalidByInverted = Standard_True;
ecf4f17c 2333 aNbChecked = 0;
2334 //
2335 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2336 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2337 for (; aExp.More(); aExp.Next()) {
2338 const TopoDS_Shape& aEIm = aExp.Current();
2339 //
2340 bValid = theValidEdges.Contains(aEIm);
2341 bInvalid = theInvEdges.Contains(aEIm);
9e9b826a 2342 bNeutral = theMENeutral.Contains(aEIm);
ecf4f17c 2343 //
420b38fd 2344 if (!bValid && !bInvalid && !bNeutral) {
ecf4f17c 2345 // edge has not been checked for some reason
2346 continue;
2347 }
9e9b826a 2348
2349 // skip not-boundary edges originated from vertex
2350 if ((theEdgesInvalidByVertex.Contains (aEIm) ||
2351 theEdgesValidByVertex.Contains (aEIm)) &&
2352 aDMEF.FindFromKey (aEIm).Extent() != 1)
2353 continue;
2354
ecf4f17c 2355 ++aNbChecked;
2356 //
9e9b826a 2357 bInvalidLoc = pMIE && pMIE->Contains (aEIm);
420b38fd 2358 bHasReallyInvalid = bInvalid && bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
ecf4f17c 2359 if (bHasReallyInvalid) {
2360 break;
2361 }
2362 //
9e9b826a 2363 bValidLoc = pMVE && pMVE->Contains(aEIm);
e08a9b03 2364 bInverted = theMEInverted.Contains(aEIm);
420b38fd 2365 if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid) {
e08a9b03 2366 bInvalid = bInverted;
ecf4f17c 2367 }
2368 //
9e9b826a 2369 if (bValidLoc && bNeutral) {
ecf4f17c 2370 bHasValid = Standard_True;
2371 }
2372 //
e08a9b03 2373 bAllValid &= bValidLoc;
420b38fd 2374 bAllInvalid &= (bInvalid || bInvalidLoc);
e08a9b03 2375 bAllInvNeutral &= (bAllInvalid && bNeutral);
2376 bIsInvalidByInverted &= (bInvalidLoc || bInverted);
ecf4f17c 2377 }
2378 //
2379 if (!aNbChecked) {
2380 aItLF.Next();
2381 continue;
2382 }
2383 //
2384 if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) {
2385 // remove edges from neutral
2386 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2387 // remove face
2388 theLFImages.Remove(aItLF);
2389 continue;
2390 }
2391 //
2392 if (bHasReallyInvalid || (bAllInvalid &&
2393 !(bHasValid || bAllValid) &&
2394 !(bAllInvNeutral && (aNbChecked == 1)))) {
2395 theInvFaces.Append(aFIm);
0da0275c 2396 if (theMFHoles.Contains(aFIm)) {
2397 theMFInvInHole.Add(aFIm);
2398 }
a8232603 2399 aItLF.Next();
2400 continue;
ecf4f17c 2401 }
2402 //
0da0275c 2403 if (theMFHoles.Contains(aFIm)) {
2404 // remove edges from neutral
2405 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2406 // remove face
2407 theLFImages.Remove(aItLF);
2408 continue;
2409 }
2410 //
e08a9b03 2411 if (bIsInvalidByInverted && !(bHasValid || bAllValid))
2412 {
2413 // The face contains only the inverted and locally invalid edges
2414 theInvertedFaces.Append(aFIm);
2415 }
2416
ecf4f17c 2417 if (!bAllInvNeutral) {
2418 aLFPT.Append(aFIm);
2419 }
2420 else {
2421 // remove edges from neutral
2422 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
2423 }
2424 aItLF.Next();
2425 }
2426 //
2427 if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) {
2428 return;
2429 }
9e9b826a 2430
ecf4f17c 2431 // check the splits once more
2432 aItLF.Initialize(aLFPT);
2433 for (; aItLF.More(); aItLF.Next()) {
2434 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2435 //
2436 // valid edges for this split
9e9b826a 2437 const TopTools_MapOfShape* pMVE = theDMFMVE.Seek(aFIm);
ecf4f17c 2438 //
2439 bHasValid = Standard_False;
2440 bAllValid = Standard_True;
2441 bAllInvalid = Standard_True;
2442 //
2443 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
2444 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
2445 for (; aExp.More(); aExp.Next()) {
2446 const TopoDS_Shape& aEIm = aExp.Current();
2447 //
2448 bValid = theValidEdges.Contains(aEIm);
2449 bInvalid = theInvEdges.Contains(aEIm);
9e9b826a 2450 bNeutral = theMENeutral.Contains(aEIm) && !aMENRem.Contains (aEIm);
2451 bValidLoc = pMVE && pMVE->Contains(aEIm);
ecf4f17c 2452 //
e08a9b03 2453 if (!bInvalid && bTreatInvertedAsInvalid) {
ecf4f17c 2454 bInvalid = theMEInverted.Contains(aEIm);
2455 }
2456 //
9e9b826a 2457 if (bValidLoc && bNeutral) {
ecf4f17c 2458 bHasValid = Standard_True;
2459 }
2460 //
2461 bAllValid = bAllValid && bValidLoc;
2462 bAllInvalid = bAllInvalid && bInvalid;
2463 }
2464 //
2465 if (bAllInvalid && !bHasValid && !bAllValid) {
2466 theInvFaces.Append(aFIm);
2467 }
2468 }
2469}
2470
0da0275c 2471//=======================================================================
2472//function : FindFacesInsideHoleWires
2473//purpose : Find faces inside holes wires from the original face
2474//=======================================================================
2475void FindFacesInsideHoleWires(const TopoDS_Face& theFOrigin,
2476 const TopoDS_Face& theFOffset,
2477 const TopTools_ListOfShape& theLFImages,
2478 const TopTools_MapOfShape& theInvertedEdges,
2479 const TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
2ebb1098 2480 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
0da0275c 2481 TopTools_MapOfShape& theMFHoles,
2482 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
2483 Handle(IntTools_Context)& theContext)
2484{
2485 if (theLFImages.IsEmpty()) {
2486 return;
2487 }
2488 //
2489 // find all hole wires in the original face
2490 TopTools_ListOfShape aLHoleWires;
2491 const TopoDS_Wire& anOuterWire = BRepTools::OuterWire(theFOrigin);
2492 TopExp_Explorer aExpW(theFOrigin, TopAbs_WIRE);
2493 for (; aExpW.More(); aExpW.Next()) {
2494 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aExpW.Current());
2495 if (!aHoleWire.IsSame(anOuterWire) && aHoleWire.Orientation() != TopAbs_INTERNAL) {
2496 aLHoleWires.Append(aHoleWire);
2497 }
2498 }
2499 //
2500 if (aLHoleWires.IsEmpty()) {
2501 // no holes in the face
2502 return;
2503 }
2504 //
2505 TopTools_ListOfShape *pLFNewHoles = theDMFNewHoles.ChangeSeek(theFOrigin);
2506 //
2507 if (!pLFNewHoles) {
2508 pLFNewHoles = theDMFNewHoles.Bound(theFOrigin, TopTools_ListOfShape());
2509 }
2510 if (pLFNewHoles->IsEmpty()) {
2511 //
2512 // find the faces representing holes in the images of the faces:
2513 // 1. for each original hole wire try to build its image
2514 // 2. build the new planar face from the images
2515 //
2516 // map vertices and edges of the splits
2517 TopTools_IndexedMapOfShape aMESplits;
2518 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2519 for (; aItLF.More(); aItLF.Next()) {
2520 TopExp::MapShapes(aItLF.Value(), TopAbs_EDGE, aMESplits);
2521 }
2522 //
2523 TopTools_ListIteratorOfListOfShape aItLW(aLHoleWires);
2524 for (; aItLW.More(); aItLW.Next()) {
2525 const TopoDS_Wire& aHoleWire = TopoDS::Wire(aItLW.Value());
2526 // find images of all edges of the original wire
2527 TopTools_IndexedMapOfShape aMEImWire;
2528 TopoDS_Iterator aItE(aHoleWire);
2529 for (; aItE.More(); aItE.Next()) {
2530 const TopoDS_Shape& aEOr = aItE.Value();
2531 const TopTools_ListOfShape *pLEIm = theDMEOrLEIm.Seek(aEOr);
2532 if (!pLEIm || pLEIm->IsEmpty()) {
2533 continue;
2534 }
2535 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
2536 for (; aItLEIm.More(); aItLEIm.Next()) {
2537 const TopoDS_Shape& aEIm = aItLEIm.Value();
2538 if (aMESplits.Contains(aEIm)) {
2539 aMEImWire.Add(aEIm);
2540 }
2541 }
2542 }
2543 //
2544 if (aMEImWire.IsEmpty()) {
2545 continue;
2546 }
2547 //
2548 // build new planar face using these edges
1155d05a 2549 TopTools_ListOfShape aLE;
0da0275c 2550 Standard_Integer i, aNbE = aMEImWire.Extent();
2551 for (i = 1; i <= aNbE; ++i) {
2552 aLE.Append(aMEImWire(i).Oriented(TopAbs_FORWARD));
2553 aLE.Append(aMEImWire(i).Oriented(TopAbs_REVERSED));
2554 }
2555 //
2556 BOPAlgo_BuilderFace aBF;
2557 aBF.SetFace(TopoDS::Face(theFOffset.Oriented(TopAbs_FORWARD)));
2558 aBF.SetShapes(aLE);
2559 aBF.Perform();
2560 //
1155d05a 2561 const TopTools_ListOfShape& aLFNew = aBF.Areas();
0da0275c 2562 if (aLFNew.IsEmpty()) {
2563 continue;
2564 }
2565 //
2566 // check if outer edges in the new faces are not inverted
2567 // because the inverted edges mean that the hole has been
2568 // filled during offset and there will be no faces to remove
2569 TopTools_IndexedDataMapOfShapeListOfShape aDMEFNew;
2570 TopTools_ListIteratorOfListOfShape aItLFNew(aLFNew);
2571 for (; aItLFNew.More(); aItLFNew.Next()) {
2572 TopExp::MapShapesAndAncestors(aItLFNew.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFNew);
2573 }
2574 //
2575 aNbE = aDMEFNew.Extent();
2576 for (i = 1; i <= aNbE; ++i) {
2577 if (aDMEFNew(i).Extent() == 1) {
2578 const TopoDS_Shape& aE = aDMEFNew.FindKey(i);
2579 if (theInvertedEdges.Contains(aE)) {
2580 break;
2581 }
2582 }
2583 }
2584 //
2585 if (i <= aNbE) {
2586 continue;
2587 }
2588 //
2589 aItLFNew.Initialize(aLFNew);
2590 for (; aItLFNew.More(); aItLFNew.Next()) {
2591 pLFNewHoles->Append(aItLFNew.Value());
2592 }
2593 }
2594 }
2ebb1098 2595
2596 // Build Edge-Face map for splits of current offset face
2597 TopTools_IndexedDataMapOfShapeListOfShape anEFSplitsMap;
2598 // Build Edge-Face map for holes
2599 TopTools_IndexedDataMapOfShapeListOfShape anEFHolesMap;
2600
0da0275c 2601 // among the splits of the offset face find those that are
2602 // located inside the hole faces
0da0275c 2603 TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2604 for (; aItLF.More(); aItLF.Next()) {
2605 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
2ebb1098 2606 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFSplitsMap);
0da0275c 2607 // get the point inside the face and classify it relatively hole faces
2608 gp_Pnt aP3D;
2609 gp_Pnt2d aP2D;
2610 Standard_Integer iErr = BOPTools_AlgoTools3D::PointInFace(aFIm, aP3D, aP2D, theContext);
2611 if (iErr) {
2612 continue;
2613 }
2614 //
2615 Standard_Real aTol = BRep_Tool::Tolerance(aFIm);
2616 //
2617 TopTools_ListIteratorOfListOfShape aItLFNew(*pLFNewHoles);
2618 for (; aItLFNew.More(); aItLFNew.Next()) {
2619 const TopoDS_Face& aFNew = TopoDS::Face(aItLFNew.Value());
2620 if (theContext->IsValidPointForFace(aP3D, aFNew, aTol)) {
2621 // the face is classified as IN
2622 theMFHoles.Add(aFIm);
2ebb1098 2623 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFHolesMap);
0da0275c 2624 break;
2625 }
2626 }
2627 }
2ebb1098 2628
2629 // Out of all found holes find those which cannot be removed
2630 // by checking their connectivity to splits of other offset faces.
2631 // These are the faces, which will create uncovered holes if removed.
2632 const Standard_Integer aNbE = anEFHolesMap.Extent();
2633 for (Standard_Integer i = 1; i <= aNbE; ++i)
2634 {
2635 const TopoDS_Shape& anEdge = anEFHolesMap.FindKey(i);
2636 const TopTools_ListOfShape& aLFHoles = anEFHolesMap(i);
2637 // Check if the edge is outer for holes
2638 if (aLFHoles.Extent() != 1)
2639 continue;
2640
2641 const TopoDS_Shape& aFHole = aLFHoles.First();
2642 if (!theMFHoles.Contains(aFHole))
2643 // Already removed
2644 continue;
2645
2646 // Check if the edge is not outer for splits
2647 const TopTools_ListOfShape& aLSplits = anEFSplitsMap.FindFromKey(anEdge);
2648 if (aLSplits.Extent() == 1)
2649 continue;
2650
2651 // Check if edge is only connected to splits of the current offset face
2652 const TopTools_ListOfShape& aLFAll = theEFMap.FindFromKey(anEdge);
2653 if (aLFAll.Extent() == 2)
2654 // Avoid removal of the hole from the splits
2655 theMFHoles.Remove(aFHole);
2656 }
0da0275c 2657}
2658
ecf4f17c 2659//=======================================================================
2660//function : GetAverageTangent
2661//purpose : Computes average tangent vector along the curve
2662//=======================================================================
2663gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
2664 const Standard_Integer theNbP)
2665{
2666 gp_Vec aVA;
2667 TopExp_Explorer aExp(theS, TopAbs_EDGE);
2668 for (; aExp.More(); aExp.Next()) {
2669 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
2670 //
2671 Standard_Real aT1, aT2;
2672 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
2673 //
2674 gp_Pnt aP;
2675 gp_Vec aV, aVSum;
2676 Standard_Real aT = aT1;
2677 Standard_Real aDt = (aT2 - aT1) / theNbP;
2678 while (aT <= aT2) {
2679 aC->D1(aT, aP, aV);
2680 aVSum += aV.Normalized();
2681 aT += aDt;
2682 }
2683 //
2684 if (aE.Orientation() == TopAbs_REVERSED) {
2685 aVSum.Reverse();
2686 }
2687 //
2688 aVA += aVSum;
2689 }
2690 return aVA;
2691}
2692
2693//=======================================================================
2694//function : CheckInverted
2695//purpose : Checks if the edge has been inverted
2696//=======================================================================
2697Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
2698 const TopoDS_Face& theFOr,
2699 const TopTools_DataMapOfShapeListOfShape& theOEImages,
2700 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2701 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
ecf4f17c 2702 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
2703 const TopTools_IndexedMapOfShape& theMEdges,
2704 TopTools_MapOfShape& theMEInverted)
2705{
b6725456 2706 // It is necessary to compare the direction from first vertex
ecf4f17c 2707 // to the last vertex on the original edge with the
2708 // same direction on the new edge. If the directions
2709 // will be different - the edge has been inverted.
2710 //
2711 TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
2712 TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
2713 //
2714 Standard_Integer i;
2715 // find vertices of the offset shape
2716 TopExp::Vertices(theEIm, aVI1, aVI2);
2717 //
2718 // find images
2719 TopTools_ListOfShape aLEImages;
2720 if (theOEOrigins.IsBound(theEIm)) {
2721 TopoDS_Wire anImages;
2722 BRep_Builder().MakeWire(anImages);
2723 //
2724 TopTools_MapOfShape aMImFence;
2725 const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm);
2726 TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr);
2727 for (; aItOffset.More(); aItOffset.Next()) {
2728 const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
2729 const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr);
2730 //
2731 TopTools_ListIteratorOfListOfShape aItImages(aLImages);
2732 for (; aItImages.More(); aItImages.Next()) {
2733 const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
2734 if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) {
2735 BRep_Builder().Add(anImages, anIm);
2736 aLEImages.Append(anIm);
2737 }
2738 }
2739 }
2740 //
2741 // find alone vertices
2742 TopoDS_Vertex aVW1, aVW2;
2743 TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
2744 TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
2745 //
2746 TopTools_ListOfShape aLVAlone;
2747 Standard_Integer aNb = aDMImVE.Extent();
2748 for (i = 1; i <= aNb; ++i) {
2749 const TopTools_ListOfShape& aLImE = aDMImVE(i);
2750 if (aLImE.Extent() == 1) {
2751 aLVAlone.Append(aDMImVE.FindKey(i));
2752 }
2753 }
2754 //
2755 if (aLVAlone.Extent() > 1) {
2756 aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
2757 aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
2758 //
2759 // check distances
2760 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2761 const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1);
2762 const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2);
2763 //
2764 Standard_Real aDist1 = aPI1.SquareDistance(aPW1);
2765 Standard_Real aDist2 = aPI1.SquareDistance(aPW2);
2766 //
2767 if (aDist1 < aDist2) {
2768 aVI1 = aVW1;
2769 aVI2 = aVW2;
2770 }
2771 else {
2772 aVI1 = aVW2;
2773 aVI2 = aVW1;
2774 }
2775 }
2776 }
2777 else {
2778 aLEImages.Append(theEIm);
2779 }
2780 //
2781 // Find edges connected to these vertices
2782 const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1);
2783 const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2);
2784 //
2785 // Find vertices on the original face corresponding to vertices on the offset edge
2786 //
2787 // find original edges for both lists
2788 TopTools_ListOfShape aLOE1, aLOE2;
2789 for (i = 0; i < 2; ++i) {
2790 const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
2791 TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2792 //
2793 TopTools_MapOfShape aMFence;
2794 //
2795 TopTools_ListIteratorOfListOfShape aItLIE(aLIE);
2796 for (; aItLIE.More(); aItLIE.Next()) {
2797 const TopoDS_Shape& aEI = aItLIE.Value();
2798 if (theEdgesOrigins.IsBound(aEI)) {
2799 const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI);
2800 //
2801 TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins);
2802 for (; aItLOE.More(); aItLOE.Next()) {
2803 const TopoDS_Shape& aEO = aItLOE.Value();
2804 if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) {
2805 TopoDS_Shape aEOin;
420b38fd 2806 if (FindShape(aEO, theFOr, NULL, aEOin)) {
b443d536 2807 AppendToList(aLOE, aEO);
ecf4f17c 2808 }
2809 }
2810 }
2811 }
2812 }
2813 }
2814 //
2815 if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) {
2816 return Standard_False;
2817 }
2818 //
2819 // find vertices common for all edges in the lists
2820 for (i = 0; i < 2; ++i) {
2821 const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
2822 TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
2823 //
2824 const TopoDS_Shape& aEO = aLOE.First();
2825 TopExp_Explorer aExpV(aEO, TopAbs_VERTEX);
2826 for (; aExpV.More(); aExpV.Next()) {
2827 const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current();
2828 //
2829 Standard_Boolean bVertValid = Standard_True;
2830 TopTools_ListIteratorOfListOfShape aItLOE(aLOE);
2831 for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) {
2832 const TopoDS_Shape& aEOx = aItLOE.Value();
2833 TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX);
2834 for (; aExpVx.More(); aExpVx.Next()) {
2835 const TopoDS_Shape& aVx = aExpVx.Current();
2836 if (aVx.IsSame(aV)) {
2837 break;
2838 }
2839 }
2840 //
2841 if (!aExpVx.More()) {
2842 bVertValid = Standard_False;
2843 break;
2844 }
2845 }
2846 //
2847 if (bVertValid) {
2848 aVO = aV;
2849 break;
2850 }
2851 }
2852 }
2853 //
2854 if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) {
2855 return Standard_False;
2856 }
2857 //
2858 // check positions of the offset and original vertices
2859 const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
2860 const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2);
2861 const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1);
2862 const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2);
2863 //
2864 gp_Vec aVI(aPI1, aPI2);
2865 gp_Vec aVO(aPO1, aPO2);
2866 //
2867 Standard_Real anAngle = aVI.Angle(aVO);
2868 Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4;
2869 if (bInverted) {
2870 TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages);
2871 for (; aItLEIm.More(); aItLEIm.Next()) {
2872 const TopoDS_Shape& aEInvr = aItLEIm.Value();
2873 theMEInverted.Add(aEInvr);
2874 }
2875 }
2876 return bInverted;
2877}
2878
baaacd46 2879//=======================================================================
2880//function : CheckInvertedBlock
2881//purpose : Checks if it is possible to remove the block containing
2882// inverted edges
2883//=======================================================================
2884Standard_Boolean CheckInvertedBlock(const TopoDS_Shape& theCB,
2885 const TopTools_ListOfShape& theLCBF,
2886 const TopTools_MapOfShape& theMEInverted,
2887 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
2888 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVInverted,
2889 BRepOffset_DataMapOfShapeMapOfShape& theDMCBVAll)
2890{
2891 // For possible removal of the block:
2892 // 1. There should be more than just one face in the block
b2d1851c 2893 if (theCB.NbChildren() < 2) {
baaacd46 2894 return Standard_False;
2895 }
2896 //
2897 // 2. The block should at least contain two connected inverted edges with
2898 // different origins (not just two images/splits of the same edge)
2899 TopTools_MapOfShape aMECBInv;
2900 TopoDS_Compound aCECBInv;
2901 BRep_Builder().MakeCompound(aCECBInv);
2902 //
2903 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
2904 for (; aExp.More(); aExp.Next()) {
2905 const TopoDS_Shape& aE = aExp.Current();
2906 if (theMEInverted.Contains(aE)) {
2907 if (aMECBInv.Add(aE)) {
2908 BRep_Builder().Add(aCECBInv, aE);
2909 }
2910 }
2911 }
2912 //
2913 if (aMECBInv.Extent() < 2) {
2914 return Standard_False;
2915 }
2916 //
2917 // check that the edges are connected and different
2918 TopTools_ListOfShape aLCBE;
2919 BOPTools_AlgoTools::MakeConnexityBlocks(aCECBInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
2920 //
2921 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
2922 for (; aItLCBE.More(); aItLCBE.Next()) {
2923 const TopoDS_Shape& aCBE = aItLCBE.Value();
2924 // count the unique edges in the block
2925 Standard_Integer aNbUnique = 0;
2926 TopTools_MapOfShape aMEOrigins;
2927 TopoDS_Iterator aItE(aCBE);
2928 for (; aItE.More(); aItE.Next()) {
2929 const TopoDS_Shape& aE = aItE.Value();
2930 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
2931 if (!pLEOr) {
2932 aMEOrigins.Add(aE);
2933 ++aNbUnique;
2934 continue;
2935 }
2936 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
2937 for (; aItLEOr.More(); aItLEOr.Next()) {
2938 const TopoDS_Shape& aEOr = aItLEOr.Value();
2939 if (aMEOrigins.Add(aEOr)) {
2940 ++aNbUnique;
2941 }
2942 }
2943 }
2944 //
2945 if (aNbUnique >= 2) {
2946 break;
2947 }
2948 }
2949 //
2950 if (!aItLCBE.More()) {
2951 return Standard_False;
2952 }
2953 //
2954 // 3. the block should not contain inverted edges which vertices
2955 // are contained in other blocks
2956 //
2957 // collect vertices from inverted edges and compare them with
2958 // vertices from other blocks
2959 TopTools_MapOfShape* pMVInverted = theDMCBVInverted.ChangeSeek(theCB);
2960 TopTools_MapOfShape* pMVAll = theDMCBVAll.ChangeSeek(theCB);
2961 if (!pMVInverted) {
2962 pMVInverted = theDMCBVInverted.Bound(theCB, TopTools_MapOfShape());
2963 pMVAll = theDMCBVAll.Bound(theCB, TopTools_MapOfShape());
2964 //
2965 GetVerticesOnEdges(theCB, theMEInverted, *pMVInverted, *pMVAll);
2966 }
2967 //
2968 TopTools_ListIteratorOfListOfShape aItLCB1(theLCBF);
2969 for (; aItLCB1.More(); aItLCB1.Next()) {
2970 const TopoDS_Shape& aCB1 = aItLCB1.Value();
2971 if (aCB1.IsSame(theCB)) {
2972 continue;
2973 }
2974 //
2975 // collect vertices from inverted edges
2976 TopTools_MapOfShape* pMVInverted1 = theDMCBVInverted.ChangeSeek(aCB1);
2977 TopTools_MapOfShape* pMVAll1 = theDMCBVAll.ChangeSeek(aCB1);
2978 if (!pMVInverted1) {
2979 pMVInverted1 = theDMCBVInverted.Bound(aCB1, TopTools_MapOfShape());
2980 pMVAll1 = theDMCBVAll.Bound(aCB1, TopTools_MapOfShape());
2981 //
2982 GetVerticesOnEdges(aCB1, theMEInverted, *pMVInverted1, *pMVAll1);
2983 }
2984 //
2985 if (pMVInverted->HasIntersection(*pMVAll1)) {
2986 return Standard_False;
2987 }
2988 }
2989 //
2990 return Standard_True;
2991}
2992
2993//=======================================================================
2994//function : GetVerticesOnEdges
2995//purpose : Get vertices from the given shape belonging to the given edges
2996//=======================================================================
2997void GetVerticesOnEdges(const TopoDS_Shape& theCB,
2998 const TopTools_MapOfShape& theEdges,
2999 TopTools_MapOfShape& theVerticesOnEdges,
3000 TopTools_MapOfShape& theAllVertices)
3001{
3002 TopExp_Explorer aExp(theCB, TopAbs_EDGE);
3003 for (; aExp.More(); aExp.Next()) {
3004 const TopoDS_Shape& aE = aExp.Current();
3005 Standard_Boolean bOnGivenEdge = theEdges.Contains(aE);
3006 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
3007 theAllVertices.Add(aItV.Value());
3008 if (bOnGivenEdge) {
3009 theVerticesOnEdges.Add(aItV.Value());
3010 }
3011 }
3012 }
3013}
3014
ecf4f17c 3015//=======================================================================
3016//function : RemoveInvalidSplitsByInvertedEdges
3017//purpose : Looking for the invalid faces containing inverted edges
3018// that can be safely removed
3019//=======================================================================
3020void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
baaacd46 3021 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
ecf4f17c 3022 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3023 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3024 TopTools_IndexedMapOfShape& theMERemoved)
3025{
3026 if (theMEInverted.IsEmpty()) {
3027 return;
3028 }
3029 //
3030 // check the faces on regularity, i.e. the splits of the same face
3031 // should not be connected only by vertex. Such irregular splits
3032 // will have to be rebuilt and cannot be removed.
3033 //
baaacd46 3034 BRep_Builder aBB;
3035 TopTools_IndexedMapOfShape aMEAvoid;
ecf4f17c 3036 TopTools_DataMapOfShapeListOfShape aDMVF;
3037 Standard_Integer aNb = theFImages.Extent(), i;
3038 for (i = 1; i <= aNb; ++i) {
3039 const TopTools_ListOfShape& aLFIm = theFImages(i);
3040 //
3041 TopoDS_Compound aCFIm;
baaacd46 3042 aBB.MakeCompound(aCFIm);
ecf4f17c 3043 //
3044 TopTools_DataMapOfShapeListOfShape aDMEF;
3045 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3046 for (; aIt.More(); aIt.Next()) {
3047 const TopoDS_Shape& aF = aIt.Value();
baaacd46 3048 aBB.Add(aCFIm, aF);
ecf4f17c 3049 //
3050 // make a map to use only outer edges
3051 TopExp_Explorer aExp(aF, TopAbs_EDGE);
3052 for (; aExp.More(); aExp.Next()) {
3053 const TopoDS_Shape& aE = aExp.Current();
3054 //
3055 TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE);
3056 if (!pLF) {
baaacd46 3057 pLF = aDMEF.Bound(aE, TopTools_ListOfShape());
ecf4f17c 3058 }
3059 else {
ecf4f17c 3060 // internal edges should not be used
3061 aMEAvoid.Add(aE);
3062 }
baaacd46 3063 AppendToList(*pLF, aF);
ecf4f17c 3064 }
3065 //
3066 // fill connection map of the vertices of inverted edges to faces
3067 aExp.Init(aF, TopAbs_VERTEX);
3068 for (; aExp.More(); aExp.Next()) {
3069 const TopoDS_Shape& aV = aExp.Current();
3070 //
3071 TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV);
3072 if (!pLF) {
baaacd46 3073 pLF = aDMVF.Bound(aV, TopTools_ListOfShape());
ecf4f17c 3074 }
baaacd46 3075 AppendToList(*pLF, aF);
ecf4f17c 3076 }
3077 }
3078 //
3079 // for the splits to be regular they should form only one block
3080 TopTools_ListOfShape aLCBF;
3081 BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
baaacd46 3082 if (aLCBF.Extent() == 1) {
3083 continue;
3084 }
ecf4f17c 3085 //
baaacd46 3086 // check if the inverted edges create the irregularity
3087 BRepOffset_DataMapOfShapeMapOfShape aDMCBVInverted, aDMCBVAll;
3088 //
3089 TopTools_ListIteratorOfListOfShape aItLCB(aLCBF);
3090 for (; aItLCB.More(); aItLCB.Next()) {
3091 const TopoDS_Shape& aCB = aItLCB.Value();
3092 //
3093 // check if it is possible to remove the block
3094 if (!CheckInvertedBlock(aCB, aLCBF, theMEInverted, theOEOrigins, aDMCBVInverted, aDMCBVAll)) {
3095 // non of the edges in this block should be removed
3096 TopExp::MapShapes(aCB, TopAbs_EDGE, aMEAvoid);
3097 continue;
ecf4f17c 3098 }
3099 }
3100 }
3101 //
3102 // all edges not included in aMEAvoid can be removed
3103 TopTools_MapOfShape aMERem;
3104 TopTools_MapIteratorOfMapOfShape aItM(theMEInverted);
3105 for (; aItM.More(); aItM.Next()) {
3106 const TopoDS_Shape& aE = aItM.Value();
3107 if (!aMEAvoid.Contains(aE)) {
3108 TopoDS_Iterator aIt(aE);
3109 for (; aIt.More(); aIt.Next()) {
3110 const TopoDS_Shape& aV = aIt.Value();
3111 const TopTools_ListOfShape *pLF = aDMVF.Seek(aV);
3112 if (pLF && (pLF->Extent() > 3)) {
3113 aMERem.Add(aE);
3114 break;
3115 }
3116 }
3117 }
3118 }
3119 //
3120 if (aMERem.IsEmpty()) {
3121 return;
3122 }
3123 //
3124 // all invalid faces containing these edges can be removed
3125 TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
3126 TopTools_MapOfShape aMFRem;
3127 TopTools_IndexedMapOfShape aMFToUpdate;
3128 aNb = theInvFaces.Extent();
3129 for (i = 1; i <= aNb; ++i) {
3130 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3131 TopTools_ListOfShape& aLFIm = theInvFaces(i);
3132 //
3133 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3134 for (; aIt.More(); ) {
3135 const TopoDS_Shape& aFIm = aIt.Value();
3136 //
3137 // to be removed the face should have at least two not connected
3138 // inverted edges
3139 TopoDS_Compound aCEInv;
baaacd46 3140 aBB.MakeCompound(aCEInv);
ecf4f17c 3141 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
3142 for (; aExp.More(); aExp.Next()) {
3143 const TopoDS_Shape& aE = aExp.Current();
ecf4f17c 3144 if (aMERem.Contains(aE)) {
baaacd46 3145 aBB.Add(aCEInv, aE);
ecf4f17c 3146 }
3147 }
3148 //
3149 // check connectivity
3150 TopTools_ListOfShape aLCBE;
3151 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
3152 //
3153 if (aLCBE.Extent() >= 2) {
3154 aMFToUpdate.Add(aF);
3155 aMFRem.Add(aFIm);
3156 aLFIm.Remove(aIt);
3157 }
3158 else {
3159 aIt.Next();
3160 }
3161 }
3162 //
3163 if (aLFIm.Extent()) {
3164 aInvFaces.Add(aF, aLFIm);
3165 }
3166 }
3167 //
3168 if (aMFRem.IsEmpty()) {
3169 return;
3170 }
3171 //
3172 theInvFaces = aInvFaces;
3173 // remove from splits
3174 aNb = aMFToUpdate.Extent();
3175 for (i = 1; i <= aNb; ++i) {
3176 const TopoDS_Shape& aF = aMFToUpdate(i);
3177 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
3178 //
3179 TopTools_ListIteratorOfListOfShape aIt(aLFIm);
3180 for (; aIt.More(); ) {
3181 const TopoDS_Shape& aFIm = aIt.Value();
3182 if (aMFRem.Contains(aFIm)) {
3183 TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved);
3184 aLFIm.Remove(aIt);
3185 }
3186 else {
3187 aIt.Next();
3188 }
3189 }
3190 }
3191}
3192
3193//=======================================================================
3194//function : RemoveInvalidSplitsFromValid
3195//purpose : Removing invalid splits of faces from valid
3196//=======================================================================
3197void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3198 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3199 const TopTools_MapOfShape& theMEInverted,
9e9b826a 3200 const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
ecf4f17c 3201 TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
3202{
3203 // Decide whether to remove the found invalid faces or not.
3204 // The procedure is the following:
3205 // 1. Make connexity blocks from invalid faces;
3206 // 2. Find free edges in this blocks;
3207 // 3. If all free edges are valid for the faces - remove block.
3208 //
3209 TopTools_MapOfShape aMFence, aMFToRem;
3210 TopoDS_Compound aCFInv;
3211 BRep_Builder aBB;
3212 aBB.MakeCompound(aCFInv);
3213 TopTools_ListIteratorOfListOfShape aItLF;
3214 //
3215 // make compound of invalid faces
3216 TopTools_DataMapOfShapeShape aDMIFOF;
3217 Standard_Integer i, aNb = theInvFaces.Extent();
3218 for (i = 1; i <= aNb; ++i) {
3219 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3220 // artificially invalid faces should not be removed
3221 if (theArtInvFaces.IsBound(aF)) {
3222 continue;
3223 }
3224 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
3225 aItLF.Initialize(aLFInv);
3226 for (; aItLF.More(); aItLF.Next()) {
3227 const TopoDS_Shape& aFIm = aItLF.Value();
3228 if (aMFence.Add(aFIm)) {
3229 aBB.Add(aCFInv, aFIm);
3230 aDMIFOF.Bind(aFIm, aF);
3231 }
3232 }
3233 }
3234 //
3235 // make connexity blocks
3236 TopTools_ListOfShape aLCBInv;
3237 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
3238 //
3239 // analyze each block
3240 aItLF.Initialize(aLCBInv);
3241 for (; aItLF.More(); aItLF.Next()) {
3242 const TopoDS_Shape& aCB = aItLF.Value();
3243 //
3244 // if connexity block contains only one face - it should be removed;
3245 TopExp_Explorer aExp(aCB, TopAbs_FACE);
3246 aExp.Next();
3247 if (aExp.More()) {
3248 // check if there are valid images left
3249 aExp.Init(aCB, TopAbs_FACE);
3250 for (; aExp.More(); aExp.Next()) {
3251 const TopoDS_Shape& aFIm = aExp.Current();
3252 const TopoDS_Shape& aF = aDMIFOF.Find(aFIm);
3253 //
3254 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
3255 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
3256 //
3257 if (aLFIm.Extent() == aLFInv.Extent()) {
3258 break;
3259 }
3260 }
3261 }
3262 //
3263 if (!aExp.More()) {
3264 aExp.Init(aCB, TopAbs_FACE);
3265 for (; aExp.More(); aExp.Next()) {
3266 const TopoDS_Shape& aF = aExp.Current();
3267 aMFToRem.Add(aF);
3268 }
3269 continue;
3270 }
3271 //
3272 // remove faces connected by inverted edges
3273 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3274 TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3275 //
9e9b826a 3276 TopTools_DataMapOfShapeListOfShape aDMFF;
ecf4f17c 3277 aExp.Init(aCB, TopAbs_FACE);
3278 for (; aExp.More(); aExp.Next()) {
3279 const TopoDS_Shape& aFCB = aExp.Current();
9e9b826a 3280 const TopoDS_Shape& aF = aDMIFOF.Find (aFCB);
3281 TopTools_ListOfShape* pList = aDMFF.ChangeSeek (aF);
3282 if (!pList)
3283 pList = aDMFF.Bound (aF, TopTools_ListOfShape());
3284 pList->Append (aFCB);
3285 }
3286
3287 for (TopTools_DataMapOfShapeListOfShape::Iterator itM (aDMFF); itM.More(); itM.Next())
3288 {
3289 const TopoDS_Shape& aF = itM.Key();
3290 const TopTools_MapOfShape* pValidInverted = theDMFMVIE.Seek (aF);
3291
3292 // either remove all of these faces or none.
3293 const TopTools_ListOfShape& aLFCB = itM.Value();
3294 TopTools_ListOfShape::Iterator itL (aLFCB);
3295 for (; itL.More(); itL.Next())
3296 {
3297 const TopoDS_Shape& aFCB = itL.Value();
3298 TopExp_Explorer aExpE(aFCB, TopAbs_EDGE);
3299 for (; aExpE.More(); aExpE.Next()) {
3300 const TopoDS_Shape& aECB = aExpE.Current();
3301 if (pValidInverted && pValidInverted->Contains (aECB))
ecf4f17c 3302 break;
9e9b826a 3303 if (aDMEF.FindFromKey(aECB).Extent() > 1)
3304 {
3305 if (!theMEInverted.Contains(aECB))
3306 break;
ecf4f17c 3307 }
3308 }
9e9b826a 3309 if (!aExpE.More())
3310 // if one removed - remove all
3311 break;
ecf4f17c 3312 }
9e9b826a 3313 if (itL.More())
3314 {
3315 for (itL.Initialize (aLFCB); itL.More(); itL.Next())
3316 {
3317 aMFToRem.Add (itL.Value());
3318 }
ecf4f17c 3319 }
3320 }
3321 }
3322 //
3323 if (aMFToRem.Extent()) {
3324 // remove invalid faces from images
3325 aNb = theInvFaces.Extent();
3326 for (i = 1; i <= aNb; ++i) {
3327 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
3328 TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
3329 aItLF.Initialize(aLFImages);
3330 for (; aItLF.More();) {
3331 const TopoDS_Shape& aFIm = aItLF.Value();
3332 if (aMFToRem.Contains(aFIm)) {
3333 aLFImages.Remove(aItLF);
3334 }
3335 else {
3336 aItLF.Next();
3337 }
3338 }
3339 }
3340 }
3341}
3342
6f04cbb1 3343namespace
3344{
3345//=======================================================================
3346//function : buildPairs
3347//purpose : builds pairs of shapes
3348//=======================================================================
3349static void buildPairs (const TopTools_IndexedMapOfShape& theSMap,
3350 BRepOffset_DataMapOfShapeMapOfShape& theIntPairs)
3351{
3352 const Standard_Integer aNbS = theSMap.Extent();
3353 if (aNbS < 2)
3354 return;
3355 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3356 {
3357 const TopoDS_Shape& aS = theSMap (it1);
3358 if (!theIntPairs.IsBound (aS))
3359 theIntPairs.Bind (aS, TopTools_MapOfShape());
3360 }
3361
3362 for (Standard_Integer it1 = 1; it1 <= aNbS; ++it1)
3363 {
3364 const TopoDS_Shape& aS1 = theSMap (it1);
3365 TopTools_MapOfShape& aMap1 = theIntPairs (aS1);
3366 for (Standard_Integer it2 = it1 + 1; it2 <= aNbS; ++it2)
3367 {
3368 const TopoDS_Shape& aS2 = theSMap (it2);
3369 aMap1.Add (aS2);
3370 theIntPairs (aS2).Add (aS1);
3371 }
3372 }
3373}
3374
3375//=======================================================================
3376//function : buildIntersectionPairs
3377//purpose : builds intersection pairs
3378//=======================================================================
3379static void buildIntersectionPairs (const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3380 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3381 const BOPAlgo_Builder& theBuilder,
3382 const TopTools_MapOfShape& theMFRemoved,
3383 const TopTools_DataMapOfShapeShape& theFOrigins,
3384 NCollection_DataMap<TopoDS_Shape,
3385 BRepOffset_DataMapOfShapeMapOfShape,
3386 TopTools_ShapeMapHasher>& theIntPairs)
3387{
3388 TopAbs_ShapeEnum aCType = TopAbs_VERTEX;
3389 // Build connection map from vertices to faces
3390 TopTools_IndexedDataMapOfShapeListOfShape aDMVF;
3391 TopExp::MapShapesAndAncestors (theBuilder.Shape(), aCType, TopAbs_FACE, aDMVF);
3392
3393 const TopTools_DataMapOfShapeListOfShape& anImages = theBuilder.Images();
3394 const TopTools_DataMapOfShapeListOfShape& anOrigins = theBuilder.Origins();
3395
3396 // Find all faces connected to the not removed faces and build intersection pairs among them.
3397 // For removed faces intersect only those connected to each other.
3398
3399 for (Standard_Integer iF = 1; iF <= theInvFaces.Extent(); ++iF)
3400 {
3401 const TopoDS_Shape& aFInv = theInvFaces.FindKey (iF);
3402
3403 TopoDS_Compound aCF, aCFRem;
3404 BRep_Builder().MakeCompound (aCF);
3405 BRep_Builder().MakeCompound (aCFRem);
3406
3407 for (Standard_Integer iC = 0; iC < 2; ++iC)
3408 {
3409 const TopTools_ListOfShape& aLF = !iC ? theInvFaces (iF) : theFImages.FindFromKey (aFInv);
3410
3411 for (TopTools_ListOfShape::Iterator it (aLF); it.More(); it.Next())
3412 {
3413 TopTools_ListOfShape aLFIm;
3414 TakeModified (it.Value(), anImages, aLFIm);
3415
3416 for (TopTools_ListOfShape::Iterator itIm (aLFIm); itIm.More(); itIm.Next())
3417 {
3418 const TopoDS_Shape& aFIm = itIm.Value();
3419
3420 if (theMFRemoved.Contains (aFIm))
3421 BRep_Builder().Add (aCFRem, aFIm);
3422 else
3423 BRep_Builder().Add (aCF, aFIm);
3424 }
3425 }
3426 }
3427
3428 TopTools_ListOfShape aLCB;
3429 BOPTools_AlgoTools::MakeConnexityBlocks (aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
3430
3431 if (aLCB.IsEmpty())
3432 continue;
3433
3434 BRepOffset_DataMapOfShapeMapOfShape* pFInterMap =
3435 theIntPairs.Bound (aFInv, BRepOffset_DataMapOfShapeMapOfShape());
3436
3437 // build pairs for not removed faces
3438 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3439 {
3440 const TopoDS_Shape& aCB = itCB.Value();
3441
3442 TopTools_IndexedMapOfShape aMFInter;
3443 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3444 {
3445 const TopoDS_Shape& aCS = exp.Current();
3446 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3447 if (!pLFV)
3448 continue;
3449
3450 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3451 {
3452 const TopoDS_Shape& aFConnected = itFV.Value();
3453
3454 TopTools_ListOfShape aLFOr;
3455 TakeModified (aFConnected, anOrigins, aLFOr);
3456 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3457 {
3458 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3459 if (pFOr)
3460 aMFInter.Add (*pFOr);
3461 }
3462 }
3463 }
3464
3465 // build intersection pairs
3466 buildPairs (aMFInter, *pFInterMap);
3467 }
3468
3469 aLCB.Clear();
3470 BOPTools_AlgoTools::MakeConnexityBlocks (aCFRem, TopAbs_EDGE, TopAbs_FACE, aLCB);
3471
3472 if (aLCB.IsEmpty())
3473 continue;
3474
3475 for (TopTools_ListOfShape::Iterator itCB (aLCB); itCB.More(); itCB.Next())
3476 {
3477 const TopoDS_Shape& aCB = itCB.Value();
3478
3479 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
3480 for (TopExp_Explorer exp (aCB, aCType); exp.More(); exp.Next())
3481 {
3482 const TopoDS_Shape& aCS = exp.Current();
3483 const TopTools_ListOfShape* pLFV = aDMVF.Seek (aCS);
3484 if (!pLFV)
3485 continue;
3486
3487 for (TopTools_ListOfShape::Iterator itFV (*pLFV); itFV.More(); itFV.Next())
3488 {
3489 const TopoDS_Shape& aFConnected = itFV.Value();
3490 TopExp::MapShapesAndAncestors (aFConnected, TopAbs_EDGE, TopAbs_FACE, aDMEF);
3491 }
3492 }
3493
3494 for (Standard_Integer iE = 1; iE <= aDMEF.Extent(); ++iE)
3495 {
3496 const TopTools_ListOfShape& aLFConnected = aDMEF (iE);
3497 if (aLFConnected.Extent() < 2)
3498 continue;
3499
3500 TopTools_IndexedMapOfShape aMFInter;
3501 for (TopTools_ListOfShape::Iterator itLF (aLFConnected); itLF.More(); itLF.Next())
3502 {
3503 const TopoDS_Shape& aFConnected = itLF.Value();
3504
3505 TopTools_ListOfShape aLFOr;
3506 TakeModified (aFConnected, anOrigins, aLFOr);
3507 for (TopTools_ListOfShape::Iterator itOr (aLFOr); itOr.More(); itOr.Next())
3508 {
3509 const TopoDS_Shape* pFOr = theFOrigins.Seek (itOr.Value());
3510 if (pFOr)
3511 aMFInter.Add (*pFOr);
3512 }
3513 }
3514
3515 buildPairs (aMFInter, *pFInterMap);
3516 }
3517 }
3518 }
3519}
3520
3521}
3522
ecf4f17c 3523//=======================================================================
3524//function : RemoveInsideFaces
3525//purpose : Looking for the inside faces that can be safely removed
3526//=======================================================================
3527void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3528 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3529 const TopTools_DataMapOfShapeShape& theArtInvFaces,
3530 const TopTools_IndexedMapOfShape& theInvEdges,
e08a9b03 3531 const TopTools_MapOfShape& theInvertedEdges,
3532 const TopTools_ListOfShape& theInvertedFaces,
ecf4f17c 3533 const TopTools_IndexedMapOfShape& theMFToCheckInt,
0da0275c 3534 const TopTools_IndexedMapOfShape& theMFInvInHole,
3535 const TopoDS_Shape& theFHoles,
6f04cbb1 3536 BRepOffset_MakeOffset_InterResults& theIntRes,
ecf4f17c 3537 TopTools_IndexedMapOfShape& theMERemoved,
baaacd46 3538 TopTools_IndexedMapOfShape& theMEInside,
ecf4f17c 3539 TopoDS_Shape& theSolids)
3540{
1155d05a 3541 TopTools_ListOfShape aLS;
ecf4f17c 3542 TopTools_MapOfShape aMFence;
3543 TopTools_IndexedMapOfShape aMFInv;
3544 TopTools_ListIteratorOfListOfShape aItLF;
3545 TopTools_DataMapOfShapeShape aDMFImF;
3546 //
3547 Standard_Integer i, aNb = theFImages.Extent();
3548 for (i = 1; i <= aNb; ++i) {
3549 const TopoDS_Shape& aF = theFImages.FindKey(i);
3550 // to avoid intersection of the splits of the same
3551 // offset faces among themselves make compound of the
3552 // splits and use it as one argument
3553 TopoDS_Compound aCFImi;
3554 BRep_Builder().MakeCompound(aCFImi);
3555 //
3556 for (Standard_Integer j = 0; j < 2; ++j) {
3557 const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i);
3558 if (!pLFSp) {
3559 continue;
3560 }
3561 //
3562 aItLF.Initialize(*pLFSp);
3563 for (; aItLF.More(); aItLF.Next()) {
3564 const TopoDS_Shape& aFIm = aItLF.Value();
3565 if (aMFence.Add(aFIm)) {
3566 BRep_Builder().Add(aCFImi, aFIm);
3567 aDMFImF.Bind(aFIm, aF);
3568 if (!j) {
3569 aMFInv.Add(aFIm);
3570 }
3571 }
3572 }
3573 }
3574 //
3575 aLS.Append(aCFImi);
3576 }
3577 //
3578 // to make the solids more complete add for intersection also the faces
3579 // consisting only of invalid edges and not included into splits
3580 aNb = theMFToCheckInt.Extent();
3581 for (i = 1; i <= aNb; ++i) {
3582 const TopoDS_Shape& aFSp = theMFToCheckInt(i);
3583 if (aMFence.Add(aFSp)) {
3584 aLS.Append(aFSp);
3585 }
3586 }
3587 //
3588 BOPAlgo_MakerVolume aMV;
3589 aMV.SetArguments(aLS);
3590 aMV.SetIntersect(Standard_True);
3591 aMV.Perform();
e08a9b03 3592 if (aMV.HasErrors())
3593 return;
3594
ecf4f17c 3595 //
3596 // get shapes connection for using in the rebuilding process
3597 // for the cases in which some of the intersection left undetected
6f04cbb1 3598 ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theIntRes.SSInterfs);
ecf4f17c 3599 //
3600 // find faces to remove
3601 const TopoDS_Shape& aSols = aMV.Shape();
3602 //
3603 TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
3604 TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
3605 //
3606 aNb = aDMFS.Extent();
3607 if (!aNb) {
3608 return;
3609 }
3610 //
3611 // To use the created solids for classifications, firstly, it is necessary
3612 // to check them on validity - the created solids should be complete,
3613 // i.e. all faces should be included.
3614 //
0da0275c 3615 TopTools_MapOfShape aMFToRem;
ecf4f17c 3616 // Check completeness
3617 if (aMV.HasDeleted()) {
0da0275c 3618 TopTools_IndexedMapOfShape aMEHoles;
3619 TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles);
bc4a3867 3620
3621 // Map edges of the solids to check the connectivity
3622 // of the removed invalid splits
3623 TopTools_IndexedMapOfShape aMESols;
3624 TopExp::MapShapes(aSols, TopAbs_EDGE, aMESols);
3625
ecf4f17c 3626 // perform additional check on faces
3627 aNb = theFImages.Extent();
3628 for (i = 1; i <= aNb; ++i) {
3629 const TopTools_ListOfShape& aLFIm = theFImages(i);
3630 if (aLFIm.IsEmpty()) {
3631 continue;
3632 }
bc4a3867 3633
3634 const TopoDS_Shape& aF = theFImages.FindKey(i);
3635 Standard_Boolean bInvalid = theInvFaces.Contains(aF);
3636 // For invalid faces it is allowed to be at least connected
3637 // to the solids, otherwise the solids are considered as broken
3638 Standard_Boolean bConnected = Standard_False;
3639
0da0275c 3640 Standard_Boolean bFaceKept = Standard_False;
ecf4f17c 3641 aItLF.Initialize(aLFIm);
3642 for (; aItLF.More(); aItLF.Next()) {
3643 const TopoDS_Shape& aFIm = aItLF.Value();
3644 if (!aMV.IsDeleted(aFIm)) {
0da0275c 3645 bFaceKept = Standard_True;
3646 continue;
3647 }
3648 //
3649 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
3650 for (; aExpE.More(); aExpE.Next()) {
3651 if (aMEHoles.Contains(aExpE.Current())) {
3652 bFaceKept = Standard_True;
3653 aMFToRem.Add(aFIm);
3654 break;
3655 }
bc4a3867 3656 if (!bFaceKept && bInvalid && !bConnected)
3657 bConnected = aMESols.Contains(aExpE.Current());
ecf4f17c 3658 }
3659 }
3660 //
bc4a3867 3661 if (!bFaceKept && !bConnected) {
ecf4f17c 3662 return;
3663 }
3664 }
3665 }
3666 //
baaacd46 3667 TopTools_IndexedMapOfShape aMEBoundary;
ecf4f17c 3668 aNb = aDMFS.Extent();
3669 for (i = 1; i <= aNb; ++i) {
baaacd46 3670 const TopoDS_Shape& aFIm = aDMFS.FindKey(i);
ecf4f17c 3671 const TopTools_ListOfShape& aLSol = aDMFS(i);
3672 if (aLSol.Extent() > 1) {
ecf4f17c 3673 aMFToRem.Add(aFIm);
3674 }
baaacd46 3675 else if (aFIm.Orientation() != TopAbs_INTERNAL) {
3676 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary);
3677 }
ecf4f17c 3678 }
e08a9b03 3679
3680 // Tool for getting the splits of faces
3681 const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
3682
ecf4f17c 3683 // update invalid faces with images
3684 aNb = aMFInv.Extent();
3685 for (i = 1; i <= aNb; ++i) {
3686 const TopoDS_Shape& aFInv = aMFInv(i);
e08a9b03 3687 TakeModified(aFInv, aMVIms, aMFInv);
ecf4f17c 3688 }
e08a9b03 3689
3690 // Take into account the faces invalid by inverted edges
3691 for (TopTools_ListOfShape::Iterator itLF(theInvertedFaces); itLF.More(); itLF.Next())
3692 TakeModified(itLF.Value(), aMVIms, aMFInv);
3693
0da0275c 3694 // check if the invalid faces inside the holes are really invalid:
3695 // check its normal direction - if it has changed relatively the
3696 // original face the offset face is invalid and should be kept for rebuilding
3697 Standard_Integer aNbFH = theMFInvInHole.Extent();
3698 for (i = 1; i <= aNbFH; ++i) {
3699 const TopoDS_Shape& aFInv = theMFInvInHole(i);
3700 TopTools_ListOfShape aLFInvIm = aMV.Modified(aFInv);
3701 if (aLFInvIm.IsEmpty()) {
3702 aLFInvIm.Append(aFInv);
3703 }
3704 //
3705 const TopoDS_Shape *pFOffset = aDMFImF.Seek(aFInv);
3706 if (!pFOffset) {
3707 continue;
3708 }
3709 TopTools_ListIteratorOfListOfShape aItLFInv(aLFInvIm);
3710 for (; aItLFInv.More(); aItLFInv.Next()) {
3711 const TopoDS_Shape& aFInvIm = aItLFInv.Value();
3712 const TopTools_ListOfShape* pLSols = aDMFS.Seek(aFInvIm);
3713 if (!pLSols || pLSols->Extent() != 1) {
3714 continue;
3715 }
3716 //
3717 const TopoDS_Shape& aFSol = pLSols->First();
3718 //
3719 TopoDS_Shape aFx;
420b38fd 3720 if (!FindShape(aFInvIm, aFSol, NULL, aFx)) {
0da0275c 3721 continue;
3722 }
3723 //
3724 if (BRepOffset_Tool::CheckPlanesNormals(TopoDS::Face(aFx), TopoDS::Face(*pFOffset))) {
3725 // the normal direction has not changed, thus the face can be removed
3726 aMFToRem.Add(aFInvIm);
3727 }
3728 }
3729 }
3730 //
ecf4f17c 3731 TopoDS_Compound aSolids;
3732 BRep_Builder().MakeCompound(aSolids);
b443d536 3733 TopTools_MapOfShape aMFKeep;
ecf4f17c 3734 //
3735 TopExp_Explorer aExpS(aSols, TopAbs_SOLID);
3736 for (; aExpS.More(); aExpS.Next()) {
3737 const TopoDS_Shape& aSol = aExpS.Current();
3738 //
3739 Standard_Boolean bAllInv(Standard_True), bAllRemoved(Standard_True);
3740
45d0af05 3741 for (TopExp_Explorer aExpF(aSol, TopAbs_FACE); aExpF.More(); aExpF.Next())
3742 {
ecf4f17c 3743 const TopoDS_Shape& aFS = aExpF.Current();
3744 //
3745 if (aFS.Orientation() == TopAbs_INTERNAL) {
3746 aMFToRem.Add(aFS);
e08a9b03 3747 continue;
ecf4f17c 3748 }
e08a9b03 3749
3750 if (aMFToRem.Contains(aFS))
3751 continue;
3752
3753 bAllRemoved = false;
3754 bAllInv &= aMFInv.Contains(aFS);
ecf4f17c 3755 }
3756 //
3757 if (bAllInv && !bAllRemoved) {
3758 // remove invalid faces but keep those that have already been marked for removal
3759 TopExp_Explorer aExpF(aSol, TopAbs_FACE);
3760 for (; aExpF.More(); aExpF.Next()) {
3761 const TopoDS_Shape& aFS = aExpF.Current();
3762 //
3763 if (aMFToRem.Contains(aFS)) {
b443d536 3764 if (!aMFKeep.Add(aFS)) {
3765 aMFKeep.Remove(aFS);
3766 }
ecf4f17c 3767 }
3768 else {
3769 aMFToRem.Add(aFS);
3770 }
3771 }
3772 }
3773 else {
3774 BRep_Builder().Add(aSolids, aSol);
3775 theSolids = aSolids;
3776 }
3777 }
3778 //
b443d536 3779 TopTools_MapIteratorOfMapOfShape aItM(aMFKeep);
3780 for (; aItM.More(); aItM.Next()) {
3781 aMFToRem.Remove(aItM.Value());
3782 }
bc4a3867 3783
3784 // Remove the invalid hanging parts external to the solids
e08a9b03 3785 RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, theInvertedEdges, aMFToRem);
bc4a3867 3786
3787 // Remove newly found internal and hanging faces
ecf4f17c 3788 RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
3789 RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
baaacd46 3790 //
3791 // Get inside faces from the removed ones comparing them with boundary edges
3792 aNb = theMERemoved.Extent();
3793 for (i = 1; i <= aNb; ++i) {
3794 const TopoDS_Shape& aE = theMERemoved(i);
3795 if (!aMEBoundary.Contains(aE)) {
3796 theMEInside.Add(aE);
3797 }
3798 }
6f04cbb1 3799
3800 // build all possible intersection pairs basing on the intersection results
3801 // taking into account removed faces.
3802 if (aMFToRem.Extent())
3803 buildIntersectionPairs (theFImages, theInvFaces, aMV, aMFToRem, aDMFImF, theIntRes.InterPairs);
ecf4f17c 3804}
3805
3806//=======================================================================
3807//function : ShapesConnections
3808//purpose : Looking for the connections between faces not to miss
3809// some necessary intersection
3810//=======================================================================
3811void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3812 const TopTools_IndexedMapOfShape& theInvEdges,
3813 const TopTools_DataMapOfShapeShape& theDMFOr,
3814 BOPAlgo_Builder& theBuilder,
3815 TopTools_DataMapOfShapeListOfShape& theSSInterfs)
3816{
3817 // update invalid edges with images and keep connection to original edge
3818 TopTools_DataMapOfShapeListOfShape aDMEOr;
45d0af05 3819 Standard_Integer aNb = theInvEdges.Extent();
3820 for (Standard_Integer i = 1; i <= aNb; ++i) {
ecf4f17c 3821 const TopoDS_Shape& aEInv = theInvEdges(i);
3822 const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv);
3823 if (aLEIm.IsEmpty()) {
3824 aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv);
3825 continue;
3826 }
3827 //
3828 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
3829 for (; aItLEIm.More(); aItLEIm.Next()) {
3830 const TopoDS_Shape& aEIm = aItLEIm.Value();
3831 //
3832 TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm);
3833 if (!pLEOr) {
3834 pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape());
3835 }
3836 AppendToList(*pLEOr, aEInv);
3837 }
3838 }
3839 //
3840 // get shapes connections for using in the rebuilding process
3841 const BOPDS_PDS& pDS = theBuilder.PDS();
3842 // analyze all Face/Face intersections
3843 const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
1155d05a 3844 Standard_Integer iInt, aNbFF = aFFs.Length();
ecf4f17c 3845 for (iInt = 0; iInt < aNbFF; ++iInt) {
3846 const BOPDS_InterfFF& aFF = aFFs(iInt);
3847 const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
1155d05a 3848 Standard_Integer aNbC = aVNC.Length();
ecf4f17c 3849 if (!aNbC) {
3850 continue;
3851 }
3852 //
3853 const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1());
3854 const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2());
3855 //
3856 const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1);
3857 const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2);
3858 //
3859 if (!pF1 || !pF2) {
3860 continue;
3861 }
3862 //
3863 if (pF1->IsSame(*pF2)) {
3864 continue;
3865 }
3866 //
3867 Standard_Boolean bInv1 = theInvFaces.Contains(*pF1);
3868 Standard_Boolean bInv2 = theInvFaces.Contains(*pF2);
3869 //
3870 if (!bInv1 && !bInv2) {
3871 continue;
3872 }
3873 //
3874 // check if it is real Face/Face intersection
3875 TopTools_MapOfShape aMEInt;
3876 for (Standard_Integer iC = 0; iC < aNbC; ++iC) {
3877 const BOPDS_Curve& aNC = aVNC(iC);
3878 const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
3879 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
3880 for (; aItLPB.More(); aItLPB.Next()) {
3881 const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
3882 Standard_Integer nEInt;
3883 if (aPB->HasEdge(nEInt)) {
3884 const TopoDS_Shape& aEInt = pDS->Shape(nEInt);
3885 aMEInt.Add(aEInt);
3886 }
3887 }
3888 }
3889 //
3890 if (aMEInt.IsEmpty()) {
3891 continue;
3892 }
3893 //
3894 // check if invalid edges of the face are in the same splits with intersection edges
3895 for (Standard_Integer i = 0; i < 2; ++i) {
3896 if ((!i && !bInv1) || (i && !bInv2)) {
3897 continue;
3898 }
3899 //
3900 const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
3901 const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
3902 const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
3903 //
3904 Standard_Boolean bFound = Standard_False;
3905 //
3906 TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm);
3907 if (aLFIm.IsEmpty()) {
3908 aLFIm.Append(aFIm);
3909 }
3910 //
3911 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
3912 for (; aItLFIm.More(); aItLFIm.Next()) {
3913 const TopoDS_Shape& aFImIm = aItLFIm.Value();
3914 //
3915 Standard_Boolean bInv(Standard_False), bInt(Standard_False);
3916 TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE);
3917 for (; aExpE.More(); aExpE.Next()) {
3918 const TopoDS_Shape& aE = aExpE.Current();
3919 if (!bInv) {
3920 bInv = aDMEOr.IsBound(aE);
3921 }
3922 if (!bInt) {
3923 bInt = aMEInt.Contains(aE);
3924 }
3925 if (bInv && bInt) {
3926 break;
3927 }
3928 }
3929 //
3930 if (!bInt || !bInv) {
3931 continue;
3932 }
3933 //
3934 bFound = Standard_True;
3935 //
3936 // append opposite face to all invalid edges in the split
3937 aExpE.Init(aFImIm, TopAbs_EDGE);
3938 for (; aExpE.More(); aExpE.Next()) {
3939 const TopoDS_Shape& aE = aExpE.Current();
3940 const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE);
3941 if (!pLEOr) {
3942 continue;
3943 }
3944 //
3945 TopTools_ListIteratorOfListOfShape aItLE(*pLEOr);
3946 for (; aItLE.More(); aItLE.Next()) {
3947 const TopoDS_Shape& aEOr = aItLE.Value();
3948 TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr);
3949 if (!pLFE) {
3950 pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape());
3951 }
3952 AppendToList(*pLFE, aFOp);
3953 }
3954 }
3955 }
3956 if (bFound) {
3957 // save connection between offset faces
3958 TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF);
3959 if (!pLF) {
3960 pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape());
3961 }
3962 AppendToList(*pLF, aFOp);
3963 }
3964 }
3965 }
3966}
3967
bc4a3867 3968//=======================================================================
3969//function : RemoveHangingParts
3970//purpose : Remove isolated invalid hanging parts
3971//=======================================================================
3972void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
3973 const TopTools_DataMapOfShapeShape& theDMFImF,
3974 const TopTools_IndexedMapOfShape& theMFInv,
3975 const TopTools_IndexedMapOfShape& theInvEdges,
e08a9b03 3976 const TopTools_MapOfShape& theInvertedEdges,
bc4a3867 3977 TopTools_MapOfShape& theMFToRem)
3978{
3979 // Map the faces of the result solids to filter them from avoided faces
3980 TopTools_IndexedMapOfShape aMFS;
3981 TopExp::MapShapes(theMV.Shape(), TopAbs_FACE, aMFS);
3982
3983 BRep_Builder aBB;
3984 // Build compound of all faces not included into solids
3985 TopoDS_Compound aCFHangs;
3986 aBB.MakeCompound(aCFHangs);
3987
3988 // Tool for getting the splits of faces
1155d05a 3989 const TopTools_DataMapOfShapeListOfShape& aMVIms = theMV.Images();
bc4a3867 3990
3991 TopTools_ListIteratorOfListOfShape aItLArgs(theMV.Arguments());
3992 for (; aItLArgs.More(); aItLArgs.Next())
3993 {
3994 TopExp_Explorer anExpF(aItLArgs.Value(), TopAbs_FACE);
3995 for (; anExpF.More(); anExpF.Next())
3996 {
3997 const TopoDS_Shape& aF = anExpF.Current();
e08a9b03 3998 TakeModified(aF, aMVIms, aCFHangs, &aMFS);
bc4a3867 3999 }
4000 }
4001
4002 // Make connexity blocks of all hanging parts and check that they are isolated
1155d05a 4003 TopTools_ListOfShape aLCBHangs;
bc4a3867 4004 BOPTools_AlgoTools::MakeConnexityBlocks(aCFHangs, TopAbs_EDGE, TopAbs_FACE, aLCBHangs);
4005 if (aLCBHangs.IsEmpty())
4006 return;
4007
4008 // To be removed, the block should contain invalid splits of offset faces and should
4009 // meet one of the following conditions:
4010 // 1. The block should not be connected to any invalid parts (Faces or Edges)
4011 // contained in solids;
4012 // 2. The block should be isolated from other faces, i.e. it should consist of
4013 // the splits of the single offset face.
4014
4015 // Map the edges and vertices of the result solids to check connectivity
4016 // of the hanging blocks to invalid parts contained in solids
4017 TopTools_IndexedDataMapOfShapeListOfShape aDMEF, aDMVE;
4018 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_EDGE , TopAbs_FACE, aDMEF);
4019 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
4020
4021 // Update invalid edges with intersection results
4022 TopTools_MapOfShape aMEInv;
4023 Standard_Integer i, aNbE = theInvEdges.Extent();
e08a9b03 4024 for (i = 1; i <= aNbE; ++i)
4025 TakeModified(theInvEdges(i), aMVIms, aMEInv);
4026
4027 // Update inverted edges with intersection results
4028 TopTools_MapOfShape aMEInverted;
4029 for (TopTools_MapIteratorOfMapOfShape itM(theInvertedEdges); itM.More(); itM.Next())
4030 TakeModified(itM.Value(), aMVIms, aMEInverted);
bc4a3867 4031
4032 // Tool for getting the origins of the splits
1155d05a 4033 const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
bc4a3867 4034
e08a9b03 4035 // Find hanging blocks to remove
4036 TopTools_ListOfShape aBlocksToRemove;
4037
1155d05a 4038 TopTools_ListIteratorOfListOfShape aItLCBH(aLCBHangs);
bc4a3867 4039 for (; aItLCBH.More(); aItLCBH.Next())
4040 {
4041 const TopoDS_Shape& aCBH = aItLCBH.Value();
4042
e08a9b03 4043 // Remove the block containing the inverted edges
4044 Standard_Boolean bHasInverted = Standard_False;
4045 TopExp_Explorer anExpE(aCBH, TopAbs_EDGE);
4046 for (; anExpE.More() && !bHasInverted; anExpE.Next())
4047 {
4048 const TopoDS_Shape& aE = anExpE.Current();
4049 bHasInverted = !aDMEF .Contains(aE) &&
4050 aMEInverted.Contains(aE);
4051 }
4052
4053 if (bHasInverted)
4054 {
4055 aBlocksToRemove.Append(aCBH);
4056 continue;
4057 }
4058
bc4a3867 4059 // Check the block to contain invalid split
4060 Standard_Boolean bHasInvalidFace = Standard_False;
4061 // Check connectivity to invalid parts
4062 Standard_Boolean bIsConnected = Standard_False;
4063 TopTools_IndexedMapOfShape aBlockME;
4064 TopExp::MapShapes(aCBH, TopAbs_EDGE, aBlockME);
4065 // Map to collect all original faces
4066 TopTools_MapOfShape aMOffsetF;
4067
4068 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
4069 for (; anExpF.More(); anExpF.Next())
4070 {
4071 const TopoDS_Shape& aF = anExpF.Current();
4072 // Check block to contain invalid face
4073 if (!bHasInvalidFace)
4074 bHasInvalidFace = theMFInv.Contains(aF);
4075
4076 // Check block for connectivity to invalid parts
4077 if (!bIsConnected)
4078 {
4079 // check edges
e08a9b03 4080 anExpE.Init(aF, TopAbs_EDGE);
bc4a3867 4081 for (; anExpE.More() && !bIsConnected; anExpE.Next())
4082 {
4083 const TopoDS_Shape& aE = anExpE.Current();
4084 const TopTools_ListOfShape *pLF = aDMEF.Seek(aE);
4085 if (pLF)
4086 {
4087 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
4088 for (; aItLF.More() && !bIsConnected; aItLF.Next())
4089 bIsConnected = theMFInv.Contains(aItLF.Value());
4090 }
4091 }
4092 // check vertices
e08a9b03 4093 if (!bIsConnected)
bc4a3867 4094 {
e08a9b03 4095 TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
4096 for (; anExpV.More() && !bIsConnected; anExpV.Next())
bc4a3867 4097 {
e08a9b03 4098 const TopoDS_Shape& aV = anExpV.Current();
4099 const TopTools_ListOfShape *pLE = aDMVE.Seek(aV);
4100 if (pLE)
4101 {
4102 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
4103 for (; aItLE.More() && !bIsConnected; aItLE.Next())
4104 bIsConnected = !aBlockME.Contains(aItLE.Value()) &&
4105 aMEInv .Contains(aItLE.Value());
4106 }
bc4a3867 4107 }
4108 }
4109 }
4110
4111 // Check block to be isolated
1155d05a 4112 const TopTools_ListOfShape* pLFOr = aMVOrs.Seek(aF);
bc4a3867 4113 if (pLFOr)
4114 {
4115 TopTools_ListIteratorOfListOfShape aItLFOr(*pLFOr);
4116 for (; aItLFOr.More(); aItLFOr.Next())
4117 {
4118 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aItLFOr.Value());
4119 if (pFOffset)
4120 aMOffsetF.Add(*pFOffset);
4121 }
4122 }
4123 else
4124 {
4125 const TopoDS_Shape* pFOffset = theDMFImF.Seek(aF);
4126 if (pFOffset)
4127 aMOffsetF.Add(*pFOffset);
4128 }
4129 }
4130
4131 Standard_Boolean bRemove = bHasInvalidFace &&
4132 (!bIsConnected || aMOffsetF.Extent() == 1);
4133
4134 if (bRemove)
e08a9b03 4135 aBlocksToRemove.Append(aCBH);
4136 }
4137
4138 // remove the invalidated blocks
4139 aItLCBH.Initialize(aBlocksToRemove);
4140 for (; aItLCBH.More(); aItLCBH.Next())
4141 {
4142 const TopoDS_Shape& aCBH = aItLCBH.Value();
4143 TopExp_Explorer anExpF(aCBH, TopAbs_FACE);
4144 for (; anExpF.More(); anExpF.Next())
4145 theMFToRem.Add(anExpF.Current());
bc4a3867 4146 }
4147}
4148
ecf4f17c 4149//=======================================================================
4150//function : RemoveValidSplits
4151//purpose : Removing valid splits according to results of intersection
4152//=======================================================================
4153void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
4154 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
4155 BOPAlgo_Builder& theGF,
4156 TopTools_IndexedMapOfShape& theMERemoved)
4157{
4158 Standard_Integer i, aNb = theImages.Extent();
4159 if (!aNb) {
4160 return;
4161 }
4162 //
4163 for (i = 1; i <= aNb; ++i) {
4164 TopTools_ListOfShape& aLSIm = theImages(i);
4165 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
4166 for (; aIt.More(); ) {
4167 const TopoDS_Shape& aSIm = aIt.Value();
4168 if (theSpRem.Contains(aSIm)) {
4169 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4170 aLSIm.Remove(aIt);
4171 continue;
4172 }
4173 //
4174 // check if all its images are have to be removed
4175 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
4176 if (aLSImIm.Extent()) {
4177 Standard_Boolean bAllRem = Standard_True;
4178 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
4179 for (; aIt1.More(); aIt1.Next()) {
4180 const TopoDS_Shape& aSImIm = aIt1.Value();
4181 if (theSpRem.Contains(aSImIm)) {
4182 TopExp::MapShapes(aSImIm, TopAbs_EDGE, theMERemoved);
4183 }
4184 else {
4185 bAllRem = Standard_False;
4186 }
4187 }
4188 //
4189 if (bAllRem) {
4190 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4191 aLSIm.Remove(aIt);
4192 continue;
4193 }
4194 }
4195 aIt.Next();
4196 }
4197 }
4198}
4199
4200//=======================================================================
4201//function : RemoveInvalidSplits
4202//purpose : Removing invalid splits according to the results of intersection
4203//=======================================================================
4204void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
4205 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4206 const TopTools_IndexedMapOfShape& theInvEdges,
4207 TopTools_IndexedDataMapOfShapeListOfShape& theImages,
4208 BOPAlgo_Builder& theGF,
4209 TopTools_IndexedMapOfShape& theMERemoved)
4210{
4211 Standard_Integer i, aNb = theImages.Extent();
4212 if (!aNb) {
4213 return;
4214 }
4215 //
4216 for (i = 1; i <= aNb; ++i) {
4217 const TopoDS_Shape& aS = theImages.FindKey(i);
4218 Standard_Boolean bArt = theArtInvFaces.IsBound(aS);
4219 //
4220 TopTools_ListOfShape& aLSIm = theImages(i);
4221 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
4222 for (; aIt.More();) {
4223 const TopoDS_Shape& aSIm = aIt.Value();
4224 if (theSpRem.Contains(aSIm)) {
4225 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4226 aLSIm.Remove(aIt);
4227 continue;
4228 }
4229 //
4230 // check if all its images are have to be removed
4231 const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
4232 if (aLSImIm.IsEmpty()) {
4233 aIt.Next();
4234 continue;
4235 }
4236 //
4237 Standard_Boolean bAllRem = Standard_True;
4238 TopTools_IndexedMapOfShape aMERemoved;
4239 TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
4240 for (; aIt1.More(); aIt1.Next()) {
4241 const TopoDS_Shape& aSImIm = aIt1.Value();
4242 if (theSpRem.Contains(aSImIm)) {
4243 TopExp::MapShapes(aSImIm, TopAbs_EDGE, aMERemoved);
4244 }
4245 else {
4246 bAllRem = Standard_False;
4247 }
4248 }
4249 //
4250 if (bAllRem) {
4251 aLSIm.Remove(aIt);
4252 continue;
4253 }
4254 //
4255 if (bArt) {
4256 aIt.Next();
4257 continue;
4258 }
4259 //
4260 // remove the face from invalid if all invalid edges of this face
4261 // have been marked for removal
4262 TopExp_Explorer aExpE(aSIm, TopAbs_EDGE);
4263 for (; aExpE.More(); aExpE.Next()) {
4264 const TopoDS_Shape& aEInv = aExpE.Current();
4265 if (theInvEdges.Contains(aEInv) && !aMERemoved.Contains(aEInv)) {
4266 break;
4267 }
4268 }
4269 if (!aExpE.More()) {
4270 TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
4271 aLSIm.Remove(aIt);
4272 }
4273 else {
4274 aIt.Next();
4275 }
4276 }
4277 }
4278}
4279
4280//=======================================================================
4281//function : FilterEdgesImages
4282//purpose : Updating the maps of images and origins of the offset edges
4283//=======================================================================
4284void FilterEdgesImages(const TopoDS_Shape& theS,
4285 TopTools_DataMapOfShapeListOfShape& theOEImages,
4286 TopTools_DataMapOfShapeListOfShape& theOEOrigins)
4287{
4288 // map edges
4289 TopTools_IndexedMapOfShape aME;
4290 TopExp::MapShapes(theS, TopAbs_EDGE, aME);
4291 //
4292 theOEOrigins.Clear();
4293 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(theOEImages);
4294 for (; aItDM.More(); aItDM.Next()) {
4295 const TopoDS_Shape& aE = aItDM.Key();
4296 TopTools_ListOfShape& aLEIm = aItDM.ChangeValue();
4297 //
4298 TopTools_ListIteratorOfListOfShape aIt(aLEIm);
4299 for (; aIt.More(); ) {
4300 const TopoDS_Shape& aEIm = aIt.Value();
4301 // filter images
4302 if (!aME.Contains(aEIm)) {
4303 // remove the image
4304 // edges with no images left should be kept in the map
4305 // to avoid their usage when building the splits of faces
4306 aLEIm.Remove(aIt);
4307 continue;
4308 }
4309 //
4310 // save origins
4311 if (theOEOrigins.IsBound(aEIm)) {
4312 AppendToList(theOEOrigins.ChangeFind(aEIm), aE);
4313 }
4314 else {
4315 TopTools_ListOfShape aLOr;
4316 aLOr.Append(aE);
4317 theOEOrigins.Bind(aEIm, aLOr);
4318 }
4319 //
4320 aIt.Next();
4321 }
4322 }
4323}
4324
4325//=======================================================================
4326//function : FilterInvalidFaces
4327//purpose : Filtering of the invalid faces
4328//=======================================================================
9e9b826a 4329void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
baaacd46 4330 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
9e9b826a 4331 const TopTools_IndexedMapOfShape& theInvEdges,
baaacd46 4332 const TopTools_IndexedMapOfShape& theMERemoved,
ecf4f17c 4333 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4334 TopTools_DataMapOfShapeShape& theArtInvFaces)
4335{
4336 //
4337 // filter invalid faces, considering faces having only valid
4338 // images left with non-free edges as valid
4339 // do not remove invalid faces if it creates free edges
4340 //
4341 TopTools_IndexedDataMapOfShapeListOfShape aReallyInvFaces;
9e9b826a 4342 // Edge-Face connexity map of all splits, both invalid and valid
4343 TopTools_IndexedDataMapOfShapeListOfShape aDMEFAll;
ecf4f17c 4344 TopTools_ListIteratorOfListOfShape aItLF;
4345 //
9e9b826a 4346 const Standard_Integer aNb = theInvFaces.Extent();
4347 for (Standard_Integer i = 1; i <= aNb; ++i) {
ecf4f17c 4348 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4349 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4350 //
4351 if (theArtInvFaces.IsBound(aF)) {
4352 if (aLFInv.IsEmpty()) {
4353 theArtInvFaces.UnBind(aF);
4354 }
4355 else {
4356 aReallyInvFaces.Add(aF, aLFInv);
4357 }
4358 continue;
4359 }
4360 //
4361 if (aLFInv.IsEmpty()) {
4362 continue;
4363 }
4364 //
9e9b826a 4365 TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
ecf4f17c 4366 Standard_Boolean bInvalid = aLFIm.IsEmpty();
4367 //
4368 if (!bInvalid) {
4369 // check two lists on common splits
4370 aItLF.Initialize(aLFInv);
4371 for (; aItLF.More(); aItLF.Next()) {
4372 const TopoDS_Shape& aFInv = aItLF.Value();
4373 //
4374 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4375 for (; aItLFIm.More(); aItLFIm.Next()) {
4376 const TopoDS_Shape& aFIm = aItLFIm.Value();
4377 //
4378 if (aFInv.IsSame(aFIm)) {
4379 break;
4380 }
4381 }
4382 //
4383 if (aItLFIm.More()) {
4384 break;
4385 }
4386 }
4387 //
4388 bInvalid = aItLF.More();
4389 }
4390 //
4391 if (!bInvalid) {
4392 // check for free edges
4393 for (Standard_Integer j = 0; !bInvalid && j < 2; ++j) {
4394 const TopTools_ListOfShape& aLI = !j ? aLFIm : aLFInv;
4395 aItLF.Initialize(aLI);
4396 for (; aItLF.More(); aItLF.Next()) {
4397 const TopoDS_Shape& aFIm = aItLF.Value();
4398 //
4399 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4400 for (; aExp.More(); aExp.Next()) {
4401 const TopoDS_Shape& aE = aExp.Current();
baaacd46 4402 if (!theMERemoved.Contains(aE)) {
4403 const TopTools_ListOfShape* pLEF = theDMEF.Seek(aE);
4404 if (pLEF && pLEF->Extent() == 1) {
ecf4f17c 4405 break;
4406 }
4407 }
4408 }
4409 //
4410 if (aExp.More()) {
4411 break;
4412 }
4413 }
4414 bInvalid = aItLF.More();
4415 }
4416 }
9e9b826a 4417 if (bInvalid)
4418 {
4419 if (aDMEFAll.IsEmpty())
4420 {
4421 aDMEFAll = theDMEF;
4422 for (Standard_Integer iF = 1; iF <= aNb; ++iF)
4423 for (TopTools_ListOfShape::Iterator itLFInv (theInvFaces(iF)); itLFInv.More(); itLFInv.Next())
4424 TopExp::MapShapesAndAncestors (itLFInv.Value(), TopAbs_EDGE, TopAbs_FACE, aDMEFAll);
4425 }
4426
4427 TopTools_MapOfShape aLocalSplits;
4428 for (Standard_Integer j = 0; j < 2; ++j)
4429 for (aItLF.Initialize((!j ? aLFIm : aLFInv)); aItLF.More(); aItLF.Next())
4430 aLocalSplits.Add (aItLF.Value());
4431
4432 // Check if all invalid edges are located inside the split and do not touch
4433 // any other faces both invalid and valid
4434 aItLF.Initialize(aLFInv);
4435 for (; aItLF.More(); aItLF.Next())
4436 {
4437 const TopoDS_Shape& aFIm = aItLF.Value();
4438 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
4439 for (; aExp.More(); aExp.Next())
4440 {
4441 const TopoDS_Shape& aE = aExp.Current();
4442 if (theInvEdges.Contains (aE) && !theMERemoved.Contains (aE))
4443 {
4444 const TopTools_ListOfShape& aLF = aDMEFAll.FindFromKey (aE);
4445 TopTools_ListOfShape::Iterator itLF (aLF);
4446 for (; itLF.More(); itLF.Next())
4447 {
4448 if (!aLocalSplits.Contains (itLF.Value()))
4449 break;
4450 }
4451 if (itLF.More())
4452 break;
4453 }
4454 }
4455 if (aExp.More())
4456 break;
4457 }
4458 bInvalid = aItLF.More();
4459 if (!bInvalid)
4460 {
4461 aItLF.Initialize(aLFInv);
4462 for (; aItLF.More(); aItLF.Next())
4463 AppendToList (aLFIm, aItLF.Value());
4464 }
4465 }
ecf4f17c 4466 //
4467 if (bInvalid) {
4468 aReallyInvFaces.Add(aF, aLFInv);
4469 }
4470 }
4471 //
4472 theInvFaces = aReallyInvFaces;
4473}
4474
4b59685a 4475//=======================================================================
4476//function : CheckEdgesCreatedByVertex
4477//purpose : Checks additionally the unchecked edges originated from vertices
4478//=======================================================================
4479void CheckEdgesCreatedByVertex (const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4480 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4481 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4482 const TopTools_IndexedMapOfShape& theValidEdges,
4483 TopTools_IndexedMapOfShape& theInvEdges)
4484{
4485 // Mark the unchecked edges contained in invalid faces as invalid
4486 const Standard_Integer aNbF = theInvFaces.Extent();
4487 for (Standard_Integer i = 1; i <= aNbF; ++i)
4488 {
4489 const TopoDS_Shape& aF = theInvFaces.FindKey (i);
4490 if (theArtInvFaces.IsBound (aF))
4491 continue;
4492
4493 const TopTools_ListOfShape& aLFIm = theInvFaces (i);
4494 for (TopTools_ListOfShape::Iterator it (aLFIm); it.More(); it.Next())
4495 {
4496 const TopoDS_Shape& aFIm = it.Value();
4497 for (TopExp_Explorer expE (aFIm, TopAbs_EDGE); expE.More(); expE.Next())
4498 {
4499 const TopoDS_Shape& aE = expE.Current();
4500 if (theInvEdges.Contains (aE)
4501 || theValidEdges.Contains (aE))
4502 {
4503 continue;
4504 }
4505
4506 // check if this edges is created by vertex
4507 const TopTools_ListOfShape* pLEOr = theEdgesOrigins.Seek (aE);
4508 if (!pLEOr)
4509 continue;
4510 TopTools_ListOfShape::Iterator itLEO (*pLEOr);
4511 for (; itLEO.More(); itLEO.Next())
4512 {
4513 if (itLEO.Value().ShapeType() != TopAbs_VERTEX)
4514 break;
4515 }
4516 if (!itLEO.More())
4517 {
4518 theInvEdges.Add (aE);
4519 }
4520 }
4521 }
4522 }
4523}
4524
ecf4f17c 4525//=======================================================================
4526//function : FilterInvalidEdges
4527//purpose : Filtering the invalid edges according to currently invalid faces
4528//=======================================================================
4529void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4530 const TopTools_DataMapOfShapeShape& theArtInvFaces,
9e9b826a 4531 const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
ecf4f17c 4532 const TopTools_IndexedMapOfShape& theMERemoved,
4533 TopTools_IndexedMapOfShape& theInvEdges)
4534{
4535 TopoDS_Compound aCEInv;
4536 TopTools_IndexedMapOfShape aMEInv;
4537 BRep_Builder aBB;
4538 aBB.MakeCompound(aCEInv);
4539 TopTools_ListIteratorOfListOfShape aItLF;
4540 //
4541 Standard_Integer i, aNb = theInvFaces.Extent();
4542 for (i = 1; i <= aNb; ++i) {
4543 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4544 aItLF.Initialize(aLFInv);
4545 for (; aItLF.More(); aItLF.Next()) {
4546 const TopoDS_Shape& aFIm = aItLF.Value();
4547 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEInv);
4548 //
4549 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4550 for (; aExpE.More(); aExpE.Next()) {
4551 const TopoDS_Shape& aE = aExpE.Current();
4552 if (theInvEdges.Contains(aE)) {
4553 aBB.Add(aCEInv, aE);
4554 }
4555 }
4556 }
4557 }
4558 //
4559 // remove edges which have been marked for removal
4560 TopTools_IndexedMapOfShape aMEInvToAvoid;
4561 TopTools_ListOfShape aLCBE;
4562 BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
4563 //
4564 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
4565 for (; aItLCBE.More(); aItLCBE.Next()) {
4566 const TopoDS_Shape& aCBE = aItLCBE.Value();
4567 TopExp_Explorer aExpCB(aCBE, TopAbs_EDGE);
4568 for (; aExpCB.More(); aExpCB.Next()) {
4569 const TopoDS_Shape& aE = aExpCB.Current();
4570 if (!theMERemoved.Contains(aE)) {
4571 break;
4572 }
4573 }
4574 //
4575 if (!aExpCB.More()) {
4576 TopExp::MapShapes(aCBE, TopAbs_EDGE, aMEInvToAvoid);
4577 }
4578 }
4579 //
4580 TopTools_IndexedMapOfShape aReallyInvEdges;
4581 //
4582 aNb = theInvFaces.Extent();
4583 for (i = 1; i <= aNb; ++i) {
4584 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4585 if (theArtInvFaces.IsBound(aF)) {
9e9b826a 4586 const TopTools_IndexedMapOfShape& aMIE = theDMFMIE.Find(aF);
4587 const Standard_Integer aNbIE = aMIE.Extent();
4588 for (Standard_Integer iE = 1; iE <= aNbIE; ++iE)
4589 {
4590 const TopoDS_Shape& aE = aMIE (iE);
ecf4f17c 4591 if (aMEInv.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4592 aReallyInvEdges.Add(aE);
4593 }
4594 }
4595 }
4596 else {
4597 const TopTools_ListOfShape& aLFInv = theInvFaces(i);
4598 aItLF.Initialize(aLFInv);
4599 for (; aItLF.More(); aItLF.Next()) {
4600 const TopoDS_Shape& aFIm = aItLF.Value();
4601 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
4602 for (; aExpE.More(); aExpE.Next()) {
4603 const TopoDS_Shape& aE = aExpE.Current();
4604 if (theInvEdges.Contains(aE) && !aMEInvToAvoid.Contains(aE)) {
4605 aReallyInvEdges.Add(aE);
4606 }
4607 }
4608 }
4609 }
4610 }
4611 //
4612 theInvEdges = aReallyInvEdges;
4613}
4614
4615//=======================================================================
4616//function : FindFacesToRebuild
4617//purpose : Looking for the faces that have to be rebuilt:
4618// 1. Faces close to invalidity
4619// 2. Faces containing some invalid parts
4620//=======================================================================
4621void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape& theLFImages,
4622 const TopTools_IndexedMapOfShape& theInvEdges,
4623 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4624 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4625 TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4626 TopTools_MapOfShape& theFSelfRebAvoid)
4627{
4628 Standard_Integer i, aNb = theLFImages.Extent();
4629 if (!aNb) {
4630 return;
4631 }
4632 //
4633 Standard_Boolean bRebuild;
4634 TopTools_ListIteratorOfListOfShape aItLF;
4635 TopTools_ListOfShape aLEValid;
4636 TopTools_MapOfShape aMFence, aMEReb, aMFReb;
4637 TopExp_Explorer aExp;
4638 //
4639 TopTools_DataMapOfShapeListOfShape aDMFLV;
4640 // get edges from invalid faces
4641 aNb = theInvFaces.Extent();
4642 for (i = 1; i <= aNb; i++) {
4643 const TopoDS_Shape& aF = theInvFaces.FindKey(i);
4644 aMFence.Clear();
4645 TopTools_ListOfShape aLVAvoid;
4646 const TopTools_ListOfShape& aLFIm = theInvFaces(i);
4647 aItLF.Initialize(aLFIm);
4648 for (; aItLF.More(); aItLF.Next()) {
4649 const TopoDS_Shape& aFIm = aItLF.Value();
4650 aExp.Init(aFIm, TopAbs_EDGE);
4651 for (; aExp.More(); aExp.Next()) {
4652 const TopoDS_Shape& aE = aExp.Current();
4653 aMEReb.Add(aE);
4654 if (theInvEdges.Contains(aE)) {
4655 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
4656 for (; aExpV.More(); aExpV.Next()) {
4657 const TopoDS_Shape& aV = aExpV.Current();
4658 if (aMFence.Add(aV)) {
4659 aLVAvoid.Append(aV);
4660 aMEReb.Add(aV);
4661 }
4662 }
4663 }
4664 }
4665 }
4666 //
4667 if (aLVAvoid.Extent()) {
4668 aDMFLV.Bind(aF, aLVAvoid);
4669 }
4670 //
4671 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aF);
4672 if (pLF) {
4673 TopTools_ListIteratorOfListOfShape aItLFE(*pLF);
4674 for (; aItLFE.More(); aItLFE.Next()) {
4675 const TopoDS_Shape& aFE = aItLFE.Value();
4676 aMFReb.Add(aFE);
4677 }
4678 }
4679 }
4680 //
4681 // get face to rebuild
4682 aNb = theLFImages.Extent();
4683 for (i = 1; i <= aNb; i++) {
4684 const TopoDS_Shape& aF = theLFImages.FindKey(i);
4685 const TopTools_ListOfShape& aLFIm = theLFImages(i);
4686 TopTools_MapOfShape aMVAvoid;
4687 if (aDMFLV.IsBound(aF)) {
4688 const TopTools_ListOfShape& aLVAvoid = aDMFLV.Find(aF);
4689 TopTools_ListIteratorOfListOfShape aItLV(aLVAvoid);
4690 for (; aItLV.More(); aItLV.Next()) {
4691 const TopoDS_Shape& aV = aItLV.Value();
4692 aMVAvoid.Add(aV);
4693 }
4694 }
4695 //
4696 bRebuild = aMFReb.Contains(aF);
4697 aLEValid.Clear();
4698 aMFence.Clear();
4699 //
4700 aItLF.Initialize(aLFIm);
4701 for (; aItLF.More(); aItLF.Next()) {
4702 const TopoDS_Shape& aFIm = aItLF.Value();
4703 aExp.Init(aFIm, TopAbs_EDGE);
4704 for (; aExp.More(); aExp.Next()) {
4705 const TopoDS_Edge& anEIm = TopoDS::Edge(aExp.Current());
4706 if (!theInvEdges.Contains(anEIm)) {
4707 if (aMFence.Add(anEIm)) {
4708 aLEValid.Append(anEIm);
4709 }
4710 }
4711 //
4712 if (!bRebuild) {
4713 bRebuild = aMEReb.Contains(anEIm);
4714 }
4715 //
4716 if (!bRebuild) {
4717 // check vertices
4718 TopExp_Explorer aExpV(anEIm, TopAbs_VERTEX);
4719 for (; aExpV.More() && !bRebuild; aExpV.Next()) {
4720 const TopoDS_Shape& aV = aExpV.Current();
4721 if (!aMVAvoid.Contains(aV)) {
4722 bRebuild = aMEReb.Contains(aV);
4723 }
4724 }
4725 }
4726 }
4727 }
4728 //
4729 if (!bRebuild) {
4730 bRebuild = aLFIm.Extent() && theInvFaces.Contains(aF);
4731 if (bRebuild) {
4732 theFSelfRebAvoid.Add(aF);
4733 }
4734 }
4735 //
4736 if (bRebuild) {
4737 theFToRebuild.Add(aF, aLEValid);
4738 }
4739 }
4740}
4741
4742//=======================================================================
4743//function : RebuildFaces
4744//purpose : Rebuilding of the faces
4745//=======================================================================
4746void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4747 const TopTools_MapOfShape& theFSelfRebAvoid,
4748 const TopoDS_Shape& theSolids,
6f04cbb1 4749 const BRepOffset_MakeOffset_InterResults& theIntRes,
bea10656 4750 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 4751 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
0da0275c 4752 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
ecf4f17c 4753 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4754 TopTools_DataMapOfShapeShape& theFacesOrigins,
4755 TopTools_DataMapOfShapeListOfShape& theOEImages,
4756 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4757 TopTools_MapOfShape& theLastInvEdges,
4758 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4759 TopTools_IndexedMapOfShape& theInvEdges,
4760 TopTools_IndexedMapOfShape& theValidEdges,
4761 const TopTools_MapOfShape& theInvertedEdges,
4762 TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
4763 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4764 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4765 TopTools_MapOfShape& theVertsToAvoid,
4766 TopTools_DataMapOfShapeShape& theETrimEInf,
4767 Handle(BRepAlgo_AsDes)& theAsDes)
4768{
4769 TopTools_MapOfShape aModifiedEdges;
4770 //
4771 // 1. Intersect faces
6f04cbb1 4772 IntersectFaces(theFToRebuild, theFSelfRebAvoid, theSolids, theIntRes, theFImages, theEdgesOrigins, theOEImages,
ecf4f17c 4773 theOEOrigins, theInvEdges, theValidEdges, theInvertedEdges, theEdgesToAvoid,
4774 theInvFaces, theArtInvFaces, theVertsToAvoid, theETrimEInf, aModifiedEdges, theAsDes);
4775 //
4776 // 2. Repeat steps to build the correct faces
bea10656 4777 BuildSplitsOfInvFaces(theFToRebuild, aModifiedEdges, theAnalyse, theFImages, theDMFNewHoles, theEdgesOrigins,
ecf4f17c 4778 theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
4779 theEdgesToAvoid, theVertsToAvoid, theAlreadyInvFaces, theValidEdges,
4780 theETrimEInf, theAsDes);
4781}
4782
4783//=======================================================================
4784//function : IntersectFaces
4785//purpose : Intersection of the faces that should be rebuild
4786// to resolve all invalidities
4787//=======================================================================
4788void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4789 const TopTools_MapOfShape& theFSelfRebAvoid,
4790 const TopoDS_Shape& theSolids,
6f04cbb1 4791 const BRepOffset_MakeOffset_InterResults& theIntRes,
ecf4f17c 4792 TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4793 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
4794 TopTools_DataMapOfShapeListOfShape& theOEImages,
4795 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
4796 TopTools_IndexedMapOfShape& theInvEdges,
4797 TopTools_IndexedMapOfShape& theValidEdges,
4798 const TopTools_MapOfShape& theInvertedEdges,
4799 TopTools_IndexedMapOfShape& theEdgesToAvoid,
4800 TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4801 const TopTools_DataMapOfShapeShape& theArtInvFaces,
4802 TopTools_MapOfShape& theVertsToAvoid,
4803 TopTools_DataMapOfShapeShape& theETrimEInf,
4804 TopTools_MapOfShape& theModifiedEdges,
4805 Handle(BRepAlgo_AsDes)& theAsDes)
4806{
4807 Standard_Integer aNbFR = theFToRebuild.Extent();
4808 if (!aNbFR) {
4809 return;
4810 }
4811 //
4812 Standard_Integer i, j, k, aNbInv;
4813 TopTools_ListIteratorOfListOfShape aItLF, aItLE;
ecf4f17c 4814 //
4815 // get vertices from invalid edges
4816 TopTools_MapOfShape aMVInv, aMVInvAll;
4817 aNbInv = theInvEdges.Extent();
4818 for (i = 1; i <= aNbInv; ++i) {
4819 const TopoDS_Shape& aEInv = theInvEdges(i);
4820 Standard_Boolean bValid = theValidEdges.Contains(aEInv);
45d0af05 4821 for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next()) {
ecf4f17c 4822 const TopoDS_Shape& aV = aExp.Current();
4823 aMVInvAll.Add(aV);
4824 if (!bValid) {
4825 aMVInv.Add(aV);
4826 }
4827 }
4828 }
4829 //
4830 Standard_Boolean bLookVertToAvoid = (aMVInv.Extent() > 0);
4831 //
4832 TopTools_DataMapOfShapeListOfShape aDMSF, aMDone, aMEInfETrim, aDMVEFull;
4833 TopTools_IndexedDataMapOfShapeListOfShape aFLE, aDMEFInv;
4834 //
4835 // Add all faces to rebuild to outgoing map <aFLE>,
4836 // plus link edges and vertices to the faces to
4837 // define intersection faces
4838 PrepareFacesForIntersection(theFToRebuild, theFImages, theInvFaces, theArtInvFaces,
4839 bLookVertToAvoid, aFLE, aMDone, aDMSF, aMEInfETrim,
4840 aDMVEFull, theETrimEInf, aDMEFInv);
4841
4842 // Find vertices to avoid while trimming the edges.
4843 // These vertices are taken from the invalid edges common between
4844 // splits of different invalid, but not artificially, faces.
4845 // Additional condition for these vertices is that all
4846 // edges adjacent to this vertex must be either invalid
4847 // or contained in invalid faces
4848 TopTools_MapOfShape aMVRInv = theVertsToAvoid;
bc4a3867 4849 FindVerticesToAvoid(aDMEFInv, theInvEdges, theValidEdges, theInvertedEdges,
4850 aDMVEFull, theOEImages, theOEOrigins, aMVRInv);
ecf4f17c 4851 //
4852 // The faces should be intersected selectively -
4853 // intersect only faces neighboring to the same invalid face
4854 // and connected to its invalid edges;
4855 // when dealing with artificially invalid faces for intersection to be
4856 // complete we need to use not only invalid edges, but also the
4857 // edges connected to invalid ones
b443d536 4858
4859 // find blocks of artificially invalid faces
4860 TopTools_DataMapOfShapeShape aDMFImF;
4861 TopoDS_Compound aCFArt;
4862 BRep_Builder().MakeCompound(aCFArt);
ecf4f17c 4863 TopTools_DataMapIteratorOfDataMapOfShapeShape aItM(theArtInvFaces);
4864 for (; aItM.More(); aItM.Next()) {
4865 const TopoDS_Shape& aF = aItM.Key();
4866 const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
4867 aItLF.Initialize(aLFInv);
4868 for (; aItLF.More(); aItLF.Next()) {
b443d536 4869 BRep_Builder().Add(aCFArt, aItLF.Value());
4870 aDMFImF.Bind(aItLF.Value(), aF);
ecf4f17c 4871 }
4872 }
4873 //
b443d536 4874 // make connexity blocks
4875 TopTools_ListOfShape aLCBArt;
4876 BOPTools_AlgoTools::MakeConnexityBlocks(aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt);
4877 //
4878 // alone edges
a8232603 4879 TopTools_MapOfShape aMEAlone, aMEInvOnArt;
b443d536 4880 //
4881 TopTools_ListIteratorOfListOfShape aItLCBArt(aLCBArt);
4882 for (; aItLCBArt.More(); aItLCBArt.Next()) {
4883 const TopoDS_Shape& aCB = aItLCBArt.Value();
41aa3c3d 4884 //
b443d536 4885 // check if aCB contains splits of only one offset face
4886 TopTools_MapOfShape aMFArt;
4887 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
4888 for (; aExpF.More(); aExpF.Next()) {
4889 aMFArt.Add(aDMFImF.Find(aExpF.Current()));
41aa3c3d 4890 }
4891 //
b443d536 4892 Standard_Boolean bAlone = (aMFArt.Extent() == 1);
41aa3c3d 4893 //
b443d536 4894 // vertices on invalid edges
4895 TopTools_MapOfShape aMVEInv;
4896 TopTools_MapOfShape aMFence;
4897 // edges that should not be marked as alone - edges having same origins as invalid ones
4898 TopTools_MapOfShape aMEAvoid;
4899 // map to find alone edges by looking for free vertices
4900 TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal;
4901 //
4902 TopExp_Explorer aExpE(aCB, TopAbs_EDGE);
4903 for (; aExpE.More(); aExpE.Next()) {
4904 const TopoDS_Shape& aE = aExpE.Current();
4905 if (theInvEdges.Contains(aE)) {
a8232603 4906 aMEInvOnArt.Add(aE);
b443d536 4907 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
4908 aMVEInv.Add(aItV.Value());
4909 }
4910 //
4911 if (bAlone) {
4912 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4913 if (pLEOr) {
4914 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4915 for (; aItLEOr.More(); aItLEOr.Next()) {
4916 TopTools_ListIteratorOfListOfShape aItLEIm(theOEImages.Find(aItLEOr.Value()));
4917 for (; aItLEIm.More(); aItLEIm.Next()) {
4918 aMEAvoid.Add(aItLEIm.Value());
4919 }
4920 }
4921 }
4922 }
4923 continue;
4924 }
4925 //
4926 if (aMFence.Add(aE)) {
4927 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal);
ecf4f17c 4928 }
41aa3c3d 4929 }
4930 //
b443d536 4931 // find edges with free vertices
4932 Standard_Integer aNbV = aDMVEVal.Extent();
4933 for (i = 1; i <= aNbV; ++i) {
4934 const TopoDS_Shape& aV = aDMVEVal.FindKey(i);
4935 if (!aMVEInv.Contains(aV)) {
4936 continue;
4937 }
ecf4f17c 4938 //
b443d536 4939 const TopTools_ListOfShape& aLEV = aDMVEVal(i);
4940 if (aLEV.Extent() > 1) {
4941 continue;
4942 }
4943 //
4944 const TopoDS_Shape& aE = aLEV.First();
4945 if (aMEAvoid.Contains(aE)) {
4946 continue;
4947 }
4948 //
4949 aMEAlone.Add(aE);
4950 //
4951 // if this alone edge adds nothing to the intersection list
4952 // it means that the origin of this edge has been split and we need to
4953 // add the neighboring images of the same origins
4954 if (aDMSF.Find(aE).Extent() > 1) {
4955 continue;
4956 }
4957 //
4958 // check also its vertices
4959 TopoDS_Iterator aItE(aE);
4960 for (; aItE.More(); aItE.Next()) {
4961 const TopoDS_Shape& aVE = aItE.Value();
4962 if (aDMSF.Find(aVE).Extent() > 2) {
4963 break;
4964 }
4965 }
4966 //
4967 if (aItE.More()) {
4968 continue;
4969 }
4970 //
4971 // the edge is useless - look for other images
4972 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
4973 if (!pLEOr) {
4974 continue;
4975 }
4976 //
4977 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
4978 for (; aItLEOr.More(); aItLEOr.Next()) {
4979 const TopoDS_Shape& aEOr = aItLEOr.Value();
41aa3c3d 4980 //
b443d536 4981 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr);
4982 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
4983 for (; aItLEIm.More(); aItLEIm.Next()) {
4984 const TopoDS_Shape& aEIm = aItLEIm.Value();
4985 //
4986 if (aMFence.Contains(aEIm)) {
4987 aMEAlone.Add(aEIm);
4988 }
ecf4f17c 4989 }
4990 }
41aa3c3d 4991 }
4992 }
4993 //
4994 // Get all invalidities from all faces to be used for avoiding
4995 // repeated usage of the common edges
4996 TopTools_MapOfShape aMAllInvs;
4997 aNbInv = theInvFaces.Extent();
4998 for (k = 1; k <= aNbInv; ++k) {
4999 TopTools_ListIteratorOfListOfShape aIt(theInvFaces(k));
5000 for (; aIt.More(); aIt.Next()) {
5001 TopExp_Explorer aExp(aIt.Value(), TopAbs_EDGE);
5002 for (; aExp.More(); aExp.Next()) {
5003 const TopoDS_Shape& aE = aExp.Current();
5004 if (theInvEdges.Contains(aE) || aMEAlone.Contains(aE)) {
5005 aMAllInvs.Add(aE);
5006 TopoDS_Iterator aItV(aE);
5007 for (; aItV.More(); aItV.Next()) {
5008 aMAllInvs.Add(aItV.Value());
ecf4f17c 5009 }
5010 }
5011 }
5012 }
5013 }
5014 //
5015 // Bounding vertices of not trimmed edges
5016 TopTools_MapOfShape aMVBounds;
41aa3c3d 5017 //
5018 TopTools_MapOfShape aMECheckExt;
ecf4f17c 5019 // Save connections between not trimmed edge and its trimmed parts
5020 TopTools_DataMapOfShapeListOfShape aDMEETrim;
5021 // Splits of the new edges
5022 TopTools_DataMapOfShapeListOfShape aEImages;
5023 BRep_Builder aBB;
dcba2e5c 5024
5025 // Keep connection between blocks of invalid edges to the lists of
5026 // found edges to be intersected for its treatment
5027 TopTools_IndexedDataMapOfShapeListOfShape aDMOENEdges;
5028
ecf4f17c 5029 aNbInv = theInvFaces.Extent();
5030 for (k = 1; k <= aNbInv; ++k) {
5031 const TopoDS_Shape& aFInv = theInvFaces.FindKey(k);
5032 Standard_Boolean bSelfRebAvoid = theFSelfRebAvoid.Contains(aFInv);
5033 const TopTools_ListOfShape& aLFInv = theInvFaces(k);
5034 //
5035 TopTools_ListOfShape aLCB;
5036 if (aLFInv.Extent() > 1) {
5037 // make compound of invalid faces
5038 TopoDS_Compound aCFInv;
5039 aBB.MakeCompound(aCFInv);
5040 //
5041 TopTools_ListIteratorOfListOfShape aIt(aLFInv);
5042 for (; aIt.More(); aIt.Next()) {
5043 const TopoDS_Shape& aFIm = aIt.Value();
5044 aBB.Add(aCFInv, aFIm);
5045 }
5046 //
5047 // make connexity blocks
5048 BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCB);
5049 }
5050 else {
5051 aLCB = aLFInv;
5052 }
5053 //
5054 Standard_Boolean bArtificial = theArtInvFaces.IsBound(aFInv);
5055 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
5056 for (; aItLCB.More(); aItLCB.Next()) {
5057 const TopoDS_Shape& aCBInv = aItLCB.Value();
5058 //
5059 TopTools_MapOfShape aMEFence;
5060 //
5061 TopoDS_Compound aCBE;
5062 aBB.MakeCompound(aCBE);
5063 //
5064 TopExp_Explorer aExp(aCBInv, TopAbs_EDGE);
5065 for (; aExp.More(); aExp.Next()) {
5066 const TopoDS_Shape& aE = aExp.Current();
5067 if (theInvEdges.Contains(aE) || (bArtificial && aMEAlone.Contains(aE))) {
5068 if (aMEFence.Add(aE)) {
5069 aBB.Add(aCBE, aE);
5070 }
5071 }
5072 }
5073 //
5074 // make connexity blocks of edges
5075 TopTools_ListOfShape aLCBE;
5076 BOPTools_AlgoTools::MakeConnexityBlocks(aCBE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
5077 //
5078 TopTools_ListIteratorOfListOfShape aItLCBE(aLCBE);
5079 for (; aItLCBE.More(); aItLCBE.Next()) {
5080 const TopoDS_Shape& aCBELoc = aItLCBE.Value();
5081 //
5082 // map of edges and vertices of processing invalidity
5083 TopTools_IndexedMapOfShape aME;
5084 // map of vertices to trim the new edges
5085 TopTools_IndexedMapOfShape aMECV;
5086 TopExp::MapShapes(aCBELoc, TopAbs_EDGE, aME);
5087 aMECV = aME;
5088 TopExp::MapShapes(aCBELoc, TopAbs_VERTEX, aME);
5089 //
5090 // Using the map <aME> find chain of faces to be intersected;
5091 //
5092 // faces for intersection
5093 TopTools_IndexedMapOfShape aMFInt;
5094 // additional faces for intersection
5095 TopTools_IndexedMapOfShape aMFIntExt;
5096 // splits of faces for intersection
5097 TopTools_ListOfShape aLFInt;
5098 // faces to avoid intersection
5099 TopTools_IndexedMapOfShape aMFAvoid;
5100 //
5101 FindFacesForIntersection(aFInv, aME, theFImages, aDMSF, aMVInvAll,
6f04cbb1 5102 theArtInvFaces, bArtificial, theIntRes.SSInterfs, aMFAvoid, aMFInt, aMFIntExt, aLFInt);
ecf4f17c 5103 if (aMFInt.Extent() < 3) {
5104 // nothing to intersect
5105 continue;
5106 }
5107 //
6f04cbb1 5108 const BRepOffset_DataMapOfShapeMapOfShape* pMFInter = theIntRes.InterPairs.Seek (aFInv);
ecf4f17c 5109 // intersect the faces, but do not intersect the invalid ones
5110 // among each other (except for the artificially invalid faces)
5111 TopTools_IndexedMapOfShape aMEToInt;
5112 Standard_Integer aNb = aMFInt.Extent();
5113 for (i = 1; i <= aNb; ++i) {
5114 const TopoDS_Face& aFi = TopoDS::Face(aMFInt(i));
5115 if (bSelfRebAvoid && aFi.IsSame(aFInv)) {
5116 continue;
5117 }
5118 //
5119 const TopTools_ListOfShape& aLFImi = theFImages.FindFromKey(aFi);
5120 //
5121 TopTools_ListOfShape& aLFEi = aFLE.ChangeFromKey(aFi);
5122 //
5123 TopTools_ListOfShape& aLFDone = aMDone.ChangeFind(aFi);
5124 //
6f04cbb1 5125 const TopTools_MapOfShape* pInterFi = !pMFInter ? 0 : pMFInter->Seek (aFi);
5126 if (pMFInter && !pInterFi)
5127 continue;
5128
ecf4f17c 5129 for (j = i + 1; j <= aNb; ++j) {
5130 const TopoDS_Face& aFj = TopoDS::Face(aMFInt(j));
5131 if (bSelfRebAvoid && aFj.IsSame(aFInv)) {
5132 continue;
5133 }
5134 //
6f04cbb1 5135 if (pInterFi && !pInterFi->Contains (aFj))
5136 continue;
5137
ecf4f17c 5138 const TopTools_ListOfShape& aLFImj = theFImages.FindFromKey(aFj);
5139 //
5140 TopTools_ListOfShape& aLFEj = aFLE.ChangeFromKey(aFj);
5141 //
5142 // if there are some common edges between faces
5143 // we should use these edges and do not intersect again.
5144 TopTools_ListOfShape aLEC;
5145 FindCommonParts(aLFImi, aLFImj, aLEC);
5146 //
5147 if (aLEC.Extent()) {
5148 // no need to intersect if we have common edges between faces
5149 Standard_Boolean bForceUse = aMFIntExt.Contains(aFi) || aMFIntExt.Contains(aFj);
5150 ProcessCommonEdges(aLEC, theInvEdges, theValidEdges, aME, theETrimEInf, aMEInfETrim,
41aa3c3d 5151 theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt);
ecf4f17c 5152 continue;
5153 }
5154 //
5155 // check if both these faces are invalid and sharing edges
5156 if (theInvFaces.Contains(aFi) && theInvFaces.Contains(aFj) &&
5157 !theArtInvFaces.IsBound(aFi) && !theArtInvFaces.IsBound(aFj)) {
5158 continue;
5159 }
5160 //
5161 // check if these two faces have already been treated
5162 aItLE.Initialize(aLFDone);
5163 for (; aItLE.More(); aItLE.Next()) {
5164 const TopoDS_Shape& aF = aItLE.Value();
5165 if (aF.IsSame(aFj)) {
5166 break;
5167 }
5168 }
5169 //
5170 if (aItLE.More()) {
5171 // use intersection line obtained on the previous steps
5172 // plus, find new origins for these lines
5173 UpdateIntersectedFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
5174 aLFEi, aLFEj, theEdgesOrigins, aMEToInt);
5175 continue;
5176 }
5177 //
5178 if (aMFAvoid.Contains(aFi) || aMFAvoid.Contains(aFj)) {
5179 continue;
5180 }
5181 //
5182 aLFDone.Append(aFj);
5183 aMDone.ChangeFind(aFj).Append(aFi);
5184 //
5185 IntersectFaces(aFInv, aFi, aFj, aLFInv, aLFImi, aLFImj,
5186 aLFEi, aLFEj, theEdgesOrigins, aMECV, aMEToInt);
5187 }
5188 }
5189 //
5190 // intersect and trim edges for this chain
41aa3c3d 5191 IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV,
5192 aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages);
dcba2e5c 5193 //
dcba2e5c 5194 Standard_Integer iE, aNbEToInt = aMEToInt.Extent();
5195 for (iE = 1; iE <= aNbEToInt; ++iE)
bc4a3867 5196 {
5197 const TopoDS_Shape& aEInt = aMEToInt(iE);
5198 TopExp_Explorer anExpE(aCBELoc, TopAbs_EDGE);
5199 for (; anExpE.More(); anExpE.Next())
5200 {
5201 const TopoDS_Shape& aE = anExpE.Current();
5202 TopTools_ListOfShape* pLEToInt = aDMOENEdges.ChangeSeek(aE);
5203 if (!pLEToInt)
5204 pLEToInt = &aDMOENEdges(aDMOENEdges.Add(aE, TopTools_ListOfShape()));
5205 AppendToList(*pLEToInt, aEInt);
5206 }
5207 }
ecf4f17c 5208 }
5209 }
5210 }
5211 //
5212 // filter the obtained edges
dcba2e5c 5213 UpdateValidEdges(theFImages, aFLE, aDMOENEdges, aMVBounds, theSolids, theInvEdges, theInvertedEdges, aMEInvOnArt,
41aa3c3d 5214 aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins,
ecf4f17c 5215 theVertsToAvoid, theETrimEInf, aEImages, aDMEETrim, theModifiedEdges, theAsDes);
5216}
5217
5218//=======================================================================
5219//function : PrepareFacesForIntersection
5220//purpose : Preparation of the maps for analyzing intersections of the faces
5221//=======================================================================
5222void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
5223 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5224 const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
5225 const TopTools_DataMapOfShapeShape& theArtInvFaces,
5226 const Standard_Boolean bLookVertToAvoid,
5227 TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
5228 TopTools_DataMapOfShapeListOfShape& theMDone,
5229 TopTools_DataMapOfShapeListOfShape& theDMSF,
5230 TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5231 TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5232 TopTools_DataMapOfShapeShape& theETrimEInf,
5233 TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv)
5234{
5235 Standard_Integer i, aNb = theFToRebuild.Extent();
5236 for (i = 1; i <= aNb; ++i) {
5237 const TopoDS_Shape& aF = theFToRebuild.FindKey(i);
5238 //
5239 TopTools_ListOfShape aLE;
5240 theFLE.Add(aF, aLE);
5241 theMDone.Bind(aF, aLE);
5242 //
5243 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5244 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
5245 for (; aItLF.More(); aItLF.Next()) {
5246 const TopoDS_Shape& aFIm = aItLF.Value();
5247 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
5248 for (; aExp.More(); aExp.Next()) {
5249 const TopoDS_Shape& aE = aExp.Current();
5250 // save connection to untrimmed face
5251 TopTools_ListOfShape *pLF = theDMSF.ChangeSeek(aE);
5252 if (!pLF) {
5253 pLF = theDMSF.Bound(aE, TopTools_ListOfShape());
5254 }
5255 AppendToList(*pLF, aF);
5256 //
5257 // save connection to untrimmed edge
5258 const TopoDS_Shape& aEInf = theETrimEInf.Find(aE);
5259 TopTools_ListOfShape *pLETrim = theMEInfETrim.ChangeSeek(aEInf);
5260 if (!pLETrim) {
5261 pLETrim = theMEInfETrim.Bound(aEInf, TopTools_ListOfShape());
5262 }
5263 AppendToList(*pLETrim, aE);
5264 //
5265 TopExp_Explorer aExpV(aE, TopAbs_VERTEX);
5266 for (; aExpV.More(); aExpV.Next()) {
5267 const TopoDS_Shape& aV = aExpV.Current();
5268 // save connection to face
5269 TopTools_ListOfShape *pLFV = theDMSF.ChangeSeek(aV);
5270 if (!pLFV) {
5271 pLFV = theDMSF.Bound(aV, TopTools_ListOfShape());
5272 }
5273 AppendToList(*pLFV, aF);
5274 //
5275 if (bLookVertToAvoid) {
5276 // save connection to edges
5277 TopTools_ListOfShape *pLEV = theDMVEFull.ChangeSeek(aV);
5278 if (!pLEV) {
5279 pLEV = theDMVEFull.Bound(aV, TopTools_ListOfShape());
5280 }
5281 AppendToList(*pLEV, aE);
5282 }
5283 }
5284 }
5285 }
5286 //
5287 if (bLookVertToAvoid) {
5288 // get edges of invalid faces (from invalid splits only)
5289 const TopTools_ListOfShape *pLFInv = theInvFaces.Seek(aF);
5290 if (!pLFInv || theArtInvFaces.IsBound(aF)) {
5291 continue;
5292 }
5293 //
5294 aItLF.Initialize(*pLFInv);
5295 for (; aItLF.More(); aItLF.Next()) {
5296 const TopoDS_Shape& aFInv = aItLF.Value();
5297 TopExp_Explorer aExp(aFInv, TopAbs_EDGE);
5298 for (; aExp.More(); aExp.Next()) {
5299 const TopoDS_Shape& aE = aExp.Current();
5300 TopTools_ListOfShape *pLF = theDMEFInv.ChangeSeek(aE);
5301 if (!pLF) {
5302 pLF = &theDMEFInv(theDMEFInv.Add(aE, TopTools_ListOfShape()));
5303 }
5304 AppendToList(*pLF, aF);
5305 }
5306 }
5307 }
5308 }
5309}
5310
5311//=======================================================================
5312//function : FindVerticesToAvoid
5313//purpose : Looking for the invalid vertices
5314//=======================================================================
5315void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
5316 const TopTools_IndexedMapOfShape& theInvEdges,
5317 const TopTools_IndexedMapOfShape& theValidEdges,
bc4a3867 5318 const TopTools_MapOfShape& theInvertedEdges,
5319 const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5320 const TopTools_DataMapOfShapeListOfShape& theOEImages,
5321 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
ecf4f17c 5322 TopTools_MapOfShape& theMVRInv)
5323{
5324 TopTools_MapOfShape aMFence;
5325 Standard_Integer i, aNb = theDMEFInv.Extent();
5326 for (i = 1; i <= aNb; ++i) {
5327 const TopTools_ListOfShape& aLFInv = theDMEFInv(i);
5328 if (aLFInv.Extent() == 1) {
5329 continue;
5330 }
5331 //
5332 const TopoDS_Shape& aE = theDMEFInv.FindKey(i);
5333 if (!theInvEdges.Contains(aE) || theValidEdges.Contains(aE)) {
5334 continue;
5335 }
bc4a3867 5336
5337 if (!aMFence.Add(aE))
5338 continue;
5339
5340 TopTools_IndexedDataMapOfShapeListOfShape aMVEEdges;
5341 // Do not check the splitting vertices, but check only the ending ones
5342 const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE);
5343 if (pLEOr)
5344 {
5345 TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr);
5346 for (; aItLEOr.More(); aItLEOr.Next())
5347 {
5348 const TopTools_ListOfShape& aLEIm = theOEImages.Find(aItLEOr.Value());
5349 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
5350 for (; aItLEIm.More(); aItLEIm.Next())
5351 {
5352 aMFence.Add(aItLEIm.Value());
5353 TopExp::MapShapesAndAncestors(aItLEIm.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5354 }
5355 }
5356 }
5357 else
5358 {
5359 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVEEdges);
5360 }
5361
5362 Standard_Integer j, aNbV = aMVEEdges.Extent();
5363 for (j = 1; j <= aNbV; ++j)
5364 {
5365 if (aMVEEdges(j).Extent() != 1)
5366 continue;
5367
5368 const TopoDS_Shape& aV = aMVEEdges.FindKey(j);
5369 if (!aMFence.Add(aV))
5370 continue;
5371 const TopTools_ListOfShape *pLE = theDMVEFull.Seek(aV);
ecf4f17c 5372 if (!pLE) {
bc4a3867 5373 // isolated vertex
ecf4f17c 5374 theMVRInv.Add(aV);
5375 continue;
5376 }
5377 //
bc4a3867 5378 // If all edges sharing the vertex are either invalid or
5379 // the vertex is connected to at least two inverted edges
5380 // mark the vertex to be avoided in the new splits
5381 Standard_Integer iNbEInverted = 0;
5382 Standard_Boolean bAllEdgesInv = Standard_True;
ecf4f17c 5383 TopTools_ListIteratorOfListOfShape aItLE(*pLE);
5384 for (; aItLE.More(); aItLE.Next()) {
5385 const TopoDS_Shape& aEV = aItLE.Value();
bc4a3867 5386
5387 if (theInvertedEdges.Contains(aEV))
5388 ++iNbEInverted;
5389
5390 if (bAllEdgesInv)
5391 bAllEdgesInv = theInvEdges.Contains(aEV);
ecf4f17c 5392 }
bc4a3867 5393
5394 if (iNbEInverted > 1 || bAllEdgesInv)
5395 {
ecf4f17c 5396 theMVRInv.Add(aV);
5397 }
5398 }
5399 }
5400}
5401
5402//=======================================================================
5403//function : FindFacesForIntersection
5404//purpose : Looking for the faces around each invalidity for intersection
5405//=======================================================================
5406void FindFacesForIntersection(const TopoDS_Shape& theFInv,
5407 const TopTools_IndexedMapOfShape& theME,
5408 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5409 const TopTools_DataMapOfShapeListOfShape& theDMSF,
5410 const TopTools_MapOfShape& theMVInvAll,
5411 const TopTools_DataMapOfShapeShape& theArtInvFaces,
5412 const Standard_Boolean theArtCase,
5413 const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
5414 TopTools_IndexedMapOfShape& theMFAvoid,
5415 TopTools_IndexedMapOfShape& theMFInt,
5416 TopTools_IndexedMapOfShape& theMFIntExt,
5417 TopTools_ListOfShape& theLFImInt)
5418{
5419 Standard_Integer i, aNbE = theME.Extent();
5420 //
5421 TopTools_IndexedMapOfShape aMShapes;
5422 //
5423 for (i = 1; i <= aNbE; ++i) {
5424 const TopoDS_Shape& aS = theME(i);
5425 if (!theDMSF.IsBound(aS)) {
5426 continue;
5427 }
5428 //
5429 // in artificial case we intersect the faces which are close to invalidity
5430 Standard_Boolean bAvoid = theArtCase ?
5431 ((aS.ShapeType() == TopAbs_VERTEX) && !theMVInvAll.Contains(aS)) : Standard_False;
5432 //
5433 const TopTools_ListOfShape& aLF = theDMSF.Find(aS);
5434 TopTools_ListIteratorOfListOfShape aItLF(aLF);
5435 for (; aItLF.More(); aItLF.Next()) {
5436 const TopoDS_Shape& aF = aItLF.Value();
5437 if (theMFInt.Contains(aF)) {
5438 continue;
5439 }
5440 //
5441 if (bAvoid && theArtInvFaces.IsBound(aF)) {
5442 theMFAvoid.Add(aF);
5443 }
5444 //
5445 theMFInt.Add(aF);
5446 //
5447 Standard_Boolean bUse = !aF.IsSame(theFInv);
5448 //
5449 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5450 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5451 for (; aItLFIm.More(); aItLFIm.Next()) {
5452 const TopoDS_Shape& aFIm = aItLFIm.Value();
5453 theLFImInt.Append(aFIm);
5454 if (bUse) {
5455 TopExp::MapShapes(aFIm, TopAbs_EDGE, aMShapes);
5456 }
5457 }
5458 }
5459 }
5460 //
5461 if (theArtCase) {
5462 return;
5463 }
5464 //
5465 const TopTools_ListOfShape* pLFInv = theSSInterfs.Seek(theFInv);
5466 if (!pLFInv) {
5467 return;
5468 }
5469 //
5470 TopTools_MapOfShape aMF;
5471 TopTools_ListIteratorOfListOfShape aItLF(*pLFInv);
5472 for (; aItLF.More(); aItLF.Next()) {
5473 const TopoDS_Shape& aF = aItLF.Value();
5474 aMF.Add(aF);
5475 }
5476 //
5477 // the faces should be unique in each place
5478 TopoDS_Compound aCF;
5479 BRep_Builder().MakeCompound(aCF);
5480 //
5481 TopTools_IndexedMapOfShape aMFToAdd;
5482 TopTools_DataMapOfShapeShape aDMFOr;
5483 //
5484 for (i = 1; i <= aNbE; ++i) {
5485 const TopoDS_Shape& aS = theME(i);
5486 const TopTools_ListOfShape* pLF = theSSInterfs.Seek(aS);
5487 if (!pLF) {
5488 continue;
5489 }
5490 //
5491 aItLF.Initialize(*pLF);
5492 for (; aItLF.More(); aItLF.Next()) {
5493 const TopoDS_Shape& aF = aItLF.Value();
5494 if (theMFInt.Contains(aF) || aMFToAdd.Contains(aF) || !aMF.Contains(aF)) {
5495 continue;
5496 }
5497 //
5498 // check if the face has some connection to already added for intersection faces
5499 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5500 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5501 for (; aItLFIm.More(); aItLFIm.Next()) {
5502 const TopoDS_Shape& aFIm = aItLFIm.Value();
5503 TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
5504 for (; aExp.More(); aExp.Next()) {
5505 if (aMShapes.Contains(aExp.Current())) {
5506 break;
5507 }
5508 }
5509 if (aExp.More()) {
5510 break;
5511 }
5512 }
5513 if (!aItLFIm.More()) {
5514 continue;
5515 }
5516 //
5517 aMFToAdd.Add(aF);
5518 aItLFIm.Initialize(aLFIm);
5519 for (; aItLFIm.More(); aItLFIm.Next()) {
5520 const TopoDS_Shape& aFIm = aItLFIm.Value();
5521 aDMFOr.Bind(aFIm, aF);
5522 BRep_Builder().Add(aCF, aFIm);
5523 }
5524 }
5525 }
5526 //
5527 if (aMFToAdd.IsEmpty()) {
5528 return;
5529 }
5530 //
5531 TopTools_ListOfShape aLCB;
5532 BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
5533 //
5534 if ((aLCB.Extent() == 1) && (aMFToAdd.Extent() > 1)) {
5535 return;
5536 }
5537 //
5538 TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
5539 for (; aItLCB.More(); aItLCB.Next()) {
5540 const TopoDS_Shape& aCB = aItLCB.Value();
5541 aMFToAdd.Clear();
5542 TopExp_Explorer aExpF(aCB, TopAbs_FACE);
5543 for (; aExpF.More(); aExpF.Next()) {
5544 const TopoDS_Shape& aFIm = aExpF.Current();
5545 aMFToAdd.Add(aDMFOr.Find(aFIm));
5546 }
5547 //
5548 if (aMFToAdd.Extent() == 1) {
5549 const TopoDS_Shape& aF = aMFToAdd(1);
5550 //
5551 theMFInt.Add(aF);
5552 theMFIntExt.Add(aF);
5553 //
5554 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
5555 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
5556 for (; aItLFIm.More(); aItLFIm.Next()) {
5557 const TopoDS_Shape& aFIm = aItLFIm.Value();
5558 theLFImInt.Append(aFIm);
5559 }
5560 }
5561 }
5562}
5563
5564//=======================================================================
5565//function : ProcessCommonEdges
5566//purpose : Analyzing the common edges between splits of offset faces
5567//=======================================================================
5568void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
5569 const TopTools_IndexedMapOfShape& theInvEdges,
5570 const TopTools_IndexedMapOfShape& theValidEdges,
5571 const TopTools_IndexedMapOfShape& theME,
5572 const TopTools_DataMapOfShapeShape& theETrimEInf,
5573 const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
5574 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
41aa3c3d 5575 const TopTools_MapOfShape& theAllInvs,
ecf4f17c 5576 const Standard_Boolean theForceUse,
5577 TopTools_IndexedMapOfShape& theMECV,
41aa3c3d 5578 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 5579 TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5580 TopTools_ListOfShape& theLFEi,
5581 TopTools_ListOfShape& theLFEj,
5582 TopTools_IndexedMapOfShape& theMEToInt)
5583{
5584 TopTools_ListOfShape aLEC;
5585 // process common edges
5586 TopTools_ListIteratorOfListOfShape aItLE(theLEC);
5587 for (; aItLE.More(); aItLE.Next()) {
5588 const TopoDS_Shape& aEC = aItLE.Value();
5589 //
5590 // check first if common edges are valid
5591 if (theInvEdges.Contains(aEC) && !theValidEdges.Contains(aEC)) {
5592 continue;
5593 }
5594 //
5595 // common edge should have connection to current invalidity
5596 if (theME.Contains(aEC)) {
5597 aLEC.Append(aEC);
5598 continue;
5599 }
5600 //
5601 TopoDS_Iterator aItV(aEC);
5602 for (; aItV.More(); aItV.Next()) {
5603 const TopoDS_Shape& aVE = aItV.Value();
5604 if (theME.Contains(aVE)) {
5605 aLEC.Append(aEC);
5606 break;
5607 }
5608 }
5609 }
5610 //
41aa3c3d 5611 Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
ecf4f17c 5612 if (bUseOnlyInf) {
41aa3c3d 5613 if (theForceUse) {
5614 aLEC = theLEC;
5615 }
5616 else {
5617 aItLE.Initialize(theLEC);
5618 for (; aItLE.More(); aItLE.Next()) {
5619 const TopoDS_Shape& aEC = aItLE.Value();
b443d536 5620 // check if all images of the origin of this edge
5621 // are not connected to any invalidity
5622 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5623 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5624 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5625 for (; aItLVE.More(); aItLVE.Next()) {
5626 const TopoDS_Shape& aECx = aItLVE.Value();
5627 if (theAllInvs.Contains(aECx) || theInvEdges.Contains(aECx)) {
41aa3c3d 5628 return;
5629 }
b443d536 5630 //
5631 TopoDS_Iterator aItV(aECx);
5632 for (; aItV.More(); aItV.Next()) {
5633 if (theAllInvs.Contains(aItV.Value())) {
5634 return;
5635 }
5636 }
41aa3c3d 5637 }
41aa3c3d 5638 // use only one element
5639 if (aLEC.IsEmpty()) {
5640 aLEC.Append(aEC);
5641 }
5642 }
5643 }
ecf4f17c 5644 }
5645 //
5646 aItLE.Initialize(aLEC);
5647 for (; aItLE.More(); aItLE.Next()) {
5648 const TopoDS_Shape& aEC = aItLE.Value();
5649 //
5650 const TopoDS_Shape& aEInt = theETrimEInf.Find(aEC);
5651 if (!bUseOnlyInf) {
5652 // find the edges of the same original edge
5653 // and take their vertices as well
5654 const TopTools_ListOfShape& aLVE = theMEInfETrim.Find(aEInt);
5655 TopTools_ListIteratorOfListOfShape aItLVE(aLVE);
5656 for (; aItLVE.More(); aItLVE.Next()) {
5657 const TopoDS_Shape& aECx = aItLVE.Value();
5658 //
5659 const TopTools_ListOfShape* pLEOr = theOEOrigins.Seek(aECx);
5660 if (!pLEOr || (pLEOr->Extent() == 1)) {
5661 TopExp::MapShapes(aECx, TopAbs_VERTEX, theMECV);
5662 }
5663 }
5664 //
5665 // bind unlimited edge to its trimmed part in face to update maps of
5666 // images and origins in the future
5667 TopTools_ListOfShape* pLTAdded = theDMEETrim.ChangeSeek(aEInt);
5668 if (!pLTAdded) {
5669 pLTAdded = theDMEETrim.Bound(aEInt, TopTools_ListOfShape());
5670 }
5671 AppendToList(*pLTAdded, aEC);
5672 }
41aa3c3d 5673 else if (!theForceUse) {
5674 theMECheckExt.Add(aEInt);
5675 }
ecf4f17c 5676 //
5677 AppendToList(theLFEi, aEInt);
5678 AppendToList(theLFEj, aEInt);
5679 theMEToInt.Add(aEInt);
5680 }
5681}
5682
5683//=======================================================================
5684//function : UpdateIntersectedFaces
5685//purpose : Updating the already interfered faces
5686//=======================================================================
5687void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
5688 const TopoDS_Shape& theFi,
5689 const TopoDS_Shape& theFj,
5690 const TopTools_ListOfShape& theLFInv,
5691 const TopTools_ListOfShape& theLFImi,
5692 const TopTools_ListOfShape& theLFImj,
5693 const TopTools_ListOfShape& theLFEi,
5694 const TopTools_ListOfShape& theLFEj,
5695 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5696 TopTools_IndexedMapOfShape& theMEToInt)
5697{
5698 // Find common edges in these two lists
5699 TopTools_MapOfShape aMEi;
5700 TopTools_ListIteratorOfListOfShape aItLE(theLFEi);
5701 for (; aItLE.More(); aItLE.Next()) {
5702 const TopoDS_Shape& aE = aItLE.Value();
5703 aMEi.Add(aE);
5704 }
5705 //
5706 // find origins
5707 TopTools_IndexedMapOfShape aMEToFindOrigins;
5708 TopTools_ListOfShape aLEToFindOrigins;
5709 if (!theFi.IsSame(theFInv)) {
5710 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5711 }
5712 if (!theFj.IsSame(theFInv)) {
5713 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5714 }
5715 //
5716 TopTools_ListOfShape aLEOrInit;
5717 aItLE.Initialize(aLEToFindOrigins);
5718 for (; aItLE.More(); aItLE.Next()) {
5719 const TopoDS_Shape& aEC = aItLE.Value();
5720 aMEToFindOrigins.Add(aEC);
5721 }
5722 //
5723 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5724 //
5725 aItLE.Initialize(theLFEj);
5726 for (; aItLE.More(); aItLE.Next()) {
5727 const TopoDS_Shape& aE = aItLE.Value();
5728 if (aMEi.Contains(aE)) {
5729 theMEToInt.Add(aE);
5730 if (aLEOrInit.Extent()) {
5731 if (theEdgesOrigins.IsBound(aE)) {
5732 TopTools_ListOfShape& aLEOr = theEdgesOrigins.ChangeFind(aE);
5733 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOrInit);
5734 for (; aItLEOr.More(); aItLEOr.Next()) {
5735 const TopoDS_Shape& aEOr = aItLEOr.Value();
5736 AppendToList(aLEOr, aEOr);
5737 }
5738 }
5739 else {
5740 theEdgesOrigins.Bind(aE, aLEOrInit);
5741 }
5742 }
5743 }
5744 }
5745}
5746
5747//=======================================================================
5748//function : IntersectFaces
5749//purpose : Intersection of the pair of faces
5750//=======================================================================
5751void IntersectFaces(const TopoDS_Shape& theFInv,
5752 const TopoDS_Shape& theFi,
5753 const TopoDS_Shape& theFj,
5754 const TopTools_ListOfShape& theLFInv,
5755 const TopTools_ListOfShape& theLFImi,
5756 const TopTools_ListOfShape& theLFImj,
5757 TopTools_ListOfShape& theLFEi,
5758 TopTools_ListOfShape& theLFEj,
5759 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
5760 TopTools_IndexedMapOfShape& theMECV,
5761 TopTools_IndexedMapOfShape& theMEToInt)
5762{
5763 // intersect faces
5764 TopAbs_State aSide = TopAbs_OUT;
5765 TopTools_ListOfShape aLInt1, aLInt2;
5766 TopoDS_Edge aNullEdge;
8948e18d 5767 TopoDS_Face aNullFace;
5768 BRepOffset_Tool::Inter3D(TopoDS::Face(theFi), TopoDS::Face(theFj), aLInt1, aLInt2, aSide,
5769 aNullEdge, aNullFace, aNullFace);
ecf4f17c 5770 //
5771 if (aLInt1.IsEmpty()) {
5772 return;
5773 }
5774 //
5775 // find common vertices for trimming edges
5776 TopTools_ListOfShape aLCV;
5777 TopTools_ListIteratorOfListOfShape aItLE;
5778 FindCommonParts(theLFImi, theLFImj, aLCV, TopAbs_VERTEX);
5779 if (aLCV.Extent() > 1) {
5780 aItLE.Initialize(aLCV);
5781 for (; aItLE.More(); aItLE.Next()) {
5782 const TopoDS_Shape& aCV = aItLE.Value();
5783 theMECV.Add(aCV);
5784 }
5785 }
5786 //
5787 // find origins
5788 TopTools_IndexedMapOfShape aMEToFindOrigins;
5789 TopTools_ListOfShape aLEToFindOrigins;
5790 if (!theFi.IsSame(theFInv)) {
5791 FindCommonParts(theLFImi, theLFInv, aLEToFindOrigins);
5792 }
5793 if (!theFj.IsSame(theFInv)) {
5794 FindCommonParts(theLFImj, theLFInv, aLEToFindOrigins);
5795 }
5796 TopTools_ListOfShape aLEOrInit;
5797 aItLE.Initialize(aLEToFindOrigins);
5798 for (; aItLE.More(); aItLE.Next()) {
5799 const TopoDS_Shape& aEC = aItLE.Value();
5800 aMEToFindOrigins.Add(aEC);
5801 }
5802 //
5803 FindOrigins(theLFImi, theLFImj, aMEToFindOrigins, theEdgesOrigins, aLEOrInit);
5804 //
5805 aItLE.Initialize(aLInt1);
5806 for (; aItLE.More(); aItLE.Next()) {
5807 const TopoDS_Shape& aEInt = aItLE.Value();
5808 theLFEi.Append(aEInt);
5809 theLFEj.Append(aEInt);
5810 //
5811 if (aLEOrInit.Extent()) {
5812 theEdgesOrigins.Bind(aEInt, aLEOrInit);
5813 }
5814 //
5815 theMEToInt.Add(aEInt);
5816 }
5817}
5818
5819//=======================================================================
5820//function : FindOrigins
5821//purpose : Looking for the origin edges
5822//=======================================================================
5823void FindOrigins(const TopTools_ListOfShape& theLFIm1,
5824 const TopTools_ListOfShape& theLFIm2,
5825 const TopTools_IndexedMapOfShape& theME,
5826 const TopTools_DataMapOfShapeListOfShape& theOrigins,
5827 TopTools_ListOfShape& theLEOr)
5828{
5829 Standard_Integer i;
5830 TopTools_MapOfShape aMFence;
5831 TopExp_Explorer aExp;
5832 TopTools_ListIteratorOfListOfShape aIt, aItLE;
5833 //
5834 for (i = 0; i < 2; ++i) {
5835 const TopTools_ListOfShape& aLF = !i ? theLFIm1 : theLFIm2;
5836 aIt.Initialize(aLF);
5837 for (; aIt.More(); aIt.Next()) {
5838 const TopoDS_Shape& aF = aIt.Value();
5839 //
5840 aExp.Init(aF, TopAbs_EDGE);
5841 for (; aExp.More(); aExp.Next()) {
5842 const TopoDS_Shape& aE = aExp.Current();
5843 //
5844 if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5845 const TopTools_ListOfShape& aLEOr = theOrigins.Find(aE);
5846 aItLE.Initialize(aLEOr);
5847 for (; aItLE.More(); aItLE.Next()) {
5848 const TopoDS_Shape& aEOr = aItLE.Value();
5849 //
5850 if (aMFence.Add(aEOr) && (aEOr.ShapeType() == TopAbs_EDGE)) {
5851 theLEOr.Append(aEOr);
5852 }
5853 } // for (; aItLE.More(); aItLE.Next()) {
5854 } // if (theME.Contains(aE) && theOrigins.IsBound(aE)) {
5855 } // aExp.Init(aF, TopAbs_EDGE);
5856 } // for (; aIt.More(); aIt.Next()) {
5857 } // for (i = 0; i < 2; ++i) {
5858}
5859
5860//=======================================================================
5861//function : IntersectAndTrimEdges
5862//purpose : Intersection of the new intersection edges among themselves
5863//=======================================================================
5864void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
5865 const TopTools_IndexedMapOfShape& theMFInt,
5866 const TopTools_IndexedMapOfShape& theMEInt,
5867 const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
5868 const TopTools_IndexedMapOfShape& theMSInv,
5869 const TopTools_IndexedMapOfShape& theMVE,
5870 const TopTools_MapOfShape& theVertsToAvoid,
5871 const TopTools_MapOfShape& theNewVertsToAvoid,
41aa3c3d 5872 const TopTools_MapOfShape& theMECheckExt,
ecf4f17c 5873 TopTools_MapOfShape& theMVBounds,
5874 TopTools_DataMapOfShapeListOfShape& theEImages)
5875{
5876 Standard_Integer i, aNb = theMEInt.Extent();
5877 if (!aNb) {
5878 return;
5879 }
5880 //
1155d05a 5881 TopTools_ListOfShape aLArgs;
ecf4f17c 5882 TopTools_MapOfShape aMFence;
5883 TopTools_ListIteratorOfListOfShape aIt, aIt1;
5884 TopExp_Explorer aExp;
5885 //
5886 // get vertices from the splits of intersected faces.
5887 // vertices are taken from the edges close to invalidity
5888 //
5889 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
5890 aNb = theMFInt.Extent();
5891 for (i = 1; i <= aNb; ++i) {
5892 const TopoDS_Shape& aF = theMFInt(i);
5893 const TopTools_ListOfShape& aLE = theFToRebuild.FindFromKey(aF);
5894 //
5895 aIt.Initialize(aLE);
5896 for (; aIt.More(); aIt.Next()) {
5897 const TopoDS_Shape& aE = aIt.Value();
5898 TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
5899 //
5900 aExp.Init(aE, TopAbs_VERTEX);
5901 for (; aExp.More(); aExp.Next()) {
5902 const TopoDS_Shape& aV1 = aExp.Current();
5903 if (!theVertsToAvoid.Contains(aV1) && theMVE.Contains(aV1) && aMFence.Add(aV1)) {
5904 aLArgs.Append(aV1);
5905 }
5906 }
5907 }
5908 }
5909 //
5910 aNb = theMSInv.Extent();
5911 for (i = 1; i <= aNb; ++i) {
5912 const TopoDS_Shape& aV = theMSInv(i);
5913 if (aV.ShapeType() != TopAbs_VERTEX) {
5914 continue;
5915 }
5916 //
5917 TopTools_ListOfShape *pLVE = aDMVE.ChangeSeek(aV);
5918 if (!pLVE) {
5919 continue;
5920 }
5921 //
5922 aIt.Initialize(*pLVE);
5923 for (; aIt.More(); aIt.Next()) {
5924 const TopoDS_Shape& aE = aIt.Value();
5925 //
5926 aExp.Init(aE, TopAbs_VERTEX);
5927 for (; aExp.More(); aExp.Next()) {
5928 const TopoDS_Shape& aV1 = aExp.Current();
5929 if (!theVertsToAvoid.Contains(aV1) && aMFence.Add(aV1)) {
5930 aLArgs.Append(aV1);
5931 }
5932 }
5933 }
5934 }
5935 //
5936 // bounding vertices of untrimmed edges
5937 TopTools_ListOfShape aLVBounds;
5938 // new intersection edges
5939 TopTools_ListOfShape aLENew;
5940 // get edges to intersect
5941 TopTools_ListOfShape aLEInt;
dcba2e5c 5942 // Common intersection edges. Should be intersected separately
41aa3c3d 5943 TopTools_ListOfShape aLCE;
5944 //
ecf4f17c 5945 aNb = theMEInt.Extent();
5946 for (i = 1; i <= aNb; ++i) {
5947 const TopoDS_Shape& aE = theMEInt(i);
41aa3c3d 5948 if (theMECheckExt.Contains(aE)) {
5949 // avoid trimming of the intersection edges by additional common edges
5950 aLCE.Append(aE);
ecf4f17c 5951 continue;
5952 }
5953 //
5954 if (!theDMEETrim.IsBound(aE)) {
5955 aLENew.Append(aE);
5956 }
5957 //
5958 aLEInt.Append(aE);
5959 aLArgs.Append(aE);
5960 //
5961 aExp.Init(aE, TopAbs_VERTEX);
5962 for (; aExp.More(); aExp.Next()) {
5963 const TopoDS_Shape& aV = aExp.Current();
5964 aLVBounds.Append(aV);
5965 }
5966 }
5967 //
5968 // Intersect Edges
5969 BOPAlgo_Builder aGF;
5970 aGF.SetArguments(aLArgs);
5971 aGF.Perform();
33ba8565 5972 if (aGF.HasErrors()) {
ecf4f17c 5973 return;
5974 }
5975 //
5976 // update vertices to avoid with SD vertices
5977 aIt.Initialize(aLVBounds);
5978 for (; aIt.More(); aIt.Next()) {
5979 const TopoDS_Shape& aV = aIt.Value();
5980 const TopTools_ListOfShape& aLVIm = aGF.Modified(aV);
5981 if (aLVIm.IsEmpty()) {
5982 theMVBounds.Add(aV);
5983 }
5984 else {
5985 const TopoDS_Shape& aVIm = aLVIm.First();
5986 theMVBounds.Add(aVIm);
5987 }
5988 }
5989 //
5990 // find invalid splits of edges
5991 TopTools_MapOfShape aMEInv;
5992 GetInvalidEdges(theNewVertsToAvoid, theMVBounds, aGF, aMEInv);
5993 //
41aa3c3d 5994 BRep_Builder aBB;
5995 // get valid splits to intersect with the commons
5996 TopoDS_Compound aCEIm;
5997 aBB.MakeCompound(aCEIm);
5998 //
ecf4f17c 5999 // remove the splits containing vertices from invalid edges
6000 aIt.Initialize(aLEInt);
6001 for (; aIt.More(); aIt.Next()) {
6002 const TopoDS_Shape& aE = aIt.Value();
6003 //
6004 TopTools_ListOfShape aLEIm = aGF.Modified(aE);
6005 if (aLEIm.IsEmpty()) {
6006 continue;
6007 }
6008 //
6009 aIt1.Initialize(aLEIm);
6010 for (; aIt1.More(); ) {
6011 const TopoDS_Shape& aEIm = aIt1.Value();
6012 //
6013 if (aMEInv.Contains(aEIm)) {
6014 aLEIm.Remove(aIt1);
6015 }
6016 else {
41aa3c3d 6017 aBB.Add(aCEIm, aEIm);
ecf4f17c 6018 aIt1.Next();
6019 }
6020 }
6021 //
6022 if (aLEIm.Extent()) {
41aa3c3d 6023 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
6024 if (!pLEIm) {
6025 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
ecf4f17c 6026 }
41aa3c3d 6027 pLEIm->Append(aLEIm);
6028 }
6029 }
6030 //
6031 if (!aLCE.Extent()) {
6032 return;
6033 }
6034 //
6035 // trim common edges by other intersection edges
6036 BOPAlgo_Builder aGFCE;
6037 aGFCE.SetArguments(aLCE);
6038 aGFCE.AddArgument(aCEIm);
6039 aGFCE.Perform();
6040 //
33ba8565 6041 if (aGFCE.HasErrors()) {
41aa3c3d 6042 return;
6043 }
6044 //
6045 const BOPDS_PDS& pDS = aGFCE.PDS();
6046 TopTools_ListIteratorOfListOfShape aItLCE(aLCE);
6047 for (; aItLCE.More(); aItLCE.Next()) {
6048 const TopoDS_Shape& aE = aItLCE.Value();
6049 TopTools_ListOfShape aLEIm = aGFCE.Modified(aE);
6050 if (aLEIm.IsEmpty()) {
6051 continue;
6052 }
6053 //
6054 // check if it's not coincide with some intersection edge
6055 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(pDS->PaveBlocks(pDS->Index(aE)));
6056 for (; aItLPB.More(); aItLPB.Next()) {
6057 if (pDS->IsCommonBlock(aItLPB.Value())) {
6058 // find with what it is a common
6059 const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock(aItLPB.Value())->PaveBlocks();
6060 BOPDS_ListIteratorOfListOfPaveBlock aItLPBC(aLPBC);
6061 for (; aItLPBC.More(); aItLPBC.Next()) {
6062 const TopoDS_Shape& aEC = pDS->Shape(aItLPBC.Value()->OriginalEdge());
6063 if (!theMECheckExt.Contains(aEC)) {
6064 break;
6065 }
6066 }
6067 if (aItLPBC.More()) {
6068 break;
6069 }
ecf4f17c 6070 }
6071 }
41aa3c3d 6072 if (aItLPB.More()) {
6073 // avoid creation of unnecessary splits from commons which
6074 // coincide with intersection edges
6075 continue;
6076 }
6077 //
6078 // save the images
6079 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
6080 if (!pLEIm) {
6081 pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
6082 }
6083 pLEIm->Append(aLEIm);
6084 //
6085 // save bounding vertices
6086 for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) {
6087 const TopoDS_Shape& aV = aItV.Value();
6088 const TopTools_ListOfShape& aLVIm = aGFCE.Modified(aV);
6089 theMVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
6090 }
ecf4f17c 6091 }
6092}
6093
6094//=======================================================================
6095//function : GetInvalidEdges
6096//purpose : Looking for the invalid edges by intersecting with invalid vertices
6097//=======================================================================
6098void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
6099 const TopTools_MapOfShape& theMVBounds,
6100 BOPAlgo_Builder& theGF,
6101 TopTools_MapOfShape& theMEInv)
6102{
6103 if (theVertsToAvoid.IsEmpty()) {
6104 return;
6105 }
6106 //
6107 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6108 // get vertices created with intersection edges
6109 const TopoDS_Shape& aRes = theGF.Shape();
6110 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6111 TopExp::MapShapesAndAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6112 //
6113 const BOPDS_PDS& pDS = theGF.PDS();
6114 //
6115 // find invalid splits of edges
6116 // check if the vertex is invalid:
6117 // a. it may be the vertex SD with the vertices to avoid
6118 // b. or it may be the vertex which is created by the intersection
6119 // of only existing edges, i.e. no new intersection edges goes
6120 // through this vertex
6121 //
6122 TopTools_MapOfShape aMVInv;
6123 Standard_Integer i, aNb = aDMVE.Extent();
6124 for (i = 1; i <= aNb; ++i) {
6125 const TopoDS_Vertex& aV = TopoDS::Vertex(aDMVE.FindKey(i));
6126 if (theMVBounds.Contains(aV)) {
6127 continue;
6128 }
6129 //
6130 Standard_Integer nV = pDS->Index(aV);
6131 if ((nV >= 0) && !pDS->IsNewShape(nV)) {
6132 continue;
6133 }
6134 //
6135 TopTools_MapIteratorOfMapOfShape aItM(theVertsToAvoid);
6136 for (; aItM.More(); aItM.Next()) {
6137 const TopoDS_Vertex& aVInv = *(TopoDS_Vertex*)&aItM.Value();
6138 Standard_Integer iFlag = BOPTools_AlgoTools::ComputeVV(aV, aVInv);
6139 if (!iFlag) {
6140 aMVInv.Add(aV);
6141 break;
6142 }
6143 }
6144 //
6145 if (aItM.More()) {
6146 const TopTools_ListOfShape& aLVE = aDMVE.FindFromKey(aV);
6147 aIt.Initialize(aLVE);
6148 for (; aIt.More(); aIt.Next()) {
6149 const TopoDS_Shape& aE = aIt.Value();
6150 theMEInv.Add(aE);
6151 }
6152 }
6153 }
6154}
6155
6156//=======================================================================
6157//function : UpdateValidEdges
6158//purpose : Making the new splits and updating the maps
6159//=======================================================================
41aa3c3d 6160void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
ecf4f17c 6161 const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
dcba2e5c 6162 const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
ecf4f17c 6163 const TopTools_MapOfShape& theMVBounds,
6164 const TopoDS_Shape& theSolids,
6165 const TopTools_IndexedMapOfShape& theInvEdges,
6166 const TopTools_MapOfShape& theInvertedEdges,
a8232603 6167 const TopTools_MapOfShape& theMEInvOnArt,
41aa3c3d 6168 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 6169 TopTools_IndexedMapOfShape& theEdgesToAvoid,
6170 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
6171 TopTools_DataMapOfShapeListOfShape& theOEImages,
6172 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6173 TopTools_MapOfShape& theVertsToAvoid,
6174 TopTools_DataMapOfShapeShape& theETrimEInf,
6175 TopTools_DataMapOfShapeListOfShape& theEImages,
6176 TopTools_DataMapOfShapeListOfShape& theEETrim,
6177 TopTools_MapOfShape& theModifiedEdges,
6178 Handle(BRepAlgo_AsDes)& theAsDes)
6179{
6180 // update images and origins of edges, plus update AsDes
6181 //
6182 // new edges
6183 TopTools_ListOfShape aLE;
6184 // back connection from edges to faces
6185 TopTools_DataMapOfShapeListOfShape aMELF;
6186 //
b443d536 6187 TopTools_MapOfShape aMETmp;
ecf4f17c 6188 Standard_Integer i, aNb = theFLE.Extent();
6189 for (i = 1; i <= aNb; ++i) {
6190 const TopoDS_Face& aF = TopoDS::Face(theFLE.FindKey(i));
6191 //
6192 const TopTools_ListOfShape& aLEInt = theFLE(i);
6193 TopTools_ListIteratorOfListOfShape aItLE(aLEInt);
6194 for (; aItLE.More(); aItLE.Next()) {
6195 const TopoDS_Shape& aE = aItLE.Value();
b443d536 6196 if ((theMECheckExt.Contains(aE) || aMETmp.Contains(aE)) && !theEImages.IsBound(aE)) {
6197 theMECheckExt.Remove(aE);
6198 aMETmp.Add(aE);
6199 continue;
6200 }
ecf4f17c 6201 TopTools_ListOfShape* pLF = aMELF.ChangeSeek(aE);
6202 if (!pLF) {
6203 pLF = aMELF.Bound(aE, TopTools_ListOfShape());
6204 aLE.Append(aE);
6205 }
6206 pLF->Append(aF);
6207 }
6208 }
6209 //
6210 if (aLE.IsEmpty()) {
6211 return;
6212 }
6213 //
6214 // bounding edges, that are going to be replaced
6215 TopTools_MapOfShape aMEB;
6216 //
6217 // new intersection edges
ecf4f17c 6218 TopTools_MapOfShape aMENew;
6219 // map of old vertices
6220 TopTools_MapOfShape aMVOld;
6221 // back connection to untrimmed edges
6222 TopTools_DataMapOfShapeListOfShape aDMEOr;
6223 //
6224 // trim the new intersection edges
dcba2e5c 6225 TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt,
6226 theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF);
ecf4f17c 6227 //
dcba2e5c 6228 if (theEImages.IsEmpty())
6229 {
6230 // No new splits is preserved
6231 // update intersection edges and exit
ecf4f17c 6232 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6233 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6234 return;
6235 }
dcba2e5c 6236
6237 BRep_Builder aBB;
6238
6239 // Make connexity blocks of the invalid edges
6240 // and treat each block separately
6241
6242 // Compound of all invalid edges to make the blocks
6243 TopoDS_Compound aCEAll;
6244 aBB.MakeCompound(aCEAll);
6245
6246 Standard_Integer aNbE = theOENEdges.Extent();
6247 for (i = 1; i <= aNbE; ++i)
6248 aBB.Add(aCEAll, theOENEdges.FindKey(i));
6249
6250 // Separate the edges into blocks
6251 TopTools_ListOfShape aLBlocks;
6252 BOPTools_AlgoTools::MakeConnexityBlocks(aCEAll, TopAbs_VERTEX, TopAbs_EDGE, aLBlocks);
6253
6254 // Perform intersection of the new splits for each block
6255
6256 // Intersected splits
6257 TopTools_IndexedDataMapOfShapeListOfShape aMBlocksSp;
6258
6259 TopTools_ListIteratorOfListOfShape aItLB(aLBlocks);
6260 for (; aItLB.More(); aItLB.Next())
6261 {
6262 const TopoDS_Shape& aBlock = aItLB.Value();
6263
6264 // Get the list of new edges for the block
6265 TopTools_ListOfShape aBlockLENew;
6266 {
6267 // Fence map
6268 TopTools_MapOfShape aMEFence;
6269 TopExp_Explorer anExpE(aBlock, TopAbs_EDGE);
6270 for (; anExpE.More(); anExpE.Next())
6271 {
6272 const TopoDS_Shape& aE = anExpE.Current();
6273 const TopTools_ListOfShape& aLEInt = theOENEdges.FindFromKey(aE);
6274 TopTools_ListIteratorOfListOfShape aItLEInt(aLEInt);
6275 for (; aItLEInt.More(); aItLEInt.Next())
6276 {
6277 if (aMEFence.Add(aItLEInt.Value()))
6278 aBlockLENew.Append(aItLEInt.Value());
6279 }
6280 }
6281 }
6282
6283 if (aBlockLENew.IsEmpty())
6284 continue;
6285
6286 // Get the splits of new edges to intersect
1155d05a 6287 TopTools_ListOfShape aLSplits;
dcba2e5c 6288
6289 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
6290 for (; aItLE.More(); aItLE.Next())
6291 {
ecf4f17c 6292 const TopoDS_Shape& aE = aItLE.Value();
ecf4f17c 6293 TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
dcba2e5c 6294 if (!pLEIm || pLEIm->IsEmpty())
ecf4f17c 6295 continue;
dcba2e5c 6296
ecf4f17c 6297 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
dcba2e5c 6298 for (; aItLEIm.More(); aItLEIm.Next())
6299 aLSplits.Append(aItLEIm.Value());
6300 }
6301
6302 if (aLSplits.IsEmpty())
6303 continue;
6304
6305 TopoDS_Shape aCE;
6306 if (aLSplits.Extent() > 1)
6307 // Intersect the new splits among themselves to avoid self-intersections
6308 IntersectEdges(aLSplits, aBlockLENew, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6309 theEImages, theModifiedEdges, aDMEOr, aMELF, aCE);
6310 else
6311 aCE = aLSplits.First();
6312
6313 aMBlocksSp.Add(aCE, aBlockLENew);
6314 }
6315
6316 // Perform filtering of the edges in two steps:
6317 // - Check each block separately using localized bounds
6318 // taken only from the splits of faces of the current block;
6319 // - Intersect all splits together and filter the splits by all bounds.
6320
6321 // FIRST STAGE - separate treatment of the blocks
6322
6323 // Valid splits to be preserved on the first stage
6324 TopTools_MapOfShape aMEVal;
6325
6326 // Blocks of valid edges on the first stage
1155d05a 6327 TopTools_ListOfShape aLValBlocks;
dcba2e5c 6328
6329 // Context for caching the classification tools
6330 Handle(IntTools_Context) aCtx = new IntTools_Context;
6331
6332 Standard_Integer aNbB = aMBlocksSp.Extent();
6333 for (i = 1; i <= aNbB; ++i)
6334 {
6335 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6336 const TopTools_ListOfShape& aBlockLENew = aMBlocksSp(i);
6337
6338 // Get all participating faces to get the bounds
6339 TopTools_ListOfShape aLFaces;
6340 TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
6341 for (; aItLE.More(); aItLE.Next())
6342 {
6343 const TopTools_ListOfShape *pLF = aMELF.Seek(aItLE.Value());
6344 if (!pLF)
6345 continue;
6346 TopTools_ListIteratorOfListOfShape aItLF(*pLF);
6347 for (; aItLF.More(); aItLF.Next())
6348 AppendToList(aLFaces, aItLF.Value());
6349 }
6350
6351 // Localized bounds of the splits of the offset faces
6352 // to filter the new splits of the current block
6353 TopoDS_Shape aFilterBounds;
6354 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6355
6356 // Filter the splits by bounds
6357 TopTools_MapOfShape aMEInvLoc;
6358 GetInvalidEdgesByBounds(aCE, aFilterBounds, theFImages, theSolids,
6359 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6360 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInvLoc);
6361
6362 // Keep only valid edges of the block
6363 TopoDS_Compound aCEVal;
6364 aBB.MakeCompound(aCEVal);
6365
6366 Standard_Boolean bKept = Standard_False;
6367
6368 TopExp_Explorer anExpE(aCE, TopAbs_EDGE);
6369 for (; anExpE.More(); anExpE.Next())
6370 {
6371 const TopoDS_Shape& aESp = anExpE.Current();
6372 if (!aMEInvLoc.Contains(aESp) && aMEVal.Add(aESp))
6373 {
6374 aBB.Add(aCEVal, aESp);
6375 bKept = Standard_True;
ecf4f17c 6376 }
6377 }
dcba2e5c 6378
6379 if (bKept)
6380 aLValBlocks.Append(aCEVal);
ecf4f17c 6381 }
dcba2e5c 6382
6383 // Filter the images of edges after the first filtering stage
6384 TopoDS_Shape aSplits1;
6385 FilterSplits(aLE, aMEVal, Standard_False, theEImages, aSplits1);
6386
6387 if (aLValBlocks.IsEmpty())
6388 {
6389 // update intersection edges
6390 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6391 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6392 return;
ecf4f17c 6393 }
dcba2e5c 6394
6395 // SECOND STAGE - Filter the remaining splits together
6396
6397 // Add for intersection already removed new edges using them
6398 // as markers for other invalid edges
6399 aNbB = aMBlocksSp.Extent();
6400 for (i = 1; i <= aNbB; ++i)
6401 {
6402 const TopoDS_Shape& aCE = aMBlocksSp.FindKey(i);
6403 for (TopExp_Explorer anExp(aCE, TopAbs_EDGE); anExp.More(); anExp.Next())
6404 {
6405 const TopoDS_Shape& aEIm = anExp.Current();
6406 if (aMENew.Contains(aEIm) && !aMEVal.Contains(aEIm))
6407 aLValBlocks.Append(aEIm);
6408 }
6409 }
6410
6411 if (aLValBlocks.Extent() > 1)
6412 // intersect the new splits among themselves to avoid self-intersections
6413 IntersectEdges(aLValBlocks, aLE, theMVBounds, theVertsToAvoid, aMENew, theMECheckExt,
6414 theEImages, theModifiedEdges, aDMEOr, aMELF, aSplits1);
6415 else
6416 aSplits1 = aLValBlocks.First();
6417
6418 // Get all faces to get the bounds from their splits
6419 TopTools_ListOfShape aLFaces;
6420 for (i = 1; i <= theFImages.Extent(); ++i)
6421 aLFaces.Append(theFImages.FindKey(i));
6422
6423 // Bounds of the splits of the offset faces to filter the new splits
6424 TopoDS_Shape aFilterBounds;
6425 GetBounds(aLFaces, theFImages, aMEB, aFilterBounds);
6426
6427 // Filter the splits by intersection with bounds
6428 TopTools_MapOfShape aMEInv;
6429 GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids,
6430 theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages,
6431 theMECheckExt, theMEInvOnArt, aCtx, theVertsToAvoid, aMEInv);
6432
6433 // Filter the images of edges after the second filtering stage
6434 // and combine all valid edges into a single compound
6435 TopoDS_Shape aSplits;
6436 FilterSplits(aLE, aMEInv, Standard_True, theEImages, aSplits);
6437
ecf4f17c 6438 // get bounds to update
6439 // we need to update the edges of all the affected faces
6440 TopTools_ListOfShape aLF;
6441 // prepare the vertices from new splits of edges
6442 TopTools_IndexedMapOfShape aMVSp;
6443 TopExp::MapShapes(aSplits, TopAbs_VERTEX, aMVSp);
6444 //
6445 Standard_Integer aNbF = theFImages.Extent();
6446 for (i = 1; i <= aNbF; ++i) {
6447 const TopoDS_Shape& aF = theFImages.FindKey(i);
6448 if (theFLE.Contains(aF)) {
6449 aLF.Append(aF);
6450 continue;
6451 }
6452 //
6453 // check the splits of faces to have vertices from splits
6454 const TopTools_ListOfShape& aLFIm = theFImages(i);
6455 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
6456 for (; aItLFIm.More(); aItLFIm.Next()) {
6457 const TopoDS_Shape& aFIm = aItLFIm.Value();
6458 //
6459 TopExp_Explorer aExpV(aFIm, TopAbs_VERTEX);
6460 for (; aExpV.More(); aExpV.Next()) {
6461 const TopoDS_Shape& aV = aExpV.Current();
6462 if (aMVSp.Contains(aV)) {
6463 break;
6464 }
6465 }
6466 //
6467 if (aExpV.More()) {
6468 break;
6469 }
6470 }
6471 //
6472 if (aItLFIm.More()) {
6473 aLF.Append(aF);
6474 }
6475 }
6476 //
6477 // get bounds from splits of faces of aLF
6478 TopoDS_Shape aBounds;
6479 TopTools_ListOfShape aLAValid, aLABounds;
6480 GetBoundsToUpdate(aLF, theOEImages, theOEOrigins, aMEB,
6481 aLABounds, aLAValid, aBounds, theAsDes);
6482 //
81a55a69 6483 // Intersect valid splits with bounds and update both
ecf4f17c 6484 BOPAlgo_Builder aGF;
ecf4f17c 6485 aGF.AddArgument(aBounds);
edfa30de 6486 aGF.AddArgument(aSplits);
ecf4f17c 6487 aGF.Perform();
6488 //
6489 // update splits
6490 UpdateImages(aLE, theEImages, aGF, theModifiedEdges);
6491 //
6492 // update new intersection edges
6493 UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
6494 theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
6495 //
6496 // update bounds
6497 UpdateImages(aLAValid, theOEImages, aGF, theModifiedEdges);
6498 UpdateOrigins(aLABounds, theOEOrigins, aGF);
6499 UpdateOrigins(aLABounds, theEdgesOrigins, aGF);
6500 UpdateIntersectedEdges(aLABounds, theETrimEInf, aGF);
6501 //
edfa30de 6502 // update the EdgesToAvoid with the splits
ecf4f17c 6503 TopTools_IndexedMapOfShape aNewEdges;
6504 const TopTools_ListOfShape* pSplitsIm = aGF.Images().Seek(aSplits);
6505 if (pSplitsIm) {
6506 TopTools_ListIteratorOfListOfShape aItSpIm(*pSplitsIm);
6507 for (; aItSpIm.More(); aItSpIm.Next()) {
6508 TopExp::MapShapes(aItSpIm.Value(), TopAbs_EDGE, aNewEdges);
6509 }
6510 }
6511 //
81a55a69 6512 // Rebuild the map of edges to avoid, using the intersection results
6513 TopTools_IndexedMapOfShape aMEAvoid;
6514 // GF's data structure
6515 const BOPDS_PDS& pDS = aGF.PDS();
6516
dcba2e5c 6517 aNbE = theEdgesToAvoid.Extent();
81a55a69 6518 for (i = 1; i <= aNbE; ++i)
6519 {
ecf4f17c 6520 const TopoDS_Shape& aE = theEdgesToAvoid(i);
6521 const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
81a55a69 6522
6523 // Only untouched and fully coinciding edges should be kept in the avoid map
6524 Standard_Boolean bKeep = aLEIm.IsEmpty();
6525 if (aLEIm.Extent() == 1 && aE.IsSame(aLEIm.First()))
6526 {
6527 const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(pDS->Index(aE));
6528 if (aLPB.Extent() == 1)
6529 {
6530 const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
6531 const Handle(BOPDS_CommonBlock)& aCB = pDS->CommonBlock(aPB);
6532 if (!aCB.IsNull())
6533 {
6534 const BOPDS_ListOfPaveBlock& aLPBCB = aCB->PaveBlocks();
6535 BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
6536 for (; aItLPB.More(); aItLPB.Next())
6537 {
6538 if (pDS->PaveBlocks(aItLPB.Value()->OriginalEdge()).Extent() > 1)
6539 break;
6540 }
6541 bKeep = !aItLPB.More();
6542 }
6543 }
6544 }
6545
6546 if (bKeep)
6547 {
6548 // keep the original edge
6549 aMEAvoid.Add(aE);
6550 continue;
6551 }
6552
ecf4f17c 6553 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
81a55a69 6554 for (; aItLEIm.More(); aItLEIm.Next())
6555 {
ecf4f17c 6556 const TopoDS_Shape& aEIm = aItLEIm.Value();
81a55a69 6557 if (!aNewEdges.Contains(aEIm))
6558 aMEAvoid.Add(aEIm);
ecf4f17c 6559 }
6560 }
81a55a69 6561 theEdgesToAvoid = aMEAvoid;
ecf4f17c 6562}
6563
6564//=======================================================================
6565//function : TrimNewIntersectionEdges
6566//purpose :
6567//=======================================================================
6568void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
6569 const TopTools_DataMapOfShapeListOfShape& theEETrim,
6570 const TopTools_MapOfShape& theMVBounds,
41aa3c3d 6571 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 6572 TopTools_DataMapOfShapeListOfShape& theEImages,
6573 TopTools_MapOfShape& theMEB,
6574 TopTools_MapOfShape& theMVOld,
dcba2e5c 6575 TopTools_MapOfShape& theMENew,
41aa3c3d 6576 TopTools_DataMapOfShapeListOfShape& theDMEOr,
6577 TopTools_DataMapOfShapeListOfShape& theMELF)
ecf4f17c 6578{
6579 TopTools_ListIteratorOfListOfShape aIt, aIt1;
6580 aIt.Initialize(theLE);
6581 for (; aIt.More(); aIt.Next()) {
6582 const TopoDS_Shape& aE = aIt.Value();
6583 //
b443d536 6584 Standard_Boolean bCheckExt = theMECheckExt.Remove(aE);
6585 //
41aa3c3d 6586 Standard_Boolean bOld = theEETrim.IsBound(aE);
6587 if (bOld) {
ecf4f17c 6588 const TopTools_ListOfShape& aLET = theEETrim.Find(aE);
6589 aIt1.Initialize(aLET);
6590 for (; aIt1.More(); aIt1.Next()) {
6591 const TopoDS_Shape& aET = aIt1.Value();
6592 theMEB.Add(aET);
6593 TopExp_Explorer aExpV(aET, TopAbs_VERTEX);
6594 for (; aExpV.More(); aExpV.Next()) {
6595 const TopoDS_Shape& aV = aExpV.Current();
6596 theMVOld.Add(aV);
6597 }
6598 }
6599 }
6600 //
6601 if (!theEImages.IsBound(aE)) {
6602 continue;
6603 }
6604 //
6605 TopTools_ListOfShape& aLEIm = theEImages.ChangeFind(aE);
6606 if (aLEIm.IsEmpty()) {
6607 theEImages.UnBind(aE);
6608 continue;
6609 }
6610 //
6611 TopoDS_Shape aCEIm;
6612 TopTools_MapOfShape aMEVBounds;
6613 //
a8232603 6614 if (aLEIm.Extent() > 1) {
ecf4f17c 6615 TopTools_IndexedMapOfShape aMV;
6616 // fuse these parts
6617 BOPAlgo_Builder aGFE;
6618 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6619 for (; aItLEIm.More(); aItLEIm.Next()) {
6620 const TopoDS_Shape& aEIm = aItLEIm.Value();
6621 aGFE.AddArgument(aEIm);
6622 TopExp::MapShapes(aEIm, TopAbs_VERTEX, aMV);
6623 }
6624 //
6625 // add two bounding vertices of this edge to the operation
6626 TopoDS_Vertex aV1, aV2;
6627 TopExp::Vertices(TopoDS::Edge(aE), aV1, aV2);
6628 //
6629 aGFE.AddArgument(aV1);
6630 aGFE.AddArgument(aV2);
6631 aMV.Add(aV1);
6632 aMV.Add(aV2);
6633 //
6634 aGFE.Perform();
33ba8565 6635 if (!aGFE.HasErrors()) {
ecf4f17c 6636 // get images of bounding vertices to remove splits containing them
6637 // in case some of the bounding edges has been interfered
6638 // during operation it is necessary to update their images as well
6639 Standard_Integer iV, aNbV = aMV.Extent();
6640 for (iV = 1; iV <= aNbV; ++iV) {
6641 const TopoDS_Shape& aV = aMV(iV);
6642 if (theMVBounds.Contains(aV) || aV.IsSame(aV1) || aV.IsSame(aV2)) {
6643 const TopTools_ListOfShape& aLVIm = aGFE.Modified(aV);
41aa3c3d 6644 aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
ecf4f17c 6645 }
6646 }
6647 //
6648 aCEIm = aGFE.Shape();
6649 }
6650 }
6651 else {
6652 aCEIm = aLEIm.First();
6653 }
6654 //
6655 aLEIm.Clear();
6656 //
6657 TopExp_Explorer aExp(aCEIm, TopAbs_EDGE);
6658 for (; aExp.More(); aExp.Next()) {
6659 const TopoDS_Shape& aEIm = aExp.Current();
6660 //
6661 // check the split not to contain bounding vertices
6662 TopoDS_Iterator aItV(aEIm);
6663 for (; aItV.More(); aItV.Next()) {
6664 const TopoDS_Shape& aV = aItV.Value();
6665 if (aMEVBounds.Contains(aV) || theMVBounds.Contains(aV)) {
6666 break;
6667 }
6668 }
6669 //
6670 if (!aItV.More()) {
ecf4f17c 6671 aLEIm.Append(aEIm);
6672 //
6673 theDMEOr.Bound(aEIm, TopTools_ListOfShape())->Append(aE);
6674 }
6675 }
6676 //
6677 if (aLEIm.IsEmpty()) {
6678 theEImages.UnBind(aE);
6679 }
6680 else {
41aa3c3d 6681 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6682 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6683 for (; aItLEIm.More(); aItLEIm.Next()) {
6684 const TopoDS_Shape& aEIm = aItLEIm.Value();
6685 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6686 if (!pLFEIm) {
6687 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6688 }
6689 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6690 for (; aItLF.More(); aItLF.Next()) {
6691 AppendToList(*pLFEIm, aItLF.Value());
6692 }
6693 //
6694 if (bCheckExt) {
6695 theMECheckExt.Add(aEIm);
6696 }
6697 else if (!bOld) {
dcba2e5c 6698 theMENew.Add(aEIm);
ecf4f17c 6699 }
6700 }
6701 }
6702 }
6703}
6704
6705//=======================================================================
6706//function : IntersectEdges
6707//purpose : Intersecting the trimmed edges to avoid self-intersections
6708//=======================================================================
1155d05a 6709void IntersectEdges(const TopTools_ListOfShape& theLA,
ecf4f17c 6710 const TopTools_ListOfShape& theLE,
ecf4f17c 6711 const TopTools_MapOfShape& theMVBounds,
6712 const TopTools_MapOfShape& theVertsToAvoid,
dcba2e5c 6713 TopTools_MapOfShape& theMENew,
41aa3c3d 6714 TopTools_MapOfShape& theMECheckExt,
ecf4f17c 6715 TopTools_DataMapOfShapeListOfShape& theEImages,
6716 TopTools_MapOfShape& theModifiedEdges,
6717 TopTools_DataMapOfShapeListOfShape& theDMEOr,
41aa3c3d 6718 TopTools_DataMapOfShapeListOfShape& theMELF,
ecf4f17c 6719 TopoDS_Shape& theSplits)
6720{
6721 BOPAlgo_Builder aGFA;
6722 aGFA.SetArguments(theLA);
6723 aGFA.Perform();
33ba8565 6724 if (aGFA.HasErrors()) {
ecf4f17c 6725 // just copy input to the result
6726 TopoDS_Compound aSp;
6727 BRep_Builder aBB;
6728 aBB.MakeCompound(aSp);
1155d05a 6729 TopTools_ListIteratorOfListOfShape anIt(theLA);
ecf4f17c 6730 for (; anIt.More(); anIt.Next()) {
6731 const TopoDS_Shape& aE = anIt.Value();
6732 aBB.Add(aSp, aE);
6733 }
6734 theSplits = aSp;
6735 return;
6736 }
6737 //
6738 UpdateImages(theLE, theEImages, aGFA, theModifiedEdges);
6739 //
6740 // compound of valid splits
6741 theSplits = aGFA.Shape();
6742 //
ecf4f17c 6743 TopTools_ListIteratorOfListOfShape aIt, aIt1;
dcba2e5c 6744
6745 // prepare list of edges to update
6746 TopTools_ListOfShape aLEInput;
6747 for (aIt.Initialize(theLA); aIt.More(); aIt.Next())
6748 {
6749 TopExp_Explorer anExpE(aIt.Value(), TopAbs_EDGE);
6750 for (; anExpE.More(); anExpE.Next())
6751 aLEInput.Append(anExpE.Current());
6752 }
6753
6754 // update new edges
6755 aIt.Initialize(aLEInput);
ecf4f17c 6756 for (; aIt.More(); aIt.Next()) {
6757 const TopoDS_Shape& aE = aIt.Value();
dcba2e5c 6758 if (!theMENew.Contains(aE))
6759 continue;
6760
ecf4f17c 6761 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
dcba2e5c 6762 if (aLEIm.IsEmpty())
6763 continue;
6764
6765 theMENew.Remove(aE);
6766 aIt1.Initialize(aLEIm);
6767 for (; aIt1.More(); aIt1.Next())
6768 theMENew.Add(aIt1.Value());
ecf4f17c 6769 }
6770 //
41aa3c3d 6771 // update edges after intersection for extended checking
dcba2e5c 6772 aIt.Initialize(aLEInput);
41aa3c3d 6773 for (; aIt.More(); aIt.Next()) {
6774 const TopoDS_Shape& aE = aIt.Value();
6775 const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
6776 if (aLEIm.IsEmpty()) {
6777 continue;
6778 }
6779 //
6780 if (theMECheckExt.Contains(aE)) {
6781 aIt1.Initialize(aLEIm);
6782 for (; aIt1.More(); aIt1.Next()) {
6783 theMECheckExt.Add(aIt1.Value());
6784 }
6785 theMECheckExt.Remove(aE);
6786 }
6787 //
6788 const TopTools_ListOfShape& aLFE = theMELF.Find(aE);
6789 aIt1.Initialize(aLEIm);
6790 for (; aIt1.More(); aIt1.Next()) {
6791 const TopoDS_Shape& aEIm = aIt1.Value();
6792 TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm);
6793 if (!pLFEIm) {
6794 pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape());
6795 }
6796 TopTools_ListIteratorOfListOfShape aItLF(aLFE);
6797 for (; aItLF.More(); aItLF.Next()) {
6798 AppendToList(*pLFEIm, aItLF.Value());
6799 }
6800 }
6801 }
6802 //
ecf4f17c 6803 TopTools_MapOfShape aMEInv;
6804 GetInvalidEdges(theVertsToAvoid, theMVBounds, aGFA, aMEInv);
6805 if (aMEInv.Extent()) {
6806 // update shape
6807 TopoDS_Compound aSp;
6808 BRep_Builder aBB;
6809 aBB.MakeCompound(aSp);
6810 TopExp_Explorer aExp(theSplits, TopAbs_EDGE);
6811 for (; aExp.More(); aExp.Next()) {
6812 const TopoDS_Shape& aE = aExp.Current();
6813 if (!aMEInv.Contains(aE)) {
6814 aBB.Add(aSp, aE);
6815 }
6816 }
6817 theSplits = aSp;
6818 }
6819 //
dcba2e5c 6820 // update origins
6821 UpdateOrigins(aLEInput, theDMEOr, aGFA);
ecf4f17c 6822}
6823
6824//=======================================================================
6825//function : GetBounds
6826//purpose : Getting edges from the splits of offset faces
6827//=======================================================================
dcba2e5c 6828void GetBounds(const TopTools_ListOfShape& theLFaces,
6829 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
ecf4f17c 6830 const TopTools_MapOfShape& theMEB,
6831 TopoDS_Shape& theBounds)
6832{
ecf4f17c 6833 BRep_Builder aBB;
dcba2e5c 6834 // Make compound of edges contained in the splits of faces
6835 TopoDS_Compound aBounds;
ecf4f17c 6836 aBB.MakeCompound(aBounds);
dcba2e5c 6837 // Fence map
ecf4f17c 6838 TopTools_MapOfShape aMFence;
dcba2e5c 6839
6840 TopTools_ListIteratorOfListOfShape aItLF(theLFaces);
6841 for (; aItLF.More(); aItLF.Next())
6842 {
6843 const TopTools_ListOfShape* pLFIm = theFImages.Seek(aItLF.Value());
6844 if (!pLFIm)
6845 continue;
6846 TopTools_ListIteratorOfListOfShape aIt(*pLFIm);
6847 for (; aIt.More(); aIt.Next())
6848 {
ecf4f17c 6849 const TopoDS_Shape& aFIm = aIt.Value();
6850 //
6851 TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
dcba2e5c 6852 for (; aExpE.More(); aExpE.Next())
6853 {
ecf4f17c 6854 const TopoDS_Shape& aEIm = aExpE.Current();
6855 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6856 aBB.Add(aBounds, aEIm);
6857 }
6858 }
6859 }
6860 }
6861 theBounds = aBounds;
6862}
6863
6864//=======================================================================
6865//function : GetBoundsToUpdate
6866//purpose : Get bounding edges that should be updated
6867//=======================================================================
6868void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
6869 const TopTools_DataMapOfShapeListOfShape& theOEImages,
6870 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
6871 const TopTools_MapOfShape& theMEB,
6872 TopTools_ListOfShape& theLABounds,
6873 TopTools_ListOfShape& theLAValid,
6874 TopoDS_Shape& theBounds,
6875 Handle(BRepAlgo_AsDes)& theAsDes)
6876{
6877 // get all edges
6878 TopoDS_Compound aBounds;
6879 BRep_Builder aBB;
6880 aBB.MakeCompound(aBounds);
6881 //
6882 TopTools_MapOfShape aMAValid, aMFence;
6883 //
6884 TopTools_ListIteratorOfListOfShape aItLF(theLF);
6885 for (; aItLF.More(); aItLF.Next()) {
6886 const TopoDS_Shape& aF = aItLF.Value();
6887 //
6888 TopTools_IndexedMapOfShape aMDE;
6889 const TopTools_ListOfShape& aLFDes = theAsDes->Descendant(aF);
6890 TopTools_ListIteratorOfListOfShape aItLFDes(aLFDes);
6891 for (; aItLFDes.More(); aItLFDes.Next()) {
6892 const TopoDS_Shape& aED = aItLFDes.Value();
6893 const TopTools_ListOfShape *pLEDIm = theOEImages.Seek(aED);
6894 if (!pLEDIm) {
6895 aMDE.Add(aED);
6896 continue;
6897 }
6898 //
6899 TopTools_ListIteratorOfListOfShape aItLEDIm(*pLEDIm);
6900 for (; aItLEDIm.More(); aItLEDIm.Next()) {
6901 const TopoDS_Shape& aEDIm = aItLEDIm.Value();
6902 aMDE.Add(aEDIm);
6903 }
6904 }
6905 //
6906 Standard_Integer j, aNbE = aMDE.Extent();
6907 for (j = 1; j <= aNbE; ++j) {
6908 const TopoDS_Edge& aEIm = TopoDS::Edge(aMDE(j));
6909 //
6910 if (!theMEB.Contains(aEIm) && aMFence.Add(aEIm)) {
6911 aBB.Add(aBounds, aEIm);
6912 theLABounds.Append(aEIm);
6913 }
6914 //
6915 const TopTools_ListOfShape *pLO = theOEOrigins.Seek(aEIm);
6916 if (pLO) {
6917 TopTools_ListIteratorOfListOfShape aItLO(*pLO);
6918 for (; aItLO.More(); aItLO.Next()) {
6919 const TopoDS_Shape& aEO = aItLO.Value();
6920 //
6921 if (aMAValid.Add(aEO)) {
6922 theLAValid.Append(aEO);
6923 }
6924 }
6925 }
6926 else {
6927 if (aMAValid.Add(aEIm)) {
6928 theLAValid.Append(aEIm);
6929 }
6930 }
6931 }
6932 }
6933 theBounds = aBounds;
6934}
6935
6936//=======================================================================
6937//function : GetInvalidEdgesByBounds
6938//purpose : Filter new splits by intersection with bounds
6939//=======================================================================
6940void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
6941 const TopoDS_Shape& theBounds,
ecf4f17c 6942 const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6943 const TopoDS_Shape& theSolids,
6944 const TopTools_IndexedMapOfShape& theInvEdges,
6945 const TopTools_MapOfShape& theMVOld,
6946 const TopTools_MapOfShape& theMENew,
6947 const TopTools_DataMapOfShapeListOfShape& theDMEOr,
41aa3c3d 6948 const TopTools_DataMapOfShapeListOfShape& theMELF,
ecf4f17c 6949 const TopTools_DataMapOfShapeListOfShape& theEImages,
41aa3c3d 6950 const TopTools_MapOfShape& theMECheckExt,
a8232603 6951 const TopTools_MapOfShape& theMEInvOnArt,
dcba2e5c 6952 Handle(IntTools_Context)& theCtx,
ecf4f17c 6953 TopTools_MapOfShape& theVertsToAvoid,
6954 TopTools_MapOfShape& theMEInv)
6955{
a8232603 6956 // map splits to check the vertices of edges
6957 TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6958 TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6959 //
ecf4f17c 6960 BOPAlgo_Section aSec;
6961 aSec.AddArgument(theSplits);
6962 aSec.AddArgument(theBounds);
6963 //
6964 aSec.Perform();
6965 //
6966 // invalid vertices
6967 TopTools_IndexedMapOfShape aMVInv;
6968 // vertices to check additionally by classification relatively to solid
6969 TopTools_MapOfShape aMVCheckAdd;
6970 // collect parts for removal
6971 const BOPDS_PDS& pDS = aSec.PDS();
6972 //
6973 // check edge/edge intersections
6974 const BOPDS_VectorOfInterfEE& aEEs = pDS->InterfEE();
1155d05a 6975 Standard_Integer i, aNb = aEEs.Length();
ecf4f17c 6976 for (i = 0; i < aNb; ++i) {
6977 const BOPDS_InterfEE& aEE = aEEs(i);
ecf4f17c 6978 //
6979 const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1());
6980 const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2());
6981 //
41aa3c3d 6982 if (!aEE.HasIndexNew()) {
6983 if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) {
6984 theMEInv.Add(aE1);
6985 }
6986 continue;
6987 }
6988 //
ecf4f17c 6989 if (theInvEdges.Contains(aE2)) {
6990 theMEInv.Add(aE1);
6991 }
6992 //
a8232603 6993 if (theMEInvOnArt.Contains(aE2)) {
6994 // avoid checking of the vertices of the split edge intersected by
6995 // the invalid edge from artificial face
6996 TopoDS_Vertex aV1, aV2;
6997 TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2);
6998 if (aDMVE.Contains(aV1) && aDMVE.Contains(aV2)) {
6999 continue;
7000 }
7001 }
7002 //
41aa3c3d 7003 // add vertices of all images of the edge from splits for checking
ecf4f17c 7004 const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1);
7005 TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr);
7006 for (; aItLEOr.More(); aItLEOr.Next()) {
7007 const TopoDS_Shape& aEOr = aItLEOr.Value();
7008 //
dcba2e5c 7009 const TopTools_ListOfShape *pLEIm = theEImages.Seek(aEOr);
7010 if (!pLEIm)
7011 continue;
7012 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
ecf4f17c 7013 for (; aItLEIm.More(); aItLEIm.Next()) {
7014 const TopoDS_Shape& aEIm = aItLEIm.Value();
7015 //
7016 TopoDS_Iterator aItV(aEIm);
7017 for (; aItV.More(); aItV.Next()) {
7018 const TopoDS_Shape& aV = aItV.Value();
7019 if (!theMVOld.Contains(aV)) {
7020 aMVInv.Add(aV);
7021 aMVCheckAdd.Add(aV);
7022 }
7023 }
7024 }
7025 }
7026 }
7027 //
ecf4f17c 7028 // to avoid unnecessary filling of parts due to extra trim of the edges
41aa3c3d 7029 // process Edge/Edge interferences of type EDGE, i.e. common blocks and check
7030 // not the bounding vertices of the edges, but check the edge itself
7031 // to be lying on some face
ecf4f17c 7032 //
7033 // all common blocks are contained in the result of SECTION operation
7034 // between sets of edges
7035 const TopoDS_Shape& aSecR = aSec.Shape();
7036 //
7037 TopTools_IndexedMapOfShape aMSSec;
7038 TopExp::MapShapes(aSecR, aMSSec);
7039 //
1155d05a 7040 const TopTools_DataMapOfShapeListOfShape& anIm = aSec.Images();
45d0af05 7041 for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
7042 {
ecf4f17c 7043 const TopoDS_Shape& aE = aExp.Current();
7044 if (aSec.IsDeleted(aE)) {
7045 // no common blocks for this edge
7046 continue;
7047 }
7048 //
1155d05a 7049 const TopTools_ListOfShape* pLEIm = anIm.Seek(aE);
ecf4f17c 7050 if (!pLEIm) {
7051 // no splits, i.e. completely coincides with some edge from boundary
7052 continue;
7053 }
7054 //
1155d05a 7055 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
ecf4f17c 7056 for (; aItLEIm.More(); aItLEIm.Next()) {
7057 const TopoDS_Shape& aEIm = aItLEIm.Value();
7058 if (!aMSSec.Contains(aEIm)) {
7059 // the edge included in section only partially.
41aa3c3d 7060 // the part not included in section may be excessive
ecf4f17c 7061 //
7062 // check vertices of this edge - if one of them is new
7063 // the edge might be removed
7064 TopoDS_Vertex aV1, aV2;
7065 TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2);
7066 if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) {
41aa3c3d 7067 // add this edge for checking by making new vertex in the middle of the edge
ecf4f17c 7068 TopoDS_Vertex aV;
7069 Standard_Real f, l;
7070 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l);
7071 BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion());
41aa3c3d 7072 // and adding this vertex for checking
7073 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
ecf4f17c 7074 aMVInv.Add(aV);
7075 break;
7076 }
7077 }
7078 }
7079 }
7080 //
41aa3c3d 7081 // Add for check also the edges created from common between splits
7082 // of offset faces edges not connected to any invalidity.
7083 // These edges may also accidentally fill some part.
7084 TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt);
7085 for (; aItM.More(); aItM.Next()) {
7086 const TopoDS_Shape& aE = aItM.Value();
7087 //
7088 // make new vertex in the middle of the edge
7089 TopoDS_Vertex aV;
7090 Standard_Real f, l;
7091 const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l);
7092 BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion());
7093 // add this vertex for checking
7094 aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
7095 aMVInv.Add(aV);
7096 }
7097 //
7098 // add for check also the vertices connected only to new or old edges
ecf4f17c 7099 aNb = aDMVE.Extent();
7100 for (i = 1; i <= aNb; ++i) {
7101 const TopoDS_Shape& aV = aDMVE.FindKey(i);
7102 if (theMVOld.Contains(aV)) {
7103 continue;
7104 }
7105 //
7106 Standard_Boolean bNew = Standard_False, bOld = Standard_False;
7107 const TopTools_ListOfShape& aLEx = aDMVE(i);
7108 TopTools_ListIteratorOfListOfShape aIt(aLEx);
7109 for (; aIt.More(); aIt.Next()) {
7110 const TopoDS_Shape& aE = aIt.Value();
41aa3c3d 7111 if (theMECheckExt.Contains(aE)) {
7112 continue;
7113 }
7114 //
ecf4f17c 7115 if (theMENew.Contains(aE)) {
7116 bNew = Standard_True;
7117 }
7118 else {
7119 bOld = Standard_True;
7120 }
7121 //
7122 if (bNew && bOld) {
7123 break;
7124 }
7125 }
7126 //
7127 if (!bNew || !bOld) {
7128 aMVInv.Add(aV);
7129 aMVCheckAdd.Remove(aV);
7130 }
7131 }
7132 //
dcba2e5c 7133 // perform the checking of the vertices
41aa3c3d 7134 Standard_Integer iv, aNbIV = aMVInv.Extent();
ecf4f17c 7135 for (iv = 1; iv <= aNbIV; ++iv) {
7136 const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv));
41aa3c3d 7137 if (theMVOld.Contains(aV)) {
7138 continue;
7139 }
7140 //
7141 const TopTools_ListOfShape* pLEInv = aDMVE.Seek(aV);
7142 if (!pLEInv) {
7143 continue;
7144 }
7145 // find faces by the edges to check the vertex
7146 TopTools_IndexedMapOfShape aMF;
7147 TopTools_ListIteratorOfListOfShape aItLE(*pLEInv);
7148 for (; aItLE.More(); aItLE.Next()) {
7149 const TopoDS_Shape& aE = aItLE.Value();
7150 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
7151 TopTools_ListIteratorOfListOfShape aItLF(aLF);
7152 for (; aItLF.More(); aItLF.Next()) {
7153 aMF.Add(aItLF.Value());
7154 }
7155 }
7156 //
7157 // check the vertex to belong to some split of the faces
ecf4f17c 7158 Standard_Boolean bInvalid = Standard_True;
7159 //
41aa3c3d 7160 Standard_Integer aNbF = aMF.Extent();
ecf4f17c 7161 for (i = 1; i <= aNbF && bInvalid; ++i) {
41aa3c3d 7162 const TopoDS_Face& aF = TopoDS::Face(aMF(i));
ecf4f17c 7163 const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
7164 //
7165 TopTools_ListIteratorOfListOfShape aItLF(aLFIm);
7166 for (; aItLF.More() && bInvalid; aItLF.Next()) {
7167 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
7168 TopExp_Explorer aExp(aFIm, TopAbs_VERTEX);
7169 for (; aExp.More() && bInvalid; aExp.Next()) {
7170 const TopoDS_Shape& aVF = aExp.Current();
7171 bInvalid = !aVF.IsSame(aV);
7172 }
41aa3c3d 7173 }
7174 //
7175 if (bInvalid) {
7176 Standard_Real U, V, aTol;
dcba2e5c 7177 Standard_Integer iStatus = theCtx->ComputeVF(aV, aF, U, V, aTol);
41aa3c3d 7178 if (!iStatus) {
7179 // classify the point relatively faces
7180 gp_Pnt2d aP2d(U, V);
7181 aItLF.Initialize(aLFIm);
7182 for (; aItLF.More() && bInvalid; aItLF.Next()) {
7183 const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
dcba2e5c 7184 bInvalid = !theCtx->IsPointInOnFace(aFIm, aP2d);
41aa3c3d 7185 }
ecf4f17c 7186 }
7187 }
7188 }
7189 //
7190 if (bInvalid && aMVCheckAdd.Contains(aV)) {
7191 // the vertex is invalid for all faces
7192 // check the same vertex for the solids
41aa3c3d 7193 const gp_Pnt& aP = BRep_Tool::Pnt(aV);
7194 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
7195 //
ecf4f17c 7196 TopExp_Explorer aExpS(theSolids, TopAbs_SOLID);
7197 for (; aExpS.More() && bInvalid; aExpS.Next()) {
7198 const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current());
dcba2e5c 7199 BRepClass3d_SolidClassifier& aSC = theCtx->SolidClassifier(aSol);
ecf4f17c 7200 aSC.Perform(aP, aTolV);
7201 bInvalid = (aSC.State() == TopAbs_OUT);
7202 }
7203 }
7204 //
7205 if (bInvalid) {
7206 theVertsToAvoid.Add(aV);
41aa3c3d 7207 aItLE.Initialize(*pLEInv);
7208 for (; aItLE.More(); aItLE.Next()) {
7209 theMEInv.Add(aItLE.Value());
ecf4f17c 7210 }
7211 }
7212 }
7213}
7214
dcba2e5c 7215//=======================================================================
7216//function : FilterSplits
7217//purpose : Filter the images of edges from the invalid edges
7218//=======================================================================
7219void FilterSplits(const TopTools_ListOfShape& theLE,
7220 const TopTools_MapOfShape& theMEFilter,
7221 const Standard_Boolean theIsInv,
7222 TopTools_DataMapOfShapeListOfShape& theEImages,
7223 TopoDS_Shape& theSplits)
7224{
7225 TopoDS_Compound aSplits;
7226 BRep_Builder().MakeCompound(aSplits);
7227 TopTools_MapOfShape aMFence;
7228
7229 TopTools_ListIteratorOfListOfShape aItLE(theLE);
7230 for (; aItLE.More(); aItLE.Next())
7231 {
7232 const TopoDS_Shape& aE = aItLE.Value();
7233 TopTools_ListOfShape *pLEIm = theEImages.ChangeSeek(aE);
7234 if (!pLEIm)
7235 continue;
7236
7237 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
7238 for (; aItLEIm.More();)
7239 {
7240 const TopoDS_Shape& aEIm = aItLEIm.Value();
7241 if (theMEFilter.Contains(aEIm) == theIsInv)
7242 {
7243 pLEIm->Remove(aItLEIm);
7244 continue;
7245 }
7246
7247 if (aMFence.Add(aEIm))
7248 BRep_Builder().Add(aSplits, aEIm);
7249 aItLEIm.Next();
7250 }
7251
7252 if (pLEIm->IsEmpty())
7253 theEImages.UnBind(aE);
7254 }
7255 theSplits = aSplits;
7256}
7257
ecf4f17c 7258//=======================================================================
7259//function : UpdateNewIntersectionEdges
7260//purpose : Updating the maps of images and origins of the offset edges
7261//=======================================================================
7262void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
7263 const TopTools_DataMapOfShapeListOfShape& theMELF,
7264 const TopTools_DataMapOfShapeListOfShape& theEImages,
7265 const TopTools_IndexedMapOfShape& theInvEdges,
7266 const TopTools_MapOfShape& theInvertedEdges,
7267 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
7268 TopTools_DataMapOfShapeListOfShape& theOEImages,
7269 TopTools_DataMapOfShapeListOfShape& theOEOrigins,
7270 TopTools_DataMapOfShapeShape& theETrimEInf,
7271 TopTools_DataMapOfShapeListOfShape& theEETrim,
7272 TopTools_MapOfShape& theModifiedEdges,
7273 Handle(BRepAlgo_AsDes)& theAsDes)
7274{
7275 TopTools_ListOfShape aLEImEmpty;
7276 TopTools_ListIteratorOfListOfShape aIt, aIt1;
7277 // update global maps of images and origins with new splits
7278 aIt.Initialize(theLE);
7279 for (; aIt.More(); aIt.Next()) {
7280 const TopoDS_Shape& aE = aIt.Value();
7281 //
7282 if (!theEImages.IsBound(aE)) {
7283 TopTools_ListOfShape* pLET = theEETrim.ChangeSeek(aE);
7284 if (!pLET) {
7285 continue;
7286 }
7287 //
7288 TopTools_ListIteratorOfListOfShape aItLET(*pLET);
7289 for (; aItLET.More();) {
7290 const TopoDS_Shape& aET = aItLET.Value();
7291 if (!theInvEdges.Contains(aET) && !theInvertedEdges.Contains(aET)) {
7292 pLET->Remove(aItLET);
7293 }
7294 else {
7295 aItLET.Next();
7296 }
7297 }
7298 //
7299 if (pLET->IsEmpty()) {
7300 continue;
7301 }
7302 }
7303 // new images
7304 const TopTools_ListOfShape& aLENew =
7305 theEImages.IsBound(aE) ? theEImages.Find(aE) : aLEImEmpty;
7306 //
7307 // save connection to untrimmed edge for the next steps
7308 aIt1.Initialize(aLENew);
7309 for (; aIt1.More(); aIt1.Next()) {
7310 const TopoDS_Shape& aET = aIt1.Value();
7311 theETrimEInf.Bind(aET, aE);
7312 theModifiedEdges.Add(aET);
7313 }
7314 //
7315 // check if it is existing edge
7316 if (!theEETrim.IsBound(aE)) {
7317 const TopTools_ListOfShape& aLF = theMELF.Find(aE);
7318 // the edge is new
7319 // add this edge to AsDes
7320 aIt1.Initialize(aLF);
7321 for (; aIt1.More(); aIt1.Next()) {
7322 const TopoDS_Shape& aF = aIt1.Value();
7323 theAsDes->Add(aF, aE);
7324 }
7325 //
7326 // add aE to the images
7327 theOEImages.Bind(aE, aLENew);
7328 theModifiedEdges.Add(aE);
7329 //
7330 // add to origins
7331 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7332 for (; aItNew.More(); aItNew.Next()) {
7333 const TopoDS_Shape& aENew = aItNew.Value();
7334 if (theOEOrigins.IsBound(aENew)) {
7335 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7336 AppendToList(aEOrigins, aE);
7337 }
7338 else {
7339 TopTools_ListOfShape aEOrigins;
7340 aEOrigins.Append(aE);
7341 theOEOrigins.Bind(aENew, aEOrigins);
7342 }
7343 }
7344 //
7345 // update connection to initial origins
7346 if (theEdgesOrigins.IsBound(aE)) {
7347 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aE);
7348 aIt1.Initialize(aLENew);
7349 for (; aIt1.More(); aIt1.Next()) {
7350 const TopoDS_Shape& aENew = aIt1.Value();
7351 if (theEdgesOrigins.IsBound(aENew)) {
7352 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7353 TopTools_ListIteratorOfListOfShape aItOrInit(aLEOrInit);
7354 for (; aItOrInit.More(); aItOrInit.Next()) {
7355 const TopoDS_Shape& aEOr = aItOrInit.Value();
7356 AppendToList(aLENewOr, aEOr);
7357 }
7358 }
7359 else {
7360 theEdgesOrigins.Bind(aENew, aLEOrInit);
7361 }
7362 }
7363 }
7364 //
7365 continue;
7366 }
7367 //
7368 // old images
7369 const TopTools_ListOfShape& aLEOld = theEETrim.Find(aE);
7370 //
7371 // list of initial origins
7372 TopTools_ListOfShape anInitOrigins;
7373 //
7374 // it is necessary to replace the old edges with new ones
7375 aIt1.Initialize(aLEOld);
7376 for (; aIt1.More(); aIt1.Next()) {
7377 const TopoDS_Shape& aEOld = aIt1.Value();
7378 //
7379 if (theOEOrigins.IsBound(aEOld)) {
7380 // get its origins
7381 const TopTools_ListOfShape& aEOrigins = theOEOrigins.Find(aEOld);
7382 //
7383 TopTools_ListIteratorOfListOfShape aItOr(aEOrigins);
7384 for (; aItOr.More(); aItOr.Next()) {
7385 const TopoDS_Shape& aEOr = aItOr.Value();
7386 //
7387 theModifiedEdges.Add(aEOr);
7388 //
7389 TopTools_ListOfShape& aEImages = theOEImages.ChangeFind(aEOr);
7390 //
7391 // remove old edge from images
7392 TopTools_ListIteratorOfListOfShape aItIm(aEImages);
7393 for (; aItIm.More(); ) {
7394 const TopoDS_Shape& aEIm = aItIm.Value();
7395 if (aEIm.IsSame(aEOld)) {
7396 aEImages.Remove(aItIm);
7397 }
7398 else {
7399 aItIm.Next();
7400 }
7401 }
7402 //
7403 // add new images
7404 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7405 for (; aItNew.More(); aItNew.Next()) {
7406 const TopoDS_Shape& aENew = aItNew.Value();
7407 AppendToList(aEImages, aENew);
7408 if (theOEOrigins.IsBound(aENew)) {
7409 TopTools_ListOfShape& aENewOrigins = theOEOrigins.ChangeFind(aENew);
7410 AppendToList(aENewOrigins, aEOr);
7411 }
7412 else {
7413 TopTools_ListOfShape aENewOrigins;
7414 aENewOrigins.Append(aEOr);
7415 theOEOrigins.Bind(aENew, aENewOrigins);
7416 }
7417 }
7418 }
7419 }
7420 else {
7421 // add to images
7422 theOEImages.Bind(aEOld, aLENew);
7423 //
7424 theModifiedEdges.Add(aEOld);
7425 //
7426 // add to origins
7427 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7428 for (; aItNew.More(); aItNew.Next()) {
7429 const TopoDS_Shape& aENew = aItNew.Value();
7430 if (theOEOrigins.IsBound(aENew)) {
7431 TopTools_ListOfShape& aEOrigins = theOEOrigins.ChangeFind(aENew);
7432 AppendToList(aEOrigins, aEOld);
7433 }
7434 else {
7435 TopTools_ListOfShape aEOrigins;
7436 aEOrigins.Append(aEOld);
7437 theOEOrigins.Bind(aENew, aEOrigins);
7438 }
7439 }
7440 }
7441 //
7442 // update connection to initial shape
7443 if (theEdgesOrigins.IsBound(aEOld)) {
7444 const TopTools_ListOfShape& aLEOrInit = theEdgesOrigins.Find(aEOld);
7445 TopTools_ListIteratorOfListOfShape aItEOrInit(aLEOrInit);
7446 for (; aItEOrInit.More(); aItEOrInit.Next()) {
7447 const TopoDS_Shape& aEOrInit = aItEOrInit.Value();
7448 AppendToList(anInitOrigins, aEOrInit);
7449 }
7450 }
7451 }
7452 //
7453 if (anInitOrigins.Extent()) {
7454 TopTools_ListIteratorOfListOfShape aItNew(aLENew);
7455 for (; aItNew.More(); aItNew.Next()) {
7456 const TopoDS_Shape& aENew = aItNew.Value();
7457 if (theEdgesOrigins.IsBound(aENew)) {
7458 TopTools_ListOfShape& aLENewOr = theEdgesOrigins.ChangeFind(aENew);
7459 TopTools_ListIteratorOfListOfShape aItOrInit(anInitOrigins);
7460 for (; aItOrInit.More(); aItOrInit.Next()) {
7461 const TopoDS_Shape& aEOr = aItOrInit.Value();
7462 AppendToList(aLENewOr, aEOr);
7463 }
7464 }
7465 else {
7466 theEdgesOrigins.Bind(aENew, anInitOrigins);
7467 }
7468 }
7469 }
7470 }
7471}
7472
2ebb1098 7473//=======================================================================
7474//function : FillGaps
7475//purpose : Fill possible gaps (holes) in the splits of the offset faces
7476//=======================================================================
7477void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
7478{
7479 Standard_Integer aNbF = theFImages.Extent();
7480 if (!aNbF)
7481 return;
7482
7483 // Check the splits of offset faces on the free edges and fill the gaps (holes)
7484 // in created splits, otherwise the closed volume will not be possible to create.
7485
7486 // Map the splits of faces to find free edges
7487 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
7488 for (Standard_Integer i = 1; i <= aNbF; ++i)
7489 {
7490 TopTools_ListIteratorOfListOfShape itLF(theFImages(i));
7491 for (; itLF.More(); itLF.Next())
7492 TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
7493 }
7494
7495 // Analyze images of each offset face on the presence of free edges
7496 // and try to fill the holes
7497 for (Standard_Integer i = 1; i <= aNbF; ++i)
7498 {
7499 TopTools_ListOfShape& aLFImages = theFImages(i);
7500 if (aLFImages.IsEmpty())
7501 continue;
7502
7503 // Collect all edges from the splits
7504 TopoDS_Compound anEdges;
7505 BRep_Builder().MakeCompound(anEdges);
7506
7507 // Collect all free edges into a map with reverted orientation
7508 TopTools_MapOfOrientedShape aFreeEdgesMap;
7509 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7510 for (; itLF.More(); itLF.Next())
7511 {
7512 const TopoDS_Shape& aFIm = itLF.Value();
7513 TopExp_Explorer anExpE(aFIm, TopAbs_EDGE);
7514 for (; anExpE.More(); anExpE.Next())
7515 {
7516 const TopoDS_Shape& aE = anExpE.Current();
7517 if (aE.Orientation() != TopAbs_FORWARD &&
7518 aE.Orientation() != TopAbs_REVERSED)
7519 // Skip internals
7520 continue;
7521
7522 const TopTools_ListOfShape& aLF = anEFMap.FindFromKey(aE);
7523 if (aLF.Extent() == 1)
7524 aFreeEdgesMap.Add(aE.Reversed());
7525
7526 BRep_Builder().Add(anEdges, aE);
7527 }
7528 }
7529
7530 if (aFreeEdgesMap.IsEmpty())
7531 // No free edges
7532 continue;
7533
7534 // Free edges are found - fill the gaps by creating new splits
7535 // of the face using these free edges
7536 const TopoDS_Shape& aF = theFImages.FindKey(i);
7537
7538 // Build new splits using all kept edges and among new splits
7539 // find those containing free edges
7540 TopTools_ListOfShape aLFNew;
7541 TopTools_DataMapOfShapeShape aDummy;
7542
7543 BuildSplitsOfFace(TopoDS::Face(aF), anEdges, aDummy, aLFNew);
7544
7545 // Find faces filling holes
7546 itLF.Initialize(aLFNew);
7547 for (; itLF.More(); itLF.Next())
7548 {
7549 const TopoDS_Shape& aFNew = itLF.Value();
7550 TopExp_Explorer anExpE(aFNew, TopAbs_EDGE);
7551 for (; anExpE.More(); anExpE.Next())
7552 {
7553 const TopoDS_Shape& aE = anExpE.Current();
7554 if (aFreeEdgesMap.Contains(aE))
7555 {
7556 // Add face to splits
7557 aLFImages.Append(aFNew);
7558 break;
7559 }
7560 }
7561 }
7562 }
7563}
7564
ecf4f17c 7565//=======================================================================
7566//function : FillHistory
7567//purpose : Saving obtained results in history tools
7568//=======================================================================
7569void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
7570 const TopTools_DataMapOfShapeListOfShape& theEImages,
7571 BRepAlgo_Image& theImage)
7572{
2ebb1098 7573 Standard_Integer aNbF = theFImages.Extent();
7574 if (!aNbF)
ecf4f17c 7575 return;
2ebb1098 7576
7577#ifdef OFFSET_DEBUG
7578 // Build compound of faces to see preliminary result
7579 TopoDS_Compound aDFaces;
7580 BRep_Builder().MakeCompound(aDFaces);
7581#endif
7582
7583 // Map of kept edges
7584 TopTools_IndexedMapOfShape anEdgesMap;
7585
ecf4f17c 7586 // Fill history for faces
2ebb1098 7587 for (Standard_Integer i = 1; i <= aNbF; ++i)
7588 {
ecf4f17c 7589 const TopTools_ListOfShape& aLFImages = theFImages(i);
2ebb1098 7590 if (aLFImages.IsEmpty())
7591 continue;
7592
7593 // Add the splits to history map
7594 const TopoDS_Shape& aF = theFImages.FindKey(i);
7595 if (theImage.HasImage(aF))
7596 theImage.Add(aF, aLFImages);
7597 else
7598 theImage.Bind(aF, aLFImages);
7599
7600 // Collect edges from splits
7601 TopTools_ListIteratorOfListOfShape itLF(aLFImages);
7602 for (; itLF.More(); itLF.Next())
7603 {
7604 const TopoDS_Shape& aFIm = itLF.Value();
7605 TopExp::MapShapes(aFIm, TopAbs_EDGE, anEdgesMap);
7606
7607#ifdef OFFSET_DEBUG
7608 BRep_Builder().Add(aDFaces, aFIm);
7609#endif
ecf4f17c 7610 }
7611 }
2ebb1098 7612
7613 // Fill history for edges (iteration by the map is safe because the
7614 // order is not important here)
ecf4f17c 7615 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(theEImages);
2ebb1098 7616 for (; aItEIm.More(); aItEIm.Next())
7617 {
ecf4f17c 7618 const TopoDS_Shape& aE = aItEIm.Key();
7619 const TopTools_ListOfShape& aLEIm = aItEIm.Value();
2ebb1098 7620
ecf4f17c 7621 Standard_Boolean bHasImage = theImage.HasImage(aE);
7622 TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
2ebb1098 7623 for (; aItLE.More(); aItLE.Next())
7624 {
ecf4f17c 7625 const TopoDS_Shape& aEIm = aItLE.Value();
2ebb1098 7626 if (anEdgesMap.Contains(aEIm))
7627 {
7628 if (bHasImage)
7629 {
ecf4f17c 7630 theImage.Add(aE, aEIm);
7631 }
2ebb1098 7632 else
7633 {
ecf4f17c 7634 theImage.Bind(aE, aEIm);
7635 bHasImage = Standard_True;
7636 }
7637 }
7638 }
7639 }
7640}
7641
7642//=======================================================================
7643//function : ProcessMicroEdge
7644//purpose : Checking if the edge is micro edge
7645//=======================================================================
7646Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
7647 const Handle(IntTools_Context)& theCtx)
7648{
7649 TopoDS_Vertex aV1, aV2;
7650 TopExp::Vertices(theEdge, aV1, aV2);
7651 if (aV1.IsNull() || aV2.IsNull()) {
7652 return Standard_False;
7653 }
7654 //
7655 Standard_Boolean bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx);
7656 if (bMicro && BRepAdaptor_Curve(theEdge).GetType() == GeomAbs_Line) {
7657 Standard_Real aLen = BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
7658 BRep_Builder().UpdateVertex(aV1, aLen / 2.);
7659 BRep_Builder().UpdateVertex(aV2, aLen / 2.);
7660 }
7661 //
7662 return bMicro;
7663}
7664
7665//=======================================================================
7666//function : UpdateOrigins
7667//purpose : Updating origins
7668//=======================================================================
7669void UpdateOrigins(const TopTools_ListOfShape& theLA,
7670 TopTools_DataMapOfShapeListOfShape& theOrigins,
7671 BOPAlgo_Builder& theGF)
7672{
7673 TopTools_ListIteratorOfListOfShape aItA(theLA);
7674 for (; aItA.More(); aItA.Next()) {
7675 const TopoDS_Shape& aS = aItA.Value();
7676 //
7677 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7678 if (aLSIm.IsEmpty()) {
7679 continue;
7680 }
7681 //
7682 TopTools_ListOfShape aLSEmpt;
7683 TopTools_ListOfShape *pLS = theOrigins.ChangeSeek(aS);
7684 if (!pLS) {
7685 pLS = &aLSEmpt;
7686 pLS->Append(aS);
7687 }
7688 //
7689 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7690 for (; aIt.More(); aIt.Next()) {
7691 const TopoDS_Shape& aSIm = aIt.Value();
7692 //
7693 TopTools_ListOfShape *pLSOr = theOrigins.ChangeSeek(aSIm);
7694 if (!pLSOr) {
7695 // just bind the origins
7696 theOrigins.Bind(aSIm, *pLS);
7697 }
7698 else {
7699 // merge two lists
7700 TopTools_ListIteratorOfListOfShape aIt1(*pLS);
7701 for (; aIt1.More(); aIt1.Next()) {
7702 const TopoDS_Shape& aS1 = aIt1.Value();
7703 AppendToList(*pLSOr, aS1);
7704 }
7705 }
7706 }
7707 }
7708}
7709
7710//=======================================================================
7711//function : UpdateImages
7712//purpose : Updating images of the shapes
7713//=======================================================================
7714void UpdateImages(const TopTools_ListOfShape& theLA,
7715 TopTools_DataMapOfShapeListOfShape& theImages,
7716 BOPAlgo_Builder& theGF,
7717 TopTools_MapOfShape& theModified)
7718{
7719 TopTools_ListIteratorOfListOfShape aIt(theLA);
e08a9b03 7720 for (; aIt.More(); aIt.Next())
7721 {
ecf4f17c 7722 const TopoDS_Shape& aS = aIt.Value();
7723 //
7724 TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS);
e08a9b03 7725 if (!pLSIm)
7726 {
ecf4f17c 7727 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
e08a9b03 7728 if (aLSIm.Extent())
7729 {
ecf4f17c 7730 theImages.Bind(aS, aLSIm);
7731 theModified.Add(aS);
7732 }
7733 continue;
7734 }
7735 //
7736 TopTools_MapOfShape aMFence;
7737 TopTools_ListOfShape aLSImNew;
7738 //
7739 Standard_Boolean bModified = Standard_False;
7740 //
7741 // check modifications of the images
7742 TopTools_ListIteratorOfListOfShape aIt1(*pLSIm);
e08a9b03 7743 for (; aIt1.More(); aIt1.Next())
7744 {
ecf4f17c 7745 const TopoDS_Shape& aSIm = aIt1.Value();
e08a9b03 7746 bModified |= TakeModified(aSIm, theGF.Images(), aLSImNew, &aMFence);
ecf4f17c 7747 }
7748 //
e08a9b03 7749 if (bModified)
7750 {
ecf4f17c 7751 *pLSIm = aLSImNew;
7752 theModified.Add(aS);
7753 }
7754 }
7755}
7756
7757//=======================================================================
7758//function : UpdateIntersectedEdges
7759//purpose : Saving connection from trimmed edges to not trimmed ones
7760//=======================================================================
7761void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
7762 TopTools_DataMapOfShapeShape& theETrimEInf,
7763 BOPAlgo_Builder& theGF)
7764{
7765 TopTools_ListIteratorOfListOfShape aItA(theLA);
7766 for (; aItA.More(); aItA.Next()) {
7767 const TopoDS_Shape& aS = aItA.Value();
7768 //
7769 const TopoDS_Shape* pEInf = theETrimEInf.Seek(aS);
7770 if (!pEInf) {
7771 continue;
7772 }
7773 //
7774 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7775 if (aLSIm.IsEmpty()) {
7776 continue;
7777 }
7778 //
7779 TopTools_ListIteratorOfListOfShape aIt(aLSIm);
7780 for (; aIt.More(); aIt.Next()) {
7781 const TopoDS_Shape& aEIm = aIt.Value();
7782 if (!theETrimEInf.IsBound(aEIm)) {
7783 theETrimEInf.Bind(aEIm, *pEInf);
7784 }
7785 }
7786 }
7787}
7788
7789//=======================================================================
7790//function : FindCommonParts
7791//purpose : Looking for the parts of type <theType> contained in both lists
7792//=======================================================================
7793void FindCommonParts(const TopTools_ListOfShape& theLS1,
7794 const TopTools_ListOfShape& theLS2,
7795 TopTools_ListOfShape& theLSC,
7796 const TopAbs_ShapeEnum theType)
7797{
7798 // map shapes in the first list
7799 TopTools_IndexedMapOfShape aMS1;
7800 TopTools_ListIteratorOfListOfShape aIt(theLS1);
7801 for (; aIt.More(); aIt.Next()) {
7802 const TopoDS_Shape& aS = aIt.Value();
7803 TopExp::MapShapes(aS, theType, aMS1);
7804 }
7805 //
7806 if (aMS1.IsEmpty()) {
7807 return;
7808 }
7809 //
7810 TopTools_MapOfShape aMFence;
7811 // check for such shapes in the other list
7812 aIt.Initialize(theLS2);
7813 for (; aIt.More(); aIt.Next()) {
7814 const TopoDS_Shape& aS = aIt.Value();
7815 //
7816 TopExp_Explorer aExp(aS, theType);
7817 for(; aExp.More(); aExp.Next()) {
7818 const TopoDS_Shape& aST = aExp.Current();
7819 //
7820 if (aMS1.Contains(aST) && aMFence.Add(aST)) {
7821 theLSC.Append(aST);
7822 }
7823 }
7824 }
7825}
7826
7827//=======================================================================
7828//function : NbPoints
7829//purpose : Defines number of sample points to get average direction of the edge
7830//=======================================================================
7831Standard_Integer NbPoints(const TopoDS_Edge& theEdge)
7832{
7833 Standard_Integer aNbP;
7834 BRepAdaptor_Curve aBAC(theEdge);
7835 switch (aBAC.GetType()) {
7836 case GeomAbs_Line:
7837 aNbP = 1;
7838 break;
7839 default:
7840 aNbP = 11;
7841 }
7842 //
7843 return aNbP;
7844}
7845
7846//=======================================================================
7847//function : FindShape
7848//purpose : Looking for the same sub-shape in the shape
7849//=======================================================================
7850Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
7851 const TopoDS_Shape& theSWhere,
420b38fd 7852 const BRepOffset_Analyse* theAnalyse,
ecf4f17c 7853 TopoDS_Shape& theRes)
7854{
7855 Standard_Boolean bFound = Standard_False;
7856 TopAbs_ShapeEnum aType = theSWhat.ShapeType();
7857 TopExp_Explorer aExp(theSWhere, aType);
7858 for (; aExp.More(); aExp.Next()) {
7859 const TopoDS_Shape& aS = aExp.Current();
7860 if (aS.IsSame(theSWhat)) {
7861 theRes = aS;
7862 bFound = Standard_True;
7863 break;
7864 }
7865 }
420b38fd 7866
7867 if (!bFound && theAnalyse)
7868 {
7869 const TopTools_ListOfShape *pLD = theAnalyse->Descendants (theSWhere);
7870 if (pLD)
7871 {
7872 for (TopTools_ListOfShape::Iterator it (*pLD); it.More(); it.Next())
7873 {
7874 const TopoDS_Shape& aS = it.Value();
7875 if (aS.IsSame (theSWhat))
7876 {
7877 theRes = aS;
7878 bFound = Standard_True;
7879 break;
7880 }
7881 }
7882 }
7883 }
7884
ecf4f17c 7885 return bFound;
7886}
7887
7888
7889//=======================================================================
7890//function : AppendToList
7891//purpose : Add to a list only unique elements
7892//=======================================================================
7893void AppendToList(TopTools_ListOfShape& theList,
7894 const TopoDS_Shape& theShape)
7895{
7896 TopTools_ListIteratorOfListOfShape aIt(theList);
7897 for (; aIt.More(); aIt.Next()) {
7898 const TopoDS_Shape& aS = aIt.Value();
7899 if (aS.IsSame(theShape)) {
7900 return;
7901 }
7902 }
7903 theList.Append(theShape);
7904}
e08a9b03 7905
7906//=======================================================================
7907//function : AddToContainer
7908//purpose : Set of methods to add a shape into container
7909//=======================================================================
7910static void AddToContainer(const TopoDS_Shape& theS,
7911 TopTools_ListOfShape& theList)
7912{
7913 theList.Append(theS);
7914}
7915static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7916 TopTools_MapOfShape& theMap)
7917{
7918 return theMap.Add(theS);
7919}
7920static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7921 TopTools_IndexedMapOfShape& theMap)
7922{
7923 const Standard_Integer aNb = theMap.Extent();
7924 const Standard_Integer anInd = theMap.Add(theS);
7925 return anInd > aNb;
7926}
7927static void AddToContainer(const TopoDS_Shape& theS,
7928 TopoDS_Shape& theSOut)
7929{
7930 BRep_Builder().Add(theSOut, theS);
7931}
7932
7933//=======================================================================
7934//function : TakeModified
7935//purpose : Check if the shape has images in the given images map.
7936// Puts in the output map either the images or the shape itself.
7937//=======================================================================
7938template <class ContainerType, class FenceMapType>
7939Standard_Boolean TakeModified(const TopoDS_Shape& theS,
7940 const TopTools_DataMapOfShapeListOfShape& theImages,
7941 ContainerType& theContainer,
7942 FenceMapType* theMFence)
7943{
7944 const TopTools_ListOfShape *pLSIm = theImages.Seek(theS);
7945 if (pLSIm)
7946 {
7947 TopTools_ListIteratorOfListOfShape itLSIm(*pLSIm);
7948 for (; itLSIm.More(); itLSIm.Next())
7949 {
7950 const TopoDS_Shape& aSIm = itLSIm.Value();
7951 if (!theMFence || AddToContainer(aSIm, *theMFence))
7952 AddToContainer(aSIm, theContainer);
7953 }
7954 return Standard_True;
7955 }
7956 else
7957 {
7958 if (!theMFence || AddToContainer(theS, *theMFence))
7959 AddToContainer(theS, theContainer);
7960 return Standard_False;
7961 }
7962}