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