0032781: Coding - get rid of unused headers [BRepCheck to ChFiKPart]
[occt.git] / src / BRepOffset / BRepOffset_Analyse.cxx
1 // Created on: 1995-10-20
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Adaptor3d_Surface.hxx>
19 #include <BOPTools_AlgoTools.hxx>
20 #include <BOPTools_AlgoTools3D.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepOffset_Analyse.hxx>
23 #include <BRepOffset_Interval.hxx>
24 #include <BRepOffset_Tool.hxx>
25 #include <BRepPrimAPI_MakePrism.hxx>
26 #include <BRepTools.hxx>
27 #include <Geom_Curve.hxx>
28 #include <gp.hxx>
29 #include <gp_Dir.hxx>
30 #include <gp_Pnt.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Vec.hxx>
33 #include <IntTools_Context.hxx>
34 #include <TopExp.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Compound.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <TopTools_MapOfShape.hxx>
43 #include <ChFi3d.hxx>
44
45 static void CorrectOrientationOfTangent(gp_Vec& TangVec,
46                                         const TopoDS_Vertex& aVertex,
47                                         const TopoDS_Edge& anEdge)
48 {
49   TopoDS_Vertex Vlast = TopExp::LastVertex(anEdge);
50   if (aVertex.IsSame(Vlast))
51     TangVec.Reverse();
52 }
53 //=======================================================================
54 //function : BRepOffset_Analyse
55 //purpose  : 
56 //=======================================================================
57
58 BRepOffset_Analyse::BRepOffset_Analyse()
59 : myOffset (0.0), myDone (Standard_False)
60 {
61 }
62
63 //=======================================================================
64 //function : BRepOffset_Analyse
65 //purpose  : 
66 //=======================================================================
67 BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, 
68                                        const Standard_Real Angle)
69 : myOffset (0.0), myDone (Standard_False)
70 {
71   Perform( S, Angle);
72 }
73
74 //=======================================================================
75 //function : EdgeAnlyse
76 //purpose  : 
77 //=======================================================================
78 static void EdgeAnalyse(const TopoDS_Edge&         E,
79                                           const TopoDS_Face&         F1,
80                                           const TopoDS_Face&         F2,
81                                           const Standard_Real        SinTol,
82                                                 BRepOffset_ListOfInterval& LI)
83 {
84   Standard_Real   f,l;
85   BRep_Tool::Range(E, F1, f, l);
86   BRepOffset_Interval I;
87   I.First(f); I.Last(l);
88   //  
89   BRepAdaptor_Surface aBAsurf1(F1, Standard_False);
90   GeomAbs_SurfaceType aSurfType1 = aBAsurf1.GetType();
91
92   BRepAdaptor_Surface aBAsurf2(F2, Standard_False);
93   GeomAbs_SurfaceType aSurfType2 = aBAsurf2.GetType();
94
95   Standard_Boolean isTwoPlanes = (aSurfType1 == GeomAbs_Plane && aSurfType2 == GeomAbs_Plane);
96
97   ChFiDS_TypeOfConcavity ConnectType = ChFiDS_Other;
98
99   if (isTwoPlanes) //then use only strong condition
100   {
101     if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0)
102       ConnectType = ChFiDS_Tangential;
103     else
104       ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False);
105   }
106   else
107   {
108     if (ChFi3d::IsTangentFaces(E, F1, F2)) //weak condition
109       ConnectType = ChFiDS_Tangential;
110     else
111       ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False);
112   }
113    
114   I.Type(ConnectType);
115   LI.Append(I);
116 }
117
118 //=======================================================================
119 //function : BuildAncestors
120 //purpose  : 
121 //=======================================================================
122 static void BuildAncestors (const TopoDS_Shape&                        S,
123                             TopTools_IndexedDataMapOfShapeListOfShape& MA)
124 {  
125   MA.Clear();
126   TopExp::MapShapesAndUniqueAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA);
127   TopExp::MapShapesAndUniqueAncestors(S,TopAbs_EDGE  ,TopAbs_FACE,MA);
128 }
129
130 //=======================================================================
131 //function : Perform
132 //purpose  : 
133 //=======================================================================
134 void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, 
135                                   const Standard_Real Angle,
136                                   const Message_ProgressRange& theRange)
137 {
138   myShape = S;
139   myNewFaces .Clear();
140   myGenerated.Clear();
141   myReplacement.Clear();
142   myDescendants.Clear();
143
144   myAngle                = Angle;
145   Standard_Real SinTol = Abs (Sin(Angle));
146
147   // Build ancestors.
148   BuildAncestors (S,myAncestors);
149
150   TopTools_ListOfShape aLETang;
151   TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
152   Message_ProgressScope aPSOuter(theRange, NULL, 2);
153   Message_ProgressScope aPS(aPSOuter.Next(), "Performing edges analysis", 1, Standard_True);
154   for ( ; Exp.More(); Exp.Next(), aPS.Next()) {
155     if (!aPS.More())
156     {
157       return;
158     }
159     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
160     if (!myMapEdgeType.IsBound(E)) {
161       BRepOffset_ListOfInterval LI;
162       myMapEdgeType.Bind(E,LI);
163       
164       const TopTools_ListOfShape& L = Ancestors(E);
165       if ( L.IsEmpty()) 
166         continue;
167
168       if (L.Extent() == 2) {
169         const TopoDS_Face& F1 = TopoDS::Face (L.First());
170         const TopoDS_Face& F2 = TopoDS::Face (L.Last());
171         EdgeAnalyse (E, F1, F2, SinTol, myMapEdgeType (E));
172
173         // For tangent faces add artificial perpendicular face
174         // to close the gap between them (if they have different offset values)
175         if (myMapEdgeType(E).Last().Type() == ChFiDS_Tangential)
176           aLETang.Append (E);
177       }
178       else if (L.Extent() == 1) {
179         Standard_Real U1, U2;
180         const TopoDS_Face& F = TopoDS::Face (L.First());
181         BRep_Tool::Range (E, F, U1, U2);
182         BRepOffset_Interval Inter (U1, U2, ChFiDS_Other);
183
184         if (!BRepTools::IsReallyClosed (E, F)) {
185           Inter.Type (ChFiDS_FreeBound);
186         }
187         myMapEdgeType (E).Append (Inter);
188       }
189       else {  
190 #ifdef OCCT_DEBUG
191         std::cout <<"edge shared by more than two faces"<<std::endl;
192 #endif  
193       }
194     }
195   }
196
197   TreatTangentFaces (aLETang, aPSOuter.Next());
198   if (!aPSOuter.More())
199   {
200     return;
201   }
202   myDone = Standard_True;
203 }
204
205 //=======================================================================
206 //function : Generated
207 //purpose  : 
208 //=======================================================================
209 void BRepOffset_Analyse::TreatTangentFaces (const TopTools_ListOfShape& theLE, const Message_ProgressRange& theRange)
210 {
211   if (theLE.IsEmpty() || myFaceOffsetMap.IsEmpty())
212   {
213     // Noting to do: either there are no tangent faces in the shape or
214     //               the face offset map has not been provided
215     return;
216   }
217
218   // Select the edges which connect faces with different offset values
219   TopoDS_Compound aCETangent;
220   BRep_Builder().MakeCompound (aCETangent);
221   // Bind to each tangent edge a max offset value of its faces
222   TopTools_DataMapOfShapeReal anEdgeOffsetMap;
223   // Bind vertices of the tangent edges with connected edges
224   // of the face with smaller offset value
225   TopTools_DataMapOfShapeShape aDMVEMin;
226   Message_ProgressScope aPSOuter(theRange, NULL, 3);
227   Message_ProgressScope aPS1(aPSOuter.Next(), "Binding vertices with connected edges", theLE.Size());
228   for (TopTools_ListOfShape::Iterator it (theLE); it.More(); it.Next(), aPS1.Next())
229   {
230     if (!aPS1.More())
231     {
232       return;
233     }
234     const TopoDS_Shape& aE = it.Value();
235     const TopTools_ListOfShape& aLA = Ancestors (aE);
236
237     const TopoDS_Shape& aF1 = aLA.First(), aF2 = aLA.Last();
238
239     const Standard_Real *pOffsetVal1 = myFaceOffsetMap.Seek (aF1);
240     const Standard_Real *pOffsetVal2 = myFaceOffsetMap.Seek (aF2);
241     const Standard_Real anOffsetVal1 = pOffsetVal1 ? Abs (*pOffsetVal1) : myOffset;
242     const Standard_Real anOffsetVal2 = pOffsetVal2 ? Abs (*pOffsetVal2) : myOffset;
243     if (anOffsetVal1 != anOffsetVal2)
244     {
245       BRep_Builder().Add (aCETangent, aE);
246       anEdgeOffsetMap.Bind (aE, Max (anOffsetVal1, anOffsetVal2));
247
248       const TopoDS_Shape& aFMin = anOffsetVal1 < anOffsetVal2 ? aF1 : aF2;
249       for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
250       {
251         const TopoDS_Shape& aV = itV.Value();
252         if (Ancestors (aV).Extent() == 3)
253         {
254           for (TopExp_Explorer expE (aFMin, TopAbs_EDGE); expE.More(); expE.Next())
255           {
256             const TopoDS_Shape& aEMin = expE.Current();
257             if (aEMin.IsSame (aE))
258               continue;
259             for (TopoDS_Iterator itV1 (aEMin); itV1.More(); itV1.Next())
260             {
261               const TopoDS_Shape& aVx = itV1.Value();
262               if (aV.IsSame (aVx))
263                 aDMVEMin.Bind (aV, aEMin);
264             }
265           }
266         }
267       }
268     }
269   }
270
271   if (anEdgeOffsetMap.IsEmpty())
272     return;
273
274   // Create map of Face ancestors for the vertices on tangent edges
275   TopTools_DataMapOfShapeListOfShape aDMVFAnc;
276
277   Message_ProgressScope aPS2(aPSOuter.Next(), "Creating map of Face ancestors", theLE.Size());
278   for (TopTools_ListOfShape::Iterator itE (theLE); itE.More(); itE.Next(), aPS2.Next())
279   {
280     if (!aPS2.More())
281     {
282       return;
283     }
284     const TopoDS_Shape& aE = itE.Value();
285     if (!anEdgeOffsetMap.IsBound (aE))
286       continue;
287
288     TopTools_MapOfShape aMFence;
289     {
290       const TopTools_ListOfShape& aLEA = Ancestors (aE);
291       for (TopTools_ListOfShape::Iterator itLEA (aLEA); itLEA.More(); itLEA.Next())
292         aMFence.Add (itLEA.Value());
293     }
294
295     for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
296     {
297       const TopoDS_Shape& aV = itV.Value();
298       TopTools_ListOfShape* pLFA = aDMVFAnc.Bound (aV, TopTools_ListOfShape());
299       const TopTools_ListOfShape& aLVA = Ancestors (aV);
300       for (TopTools_ListOfShape::Iterator itLVA (aLVA); itLVA.More(); itLVA.Next())
301       {
302         const TopoDS_Edge& aEA = TopoDS::Edge (itLVA.Value());
303         const BRepOffset_ListOfInterval* pIntervals = myMapEdgeType.Seek (aEA);
304         if (!pIntervals || pIntervals->IsEmpty())
305           continue;
306         if (pIntervals->First().Type() == ChFiDS_Tangential)
307           continue;
308
309         const TopTools_ListOfShape& aLEA = Ancestors (aEA);
310         for (TopTools_ListOfShape::Iterator itLEA (aLEA); itLEA.More(); itLEA.Next())
311         {
312           const TopoDS_Shape& aFA = itLEA.Value();
313           if (aMFence.Add (aFA))
314             pLFA->Append (aFA);
315         }
316       }
317     }
318   }
319
320   Handle(IntTools_Context) aCtx = new IntTools_Context();
321   // Tangency criteria
322   Standard_Real aSinTol = Abs (Sin (myAngle));
323
324   // Make blocks of connected edges
325   TopTools_ListOfListOfShape aLCB;
326   TopTools_IndexedDataMapOfShapeListOfShape aMVEMap;
327
328   BOPTools_AlgoTools::MakeConnexityBlocks (aCETangent, TopAbs_VERTEX, TopAbs_EDGE, aLCB, aMVEMap);
329
330   // Analyze each block to find co-planar edges
331   Message_ProgressScope aPS3(aPSOuter.Next(), "Analyzing blocks to find co-planar edges", aLCB.Size());
332   for (TopTools_ListOfListOfShape::Iterator itLCB (aLCB); itLCB.More(); itLCB.Next(), aPS3.Next())
333   {
334     if (!aPS3.More())
335     {
336       return;
337     }
338     const TopTools_ListOfShape& aCB = itLCB.Value();
339
340     TopTools_MapOfShape aMFence;
341     for (TopTools_ListOfShape::Iterator itCB1 (aCB); itCB1.More(); itCB1.Next())
342     {
343       const TopoDS_Edge& aE1 = TopoDS::Edge (itCB1.Value());
344       if (!aMFence.Add (aE1))
345         continue;
346
347       TopoDS_Compound aBlock;
348       BRep_Builder().MakeCompound (aBlock);
349       BRep_Builder().Add (aBlock, aE1.Oriented (TopAbs_FORWARD));
350
351       Standard_Real anOffset = anEdgeOffsetMap.Find (aE1);
352       const TopTools_ListOfShape& aLF1 = Ancestors (aE1);
353
354       gp_Dir aDN1;
355       BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE1, TopoDS::Face (aLF1.First()), aDN1);
356
357       TopTools_ListOfShape::Iterator itCB2 = itCB1;
358       for (itCB2.Next(); itCB2.More(); itCB2.Next())
359       {
360         const TopoDS_Edge& aE2 = TopoDS::Edge (itCB2.Value());
361         if (aMFence.Contains (aE2))
362           continue;
363
364         const TopTools_ListOfShape& aLF2 = Ancestors (aE2);
365
366         gp_Dir aDN2;
367         BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE2, TopoDS::Face (aLF2.First()), aDN2);
368
369         if (aDN1.XYZ().Crossed (aDN2.XYZ()).Modulus() < aSinTol)
370         {
371           BRep_Builder().Add (aBlock, aE2.Oriented (TopAbs_FORWARD));
372           aMFence.Add (aE2);
373           anOffset = Max (anOffset, anEdgeOffsetMap.Find (aE2));
374         }
375       }
376
377       // Make the prism
378       BRepPrimAPI_MakePrism aMP (aBlock, gp_Vec (aDN1.XYZ()) * anOffset);
379       if (!aMP.IsDone())
380         continue;
381
382       TopTools_IndexedDataMapOfShapeListOfShape aPrismAncestors;
383       TopExp::MapShapesAndAncestors (aMP.Shape(), TopAbs_EDGE, TopAbs_FACE, aPrismAncestors);
384       TopExp::MapShapesAndAncestors (aMP.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aPrismAncestors);
385
386       for (TopoDS_Iterator itE (aBlock); itE.More(); itE.Next())
387       {
388         const TopoDS_Edge& aE = TopoDS::Edge (itE.Value());
389         const TopTools_ListOfShape& aLG = aMP.Generated (aE);
390         TopoDS_Face aFNew = TopoDS::Face (aLG.First());
391
392         TopTools_ListOfShape& aLA = myAncestors.ChangeFromKey (aE);
393
394         TopoDS_Shape aF1 = aLA.First();
395         TopoDS_Shape aF2 = aLA.Last();
396
397         const Standard_Real *pOffsetVal1 = myFaceOffsetMap.Seek (aF1);
398         const Standard_Real *pOffsetVal2 = myFaceOffsetMap.Seek (aF2);
399         const Standard_Real anOffsetVal1 = pOffsetVal1 ? Abs (*pOffsetVal1) : myOffset;
400         const Standard_Real anOffsetVal2 = pOffsetVal2 ? Abs (*pOffsetVal2) : myOffset;
401
402         const TopoDS_Shape& aFToRemove = anOffsetVal1 > anOffsetVal2 ? aF1 : aF2;
403         const TopoDS_Shape& aFOpposite = anOffsetVal1 > anOffsetVal2 ? aF2 : aF1;
404
405         // Orient the face so its normal is directed to smaller offset face
406         {
407           // get normal of the new face
408           gp_Dir aDN;
409           BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aFNew, aDN);
410         
411           // get bi-normal for the aFOpposite
412           TopoDS_Edge aEInF;
413           for (TopExp_Explorer aExpE (aFOpposite, TopAbs_EDGE); aExpE.More(); aExpE.Next())
414           {
415             if (aE.IsSame (aExpE.Current()))
416             {
417               aEInF = TopoDS::Edge (aExpE.Current());
418               break;
419             }
420           }
421         
422           gp_Pnt2d aP2d;
423           gp_Pnt aPInF;
424           Standard_Real f, l;
425           const Handle(Geom_Curve)& aC3D = BRep_Tool::Curve (aEInF, f, l);
426           gp_Pnt aPOnE = aC3D->Value ((f + l) / 2.);
427           BOPTools_AlgoTools3D::PointNearEdge (aEInF, TopoDS::Face (aFOpposite), (f + l) / 2., 1.e-5, aP2d, aPInF);
428         
429           gp_Vec aBN (aPOnE, aPInF);
430         
431           if (aBN.Dot (aDN) < 0)
432             aFNew.Reverse();
433         }
434
435         // Remove the face with bigger offset value from edge ancestors
436         for (TopTools_ListOfShape::Iterator itA (aLA); itA.More();itA.Next())
437         {
438           if (itA.Value().IsSame (aFToRemove))
439           {
440             aLA.Remove (itA);
441             break;
442           }
443         }
444         aLA.Append (aFNew);
445
446         myMapEdgeType (aE).Clear();
447         // Analyze edge again
448         EdgeAnalyse (aE, TopoDS::Face (aFOpposite), aFNew,  aSinTol, myMapEdgeType (aE));
449
450         // Analyze vertices
451         TopTools_MapOfShape aFNewEdgeMap;
452         aFNewEdgeMap.Add (aE);
453         for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
454         {
455           const TopoDS_Shape& aV = itV.Value();
456           // Add Side edge to map of Ancestors with the correct orientation
457           TopoDS_Edge aEG = TopoDS::Edge (aMP.Generated (aV).First());
458           myGenerated.Bind (aV, aEG);
459           {
460             for (TopExp_Explorer anExpEg (aFNew, TopAbs_EDGE); anExpEg.More(); anExpEg.Next())
461             {
462               if (anExpEg.Current().IsSame (aEG))
463               {
464                 aEG = TopoDS::Edge (anExpEg.Current());
465                 break;
466               }
467             }
468           }
469
470           if (aDMVEMin.IsBound (aV))
471           {
472             const TopTools_ListOfShape* pSA = aDMVFAnc.Seek (aV);
473             if (pSA && pSA->Extent() == 1)
474             {
475               // Adjust orientation of generated edge to its new ancestor
476               TopoDS_Edge aEMin = TopoDS::Edge (aDMVEMin.Find (aV));
477               for (TopExp_Explorer expEx (pSA->First(), TopAbs_EDGE); expEx.More(); expEx.Next())
478               {
479                 if (expEx.Current().IsSame (aEMin))
480                 {
481                   aEMin = TopoDS::Edge (expEx.Current());
482                   break;
483                 }
484               }
485
486               TopAbs_Orientation anOriInEMin (TopAbs_FORWARD), anOriInEG (TopAbs_FORWARD);
487               
488               for (TopoDS_Iterator itx (aEMin); itx.More(); itx.Next())
489               {
490                 if (itx.Value().IsSame (aV))
491                 {
492                   anOriInEMin = itx.Value().Orientation();
493                   break;
494                 }
495               }
496               
497               for (TopoDS_Iterator itx (aEG); itx.More(); itx.Next())
498               {
499                 if (itx.Value().IsSame (aV))
500                 {
501                   anOriInEG = itx.Value().Orientation();
502                   break;
503                 }
504               }
505               
506               if (anOriInEG == anOriInEMin)
507                 aEG.Reverse();
508             }
509           }
510
511           TopTools_ListOfShape& aLVA = myAncestors.ChangeFromKey (aV);
512           if (!aLVA.Contains (aEG))
513             aLVA.Append (aEG);
514           aFNewEdgeMap.Add (aEG);
515
516           TopTools_ListOfShape& aLEGA =
517             myAncestors (myAncestors.Add (aEG, aPrismAncestors.FindFromKey (aEG)));
518           {
519             // Add ancestors from the shape
520             const TopTools_ListOfShape* pSA = aDMVFAnc.Seek (aV);
521             if (pSA && !pSA->IsEmpty())
522             {
523               TopTools_ListOfShape aLSA = *pSA;
524               aLEGA.Append (aLSA);
525             }
526           }
527
528           myMapEdgeType.Bind (aEG, BRepOffset_ListOfInterval());
529           if (aLEGA.Extent() == 2)
530           {
531             EdgeAnalyse (aEG, TopoDS::Face (aLEGA.First()), TopoDS::Face (aLEGA.Last()),
532                          aSinTol, myMapEdgeType (aEG));
533           }
534         }
535
536         // Find an edge opposite to tangential one and add ancestors for it
537         TopoDS_Edge aEOpposite;
538         for (TopExp_Explorer anExpE (aFNew, TopAbs_EDGE); anExpE.More(); anExpE.Next())
539         {
540           if (!aFNewEdgeMap.Contains (anExpE.Current()))
541           {
542             aEOpposite = TopoDS::Edge (anExpE.Current());
543             break;
544           }
545         }
546
547         {
548           // Find it in aFOpposite
549           for (TopExp_Explorer anExpE (aFToRemove, TopAbs_EDGE); anExpE.More(); anExpE.Next())
550           {
551             const TopoDS_Shape& aEInFToRem = anExpE.Current();
552             if (aE.IsSame (aEInFToRem))
553             {
554               if (BOPTools_AlgoTools::IsSplitToReverse (aEOpposite, aEInFToRem, aCtx))
555                 aEOpposite.Reverse();
556               break;
557             }
558           }
559         }
560
561         TopTools_ListOfShape aLFOpposite;
562         aLFOpposite.Append (aFNew);
563         aLFOpposite.Append (aFToRemove);
564         myAncestors.Add (aEOpposite, aLFOpposite);
565         myMapEdgeType.Bind (aEOpposite, BRepOffset_ListOfInterval());
566         EdgeAnalyse (aEOpposite, aFNew, TopoDS::Face (aFToRemove), aSinTol, myMapEdgeType (aEOpposite));
567
568         TopTools_DataMapOfShapeShape* pEEMap = myReplacement.ChangeSeek (aFToRemove);
569         if (!pEEMap)
570           pEEMap = myReplacement.Bound (aFToRemove, TopTools_DataMapOfShapeShape());
571         pEEMap->Bind (aE, aEOpposite);
572
573         // Add ancestors for the vertices
574         for (TopoDS_Iterator itV (aEOpposite); itV.More(); itV.Next())
575         {
576           const TopoDS_Shape& aV = itV.Value();
577           const TopTools_ListOfShape& aLVA = aPrismAncestors.FindFromKey (aV);
578           myAncestors.Add (aV, aLVA);
579         }
580
581         myNewFaces.Append (aFNew);
582         myGenerated.Bind (aE, aFNew);
583       }
584     }
585   }
586 }
587
588 //=======================================================================
589 //function : EdgeReplacement
590 //purpose  : 
591 //=======================================================================
592 const TopoDS_Edge& BRepOffset_Analyse::EdgeReplacement (const TopoDS_Face& theF,
593                                                         const TopoDS_Edge& theE) const
594 {
595   const TopTools_DataMapOfShapeShape* pEE = myReplacement.Seek (theF);
596   if (!pEE)
597     return theE;
598
599   const TopoDS_Shape* pE = pEE->Seek (theE);
600   if (!pE)
601     return theE;
602
603   return TopoDS::Edge (*pE);
604 }
605
606 //=======================================================================
607 //function : Generated
608 //purpose  : 
609 //=======================================================================
610 TopoDS_Shape BRepOffset_Analyse::Generated (const TopoDS_Shape& theS) const
611 {
612   static TopoDS_Shape aNullShape;
613   const TopoDS_Shape* pGenS = myGenerated.Seek (theS);
614   return pGenS ? *pGenS : aNullShape;
615 }
616
617 //=======================================================================
618 //function : Descendants
619 //purpose  : 
620 //=======================================================================
621 const TopTools_ListOfShape* BRepOffset_Analyse::Descendants (const TopoDS_Shape& theS,
622                                                              const Standard_Boolean theUpdate) const
623 {
624   if (myDescendants.IsEmpty() || theUpdate)
625   {
626     myDescendants.Clear();
627     const Standard_Integer aNbA = myAncestors.Extent();
628     for (Standard_Integer i = 1; i <= aNbA; ++i)
629     {
630       const TopoDS_Shape& aSS = myAncestors.FindKey (i);
631       const TopTools_ListOfShape& aLA = myAncestors (i);
632
633       for (TopTools_ListOfShape::Iterator it (aLA); it.More(); it.Next())
634       {
635         const TopoDS_Shape& aSA = it.Value();
636
637         TopTools_ListOfShape* pLD = myDescendants.ChangeSeek (aSA);
638         if (!pLD)
639           pLD = myDescendants.Bound (aSA, TopTools_ListOfShape());
640         if (!pLD->Contains (aSS))
641           pLD->Append (aSS);
642       }
643     }
644   }
645
646   return myDescendants.Seek (theS);
647 }
648
649 //=======================================================================
650 //function : Clear
651 //purpose  : 
652 //=======================================================================
653 void BRepOffset_Analyse::Clear()
654 {
655   myDone = Standard_False;
656   myShape     .Nullify();
657   myMapEdgeType.Clear();
658   myAncestors  .Clear();
659   myFaceOffsetMap.Clear();
660   myReplacement.Clear();
661   myDescendants.Clear();
662   myNewFaces .Clear();
663   myGenerated.Clear();
664 }
665
666 //=======================================================================
667 //function : BRepOffset_ListOfInterval&
668 //purpose  : 
669 //=======================================================================
670 const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E) const 
671 {
672   return myMapEdgeType (E);
673 }
674
675 //=======================================================================
676 //function : Edges
677 //purpose  : 
678 //=======================================================================
679 void BRepOffset_Analyse::Edges(const TopoDS_Vertex&  V, 
680                                const ChFiDS_TypeOfConcavity T,
681                                TopTools_ListOfShape& LE) const
682 {
683   LE.Clear();
684   const TopTools_ListOfShape& L = Ancestors (V);
685   TopTools_ListIteratorOfListOfShape it(L);
686   
687   for ( ;it.More(); it.Next()) {
688     const TopoDS_Edge& E = TopoDS::Edge(it.Value());
689     const BRepOffset_ListOfInterval *pIntervals = myMapEdgeType.Seek (E);
690     if (pIntervals && pIntervals->Extent() > 0)
691     {
692       TopoDS_Vertex V1,V2;
693       BRepOffset_Tool::EdgeVertices (E,V1,V2);
694       if (V1.IsSame(V)) {
695         if (pIntervals->Last().Type() == T)
696           LE.Append (E);
697       }
698       if (V2.IsSame(V)) {
699         if (pIntervals->First().Type() == T)
700           LE.Append (E);
701       }
702     }
703   }
704 }
705
706
707 //=======================================================================
708 //function : Edges
709 //purpose  : 
710 //=======================================================================
711 void BRepOffset_Analyse::Edges(const TopoDS_Face&    F, 
712                                const ChFiDS_TypeOfConcavity T,
713                                TopTools_ListOfShape& LE) const
714 {
715   LE.Clear();
716   TopExp_Explorer exp(F, TopAbs_EDGE);
717
718   for ( ;exp.More(); exp.Next()) {
719     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
720
721     const BRepOffset_ListOfInterval& Lint = Type(E);
722     BRepOffset_ListIteratorOfListOfInterval it(Lint);
723     for ( ;it.More(); it.Next()) {
724       if (it.Value().Type() == T) LE.Append(E);
725     }
726   }
727 }
728
729 //=======================================================================
730 //function : TangentEdges
731 //purpose  : 
732 //=======================================================================
733 void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge&    Edge  ,
734                                       const TopoDS_Vertex&  Vertex,
735                                       TopTools_ListOfShape& Edges  ) const 
736 {
737   gp_Vec V,VRef;
738
739   Standard_Real U,URef;
740   BRepAdaptor_Curve C3d, C3dRef;
741
742   URef   = BRep_Tool::Parameter(Vertex,Edge);
743   C3dRef = BRepAdaptor_Curve(Edge);
744   VRef   = C3dRef.DN(URef,1);
745   CorrectOrientationOfTangent(VRef, Vertex, Edge);
746   if (VRef.SquareMagnitude() < gp::Resolution()) return;
747
748   Edges.Clear();
749
750   const TopTools_ListOfShape& Anc = Ancestors(Vertex);
751   TopTools_ListIteratorOfListOfShape it(Anc);
752   for ( ; it.More(); it.Next()) {
753     const TopoDS_Edge& CurE = TopoDS::Edge(it.Value());
754     if ( CurE.IsSame(Edge)) continue;
755     U   = BRep_Tool::Parameter(Vertex,CurE);
756     C3d = BRepAdaptor_Curve(CurE);
757     V   = C3d.DN(U,1);
758     CorrectOrientationOfTangent(V, Vertex, CurE);
759     if (V.SquareMagnitude() < gp::Resolution()) continue;
760     if (V.IsOpposite(VRef,myAngle)) {
761       Edges.Append(CurE);
762     }
763   }
764 }
765
766 //=======================================================================
767 //function : Explode
768 //purpose  : 
769 //=======================================================================
770 void BRepOffset_Analyse::Explode (TopTools_ListOfShape& List,
771                                   const ChFiDS_TypeOfConcavity T) const
772 {
773   List.Clear();
774   BRep_Builder B;
775   TopTools_MapOfShape Map;
776
777   TopExp_Explorer Fexp;
778   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
779     if ( Map.Add(Fexp.Current())) {
780       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
781       TopoDS_Compound Co;
782       B.MakeCompound(Co);
783       B.Add(Co,Face);
784       // add to Co all faces from the cloud of faces
785       // G1 created from <Face>
786       AddFaces(Face,Co,Map,T);
787       List.Append(Co);
788     }
789   }
790 }
791
792 //=======================================================================
793 //function : Explode
794 //purpose  : 
795 //=======================================================================
796 void BRepOffset_Analyse::Explode (TopTools_ListOfShape& List,
797                                   const ChFiDS_TypeOfConcavity T1,
798                                   const ChFiDS_TypeOfConcavity T2) const
799 {
800   List.Clear();
801   BRep_Builder B;
802   TopTools_MapOfShape Map;
803   
804   TopExp_Explorer Fexp;
805   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
806     if ( Map.Add(Fexp.Current())) {
807       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
808       TopoDS_Compound Co;
809       B.MakeCompound(Co);
810       B.Add(Co,Face);
811       // add to Co all faces from the cloud of faces
812       // G1 created from  <Face>
813       AddFaces(Face,Co,Map,T1,T2);
814       List.Append(Co);
815     }
816   }
817 }
818
819 //=======================================================================
820 //function : AddFaces
821 //purpose  : 
822 //=======================================================================
823 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
824                                    TopoDS_Compound&      Co,
825                                    TopTools_MapOfShape&  Map,
826                                    const ChFiDS_TypeOfConcavity T) const
827 {
828   BRep_Builder B;
829   const TopTools_ListOfShape *pLE = Descendants (Face);
830   if (!pLE)
831     return;
832   for (TopTools_ListOfShape::Iterator it (*pLE); it.More(); it.Next())
833   {
834     const TopoDS_Edge& E = TopoDS::Edge (it.Value());
835     const BRepOffset_ListOfInterval& LI = Type(E);
836     if (!LI.IsEmpty() && LI.First().Type() == T) {
837       // so <NewFace> is attached to G1 by <Face>
838       const TopTools_ListOfShape& L = Ancestors(E);
839       if (L.Extent() == 2) {
840         TopoDS_Face F1 = TopoDS::Face (L.First());
841         if (F1.IsSame (Face))
842           F1 = TopoDS::Face (L.Last());
843         if (Map.Add (F1)) {
844           B.Add (Co, F1);
845           AddFaces (F1, Co, Map, T);
846         }
847       }
848     }
849   }
850 }
851
852 //=======================================================================
853 //function : AddFaces
854 //purpose  : 
855 //=======================================================================
856 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
857                                    TopoDS_Compound&      Co,
858                                    TopTools_MapOfShape&  Map,
859                                    const ChFiDS_TypeOfConcavity T1,
860                                    const ChFiDS_TypeOfConcavity T2) const
861 {
862   BRep_Builder B;
863   const TopTools_ListOfShape *pLE = Descendants (Face);
864   if (!pLE)
865     return;
866   for (TopTools_ListOfShape::Iterator it (*pLE); it.More(); it.Next())
867   {
868     const TopoDS_Edge& E = TopoDS::Edge (it.Value());
869     const BRepOffset_ListOfInterval& LI = Type(E);
870     if (!LI.IsEmpty() && 
871         (LI.First().Type() == T1 || LI.First().Type() == T2)) {
872       // so <NewFace> is attached to G1 by <Face>
873       const TopTools_ListOfShape& L = Ancestors(E);
874       if (L.Extent() == 2) {
875         TopoDS_Face F1 = TopoDS::Face (L.First());
876         if (F1.IsSame (Face))
877           F1 = TopoDS::Face (L.Last());
878         if (Map.Add (F1)) {
879           B.Add (Co, F1);
880           AddFaces (F1, Co, Map, T1, T2);
881         }
882       }
883     }
884   }
885 }