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