0032206: Visualization, TKOpenGl - move out OpenGL ES support to dedicated library...
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_UnifySameDomain.cxx
1 // Created on: 2012-06-09
2 // Created by: jgv@ROLEX
3 // Copyright (c) 2012-2014 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 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepLib.hxx>
20 #include <BRepLib_MakeEdge.hxx>
21 #include <BRepLib_MakeFace.hxx>
22 #include <BRepTopAdaptor_TopolTool.hxx>
23 #include <GC_MakeCircle.hxx>
24 #include <Geom2d_Line.hxx>
25 #include <GCE2d_MakeLine.hxx>
26 #include <Geom2d_TrimmedCurve.hxx>
27 #include <Geom2dConvert.hxx>
28 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
29 #include <Geom_BezierCurve.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <Geom_Circle.hxx>
32 #include <Geom_CylindricalSurface.hxx>
33 #include <Geom_ElementarySurface.hxx>
34 #include <Geom_Line.hxx>
35 #include <Geom_OffsetSurface.hxx>
36 #include <Geom_Plane.hxx>
37 #include <Geom_RectangularTrimmedSurface.hxx>
38 #include <Geom_Surface.hxx>
39 #include <Geom_SurfaceOfLinearExtrusion.hxx>
40 #include <Geom_SurfaceOfRevolution.hxx>
41 #include <Geom_SweptSurface.hxx>
42 #include <Geom_TrimmedCurve.hxx>
43 #include <GeomAdaptor_Surface.hxx>
44 #include <GeomConvert.hxx>
45 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
46 #include <GeomLib_IsPlanarSurface.hxx>
47 #include <gp_Cylinder.hxx>
48 #include <gp_Dir.hxx>
49 #include <gp_Lin.hxx>
50 #include <IntPatch_ImpImpIntersection.hxx>
51 #include <ShapeAnalysis_Edge.hxx>
52 #include <ShapeAnalysis_WireOrder.hxx>
53 #include <ShapeBuild_Edge.hxx>
54 #include <ShapeBuild_ReShape.hxx>
55 #include <ShapeFix_Edge.hxx>
56 #include <ShapeFix_Face.hxx>
57 #include <ShapeFix_Shell.hxx>
58 #include <ShapeFix_Wire.hxx>
59 #include <ShapeUpgrade_UnifySameDomain.hxx>
60 #include <Standard_Type.hxx>
61 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
62 #include <TColGeom2d_HArray1OfBSplineCurve.hxx>
63 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
64 #include <TColGeom2d_SequenceOfCurve.hxx>
65 #include <TColGeom_Array1OfBSplineCurve.hxx>
66 #include <TColGeom_HArray1OfBSplineCurve.hxx>
67 #include <TColGeom_SequenceOfSurface.hxx>
68 #include <TColStd_Array1OfReal.hxx>
69 #include <TColStd_MapOfInteger.hxx>
70 #include <TopExp.hxx>
71 #include <TopExp_Explorer.hxx>
72 #include <TopoDS.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
75 #include <TopoDS_Shape.hxx>
76 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
77 #include <TopTools_IndexedMapOfShape.hxx>
78 #include <TopTools_ListIteratorOfListOfShape.hxx>
79 #include <TopTools_MapOfShape.hxx>
80 #include <TopTools_SequenceOfShape.hxx>
81 #include <gp_Circ.hxx>
82 #include <BRepAdaptor_Curve.hxx>
83 #include <BRepAdaptor_Curve2d.hxx>
84 #include <BRepAdaptor_Surface.hxx>
85 #include <gp_Vec2d.hxx>
86 #include <Extrema_ExtPS.hxx>
87 #include <BRepTools.hxx>
88 #include <BRepTopAdaptor_FClass2d.hxx>
89 #include <ElCLib.hxx>
90 #include <BRepBuilderAPI_MakeEdge.hxx>
91 #include <BRepBuilderAPI_MakeWire.hxx>
92 #include <BRepBuilderAPI_MakeFace.hxx>
93 #include <GCPnts_AbscissaPoint.hxx>
94 #include <ElSLib.hxx>
95 #include <GeomProjLib.hxx>
96
97 IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_UnifySameDomain,Standard_Transient)
98
99 struct SubSequenceOfEdges
100 {
101   TopTools_SequenceOfShape SeqsEdges;
102   TopoDS_Edge UnionEdges;
103 };
104
105 static Standard_Real TrueValueOfOffset(const Standard_Real theValue,
106                                        const Standard_Real thePeriod)
107 {
108   if (theValue > 0.)
109     return thePeriod;
110
111   return (-thePeriod);
112 }
113
114 //=======================================================================
115 //function : UpdateBoundaries
116 //purpose  : auxilary
117 //=======================================================================
118 static void UpdateBoundaries(const Handle(Geom2d_Curve)& thePCurve,
119                              const Standard_Real         theFirst,
120                              const Standard_Real         theLast,
121                              Standard_Real& theUfirst,
122                              Standard_Real& theUlast)
123 {
124   const Standard_Integer NbSamples = 4;
125   Standard_Real Delta = (theLast - theFirst)/NbSamples;
126
127   for (Standard_Integer i = 0; i <= NbSamples; i++)
128   {
129     Standard_Real aParam = theFirst + i*Delta;
130     gp_Pnt2d aPoint = thePCurve->Value(aParam);
131     if (aPoint.X() < theUfirst)
132       theUfirst = aPoint.X();
133     if (aPoint.X() > theUlast)
134       theUlast  = aPoint.X();
135   }
136 }
137
138 static void RemoveEdgeFromMap(const TopoDS_Edge& theEdge,
139                               TopTools_IndexedDataMapOfShapeListOfShape& theVEmap)
140 {
141   TopoDS_Vertex VV [2];
142   TopExp::Vertices(theEdge, VV[0], VV[1]);
143   for (Standard_Integer i = 0; i < 2; i++)
144   {
145     TopTools_ListOfShape& Elist = theVEmap.ChangeFromKey(VV[i]);
146     TopTools_ListIteratorOfListOfShape itl(Elist);
147     while (itl.More())
148     {
149       const TopoDS_Shape& anEdge = itl.Value();
150       if (anEdge.IsSame(theEdge))
151         Elist.Remove(itl);
152       else
153         itl.Next();
154     }
155   }
156 }
157
158 static Standard_Real ComputeMinEdgeSize(const TopTools_SequenceOfShape& theEdges,
159                                         const TopoDS_Face&              theRefFace,
160                                         TopTools_MapOfShape&            theEdgesMap)
161 {
162   Standard_Real MinSize = RealLast();
163   
164   for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++)
165   {
166     const TopoDS_Edge& anEdge = TopoDS::Edge(theEdges(ind));
167     theEdgesMap.Add(anEdge);
168     TopoDS_Vertex V1, V2;
169     TopExp::Vertices(anEdge, V1, V2);
170     BRepAdaptor_Curve2d BAcurve2d(anEdge, theRefFace);
171     gp_Pnt2d FirstP2d = BAcurve2d.Value(BAcurve2d.FirstParameter());
172     gp_Pnt2d LastP2d  = BAcurve2d.Value(BAcurve2d.LastParameter());
173     Standard_Real aSqDist;
174     if (V1.IsSame(V2) &&
175         !BRep_Tool::Degenerated(anEdge))
176     {
177       gp_Pnt2d MidP2d = BAcurve2d.Value((BAcurve2d.FirstParameter()+BAcurve2d.LastParameter())/2);
178       aSqDist = FirstP2d.SquareDistance(MidP2d);
179     }
180     else
181       aSqDist = FirstP2d.SquareDistance(LastP2d);
182     if (aSqDist < MinSize)
183       MinSize = aSqDist;
184   }
185   MinSize = Sqrt(MinSize);
186   return MinSize;
187 }
188
189 static void FindFaceWithMaxUbound(const TopTools_SequenceOfShape& theFaces,
190                                   const TopoDS_Face&              theRefFace,
191                                   const TopTools_MapOfShape&      theEdgesMap,
192                                   Standard_Real&                  theUmax,
193                                   Standard_Integer&               theIndFaceMax)
194 {
195   theUmax = RealFirst();
196   theIndFaceMax = 0;
197   for (Standard_Integer ii = 1; ii <= theFaces.Length(); ii++)
198   {
199     const TopoDS_Face& face_ii = TopoDS::Face(theFaces(ii));
200     Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
201     TopExp_Explorer Explo(face_ii, TopAbs_EDGE);
202     for (; Explo.More(); Explo.Next())
203     {
204       const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
205       if (!theEdgesMap.Contains(anEdge))
206         continue;
207       Standard_Real fpar, lpar;
208       Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar);
209       UpdateBoundaries(aPCurve, fpar, lpar, Ufirst, Ulast);
210     }
211     if (Ulast > theUmax)
212     {
213       theUmax = Ulast;
214       theIndFaceMax = ii;
215     }
216   }
217 }
218
219 static void RelocatePCurvesToNewUorigin(const TopTools_SequenceOfShape& theEdges,
220                                         const TopoDS_Shape&             theFirstFace,
221                                         const TopoDS_Face&              theRefFace,
222                                         const Standard_Real             theCoordTol,
223                                         const Standard_Real             theUperiod,
224                                         TopTools_IndexedDataMapOfShapeListOfShape& theVEmap,
225                                         NCollection_DataMap<TopoDS_Shape, Handle(Geom2d_Curve)>& theEdgeNewPCurve,
226                                         TopTools_MapOfShape&      theUsedEdges)
227 {
228   TopTools_MapOfShape EdgesOfFirstFace;
229   TopExp::MapShapes(theFirstFace, EdgesOfFirstFace);
230   
231   for (;;) //walk by contours
232   {
233     //try to find the start edge that:
234     //1. belongs to outer edges of first face;
235     //2. has minimum U-coord of its start point
236     TopoDS_Edge StartEdge;
237     TopAbs_Orientation anOr = TopAbs_FORWARD;
238     Standard_Real anUmin = RealLast();
239     for (Standard_Integer ii = 1; ii <= theEdges.Length(); ii++)
240     {
241       const TopoDS_Edge& anEdge = TopoDS::Edge(theEdges(ii));
242       if (theUsedEdges.Contains(anEdge))
243         continue;
244       if (EdgesOfFirstFace.Contains(anEdge))
245       {
246         if (StartEdge.IsNull())
247         {
248           StartEdge = anEdge;
249           BRepAdaptor_Curve2d StartBAcurve(StartEdge, theRefFace);
250           Standard_Real aFirstParam, aLastParam;
251           if (StartEdge.Orientation() == TopAbs_FORWARD)
252           {
253             aFirstParam = StartBAcurve.FirstParameter();
254             aLastParam  = StartBAcurve.LastParameter();
255           }
256           else
257           {
258             aFirstParam = StartBAcurve.LastParameter();
259             aLastParam  = StartBAcurve.FirstParameter();
260           }
261           gp_Pnt2d aFirstPoint = StartBAcurve.Value(aFirstParam);
262           gp_Pnt2d aLastPoint  = StartBAcurve.Value(aLastParam);
263           if (aFirstPoint.X() < aLastPoint.X())
264           {
265             anUmin = aFirstPoint.X();
266             anOr = TopAbs_FORWARD;
267           }
268           else
269           {
270             anUmin = aLastPoint.X();
271             anOr = TopAbs_REVERSED;
272           }
273         }
274         else
275         {
276           BRepAdaptor_Curve2d aBAcurve(anEdge, theRefFace);
277           Standard_Real aFirstParam, aLastParam;
278           if (anEdge.Orientation() == TopAbs_FORWARD)
279           {
280             aFirstParam = aBAcurve.FirstParameter();
281             aLastParam  = aBAcurve.LastParameter();
282           }
283           else
284           {
285             aFirstParam = aBAcurve.LastParameter();
286             aLastParam  = aBAcurve.FirstParameter();
287           }
288           gp_Pnt2d aFirstPoint = aBAcurve.Value(aFirstParam);
289           gp_Pnt2d aLastPoint  = aBAcurve.Value(aLastParam);
290           if (aFirstPoint.X() < anUmin)
291           {
292             StartEdge = anEdge;
293             anUmin = aFirstPoint.X();
294             anOr = TopAbs_FORWARD;
295           }
296           if (aLastPoint.X() < anUmin)
297           {
298             StartEdge = anEdge;
299             anUmin = aLastPoint.X();
300             anOr = TopAbs_REVERSED;
301           }
302         }
303       } //if (EdgesOfFirstFace.Contains(anEdge))
304     } //for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
305     
306     if (StartEdge.IsNull()) //all contours are passed
307       break;
308     
309     TopoDS_Vertex StartVertex = (anOr == TopAbs_FORWARD)?
310       TopExp::FirstVertex(StartEdge, Standard_True) : TopExp::LastVertex(StartEdge, Standard_True);
311     TopoDS_Edge CurEdge = StartEdge;
312     Standard_Real fpar, lpar;
313     Handle(Geom2d_Curve) CurPCurve = BRep_Tool::CurveOnSurface(CurEdge, theRefFace, fpar, lpar);
314     CurPCurve = new Geom2d_TrimmedCurve(CurPCurve, fpar, lpar);
315     theEdgeNewPCurve.Bind(CurEdge, CurPCurve);
316     if (CurEdge.Orientation() == TopAbs_REVERSED)
317     { Standard_Real tmp = fpar; fpar = lpar; lpar = tmp; }
318     //Standard_Real StartParam = (anOr == TopAbs_FORWARD)? fpar : lpar;
319     Standard_Real CurParam = (anOr == TopAbs_FORWARD)? lpar : fpar;
320     //gp_Pnt2d StartPoint = CurPCurve->Value(StartParam);
321     gp_Pnt2d CurPoint = CurPCurve->Value(CurParam);
322     for (;;) //collect pcurves of a contour
323     {
324       RemoveEdgeFromMap(CurEdge, theVEmap);
325       theUsedEdges.Add(CurEdge);
326       TopoDS_Vertex CurVertex = (anOr == TopAbs_FORWARD)?
327         TopExp::LastVertex(CurEdge, Standard_True) : TopExp::FirstVertex(CurEdge, Standard_True);
328       
329       const TopTools_ListOfShape& Elist = theVEmap.FindFromKey(CurVertex);
330       if (Elist.IsEmpty())
331         break; //end of contour in 3d
332       
333       TopTools_ListIteratorOfListOfShape itl(Elist);
334       for (; itl.More(); itl.Next())
335       {
336         const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
337         if (anEdge.IsSame(CurEdge))
338           continue;
339         TopoDS_Vertex aFirstVertex = (anOr == TopAbs_FORWARD)?
340           TopExp::FirstVertex(anEdge, Standard_True) : TopExp::LastVertex(anEdge, Standard_True);
341         if (!aFirstVertex.IsSame(CurVertex)) //may be if CurVertex is deg.vertex
342           continue;
343         
344         Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar);
345         aPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
346         if (anEdge.Orientation() == TopAbs_REVERSED)
347         { Standard_Real tmp = fpar; fpar = lpar; lpar = tmp; }
348         Standard_Real aParam = (anOr == TopAbs_FORWARD)? fpar : lpar;
349         gp_Pnt2d aPoint = aPCurve->Value(aParam);
350         Standard_Real anOffset = CurPoint.X() - aPoint.X();
351         if (!(Abs(anOffset) < theCoordTol ||
352               Abs(Abs(anOffset) - theUperiod) < theCoordTol))
353           continue; //may be if CurVertex is deg.vertex
354         
355         if (Abs(anOffset) > theUperiod/2)
356         {
357           anOffset = TrueValueOfOffset(anOffset, theUperiod);
358           gp_Vec2d aVec(anOffset, 0.);
359           Handle(Geom2d_Curve) aNewPCurve = Handle(Geom2d_Curve)::DownCast(aPCurve->Copy());
360           aNewPCurve->Translate(aVec);
361           aPCurve = aNewPCurve;
362         }
363         theEdgeNewPCurve.Bind(anEdge, aPCurve);
364         CurEdge = anEdge;
365         TopAbs_Orientation CurOr = TopAbs::Compose(anOr, CurEdge.Orientation());
366         CurParam = (CurOr == TopAbs_FORWARD)?
367           aPCurve->LastParameter() : aPCurve->FirstParameter();
368         CurPoint = aPCurve->Value(CurParam);
369         break;
370       }
371     } //for (;;) (collect pcurves of a contour)
372   } //for (;;) (walk by contours)
373 }
374
375 static void InsertWiresIntoFaces(const TopTools_SequenceOfShape& theWires,
376                                  const TopTools_SequenceOfShape& theFaces,
377                                  const TopoDS_Face&              theRefFace)
378 {
379   BRep_Builder BB;
380   for (Standard_Integer ii = 1; ii <= theWires.Length(); ii++)
381   {
382     const TopoDS_Wire& aWire = TopoDS::Wire(theWires(ii));
383     TopoDS_Iterator iter(aWire);
384     const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
385     BRepAdaptor_Curve2d BAcurve2d(anEdge, theRefFace);
386     gp_Pnt2d aPnt2d = BAcurve2d.Value((BAcurve2d.FirstParameter() + BAcurve2d.LastParameter())/2.);
387     TopoDS_Shape RequiredFace;
388     for (Standard_Integer jj = 1; jj <= theFaces.Length(); jj++)
389     {
390       const TopoDS_Face& aFace = TopoDS::Face(theFaces(jj));
391       BRepTopAdaptor_FClass2d Classifier(aFace, Precision::Confusion());
392       TopAbs_State aStatus = Classifier.Perform(aPnt2d);
393       if (aStatus == TopAbs_IN)
394       {
395         RequiredFace = aFace.Oriented (TopAbs_FORWARD);
396         break;
397       }
398     }
399     if (!RequiredFace.IsNull())
400     {
401       BB.Add(RequiredFace, aWire);
402     }
403     else
404     {
405       Standard_ASSERT_INVOKE ("ShapeUpgrade_UnifySameDomain: wire remains unclassified");
406     }
407   }
408 }
409
410 static TopoDS_Face FindCommonFace(const TopoDS_Edge&  theEdge1,
411                                   const TopoDS_Edge&  theEdge2,
412                                   const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap,
413                                   TopAbs_Orientation& theOrOfE1OnFace,
414                                   TopAbs_Orientation& theOrOfE2OnFace)
415 {
416   TopoDS_Vertex aVertex;
417   TopExp::CommonVertex(theEdge1, theEdge2, aVertex);
418   const TopTools_ListOfShape& Flist = theVFmap.FindFromKey(aVertex);
419   TopTools_ListIteratorOfListOfShape itl(Flist);
420   for (; itl.More(); itl.Next())
421   {
422     TopoDS_Face aFace = TopoDS::Face(itl.Value());
423     aFace.Orientation(TopAbs_FORWARD);
424     Standard_Boolean e1found = Standard_False, e2found = Standard_False;
425     TopExp_Explorer Explo(aFace, TopAbs_EDGE);
426     for (; Explo.More(); Explo.Next())
427     {
428       const TopoDS_Shape& anEdge = Explo.Current();
429       if (anEdge.IsSame(theEdge1))
430       {
431         e1found = Standard_True;
432         theOrOfE1OnFace = anEdge.Orientation();
433       }
434       if (anEdge.IsSame(theEdge2))
435       {
436         e2found = Standard_True;
437         theOrOfE2OnFace = anEdge.Orientation();
438       }
439       if (e1found && e2found)
440         return aFace;
441     }
442   }
443
444   TopoDS_Face NullFace;
445   return NullFace;
446 }
447
448 static Standard_Boolean FindClosestPoints(const TopoDS_Edge& theEdge1,
449                                           const TopoDS_Edge& theEdge2,
450                                           const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap,
451                                           TopoDS_Face& theCommonFace,
452                                           Standard_Real& theMinSqDist,
453                                           TopAbs_Orientation& OrOfE1OnFace,
454                                           TopAbs_Orientation& OrOfE2OnFace,
455                                           Standard_Integer& theIndOnE1,
456                                           Standard_Integer& theIndOnE2,
457                                           gp_Pnt2d* PointsOnEdge1,
458                                           gp_Pnt2d* PointsOnEdge2)
459                                 
460 {
461   theCommonFace = FindCommonFace(theEdge1, theEdge2, theVFmap, OrOfE1OnFace, OrOfE2OnFace);
462   if (theCommonFace.IsNull())
463     return Standard_False;
464   
465   Standard_Real fpar1, lpar1, fpar2, lpar2;
466   Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(theEdge1, theCommonFace, fpar1, lpar1);
467   Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(theEdge2, theCommonFace, fpar2, lpar2);
468   PointsOnEdge1[0] = PCurve1->Value(fpar1);
469   PointsOnEdge1[1] = PCurve1->Value(lpar1);
470   PointsOnEdge2[0] = PCurve2->Value(fpar2);
471   PointsOnEdge2[1] = PCurve2->Value(lpar2);
472   theMinSqDist = RealLast();
473   theIndOnE1 = -1;
474   theIndOnE2 = -1;
475   for (Standard_Integer ind1 = 0; ind1 < 2; ind1++)
476     for (Standard_Integer ind2 = 0; ind2 < 2; ind2++)
477     {
478       Standard_Real aSqDist = PointsOnEdge1[ind1].SquareDistance(PointsOnEdge2[ind2]);
479       if (aSqDist < theMinSqDist)
480       {
481         theMinSqDist = aSqDist;
482         theIndOnE1 = ind1; theIndOnE2 = ind2;
483       }
484     }
485   return Standard_True;
486 }
487
488 //=======================================================================
489 //function : ReconstructMissedSeam
490 //purpose  : auxilary
491 //=======================================================================
492 static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
493                                   const TopTools_SequenceOfShape& theRemovedEdges,
494                                   const TopTools_MapOfShape&      theUsedEdges,
495                                   const TopoDS_Face&              theFrefFace,
496                                   const TopoDS_Vertex&            theCurVertex,
497                                   const gp_Pnt2d&                 theCurPoint,
498                                   const Standard_Real             thePeriod,
499                                   const Standard_Real             theFaceCoordMin,
500                                   const Standard_Boolean          theIsU,
501                                   const Standard_Real             theCoordTol,
502                                   TopoDS_Edge&                    theNextEdge,
503                                   TopoDS_Wire&                    theNewWire,
504                                   gp_Pnt2d&                       theNextPoint,
505                                   gp_Pnt2d&                       theStartOfNextEdge,
506                                   TopoDS_Vertex&                  theLastVertexOfSeam,
507                                   TopTools_IndexedDataMapOfShapeListOfShape& theVEmap)
508                                   
509 {
510   Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theFrefFace);
511   GeomAbs_Shape aContinuity;
512   if (theIsU)
513     aContinuity = (RefSurf->IsUPeriodic())? GeomAbs_CN : GeomAbs_C0;
514   else
515     aContinuity = (RefSurf->IsVPeriodic())? GeomAbs_CN : GeomAbs_C0;
516
517   Standard_Integer IndCoord = theIsU? 1 : 2;
518   
519   Standard_Real SeamDir = 1.; //up or right
520   if (theIsU && Abs(theCurPoint.Coord(IndCoord) - theFaceCoordMin) <= theCoordTol)
521     SeamDir = -1.; //down
522   else if (!theIsU && Abs(theCurPoint.Coord(IndCoord) - theFaceCoordMin) > theCoordTol)
523     SeamDir = -1.; //left
524
525   //Consider as the candidate to be next edge:
526   //only the edge that has first point with X(or Y)-coordinate close to X(or Y)-coordinate of theCurPoint
527   //Choose from candidates the edge that is closest to theCurPoint in the defined direction SeamDir
528   Standard_Real MinDeltaSeamCoord = RealLast();
529   for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++)
530   {
531     const TopoDS_Edge& aCandidate = TopoDS::Edge(theEdges(ind));
532     if (theUsedEdges.Contains(aCandidate))
533       continue;
534     BRepAdaptor_Curve2d BAcurve2d(aCandidate, theFrefFace);
535     Standard_Real CandParam = (aCandidate.Orientation() == TopAbs_FORWARD)?
536       BAcurve2d.FirstParameter() : BAcurve2d.LastParameter();
537     gp_Pnt2d CandPoint = BAcurve2d.Value(CandParam);
538     Standard_Real DeltaCoord = Abs(CandPoint.Coord(IndCoord) - theCurPoint.Coord(IndCoord));
539     if (DeltaCoord > theCoordTol)
540       continue;
541     
542     Standard_Real DeltaSeamCoord = CandPoint.Coord(3-IndCoord) - theCurPoint.Coord(3-IndCoord);
543     DeltaSeamCoord *= SeamDir;
544     if (DeltaSeamCoord < 0.) //on the other side from CurPoint
545       continue;
546     if (DeltaSeamCoord < MinDeltaSeamCoord)
547     {
548       MinDeltaSeamCoord = DeltaSeamCoord;
549       theNextEdge = aCandidate;
550       theStartOfNextEdge = CandPoint;
551     }
552   }
553   
554   //Build missed seam edge
555   theLastVertexOfSeam = TopExp::FirstVertex(theNextEdge, Standard_True); //with orientation
556   TopoDS_Vertex V1, V2;
557   Standard_Real Param1, Param2, aCoord = 0.;
558   Handle(Geom_Curve) Iso;
559   
560   TopoDS_Edge aRemovedEdge; //try to find it in <RemovedEdges>
561   for (Standard_Integer i = 1; i <= theRemovedEdges.Length(); i++)
562   {
563     const TopoDS_Edge& anEdge = TopoDS::Edge(theRemovedEdges(i));
564     Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(anEdge, theFrefFace, Param1, Param2);
565     if (aPC.IsNull())
566       continue;
567     
568     GeomAbs_Shape aContOnRefFace = BRep_Tool::Continuity(anEdge, theFrefFace, theFrefFace);
569     if (aContOnRefFace > aContinuity)
570       aContinuity = aContOnRefFace;
571     
572     TopoDS_Vertex aV1, aV2;
573     TopExp::Vertices(anEdge, aV1, aV2);
574     if ((aV1.IsSame(theCurVertex) && aV2.IsSame(theLastVertexOfSeam)) ||
575         (aV1.IsSame(theLastVertexOfSeam) && aV2.IsSame(theCurVertex)))
576     {
577       aRemovedEdge = anEdge;
578       break;
579     }
580   }
581   if (aRemovedEdge.IsNull())
582   {
583     Standard_Real CurTol  = BRep_Tool::Tolerance(theCurVertex);
584     Standard_Real LastTol = BRep_Tool::Tolerance(theLastVertexOfSeam);
585     aCoord = (CurTol < LastTol)? theCurPoint.Coord(IndCoord) : theStartOfNextEdge.Coord(IndCoord);
586     Iso = (theIsU)? RefSurf->UIso(aCoord) : RefSurf->VIso(aCoord);
587     if (SeamDir > 0)
588     {
589       V1 = theCurVertex; V2 = theLastVertexOfSeam;
590       Param1 = theCurPoint.Coord(3-IndCoord); Param2 = theStartOfNextEdge.Coord(3-IndCoord);
591     }
592     else
593     {
594       V1 = theLastVertexOfSeam; V2 = theCurVertex;
595       Param1 = theStartOfNextEdge.Coord(3-IndCoord); Param2 = theCurPoint.Coord(3-IndCoord);
596     }
597   }
598   else
599   {
600     TopExp::Vertices(aRemovedEdge, V1, V2);
601     Iso = BRep_Tool::Curve(aRemovedEdge, Param1, Param2);
602   }
603   
604   TopoDS_Edge MissedSeam = BRepLib_MakeEdge(Iso, V1, V2, Param1, Param2);
605   BRep_Builder BB;
606   
607   //gp_Vec2d Offset(theUperiod, 0.);
608   gp_Vec2d Offset;
609   if (theIsU)
610     Offset.SetCoord(thePeriod, 0.);
611   else
612     Offset.SetCoord(0., thePeriod);
613   if (aRemovedEdge.IsNull())
614   {
615     Standard_Real SeamCoordOrigin = 0.;
616     //Correct Param1 and Param2 if needed:
617     //when iso-curve is periodic and Param1 and Param2 do not fit into SeamCoord-range of surface,
618     //(for example, V-range of sphere)
619     //BRepLib_MakeEdge may shift Param1 and Param2
620     Standard_Real InitialParam1 = Param1, InitialParam2 = Param2;
621     Handle(Geom_Curve) MissedCurve = BRep_Tool::Curve(MissedSeam, Param1, Param2);
622     if ((Param1 != InitialParam1 || Param2 != InitialParam2) &&
623         MissedCurve->IsPeriodic())
624     {
625       //Vorigin = -(MissedCurve->Period());
626       SeamCoordOrigin = -(Param1 - InitialParam1);
627     }
628     /////////////////////////////////////
629     //Handle(Geom2d_Line) PC1 = new Geom2d_Line(gp_Pnt2d(anU, Vorigin), gp_Dir2d(0., 1.));
630     Handle(Geom2d_Line) PC1;
631     if (theIsU)
632       PC1 = new Geom2d_Line(gp_Pnt2d(aCoord, SeamCoordOrigin), gp_Dir2d(0., 1.));
633     else
634       PC1 = new Geom2d_Line(gp_Pnt2d(SeamCoordOrigin, aCoord), gp_Dir2d(1., 0.));
635     
636     Handle(Geom2d_Curve) PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy());
637     if (theIsU && SeamDir > 0)
638       Offset *= -1;
639     else if (!theIsU && SeamDir < 0)
640       Offset *= -1;
641     PC2->Translate(Offset);
642     
643     if (SeamDir > 0)
644       BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.);
645     else
646       BB.UpdateEdge(MissedSeam, PC2, PC1, theFrefFace, 0.);
647
648     if (SeamDir < 0)
649       MissedSeam.Reverse();
650   }
651   else
652   {
653     TopoDS_Edge aSeam = aRemovedEdge;
654     aSeam.Orientation(TopAbs_FORWARD);
655     Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface(aSeam, theFrefFace, Param1, Param2);
656     aSeam.Reverse();
657     Handle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(aSeam, theFrefFace, Param1, Param2);
658     Standard_Boolean IsSeam = (PC1 != PC2);
659     if (!IsSeam) //it was not a seam
660     {
661       aCoord = theCurPoint.Coord(IndCoord);
662       gp_Pnt2d PointOnRemovedEdge = PC1->Value(Param1);
663       Standard_Real CoordOfRemovededge = PointOnRemovedEdge.Coord(IndCoord);
664       if (Abs(aCoord - CoordOfRemovededge) > thePeriod/2)
665       {
666         Standard_Real Sign = (aCoord > CoordOfRemovededge)? 1 : -1;
667         Offset *= Sign;
668         PC1 = Handle(Geom2d_Curve)::DownCast(PC2->Copy());
669         PC1->Translate(Offset);
670       }
671       else
672       {
673         if (SeamDir > 0)
674           Offset *= -1;
675         PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy());
676         PC2->Translate(Offset);
677       }
678     }
679     if (theCurVertex.IsSame(V1))
680       BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.);
681     else
682     {
683       if (IsSeam)
684         BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.);
685       else
686         BB.UpdateEdge(MissedSeam, PC2, PC1, theFrefFace, 0.);
687       
688       MissedSeam.Reverse();
689     }
690   }
691
692   BB.Continuity(MissedSeam, theFrefFace, theFrefFace, aContinuity);
693   BB.Add(theNewWire, MissedSeam);
694   //add newly created edge into VEmap
695   MissedSeam.Reverse();
696   TopExp::MapShapesAndUniqueAncestors(MissedSeam, TopAbs_VERTEX, TopAbs_EDGE, theVEmap);
697                   
698   BRepAdaptor_Curve2d BAcurve2d(theNextEdge, theFrefFace);
699   Standard_Real ParamOfNextPoint = (theNextEdge.Orientation() == TopAbs_FORWARD)?
700     BAcurve2d.LastParameter() : BAcurve2d.FirstParameter();
701   theNextPoint = BAcurve2d.Value(ParamOfNextPoint);
702 }
703
704 //=======================================================================
705 //function : SameSurf
706 //purpose  : auxilary
707 //=======================================================================
708 static Standard_Boolean SameSurf(const Handle(Geom_Surface)& theS1, const Handle(Geom_Surface)& theS2)
709 {
710   static Standard_Real aCoefs[2] = { 0.3399811, 0.7745966 };
711
712   Standard_Real uf1, ul1, vf1, vl1, uf2, ul2, vf2, vl2;
713   theS1->Bounds(uf1, ul1, vf1, vl1);
714   theS2->Bounds(uf2, ul2, vf2, vl2);
715   Standard_Real aPTol = Precision::PConfusion();
716   if (Precision::IsNegativeInfinite(uf1))
717   {
718     if (!Precision::IsNegativeInfinite(uf2))
719     {
720       return Standard_False;
721     }
722     else
723     {
724       uf1 = Min(-1., (ul1 - 1.));
725     }
726   }
727   else
728   {
729     if (Precision::IsNegativeInfinite(uf2))
730     {
731       return Standard_False;
732     }
733     else
734     {
735       if (Abs(uf1 - uf2) > aPTol)
736       {
737         return Standard_False;
738       }
739     }
740   }
741   //
742   if (Precision::IsNegativeInfinite(vf1))
743   {
744     if (!Precision::IsNegativeInfinite(vf2))
745     {
746       return Standard_False;
747     }
748     else
749     {
750       vf1 = Min(-1., (vl1 - 1.));
751     }
752   }
753   else
754   {
755     if (Precision::IsNegativeInfinite(vf2))
756     {
757       return Standard_False;
758     }
759     else
760     {
761       if (Abs(vf1 - vf2) > aPTol)
762       {
763         return Standard_False;
764       }
765     }
766   }
767   //
768   if (Precision::IsPositiveInfinite(ul1))
769   {
770     if (!Precision::IsPositiveInfinite(ul2))
771     {
772       return Standard_False;
773     }
774     else
775     {
776       ul1 = Max(1., (uf1 + 1.));
777     }
778   }
779   else
780   {
781     if (Precision::IsPositiveInfinite(ul2))
782     {
783       return Standard_False;
784     }
785     else
786     {
787       if (Abs(ul1 - ul2) > aPTol)
788       {
789         return Standard_False;
790       }
791     }
792   }
793   //
794   if (Precision::IsPositiveInfinite(vl1))
795   {
796     if (!Precision::IsPositiveInfinite(vl2))
797     {
798       return Standard_False;
799     }
800     else
801     {
802       vl1 = Max(1., (vf1 + 1.));
803     }
804   }
805   else
806   {
807     if (Precision::IsPositiveInfinite(vl2))
808     {
809       return Standard_False;
810     }
811     else
812     {
813       if (Abs(vl1 - vl2) > aPTol)
814       {
815         return Standard_False;
816       }
817     }
818   }
819   //
820
821   Standard_Real u, v, du = (ul1 - uf1), dv = (vl1 - vf1);
822   Standard_Integer i, j;
823   for (i = 0; i < 2; ++i)
824   {
825     u = uf1 + aCoefs[i] * du;
826     for (j = 0; j < 2; ++j)
827     {
828       v = vf1 + aCoefs[j] * dv;
829       gp_Pnt aP1 = theS1->Value(u, v);
830       gp_Pnt aP2 = theS2->Value(u, v);
831       if (!aP1.IsEqual(aP2, aPTol))
832       {
833         return Standard_False;
834       }
835     }
836   }
837
838   return Standard_True;
839 }
840 //=======================================================================
841 //function : TransformPCurves
842 //purpose  : auxilary
843 //=======================================================================
844 static void TransformPCurves(const TopoDS_Face& theRefFace,
845                              const TopoDS_Face& theFace,
846                              TopTools_MapOfShape& theMapEdgesWithTemporaryPCurves)
847 {
848   Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theRefFace);
849   if (RefSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
850     RefSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf))->BasisSurface();
851
852   Handle(Geom_Surface) SurfFace = BRep_Tool::Surface(theFace);
853   if (SurfFace->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
854     SurfFace = (Handle(Geom_RectangularTrimmedSurface)::DownCast(SurfFace))->BasisSurface();
855
856   Standard_Boolean ToModify = Standard_False,
857     ToTranslate = Standard_False,
858     ToRotate = Standard_False,
859     X_Reverse = Standard_False,
860     Y_Reverse = Standard_False,
861     ToProject = Standard_False;
862   
863   Standard_Real aTranslation = 0., anAngle = 0.;
864
865   //Get axes of surface of face and of surface of RefFace
866   Handle(Geom_ElementarySurface) ElemSurfFace = Handle(Geom_ElementarySurface)::DownCast(SurfFace);
867   Handle(Geom_ElementarySurface) ElemRefSurf = Handle(Geom_ElementarySurface)::DownCast(RefSurf);
868
869   if (!ElemSurfFace.IsNull() && !ElemRefSurf.IsNull())
870   {
871     gp_Ax3 AxisOfSurfFace = ElemSurfFace->Position();
872     gp_Ax3 AxisOfRefSurf = ElemRefSurf->Position();
873   
874     gp_Pnt OriginRefSurf  = AxisOfRefSurf.Location();
875
876     Standard_Real aParam = ElCLib::LineParameter(AxisOfSurfFace.Axis(), OriginRefSurf);
877
878     if (Abs(aParam) > Precision::PConfusion())
879       aTranslation = -aParam;
880
881     gp_Dir VdirSurfFace = AxisOfSurfFace.Direction();
882     gp_Dir VdirRefSurf  = AxisOfRefSurf.Direction();
883     gp_Dir XdirSurfFace = AxisOfSurfFace.XDirection();
884     gp_Dir XdirRefSurf  = AxisOfRefSurf.XDirection();
885   
886     gp_Dir CrossProd1 = AxisOfRefSurf.XDirection() ^ AxisOfRefSurf.YDirection();
887     gp_Dir CrossProd2 = AxisOfSurfFace.XDirection() ^ AxisOfSurfFace.YDirection();
888     if (CrossProd1 * CrossProd2 < 0.)
889       X_Reverse = Standard_True;
890
891     Standard_Real ScalProd = VdirSurfFace * VdirRefSurf;
892     if (ScalProd < 0.)
893       Y_Reverse = Standard_True;
894
895     if (!X_Reverse && !Y_Reverse)
896     {
897       gp_Dir DirRef = VdirRefSurf;
898       if (!AxisOfRefSurf.Direct())
899         DirRef.Reverse();
900       anAngle = XdirRefSurf.AngleWithRef(XdirSurfFace, DirRef);
901     }
902     else
903       anAngle = XdirRefSurf.Angle(XdirSurfFace);
904
905     ToRotate = (Abs(anAngle) > Precision::PConfusion());
906
907     ToTranslate = (Abs(aTranslation) > Precision::PConfusion());
908
909     ToModify = ToTranslate || ToRotate || X_Reverse || Y_Reverse;
910   }
911   else
912   {
913     if (!SameSurf(RefSurf, SurfFace))
914     {
915       ToProject = Standard_True;
916     }
917   }
918
919   BRep_Builder BB;
920   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
921   for (; Explo.More(); Explo.Next())
922   {
923     const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
924     if (BRep_Tool::Degenerated(anEdge) && ToModify)
925       continue;
926     if (BRepTools::IsReallyClosed(anEdge, theFace))
927       continue;
928
929     Standard_Real fpar, lpar;
930     Handle(Geom2d_Curve) PCurveOnRef = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar);
931     if (!PCurveOnRef.IsNull() && !(ToModify || ToProject))
932       continue;
933
934     Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar);
935     Handle(Geom2d_Curve) aNewPCurve;
936     if (ToProject)
937     {
938       Handle(Geom_Curve) aC3d = BRep_Tool::Curve(anEdge, fpar, lpar);
939       aC3d = new Geom_TrimmedCurve(aC3d, fpar, lpar);
940       Standard_Real tol = BRep_Tool::Tolerance(anEdge);
941       tol = Min(tol, Precision::Approximation());
942       aNewPCurve =
943         GeomProjLib::Curve2d(aC3d, RefSurf);
944     }
945     else
946     {
947       aNewPCurve = Handle(Geom2d_Curve)::DownCast(aPCurve->Copy());
948     }
949     if (ToTranslate)
950       aNewPCurve->Translate(gp_Vec2d(0., aTranslation));
951     if (Y_Reverse)
952       aNewPCurve->Mirror(gp::OX2d());
953     if (X_Reverse)
954     {
955       aNewPCurve->Mirror(gp::OY2d());
956       aNewPCurve->Translate(gp_Vec2d(2*M_PI, 0.));
957     }
958     if (ToRotate)
959       aNewPCurve->Translate(gp_Vec2d(anAngle, 0.));
960
961     theMapEdgesWithTemporaryPCurves.Add(anEdge);
962     
963     BB.UpdateEdge(anEdge, aNewPCurve, theRefFace, 0.);
964     BB.Range(anEdge, fpar, lpar);
965   }
966 }
967                              
968 //=======================================================================
969 //function : AddPCurves
970 //purpose  : auxilary
971 //=======================================================================
972 static void AddPCurves(const TopTools_SequenceOfShape& theFaces,
973                        const TopoDS_Face&              theRefFace,
974                        TopTools_MapOfShape& theMapEdgesWithTemporaryPCurves)
975 {
976   BRepAdaptor_Surface RefBAsurf(theRefFace, Standard_False);
977
978   GeomAbs_SurfaceType aType = RefBAsurf.GetType();
979   if (aType == GeomAbs_Plane)
980     return;
981
982   for (Standard_Integer i = 1; i <= theFaces.Length(); i++)
983   {
984     TopoDS_Face aFace = TopoDS::Face(theFaces(i));
985     aFace.Orientation(TopAbs_FORWARD);
986     if (aFace.IsSame(theRefFace))
987       continue;
988
989     TransformPCurves(theRefFace, aFace, theMapEdgesWithTemporaryPCurves);
990   }
991 }
992
993 //=======================================================================
994 //function : AddOrdinaryEdges
995 //purpose  : auxilary
996 //=======================================================================
997 // adds edges from the shape to the sequence
998 // seams and equal edges are dropped
999 // Returns true if one of original edges dropped
1000 static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
1001                                          const TopoDS_Shape aShape,
1002                                          Standard_Integer& anIndex,
1003                                          TopTools_SequenceOfShape& theRemovedEdges)
1004 {
1005   //map of edges
1006   TopTools_IndexedMapOfShape aNewEdges;
1007   //add edges without seams
1008   for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
1009     TopoDS_Shape edge = exp.Current();
1010     if(aNewEdges.Contains(edge))
1011     {
1012       aNewEdges.RemoveKey(edge);
1013       theRemovedEdges.Append(edge);
1014     }
1015     else
1016       aNewEdges.Add(edge);
1017   }
1018
1019   Standard_Boolean isDropped = Standard_False;
1020   //merge edges and drop seams
1021   Standard_Integer i;
1022   for (i = 1; i <= edges.Length(); i++) {
1023     TopoDS_Shape current = edges(i);
1024     if(aNewEdges.Contains(current)) {
1025
1026       aNewEdges.RemoveKey(current);
1027       edges.Remove(i);
1028       theRemovedEdges.Append(current);
1029       i--;
1030
1031       if(!isDropped) {
1032         isDropped = Standard_True;
1033         anIndex = i;
1034       }
1035     }
1036   }
1037
1038   //add edges to the sequence
1039   for (i = 1; i <= aNewEdges.Extent(); i++)
1040     edges.Append(aNewEdges(i));
1041
1042   return isDropped;
1043 }
1044
1045 //=======================================================================
1046 //function : getCylinder
1047 //purpose  : auxilary
1048 //=======================================================================
1049 static Standard_Boolean getCylinder(Handle(Geom_Surface)& theInSurface,
1050                                     gp_Cylinder& theOutCylinder)
1051 {
1052   Standard_Boolean isCylinder = Standard_False;
1053
1054   if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
1055     Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface);
1056
1057     theOutCylinder = aGC->Cylinder();
1058     isCylinder = Standard_True;
1059   }
1060   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1061     Handle(Geom_SurfaceOfRevolution) aRS =
1062       Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface);
1063     Handle(Geom_Curve) aBasis = aRS->BasisCurve();
1064     if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) {
1065       Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis);
1066       gp_Dir aDir = aRS->Direction();
1067       gp_Dir aBasisDir = aBasisLine->Position().Direction();
1068       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
1069         // basis line is parallel to the revolution axis: it is a cylinder
1070         gp_Pnt aLoc = aRS->Location();
1071         Standard_Real aR = aBasisLine->Lin().Distance(aLoc);
1072         gp_Ax3 aCylAx (aLoc, aDir);
1073
1074         theOutCylinder = gp_Cylinder(aCylAx, aR);
1075         isCylinder = Standard_True;
1076       }
1077     }
1078   }
1079   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
1080     Handle(Geom_SurfaceOfLinearExtrusion) aLES =
1081       Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface);
1082     Handle(Geom_Curve) aBasis = aLES->BasisCurve();
1083     if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) {
1084       Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis);
1085       gp_Dir aDir = aLES->Direction();
1086       gp_Dir aBasisDir = aBasisCircle->Position().Direction();
1087       if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
1088         // basis circle is normal to the extrusion axis: it is a cylinder
1089         gp_Pnt aLoc = aBasisCircle->Location();
1090         Standard_Real aR = aBasisCircle->Radius();
1091         gp_Ax3 aCylAx (aLoc, aDir);
1092
1093         theOutCylinder = gp_Cylinder(aCylAx, aR);
1094         isCylinder = Standard_True;
1095       }
1096     }
1097   }
1098   else {
1099   }
1100
1101   return isCylinder;
1102 }
1103
1104 //=======================================================================
1105 //function : ClearRts
1106 //purpose  : auxilary
1107 //=======================================================================
1108 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
1109 {
1110   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1111     Handle(Geom_RectangularTrimmedSurface) rts =
1112       Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
1113     return rts->BasisSurface();
1114   }
1115   return aSurface;
1116 }
1117
1118 //=======================================================================
1119 //function : GetNormalToSurface
1120 //purpose  : Gets the normal to surface by the given parameter on edge.
1121 //           Returns True if normal was computed.
1122 //=======================================================================
1123 static Standard_Boolean GetNormalToSurface(const TopoDS_Face& theFace,
1124                                            const TopoDS_Edge& theEdge,
1125                                            const Standard_Real theP,
1126                                            gp_Dir& theNormal)
1127 {
1128   Standard_Real f, l;
1129   // get 2d curve to get point in 2d
1130   const Handle(Geom2d_Curve)& aC2d = BRep_Tool::CurveOnSurface(theEdge, theFace, f, l);
1131   if (aC2d.IsNull()) {
1132     return Standard_False;
1133   }
1134   //
1135   // 2d point
1136   gp_Pnt2d aP2d;
1137   aC2d->D0(theP, aP2d);
1138   //
1139   // get D1
1140   gp_Vec aDU, aDV;
1141   gp_Pnt aP3d;
1142   TopLoc_Location aLoc;
1143   const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
1144   aS->D1(aP2d.X(), aP2d.Y(), aP3d, aDU, aDV);
1145   //
1146   // compute normal
1147   gp_Vec aVNormal = aDU.Crossed(aDV);
1148   if (aVNormal.Magnitude() < Precision::Confusion()) {
1149     return Standard_False;
1150   }
1151   //
1152   if (theFace.Orientation() == TopAbs_REVERSED) {
1153     aVNormal.Reverse();
1154   }
1155   //
1156   aVNormal.Transform(aLoc.Transformation());
1157   theNormal = gp_Dir(aVNormal);
1158   return Standard_True;
1159 }
1160
1161 //=======================================================================
1162 //function : IsSameDomain
1163 //purpose  : 
1164 //=======================================================================
1165 static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
1166                                      const TopoDS_Face& aCheckedFace,
1167                                      const Standard_Real theLinTol,
1168                                      const Standard_Real theAngTol,
1169                                      ShapeUpgrade_UnifySameDomain::DataMapOfFacePlane& theFacePlaneMap)
1170 {
1171   //checking the same handles
1172   TopLoc_Location L1, L2;
1173   Handle(Geom_Surface) S1, S2;
1174
1175   S1 = BRep_Tool::Surface(aFace,L1);
1176   S2 = BRep_Tool::Surface(aCheckedFace,L2);
1177
1178   if (S1 == S2 && L1 == L2)
1179     return Standard_True;
1180
1181   S1 = BRep_Tool::Surface(aFace);
1182   S2 = BRep_Tool::Surface(aCheckedFace);
1183
1184   S1 = ClearRts(S1);
1185   S2 = ClearRts(S2);
1186
1187   //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
1188   //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
1189   //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
1190   //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
1191   //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
1192
1193   // case of two planar surfaces:
1194   // all kinds of surfaces checked, including b-spline and bezier
1195   GeomLib_IsPlanarSurface aPlanarityChecker1(S1, theLinTol);
1196   if (aPlanarityChecker1.IsPlanar()) {
1197     GeomLib_IsPlanarSurface aPlanarityChecker2(S2, theLinTol);
1198     if (aPlanarityChecker2.IsPlanar()) {
1199       gp_Pln aPln1 = aPlanarityChecker1.Plan();
1200       gp_Pln aPln2 = aPlanarityChecker2.Plan();
1201
1202       if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) &&
1203         aPln1.Distance(aPln2) < theLinTol)
1204       {
1205         Handle(Geom_Plane) aPlaneOfFaces;
1206         if (theFacePlaneMap.IsBound(aFace))
1207           aPlaneOfFaces = theFacePlaneMap(aFace);
1208         else if (theFacePlaneMap.IsBound(aCheckedFace))
1209           aPlaneOfFaces = theFacePlaneMap(aCheckedFace);
1210         else
1211           aPlaneOfFaces = new Geom_Plane(aPln1);
1212
1213         theFacePlaneMap.Bind(aFace, aPlaneOfFaces);
1214         theFacePlaneMap.Bind(aCheckedFace, aPlaneOfFaces);
1215         
1216         return Standard_True;
1217       }
1218     }
1219   }
1220
1221   // case of two elementary surfaces: use OCCT tool
1222   // elementary surfaces: ConicalSurface, CylindricalSurface,
1223   //                      Plane, SphericalSurface and ToroidalSurface
1224   if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
1225       S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1226   {
1227     Handle(GeomAdaptor_Surface) aGA1 = new GeomAdaptor_Surface(S1);
1228     Handle(GeomAdaptor_Surface) aGA2 = new GeomAdaptor_Surface(S2);
1229
1230     Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
1231     Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
1232
1233     try {
1234       IntPatch_ImpImpIntersection anIIInt(aGA1, aTT1, aGA2, aTT2, theLinTol, theLinTol);
1235       if (!anIIInt.IsDone() || anIIInt.IsEmpty())
1236         return Standard_False;
1237
1238       return anIIInt.TangentFaces();
1239     }
1240     catch (Standard_Failure const&) {
1241       return Standard_False;
1242     }
1243   }
1244
1245   // case of two cylindrical surfaces, at least one of which is a swept surface
1246   // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
1247   if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
1248        S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
1249       (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
1250        S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
1251   {
1252     gp_Cylinder aCyl1, aCyl2;
1253     if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
1254       if (fabs(aCyl1.Radius() - aCyl2.Radius()) < theLinTol) {
1255         gp_Dir aDir1 = aCyl1.Position().Direction();
1256         gp_Dir aDir2 = aCyl2.Position().Direction();
1257         if (aDir1.IsParallel(aDir2, Precision::Angular())) {
1258           gp_Pnt aLoc1 = aCyl1.Location();
1259           gp_Pnt aLoc2 = aCyl2.Location();
1260           gp_Vec aVec12 (aLoc1, aLoc2);
1261           if (aVec12.SquareMagnitude() < theLinTol*theLinTol ||
1262               aVec12.IsParallel(aDir1, Precision::Angular())) {
1263             return Standard_True;
1264           }
1265         }
1266       }
1267     }
1268   }
1269
1270   return Standard_False;
1271 }
1272
1273 //=======================================================================
1274 //function : UpdateMapOfShapes
1275 //purpose  :
1276 //=======================================================================
1277 static void UpdateMapOfShapes(TopTools_MapOfShape& theMapOfShapes,
1278                               Handle(ShapeBuild_ReShape)& theContext)
1279 {
1280   for (TopTools_MapIteratorOfMapOfShape it(theMapOfShapes); it.More(); it.Next()) {
1281     const TopoDS_Shape& aShape = it.Value();
1282     TopoDS_Shape aContextShape = theContext->Apply(aShape);
1283     if (!aContextShape.IsSame(aShape))
1284       theMapOfShapes.Add(aContextShape);
1285   }
1286 }
1287
1288 //=======================================================================
1289 //function : GlueEdgesWithPCurves
1290 //purpose  : Glues the pcurves of the sequence of edges
1291 //           and glues their 3d curves
1292 //=======================================================================
1293 static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
1294                                         const TopoDS_Vertex& FirstVertex,
1295                                         const TopoDS_Vertex& LastVertex)
1296 {
1297   Standard_Integer i, j;
1298
1299   TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
1300   TColGeom_SequenceOfSurface SurfSeq;
1301   NCollection_Sequence<TopLoc_Location> LocSeq;
1302   
1303   for (int aCurveIndex = 0;; aCurveIndex++)
1304   {
1305     Handle(Geom2d_Curve) aCurve;
1306     Handle(Geom_Surface) aSurface;
1307     TopLoc_Location aLocation;
1308     Standard_Real aFirst, aLast;
1309     BRep_Tool::CurveOnSurface (FirstEdge, aCurve, aSurface, aLocation, aFirst, aLast, aCurveIndex);
1310     if (aCurve.IsNull())
1311       break;
1312
1313     SurfSeq.Append(aSurface);
1314     LocSeq.Append(aLocation);
1315   }
1316
1317   Standard_Real fpar, lpar;
1318   BRep_Tool::Range(FirstEdge, fpar, lpar);
1319   TopoDS_Edge PrevEdge = FirstEdge;
1320   TopoDS_Vertex CV;
1321   Standard_Real MaxTol = 0.;
1322   
1323   TopoDS_Edge ResEdge;
1324   BRep_Builder BB;
1325
1326   Standard_Integer nb_curve = aChain.Length();   //number of curves
1327   TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1);                    //array of the curves
1328   TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
1329     
1330   TopoDS_Vertex PrevVertex = FirstVertex;
1331   for (i = 1; i <= nb_curve; i++)
1332   {
1333     TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
1334     TopoDS_Vertex VF, VL;
1335     TopExp::Vertices(anEdge, VF, VL);
1336     Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
1337     
1338     Standard_Real Tol1 = BRep_Tool::Tolerance(VF);
1339     Standard_Real Tol2 = BRep_Tool::Tolerance(VL);
1340     if (Tol1 > MaxTol)
1341       MaxTol = Tol1;
1342     if (Tol2 > MaxTol)
1343       MaxTol = Tol2;
1344     
1345     if (i > 1)
1346     {
1347       TopExp::CommonVertex(PrevEdge, anEdge, CV);
1348       Standard_Real Tol = BRep_Tool::Tolerance(CV);
1349       tabtolvertex(i-2) = Tol;
1350     }
1351     
1352     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
1353     Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar);
1354     tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
1355     GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion());
1356     if (ToReverse)
1357       tab_c3d(i-1)->Reverse();
1358     PrevVertex = (ToReverse)? VF : VL;
1359     PrevEdge = anEdge;
1360   }
1361   Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1362   Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1363   Standard_Boolean closed_flag = Standard_False;
1364   GeomConvert::ConcatC1(tab_c3d,
1365                         tabtolvertex,
1366                         ArrayOfIndices,
1367                         concatcurve,
1368                         closed_flag,
1369                         Precision::Confusion());   //C1 concatenation
1370   
1371   if (concatcurve->Length() > 1)
1372   {
1373     GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1374     
1375     for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1376       Concat.Add( concatcurve->Value(i), MaxTol, Standard_True );
1377     
1378     concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1379   }
1380   Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower());
1381   
1382   TColGeom2d_SequenceOfBoundedCurve ResPCurves;
1383   for (j = 1; j <= SurfSeq.Length(); j++)
1384   {
1385     TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves
1386     
1387     PrevVertex = FirstVertex;
1388     PrevEdge = FirstEdge;
1389     for (i = 1; i <= nb_curve; i++)
1390     {
1391       TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
1392       TopoDS_Vertex VF, VL;
1393       TopExp::Vertices(anEdge, VF, VL);
1394       Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
1395
1396       Handle(Geom2d_Curve) aPCurve =
1397         BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), LocSeq(j), fpar, lpar);
1398       if (aPCurve.IsNull())
1399         continue;
1400       Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
1401       tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve);
1402       Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion());
1403       if (ToReverse)
1404         tab_c2d(i-1)->Reverse();
1405       PrevVertex = (ToReverse)? VF : VL;
1406       PrevEdge = anEdge;
1407     }
1408     Handle(TColGeom2d_HArray1OfBSplineCurve)  concatc2d;     //array of the concatenated curves
1409     Handle(TColStd_HArray1OfInteger)        ArrayOfInd2d;  //array of the remining Vertex
1410     closed_flag = Standard_False;
1411     Geom2dConvert::ConcatC1(tab_c2d,
1412                             tabtolvertex,
1413                             ArrayOfInd2d,
1414                             concatc2d,
1415                             closed_flag,
1416                             Precision::Confusion());   //C1 concatenation
1417     
1418     if (concatc2d->Length() > 1)
1419     {
1420       Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower()));
1421       
1422       for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++)
1423         Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True );
1424       
1425       concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve());
1426     }
1427     Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower());
1428     ResPCurves.Append(aResPCurve);
1429   }
1430   
1431   ResEdge = BRepLib_MakeEdge(ResCurve,
1432                              FirstVertex, LastVertex,
1433                              ResCurve->FirstParameter(), ResCurve->LastParameter());
1434   BB.SameRange(ResEdge, Standard_False);
1435   BB.SameParameter(ResEdge, Standard_False);
1436   for (j = 1; j <= ResPCurves.Length(); j++)
1437   {
1438     BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), LocSeq(j), MaxTol);
1439     BB.Range(ResEdge, SurfSeq(j), LocSeq(j), ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
1440   }
1441
1442   BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
1443   
1444   return ResEdge;
1445 }
1446
1447 //=======================================================================
1448 //function : MergeSubSeq
1449 //purpose  : Merges a sequence of edges into one edge if possible
1450 //=======================================================================
1451
1452 static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& theChain,
1453                                     const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap,
1454                                     TopoDS_Edge& OutEdge, 
1455                                     double theAngTol, 
1456                                     Standard_Boolean ConcatBSplines,
1457                                     Standard_Boolean isSafeInputMode,
1458                                     Handle(ShapeBuild_ReShape)& theContext)
1459 {
1460   ShapeAnalysis_Edge sae;
1461   BRep_Builder B;
1462   // union edges in chain
1463   int j;
1464   Standard_Real fp1,lp1,fp2,lp2;
1465   Standard_Boolean IsUnionOfLinesPossible = Standard_True;
1466   Standard_Boolean IsUnionOfCirclesPossible = Standard_True;
1467   Handle(Geom_Curve) c3d1, c3d2;
1468   for(j = 1; j < theChain.Length(); j++) 
1469   {
1470     TopoDS_Edge edge1 = TopoDS::Edge(theChain.Value(j));
1471     TopoDS_Edge edge2 = TopoDS::Edge(theChain.Value(j+1));
1472
1473     if (BRep_Tool::Degenerated(edge1) &&
1474         BRep_Tool::Degenerated(edge2))
1475     {
1476       //Find the closest points in 2d
1477       TopoDS_Edge edgeFirst = TopoDS::Edge(theChain.First());
1478       TopoDS_Edge edgeLast  = TopoDS::Edge(theChain.Last());
1479       TopoDS_Face CommonFace;
1480       Standard_Real MinSqDist;
1481       TopAbs_Orientation OrOfE1OnFace, OrOfE2OnFace;
1482       Standard_Integer IndOnE1, IndOnE2;
1483       gp_Pnt2d PointsOnEdge1 [2], PointsOnEdge2 [2];
1484       if (!FindClosestPoints(edgeFirst, edgeLast, theVFmap, CommonFace,
1485                              MinSqDist, OrOfE1OnFace, OrOfE2OnFace,
1486                              IndOnE1, IndOnE2, PointsOnEdge1, PointsOnEdge2))
1487         return Standard_False;
1488       
1489       //Define indices corresponding to extremities of future edge
1490       IndOnE1 = 1 - IndOnE1;
1491       IndOnE2 = 1 - IndOnE2;
1492
1493       //Construct new degenerated edge
1494       gp_Pnt2d StartPoint = PointsOnEdge1[IndOnE1];
1495       gp_Pnt2d EndPoint   = PointsOnEdge2[IndOnE2];
1496       if ((OrOfE1OnFace == TopAbs_FORWARD  && IndOnE1 == 1) ||
1497           (OrOfE1OnFace == TopAbs_REVERSED && IndOnE1 == 0))
1498       { gp_Pnt2d Tmp = StartPoint; StartPoint = EndPoint; EndPoint = Tmp; }
1499       
1500       Handle(Geom2d_Line) aLine = GCE2d_MakeLine(StartPoint, EndPoint);
1501
1502       TopoDS_Vertex aVertex = TopExp::FirstVertex(edgeFirst);
1503       TopoDS_Vertex StartVertex = aVertex, EndVertex = aVertex;
1504       StartVertex.Orientation(TopAbs_FORWARD);
1505       EndVertex.Orientation(TopAbs_REVERSED);
1506       
1507       TopoDS_Edge NewEdge;
1508       B.MakeEdge(NewEdge);
1509       B.UpdateEdge(NewEdge, aLine, CommonFace, Precision::Confusion());
1510       B.Range(NewEdge, 0., StartPoint.Distance(EndPoint));
1511       B.Add (NewEdge, StartVertex);
1512       B.Add (NewEdge, EndVertex);
1513       B.Degenerated(NewEdge, Standard_True);
1514       OutEdge = NewEdge;
1515       return Standard_True;
1516     }
1517     
1518     c3d1 = BRep_Tool::Curve(edge1,fp1,lp1);
1519     c3d2 = BRep_Tool::Curve(edge2,fp2,lp2);
1520
1521     if(c3d1.IsNull() || c3d2.IsNull()) 
1522       return Standard_False;
1523
1524     while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1525       Handle(Geom_TrimmedCurve) tc =
1526         Handle(Geom_TrimmedCurve)::DownCast(c3d1);
1527       c3d1 = tc->BasisCurve();
1528     }
1529     while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1530       Handle(Geom_TrimmedCurve) tc =
1531         Handle(Geom_TrimmedCurve)::DownCast(c3d2);
1532       c3d2 = tc->BasisCurve();
1533     }
1534     if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
1535       Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
1536       Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
1537       gp_Dir Dir1 = L1->Position().Direction();
1538       gp_Dir Dir2 = L2->Position().Direction();
1539       if(!Dir1.IsParallel(Dir2,theAngTol))  
1540         IsUnionOfLinesPossible = Standard_False;
1541     }
1542     else
1543       IsUnionOfLinesPossible = Standard_False;
1544     if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
1545       Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
1546       Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
1547       gp_Pnt P01 = C1->Location();
1548       gp_Pnt P02 = C2->Location();
1549       if (P01.Distance(P02) > Precision::Confusion())
1550         IsUnionOfCirclesPossible = Standard_False;
1551     }
1552     else
1553       IsUnionOfCirclesPossible = Standard_False;
1554   }
1555   if (IsUnionOfLinesPossible && IsUnionOfCirclesPossible)
1556     return Standard_False;
1557
1558   //union of lines is possible
1559   if (IsUnionOfLinesPossible)
1560   {
1561     TopoDS_Vertex V[2];
1562     V[0] = sae.FirstVertex(TopoDS::Edge(theChain.First()));
1563     gp_Pnt PV1 = BRep_Tool::Pnt(V[0]);
1564     V[1] = sae.LastVertex(TopoDS::Edge(theChain.Last()));
1565     gp_Pnt PV2 = BRep_Tool::Pnt(V[1]);
1566     gp_Vec Vec(PV1, PV2);
1567     if (isSafeInputMode) {
1568       for (int k = 0; k < 2; k++) {
1569         if (!theContext->IsRecorded(V[k])) {
1570           TopoDS_Vertex Vcopy = TopoDS::Vertex(V[k].EmptyCopied());
1571           theContext->Replace(V[k], Vcopy);
1572           V[k] = Vcopy;
1573         }
1574         else
1575           V[k] = TopoDS::Vertex(theContext->Apply(V[k]));
1576       }
1577     }
1578     Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
1579     Standard_Real dist = PV1.Distance(PV2);
1580     Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
1581     TopoDS_Edge E;
1582     B.MakeEdge (E, tc ,Precision::Confusion());
1583     B.Add (E,V[0]);  B.Add (E,V[1]);
1584     B.UpdateVertex(V[0], 0., E, 0.);
1585     B.UpdateVertex(V[1], dist, E, 0.);
1586     OutEdge = E;
1587     return Standard_True;
1588   }
1589
1590   if (IsUnionOfCirclesPossible)
1591   {
1592     double f,l;
1593     TopoDS_Edge FE = TopoDS::Edge(theChain.First());
1594     Handle(Geom_Curve) c3d = BRep_Tool::Curve(FE,f,l);
1595
1596     while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1597       Handle(Geom_TrimmedCurve) tc =
1598         Handle(Geom_TrimmedCurve)::DownCast(c3d);
1599       c3d = tc->BasisCurve();
1600     }
1601     Handle(Geom_Circle) Cir = Handle(Geom_Circle)::DownCast(c3d);
1602
1603     TopoDS_Vertex V[2];
1604     V[0] = sae.FirstVertex(FE);
1605     V[1] = sae.LastVertex(TopoDS::Edge(theChain.Last()));
1606     TopoDS_Edge E;
1607     if (V[0].IsSame(V[1])) {
1608       // closed chain
1609       BRepAdaptor_Curve adef(FE);
1610       Handle(Geom_Circle) Cir1;
1611       double FP, LP;
1612       if ( FE.Orientation() == TopAbs_FORWARD)
1613       {
1614         FP = adef.FirstParameter();
1615         LP = adef.LastParameter();
1616       }
1617       else
1618       {
1619         FP = adef.LastParameter();
1620         LP = adef.FirstParameter();
1621       }
1622       if (Abs(FP) < Precision::PConfusion())
1623       {
1624         B.MakeEdge (E,Cir, Precision::Confusion());
1625         B.Add(E,V[0]);
1626         B.Add(E,V[1]);
1627         E.Orientation(FE.Orientation());
1628       }
1629       else
1630       {
1631         GC_MakeCircle MC1 (adef.Value(FP), adef.Value((FP + LP) * 0.5), adef.Value(LP));
1632         if (MC1.IsDone())
1633           Cir1 = MC1.Value();
1634         else
1635           return Standard_False;
1636         B.MakeEdge (E, Cir1, Precision::Confusion());
1637         B.Add(E,V[0]);
1638         B.Add(E,V[1]);
1639       }
1640     }
1641     else {
1642       if (isSafeInputMode) {
1643         for (int k = 0; k < 2; k++) {
1644           if (!theContext->IsRecorded(V[k])) {
1645             TopoDS_Vertex Vcopy = TopoDS::Vertex(V[k].EmptyCopied());
1646             theContext->Replace(V[k], Vcopy);
1647             V[k] = Vcopy;
1648           }
1649           else
1650             V[k] = TopoDS::Vertex(theContext->Apply(V[k]));
1651         }
1652       }
1653       gp_Pnt PV1 = BRep_Tool::Pnt(V[0]);
1654       gp_Pnt PV2 = BRep_Tool::Pnt(V[1]);
1655       TopoDS_Vertex VM = sae.LastVertex(FE);
1656       gp_Pnt PVM = BRep_Tool::Pnt(VM);
1657       GC_MakeCircle MC (PV1,PVM,PV2);
1658       Handle(Geom_Circle) C = MC.Value();
1659       gp_Pnt P0 = C->Location();
1660       gp_Dir D1(gp_Vec(P0,PV1));
1661       gp_Dir D2(gp_Vec(P0,PV2));
1662       Standard_Real fpar = C->XAxis().Direction().Angle(D1);
1663       if(fabs(fpar)>Precision::Confusion()) {
1664         // check orientation
1665         gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
1666         if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
1667           fpar = -fpar;
1668         }
1669       }
1670       Standard_Real lpar = C->XAxis().Direction().Angle(D2);
1671       if(fabs(lpar)>Precision::Confusion()) {
1672         // check orientation
1673         gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
1674         if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
1675           lpar = -lpar;
1676         }
1677       }
1678       if (lpar < fpar) lpar += 2*M_PI;
1679       Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
1680       B.MakeEdge (E,tc,Precision::Confusion());
1681       B.Add(E,V[0]);
1682       B.Add(E,V[1]);
1683       B.UpdateVertex(V[0], fpar, E, 0.);
1684       B.UpdateVertex(V[1], lpar, E, 0.);
1685     }
1686     OutEdge = E;
1687     return Standard_True;
1688   }
1689   if (theChain.Length() > 1 && ConcatBSplines) {
1690     // second step: union edges with various curves
1691     // skl for bug 0020052 from Mantis: perform such unions
1692     // only if curves are bspline or bezier
1693
1694     TopoDS_Vertex VF = sae.FirstVertex(TopoDS::Edge(theChain.First()));
1695     TopoDS_Vertex VL = sae.LastVertex(TopoDS::Edge(theChain.Last()));
1696     Standard_Boolean NeedUnion = Standard_True;
1697     for(j = 1; j <= theChain.Length(); j++) {
1698       TopoDS_Edge edge = TopoDS::Edge(theChain.Value(j));
1699       TopLoc_Location Loc;
1700       Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
1701       if(c3d.IsNull()) continue;
1702       while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1703         Handle(Geom_TrimmedCurve) tc =
1704           Handle(Geom_TrimmedCurve)::DownCast(c3d);
1705         c3d = tc->BasisCurve();
1706       }
1707       if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
1708             c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
1709       NeedUnion = Standard_False;
1710       break;
1711     }
1712     if(NeedUnion) {
1713 #ifdef OCCT_DEBUG
1714       std::cout<<"can not make analitical union => make approximation"<<std::endl;
1715 #endif
1716       TopoDS_Edge E = GlueEdgesWithPCurves(theChain, VF, VL);
1717       OutEdge = E;
1718       return Standard_True;
1719     }
1720     else {
1721 #ifdef OCCT_DEBUG
1722       std::cout<<"can not make approximation for such types of curves"<<std::endl;
1723 #endif
1724       return Standard_False;
1725     }
1726   }
1727   return Standard_False;
1728 }
1729
1730 //=======================================================================
1731 //function : IsMergingPossible
1732 //purpose  : Checks if merging of two edges is possible
1733 //=======================================================================
1734
1735 static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, 
1736                                           double theAngTol, double theLinTol, 
1737                                           const TopTools_MapOfShape& AvoidEdgeVrt, const bool theLineDirectionOk,
1738                                           const gp_Pnt& theFirstPoint, const gp_Vec& theDirectionVec,
1739                                           const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap)
1740 {
1741   Standard_Boolean IsDegE1 = BRep_Tool::Degenerated(edge1);
1742   Standard_Boolean IsDegE2 = BRep_Tool::Degenerated(edge2);
1743   
1744   if (IsDegE1 && IsDegE2)
1745   {
1746     //Find connstion point in 2d
1747     TopoDS_Face CommonFace;
1748     Standard_Real MinSqDist;
1749     TopAbs_Orientation OrOfE1OnFace, OrOfE2OnFace;
1750     Standard_Integer IndOnE1, IndOnE2;
1751     gp_Pnt2d PointsOnEdge1 [2], PointsOnEdge2 [2];
1752     if (!FindClosestPoints(edge1, edge2, theVFmap, CommonFace,
1753                            MinSqDist, OrOfE1OnFace, OrOfE2OnFace,
1754                            IndOnE1, IndOnE2, PointsOnEdge1, PointsOnEdge2))
1755       return Standard_False;
1756     
1757     if (MinSqDist <= Precision::SquareConfusion())
1758       return Standard_True;
1759     
1760     return Standard_False;
1761   }
1762   else if (IsDegE1 || IsDegE2)
1763     return Standard_False;
1764   
1765   TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True);
1766   if (CV.IsNull() || AvoidEdgeVrt.Contains(CV))
1767     return Standard_False;
1768
1769   BRepAdaptor_Curve ade1(edge1);
1770   BRepAdaptor_Curve ade2(edge2);
1771
1772   GeomAbs_CurveType t1 = ade1.GetType();
1773   GeomAbs_CurveType t2 = ade2.GetType();
1774
1775   if( t1 == GeomAbs_Circle && t2 == GeomAbs_Circle)
1776   {
1777     if (ade1.Circle().Location().Distance(ade2.Circle().Location()) > Precision::Confusion())
1778       return Standard_False;
1779   }
1780
1781   if( ( (t1 != GeomAbs_BezierCurve && t1 != GeomAbs_BSplineCurve) ||
1782       (t2 != GeomAbs_BezierCurve && t2 != GeomAbs_BSplineCurve)) && t1 != t2)
1783     return Standard_False;
1784
1785   gp_Vec Diff1, Diff2;
1786   gp_Pnt P1, P2;
1787   if (edge1.Orientation() == TopAbs_FORWARD)
1788     ade1.D1(ade1.LastParameter(), P1, Diff1);
1789   else
1790   {
1791     ade1.D1(ade1.FirstParameter(), P1, Diff1);
1792     Diff1 = -Diff1;
1793   }
1794
1795   if (edge2.Orientation() == TopAbs_FORWARD)
1796     ade2.D1(ade2.FirstParameter(), P2, Diff2);
1797   else
1798   {
1799     ade2.D1(ade2.LastParameter(), P2, Diff2);
1800     Diff2 = -Diff2;
1801   }
1802
1803   if (Diff1.Angle(Diff2) > theAngTol)
1804     return Standard_False;
1805
1806   if (theLineDirectionOk && t2 == GeomAbs_Line)
1807   {
1808     // Check that the accumulated deflection does not exceed the linear tolerance
1809     Standard_Real aLast = (edge2.Orientation() == TopAbs_FORWARD) ?
1810       ade2.LastParameter() : ade2.FirstParameter();
1811     gp_Vec aCurV(theFirstPoint, ade2.Value(aLast));
1812     Standard_Real aDD = theDirectionVec.CrossSquareMagnitude(aCurV);
1813     if (aDD > theLinTol*theLinTol)
1814       return Standard_False;
1815
1816     // Check that the accumulated angle does not exceed the angular tolerance.
1817     // For symmetry, check the angle between vectors of:
1818     // - first edge and resulting curve, and
1819     // - the last edge and resulting curve.
1820     if (theDirectionVec.Angle(aCurV) > theAngTol || Diff2.Angle(aCurV) > theAngTol)
1821       return Standard_False;
1822   }
1823
1824   return Standard_True;
1825 }
1826
1827 //=======================================================================
1828 //function : GetLineEdgePoints
1829 //purpose  : 
1830 //=======================================================================
1831 static Standard_Boolean GetLineEdgePoints(const TopoDS_Edge& theInpEdge, gp_Pnt& theFirstPoint, gp_Vec& theDirectionVec)
1832 {
1833   double f, l;
1834   Handle(Geom_Curve) aCur = BRep_Tool::Curve(theInpEdge, f, l);
1835   if(aCur.IsNull()) 
1836     return Standard_False;
1837
1838   Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur);
1839   if (!aTC.IsNull())
1840     aCur = aTC->BasisCurve();
1841
1842   if (aCur->DynamicType() != STANDARD_TYPE(Geom_Line))
1843     return Standard_False;
1844
1845   if (theInpEdge.Orientation() == TopAbs_REVERSED) {
1846     Standard_Real tmp = f;
1847     f = l;
1848     l = tmp;
1849   }
1850   theFirstPoint = aCur->Value(f);
1851   gp_Pnt aLP = aCur->Value(l);
1852   theDirectionVec = aLP.XYZ().Subtracted(theFirstPoint.XYZ());
1853   theDirectionVec.Normalize();
1854   return Standard_True;
1855 }
1856
1857 //=======================================================================
1858 //function : GenerateSubSeq
1859 //purpose  : Generates sub-sequences of edges from sequence of edges
1860 //Edges from each subsequences can be merged into the one edge  
1861 //=======================================================================
1862
1863 static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
1864                             NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
1865                             Standard_Boolean IsClosed, double theAngTol, double theLinTol, 
1866                             const TopTools_MapOfShape& AvoidEdgeVrt,
1867                             const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap)
1868 {
1869   Standard_Boolean isOk = Standard_False;
1870   TopoDS_Edge edge1, edge2;
1871
1872   SubSequenceOfEdges SubSeq;
1873   TopoDS_Edge RefEdge = TopoDS::Edge(anInpEdgeSeq(1));
1874   SubSeq.SeqsEdges.Append(RefEdge);
1875   SeqOfSubSeqOfEdges.Append(SubSeq);
1876
1877   gp_Pnt aFirstPoint;
1878   gp_Vec aDirectionVec;
1879   Standard_Boolean isLineDirectionOk = GetLineEdgePoints(RefEdge, aFirstPoint, aDirectionVec);  
1880   
1881   for (int i = 1; i < anInpEdgeSeq.Length(); i++)
1882   {
1883     edge1 = TopoDS::Edge(anInpEdgeSeq(i));
1884     edge2 = TopoDS::Edge(anInpEdgeSeq(i+1));
1885     isOk = IsMergingPossible(edge1, edge2, theAngTol, theLinTol,
1886                              AvoidEdgeVrt, isLineDirectionOk, aFirstPoint, aDirectionVec, theVFmap);
1887     if (!isOk)
1888     {
1889       SubSequenceOfEdges aSubSeq;
1890       aSubSeq.SeqsEdges.Append(edge2);
1891       SeqOfSubSeqOfEdges.Append(aSubSeq);
1892       isLineDirectionOk = GetLineEdgePoints(edge2, aFirstPoint, aDirectionVec);
1893     }
1894     else
1895       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(edge2);
1896   }
1897   /// check first and last chain segments
1898   if (IsClosed && SeqOfSubSeqOfEdges.Length() > 1)
1899   {
1900     edge1 = TopoDS::Edge(anInpEdgeSeq.Last());
1901     edge2 = TopoDS::Edge(anInpEdgeSeq.First());
1902     if (IsMergingPossible(edge1, edge2, theAngTol, theLinTol,
1903                           AvoidEdgeVrt, Standard_False, aFirstPoint, aDirectionVec, theVFmap))
1904     {
1905       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges);
1906       SeqOfSubSeqOfEdges.Remove(1);
1907     }
1908   }
1909 }
1910
1911 //=======================================================================
1912 //function : MergeEdges
1913 //purpose  : auxilary
1914 //=======================================================================
1915 static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges,
1916                                    const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap,
1917                                    const Standard_Real theAngTol,
1918                                    const Standard_Real theLinTol,
1919                                    const Standard_Boolean ConcatBSplines,
1920                                    const Standard_Boolean isSafeInputMode,
1921                                    Handle(ShapeBuild_ReShape)& theContext,
1922                                    NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
1923                                    const TopTools_MapOfShape& NonMergVrt)
1924 {
1925   TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
1926   Standard_Integer j;
1927   TopTools_MapOfShape VerticesToAvoid;
1928   const Standard_Integer aNbE = SeqEdges.Length();
1929   for (j = 1; j <= aNbE; j++)
1930   {
1931     TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j));
1932     // fill in the map V-E
1933     for (TopoDS_Iterator it(anEdge.Oriented(TopAbs_FORWARD)); it.More(); it.Next())
1934     {
1935       TopoDS_Shape aV = it.Value();
1936       if (aV.Orientation() == TopAbs_FORWARD || aV.Orientation() == TopAbs_REVERSED)
1937       {
1938         if (!aMapVE.Contains(aV))
1939           aMapVE.Add(aV, TopTools_ListOfShape());
1940         aMapVE.ChangeFromKey(aV).Append(anEdge);
1941       }
1942     }
1943   }
1944   VerticesToAvoid.Unite(NonMergVrt);
1945
1946   // do loop while there are unused edges
1947   TopTools_MapOfShape aUsedEdges;
1948
1949   for (Standard_Integer iE = 1; iE <= aNbE; ++iE)
1950   {
1951     TopoDS_Edge edge = TopoDS::Edge (SeqEdges (iE));
1952     if (!aUsedEdges.Add (edge))
1953       continue;
1954
1955     // make chain for unite
1956     TopTools_SequenceOfShape aChain;
1957     aChain.Append(edge);
1958     TopoDS_Vertex V[2];
1959     TopExp::Vertices(edge, V[0], V[1], Standard_True);
1960
1961     // connect more edges to the chain in both directions
1962     for (j = 0; j < 2; j++)
1963     {
1964       Standard_Boolean isAdded = Standard_True;
1965       while (isAdded)
1966       {
1967         isAdded = Standard_False;
1968         if (V[j].IsNull())
1969           break;
1970         const TopTools_ListOfShape& aLE = aMapVE.FindFromKey(V[j]);
1971         for (TopTools_ListIteratorOfListOfShape itL(aLE); itL.More(); itL.Next())
1972         {
1973           edge = TopoDS::Edge(itL.Value());
1974           if (!aUsedEdges.Contains(edge))
1975           {
1976             TopoDS_Vertex V2[2];
1977             TopExp::Vertices(edge, V2[0], V2[1], Standard_True);
1978             // the neighboring edge must have V[j] reversed and located on the opposite end
1979             if (V2[1 - j].IsEqual(V[j].Reversed()))
1980             {
1981               if (j == 0)
1982                 aChain.Prepend(edge);
1983               else
1984                 aChain.Append(edge);
1985               aUsedEdges.Add(edge);
1986               V[j] = V2[j];
1987               isAdded = Standard_True;
1988               break;
1989             }
1990           }
1991         }
1992       }
1993     }
1994
1995     if (aChain.Length() < 2)
1996       continue;
1997
1998     Standard_Boolean IsClosed = Standard_False;
1999     if (V[0].IsSame ( V[1] ))
2000       IsClosed = Standard_True;
2001
2002     // split chain by vertices at which merging is not possible
2003     NCollection_Sequence<SubSequenceOfEdges> aOneSeq;
2004     GenerateSubSeq(aChain, aOneSeq, IsClosed, theAngTol, theLinTol, VerticesToAvoid, theVFmap);
2005
2006     // put sub-chains in the result
2007     SeqOfSubSeqOfEdges.Append(aOneSeq);
2008   }
2009
2010   for (int i = 1; i <= SeqOfSubSeqOfEdges.Length(); i++)
2011   {
2012     TopoDS_Edge UE;
2013     if (SeqOfSubSeqOfEdges(i).SeqsEdges.Length() < 2)
2014       continue;
2015     if (MergeSubSeq(SeqOfSubSeqOfEdges(i).SeqsEdges, theVFmap,
2016                     UE, theAngTol, 
2017                     ConcatBSplines, isSafeInputMode, theContext))
2018       SeqOfSubSeqOfEdges(i).UnionEdges = UE;
2019   }
2020   return Standard_True;
2021 }
2022
2023 //=======================================================================
2024 //function : MergeSeq
2025 //purpose  : Tries to unify the sequence of edges with the set of
2026 //           another edges which lies on the same geometry
2027 //=======================================================================
2028 static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges,
2029                                   const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap,
2030                                   const Standard_Real theAngTol,
2031                                   const Standard_Real theLinTol,
2032                                   const Standard_Boolean ConcatBSplines,
2033                                   const Standard_Boolean isSafeInputMode,
2034                                   Handle(ShapeBuild_ReShape)& theContext,
2035                                   const TopTools_MapOfShape& nonMergVert)
2036 {
2037   NCollection_Sequence<SubSequenceOfEdges> SeqOfSubsSeqOfEdges;
2038   if (MergeEdges(SeqEdges, theVFmap, theAngTol, theLinTol, ConcatBSplines, isSafeInputMode,
2039                  theContext, SeqOfSubsSeqOfEdges, nonMergVert))
2040   {
2041     for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ )
2042     {
2043       if (SeqOfSubsSeqOfEdges(i).UnionEdges.IsNull())
2044         continue;
2045
2046       theContext->Merge(SeqOfSubsSeqOfEdges(i).SeqsEdges,
2047         SeqOfSubsSeqOfEdges(i).UnionEdges);
2048     }
2049     return Standard_True;
2050   }
2051   return Standard_False;
2052 }
2053
2054 //=======================================================================
2055 //function : CheckSharedVertices
2056 //purpose  : Checks the sequence of edges on the presence of shared vertex 
2057 //=======================================================================
2058
2059 static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, 
2060                                 const TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgesVertex,
2061                                 const TopTools_MapOfShape& theMapKeepShape,
2062                                 TopTools_MapOfShape& theShareVertMap)
2063 {
2064   ShapeAnalysis_Edge sae;
2065   TopTools_SequenceOfShape SeqVertexes;
2066   TopTools_MapOfShape MapVertexes;
2067   for (Standard_Integer k = 1; k <= theSeqEdges.Length(); k++ )
2068   {
2069     TopoDS_Vertex aV1 = sae.FirstVertex(TopoDS::Edge(theSeqEdges(k)));
2070     TopoDS_Vertex aV2 = sae.LastVertex(TopoDS::Edge(theSeqEdges(k)));
2071     if (!MapVertexes.Add(aV1))
2072       SeqVertexes.Append(aV1);
2073     if (!MapVertexes.Add(aV2))
2074       SeqVertexes.Append(aV2);
2075   }
2076
2077   for (Standard_Integer k = 1; k <= SeqVertexes.Length()/* && !IsSharedVertexPresent*/; k++ )
2078   {
2079     const TopTools_ListOfShape& ListEdgesV1 = theMapEdgesVertex.FindFromKey(SeqVertexes(k));
2080     if (ListEdgesV1.Extent() > 2 || theMapKeepShape.Contains(SeqVertexes(k)))
2081       theShareVertMap.Add(SeqVertexes(k));
2082   }
2083   //return theShareVertMap.IsEmpty() ? false : true;
2084 }
2085
2086 //=======================================================================
2087 //function : ShapeUpgrade_UnifySameDomain
2088 //purpose  : Constructor
2089 //=======================================================================
2090
2091 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
2092   : myLinTol(Precision::Confusion()),
2093     myAngTol(Precision::Angular()),
2094     myUnifyFaces(Standard_True),
2095     myUnifyEdges (Standard_True),
2096     myConcatBSplines (Standard_False),
2097     myAllowInternal (Standard_False),
2098     mySafeInputMode(Standard_True),
2099     myHistory(new BRepTools_History)
2100 {
2101   myContext = new ShapeBuild_ReShape;
2102 }
2103
2104 //=======================================================================
2105 //function : ShapeUpgrade_UnifySameDomain
2106 //purpose  : Constructor
2107 //=======================================================================
2108
2109 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape,
2110                                                            const Standard_Boolean UnifyEdges,
2111                                                            const Standard_Boolean UnifyFaces,
2112                                                            const Standard_Boolean ConcatBSplines)
2113   : myInitShape (aShape),
2114     myLinTol(Precision::Confusion()),
2115     myAngTol(Precision::Angular()),
2116     myUnifyFaces(UnifyFaces),
2117     myUnifyEdges (UnifyEdges),
2118     myConcatBSplines (ConcatBSplines),
2119     myAllowInternal (Standard_False),
2120     mySafeInputMode (Standard_True),
2121     myShape (aShape),
2122     myHistory(new BRepTools_History)
2123 {
2124   myContext = new ShapeBuild_ReShape;
2125 }
2126
2127 //=======================================================================
2128 //function : Initialize
2129 //purpose  : 
2130 //=======================================================================
2131
2132 void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
2133                                               const Standard_Boolean UnifyEdges,
2134                                               const Standard_Boolean UnifyFaces,
2135                                               const Standard_Boolean ConcatBSplines)
2136 {
2137   myInitShape = aShape;
2138   myShape = aShape;
2139   myUnifyEdges = UnifyEdges;
2140   myUnifyFaces = UnifyFaces;
2141   myConcatBSplines = ConcatBSplines;
2142
2143   myContext->Clear();
2144   myKeepShapes.Clear();
2145   myFacePlaneMap.Clear();
2146   myHistory->Clear();
2147 }
2148
2149 //=======================================================================
2150 //function : AllowInternalEdges
2151 //purpose  : 
2152 //=======================================================================
2153
2154 void ShapeUpgrade_UnifySameDomain::AllowInternalEdges (const Standard_Boolean theValue)
2155 {
2156   myAllowInternal = theValue;
2157 }
2158
2159 //=======================================================================
2160 //function : SetSafeInputMode
2161 //purpose  : 
2162 //=======================================================================
2163
2164 void ShapeUpgrade_UnifySameDomain::SetSafeInputMode(Standard_Boolean theValue)
2165 {
2166   mySafeInputMode = theValue;
2167 }
2168
2169 //=======================================================================
2170 //function : KeepShape
2171 //purpose  : 
2172 //=======================================================================
2173
2174 void ShapeUpgrade_UnifySameDomain::KeepShape(const TopoDS_Shape& theShape)
2175 {
2176   if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_VERTEX)
2177     myKeepShapes.Add(theShape);
2178 }
2179
2180 //=======================================================================
2181 //function : KeepShapes
2182 //purpose  : 
2183 //=======================================================================
2184
2185 void ShapeUpgrade_UnifySameDomain::KeepShapes(const TopTools_MapOfShape& theShapes)
2186 {
2187   for (TopTools_MapIteratorOfMapOfShape it(theShapes); it.More(); it.Next()) {
2188     if (it.Value().ShapeType() == TopAbs_EDGE || it.Value().ShapeType() == TopAbs_VERTEX)
2189       myKeepShapes.Add(it.Value());
2190   }
2191 }
2192
2193 //=======================================================================
2194 //function : UnifyFaces
2195 //purpose  : 
2196 //=======================================================================
2197
2198 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
2199 {
2200   // creating map of edge faces for the whole shape
2201   TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces;
2202   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces);
2203   
2204   // unify faces in each shell separately
2205   TopExp_Explorer exps;
2206   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
2207     IntUnifyFaces(exps.Current(), aGMapEdgeFaces);
2208
2209   // gather all faces out of shells in one compound and unify them at once
2210   BRep_Builder aBB;
2211   TopoDS_Compound aCmp;
2212   aBB.MakeCompound(aCmp);
2213   Standard_Integer nbf = 0;
2214   for (exps.Init(myShape, TopAbs_FACE, TopAbs_SHELL); exps.More(); exps.Next(), nbf++)
2215     aBB.Add(aCmp, exps.Current());
2216
2217   if (nbf > 0)
2218     IntUnifyFaces(aCmp, aGMapEdgeFaces);
2219   
2220   myShape = myContext->Apply(myShape);
2221 }
2222
2223 //=======================================================================
2224 //function : SetFixWireModes
2225 //purpose  : 
2226 //=======================================================================
2227
2228 static void SetFixWireModes(ShapeFix_Face& theSff)
2229 {
2230   Handle(ShapeFix_Wire) aFixWire = theSff.FixWireTool();
2231   aFixWire->FixSelfIntersectionMode() = 0;
2232   aFixWire->FixNonAdjacentIntersectingEdgesMode() = 0;
2233   aFixWire->FixLackingMode() = 0;
2234   aFixWire->FixNotchedEdgesMode() = 0;
2235   aFixWire->ModifyTopologyMode() = Standard_False;
2236   aFixWire->ModifyRemoveLoopMode() = 0;
2237   aFixWire->FixGapsByRangesMode() = Standard_False;
2238   aFixWire->FixSmallMode() = 0;
2239 }
2240
2241 //=======================================================================
2242 //function : IntUnifyFaces
2243 //purpose  : 
2244 //=======================================================================
2245
2246 void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
2247    TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces)
2248 {
2249   // creating map of edge faces for the shape
2250   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
2251   TopExp::MapShapesAndAncestors(theInpShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
2252
2253   // map of processed shapes
2254   TopTools_MapOfShape aProcessed;
2255
2256   // processing each face
2257   TopExp_Explorer exp;
2258   for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
2259     
2260     TopoDS_Face aFace = TopoDS::Face(exp.Current());
2261
2262     if (aProcessed.Contains(aFace))
2263       continue;
2264
2265     // Boundary edges for the new face
2266     TopTools_SequenceOfShape edges;
2267     TopTools_SequenceOfShape RemovedEdges;
2268
2269     Standard_Integer dummy;
2270     AddOrdinaryEdges(edges, aFace, dummy, RemovedEdges);
2271
2272     // Faces to get unified with the current faces
2273     TopTools_SequenceOfShape faces;
2274
2275     // Add the current face for unification
2276     faces.Append(aFace);
2277
2278     // surface and location to construct result
2279     TopLoc_Location aBaseLocation;
2280     Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace);
2281     aBaseSurface = ClearRts(aBaseSurface);
2282     TopAbs_Orientation RefFaceOrientation = aFace.Orientation();
2283
2284     //Take original surface
2285     TopoDS_Face RefFace;
2286     BRep_Builder BB;
2287     BB.MakeFace(RefFace, aBaseSurface, aBaseLocation, 0.);
2288     RefFace.Orientation(RefFaceOrientation);
2289     TopTools_MapOfShape MapEdgesWithTemporaryPCurves; //map of edges not lying on RefFace
2290     //these edges may be updated by temporary pcurves
2291     
2292     Standard_Real Uperiod = (aBaseSurface->IsUPeriodic())? aBaseSurface->UPeriod() : 0.;
2293     Standard_Real Vperiod = (aBaseSurface->IsVPeriodic())? aBaseSurface->VPeriod() : 0.;
2294
2295     // find adjacent faces to union
2296     Standard_Integer i;
2297     for (i = 1; i <= edges.Length(); i++) {
2298       TopoDS_Edge edge = TopoDS::Edge(edges(i));
2299       if (BRep_Tool::Degenerated(edge))
2300         continue;
2301
2302       // get connectivity of the edge in the global shape
2303       const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge);
2304       if (!myAllowInternal && (aGList.Extent() != 2 || myKeepShapes.Contains(edge))) {
2305         // non manifold case is not processed unless myAllowInternal
2306         continue;
2307       }
2308       //
2309       // Get the faces connected through the edge in the current shape
2310       const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
2311       if (aList.Extent() < 2) {
2312         continue;
2313       }
2314
2315       // for a planar face create and store pcurve of edge on face
2316       // to speed up all operations
2317       if (!mySafeInputMode && aBaseSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
2318         BRepLib::BuildPCurveForEdgeOnPlane(edge, aFace);
2319
2320       // get normal of the face to compare it with normals of other faces
2321       gp_Dir aDN1;
2322       //
2323       // take intermediate point on edge to compute the normal
2324       Standard_Real f, l;
2325       BRep_Tool::Range(edge, f, l);
2326       Standard_Real aTMid = (f + l) * .5;
2327       //
2328       Standard_Boolean bCheckNormals = GetNormalToSurface(aFace, edge, aTMid, aDN1);
2329       //
2330       // Process the faces
2331       TopTools_ListIteratorOfListOfShape anIter(aList);
2332       for (; anIter.More(); anIter.Next()) {
2333         
2334         TopoDS_Face aCheckedFace = TopoDS::Face(anIter.Value());
2335         if (aCheckedFace.IsSame(aFace))
2336           continue;
2337
2338         if (aProcessed.Contains(aCheckedFace))
2339           continue;
2340
2341         if (bCheckNormals) {
2342           // get normal of checked face using the same parameter on edge
2343           gp_Dir aDN2;
2344           if (GetNormalToSurface(aCheckedFace, edge, aTMid, aDN2)) {
2345             // and check if the adjacent faces are having approximately same normals
2346             Standard_Real anAngle = aDN1.Angle(aDN2);
2347             if (anAngle > myAngTol) {
2348               continue;
2349             }
2350           }
2351         }
2352         //
2353         if (IsSameDomain(aFace,aCheckedFace, myLinTol, myAngTol, myFacePlaneMap)) {
2354
2355           if (AddOrdinaryEdges(edges, aCheckedFace, dummy, RemovedEdges)) {
2356             // sequence edges is modified
2357             i = dummy;
2358           }
2359
2360           faces.Append(aCheckedFace);
2361           aProcessed.Add(aCheckedFace);
2362           break;
2363         }
2364       }
2365     }
2366
2367     if (faces.Length() > 1) {
2368       if (myFacePlaneMap.IsBound(faces(1)))
2369       {
2370         const Handle(Geom_Plane)& aPlane = myFacePlaneMap(faces(1));
2371         TopLoc_Location aLoc;
2372         BB.UpdateFace(RefFace, aPlane, aLoc, Precision::Confusion());
2373       }
2374       //Add correct pcurves for the reference surface to the edges of other faces
2375       TopoDS_Face F_RefFace = RefFace;
2376       F_RefFace.Orientation(TopAbs_FORWARD);
2377       AddPCurves(faces, F_RefFace, MapEdgesWithTemporaryPCurves);
2378       
2379       // fill in the connectivity map for selected faces
2380       TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
2381       for (i = 1; i <= faces.Length(); i++) {
2382         TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
2383       }
2384       // Collect keep edges and multi-connected edges, i.e. edges that are internal to
2385       // the set of selected faces and have connections to other faces.
2386       TopTools_ListOfShape aKeepEdges;
2387       for (i = 1; i <= aMapEF.Extent(); i++) {
2388         const TopTools_ListOfShape& aLF = aMapEF(i);
2389         if (aLF.Extent() == 2) {
2390           const TopoDS_Shape& aE = aMapEF.FindKey(i);
2391           const TopTools_ListOfShape& aGLF = theGMapEdgeFaces.FindFromKey(aE);
2392           if (aGLF.Extent() > 2 || myKeepShapes.Contains(aE)) {
2393             aKeepEdges.Append(aE);
2394           }
2395         }
2396       } 
2397       if (!aKeepEdges.IsEmpty()) {
2398         if  (!myAllowInternal) {
2399           // Remove from the selection the faces which have no other connect edges 
2400           // and contain multi-connected edges and/or keep edges.
2401           TopTools_MapOfShape anAvoidFaces;
2402           TopTools_ListIteratorOfListOfShape it(aKeepEdges);
2403           for (; it.More(); it.Next()) {
2404             const TopoDS_Shape& aE = it.Value();
2405             const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
2406             anAvoidFaces.Add(aLF.First());
2407             anAvoidFaces.Add(aLF.Last());
2408           }
2409           for (i = 1; i <= faces.Length(); i++) {
2410             if (anAvoidFaces.Contains(faces(i))) {
2411               // update the boundaries of merged area, for that
2412               // remove from 'edges' the edges of this face and add to 'edges' 
2413               // the edges of this face that were not present in 'edges' before
2414               Standard_Boolean hasConnectAnotherFaces = Standard_False;
2415               TopExp_Explorer ex(faces(i), TopAbs_EDGE);
2416               for (; ex.More() && !hasConnectAnotherFaces; ex.Next()) {
2417                 TopoDS_Shape aE = ex.Current();
2418                 const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
2419                 if (aLF.Extent() > 1) {
2420                   for (it.Init(aLF); it.More() && !hasConnectAnotherFaces; it.Next()) {
2421                     if (!anAvoidFaces.Contains(it.Value()))
2422                       hasConnectAnotherFaces = Standard_True;
2423                   }
2424                 }
2425               }
2426               if (!hasConnectAnotherFaces) {
2427                 AddOrdinaryEdges(edges, faces(i), dummy, RemovedEdges);
2428                 faces.Remove(i);
2429                 i--;
2430               }
2431             }
2432           }
2433           // check if the faces with keep edges contained in 
2434           // already updated the boundaries of merged area
2435           if (!faces.IsEmpty()) {
2436             TopTools_MapOfShape aMapFaces;
2437             for (i = 1; i <= faces.Length(); i++) {
2438               aMapFaces.Add(faces(i));
2439             }
2440             for (it.Init(aKeepEdges); it.More(); it.Next()) {
2441               const TopoDS_Shape& aE = it.Value();
2442               const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
2443               if (aLF.Extent() < 2)
2444                 continue;
2445               if (aMapFaces.Contains(aLF.First()) && 
2446                   aMapFaces.Contains(aLF.Last())) {
2447                 for (i = 1; i <= faces.Length(); i++) {
2448                   if (faces(i).IsEqual(aLF.First()) ||
2449                       faces(i).IsEqual(aLF.Last())) {
2450                     AddOrdinaryEdges(edges, faces(i), dummy, RemovedEdges);
2451                     faces.Remove(i);
2452                     i--;
2453                   }
2454                 }
2455               }
2456             }
2457           }
2458         } //if (!myAllowInternal)
2459         else { //internal edges are allowed
2460           // add multi-connected and keep edges as internal in new face
2461           TopTools_ListIteratorOfListOfShape it(aKeepEdges);
2462           for (; it.More(); it.Next()) {
2463             const TopoDS_Shape& aE = it.Value();
2464             edges.Append(aE.Oriented(TopAbs_INTERNAL));
2465           }
2466         }
2467       } //if (!aKeepEdges.IsEmpty())
2468     } //if (faces.Length() > 1)
2469
2470     TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
2471     for (i = 1; i <= faces.Length(); i++)
2472       TopExp::MapShapesAndUniqueAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
2473     
2474     //Correct orientation of edges
2475     for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
2476     {
2477       const TopoDS_Shape& anEdge = edges (ii);
2478       Standard_Integer indE = aMapEF.FindIndex (anEdge);
2479       const TopTools_ListOfShape& aLF = aMapEF (indE);
2480       if (myAllowInternal &&
2481           myKeepShapes.Contains(anEdge) &&
2482           aLF.Extent() == 2)
2483         edges(ii).Orientation(TopAbs_INTERNAL);
2484       
2485       if (anEdge.Orientation() != TopAbs_INTERNAL)
2486         edges (ii) = aMapEF.FindKey (indE);
2487     }
2488
2489     //Exclude internal edges
2490     TopTools_IndexedMapOfShape InternalEdges;
2491     Standard_Integer ind_e = 1;
2492     while (ind_e <= edges.Length())
2493     {
2494       const TopoDS_Shape& anEdge = edges(ind_e);
2495       if (anEdge.Orientation() == TopAbs_INTERNAL)
2496       {
2497         InternalEdges.Add(anEdge);
2498         edges.Remove(ind_e);
2499       }
2500       else
2501         ind_e++;
2502     }    
2503
2504     if (RefFaceOrientation == TopAbs_REVERSED)
2505       for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
2506         edges(ii).Reverse();
2507     TopoDS_Face F_RefFace = RefFace;
2508     F_RefFace.Orientation(TopAbs_FORWARD);
2509     
2510     // all faces collected in the sequence. Perform union of faces
2511     if (faces.Length() > 1)
2512     {
2513       Standard_Real CoordTol = Precision::Confusion();
2514       TopTools_MapOfShape edgesMap;
2515       CoordTol = ComputeMinEdgeSize(edges, F_RefFace, edgesMap);
2516       CoordTol /= 10.;
2517       CoordTol = Max(CoordTol, Precision::Confusion());
2518
2519       TopTools_IndexedDataMapOfShapeListOfShape VEmap;
2520       for (Standard_Integer ind = 1; ind <= edges.Length(); ind++)
2521         TopExp::MapShapesAndUniqueAncestors(edges(ind), TopAbs_VERTEX, TopAbs_EDGE, VEmap);
2522       
2523       //Perform relocating to new U-origin
2524       //Define boundaries in 2d space of RefFace
2525       if (Uperiod != 0.)
2526       {
2527         //try to find a real seam edge - if it exists, do nothing
2528         Standard_Boolean SeamFound = Standard_False;
2529         for (Standard_Integer ii = 1; ii <= faces.Length(); ii++)
2530         {
2531           const TopoDS_Face& face_ii = TopoDS::Face(faces(ii));
2532           TopoDS_Wire anOuterWire = BRepTools::OuterWire(face_ii);
2533           TopoDS_Iterator itw(anOuterWire);
2534           for (; itw.More(); itw.Next())
2535           {
2536             const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2537             if (BRepTools::IsReallyClosed(anEdge, face_ii))
2538             {
2539               SeamFound = Standard_True;
2540               break;
2541             }
2542           }
2543         }
2544         
2545         if (!SeamFound)
2546         {
2547           //try to find the origin of U in 2d space
2548           //so that all the faces are in [origin, origin + Uperiod]
2549           Standard_Real Umax;
2550           Standard_Integer i_face_max;
2551           FindFaceWithMaxUbound(faces, F_RefFace, edgesMap, Umax, i_face_max);
2552           
2553           TopTools_MapOfShape UsedEdges;
2554           NCollection_DataMap<TopoDS_Shape, Handle(Geom2d_Curve)> EdgeNewPCurve;
2555
2556           //Relocate pcurves to new U-origin
2557           RelocatePCurvesToNewUorigin(edges, faces(i_face_max), F_RefFace, CoordTol, Uperiod,
2558                                       VEmap, EdgeNewPCurve, UsedEdges);
2559
2560           //PCurves from unused edges (may be degenerated edges)
2561           for (Standard_Integer ind = 1; ind <= edges.Length(); ind++)
2562           {
2563             const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ind));
2564             if (!UsedEdges.Contains(anEdge))
2565             {
2566               Standard_Real fpar, lpar;
2567               Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar);
2568               aPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
2569               EdgeNewPCurve.Bind(anEdge, aPCurve);
2570             }
2571           }
2572           
2573           //Restore VEmap
2574           VEmap.Clear();
2575           for (Standard_Integer ind = 1; ind <= edges.Length(); ind++)
2576             TopExp::MapShapesAndUniqueAncestors(edges(ind), TopAbs_VERTEX, TopAbs_EDGE, VEmap);
2577
2578           //Find NewUmin and NewUmax
2579           Standard_Real NewUmin = RealLast(), NewUmax = RealFirst();
2580           for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
2581           {
2582             const Handle(Geom2d_Curve)& aPCurve = EdgeNewPCurve(edges(ii));
2583             UpdateBoundaries(aPCurve, aPCurve->FirstParameter(), aPCurve->LastParameter(),
2584                              NewUmin, NewUmax);
2585           }
2586           
2587           if (NewUmax - NewUmin < Uperiod - CoordTol &&
2588               !(-Precision::Confusion() < NewUmin && NewUmin < Uperiod+Precision::Confusion() &&
2589                 -Precision::Confusion() < NewUmax && NewUmax < Uperiod+Precision::Confusion()))
2590           {
2591             //we can build a face without seam edge:
2592             //update the edges with earlier computed relocated pcurves
2593             //fitting into (NewUorigin, NewUorigin + Uperiod)
2594             Standard_Real umin, umax, vmin, vmax;
2595             aBaseSurface->Bounds(umin, umax, vmin, vmax);
2596             Standard_Real RestSpaceInU = Uperiod - (NewUmax - NewUmin);
2597             Standard_Real NewUorigin = NewUmin - RestSpaceInU/2;
2598             if (NewUorigin < umin)
2599               NewUorigin = umin;
2600             Handle(Geom_Surface) NewSurf;
2601             if (NewUorigin == umin)
2602               NewSurf = aBaseSurface;
2603             else
2604               NewSurf = new Geom_RectangularTrimmedSurface(aBaseSurface,
2605                                                            NewUorigin, NewUorigin + Uperiod,
2606                                                            Standard_True); //trim U
2607             TopoDS_Face OldRefFace = RefFace;
2608             Handle(Geom2d_Curve) NullPCurve;
2609             RefFace.Nullify();
2610             BB.MakeFace(RefFace, NewSurf, aBaseLocation, 0.);
2611             for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
2612             {
2613               TopoDS_Edge anEdge = TopoDS::Edge(edges(ii));
2614               if (MapEdgesWithTemporaryPCurves.Contains(anEdge))
2615                 BB.UpdateEdge(anEdge, NullPCurve, OldRefFace, 0.);
2616               const Handle(Geom2d_Curve)& aPCurve = EdgeNewPCurve(anEdge);
2617               BB.UpdateEdge(anEdge, aPCurve, RefFace, 0.);
2618             }
2619           }
2620         } //if (!SeamFound)
2621       } //if (Uperiod != 0.)
2622       ////////////////////////////////////
2623       F_RefFace = RefFace;
2624       F_RefFace.Orientation(TopAbs_FORWARD);
2625       
2626       TopTools_SequenceOfShape NewFaces, NewWires;
2627       
2628       if (Uperiod == 0 || Vperiod == 0)
2629       {
2630         //Set the "periods" for closed non-periodic surface
2631         TopLoc_Location aLoc;
2632         Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc);
2633         if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
2634           aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface();
2635         Standard_Real Ufirst, Ulast, Vfirst, Vlast;
2636         aSurf->Bounds(Ufirst, Ulast, Vfirst, Vlast);
2637         if (Uperiod == 0 && aSurf->IsUClosed())
2638           Uperiod = Ulast - Ufirst;
2639         if (Vperiod == 0 && aSurf->IsVClosed())
2640           Vperiod = Vlast - Vfirst;
2641       }
2642
2643       TopTools_MapOfShape UsedEdges;
2644
2645       Standard_Real FaceUmin = RealLast();
2646       Standard_Real FaceVmin = RealLast();
2647       for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
2648       {
2649         const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ii));
2650         BRepAdaptor_Curve2d aBAcurve(anEdge, F_RefFace);
2651         gp_Pnt2d aFirstPoint = aBAcurve.Value(aBAcurve.FirstParameter());
2652         gp_Pnt2d aLastPoint  = aBAcurve.Value(aBAcurve.LastParameter());
2653         
2654         if (aFirstPoint.X() < FaceUmin)
2655           FaceUmin = aFirstPoint.X();
2656         if (aLastPoint.X() < FaceUmin)
2657           FaceUmin = aLastPoint.X();
2658         
2659         if (aFirstPoint.Y() < FaceVmin)
2660           FaceVmin = aFirstPoint.Y();
2661         if (aLastPoint.Y() < FaceVmin)
2662           FaceVmin = aLastPoint.Y();
2663       }
2664
2665       //Building new wires from <edges>
2666       //and build faces
2667       while (!edges.IsEmpty())
2668       {
2669         //try to find non-degenerated edge
2670         TopoDS_Edge StartEdge = TopoDS::Edge(edges(1));
2671         Standard_Integer istart = 1;
2672         while (BRep_Tool::Degenerated(StartEdge) &&
2673                istart < edges.Length())
2674         {
2675           istart++;
2676           StartEdge = TopoDS::Edge(edges(istart));
2677         }
2678
2679         TopoDS_Wire aNewWire;
2680         BB.MakeWire(aNewWire);
2681         BB.Add(aNewWire, StartEdge);
2682         RemoveEdgeFromMap(StartEdge, VEmap);
2683         
2684         Standard_Real fpar, lpar;
2685         Handle(Geom2d_Curve) StartPCurve = BRep_Tool::CurveOnSurface(StartEdge, F_RefFace, fpar, lpar);
2686         TopoDS_Vertex StartVertex, CurVertex;
2687         TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True); //with orientation
2688         Standard_Real StartParam, CurParam;
2689         if (StartEdge.Orientation() == TopAbs_FORWARD)
2690         {
2691           StartParam = fpar; CurParam = lpar;
2692         }
2693         else
2694         {
2695           StartParam = lpar; CurParam = fpar;
2696         }
2697         gp_Pnt2d StartPoint = StartPCurve->Value(StartParam);
2698         gp_Pnt2d CurPoint   = StartPCurve->Value(CurParam);
2699         
2700         TopoDS_Edge CurEdge = StartEdge;
2701         for (;;) //loop till the end of current new wire
2702         {
2703           TopoDS_Edge NextEdge;
2704           gp_Pnt2d NextPoint;
2705           
2706           const TopTools_ListOfShape& Elist = VEmap.FindFromKey(CurVertex);
2707           TopTools_ListIteratorOfListOfShape itl(Elist);
2708           if (Elist.IsEmpty())
2709           {
2710             if (CurVertex.IsSame(StartVertex))
2711             {
2712               //Points of two vertices coincide in 3d but may be not in 2d
2713               if (Uperiod != 0. &&
2714                   Abs(StartPoint.X() - CurPoint.X()) > Uperiod/2) //end of parametric space
2715               {
2716                 //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
2717                 gp_Pnt2d StartOfNextEdge;
2718                 TopoDS_Vertex LastVertexOfSeam;
2719                 ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
2720                                       CurPoint, Uperiod, FaceUmin, Standard_True, CoordTol,
2721                                       NextEdge, aNewWire, NextPoint,
2722                                       StartOfNextEdge, LastVertexOfSeam, VEmap);
2723               }
2724               else if (Vperiod != 0. &&
2725                        Abs(StartPoint.Y() - CurPoint.Y()) > Vperiod/2) //end of parametric space
2726               {
2727                 //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
2728                 gp_Pnt2d StartOfNextEdge;
2729                 TopoDS_Vertex LastVertexOfSeam;
2730                 ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
2731                                       CurPoint, Vperiod, FaceVmin, Standard_False, CoordTol,
2732                                       NextEdge, aNewWire, NextPoint,
2733                                       StartOfNextEdge, LastVertexOfSeam, VEmap);
2734               }
2735               else
2736               {
2737                 break; //end of wire
2738               }
2739             }
2740           }
2741           
2742           if (NextEdge.IsNull())
2743           {
2744             Standard_Boolean EndOfWire = Standard_False;
2745             
2746             TopTools_ListOfShape TmpElist, TrueElist;
2747             //<TrueElist> will be the list of candidates to become <NextEdge>
2748             for (itl.Initialize(Elist); itl.More(); itl.Next())
2749             {
2750               const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2751               if (UsedEdges.Contains(anEdge))
2752                 continue;
2753               TopoDS_Vertex aFirstVertex = TopExp::FirstVertex(anEdge, Standard_True);
2754               if (!aFirstVertex.IsSame(CurVertex))
2755                 continue;
2756               TmpElist.Append(anEdge);
2757             }
2758             if (TmpElist.Extent() <= 1 ||
2759                 (Uperiod != 0. || Vperiod != 0))
2760               TrueElist.Assign(TmpElist);
2761             else
2762             {
2763               //we must choose the closest direction - the biggest angle
2764               Standard_Real MaxAngle = RealFirst();
2765               TopoDS_Edge TrueEdge;
2766               Handle(Geom2d_Curve) CurPCurve = BRep_Tool::CurveOnSurface(CurEdge, F_RefFace, fpar, lpar);
2767               CurParam = (CurEdge.Orientation() == TopAbs_FORWARD)? lpar : fpar;
2768               gp_Vec2d CurDir;
2769               CurPCurve->D1(CurParam, CurPoint, CurDir);
2770               CurDir.Normalize();
2771               if (CurEdge.Orientation() == TopAbs_REVERSED)
2772                 CurDir.Reverse();
2773               for (itl.Initialize(TmpElist); itl.More(); itl.Next())
2774               {
2775                 const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2776                 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar);
2777                 Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar;
2778                 gp_Pnt2d aPoint;
2779                 gp_Vec2d aDir;
2780                 aPCurve->D1(aParam, aPoint, aDir);
2781                 aDir.Normalize();
2782                 if (anEdge.Orientation() == TopAbs_REVERSED)
2783                   aDir.Reverse();
2784                 Standard_Real anAngle = CurDir.Angle(aDir);
2785                 if (anAngle > MaxAngle)
2786                 {
2787                   MaxAngle = anAngle;
2788                   TrueEdge = anEdge;
2789                 }
2790               }
2791               TrueElist.Append(TrueEdge);
2792             }
2793
2794             //Find next edge in TrueElist
2795             for (itl.Initialize(TrueElist); itl.More(); itl.Next())
2796             {
2797               const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2798               
2799               Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar);
2800               Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar;
2801               gp_Pnt2d aPoint = aPCurve->Value(aParam);
2802               Standard_Real DiffU = Abs(aPoint.X() - CurPoint.X());
2803               Standard_Real DiffV = Abs(aPoint.Y() - CurPoint.Y());
2804               if (Uperiod != 0. &&
2805                   DiffU > CoordTol &&
2806                   Abs(DiffU - Uperiod) > CoordTol) //may be is is a deg.vertex
2807                 continue;
2808               if (Vperiod != 0. &&
2809                   DiffV > CoordTol &&
2810                   Abs(DiffV - Vperiod) > CoordTol) //may be is is a deg.vertex
2811                 continue;
2812               
2813               //Check: may be <CurPoint> and <aPoint> are on Period from each other
2814               if (Uperiod != 0. && DiffU > Uperiod/2) //end of parametric space
2815               {
2816                 //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
2817                 gp_Pnt2d StartOfNextEdge;
2818                 TopoDS_Vertex LastVertexOfSeam;
2819                 ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
2820                                       CurPoint, Uperiod, FaceUmin, Standard_True, CoordTol,
2821                                       NextEdge, aNewWire, NextPoint,
2822                                       StartOfNextEdge, LastVertexOfSeam, VEmap);
2823                 
2824                 //Check: may be it is the end
2825                 if (LastVertexOfSeam.IsSame(StartVertex) &&
2826                     Abs(StartPoint.X() - StartOfNextEdge.X()) < Uperiod/2)
2827                   EndOfWire = Standard_True;
2828                 
2829                 break;
2830               } //if (Uperiod != 0. && Abs(aPoint.X() - CurPoint.X()) > Uperiod/2)
2831               else if (Vperiod != 0. && DiffV > Vperiod/2) //end of parametric space
2832               {
2833                 //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
2834                 gp_Pnt2d StartOfNextEdge;
2835                 TopoDS_Vertex LastVertexOfSeam;
2836                 ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
2837                                       CurPoint, Vperiod, FaceVmin, Standard_False, CoordTol,
2838                                       NextEdge, aNewWire, NextPoint,
2839                                       StartOfNextEdge, LastVertexOfSeam, VEmap);
2840                 
2841                 //Check: may be it is the end
2842                 if (LastVertexOfSeam.IsSame(StartVertex) &&
2843                     Abs(StartPoint.Y() - StartOfNextEdge.Y()) < Vperiod/2)
2844                   EndOfWire = Standard_True;
2845                 
2846                 break;
2847               }
2848               else
2849               {
2850                 NextEdge = anEdge;
2851                 Standard_Real LastParam = (NextEdge.Orientation() == TopAbs_FORWARD)? lpar : fpar;
2852                 NextPoint = aPCurve->Value(LastParam);
2853                 break;
2854               }
2855             } //for (itl.Initialize(TrueElist); itl.More(); itl.Next())
2856             
2857             if (EndOfWire)
2858               break;
2859           }
2860           
2861           if (NextEdge.IsNull())
2862           {
2863             //throw Standard_ConstructionError("Construction of unified wire failed: no proper edge found");
2864             return;
2865           }
2866           else
2867           {
2868             CurPoint = NextPoint;
2869             CurEdge = NextEdge;
2870             CurVertex = TopExp::LastVertex(CurEdge, Standard_True); //with orientation
2871             BB.Add(aNewWire, CurEdge);
2872             UsedEdges.Add(CurEdge);
2873             RemoveEdgeFromMap(CurEdge, VEmap);
2874           }
2875         } //for (;;)
2876         aNewWire.Closed(Standard_True);
2877         UsedEdges.Add(StartEdge);
2878         
2879         //Remove used edges from sequence
2880         Standard_Integer ind = 1;
2881         while (ind <= edges.Length())
2882         {
2883           if (UsedEdges.Contains(edges(ind)))
2884             edges.Remove(ind);
2885           else
2886             ind++;
2887         }
2888         
2889         //add just built wire to current face or save it in the sequence of wires
2890         Standard_Boolean EdgeOnBoundOfSurfFound = Standard_False;
2891         TopoDS_Iterator itw(aNewWire);
2892         for (; itw.More(); itw.Next())
2893         {
2894           const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2895           if (BRep_Tool::IsClosed(anEdge, RefFace))
2896           {
2897             EdgeOnBoundOfSurfFound = Standard_True;
2898             break;
2899           }
2900         }
2901         if (EdgeOnBoundOfSurfFound) //this wire can not be a hole
2902         {
2903           TopLoc_Location aLoc;
2904           Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc);
2905           TopoDS_Face aResult;
2906           BB.MakeFace(aResult,aSurf,aLoc,0);
2907           BB.Add(aResult, aNewWire);
2908           aResult.Orientation(RefFaceOrientation);
2909           NewFaces.Append(aResult);
2910         }
2911         else //may be this wire is a hole
2912         {
2913           NewWires.Append(aNewWire);
2914         }
2915       } //while (!edges.IsEmpty())
2916
2917       //Build wires from internal edges
2918       TopTools_IndexedDataMapOfShapeListOfShape IntVEmap;
2919       for (Standard_Integer ii = 1; ii <= InternalEdges.Extent(); ii++)
2920         TopExp::MapShapesAndAncestors(InternalEdges(ii), TopAbs_VERTEX, TopAbs_EDGE, IntVEmap);
2921       TopTools_SequenceOfShape InternalWires;
2922       while (!InternalEdges.IsEmpty())
2923       {
2924         TopoDS_Edge aFirstEdge = TopoDS::Edge(InternalEdges(1));
2925         InternalEdges.RemoveFromIndex(1);
2926         TopoDS_Wire anInternalWire;
2927         BB.MakeWire(anInternalWire);
2928         BB.Add(anInternalWire, aFirstEdge);
2929         TopoDS_Edge EndEdges [2];
2930         EndEdges[0] = EndEdges[1] = aFirstEdge;
2931         TopoDS_Vertex VV [2];
2932         TopExp::Vertices(aFirstEdge, VV[0], VV[1]);
2933         for (;;)
2934         {
2935           if (VV[0].IsSame(VV[1])) //closed wire
2936             break;
2937           Standard_Boolean found = Standard_False;
2938           for (Standard_Integer ii = 0; ii < 2; ii++)
2939           {
2940             const TopTools_ListOfShape& Elist = IntVEmap.FindFromKey(VV[ii]);
2941             TopTools_ListIteratorOfListOfShape itl(Elist);
2942             for (; itl.More(); itl.Next())
2943             {
2944               TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2945               if (anEdge.IsSame(EndEdges[ii]))
2946                 continue;
2947               found = Standard_True;
2948               InternalEdges.RemoveKey(anEdge);
2949               BB.Add(anInternalWire, anEdge);
2950               TopoDS_Vertex V1, V2;
2951               TopExp::Vertices(anEdge, V1, V2);
2952               VV[ii] = (V1.IsSame(VV[ii]))? V2 : V1;
2953               EndEdges[ii] = anEdge;
2954               break;
2955             }
2956           }
2957           if (!found) //end of open wire
2958             break;
2959         }
2960         InternalWires.Append(anInternalWire);
2961       }
2962
2963       //Insert new faces instead of old ones
2964       if (NewFaces.IsEmpty())
2965       {
2966         //one face without seam
2967         TopLoc_Location aLoc;
2968         Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc);
2969         TopoDS_Face aResult;
2970         BB.MakeFace(aResult,aSurf,aLoc,0.);
2971         for (Standard_Integer ii = 1; ii <= NewWires.Length(); ii++)
2972           BB.Add(aResult, NewWires(ii));
2973         for (Standard_Integer ii = 1; ii <= InternalWires.Length(); ii++)
2974           BB.Add(aResult, InternalWires(ii));
2975         aResult.Orientation(RefFaceOrientation);
2976         myContext->Merge(faces, aResult);
2977       }
2978       else if (NewFaces.Length() == 1)
2979       {
2980         TopoDS_Shape aNewFace = NewFaces(1).Oriented (TopAbs_FORWARD);
2981         for (Standard_Integer ii = 1; ii <= NewWires.Length(); ii++)
2982           BB.Add(aNewFace, NewWires(ii));
2983         for (Standard_Integer ii = 1; ii <= InternalWires.Length(); ii++)
2984           BB.Add(aNewFace, InternalWires(ii));
2985         myContext->Merge(faces, NewFaces(1));
2986       }
2987       else
2988       {
2989         //Insert new wires and internal wires into correspondent faces
2990         InsertWiresIntoFaces(NewWires, NewFaces, RefFace);
2991         InsertWiresIntoFaces(InternalWires, NewFaces, RefFace);
2992         
2993         NCollection_Sequence<TopTools_MapOfShape> Emaps;
2994         for (Standard_Integer ii = 1; ii <= faces.Length(); ii++)
2995         {
2996           TopTools_MapOfShape aEmap;
2997           TopExp::MapShapes(faces(ii), aEmap);
2998           Emaps.Append(aEmap);
2999         }
3000         for (Standard_Integer ii = 1; ii <= NewFaces.Length(); ii++)
3001         {
3002           TopTools_SequenceOfShape facesForThisFace;
3003           TopTools_MapOfShape UsedFaces;
3004           TopExp_Explorer Explo(NewFaces(ii), TopAbs_EDGE);
3005           for (; Explo.More(); Explo.Next())
3006           {
3007             const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
3008             if (BRep_Tool::Degenerated(anEdge) ||
3009                 BRep_Tool::IsClosed(anEdge, RefFace))
3010               continue;
3011             Standard_Integer jj;
3012             for (jj = 1; jj <= Emaps.Length(); jj++)
3013               if (Emaps(jj).Contains(anEdge))
3014                 break;
3015             if (UsedFaces.Add(faces(jj)))
3016               facesForThisFace.Append(faces(jj));
3017           }
3018           myContext->Merge(facesForThisFace, NewFaces(ii));
3019         }
3020       }
3021     } //if (faces.Length() > 1)
3022   } // end processing each face
3023 }
3024
3025 //=======================================================================
3026 //function : UnifyEdges
3027 //purpose  : 
3028 //=======================================================================
3029 void ShapeUpgrade_UnifySameDomain::UnifyEdges()
3030 {
3031   TopoDS_Shape aRes = myContext->Apply(myShape);
3032   // creating map of edge faces
3033   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
3034   TopExp::MapShapesAndAncestors(aRes, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
3035   // creating map of vertex edges
3036   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgesVertex;
3037   TopExp::MapShapesAndUniqueAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aMapEdgesVertex);
3038   // creating map of vertex faces
3039   TopTools_IndexedDataMapOfShapeListOfShape aVFmap;
3040   TopExp::MapShapesAndUniqueAncestors(aRes, TopAbs_VERTEX, TopAbs_FACE, aVFmap);
3041
3042   if (mySafeInputMode)
3043     UpdateMapOfShapes(myKeepShapes, myContext);
3044
3045   // Sequence of the edges of the shape
3046   TopTools_SequenceOfShape aSeqEdges;
3047   const Standard_Integer aNbE = aMapEdgeFaces.Extent();
3048   for (Standard_Integer i = 1; i <= aNbE; ++i)
3049     aSeqEdges.Append(aMapEdgeFaces.FindKey(i));
3050
3051   // Prepare map of shared vertices (with the number of connected edges greater then 2)
3052   TopTools_MapOfShape aSharedVert;
3053   CheckSharedVertices(aSeqEdges, aMapEdgesVertex, myKeepShapes, aSharedVert);
3054   // Merge the edges avoiding removal of the shared vertices
3055   Standard_Boolean isMerged = MergeSeq(aSeqEdges, aVFmap, myAngTol, myLinTol, myConcatBSplines,
3056                                        mySafeInputMode, myContext, aSharedVert);
3057   // Collect faces to rebuild
3058   TopTools_IndexedMapOfShape aChangedFaces;
3059   if (isMerged)
3060   {
3061     for (Standard_Integer i = 1; i <= aNbE; ++i)
3062     {
3063       const TopoDS_Shape& aE = aMapEdgeFaces.FindKey(i);
3064       if (myContext->IsRecorded(aE))
3065       {
3066         TopTools_ListIteratorOfListOfShape it(aMapEdgeFaces(i));
3067         for (; it.More(); it.Next())
3068           aChangedFaces.Add(it.Value());
3069       }
3070     }
3071   }
3072
3073   // fix changed faces and replace them in the local context
3074   Standard_Real aPrec = Precision::Confusion();
3075   for (Standard_Integer i = 1; i <= aChangedFaces.Extent(); i++) {
3076     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(aChangedFaces.FindKey(i)));
3077     if (aFace.IsNull())
3078       continue;
3079
3080     // for a planar face create and store pcurve of edge on face
3081     // to speed up all operations; but this is allowed only when non-safe mode in force
3082     if (!mySafeInputMode)
3083     {
3084       TopLoc_Location aLoc;
3085       Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace, aLoc);
3086       aSurface = ClearRts(aSurface);
3087       if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
3088       {
3089         TopTools_ListOfShape aLE;
3090         for (TopExp_Explorer anEx(aFace, TopAbs_EDGE); anEx.More(); anEx.Next())
3091           aLE.Append(anEx.Current());
3092         BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFace);
3093       }
3094     }
3095
3096     ShapeFix_Face sff(aFace);
3097     if (mySafeInputMode)
3098       sff.SetContext(myContext);
3099     sff.SetPrecision(aPrec);
3100     sff.SetMinTolerance(aPrec);
3101     sff.SetMaxTolerance(Max(1., aPrec*1000.));
3102     sff.FixOrientationMode() = 0;
3103     sff.FixAddNaturalBoundMode() = 0;
3104     sff.FixIntersectingWiresMode() = 0;
3105     sff.FixLoopWiresMode() = 0;
3106     sff.FixSplitFaceMode() = 0;
3107     sff.FixPeriodicDegeneratedMode() = 0;
3108     SetFixWireModes(sff);
3109     sff.Perform();
3110     TopoDS_Shape aNewFace = sff.Face();
3111     myContext->Replace(aFace,aNewFace);
3112   }
3113
3114   if (aChangedFaces.Extent() > 0) {
3115     // fix changed shell and replace it in the local context
3116     TopoDS_Shape aRes1 = myContext->Apply(aRes);
3117     Standard_Boolean isChanged = Standard_False;
3118     TopExp_Explorer expsh;
3119     for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
3120       TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
3121       Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
3122       sfsh->FixFaceOrientation(aShell);
3123       TopoDS_Shape aNewShell = sfsh->Shell();
3124       if (!aNewShell.IsSame(aShell)) {
3125         myContext->Replace(aShell, aNewShell);
3126         isChanged = Standard_True;
3127       }
3128     }
3129     if (isChanged)
3130       aRes1 = myContext->Apply(aRes1);
3131     myContext->Replace(myShape, aRes1);
3132   }
3133
3134   myShape = myContext->Apply(myShape);
3135 }
3136
3137 //=======================================================================
3138 //function : Build
3139 //purpose  : builds the resulting shape
3140 //=======================================================================
3141 void ShapeUpgrade_UnifySameDomain::Build() 
3142 {
3143   if (myUnifyFaces)
3144     UnifyFaces();
3145   if (myUnifyEdges)
3146     UnifyEdges();
3147
3148   // Fill the history of modifications during the operation
3149   FillHistory();
3150 }
3151
3152 //=======================================================================
3153 //function : FillHistory
3154 //purpose  : Fill the history of modifications during the operation
3155 //=======================================================================
3156 void ShapeUpgrade_UnifySameDomain::FillHistory()
3157 {
3158   if (myHistory.IsNull())
3159     // History is not requested
3160     return;
3161
3162   // Only Vertices, Edges and Faces can be modified during unification.
3163   // Thus, only these kind of shapes should be checked.
3164
3165   // Get history from the context.
3166   // It contains all modifications of the operation. Some of these
3167   // modifications become not relevant and should be filtered.
3168   Handle(BRepTools_History) aCtxHistory = myContext->History();
3169
3170   // Explore the history of the context and fill
3171   // the history of UnifySameDomain algorithm
3172   Handle(BRepTools_History) aUSDHistory = new BRepTools_History();
3173
3174   // Map all Vertices, Edges, Faces and Solids in the input shape
3175   TopTools_IndexedMapOfShape aMapInputShape;
3176   TopExp::MapShapes(myInitShape, TopAbs_VERTEX, aMapInputShape);
3177   TopExp::MapShapes(myInitShape, TopAbs_EDGE  , aMapInputShape);
3178   TopExp::MapShapes(myInitShape, TopAbs_FACE  , aMapInputShape);
3179   TopExp::MapShapes(myInitShape, TopAbs_SOLID , aMapInputShape);
3180
3181   // Map all Vertices, Edges, Faces and Solids in the result shape
3182   TopTools_IndexedMapOfShape aMapResultShapes;
3183   TopExp::MapShapes(myShape, TopAbs_VERTEX, aMapResultShapes);
3184   TopExp::MapShapes(myShape, TopAbs_EDGE  , aMapResultShapes);
3185   TopExp::MapShapes(myShape, TopAbs_FACE  , aMapResultShapes);
3186   TopExp::MapShapes(myShape, TopAbs_SOLID , aMapResultShapes);
3187
3188   // Iterate on all input shapes and get their modifications
3189   Standard_Integer i, aNb = aMapInputShape.Extent();
3190   for (i = 1; i <= aNb; ++i)
3191   {
3192     const TopoDS_Shape& aS = aMapInputShape(i);
3193
3194     // Check the shape itself to be present in the result
3195     if (aMapResultShapes.Contains(aS))
3196     {
3197       // The shape is present in the result as is, thus has not been modified
3198       continue;
3199     }
3200
3201     // Check if the shape has been modified during the operation
3202     const TopTools_ListOfShape& aLSImages = aCtxHistory->Modified(aS);
3203     if (aLSImages.IsEmpty())
3204     {
3205       // The shape has not been modified and not present in the result,
3206       // thus it has been removed
3207       aUSDHistory->Remove(aS);
3208       continue;
3209     }
3210
3211     // Check the images of the shape to be present in the result
3212     Standard_Boolean bRemoved = Standard_True;
3213     TopTools_ListIteratorOfListOfShape aItLSIm(aLSImages);
3214     for (; aItLSIm.More(); aItLSIm.Next())
3215     {
3216       const TopoDS_Shape& aSIm = aItLSIm.Value();
3217       if (aMapResultShapes.Contains(aSIm))
3218       {
3219         if (!aSIm.IsSame(aS))
3220           // Image is found in the result, thus the shape has been modified
3221           aUSDHistory->AddModified(aS, aSIm);
3222         bRemoved = Standard_False;
3223       }
3224     }
3225
3226     if (bRemoved)
3227     {
3228       // No images are found in the result, thus the shape has been removed
3229       aUSDHistory->Remove(aS);
3230     }
3231   }
3232
3233   // Merge the history of the operation into global history
3234   myHistory->Merge(aUSDHistory);
3235 }