0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / BRepOffset / BRepOffset_MakeOffset_1.cxx
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
33 #include <BRepLib.hxx>
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>
53 #include <BOPAlgo_BuilderFace.hxx>
54
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_DataMapOfShapeShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <TopTools_MapOfOrientedShape.hxx>
59
60 #include <BOPTools_AlgoTools3D.hxx>
61 #include <BOPTools_AlgoTools.hxx>
62 #include <BOPTools_AlgoTools2D.hxx>
63 #include <BOPTools_Set.hxx>
64
65 #include <IntTools_Context.hxx>
66 #include <IntTools_ShrunkRange.hxx>
67
68 #ifdef OFFSET_DEBUG
69 #include <BRepAlgoAPI_Check.hxx>
70 #endif
71
72 typedef NCollection_DataMap
73   <TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeMapOfShape;
74 typedef NCollection_DataMap
75   <TopoDS_Shape, TopTools_IndexedMapOfShape, TopTools_ShapeMapHasher> BRepOffset_DataMapOfShapeIndexedMapOfShape;
76
77 static
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
87 static
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
98 static
99   void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
100                                 const TopoDS_Shape& theEdges,
101                                 TopTools_ListOfShape& theLFImages);
102
103 static
104   void BuildSplitsOfFace(const TopoDS_Face& theFace,
105                          const TopoDS_Shape& theEdges,
106                          TopTools_DataMapOfShapeShape& theOrigins,
107                          TopTools_ListOfShape& theLFImages);
108
109 static
110   void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
111                           const TopTools_MapOfShape& theModifiedEdges,
112                           const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
113                           const BRepOffset_Analyse* theAnalyse,
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,
127                           TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
128                           TopoDS_Shape& theSolids,
129                           TopTools_DataMapOfShapeListOfShape& theSSInterfs);
130
131 static 
132   void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, 
133                              const TopTools_MapOfShape& theModifiedEdges,
134                              const BRepOffset_Analyse* theAnalyse,
135                              TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
136                              TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
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
149 static 
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
158 static
159   void FindInvalidEdges(const TopoDS_Face& theF,
160                         const TopTools_ListOfShape& theLFImages,
161                         const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
162                         const TopTools_DataMapOfShapeShape& theFacesOrigins,
163                         const BRepOffset_Analyse* theAnalyse,
164                         const TopTools_DataMapOfShapeListOfShape& theOEImages,
165                         const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
166                         TopTools_IndexedMapOfShape& theInvEdges,
167                         TopTools_IndexedMapOfShape& theValidEdges,
168                         BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
169                         BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
170                         BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
171                         BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
172                         TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
173                         TopTools_MapOfShape& theMEInverted,
174                         TopTools_MapOfShape& theEdgesInvalidByVertex,
175                         TopTools_MapOfShape& theEdgesValidByVertex);
176
177 static
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
188 static
189   void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
190                         const TopTools_IndexedMapOfShape& theInvEdges,
191                         const TopTools_IndexedMapOfShape& theValidEdges,
192                         const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
193                         const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
194                         const TopTools_MapOfShape& theLENeutral,
195                         const TopTools_MapOfShape& theMEInverted,
196                         const TopTools_MapOfShape& theEdgesInvalidByVertex,
197                         const TopTools_MapOfShape& theEdgesValidByVertex,
198                         const TopTools_MapOfShape& theMFHoles,
199                         TopTools_IndexedMapOfShape& theMFInvInHole,
200                         TopTools_ListOfShape& theInvFaces,
201                         TopTools_ListOfShape& theInvertedFaces);
202
203 static
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,
209                                 const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
210                                 TopTools_MapOfShape& theMFHoles,
211                                 TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
212                                 Handle(IntTools_Context)& theContext);
213
214 static
215   gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
216                            const Standard_Integer theNbP);
217
218 static
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,
224                                  const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
225                                  const TopTools_IndexedMapOfShape& theMEdges,
226                                  TopTools_MapOfShape& theMEInverted);
227
228 static
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
236 static
237   void GetVerticesOnEdges(const TopoDS_Shape& theCB,
238                           const TopTools_MapOfShape& theEdges,
239                           TopTools_MapOfShape& theVerticesOnEdges,
240                           TopTools_MapOfShape& theAllVertices);
241
242 static
243   void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
244                                           const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
245                                           TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
246                                           TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
247                                           TopTools_IndexedMapOfShape& theMERemoved);
248
249 static
250   void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
251                                     const TopTools_DataMapOfShapeShape& theArtInvFaces,
252                                     const TopTools_MapOfShape& theMEInverted,
253                                     const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
254                                     TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
255
256 static
257   void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
258                          TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
259                          const TopTools_DataMapOfShapeShape& theArtInvFaces,
260                          const TopTools_IndexedMapOfShape& theInvEdges,
261                          const TopTools_MapOfShape& theInvertedEdges,
262                          const TopTools_ListOfShape& theInvertedFaces,
263                          const TopTools_IndexedMapOfShape& theMFToCheckInt,
264                          const TopTools_IndexedMapOfShape& theMFInvInHole,
265                          const TopoDS_Shape& theFHoles,
266                          TopTools_DataMapOfShapeListOfShape& theSSInterfs,
267                          TopTools_IndexedMapOfShape& theMERemoved,
268                          TopTools_IndexedMapOfShape& theMEInside,
269                          TopoDS_Shape& theSolids);
270
271 static
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
278 static
279   void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
280                           const TopTools_DataMapOfShapeShape& theDMFImF,
281                           const TopTools_IndexedMapOfShape& theMFInv,
282                           const TopTools_IndexedMapOfShape& theInvEdges,
283                           const TopTools_MapOfShape& theInvertedEdges,
284                           TopTools_MapOfShape& theMFToRem);
285
286 static
287   void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
288                          TopTools_IndexedDataMapOfShapeListOfShape& theImages,
289                          BOPAlgo_Builder& theGF,
290                          TopTools_IndexedMapOfShape& theMERemoved);
291
292 static
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
300 static
301   void FilterEdgesImages(const TopoDS_Shape& theS,
302                          TopTools_DataMapOfShapeListOfShape& theOEImages,
303                          TopTools_DataMapOfShapeListOfShape& theOEOrigins);
304
305 static
306   void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
307                           const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
308                           const TopTools_IndexedMapOfShape& theInvEdges,
309                           const TopTools_IndexedMapOfShape& theMERemoved,
310                           TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
311                           TopTools_DataMapOfShapeShape& theArtInvFaces);
312
313 static
314   void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
315                           const TopTools_DataMapOfShapeShape& theArtInvFaces,
316                           const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
317                           const TopTools_IndexedMapOfShape& theMERemoved,
318                           TopTools_IndexedMapOfShape& theInvEdges);
319
320 static
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
327 static 
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
335 static
336   void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
337                     const TopTools_MapOfShape& theFSelfRebAvoid,
338                     const TopoDS_Shape& theSolids,
339                     const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
340                     const BRepOffset_Analyse* theAnalyse,
341                     TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
342                     TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
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
359 static
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
379 static
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
393 static
394   void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
395                            const TopTools_IndexedMapOfShape& theInvEdges,
396                            const TopTools_IndexedMapOfShape& theValidEdges,
397                            const TopTools_MapOfShape& theInvertedEdges,
398                            const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
399                            const TopTools_DataMapOfShapeListOfShape& theOEImages,
400                            const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
401                            TopTools_MapOfShape& theMVRInv);
402
403 static
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
417 static
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,
425                           const TopTools_MapOfShape& theAllInvs,
426                           const Standard_Boolean theForceUse,
427                           TopTools_IndexedMapOfShape& theMECV,
428                           TopTools_MapOfShape& theMECheckExt,
429                           TopTools_DataMapOfShapeListOfShape& theDMEETrim,
430                           TopTools_ListOfShape& theLFEi,
431                           TopTools_ListOfShape& theLFEj,
432                           TopTools_IndexedMapOfShape& theMEToInt);
433
434 static
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
446 static
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
459 static 
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
466 static
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,
475                              const TopTools_MapOfShape& theMECheckExt,
476                              TopTools_MapOfShape& theMVBounds,
477                              TopTools_DataMapOfShapeListOfShape& theEImages);
478
479 static
480   void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
481                        const TopTools_MapOfShape& theMVBounds,
482                        BOPAlgo_Builder& theGF,
483                        TopTools_MapOfShape& theMEInv);
484
485 static
486   void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
487                         const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
488                         const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
489                         const TopTools_MapOfShape& theMVBounds,
490                         const TopoDS_Shape& theSolids,
491                         const TopTools_IndexedMapOfShape& theInvEdges,
492                         const TopTools_MapOfShape& theInvertedEdges,
493                         const TopTools_MapOfShape& theMEInvOnArt,
494                         TopTools_MapOfShape& theMECheckExt,
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
506 static
507   void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
508                                 const TopTools_DataMapOfShapeListOfShape& theEETrim,
509                                 const TopTools_MapOfShape& theMVBounds,
510                                 TopTools_MapOfShape& theMECheckExt,
511                                 TopTools_DataMapOfShapeListOfShape& theEImages,
512                                 TopTools_MapOfShape& theMEB,
513                                 TopTools_MapOfShape& theMVOld,
514                                 TopTools_MapOfShape& theMENew,
515                                 TopTools_DataMapOfShapeListOfShape& theDMEOr,
516                                 TopTools_DataMapOfShapeListOfShape& theMELF);
517
518 static
519   void IntersectEdges(const TopTools_ListOfShape& theLA,
520                       const TopTools_ListOfShape& theLE,
521                       const TopTools_MapOfShape& theMVBounds,
522                       const TopTools_MapOfShape& theVertsToAvoid,
523                       TopTools_MapOfShape& theMENew,
524                       TopTools_MapOfShape& theMECheckExt,
525                       TopTools_DataMapOfShapeListOfShape& theEImages,
526                       TopTools_MapOfShape& theModifiedEdges,
527                       TopTools_DataMapOfShapeListOfShape& theDMEOr,
528                       TopTools_DataMapOfShapeListOfShape& theMELF,
529                       TopoDS_Shape& theSplits);
530
531 static
532   void GetBounds(const TopTools_ListOfShape& theLFaces,
533                  const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
534                  const TopTools_MapOfShape& theMEB,
535                  TopoDS_Shape& theBounds);
536
537 static
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
547 static
548   void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
549                                const TopoDS_Shape& theBounds,
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,
556                                const TopTools_DataMapOfShapeListOfShape& theMELF,
557                                const TopTools_DataMapOfShapeListOfShape& theEImages,
558                                const TopTools_MapOfShape& theMECheckExt,
559                                const TopTools_MapOfShape& theMEInvOnArt,
560                                Handle(IntTools_Context)& theCtx,
561                                TopTools_MapOfShape& theVertsToAvoid,
562                                TopTools_MapOfShape& theMEInv);
563
564 static
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
571 static
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
585 static
586   void FillGaps(TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
587
588 static
589   void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
590                    const TopTools_DataMapOfShapeListOfShape& theEImages,
591                    BRepAlgo_Image& theImage);
592
593 static
594   void UpdateOrigins(const TopTools_ListOfShape& theLA,
595                      TopTools_DataMapOfShapeListOfShape& theOrigins,
596                      BOPAlgo_Builder& theGF);
597
598 static
599   void UpdateImages(const TopTools_ListOfShape& theLA,
600                     TopTools_DataMapOfShapeListOfShape& theImages,
601                     BOPAlgo_Builder& theGF,
602                     TopTools_MapOfShape& theModified);
603
604 static
605   void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
606                               TopTools_DataMapOfShapeShape& theETrimEInf,
607                               BOPAlgo_Builder& theGF);
608
609 static
610   Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
611                                     const Handle(IntTools_Context)& theCtx);
612
613 static
614   void FindCommonParts(const TopTools_ListOfShape& theLS1,
615                        const TopTools_ListOfShape& theLS2,
616                        TopTools_ListOfShape& theLSC,
617                        const TopAbs_ShapeEnum theType = TopAbs_EDGE);
618
619 static
620   Standard_Integer NbPoints(const TopoDS_Edge& theE);
621
622 static
623   Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
624                              const TopoDS_Shape& theSWhere,
625                              const BRepOffset_Analyse* theAnalyse,
626                              TopoDS_Shape& theRes);
627
628 static
629   void AppendToList(TopTools_ListOfShape& theL,
630                     const TopoDS_Shape& theS);
631
632 template <class ContainerType, class FenceMapType>
633 static Standard_Boolean TakeModified(const TopoDS_Shape& theS,
634                                      const TopTools_DataMapOfShapeListOfShape& theImages,
635                                      ContainerType& theMapOut,
636                                      FenceMapType* theMFence);
637
638 template <class ContainerType>
639 static 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
647 //=======================================================================
648 //function : BuildSplitsOfTrimmedFaces
649 //purpose  : Building splits of already trimmed faces
650 //=======================================================================
651 void 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     //
685     BuildSplitsOfTrimmedFace(aF, aCE, aLFImages);
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 //=======================================================================
698 void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
699                                                        const BRepOffset_Analyse& theAnalyse,
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;
732   // images of the hole faces of the original faces
733   TopTools_DataMapOfShapeListOfShape aDMFNewHoles;
734   // solid build from the new splits
735   TopoDS_Shape aSolids;
736   // now we can split the faces
737   BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, &theAnalyse, theAsDes, theFacesOrigins,
738                      anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges,
739                      anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages,
740                      aDMFNewHoles, aSolids, aSSInterfs);
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;
751       RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, &theAnalyse, aFImages, aDMFNewHoles,
752                    theEdgesOrigins, theFacesOrigins, anOEImages, anOEOrigins, aLastInvEdges,
753                    anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges, anAlreadyInvFaces,
754                    anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes);
755     }
756   }
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
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 //=======================================================================
770 void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, 
771                            const TopTools_MapOfShape& theModifiedEdges,
772                            const BRepOffset_Analyse* theAnalyse,
773                            TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
774                            TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
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   //
812   BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAnalyse, theAsDes, theFacesOrigins, 
813                      theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges, 
814                      anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages,
815                      theDMFNewHoles, aSolids, aSSInterfs);
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()) {
823       RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, theAnalyse, theFImages, theDMFNewHoles,
824                    theEdgesOrigins, theFacesOrigins, theOEImages, theOEOrigins, theLastInvEdges,
825                    theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges, theAlreadyInvFaces,
826                    anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes);
827     }
828   }
829 }
830
831 //=======================================================================
832 //function : BuildSplitsOfFaces
833 //purpose  : Building the splits of offset faces and
834 //           looking for the invalid splits
835 //=======================================================================
836 void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
837                         const TopTools_MapOfShape& theModifiedEdges,
838                         const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
839                         const BRepOffset_Analyse* theAnalyse,
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,
853                         TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
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;
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;
872   // map of valid inverted edges for the face
873   BRepOffset_DataMapOfShapeMapOfShape aDMFMVIE;
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;
878   // map of edges created from vertex and marked as valid
879   TopTools_MapOfShape aMEdgeValidByVertex;
880   // connection map from old edges to new ones
881   TopTools_DataMapOfShapeListOfShape aDMEOrLEIm;
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     //
903 #ifdef OFFSET_DEBUG
904     // check the found edges on self-intersection
905     BRepAlgoAPI_Check aChecker(aCE);
906     if (!aChecker.IsValid())
907     {
908       std::cout << "Offset_i_c Error: set of edges to build faces is self-intersecting\n";
909     }
910 #endif
911     // build splits
912     TopTools_ListOfShape aLFImages;
913     BuildSplitsOfFace(aF, aCE, theFacesOrigins, aLFImages);
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;
930       BuildSplitsOfFace(aF, aCE1, theFacesOrigins, aLFImages1);
931       //
932       // check if the rebuilding has added some new faces to the splits
933       for (TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1); aItLFIm.More();)
934       {
935         Standard_Boolean bAllInv = Standard_True;
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();
940           if (!aMapEInv.Contains(aE)) {
941             bAllInv = Standard_False;
942             if (!aMENInv.Contains(aE)) {
943               break;
944             }
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) {
969         TopTools_IndexedMapOfShape aMEInv;
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);
982               aMEInv.Add (aE);
983             }
984             else {
985               theValidEdges.Add(aE);
986             }
987           }
988         }
989         //
990         aDMFMIE.Bind(aF, aMEInv);
991         aLFDone.Append(aF);
992         //
993         continue;
994       }
995     }
996     //
997     // find invalid edges
998     FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theAnalyse, theOEImages,
999                      theOEOrigins, theInvEdges, theValidEdges, aDMFMVE, aDMFMNE, aDMFMIE,
1000                      aDMFMVIE, aDMEOrLEIm, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex);
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   //
1014   if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty() && aDMFMIE.IsEmpty()) {
1015     return;
1016   }
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
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   }
1032   // show valid edges
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   }
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   }
1047 #endif
1048
1049 #ifdef OFFSET_DEBUG
1050   // Show all obtained splits of faces
1051   TopoDS_Compound aCFIm1;
1052   BRep_Builder().MakeCompound(aCFIm1);
1053 #endif
1054
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())
1064     {
1065       TopExp::MapShapesAndAncestors(itLFIm.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
1066 #ifdef OFFSET_DEBUG
1067       BRep_Builder().Add(aCFIm1, itLFIm.Value());
1068 #endif
1069     }
1070   }
1071
1072   TopTools_MapOfShape anEmptyMap;
1073   // invalid faces inside the holes
1074   TopTools_IndexedMapOfShape aMFInvInHole;
1075   // all hole faces
1076   TopoDS_Compound aFHoles;
1077   aBB.MakeCompound(aFHoles);
1078   // Find the faces containing only the inverted edges and the invalid ones
1079   TopTools_ListOfShape anInvertedFaces;
1080   // find invalid faces
1081   // considering faces containing only invalid edges as invalid
1082   aItLF.Initialize(aLFDone);
1083   for (; aItLF.More(); aItLF.Next()) {
1084     const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
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     }
1092     else
1093     {
1094       // neutral edges
1095       const TopTools_MapOfShape* pMNE = aDMFMNE.ChangeSeek(aF);
1096       if (!pMNE) {
1097         pMNE = &anEmptyMap;
1098       }
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,
1103                                aDMEOrLEIm, anEFMap, aMFHoles, theDMFNewHoles, aCtx);
1104       //
1105       TopTools_MapIteratorOfMapOfShape aItMH(aMFHoles);
1106       for (; aItMH.More(); aItMH.Next()) {
1107         aBB.Add(aFHoles, aItMH.Value());
1108       }
1109       //
1110       // find invalid faces
1111       FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFMVE, aDMFMIE,
1112                        *pMNE, theInvertedEdges, aMEdgeInvalidByVertex, aMEdgeValidByVertex,
1113                        aMFHoles, aMFInvInHole, aLFInv, anInvertedFaces);
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
1152   RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theOEOrigins,
1153                                      theInvFaces, theFImages, aMERemoved);
1154   if (theInvFaces.IsEmpty()) {
1155     theInvEdges.Clear();
1156     return;
1157   }
1158   //
1159   // remove invalid splits from valid splits
1160   RemoveInvalidSplitsFromValid (theInvFaces, theArtInvFaces, theInvertedEdges,
1161                                 aDMFMVIE, theFImages);
1162   //
1163   // remove inside faces
1164   TopTools_IndexedMapOfShape aMEInside;
1165   RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, theInvEdges, theInvertedEdges,
1166                     anInvertedFaces, aMFToCheckInt, aMFInvInHole, aFHoles, theSSInterfs,
1167                     aMERemoved, aMEInside, theSolids);
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   //
1183   TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
1184   TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMEF);
1185   //
1186   // filter maps of images and origins
1187   FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
1188   //
1189   // filter invalid faces
1190   FilterInvalidFaces(theFImages, aDMEF, theInvEdges, aMEInside, theInvFaces, theArtInvFaces);
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
1213   FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFMIE, aMERemoved, theInvEdges);
1214   //
1215   // Check additionally validity of edges originated from vertices.
1216   CheckEdgesCreatedByVertex (theInvFaces, theArtInvFaces, theEdgesOrigins,
1217                              theValidEdges, theEdgesToAvoid);
1218
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 //=======================================================================
1254 void 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
1268   TopTools_ListOfShape aLS;
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();
1298   if (aGFE.HasErrors()) {
1299     return;
1300   }
1301   //
1302   TopTools_ListOfShape aLA;
1303   // fill map with edges images
1304   TopTools_ListIteratorOfListOfShape aIt(aLS);
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 //=======================================================================
1335 Standard_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);
1368   // Fence map
1369   TopTools_MapOfShape aMEFence;
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         //
1386         if (!aMEFence.Add(aEIm))
1387           continue;
1388
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 //=======================================================================
1438 void BuildSplitsOfFace(const TopoDS_Face& theFace,
1439                        const TopoDS_Shape& theEdges,
1440                        TopTools_DataMapOfShapeShape& theFacesOrigins,
1441                        TopTools_ListOfShape& theLFImages)
1442 {
1443   theLFImages.Clear();
1444   //
1445   // take edges to split the face
1446   TopTools_ListOfShape aLE;
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
1461   BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
1462   //
1463   // build splits of faces
1464   BOPAlgo_BuilderFace aBF;
1465   aBF.SetFace(aFF);
1466   aBF.SetShapes(aLE);
1467   aBF.Perform();
1468   //
1469   const TopTools_ListOfShape& aLFSp = aBF.Areas();
1470   TopTools_ListIteratorOfListOfShape aItLF(aLFSp);
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 //=======================================================================
1484 void BuildSplitsOfTrimmedFace(const TopoDS_Face& theFace,
1485                               const TopoDS_Shape& theEdges,
1486                               TopTools_ListOfShape& theLFImages)
1487 {
1488   BOPAlgo_Builder aGF;
1489   //
1490   aGF.AddArgument(theFace);
1491   aGF.AddArgument(theEdges);
1492   aGF.Perform();
1493   if (aGF.HasErrors()) {
1494     return;
1495   }
1496   //
1497   // splits of the offset shape
1498   theLFImages = aGF.Modified(theFace);
1499 }
1500
1501 //=======================================================================
1502 //function : CheckIfArtificial
1503 //purpose  : Checks if the face is artificially invalid
1504 //=======================================================================
1505 Standard_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();
1531       const TopTools_ListOfShape* pLENInv = aMVE.Seek(aVEInv);
1532       if (pLENInv) {
1533         TopTools_ListIteratorOfListOfShape aItLEInv(*pLENInv);
1534         for (; aItLEInv.More(); aItLEInv.Next()) {
1535           const TopoDS_Shape& aENInv = aItLEInv.Value();
1536           if (!aMEUsed.Contains(aENInv)) {
1537             theMENInv.Add(aENInv);
1538           }
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 //=======================================================================
1590 void FindInvalidEdges(const TopoDS_Face& theF,
1591                       const TopTools_ListOfShape& theLFImages,
1592                       const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
1593                       const TopTools_DataMapOfShapeShape& theFacesOrigins,
1594                       const BRepOffset_Analyse* theAnalyse,
1595                       const TopTools_DataMapOfShapeListOfShape& theOEImages,
1596                       const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
1597                       TopTools_IndexedMapOfShape& theInvEdges,
1598                       TopTools_IndexedMapOfShape& theValidEdges,
1599                       BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
1600                       BRepOffset_DataMapOfShapeMapOfShape& theDMFMNE,
1601                       BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
1602                       BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
1603                       TopTools_DataMapOfShapeListOfShape& theDMEOrLEIm,
1604                       TopTools_MapOfShape& theMEInverted,
1605                       TopTools_MapOfShape& theEdgesInvalidByVertex,
1606                       TopTools_MapOfShape& theEdgesValidByVertex)
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
1615
1616   // original face
1617   const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
1618   // invalid edges
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;
1628   // back map from the original shapes to their offset images
1629   TopTools_DataMapOfShapeListOfShape anImages;
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       }
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       }
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
1687     TopTools_MapOfShape aMVE;
1688     // invalid edges for this split
1689     TopTools_IndexedMapOfShape aMIE;
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       }
1716       if (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1)
1717         continue;
1718       //
1719       TopTools_MapOfShape aME, aMV, aMF;
1720       Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
1721       Standard_Integer aNbP = NbPoints(aEIm), aNbInv = 0;
1722       Standard_Boolean bUseVertex = !aNbVOr ? Standard_False :
1723         (aNbVOr == 1 &&
1724          aDMEF.FindFromKey(aEIm).Extent() == 1 &&
1725          !theOEOrigins.IsBound(aEIm));
1726       //
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
1735           if (!bUseVertex) {
1736             continue;
1737           }
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);
1748             // Avoid classification of edges originated from vertices
1749             // located between tangent edges
1750             Standard_Boolean bAllTgt = Standard_True;
1751             TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
1752             gp_Vec aVRef = GetAverageTangent (aItLEFOr.Value(), aNbP);
1753             for (; aItLEFOr.More(); aItLEFOr.Next())
1754             {
1755               const TopoDS_Shape& aEOr = aItLEFOr.Value();
1756               BRep_Builder().Add(aCEOr, aEOr);
1757
1758               gp_Vec aVCur = GetAverageTangent (aEOr, aNbP);
1759               if (!aVRef.IsParallel (aVCur, Precision::Angular()))
1760                 bAllTgt = Standard_False;
1761             }
1762             if (!bAllTgt)
1763               aEOrF = aCEOr;
1764           }
1765         }
1766         else {
1767           FindShape(aSOr, aFOr, theAnalyse, aEOrF);
1768           //
1769           TopTools_ListOfShape *pLEIm = theDMEOrLEIm.ChangeSeek(aSOr);
1770           if (!pLEIm) {
1771             pLEIm = theDMEOrLEIm.Bound(aSOr, TopTools_ListOfShape());
1772           }
1773           AppendToList(*pLEIm, aEIm);
1774         }
1775         //
1776         if (aEOrF.IsNull()) {
1777           // the edge has not been found
1778           continue;
1779         }
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);
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           }
1840           if (theAnalyse)
1841           {
1842             for (TopTools_ListOfShape::Iterator itFA (theAnalyse->Ancestors (aEOrF));
1843                  itFA.More(); itFA.Next())
1844               aMF.Add (itFA.Value());
1845           }
1846           //
1847           if (aCos < Precision::Confusion()) {
1848             bInvalid = Standard_True;
1849             aNbInv++;
1850           }
1851         }
1852         bChecked = Standard_True;
1853       }
1854       //
1855       if (!bChecked) {
1856         continue;
1857       }
1858       //
1859       Standard_Boolean bLocalOnly = (aNbVOr > 1 && (aLEOr.Extent() - aNbVOr) > 1);
1860       Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
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;
1890       }
1891       //
1892       if (bInvalid) {
1893         if (!bLocalOnly)
1894           theInvEdges.Add(aEIm);
1895         aMIE.Add (aEIm);
1896         aMEInv.Add(aEIm);
1897         continue;
1898       }
1899       //
1900       // check if the edge has been inverted
1901       Standard_Boolean bInverted = !aNbE || bLocalOnly ? Standard_False :
1902         CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
1903           theEdgesOrigins, aDMVE, aMEdges, theMEInverted);
1904       //
1905       if (!bInverted || !aNbVOr) {
1906         if (!bLocalOnly)
1907           theValidEdges.Add(aEIm);
1908         aMVE.Add (aEIm);
1909         aMEVal.Add(aEIm);
1910       }
1911     }
1912     //
1913     // valid edges
1914     if (aMVE.Extent())
1915     {
1916       theDMFMVE.Bind (aFIm, aMVE);
1917     }
1918     //
1919     // invalid edges
1920     if (aMIE.Extent())
1921     {
1922       theDMFMIE.Bind (aFIm, aMIE);
1923     }
1924   }
1925   //
1926   // process invalid edges:
1927   // check for the inverted edges
1928   TopTools_MapOfShape aMVIE;
1929   // fill neutral edges
1930   TopTools_MapOfShape aMNE;
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
1938     if (aMEVal.Contains(aEIm))
1939     {
1940       aMNE.Add (aEIm);
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);
1966           aMVIE.Add (aEIm1);
1967         }
1968       }
1969     }
1970   }
1971   //
1972   if (aMNE.Extent())
1973   {
1974     theDMFMNE.Bind (theF, aMNE);
1975   }
1976   //
1977   if (aMVIE.Extent())
1978   {
1979     theDMFMVIE.Bind (theF, aMVIE);
1980   }
1981 }
1982
1983 namespace 
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 //=======================================================================
2007 void 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
2173 //=======================================================================
2174 //function : FindInvalidFaces
2175 //purpose  : Looking for the invalid faces by analyzing their invalid edges
2176 //=======================================================================
2177 void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
2178                       const TopTools_IndexedMapOfShape& theInvEdges,
2179                       const TopTools_IndexedMapOfShape& theValidEdges,
2180                       const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVE,
2181                       const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
2182                       const TopTools_MapOfShape& theMENeutral,
2183                       const TopTools_MapOfShape& theMEInverted,
2184                       const TopTools_MapOfShape& theEdgesInvalidByVertex,
2185                       const TopTools_MapOfShape& theEdgesValidByVertex,
2186                       const TopTools_MapOfShape& theMFHoles,
2187                       TopTools_IndexedMapOfShape& theMFInvInHole,
2188                       TopTools_ListOfShape& theInvFaces,
2189                       TopTools_ListOfShape& theInvertedFaces)
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;
2202   Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral, bInverted;
2203   Standard_Boolean bIsInvalidByInverted;
2204   Standard_Integer aNbChecked;
2205   //
2206   Standard_Boolean bTreatInvertedAsInvalid = (theLFImages.Extent() == 1);
2207   //
2208   // neutral edges to remove
2209   TopTools_IndexedMapOfShape aMENRem;
2210   //
2211   // faces for post treat
2212   TopTools_ListOfShape aLFPT;
2213   //
2214   TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
2215   TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
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);
2223   for (; aItLF.More(); ) {
2224     const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
2225     //
2226     // valid edges for this split
2227     const TopTools_MapOfShape* pMVE = theDMFMVE.Seek (aFIm);
2228     // invalid edges for this split
2229     const TopTools_IndexedMapOfShape* pMIE = theDMFMIE.Seek (aFIm);
2230     //
2231     bHasValid = Standard_False;
2232     bAllValid = Standard_True;
2233     bAllInvalid = Standard_True;
2234     bHasReallyInvalid = Standard_False;
2235     bAllInvNeutral = Standard_True;
2236     bIsInvalidByInverted = Standard_True;
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);
2246       bNeutral = theMENeutral.Contains(aEIm);
2247       //
2248       if (!bValid && !bInvalid && !bNeutral) {
2249         // edge has not been checked for some reason
2250         continue;
2251       }
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
2259       ++aNbChecked;
2260       //
2261       bInvalidLoc = pMIE && pMIE->Contains (aEIm);
2262       bHasReallyInvalid = bInvalid && bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
2263       if (bHasReallyInvalid) {
2264         break;
2265       }
2266       //
2267       bValidLoc = pMVE && pMVE->Contains(aEIm);
2268       bInverted = theMEInverted.Contains(aEIm);
2269       if (!bInvalid && !bInvalidLoc && bTreatInvertedAsInvalid) {
2270         bInvalid = bInverted;
2271       }
2272       //
2273       if (bValidLoc && bNeutral) {
2274         bHasValid = Standard_True;
2275       }
2276       //
2277       bAllValid &= bValidLoc;
2278       bAllInvalid &= (bInvalid || bInvalidLoc);
2279       bAllInvNeutral &= (bAllInvalid && bNeutral);
2280       bIsInvalidByInverted &= (bInvalidLoc || bInverted);
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);
2300       if (theMFHoles.Contains(aFIm)) {
2301         theMFInvInHole.Add(aFIm);
2302       }
2303       aItLF.Next();
2304       continue;
2305     }
2306     //
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     //
2315     if (bIsInvalidByInverted && !(bHasValid || bAllValid))
2316     {
2317       // The face contains only the inverted and locally invalid edges
2318       theInvertedFaces.Append(aFIm);
2319     }
2320
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   }
2334
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
2341     const TopTools_MapOfShape* pMVE = theDMFMVE.Seek(aFIm);
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);
2354       bNeutral = theMENeutral.Contains(aEIm) && !aMENRem.Contains (aEIm);
2355       bValidLoc = pMVE && pMVE->Contains(aEIm);
2356       //
2357       if (!bInvalid && bTreatInvertedAsInvalid) {
2358         bInvalid = theMEInverted.Contains(aEIm);
2359       }
2360       //
2361       if (bValidLoc && bNeutral) {
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
2375 //=======================================================================
2376 //function : FindFacesInsideHoleWires
2377 //purpose  : Find faces inside holes wires from the original face
2378 //=======================================================================
2379 void 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,
2384                               const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
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
2453       TopTools_ListOfShape aLE;
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       //
2465       const TopTools_ListOfShape& aLFNew = aBF.Areas();
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   }
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
2505   // among the splits of the offset face find those that are
2506   // located inside the hole faces
2507   TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
2508   for (; aItLF.More(); aItLF.Next()) {
2509     const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value());
2510     TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFSplitsMap);
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);
2527         TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, anEFHolesMap);
2528         break;
2529       }
2530     }
2531   }
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   }
2561 }
2562
2563 //=======================================================================
2564 //function : GetAverageTangent
2565 //purpose  : Computes average tangent vector along the curve
2566 //=======================================================================
2567 gp_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 //=======================================================================
2601 Standard_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,
2606                                const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
2607                                const TopTools_IndexedMapOfShape& theMEdges,
2608                                TopTools_MapOfShape& theMEInverted)
2609 {
2610   // It is necessary to compare the direction from first vertex
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;
2710             if (FindShape(aEO, theFOr, NULL, aEOin)) {
2711               AppendToList(aLOE, aEO);
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
2783 //=======================================================================
2784 //function : CheckInvertedBlock
2785 //purpose  : Checks if it is possible to remove the block containing
2786 //           inverted edges
2787 //=======================================================================
2788 Standard_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
2797   if (theCB.NbChildren() < 2) {
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 //=======================================================================
2901 void 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
2919 //=======================================================================
2920 //function : RemoveInvalidSplitsByInvertedEdges
2921 //purpose  : Looking for the invalid faces containing inverted edges
2922 //           that can be safely removed
2923 //=======================================================================
2924 void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
2925                                         const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
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   //
2938   BRep_Builder aBB;
2939   TopTools_IndexedMapOfShape aMEAvoid;
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;
2946     aBB.MakeCompound(aCFIm);
2947     //
2948     TopTools_DataMapOfShapeListOfShape aDMEF;
2949     TopTools_ListIteratorOfListOfShape aIt(aLFIm);
2950     for (; aIt.More(); aIt.Next()) {
2951       const TopoDS_Shape& aF = aIt.Value();
2952       aBB.Add(aCFIm, aF);
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) {
2961           pLF = aDMEF.Bound(aE, TopTools_ListOfShape());
2962         }
2963         else {
2964           // internal edges should not be used
2965           aMEAvoid.Add(aE);
2966         }
2967         AppendToList(*pLF, aF);
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) {
2977           pLF = aDMVF.Bound(aV, TopTools_ListOfShape());
2978         }
2979         AppendToList(*pLF, aF);
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);
2986     if (aLCBF.Extent() == 1) {
2987       continue;
2988     }
2989     //
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;
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;
3044       aBB.MakeCompound(aCEInv);
3045       TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
3046       for (; aExp.More(); aExp.Next()) {
3047         const TopoDS_Shape& aE = aExp.Current();
3048         if (aMERem.Contains(aE)) {
3049           aBB.Add(aCEInv, aE);
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 //=======================================================================
3101 void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3102                                   const TopTools_DataMapOfShapeShape& theArtInvFaces,
3103                                   const TopTools_MapOfShape& theMEInverted,
3104                                   const BRepOffset_DataMapOfShapeMapOfShape& theDMFMVIE,
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     //
3180     TopTools_DataMapOfShapeListOfShape aDMFF;
3181     aExp.Init(aCB, TopAbs_FACE);
3182     for (; aExp.More(); aExp.Next()) {
3183       const TopoDS_Shape& aFCB = aExp.Current();
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))
3206             break;
3207           if (aDMEF.FindFromKey(aECB).Extent() > 1)
3208           {
3209             if (!theMEInverted.Contains(aECB))
3210               break;
3211           }
3212         }
3213         if (!aExpE.More())
3214           // if one removed - remove all
3215           break;
3216       }
3217       if (itL.More())
3218       {
3219         for (itL.Initialize (aLFCB); itL.More(); itL.Next())
3220         {
3221           aMFToRem.Add (itL.Value());
3222         }
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 //=======================================================================
3251 void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
3252                        TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
3253                        const TopTools_DataMapOfShapeShape& theArtInvFaces,
3254                        const TopTools_IndexedMapOfShape& theInvEdges,
3255                        const TopTools_MapOfShape& theInvertedEdges,
3256                        const TopTools_ListOfShape& theInvertedFaces,
3257                        const TopTools_IndexedMapOfShape& theMFToCheckInt,
3258                        const TopTools_IndexedMapOfShape& theMFInvInHole,
3259                        const TopoDS_Shape& theFHoles,
3260                        TopTools_DataMapOfShapeListOfShape& theSSInterfs,
3261                        TopTools_IndexedMapOfShape& theMERemoved,
3262                        TopTools_IndexedMapOfShape& theMEInside,
3263                        TopoDS_Shape& theSolids)
3264 {
3265   TopTools_ListOfShape aLS;
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();
3316   if (aMV.HasErrors())
3317     return;
3318
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   //
3339   TopTools_MapOfShape aMFToRem;
3340   // Check completeness
3341   if (aMV.HasDeleted()) {
3342     TopTools_IndexedMapOfShape aMEHoles;
3343     TopExp::MapShapes(theFHoles, TopAbs_EDGE, aMEHoles);
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
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       }
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
3364       Standard_Boolean bFaceKept = Standard_False;
3365       aItLF.Initialize(aLFIm);
3366       for (; aItLF.More(); aItLF.Next()) {
3367         const TopoDS_Shape& aFIm = aItLF.Value();
3368         if (!aMV.IsDeleted(aFIm)) {
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           }
3380           if (!bFaceKept && bInvalid && !bConnected)
3381             bConnected = aMESols.Contains(aExpE.Current());
3382         }
3383       }
3384       //
3385       if (!bFaceKept && !bConnected) {
3386         return;
3387       }
3388     }
3389   }
3390   //
3391   TopTools_IndexedMapOfShape aMEBoundary;
3392   aNb = aDMFS.Extent();
3393   for (i = 1; i <= aNb; ++i) {
3394     const TopoDS_Shape& aFIm = aDMFS.FindKey(i);
3395     const TopTools_ListOfShape& aLSol = aDMFS(i);
3396     if (aLSol.Extent() > 1) {
3397       aMFToRem.Add(aFIm);
3398     }
3399     else if (aFIm.Orientation() != TopAbs_INTERNAL) {
3400       TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEBoundary);
3401     }
3402   }
3403
3404   // Tool for getting the splits of faces
3405   const TopTools_DataMapOfShapeListOfShape& aMVIms = aMV.Images();
3406
3407   // update invalid faces with images
3408   aNb = aMFInv.Extent();
3409   for (i = 1; i <= aNb; ++i) {
3410     const TopoDS_Shape& aFInv = aMFInv(i);
3411     TakeModified(aFInv, aMVIms, aMFInv);
3412   }
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
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;
3444       if (!FindShape(aFInvIm, aFSol, NULL, aFx)) {
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   //
3455   TopoDS_Compound aSolids;
3456   BRep_Builder().MakeCompound(aSolids);
3457   TopTools_MapOfShape aMFKeep;
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
3465     for (TopExp_Explorer aExpF(aSol, TopAbs_FACE); aExpF.More(); aExpF.Next())
3466     {
3467       const TopoDS_Shape& aFS = aExpF.Current();
3468       //
3469       if (aFS.Orientation() == TopAbs_INTERNAL) {
3470         aMFToRem.Add(aFS);
3471         continue;
3472       }
3473
3474       if (aMFToRem.Contains(aFS))
3475         continue;
3476
3477       bAllRemoved = false;
3478       bAllInv &= aMFInv.Contains(aFS);
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)) {
3488           if (!aMFKeep.Add(aFS)) {
3489             aMFKeep.Remove(aFS);
3490           }
3491         }
3492         else {
3493           aMFToRem.Add(aFS);
3494         }
3495       }
3496     }
3497     else {
3498       BRep_Builder().Add(aSolids, aSol);
3499       theSolids = aSolids;
3500     }
3501   }
3502   //
3503   TopTools_MapIteratorOfMapOfShape aItM(aMFKeep);
3504   for (; aItM.More(); aItM.Next()) {
3505     aMFToRem.Remove(aItM.Value());
3506   }
3507
3508   // Remove the invalid hanging parts external to the solids
3509   RemoveHangingParts(aMV, aDMFImF, aMFInv, theInvEdges, theInvertedEdges, aMFToRem);
3510
3511   // Remove newly found internal and hanging faces
3512   RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
3513   RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
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   }
3523 }
3524
3525 //=======================================================================
3526 //function : ShapesConnections
3527 //purpose  : Looking for the connections between faces not to miss
3528 //           some necessary intersection
3529 //=======================================================================
3530 void 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;
3538   Standard_Integer aNb = theInvEdges.Extent();
3539   for (Standard_Integer i = 1; i <= aNb; ++i) {
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();
3563   Standard_Integer iInt, aNbFF = aFFs.Length();
3564   for (iInt = 0; iInt < aNbFF; ++iInt) {
3565     const BOPDS_InterfFF& aFF = aFFs(iInt);
3566     const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
3567     Standard_Integer aNbC = aVNC.Length();
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
3687 //=======================================================================
3688 //function : RemoveHangingParts
3689 //purpose  : Remove isolated invalid hanging parts
3690 //=======================================================================
3691 void RemoveHangingParts(const BOPAlgo_MakerVolume& theMV,
3692                         const TopTools_DataMapOfShapeShape& theDMFImF,
3693                         const TopTools_IndexedMapOfShape& theMFInv,
3694                         const TopTools_IndexedMapOfShape& theInvEdges,
3695                         const TopTools_MapOfShape& theInvertedEdges,
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
3708   const TopTools_DataMapOfShapeListOfShape& aMVIms = theMV.Images();
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();
3717       TakeModified(aF, aMVIms, aCFHangs, &aMFS);
3718     }
3719   }
3720
3721   // Make connexity blocks of all hanging parts and check that they are isolated
3722   TopTools_ListOfShape aLCBHangs;
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();
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);
3750
3751   // Tool for getting the origins of the splits
3752   const TopTools_DataMapOfShapeListOfShape& aMVOrs = theMV.Origins();
3753
3754   // Find hanging blocks to remove
3755   TopTools_ListOfShape aBlocksToRemove;
3756
3757   TopTools_ListIteratorOfListOfShape aItLCBH(aLCBHangs);
3758   for (; aItLCBH.More(); aItLCBH.Next())
3759   {
3760     const TopoDS_Shape& aCBH = aItLCBH.Value();
3761
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
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
3799         anExpE.Init(aF, TopAbs_EDGE);
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
3812         if (!bIsConnected)
3813         {
3814           TopExp_Explorer anExpV(aF, TopAbs_VERTEX);
3815           for (; anExpV.More() && !bIsConnected; anExpV.Next())
3816           {
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             }
3826           }
3827         }
3828       }
3829
3830       // Check block to be isolated
3831       const TopTools_ListOfShape* pLFOr = aMVOrs.Seek(aF);
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)
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());
3865   }
3866 }
3867
3868 //=======================================================================
3869 //function : RemoveValidSplits
3870 //purpose  : Removing valid splits according to results of intersection
3871 //=======================================================================
3872 void 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 //=======================================================================
3923 void 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 //=======================================================================
4003 void 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 //=======================================================================
4048 void FilterInvalidFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4049                         const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
4050                         const TopTools_IndexedMapOfShape& theInvEdges,
4051                         const TopTools_IndexedMapOfShape& theMERemoved,
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;
4061   // Edge-Face connexity map of all splits, both invalid and valid
4062   TopTools_IndexedDataMapOfShapeListOfShape aDMEFAll;
4063   TopTools_ListIteratorOfListOfShape aItLF;
4064   //
4065   const Standard_Integer aNb = theInvFaces.Extent();
4066   for (Standard_Integer i = 1; i <= aNb; ++i) {
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     //
4084     TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
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();
4121             if (!theMERemoved.Contains(aE)) {
4122               const TopTools_ListOfShape* pLEF = theDMEF.Seek(aE);
4123               if (pLEF && pLEF->Extent() == 1) {
4124                 break;
4125               }
4126             }
4127           }
4128           //
4129           if (aExp.More()) {
4130             break;
4131           }
4132         }
4133         bInvalid = aItLF.More();
4134       }
4135     }
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     }
4185     //
4186     if (bInvalid) {
4187       aReallyInvFaces.Add(aF, aLFInv);
4188     }
4189   }
4190   //
4191   theInvFaces = aReallyInvFaces;
4192 }
4193
4194 //=======================================================================
4195 //function : CheckEdgesCreatedByVertex
4196 //purpose  : Checks additionally the unchecked edges originated from vertices
4197 //=======================================================================
4198 void 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
4244 //=======================================================================
4245 //function : FilterInvalidEdges
4246 //purpose  : Filtering the invalid edges according to currently invalid faces
4247 //=======================================================================
4248 void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
4249                         const TopTools_DataMapOfShapeShape& theArtInvFaces,
4250                         const BRepOffset_DataMapOfShapeIndexedMapOfShape& theDMFMIE,
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)) {
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);
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 //=======================================================================
4340 void 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 //=======================================================================
4465 void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
4466                   const TopTools_MapOfShape& theFSelfRebAvoid,
4467                   const TopoDS_Shape& theSolids,
4468                   const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
4469                   const BRepOffset_Analyse* theAnalyse,
4470                   TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
4471                   TopTools_DataMapOfShapeListOfShape& theDMFNewHoles,
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
4496   BuildSplitsOfInvFaces(theFToRebuild, aModifiedEdges, theAnalyse, theFImages, theDMFNewHoles, theEdgesOrigins,
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 //=======================================================================
4507 void 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;
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);
4540     for (TopExp_Explorer aExp (aEInv, TopAbs_VERTEX); aExp.More(); aExp.Next()) {
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;
4568   FindVerticesToAvoid(aDMEFInv, theInvEdges, theValidEdges, theInvertedEdges,
4569                       aDMVEFull, theOEImages, theOEOrigins, aMVRInv);
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
4577
4578   // find blocks of artificially invalid faces
4579   TopTools_DataMapOfShapeShape aDMFImF;
4580   TopoDS_Compound aCFArt;
4581   BRep_Builder().MakeCompound(aCFArt);
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()) {
4588       BRep_Builder().Add(aCFArt, aItLF.Value());
4589       aDMFImF.Bind(aItLF.Value(), aF);
4590     }
4591   }
4592   //
4593   // make connexity blocks
4594   TopTools_ListOfShape aLCBArt;
4595   BOPTools_AlgoTools::MakeConnexityBlocks(aCFArt, TopAbs_VERTEX, TopAbs_FACE, aLCBArt);
4596   //
4597   // alone edges
4598   TopTools_MapOfShape aMEAlone, aMEInvOnArt;
4599   //
4600   TopTools_ListIteratorOfListOfShape aItLCBArt(aLCBArt);
4601   for (; aItLCBArt.More(); aItLCBArt.Next()) {
4602     const TopoDS_Shape& aCB = aItLCBArt.Value();
4603     //
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()));
4609     }
4610     //
4611     Standard_Boolean bAlone = (aMFArt.Extent() == 1);
4612     //
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)) {
4625         aMEInvOnArt.Add(aE);
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);
4647       }
4648     }
4649     //
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       }
4657       //
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();
4699         //
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           }
4708         }
4709       }
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());
4728           }
4729         }
4730       }
4731     }
4732   }
4733   //
4734   // Bounding vertices of not trimmed edges
4735   TopTools_MapOfShape aMVBounds;
4736   //
4737   TopTools_MapOfShape aMECheckExt;
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;
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
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,
4862                                  theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt);
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
4902         IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV,
4903                               aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages);
4904         //
4905         Standard_Integer iE, aNbEToInt = aMEToInt.Extent();
4906         for (iE = 1; iE <= aNbEToInt; ++iE)
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         }
4919       }
4920     }
4921   }
4922   //
4923   // filter the obtained edges
4924   UpdateValidEdges(theFImages, aFLE, aDMOENEdges, aMVBounds, theSolids, theInvEdges, theInvertedEdges, aMEInvOnArt,
4925                    aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins,
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 //=======================================================================
4933 void 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 //=======================================================================
5026 void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
5027                          const TopTools_IndexedMapOfShape& theInvEdges,
5028                          const TopTools_IndexedMapOfShape& theValidEdges,
5029                          const TopTools_MapOfShape& theInvertedEdges,
5030                          const TopTools_DataMapOfShapeListOfShape& theDMVEFull,
5031                          const TopTools_DataMapOfShapeListOfShape& theOEImages,
5032                          const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
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     }
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);
5083       if (!pLE) {
5084         // isolated vertex
5085         theMVRInv.Add(aV);
5086         continue;
5087       }
5088       //
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;
5094       TopTools_ListIteratorOfListOfShape aItLE(*pLE);
5095       for (; aItLE.More(); aItLE.Next()) {
5096         const TopoDS_Shape& aEV = aItLE.Value();
5097
5098         if (theInvertedEdges.Contains(aEV))
5099           ++iNbEInverted;
5100
5101         if (bAllEdgesInv)
5102           bAllEdgesInv = theInvEdges.Contains(aEV);
5103       }
5104
5105       if (iNbEInverted > 1 || bAllEdgesInv)
5106       {
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 //=======================================================================
5117 void 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 //=======================================================================
5279 void 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,
5286                         const TopTools_MapOfShape& theAllInvs,
5287                         const Standard_Boolean theForceUse,
5288                         TopTools_IndexedMapOfShape& theMECV,
5289                         TopTools_MapOfShape& theMECheckExt,
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   //
5322   Standard_Boolean bUseOnlyInf = aLEC.IsEmpty();
5323   if (bUseOnlyInf) {
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();
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)) {
5339             return;
5340           }
5341           //
5342           TopoDS_Iterator aItV(aECx);
5343           for (; aItV.More(); aItV.Next()) {
5344             if (theAllInvs.Contains(aItV.Value())) {
5345               return;
5346             }
5347           }
5348         }
5349         // use only one element
5350         if (aLEC.IsEmpty()) {
5351           aLEC.Append(aEC);
5352         }
5353       }
5354     }
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     }
5384     else if (!theForceUse) {
5385       theMECheckExt.Add(aEInt);
5386     }
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 //=======================================================================
5398 void 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 //=======================================================================
5462 void 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 //=======================================================================
5532 void 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 //=======================================================================
5573 void 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,
5581                            const TopTools_MapOfShape& theMECheckExt,
5582                            TopTools_MapOfShape& theMVBounds,
5583                            TopTools_DataMapOfShapeListOfShape& theEImages)
5584 {
5585   Standard_Integer i, aNb = theMEInt.Extent();
5586   if (!aNb) {
5587     return;
5588   }
5589   //
5590   TopTools_ListOfShape aLArgs;
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;
5651   // Common intersection edges. Should be intersected separately
5652   TopTools_ListOfShape aLCE;
5653   //
5654   aNb = theMEInt.Extent();
5655   for (i = 1; i <= aNb; ++i) {
5656     const TopoDS_Shape& aE = theMEInt(i);
5657     if (theMECheckExt.Contains(aE)) {
5658       // avoid trimming of the intersection edges by additional common edges
5659       aLCE.Append(aE);
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();
5681   if (aGF.HasErrors()) {
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   //
5703   BRep_Builder aBB;
5704   // get valid splits to intersect with the commons
5705   TopoDS_Compound aCEIm;
5706   aBB.MakeCompound(aCEIm);
5707   //
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 {
5726         aBB.Add(aCEIm, aEIm);
5727         aIt1.Next();
5728       }
5729     }
5730     //
5731     if (aLEIm.Extent()) {
5732       TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
5733       if (!pLEIm) {
5734         pLEIm = theEImages.Bound(aE, TopTools_ListOfShape());
5735       }
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   //
5750   if (aGFCE.HasErrors()) {
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         }
5779       }
5780     }
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     }
5800   }
5801 }
5802
5803 //=======================================================================
5804 //function : GetInvalidEdges
5805 //purpose  : Looking for the invalid edges by intersecting with invalid vertices
5806 //=======================================================================
5807 void 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 //=======================================================================
5869 void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
5870                       const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
5871                       const TopTools_IndexedDataMapOfShapeListOfShape& theOENEdges,
5872                       const TopTools_MapOfShape& theMVBounds,
5873                       const TopoDS_Shape& theSolids,
5874                       const TopTools_IndexedMapOfShape& theInvEdges,
5875                       const TopTools_MapOfShape& theInvertedEdges,
5876                       const TopTools_MapOfShape& theMEInvOnArt,
5877                       TopTools_MapOfShape& theMECheckExt,
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   //
5896   TopTools_MapOfShape aMETmp;
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();
5905       if ((theMECheckExt.Contains(aE) || aMETmp.Contains(aE)) && !theEImages.IsBound(aE)) {
5906         theMECheckExt.Remove(aE);
5907         aMETmp.Add(aE);
5908         continue;
5909       }
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
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
5934   TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt,
5935                            theEImages, aMEB, aMVOld, aMENew, aDMEOr, aMELF);
5936   //
5937   if (theEImages.IsEmpty())
5938   {
5939     // No new splits is preserved
5940     // update intersection edges and exit
5941     UpdateNewIntersectionEdges(aLE, aMELF, theEImages, theInvEdges, theInvertedEdges, theEdgesOrigins,
5942       theOEImages, theOEOrigins, theETrimEInf, theEETrim, theModifiedEdges, theAsDes);
5943     return;
5944   }
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
5996     TopTools_ListOfShape aLSplits;
5997
5998     TopTools_ListIteratorOfListOfShape aItLE(aBlockLENew);
5999     for (; aItLE.More(); aItLE.Next())
6000     {
6001       const TopoDS_Shape& aE = aItLE.Value();
6002       TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE);
6003       if (!pLEIm || pLEIm->IsEmpty())
6004         continue;
6005
6006       TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
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
6036   TopTools_ListOfShape aLValBlocks;
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;
6085       }
6086     }
6087
6088     if (bKept)
6089       aLValBlocks.Append(aCEVal);
6090   }
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;
6102   }
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
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   //
6192   // Intersect valid splits with bounds and update both
6193   BOPAlgo_Builder aGF;
6194   aGF.AddArgument(aBounds);
6195   aGF.AddArgument(aSplits);
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   //
6211   // update the EdgesToAvoid with the splits
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   //
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
6226   aNbE = theEdgesToAvoid.Extent();
6227   for (i = 1; i <= aNbE; ++i)
6228   {
6229     const TopoDS_Shape& aE = theEdgesToAvoid(i);
6230     const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
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
6262     TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
6263     for (; aItLEIm.More(); aItLEIm.Next())
6264     {
6265       const TopoDS_Shape& aEIm = aItLEIm.Value();
6266       if (!aNewEdges.Contains(aEIm))
6267         aMEAvoid.Add(aEIm);
6268     }
6269   }
6270   theEdgesToAvoid = aMEAvoid;
6271 }
6272
6273 //=======================================================================
6274 //function : TrimNewIntersectionEdges
6275 //purpose  : 
6276 //=======================================================================
6277 void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
6278                               const TopTools_DataMapOfShapeListOfShape& theEETrim,
6279                               const TopTools_MapOfShape& theMVBounds,
6280                               TopTools_MapOfShape& theMECheckExt,
6281                               TopTools_DataMapOfShapeListOfShape& theEImages,
6282                               TopTools_MapOfShape& theMEB,
6283                               TopTools_MapOfShape& theMVOld,
6284                               TopTools_MapOfShape& theMENew,
6285                               TopTools_DataMapOfShapeListOfShape& theDMEOr,
6286                               TopTools_DataMapOfShapeListOfShape& theMELF)
6287 {
6288   TopTools_ListIteratorOfListOfShape aIt, aIt1;
6289   aIt.Initialize(theLE);
6290   for (; aIt.More(); aIt.Next()) {
6291     const TopoDS_Shape& aE = aIt.Value();
6292     //
6293     Standard_Boolean bCheckExt = theMECheckExt.Remove(aE);
6294     //
6295     Standard_Boolean bOld = theEETrim.IsBound(aE);
6296     if (bOld) {
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     //
6323     if (aLEIm.Extent() > 1) {
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();
6344       if (!aGFE.HasErrors()) {
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);
6353             aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First());
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()) {
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 {
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) {
6407           theMENew.Add(aEIm);
6408         }
6409       }
6410     }
6411   }
6412 }
6413
6414 //=======================================================================
6415 //function : IntersectEdges
6416 //purpose  : Intersecting the trimmed edges to avoid self-intersections
6417 //=======================================================================
6418 void IntersectEdges(const TopTools_ListOfShape& theLA,
6419                     const TopTools_ListOfShape& theLE,
6420                     const TopTools_MapOfShape& theMVBounds,
6421                     const TopTools_MapOfShape& theVertsToAvoid,
6422                     TopTools_MapOfShape& theMENew,
6423                     TopTools_MapOfShape& theMECheckExt,
6424                     TopTools_DataMapOfShapeListOfShape& theEImages,
6425                     TopTools_MapOfShape& theModifiedEdges,
6426                     TopTools_DataMapOfShapeListOfShape& theDMEOr,
6427                     TopTools_DataMapOfShapeListOfShape& theMELF,
6428                     TopoDS_Shape& theSplits)
6429 {
6430   BOPAlgo_Builder aGFA;
6431   aGFA.SetArguments(theLA);
6432   aGFA.Perform();
6433   if (aGFA.HasErrors()) {
6434     // just copy input to the result
6435     TopoDS_Compound aSp;
6436     BRep_Builder aBB;
6437     aBB.MakeCompound(aSp);
6438     TopTools_ListIteratorOfListOfShape anIt(theLA);
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   //
6452   TopTools_ListIteratorOfListOfShape aIt, aIt1;
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);
6465   for (; aIt.More(); aIt.Next()) {
6466     const TopoDS_Shape& aE = aIt.Value();
6467     if (!theMENew.Contains(aE))
6468       continue;
6469
6470     const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE);
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());
6478   }
6479   //
6480   // update edges after intersection for extended checking
6481   aIt.Initialize(aLEInput);
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   //
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   //
6529   // update origins
6530   UpdateOrigins(aLEInput, theDMEOr, aGFA);
6531 }
6532
6533 //=======================================================================
6534 //function : GetBounds
6535 //purpose  : Getting edges from the splits of offset faces
6536 //=======================================================================
6537 void GetBounds(const TopTools_ListOfShape& theLFaces,
6538                const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
6539                const TopTools_MapOfShape& theMEB,
6540                TopoDS_Shape& theBounds)
6541 {
6542   BRep_Builder aBB;
6543   // Make compound of edges contained in the splits of faces
6544   TopoDS_Compound aBounds;
6545   aBB.MakeCompound(aBounds);
6546   // Fence map
6547   TopTools_MapOfShape aMFence;
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     {
6558       const TopoDS_Shape& aFIm = aIt.Value();
6559       //
6560       TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
6561       for (; aExpE.More(); aExpE.Next())
6562       {
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 //=======================================================================
6577 void 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 //=======================================================================
6649 void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
6650                              const TopoDS_Shape& theBounds,
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,
6657                              const TopTools_DataMapOfShapeListOfShape& theMELF,
6658                              const TopTools_DataMapOfShapeListOfShape& theEImages,
6659                              const TopTools_MapOfShape& theMECheckExt,
6660                              const TopTools_MapOfShape& theMEInvOnArt,
6661                              Handle(IntTools_Context)& theCtx,
6662                              TopTools_MapOfShape& theVertsToAvoid,
6663                              TopTools_MapOfShape& theMEInv)
6664 {
6665   // map splits to check the vertices of edges
6666   TopTools_IndexedDataMapOfShapeListOfShape aDMVE;
6667   TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE);
6668   //
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();
6684   Standard_Integer i, aNb = aEEs.Length();
6685   for (i = 0; i < aNb; ++i) {
6686     const BOPDS_InterfEE& aEE = aEEs(i);
6687     //
6688     const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1());
6689     const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2());
6690     //
6691     if (!aEE.HasIndexNew()) {
6692       if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) {
6693         theMEInv.Add(aE1);
6694       }
6695       continue;
6696     }
6697     //
6698     if (theInvEdges.Contains(aE2)) {
6699       theMEInv.Add(aE1);
6700     }
6701     //
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     //
6712     // add vertices of all images of the edge from splits for checking
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       //
6718       const TopTools_ListOfShape *pLEIm = theEImages.Seek(aEOr);
6719       if (!pLEIm)
6720         continue;
6721       TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
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   //
6737   // to avoid unnecessary filling of parts due to extra trim of the edges
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
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   //
6749   const TopTools_DataMapOfShapeListOfShape& anIm = aSec.Images();
6750   for (TopExp_Explorer aExp(theSplits, TopAbs_EDGE); aExp.More(); aExp.Next())
6751   {
6752     const TopoDS_Shape& aE = aExp.Current();
6753     if (aSec.IsDeleted(aE)) {
6754       // no common blocks for this edge
6755       continue;
6756     }
6757     //
6758     const TopTools_ListOfShape* pLEIm = anIm.Seek(aE);
6759     if (!pLEIm) {
6760       // no splits, i.e. completely coincides with some edge from boundary
6761       continue;
6762     }
6763     //
6764     TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
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.
6769         // the part not included in section may be excessive
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)) {
6776           // add this edge for checking by making new vertex in the middle of the edge
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());
6781           // and adding this vertex for checking
6782           aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE);
6783           aMVInv.Add(aV);
6784           break;
6785         }
6786       }
6787     }
6788   }
6789   //
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
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();
6820       if (theMECheckExt.Contains(aE)) {
6821         continue;
6822       }
6823       //
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   //
6842   // perform the checking of the vertices
6843   Standard_Integer iv, aNbIV = aMVInv.Extent();
6844   for (iv = 1; iv <= aNbIV; ++iv) {
6845     const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv));
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
6867     Standard_Boolean bInvalid = Standard_True;
6868     //
6869     Standard_Integer aNbF = aMF.Extent();
6870     for (i = 1; i <= aNbF && bInvalid; ++i) {
6871       const TopoDS_Face& aF = TopoDS::Face(aMF(i));
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         }
6882       }
6883       //
6884       if (bInvalid) {
6885         Standard_Real U, V, aTol;
6886         Standard_Integer iStatus = theCtx->ComputeVF(aV, aF, U, V, aTol);
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());
6893             bInvalid = !theCtx->IsPointInOnFace(aFIm, aP2d);
6894           }
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
6902       const gp_Pnt& aP = BRep_Tool::Pnt(aV);
6903       Standard_Real aTolV = BRep_Tool::Tolerance(aV);
6904       //
6905       TopExp_Explorer aExpS(theSolids, TopAbs_SOLID);
6906       for (; aExpS.More() && bInvalid; aExpS.Next()) {
6907         const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current());
6908         BRepClass3d_SolidClassifier& aSC = theCtx->SolidClassifier(aSol);
6909         aSC.Perform(aP, aTolV);
6910         bInvalid = (aSC.State() == TopAbs_OUT);
6911       }
6912     }
6913     //
6914     if (bInvalid) {
6915       theVertsToAvoid.Add(aV);
6916       aItLE.Initialize(*pLEInv);
6917       for (; aItLE.More(); aItLE.Next()) {
6918         theMEInv.Add(aItLE.Value());
6919       }
6920     }
6921   }
6922 }
6923
6924 //=======================================================================
6925 //function : FilterSplits
6926 //purpose  : Filter the images of edges from the invalid edges
6927 //=======================================================================
6928 void 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
6967 //=======================================================================
6968 //function : UpdateNewIntersectionEdges
6969 //purpose  : Updating the maps of images and origins of the offset edges
6970 //=======================================================================
6971 void 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
7182 //=======================================================================
7183 //function : FillGaps
7184 //purpose  : Fill possible gaps (holes) in the splits of the offset faces
7185 //=======================================================================
7186 void 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
7274 //=======================================================================
7275 //function : FillHistory
7276 //purpose  : Saving obtained results in history tools
7277 //=======================================================================
7278 void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
7279                  const TopTools_DataMapOfShapeListOfShape& theEImages,
7280                  BRepAlgo_Image& theImage)
7281 {
7282   Standard_Integer aNbF = theFImages.Extent();
7283   if (!aNbF)
7284     return;
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
7295   // Fill history for faces
7296   for (Standard_Integer i = 1; i <= aNbF; ++i)
7297   {
7298     const TopTools_ListOfShape& aLFImages = theFImages(i);
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
7319     }
7320   }
7321
7322   // Fill history for edges (iteration by the map is safe because the
7323   // order is not important here)
7324   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(theEImages);
7325   for (; aItEIm.More(); aItEIm.Next())
7326   {
7327     const TopoDS_Shape& aE = aItEIm.Key();
7328     const TopTools_ListOfShape& aLEIm = aItEIm.Value();
7329
7330     Standard_Boolean bHasImage = theImage.HasImage(aE);
7331     TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
7332     for (; aItLE.More(); aItLE.Next())
7333     {
7334       const TopoDS_Shape& aEIm = aItLE.Value();
7335       if (anEdgesMap.Contains(aEIm))
7336       {
7337         if (bHasImage)
7338         {
7339           theImage.Add(aE, aEIm);
7340         }
7341         else
7342         {
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 //=======================================================================
7355 Standard_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 //=======================================================================
7378 void 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 //=======================================================================
7423 void UpdateImages(const TopTools_ListOfShape& theLA,
7424                   TopTools_DataMapOfShapeListOfShape& theImages,
7425                   BOPAlgo_Builder& theGF,
7426                   TopTools_MapOfShape& theModified)
7427 {
7428   TopTools_ListIteratorOfListOfShape aIt(theLA);
7429   for (; aIt.More(); aIt.Next())
7430   {
7431     const TopoDS_Shape& aS = aIt.Value();
7432     //
7433     TopTools_ListOfShape* pLSIm = theImages.ChangeSeek(aS);
7434     if (!pLSIm)
7435     {
7436       const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
7437       if (aLSIm.Extent())
7438       {
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);
7452     for (; aIt1.More(); aIt1.Next())
7453     {
7454       const TopoDS_Shape& aSIm = aIt1.Value();
7455       bModified |= TakeModified(aSIm, theGF.Images(), aLSImNew, &aMFence);
7456     }
7457     //
7458     if (bModified)
7459     {
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 //=======================================================================
7470 void 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 //=======================================================================
7502 void 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 //=======================================================================
7540 Standard_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 //=======================================================================
7559 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
7560                            const TopoDS_Shape& theSWhere,
7561                            const BRepOffset_Analyse* theAnalyse,
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   }
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
7594   return bFound;
7595 }
7596
7597
7598 //=======================================================================
7599 //function : AppendToList
7600 //purpose  : Add to a list only unique elements
7601 //=======================================================================
7602 void 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 }
7614
7615 //=======================================================================
7616 //function : AddToContainer
7617 //purpose  : Set of methods to add a shape into container
7618 //=======================================================================
7619 static void AddToContainer(const TopoDS_Shape& theS,
7620                            TopTools_ListOfShape& theList)
7621 {
7622   theList.Append(theS);
7623 }
7624 static Standard_Boolean AddToContainer(const TopoDS_Shape& theS,
7625                                        TopTools_MapOfShape& theMap)
7626 {
7627   return theMap.Add(theS);
7628 }
7629 static 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 }
7636 static 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 //=======================================================================
7647 template <class ContainerType, class FenceMapType>
7648 Standard_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 }