0024428: Implementation of LGPL license
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_Sewing.cxx
1 // Created on: 1995-03-24
2 // Created by: Jing Cheng MEI
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // dcl          CCI60011 : Correction of degeneratedSection
18 //              Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
19 // dcl          Thu Aug 20 09:24:49 1998
20 //              Suppression of little faces.
21 // dcl          Fri Aug  7 15:27:46 1998
22 //                Refection of function SameParameter Edge.
23 //              Merge on the edge which has the less of poles.
24 //              Suppression of the Connected Edge function.
25 // dcl          Tue Jun  9 14:21:53 1998
26 //              Do not merge edge if they belong the same face
27 //              Tolerance management in VerticesAssembling
28 //              Tolerance management in Cutting
29 // dcl          Thu May 14 15:51:46 1998
30 //              optimization of cutting
31 // dcl          Thu May 7  15:51:46 1998
32 //              Add of cutting option
33 //              Add of SameParameter call
34
35
36 //-- lbr April 1 97
37 //-- dpf December 10 1997 Processing of pcurve collections
38
39 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode 
40 //rln 02.02.99 BUC60449 Protection against exception on NT
41
42 #define TEST 1
43
44 #include <BRepBuilderAPI_Sewing.ixx>
45
46 #include <Bnd_Box.hxx>
47 #include <Bnd_Box2d.hxx>
48 #include <Bnd_HArray1OfBox.hxx>
49 #include <BndLib_Add2dCurve.hxx>
50 #include <BndLib_Add3dCurve.hxx>
51 #include <BRep_Builder.hxx>
52 #include <BRep_Tool.hxx>
53 #include <BRepLib.hxx>
54 #include <BRepTools_Quilt.hxx>
55 #include <BSplCLib.hxx>
56 #include <Extrema_ExtPC.hxx>
57 #include <GCPnts_AbscissaPoint.hxx>
58 #include <GCPnts_UniformAbscissa.hxx>
59 #include <GCPnts_UniformDeflection.hxx>
60 #include <Geom2d_BezierCurve.hxx>
61 #include <Geom2d_BSplineCurve.hxx>
62 #include <Geom2d_Curve.hxx>
63 #include <Geom2d_Line.hxx>
64 #include <Geom2d_TrimmedCurve.hxx>
65 #include <Geom2dAdaptor_Curve.hxx>
66 #include <Geom2dConvert.hxx>
67 #include <Geom_BezierCurve.hxx>
68 #include <Geom_BSplineCurve.hxx>
69 #include <Geom_Curve.hxx>
70 #include <Geom_Line.hxx>
71 #include <Geom_Surface.hxx>
72 #include <GeomAdaptor_Curve.hxx>
73 #include <GeomAdaptor_Surface.hxx>
74 #include <GeomLib.hxx>
75 #include <gp_Pnt.hxx>
76 #include <gp_Vec.hxx>
77 //#include <LocalAnalysis_SurfaceContinuity.hxx>
78 #include <Precision.hxx>
79 #include <Standard_ErrorHandler.hxx>
80 #include <Standard_Failure.hxx>
81 #include <TColgp_Array1OfVec.hxx>
82 #include <TColgp_SequenceOfPnt.hxx>
83 #include <TColStd_Array1OfInteger.hxx>
84 #include <TColStd_Array1OfReal.hxx>
85 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
86 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
87 #include <TColStd_IndexedMapOfInteger.hxx>
88 #include <TColStd_ListIteratorOfListOfInteger.hxx>
89 #include <TColStd_ListOfInteger.hxx>
90 #include <TColStd_MapOfInteger.hxx>
91 #include <TColStd_SequenceOfReal.hxx>
92 #include <TopAbs.hxx>
93 #include <TopExp.hxx>
94 #include <TopExp_Explorer.hxx>
95 #include <TopLoc_Location.hxx>
96 #include <TopoDS.hxx>
97 #include <TopoDS_Edge.hxx>
98 #include <TopoDS_Iterator.hxx>
99 #include <TopoDS_Shape.hxx>
100 #include <TopoDS_Vertex.hxx>
101 #include <TopoDS_Wire.hxx>
102 #include <TopoDS_Shell.hxx>
103 #include <TopTools_Array1OfShape.hxx>
104 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
105 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
106 #include <TopTools_DataMapOfShapeInteger.hxx>
107 #include <TopTools_DataMapOfShapeListOfShape.hxx>
108 #include <TopTools_ListIteratorOfListOfShape.hxx>
109 #include <TopTools_ListOfShape.hxx>
110 #include <TopTools_MapIteratorOfMapOfShape.hxx>
111 #include <TopTools_MapOfShape.hxx>
112 #include <TopTools_SequenceOfShape.hxx>
113 #include <TopoDS_Compound.hxx>
114 #include <TColStd_Array2OfReal.hxx>
115 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
116 #include <BRepTools.hxx>
117 #include <Geom_RectangularTrimmedSurface.hxx>
118 #include <Geom_OffsetSurface.hxx>
119 #include <BRep_PointOnCurve.hxx>
120 #include <BRep_ListOfPointRepresentation.hxx>
121 #include <BRep_TVertex.hxx>
122 #include <Message_ProgressSentry.hxx>
123 #include <BRepBuilderAPI_VertexInspector.hxx>
124 #include <BRepBuilderAPI_CellFilter.hxx>
125 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
126 #include <NCollection_UBTreeFiller.hxx>
127
128 //=======================================================================
129 //function : SameRange
130 //purpose  : 
131 //=======================================================================
132
133 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
134                                                 const Standard_Real FirstOnCurve,
135                                                 const Standard_Real LastOnCurve,
136                                                 const Standard_Real RequestedFirst,
137                                                 const Standard_Real RequestedLast) const
138 {
139   Handle(Geom2d_Curve) NewCurvePtr;
140   try {
141     
142     GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
143                        RequestedFirst,RequestedLast,NewCurvePtr);
144   }
145   catch (Standard_Failure) {
146 #ifdef DEB
147     cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
148     Standard_Failure::Caught()->Print(cout); cout << endl;
149 #endif
150   }
151   return NewCurvePtr;
152 }
153
154 //=======================================================================
155 //function : WhichFace
156 //purpose  : Give the face whose edge is the border
157 //=======================================================================
158
159 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
160 {
161   TopoDS_Shape bound = theEdg;
162   if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
163   if (myBoundFaces.Contains(bound)) {
164     Standard_Integer i = 1;
165     TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
166     for (; itf.More(); itf.Next(), i++)
167       if (i == index) return TopoDS::Face(itf.Value());
168   }
169   return TopoDS_Face();
170 }
171
172 //=======================================================================
173 //function : IsClosedShape
174 //purpose  : 
175 //=======================================================================
176
177 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
178                                       const TopoDS_Shape& v1, const TopoDS_Shape& v2)
179 {
180   Standard_Real TotLength = 0.0;
181   TopExp_Explorer aexp;
182   for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
183     TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
184     if (aedge.IsNull()) continue;
185     TopoDS_Vertex ve1,ve2;
186     TopExp::Vertices(aedge,ve1,ve2);
187     if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
188     if (BRep_Tool::Degenerated(aedge)) continue;
189     Standard_Real first,last;
190     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
191     if (!c3d.IsNull()) {
192       GeomAdaptor_Curve cAdapt(c3d);
193       Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
194       TotLength += length;
195       if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
196     }
197   }
198   if (TotLength > 0.0) {
199     gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
200     gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
201     return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
202   }
203   return Standard_False;
204 }
205
206 //=======================================================================
207 //function : IsClosedByIsos
208 //purpose  : 
209 //=======================================================================
210 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
211                                        const Handle(Geom2d_Curve)& acrv2d,
212                                        const Standard_Real f2d,
213                                        const  Standard_Real l2d,
214                                        const Standard_Boolean isUIsos) 
215 {
216   Standard_Boolean isClosed = Standard_False;
217  
218   gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ? 
219                      acrv2d->Value(f2d) :  acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
220   gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ? 
221                      acrv2d->Value(l2d) :  acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
222   Handle(Geom_Curve) aCrv1;
223   Handle(Geom_Curve) aCrv2;
224   if(isUIsos) {
225     aCrv1 = thesurf->UIso(psurf1.X());
226     aCrv2 = thesurf->UIso(psurf2.X());
227   }
228   else {
229     aCrv1 = thesurf->VIso(psurf1.Y());
230     aCrv2 = thesurf->VIso(psurf2.Y());
231   }
232   gp_Pnt p11,p1m,p12,p21,p2m,p22;
233   Standard_Real af1 = aCrv1->FirstParameter();
234   Standard_Real al1 = aCrv1->LastParameter();
235   Standard_Real af2 = aCrv2->FirstParameter();
236   Standard_Real al2 = aCrv2->LastParameter();
237   aCrv1->D0(af1,p11);
238   aCrv1->D0((af1+al1)*0.5,p1m);
239   aCrv1->D0(al1,p12);
240   aCrv2->D0(af2,p21);
241   aCrv2->D0((af2+al2)*0.5,p2m);
242   aCrv2->D0(al2,p22);
243   isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() < 
244                (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
245               ((p21.XYZ() - p22.XYZ()).Modulus() < 
246                (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
247   return isClosed;
248 }
249 //=======================================================================
250 //function : IsUClosedSurface
251 //purpose  : 
252 //=======================================================================
253
254 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
255                                                    const TopoDS_Shape& theEdge,
256                                                    const TopLoc_Location& theloc) const
257 {
258   Handle(Geom_Surface) tmpsurf = surf;
259   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
260     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
261   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
262     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
263   else {
264     Standard_Boolean isClosed = tmpsurf->IsUClosed();
265     if(!isClosed) {
266       Standard_Real f2d, l2d;
267       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
268       if(!acrv2d.IsNull())
269         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
270       
271     }
272     return isClosed;
273   }
274   return IsUClosedSurface(tmpsurf,theEdge,theloc);
275   //return surf->IsUClosed();
276 }
277
278 //=======================================================================
279 //function : IsVClosedSurface
280 //purpose  : 
281 //=======================================================================
282
283 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
284                                                    const TopoDS_Shape& theEdge,
285                                                    const TopLoc_Location& theloc) const
286 {
287   Handle(Geom_Surface) tmpsurf = surf;
288   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
289     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
290   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
291     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
292   else {
293     Standard_Boolean isClosed = tmpsurf->IsVClosed();
294     if(!isClosed) {
295       Standard_Real f2d, l2d;
296       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
297       if(!acrv2d.IsNull())
298         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
299     }
300     return isClosed;
301   }
302   return IsVClosedSurface(tmpsurf,theEdge,theloc);
303   //return surf->IsVClosed();
304 }
305
306 //=======================================================================
307 //function : SameParameter
308 //purpose  : internal use
309 //=======================================================================
310
311 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
312 {
313   try {
314     
315     BRepLib::SameParameter(edge);
316   }
317   catch (Standard_Failure) {
318 #ifdef DEB
319     cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
320     Standard_Failure::Caught()->Print(cout); cout << endl;
321 #endif
322   }
323 }
324
325 //=======================================================================
326 //function : SameParameterEdge
327 //purpose  : internal use
328 //           Merge the Sequence Of Section on one edge.
329 //           This function keep the curve3d,curve2d,range and parametrization
330 //           from the first section, and report and made sameparameter the
331 //           pcurves of the other function.
332 //           This function works when the are not more than two Pcurves
333 //           on a same face.
334 //=======================================================================
335
336 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
337                                                const TopTools_SequenceOfShape& seqEdges,
338                                                const TColStd_SequenceOfInteger& seqForward,
339                                                TopTools_MapOfShape& mapMerged,
340                                                const Handle(BRepTools_ReShape)& locReShape)
341 {
342   // Retrieve reference section
343   TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
344   TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
345   aTmpShape = locReShape->Apply(Edge1);
346   if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
347   Standard_Boolean isDone = Standard_False;
348
349   // Create data structures for temporary merged edges
350   TopTools_ListOfShape listFaces1;
351   TopTools_MapOfShape MergedFaces;
352
353   if (mySewing) {
354
355     // Fill MergedFaces with faces of Edge1
356     TopoDS_Shape bnd1 = edge;
357     if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
358     if (myBoundFaces.Contains(bnd1)) {
359       TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
360       for (; itf.More(); itf.Next())
361         if (MergedFaces.Add(itf.Value()))
362           listFaces1.Append(itf.Value());
363     }
364   }
365   else {
366
367     // Create presentation edge
368     TopoDS_Vertex V1, V2;
369     TopExp::Vertices(Edge1,V1,V2);
370     if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
371     if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
372
373     TopoDS_Edge NewEdge = Edge1;
374     NewEdge.EmptyCopy();
375
376     // Add the vertices
377     BRep_Builder aBuilder;
378     TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
379     aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
380     aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
381
382     Edge1 = NewEdge;
383   }
384
385   Standard_Boolean isForward = Standard_True;
386
387   // Merge candidate sections
388   for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
389
390     // Retrieve candidate section
391     TopoDS_Shape oedge2 = seqEdges(i);
392
393     if (mySewing) {
394
395       aTmpShape = myReShape->Apply(oedge2); //for porting
396       TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
397       aTmpShape = locReShape->Apply(Edge2);
398       if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
399
400       // Calculate relative orientation
401       Standard_Integer Orientation = seqForward(i);
402       if (!isForward) Orientation = (Orientation? 0 : 1);
403
404       // Retrieve faces information for the second edge
405       TopoDS_Shape bnd2 = oedge2;
406       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
407       if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
408       const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
409
410       Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
411       TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
412       if (NewEdge.IsNull()) continue;
413
414       // Record faces information for the temporary merged edge
415       TopTools_ListIteratorOfListOfShape itf(listFaces2);
416       for (; itf.More(); itf.Next())
417         if (MergedFaces.Add(itf.Value()))
418           listFaces1.Append(itf.Value());
419
420       // Record merged section orientation
421       if (!Orientation && whichSec != 1)
422         isForward = isForward? Standard_False : Standard_True;
423       Edge1 = NewEdge;
424     }
425
426     // Append actually merged edge
427     mapMerged.Add(oedge2);
428     isDone = Standard_True;
429
430     if (!myNonmanifold) break;
431   }
432
433   if (isDone) {
434     // Change result orientation
435     Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
436   }
437   else Edge1.Nullify();
438
439   return Edge1;
440 }
441
442 //=======================================================================
443 //function : SameParameterEdge
444 //purpose  : internal use
445 //=======================================================================
446 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
447                                        TopTools_SequenceOfShape& theSeqNMVert,
448                                        TColStd_SequenceOfReal& theSeqPars)
449 {
450   TopoDS_Iterator aItV(theEdge,Standard_False);
451   for( ; aItV.More(); aItV.Next()) {
452     if(aItV.Value().Orientation() == TopAbs_INTERNAL || 
453         aItV.Value().Orientation() == TopAbs_EXTERNAL)
454     theSeqNMVert.Append(aItV.Value());
455   }
456   Standard_Integer nbV = theSeqNMVert.Length();
457   if(!nbV)
458     return Standard_False;
459   Standard_Real first, last;
460   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
461   GeomAdaptor_Curve GAC(c3d);
462   Extrema_ExtPC locProj;
463   locProj.Initialize(GAC, first, last);
464   gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
465
466   
467   for (Standard_Integer i = 1; i <= nbV; i++) {
468     TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
469     gp_Pnt pt = BRep_Tool::Pnt(aV);
470     
471     Standard_Real distF2 = pfirst.SquareDistance(pt);
472     Standard_Real distL2 = plast.SquareDistance(pt);
473     Standard_Real apar = (distF2 > distL2 ? last : first);
474     // Project current point on curve
475     locProj.Perform(pt);
476     if (locProj.IsDone() && locProj.NbExt() > 0) {
477           Standard_Real dist2Min = Min(distF2,distL2);
478           Standard_Integer ind, indMin = 0;
479           for (ind = 1; ind <= locProj.NbExt(); ind++) {
480             Standard_Real dProj2 = locProj.SquareDistance(ind);
481             if (dProj2 < dist2Min) { 
482           indMin = ind; dist2Min = dProj2; 
483         }
484       }
485       if(indMin) 
486         apar = locProj.Point(indMin).Parameter();
487          
488       theSeqPars.Append(apar);  
489         
490     }
491   }
492   return Standard_True;
493 }
494
495 static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
496 {
497   return (dist * 0.5 + Tol1 + Tol2);
498 }
499 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
500                                                const TopoDS_Edge& edgeLast,
501                                                const TopTools_ListOfShape& listFacesFirst,
502                                                const TopTools_ListOfShape& listFacesLast,
503                                                const Standard_Boolean secForward, 
504                                                Standard_Integer& whichSec,
505                                                const Standard_Boolean firstCall)
506 {
507   // Do not process floating edges
508   if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
509
510   // Sort input edges
511   TopoDS_Edge edge1, edge2;
512   if (firstCall) {
513     // Take the longest edge as first
514     Standard_Real f, l;
515     Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
516     GeomAdaptor_Curve cAdapt1(c3d1);
517     Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
518     Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
519     GeomAdaptor_Curve cAdapt2(c3d2);
520     Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
521     if (len1 < len2) {
522       edge1 = edgeLast;
523       edge2 = edgeFirst;
524       whichSec = 2;
525     }
526     else {
527       edge1 = edgeFirst;
528       edge2 = edgeLast;
529       whichSec = 1;
530     }
531   }
532   else {
533     if (whichSec == 1) {
534       edge1 = edgeLast;
535       edge2 = edgeFirst;
536       whichSec = 2;
537     }
538     else {
539       edge1 = edgeFirst;
540       edge2 = edgeLast;
541       whichSec = 1;
542     }
543   }
544
545   Standard_Real first, last;
546   BRep_Tool::Range(edge1, first, last);
547   BRep_Builder aBuilder;
548
549   //To keep NM vertices on edge
550   TopTools_SequenceOfShape aSeqNMVert;
551   TColStd_SequenceOfReal aSeqNMPars;
552   findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
553   findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
554
555   // Create new edge
556   TopoDS_Edge edge;
557   aBuilder.MakeEdge(edge);
558   edge.Orientation( edge1.Orientation());
559  
560
561   // Retrieve edge curve
562   TopLoc_Location loc3d;
563   Standard_Real first3d, last3d;
564   Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
565   if (!loc3d.IsIdentity()) {
566     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
567     c3d->Transform(loc3d.Transformation());
568   }
569   aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
570   aBuilder.Range(edge, first, last);
571   aBuilder.SameRange(edge, Standard_False); //Standard_True
572   aBuilder.SameParameter(edge, Standard_False);
573   // Create and add new vertices
574   {
575     TopoDS_Vertex V1New, V2New;
576
577     // Retrieve original vertices from edges
578     TopoDS_Vertex V11,V12,V21,V22;
579     TopExp::Vertices(edge1,V11,V12);
580     TopExp::Vertices(edge2,V21,V22);
581
582     //check that edges merged valid way (for edges having length less than specified
583     //tolerance
584     // Check if edges are closed
585     Standard_Boolean isClosed1 = V11.IsSame(V12);
586     Standard_Boolean isClosed2 = V21.IsSame(V22);
587     if(!isClosed1 && !isClosed2)
588     {
589       if(secForward )
590       {
591         if( V11.IsSame(V22) || V12.IsSame(V21) )
592           return TopoDS_Edge();
593       }
594       else
595       {
596         if( V11.IsSame(V21) || V12.IsSame(V22) )
597           return TopoDS_Edge();
598       }
599     }
600
601     //szv: do not reshape here!!!
602     //V11 = TopoDS::Vertex(myReShape->Apply(V11));
603     //V12 = TopoDS::Vertex(myReShape->Apply(V12));
604     //V21 = TopoDS::Vertex(myReShape->Apply(V21));
605     //V22 = TopoDS::Vertex(myReShape->Apply(V22));
606
607     gp_Pnt p11 = BRep_Tool::Pnt(V11);
608     gp_Pnt p12 = BRep_Tool::Pnt(V12);
609     gp_Pnt p21 = BRep_Tool::Pnt(V21); 
610     gp_Pnt p22 = BRep_Tool::Pnt(V22);
611
612     
613
614     //Standard_Boolean isRev = Standard_False;
615     gp_Pnt pfirst;
616     Standard_Real Tol1 = 0.;
617     if (isClosed1 || isClosed2) {
618       // at least one of the edges is closed
619       if (isClosed1 && isClosed2) {
620         // both edges are closed
621         pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
622         gp_Vec v1 =  p21.XYZ() - p11.XYZ();
623         Standard_Real d1 = v1.Magnitude();
624         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
625         //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
626       }
627       else if (isClosed1) {
628         // only first edge is closed
629         gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
630         pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
631         gp_Vec v1 =  p22.XYZ() - p21.XYZ();
632         Standard_Real d1 = v1.Magnitude();
633         Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
634         gp_Vec v2 =  p11.XYZ() - pt;
635         Standard_Real d2 = v2.Magnitude();
636         Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
637         //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
638         //Tol1 = Max(pfirst.Distance(p11),Tol1);
639       }
640       else {
641         // only second edge is closed
642         gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
643         pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
644         gp_Vec v1 =  p11.XYZ() - p12.XYZ();
645         Standard_Real d1 = v1.Magnitude();
646         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
647         gp_Vec v2 =  p21.XYZ() - pt;
648         Standard_Real d2 = v2.Magnitude();
649         Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
650         //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
651         //Tol1 = Max(pfirst.Distance(p21),Tol1);
652       }
653       aBuilder.MakeVertex(V1New,pfirst,Tol1);
654       V2New = V1New;
655     }
656     else {
657       // both edges are open
658       gp_Pnt plast;
659       Standard_Real Tol2 = 0.;
660       Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) :  V11.IsSame(V22) );
661       Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
662       if (secForward) {
663         //case if vertices already sewed
664         if(!isOldFirst)
665         {
666           pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
667           gp_Vec v1 =  p21.XYZ() - p11.XYZ();
668           Standard_Real d1 = v1.Magnitude();
669           Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
670         }
671         if(!isOldLast)
672         {
673           plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
674
675           gp_Vec v2 =  p22.XYZ() - p12.XYZ();
676           Standard_Real d2 = v2.Magnitude();
677
678           Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
679         }
680
681       }
682       else {
683         if(!isOldFirst)
684         {
685           pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
686           gp_Vec v1 =  p22.XYZ() - p11.XYZ();
687           Standard_Real d1 = v1.Magnitude();
688           Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
689         }
690         if(!isOldLast)
691         {
692           plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
693           gp_Vec v2 =  p21.XYZ() - p12.XYZ();
694           Standard_Real d2 = v2.Magnitude();
695           Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
696         }
697
698       }
699       if(!isOldFirst)
700         aBuilder.MakeVertex(V1New,pfirst,Tol1);
701       else
702         V1New = V11;
703        
704
705       if(!isOldLast)
706         aBuilder.MakeVertex(V2New,plast,Tol2);
707       else
708         V2New = V12;
709
710     }
711
712     // Add the vertices in the good sense
713     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
714     TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
715     aBuilder.Add(anEdge,aLocalEdge);
716     aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
717     aBuilder.Add(anEdge,aLocalEdge);
718
719     Standard_Integer k =1;
720     for( ; k <= aSeqNMVert.Length(); k++)
721       aBuilder.Add(anEdge,aSeqNMVert.Value(k));
722
723   }
724
725   // Retrieve second PCurves
726   TopLoc_Location loc2;
727   Handle(Geom_Surface) surf2;
728   
729   //Handle(Geom2d_Curve) c2d2, c2d21;
730   //  Standard_Real firstOld, lastOld;
731
732   TopTools_ListIteratorOfListOfShape itf2;
733   if (whichSec == 1) itf2.Initialize(listFacesLast);
734   else               itf2.Initialize(listFacesFirst);
735   Standard_Boolean isResEdge = Standard_False;
736   TopoDS_Face fac2;
737   for (; itf2.More(); itf2.Next()) {
738     Handle(Geom2d_Curve) c2d2, c2d21;
739     Standard_Real firstOld, lastOld;
740     fac2 = TopoDS::Face(itf2.Value());
741
742     surf2 = BRep_Tool::Surface(fac2, loc2);
743     Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
744       BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
745     if (isSeam2) {
746       if (!myNonmanifold) return TopoDS_Edge();
747       TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
748       c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
749     }
750     c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
751     if (c2d2.IsNull() && c2d21.IsNull()) continue;
752
753     if (!c2d21.IsNull()) {
754       c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
755       if (!secForward) {
756         if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
757           c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
758         Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
759         Standard_Real last2d = lastOld;   //c2dTmp->LastParameter();
760         firstOld = c2d21->ReversedParameter(last2d);
761         lastOld = c2d21->ReversedParameter(first2d);
762         c2d21->Reverse();
763       }
764       c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
765     }
766
767     // Make second PCurve sameRange with the 3d curve
768     c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
769     
770     if (!secForward) {
771       if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
772         c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
773       Standard_Real first2d = firstOld; 
774       Standard_Real last2d = lastOld;   
775       firstOld = c2d2->ReversedParameter(last2d);
776       lastOld = c2d2->ReversedParameter(first2d);
777       c2d2->Reverse();
778     }
779
780     c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
781     if (c2d2.IsNull()) continue;
782
783     // Add second PCurve
784     Standard_Boolean isSeam = Standard_False;
785     TopAbs_Orientation Ori = TopAbs_FORWARD;
786     //Handle(Geom2d_Curve) c2d1, c2d11;
787
788     TopTools_ListIteratorOfListOfShape itf1;
789     if (whichSec == 1) itf1.Initialize(listFacesFirst);
790     else               itf1.Initialize(listFacesLast);
791     for (; itf1.More() && !isSeam; itf1.Next()) {
792       Handle(Geom2d_Curve) c2d1, c2d11;
793       const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
794
795       TopLoc_Location loc1;
796       Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
797       
798       Standard_Real first2d, last2d;
799       Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
800         BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
801       c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
802       Ori = edge1.Orientation();
803       if (fac1.Orientation() == TopAbs_REVERSED) 
804         Ori = TopAbs::Reverse(Ori);
805
806       if (isSeam1) {
807         if (!myNonmanifold) return TopoDS_Edge();
808         TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
809         c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
810         //if(fac1.Orientation() == TopAbs_REVERSED) //
811         if(Ori == TopAbs_FORWARD)
812           aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
813         else
814           aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
815       }
816       else  aBuilder.UpdateEdge(edge,c2d1,fac1,0);
817
818       if (c2d1.IsNull() && c2d11.IsNull()) continue;
819
820       if (surf2 == surf1) {
821         // Merge sections which are on the same face
822         if (!loc2.IsDifferent(loc1)) {
823           Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
824           Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
825           if (uclosed || vclosed) {
826             Standard_Real pf = c2d1->FirstParameter();
827             //      Standard_Real pl = c2d1->LastParameter();
828             gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
829             //      gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
830             gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
831             gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
832             Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
833             Standard_Real U1, U2, V1, V2;
834             surf2->Bounds(U1, U2, V1, V2);
835             isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
836               (vclosed && aDist > 0.75*(fabs(V2-V1))));
837             if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
838           }
839         }
840       }
841
842       isResEdge = Standard_True;
843       if (isSeam) {
844         if (Ori == TopAbs_FORWARD)
845           aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
846         else
847           aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
848       }
849       else if (isSeam2) {
850         TopAbs_Orientation InitOri  = edge2.Orientation();
851         TopAbs_Orientation SecOri  = edge.Orientation();
852         if (fac2.Orientation() == TopAbs_REVERSED) {
853
854           InitOri = TopAbs::Reverse(InitOri);
855           SecOri = TopAbs::Reverse(SecOri);
856         }
857         if(!secForward)
858           InitOri = TopAbs::Reverse(InitOri);
859
860         if (InitOri == TopAbs_FORWARD)
861           aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
862         else
863           aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
864       } 
865       else {
866         aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
867       }
868
869     }
870   }
871   Standard_Real tolReached = Precision::Infinite();
872   Standard_Boolean isSamePar = Standard_False; 
873   if( isResEdge)
874   {
875     SameParameter(edge);
876     if( BRep_Tool::SameParameter(edge))
877     {
878       isSamePar = Standard_True;
879       tolReached = BRep_Tool::Tolerance(edge);
880     }
881   }
882  
883  
884   if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
885     Standard_Integer whichSecn = whichSec;
886     // Try to merge on the second section
887     Standard_Boolean second_ok = Standard_False;
888     TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
889       secForward,whichSecn,Standard_False);
890     if( !s_edge.IsNull())
891     {
892       Standard_Real tolReached_2  = BRep_Tool::Tolerance(s_edge);
893       second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
894       if( second_ok)
895       {
896         edge = s_edge;
897         whichSec = whichSecn;
898         tolReached = tolReached_2;
899       }
900     }
901
902     if (!second_ok && !edge.IsNull()) {
903
904       GeomAdaptor_Curve c3dAdapt(c3d);
905
906       // Discretize edge curve
907       Standard_Integer i, j, nbp = 23;
908       Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
909       TColgp_Array1OfPnt c3dpnt(1,nbp);
910       for (i = 1; i <= nbp; i++) 
911         c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
912
913       Standard_Real dist = 0., maxTol = -1.0;
914       Standard_Boolean more = Standard_True;
915
916       for (j = 1; more; j++) {
917         Handle(Geom2d_Curve) c2d2;
918         BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
919             
920         more = !c2d2.IsNull();
921         if (more) {
922           Handle(Geom_Surface) aS = surf2;
923           if(!loc2.IsIdentity())
924             aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
925
926           Standard_Real dist2 = 0.;
927           deltaT = (last - first) / (nbp + 1);
928           for (i = 1; i <= nbp; i++) {
929             gp_Pnt2d aP2d =  c2d2->Value(first + i*deltaT);
930             gp_Pnt aP2(0.,0.,0.);
931             aS->D0(aP2d.X(),aP2d.Y(), aP2);
932             gp_Pnt aP1 = c3dpnt(i);
933             dist = aP2.SquareDistance(aP1);
934             if (dist > dist2) 
935               dist2 = dist;
936           }
937           maxTol = Max(sqrt(dist2), Precision::Confusion());
938         }
939       }
940       if(maxTol >= 0. && maxTol < tolReached)
941         aBuilder.UpdateEdge(edge, maxTol);
942       aBuilder.SameParameter(edge,Standard_True);
943     }
944   }
945
946   BRepLib::EncodeRegularity(edge,0.01);
947   Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
948   if (tolEdge1 > MaxTolerance()) edge.Nullify();
949   return edge;
950 }
951
952 //=======================================================================
953 // function : EvaluateAngulars
954 // purpose  : internal use
955 //=======================================================================
956
957 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
958                                        TColStd_Array1OfBoolean& secForward,
959                                        TColStd_Array1OfReal& tabAng,
960                                        const Standard_Integer indRef) const
961 {
962   tabAng.Init(-1.0);
963
964   Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
965
966   TopoDS_Edge edge;
967   TopoDS_Face face;
968   TopLoc_Location loc;
969   Standard_Real first, last;
970   Handle(Geom_Curve) c3d;
971   Handle(Geom2d_Curve) c2d;
972   Handle(Geom_Surface) surf;
973   TColgp_Array1OfVec normRef(1,npt);
974
975   for (i = indRef; i <= lengSec; i++) {
976
977     edge = TopoDS::Edge(sequenceSec(i));
978
979     TopoDS_Shape bnd = edge;
980     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
981     if (myBoundFaces.Contains(bnd)) {
982       face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
983       surf = BRep_Tool::Surface(face,loc);
984       if (!loc.IsIdentity()) {
985         surf = Handle(Geom_Surface)::DownCast(surf->Copy());
986         surf->Transform(loc.Transformation());
987       }
988       c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
989     }
990     else if (i == indRef) return;
991     else continue;
992
993     c3d = BRep_Tool::Curve(edge, loc, first, last);
994     if (!loc.IsIdentity()) {
995       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
996       c3d->Transform(loc.Transformation());
997     }
998
999     GeomAdaptor_Curve adapt(c3d);
1000     GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1001
1002     Standard_Real cumulateAngular = 0.0;
1003     Standard_Integer nbComputedAngle = 0;
1004
1005     for (j = 1; j <= npt; j++) {
1006       gp_Pnt2d P;
1007       c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1008       gp_Vec w1, w2;
1009       gp_Pnt unused;
1010       surf->D1(P.X(), P.Y(), unused, w1, w2);
1011       gp_Vec n = w1^w2; // Compute the normal vector
1012       if (i == indRef) normRef(j) = n;
1013       else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1014         nbComputedAngle++;
1015         Standard_Real angular = n.Angle(normRef(j));
1016         if (angular > M_PI/2.) angular = M_PI - angular;
1017         cumulateAngular += angular;
1018       }
1019     }
1020
1021     if (nbComputedAngle)
1022       tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1023   }
1024 }
1025
1026 //=======================================================================
1027 // function : EvaluateDistances
1028 // purpose  : internal use
1029 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1030 // Remarks (lengSec - indRef) must be >= 1 
1031 //=======================================================================
1032 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1033                                               TColStd_Array1OfBoolean& secForward,
1034                                               TColStd_Array1OfReal& tabDst,
1035                                               TColStd_Array1OfReal& arrLen,
1036                                               TColStd_Array1OfReal& tabMinDist,
1037                                               const Standard_Integer indRef) const
1038 {
1039   secForward.Init(Standard_True);
1040   tabDst.Init(-1.0);
1041   arrLen.Init(0.);
1042   tabMinDist.Init(Precision::Infinite());
1043   const Standard_Integer npt = 8; // Number of points for curve discretization
1044   TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1045
1046   Standard_Integer i, j, lengSec = sequenceSec.Length();
1047   TColgp_SequenceOfPnt seqSec;
1048
1049   Handle(Geom_Curve) c3dRef;
1050   Standard_Real firstRef=0., lastRef=0.;
1051   
1052   for (i = indRef; i <= lengSec; i++) {
1053
1054     // reading of the edge (attention for the first one: reference)
1055     const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1056
1057     TopLoc_Location loc;
1058     Standard_Real first, last;
1059     Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1060     if (!loc.IsIdentity()) {
1061       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1062       c3d->Transform(loc.Transformation());
1063     }
1064
1065     if (i == indRef) {
1066       c3dRef = c3d; firstRef = first; lastRef = last;
1067     }
1068
1069     Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1070     Standard_Real aMinDist = Precision::Infinite();
1071
1072     Standard_Real T, deltaT = (last - first) / (npt - 1);
1073     Standard_Real aLenSec2 = 0.;
1074    
1075     Standard_Integer nbFound = 0;
1076     for (j = 1; j <= npt; j++) {
1077
1078       // Uniform parameter on curve
1079       if (j == 1) T = first;
1080       else if (j == npt) T = last;
1081       else T = first + (j - 1) * deltaT;
1082
1083       // Take point on curve
1084       gp_Pnt pt = c3d->Value(T);
1085      
1086       if (i == indRef) {
1087         ptsRef(j) = pt;
1088         if(j > 1)
1089           aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1090       }
1091       else {
1092         ptsSec(j) = pt;
1093         //protection to avoid merging with small sections
1094         if(j > 1)
1095           aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1096         // To evaluate mutual orientation and distance
1097         dist = pt.Distance(ptsRef(j));
1098         if(aMinDist > dist)
1099           aMinDist = dist;
1100         if (distFor < dist) distFor = dist;
1101         dist = pt.Distance(ptsRef(npt-j+1));
1102    
1103         if(aMinDist > dist)
1104           aMinDist = dist;
1105         if (distRev < dist) distRev = dist;
1106
1107         // Check that point lays between vertices of reference curve
1108         const gp_Pnt &p11 = ptsRef(1);
1109         const gp_Pnt &p12 = ptsRef(npt);
1110         const gp_Vec aVec1(pt,p11);
1111         const gp_Vec aVec2(pt,p12);
1112         const gp_Vec aVecRef(p11,p12);
1113         if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1114           nbFound++;
1115       }
1116     }
1117
1118     Standard_Real aLenSec = sqrt(aLenSec2);
1119     
1120     //if(aLenSec < myMinTolerance )
1121      // continue;
1122     arrLen.SetValue(i,aLenSec);
1123     // Record mutual orientation
1124     Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1125     secForward(i) = isForward;
1126
1127     dist = (isForward? distFor : distRev);
1128     if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1129     {
1130       tabDst(i) = dist;
1131       tabMinDist(i) = aMinDist;
1132     }
1133     else
1134     {
1135       nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1136       TColgp_Array1OfPnt arrProj(1, npt);
1137       TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1138       if( arrLen(indRef) >= arrLen(i)) 
1139         ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1140       else
1141         ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1142       for( j = 1; j <= npt; j++ )
1143       {
1144         if(arrDist(j) < 0.)
1145           continue;
1146         if(dist < arrDist(j))
1147           dist = arrDist(j);
1148         if( aMinDist > arrDist(j))
1149           aMinDist = arrDist(j);
1150         nbFound++;
1151       }
1152       if(nbFound > 1)
1153       {
1154         tabDst(i) = dist;
1155         tabMinDist(i) =  aMinDist;
1156       }
1157     }
1158   }
1159
1160   /*
1161   // Project distant points
1162   Standard_Integer nbFailed = seqSec.Length();
1163   if (!nbFailed) return;
1164
1165   TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1166   for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1167   TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1168
1169   ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1170
1171   // Process distant sections
1172   Standard_Integer idx1 = 1;
1173   for (i = indRef + 1; i <= lengSec; i++) {
1174
1175     // Skip section if already evaluated
1176     if (tabDst(i) >= 0.0) continue;
1177
1178     Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1179
1180     Standard_Integer idx2 = (idx1 - 1)*npt;
1181
1182     for (j = 1; j <= npt; j++) {
1183
1184       dist = arrDist(idx2 + j);
1185       // If point is not projected - stop evaluation
1186       if (dist < 0.0) { distMax = -1.0; break; }
1187       if (distMax < dist) distMax = dist;
1188       if(aMinDist > dist) aMinDist = dist;
1189     }
1190
1191     // If section is close - record distance
1192     if (distMax >= 0.0) {
1193       if (secForward(i)) {
1194         dist = arrPnt(idx2+1).Distance(ptsRef(1));
1195         if (distMax < dist) distMax = dist;
1196         if(aMinDist > dist) aMinDist = dist;
1197         dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1198         if (distMax < dist) distMax = dist;
1199         if(aMinDist > dist) aMinDist = dist;
1200       }
1201       else {
1202         dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1203         if (distMax < dist) distMax = dist;
1204         if(aMinDist > dist) aMinDist = dist;
1205         dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1206         if (distMax < dist) distMax = dist;
1207         if(aMinDist > dist) aMinDist = dist;
1208       }
1209
1210       if (distMax < myTolerance) 
1211       {
1212         tabDst(i) = distMax;
1213         tabMinDist(i) = aMinDist;
1214       }
1215     }
1216
1217     idx1++; // To the next distant curve
1218   }*/
1219 }
1220
1221 //=======================================================================
1222 //function : IsMergedClosed
1223 //purpose  :  internal use
1224 //=======================================================================
1225
1226 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1227                                                  const TopoDS_Edge& Edge2,
1228                                                  const TopoDS_Face& face) const
1229 {
1230   // Check for closed surface
1231   TopLoc_Location loc;
1232   Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1233   Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1234   Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1235   if (!isUClosed && !isVClosed) return Standard_False;
1236   // Check condition on closed surface
1237   /*
1238   Standard_Real first1,last1,first2,last2;
1239   Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1240   Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1241   if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1242   */
1243   Standard_Real first2d1,last2d1,first2d2,last2d2;
1244   Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1245   Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1246   if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1247   /*
1248   gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1249   gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1250   Standard_Real dist = p1.Distance(p2);
1251   gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1252   gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1253   Standard_Real dist2d = p12d.Distance(p22d);
1254   GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1255   Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1256   return (dist2d*0.2 >= distSurf);
1257   */
1258   Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1259   Standard_Real SUmin, SUmax, SVmin, SVmax;
1260   Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1261   Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1262   { //szv: Use brackets to destroy local variables
1263     Bnd_Box2d B1, B2;
1264     Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1265     BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1266     BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1267     B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1268     B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1269     Standard_Real du, dv;
1270     du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1271     isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1272     du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1273     isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1274     surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1275   }
1276   if (isUClosed && isVLongC1 && isVLongC2) {
1277     // Do not merge if not overlapped by V
1278     Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1279     if (dist < 0.0) {
1280       Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1281       Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1282       if (distOuter <= distInner) return Standard_True;
1283     }
1284   }
1285   if (isVClosed && isULongC1 && isULongC2) {
1286     // Do not merge if not overlapped by U
1287     Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1288     if (dist < 0.0) {
1289       Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1290       Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1291       if (distOuter <= distInner) return Standard_True;
1292     }
1293   }
1294   return Standard_False;
1295 }
1296
1297 //=======================================================================
1298 //function : AnalysisNearestEdges
1299 //purpose  : 
1300 //=======================================================================
1301
1302 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1303                                                  TColStd_SequenceOfInteger& seqIndCandidate,
1304                                                  TColStd_SequenceOfInteger& seqOrientations,
1305                                                  const Standard_Boolean evalDist)
1306 {
1307
1308   Standard_Integer workIndex = seqIndCandidate.First();
1309   TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1310   TopoDS_Shape bnd = workedge;
1311   TopTools_ListOfShape workfaces;
1312   if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1313   if (myBoundFaces.Contains(bnd)) 
1314     workfaces = myBoundFaces.FindFromKey(bnd);
1315   if(workfaces.IsEmpty()) return;
1316   TopTools_MapOfShape mapFaces;
1317   TopTools_ListIteratorOfListOfShape lIt;
1318   for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1319     mapFaces.Add(lIt.Value());
1320   TColStd_SequenceOfInteger seqNotCandidate;
1321   TColStd_SequenceOfInteger seqNewForward;
1322   // Separates edges belonging the same face as work edge 
1323   // for exception of edges belonging closed faces 
1324
1325   seqNotCandidate.Append(workIndex);
1326   for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1327     Standard_Integer index = seqIndCandidate.Value(i);
1328     Standard_Boolean isRemove = Standard_False;
1329     if(index == workIndex) {
1330       seqIndCandidate.Remove(i);
1331       seqOrientations.Remove(i);
1332       isRemove = Standard_True;
1333     }
1334     if(!isRemove) {
1335       TopoDS_Shape bnd2 = sequenceSec.Value(index);
1336       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1337
1338       if(myBoundFaces.Contains(bnd2)) {
1339         const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1340         Standard_Boolean isMerged = Standard_True;
1341         for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1342           if(mapFaces.Contains(lIt.Value())) {
1343             TopLoc_Location loc;
1344             Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1345             isMerged = ((IsUClosedSurface(surf,bnd2,loc) ||  IsVClosedSurface(surf,bnd2,loc)) && 
1346               IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1347           }
1348         }
1349         if(!isMerged) {
1350           seqNotCandidate.Append(index);
1351           seqIndCandidate.Remove(i);
1352           seqOrientations.Remove(i);
1353           isRemove = Standard_True;
1354         }
1355       }
1356       else {
1357         seqIndCandidate.Remove(i);
1358         seqOrientations.Remove(i);
1359         isRemove = Standard_True;
1360       }
1361     }
1362     if(!isRemove) i++;  
1363   }
1364   if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1365   if(!evalDist) return;
1366   TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1367   TColStd_MapOfInteger MapIndex;
1368   TColStd_SequenceOfInteger seqForward;
1369
1370   // Definition and removing edges wich are not candidate for work edge 
1371   // ( they have other nearest edges belonging to the work face) 
1372   for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1373     Standard_Integer index1 = seqNotCandidate.Value(k);
1374     TopoDS_Shape edge = sequenceSec.Value(index1);
1375     TopTools_SequenceOfShape tmpSeq;
1376     tmpSeq.Append(edge);
1377     for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++) 
1378       tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1379
1380     Standard_Integer lengSec = tmpSeq.Length();
1381     TColStd_Array1OfBoolean tabForward(1,lengSec);
1382     TColStd_Array1OfReal tabDist(1,lengSec);
1383     TColStd_Array1OfReal arrLen(1,lengSec);
1384     TColStd_Array1OfReal tabMinDist(1,lengSec);
1385     for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++) 
1386       tabDist(i1) =-1;
1387
1388     EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1389     if(k == 1) {
1390       for(Standard_Integer n = 1; n < lengSec; n++) {
1391         if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1392           MapIndex.Add(n);
1393           continue;
1394         }
1395         TotTabDist(k,n) = tabDist(n+1 );
1396         seqForward.Append(tabForward(n+1) ? 1:0);
1397       }
1398     }
1399     else {
1400       for(Standard_Integer n = 1; n < lengSec; n++) {
1401         if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1402         if(tabDist(n+1) < TotTabDist(1,n)) {
1403           MapIndex.Add(n);
1404         }
1405       }
1406     }
1407
1408   }
1409
1410   Standard_Integer i2 = seqIndCandidate.Length();
1411   for( ; i2 >=1 ; i2--)
1412   {
1413     if(MapIndex.Contains(i2))
1414     { 
1415       seqIndCandidate.Remove(i2);
1416       seqOrientations.Remove(i2);
1417     }
1418
1419   }
1420   //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1421   //  seqIndCandidate.Remove(IMap.Key());
1422   //  seqOrientations.Remove(IMap.Key());
1423   //}
1424 }
1425
1426 //=======================================================================
1427 //function : FindCandidates
1428 //purpose  : internal use
1429 //=======================================================================
1430
1431 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1432                                                        TColStd_IndexedMapOfInteger& mapReference,
1433                                                        TColStd_SequenceOfInteger& seqCandidates,
1434                                                        TColStd_SequenceOfInteger& seqOrientations)
1435 {
1436   Standard_Integer i, nbSections = seqSections.Length();
1437   if(nbSections <= 1)
1438     return Standard_False;
1439   // Retrieve last reference index
1440   Standard_Integer indReference = mapReference(mapReference.Extent());
1441   Standard_Integer nbCandidates = 0;
1442   TopTools_MapOfShape Faces1;
1443   //if (nbSections > 1) {
1444
1445   TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1446
1447   // Retrieve faces for reference section
1448
1449   { //szv: Use brackets to destroy local variables
1450     TopoDS_Shape bnd = Edge1;
1451     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1452     if (myBoundFaces.Contains(bnd)) {
1453       TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1454       for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1455     }
1456   }
1457
1458   // Check merging conditions for candidates and remove unsatisfactory
1459   TopTools_SequenceOfShape seqSectionsNew;
1460   TColStd_SequenceOfInteger seqCandidatesNew;
1461   for (i = 1; i <= nbSections; i++) {
1462     if (i == indReference) {
1463       seqSectionsNew.Prepend(Edge1);
1464       seqCandidatesNew.Prepend(i);
1465     }
1466     else {
1467       const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1468       seqSectionsNew.Append(Edge2);
1469       seqCandidatesNew.Append(i);
1470     }
1471   }
1472
1473   Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1474   if (nbSectionsNew > 1) {
1475     
1476     // Evaluate distances between reference and other sections
1477     TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1478     TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1479     TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1480     TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1481     EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1482     
1483     // Fill sequence of candidate indices sorted by distance
1484     for (i = 2; i <= nbSectionsNew; i++) {
1485       Standard_Real aMaxDist = arrDistance(i);
1486       if (aMaxDist >= 0.0 && aMaxDist <= myTolerance &&  arrLen(i) > myMinTolerance) {
1487         
1488         // Reference section is connected to section #i
1489         Standard_Boolean isInserted = Standard_False;
1490         Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1491         for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1492           Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1493           
1494           if( aDelta < Precision::Confusion()) {
1495
1496             if(fabs(aDelta) > RealSmall() || 
1497               arrMinDist(i) < arrMinDist(seqCandidates.Value(j))) 
1498             {
1499               seqCandidates.InsertBefore(j,i);
1500               seqOrientations.InsertBefore(j,ori);
1501               isInserted = Standard_True;
1502             }
1503           }
1504         }
1505         if (!isInserted) {
1506           seqCandidates.Append(i);
1507           seqOrientations.Append(ori);
1508         }
1509       }
1510     }
1511    
1512     nbCandidates = seqCandidates.Length();
1513     if (!nbCandidates) 
1514       return Standard_False; // Section has no candidates to merge
1515     
1516     // Replace candidate indices
1517    
1518     for (i = 1; i <= nbCandidates; i++)
1519       seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1520     
1521   }
1522   
1523   if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1524
1525   if (myNonmanifold && nbCandidates >1) {
1526     TColStd_SequenceOfInteger seqNewCandidates;
1527     TColStd_SequenceOfInteger seqOrientationsNew;
1528     seqCandidates.Prepend(1);
1529     seqOrientations.Prepend(1);
1530     for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1531       AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1532       if(k == 1 && !seqCandidates.Length()) return Standard_False;
1533       if(seqCandidates.Length()) {
1534         seqNewCandidates.Append(seqCandidates.First());
1535         seqOrientationsNew.Append(seqOrientations.First()); 
1536       }
1537     }
1538     seqCandidates.Prepend(seqNewCandidates);
1539     seqOrientations.Prepend(seqOrientationsNew);
1540     return Standard_True;
1541   }
1542   else {
1543
1544     // For manifold case leave only one candidate from equidistant candidates
1545     /*Standard_Integer minIndex = seqCandidateIndex.First();
1546     Standard_Real minDistance = arrDistance(minIndex);
1547
1548     // Find equidistant candidates
1549     TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1550     for (i = 2; i <= nbCandidates; i++) {
1551     Standard_Integer index = seqCandidateIndex(i);
1552     if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1553     seqEqDistantIndex.Append(index);
1554     }
1555
1556     Standard_Integer eqLen = seqEqDistantIndex.Length();
1557     if (eqLen > 2) {
1558
1559     // Fill map of faces which equidistant sections belong to
1560     TopTools_MapOfShape mapFace;
1561     for (i = 1; i <= eqLen; i++) {
1562     Standard_Integer index = seqEqDistantIndex.Value(i);
1563     if (isCandidate(index)) {
1564     mapFace.Add(arrFace(index));
1565     }
1566     }
1567
1568     // Non Manifold case
1569     // Edges are merged by pair among a face continuity C1 criterion
1570     if (mapFace.Extent() == eqLen) {
1571
1572     tabDist.Init(-1);
1573     tabMinInd.Init(-1);
1574     min=10000000.;
1575     //indMin = -1;
1576     Standard_Integer indMin = -1;// To check if the edge can be merged.
1577     // Computation of distances between the edges.
1578     TopTools_SequenceOfShape seqSh;
1579     Standard_Integer nbInd = EqDistSeq.Length();
1580     TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1581     seqSh.Append(sequenceSec.Value(1));
1582     for (j = 2; j <= EqDistSeq.Length(); j++) {
1583     Standard_Integer index = EqDistSeq.Value(j);
1584     tmptabForward(j) = tabForward(index);
1585     seqSh.Append(sequenceSec.Value(index));
1586     }
1587
1588     EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1589
1590     for(j=2; j <= seqSh.Length(); j++) {
1591     if (tabDist(j) > -1.) {  // if edge(j) is connected to edge(i)
1592     if (min > tabDist(j)) {
1593     min = tabDist(j);
1594     indMin = j;
1595     }
1596     }
1597     }
1598
1599     //  Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1600     if (indMin > 0) {
1601     seqSh.Remove(indMin);
1602     for(j =2; j <= tmpSeq.Length(); ) {
1603     TopoDS_Shape sh = tmpSeq.Value(j);
1604     Standard_Boolean isRem = Standard_False;
1605     for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1606     if(seqSh.Value(k) == sh) {
1607     isRem = Standard_True;
1608     break;
1609     }
1610     }
1611     if(isRem) {
1612     tmpSeq.Remove(j);
1613     tabMinForward.Remove(j); // = -1;
1614     } 
1615     else j++;
1616     }
1617     }
1618     }
1619     }*/
1620
1621     // Find the best approved candidate
1622     while (nbCandidates) {
1623       // Retrieve first candidate
1624       Standard_Integer indCandidate = seqCandidates.First();
1625       // Candidate is approved if it is in the map
1626       if (mapReference.Contains(indCandidate)) break;
1627       // Find candidates for candidate #indCandidate
1628       mapReference.Add(indCandidate); // Push candidate in the map
1629       TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1630       Standard_Boolean isFound =
1631         FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1632       mapReference.RemoveLast(); // Pop candidate from the map
1633       if (isFound) isFound = (seqCandidates1.Length() > 0);
1634       if (isFound) {
1635         Standard_Integer indCandidate1 = seqCandidates1.First();
1636         // If indReference is the best candidate for indCandidate
1637         // then indCandidate is the best candidate for indReference
1638         if (indCandidate1 == indReference) break;
1639         // If some other reference in the map is the best candidate for indCandidate
1640         // then assume that reference is the best candidate for indReference
1641         if (mapReference.Contains(indCandidate1)) {
1642           seqCandidates.Prepend(indCandidate1);
1643           nbCandidates++;
1644           break;
1645         }
1646         isFound = Standard_False;
1647       }
1648       if (!isFound) {
1649         // Remove candidate #1
1650         seqCandidates.Remove(1);
1651         seqOrientations.Remove(1);
1652         nbCandidates--;
1653       }
1654     }
1655   }
1656   //gka
1657   if(nbCandidates > 0)
1658   {
1659     Standard_Integer anInd = seqCandidates.Value(1);
1660     TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1661     TopoDS_Shape bnd = Edge2;
1662     if (mySectionBound.IsBound(bnd)) 
1663       bnd = mySectionBound(bnd);
1664     //gka
1665     if (myBoundFaces.Contains(bnd)) {
1666       Standard_Boolean isOK = Standard_True;
1667       TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1668       for (; itf2.More() && isOK; itf2.Next()) {
1669         const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1670         // Check whether condition is satisfied
1671         isOK = !Faces1.Contains(Face2);
1672         if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1673       }
1674       if(!isOK)
1675         return Standard_False;
1676     }
1677   }
1678   return (nbCandidates > 0);
1679 }
1680
1681 //=======================================================================
1682 //function : Constructor
1683 //purpose  : 
1684 //=======================================================================
1685
1686 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1687                                  const Standard_Boolean optionSewing,
1688                                  const Standard_Boolean optionAnalysis,
1689                                  const Standard_Boolean optionCutting,
1690                                  const Standard_Boolean optionNonmanifold)
1691 {
1692   myReShape = new BRepTools_ReShape;
1693   Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1694 }
1695
1696 //=======================================================================
1697 //function : Init
1698 //purpose  : Initialise Talerance, and options sewing, faceAnalysis and cutting
1699 //=======================================================================
1700
1701 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1702                            const Standard_Boolean optionSewing,
1703                            const Standard_Boolean optionAnalysis,
1704                            const Standard_Boolean optionCutting,
1705                            const Standard_Boolean optionNonmanifold)
1706 {
1707   // Set tolerance and Perform options
1708   myTolerance      = Max (tolerance, Precision::Confusion());
1709   mySewing         = optionSewing;
1710   myAnalysis       = optionAnalysis;
1711   myCutting        = optionCutting;
1712   myNonmanifold    = optionNonmanifold;
1713   // Set min and max tolerances
1714   myMinTolerance   = myTolerance * 1e-4; //szv: proposal
1715   if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1716   myMaxTolerance   = Precision::Infinite();
1717   // Set other modes
1718   myFaceMode           = Standard_True;
1719   myFloatingEdgesMode  = Standard_False;
1720   //myCuttingFloatingEdgesMode = Standard_False; //gka
1721   mySameParameterMode  = Standard_True;
1722   myLocalToleranceMode = Standard_False;
1723   mySewedShape.Nullify();
1724   // Load empty shape
1725   Load(TopoDS_Shape());
1726 }
1727
1728 //=======================================================================
1729 //function : Load
1730 //purpose  : Loads the context shape
1731 //=======================================================================
1732
1733 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1734 {
1735   myReShape->Clear();
1736   if (theShape.IsNull()) myShape.Nullify();
1737   else myShape = myReShape->Apply(theShape);
1738   mySewedShape.Nullify();
1739   // Nullify flags and counters
1740   myNbShapes = myNbEdges = myNbVertices = 0;
1741   // Clear all maps
1742   myOldShapes.Clear();
1743   //myOldFaces.Clear();
1744   myDegenerated.Clear();
1745   myFreeEdges.Clear();
1746   myMultipleEdges.Clear();
1747   myContigousEdges.Clear();
1748   myContigSecBound.Clear();
1749   myBoundFaces.Clear();
1750   myBoundSections.Clear();
1751   myVertexNode.Clear();
1752   myVertexNodeFree.Clear();
1753   myNodeSections.Clear();
1754   myCuttingNode.Clear();
1755   mySectionBound.Clear();
1756   myLittleFace.Clear();
1757 }
1758
1759 //=======================================================================
1760 //function : Add
1761 //purpose  : 
1762 //=======================================================================
1763
1764 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1765 {
1766   if (aShape.IsNull()) return;
1767   TopoDS_Shape oShape = myReShape->Apply(aShape);
1768   myOldShapes.Add(aShape,oShape);
1769   myNbShapes = myOldShapes.Extent();
1770 }
1771
1772 //=======================================================================
1773 //function : Perform
1774 //purpose  : 
1775 //=======================================================================
1776
1777 #ifdef DEB
1778 #include <OSD_Timer.hxx>
1779 #endif
1780
1781 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1782 {
1783   const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1784   Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1785 #ifdef DEB
1786   Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1787   OSD_Chronometer chr_total, chr_local;
1788   chr_total.Reset();
1789   chr_total.Start();
1790 #endif
1791
1792   // face analysis
1793   if (myAnalysis)
1794   {
1795 #if DEB
1796     cout << "Begin face analysis..." << endl;
1797     chr_local.Reset();
1798     chr_local.Start();
1799 #endif
1800     FaceAnalysis (thePI);
1801     if (!aPS.More())
1802       return;
1803     aPS.Next();
1804 #if DEB
1805     chr_local.Stop();
1806     chr_local.Show(t_analysis);
1807     cout << "Face analysis finished after " << t_analysis << " s" << endl;
1808 #endif
1809   }
1810
1811   if (myNbShapes || !myShape.IsNull())
1812   {
1813
1814     FindFreeBoundaries();
1815
1816     if (myBoundFaces.Extent())
1817     {
1818
1819 #if DEB
1820       cout << "Begin vertices assembling..." << endl;
1821       chr_local.Reset();
1822       chr_local.Start();
1823 #endif
1824       VerticesAssembling (thePI);
1825       if (!aPS.More())
1826         return;
1827       aPS.Next();
1828 #if DEB
1829       chr_local.Stop();
1830       chr_local.Show(t_assembling);
1831       cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1832 #endif
1833       if (myCutting)
1834       {
1835 #if DEB
1836         cout << "Begin cutting..." << endl;
1837         chr_local.Reset();
1838         chr_local.Start();
1839 #endif
1840         Cutting (thePI);
1841         if (!aPS.More())
1842           return;
1843         aPS.Next();
1844 #if DEB
1845         chr_local.Stop();
1846         chr_local.Show(t_cutting);
1847         cout << "Cutting finished after " << t_cutting << " s" << endl;
1848 #endif
1849       }
1850 #if DEB
1851       cout << "Begin merging..." << endl;
1852       chr_local.Reset();
1853       chr_local.Start();
1854 #endif
1855       Merging (Standard_True, thePI);
1856       if (!aPS.More())
1857         return;
1858       aPS.Next();
1859 #if DEB
1860       chr_local.Stop();
1861       chr_local.Show(t_merging);
1862       cout << "Merging finished after " << t_merging << " s" << endl;
1863 #endif
1864     }
1865     else
1866     {
1867       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1868       if (myCutting)
1869         aPS.Next( 1, Handle(TCollection_HAsciiString)());
1870       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1871       if (!aPS.More())
1872         return;
1873     }
1874
1875     if (mySewing)
1876     {
1877
1878 #if DEB
1879       cout << "Creating sewed shape..." << endl;
1880 #endif
1881       // examine the multiple edges if any and process sameparameter for edges if necessary
1882       EdgeProcessing (thePI);
1883       if (!aPS.More())
1884         return;
1885       CreateSewedShape();
1886       if (!aPS.More())
1887       {
1888         mySewedShape.Nullify();
1889         return;
1890       }
1891       if (mySameParameterMode && myFaceMode)
1892         SameParameterShape();
1893       if (!aPS.More())
1894       {
1895         mySewedShape.Nullify();
1896         return;
1897       }
1898 #if DEB
1899       cout << "Sewed shape created" << endl;
1900 #endif
1901     }
1902
1903     // create edge informations for output
1904     CreateOutputInformations();
1905     if (!aPS.More())
1906     {
1907       mySewedShape.Nullify();
1908       return;
1909     }
1910   }
1911 #if DEB
1912   chr_total.Stop();
1913   chr_total.Show(t_total);
1914   cout << "Sewing finished!" << endl;
1915   cout << " analysis time   : " << t_analysis << " s" << endl;
1916   cout << " assembling time : " << t_assembling << " s" << endl;
1917   cout << " cutting time    : " << t_cutting << " s" << endl;
1918   cout << " merging time    : " << t_merging << " s" << endl;
1919   cout << "Total time       : " << t_total << " s" << endl;
1920 #endif
1921 }
1922
1923 //=======================================================================
1924 //function : SewedShape
1925 //purpose  : give the sewed shape
1926 //           if a null shape, reasons:
1927 //             -- no useable input shapes : all input shapes are degenerated
1928 //             -- has multiple edges
1929 //=======================================================================
1930
1931 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1932 {
1933   return mySewedShape;
1934 }
1935
1936 //=======================================================================
1937 //function : NbFreeEdges
1938 //purpose  : 
1939 //=======================================================================
1940
1941 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1942 {
1943   return myFreeEdges.Extent();
1944 }
1945
1946 //=======================================================================
1947 //function : FreeEdge
1948 //purpose  : 
1949 //=======================================================================
1950
1951 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1952 {
1953   Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1954   return TopoDS::Edge(myFreeEdges(index));
1955 }
1956
1957 //=======================================================================
1958 //function : NbMultipleEdges
1959 //purpose  : 
1960 //=======================================================================
1961
1962 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1963 {
1964   return myMultipleEdges.Extent();
1965 }
1966
1967 //=======================================================================
1968 //function : MultipleEdge
1969 //purpose  : 
1970 //=======================================================================
1971
1972 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1973 {
1974   Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1975   return TopoDS::Edge(myMultipleEdges(index));
1976 }
1977
1978 //=======================================================================
1979 //function : NbContigousEdges
1980 //purpose  : 
1981 //=======================================================================
1982
1983 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1984 {
1985   return myContigousEdges.Extent();
1986 }
1987
1988 //=======================================================================
1989 //function : ContigousEdge
1990 //purpose  : 
1991 //=======================================================================
1992
1993 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
1994 {
1995   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
1996   return TopoDS::Edge(myContigousEdges.FindKey(index));
1997 }
1998
1999 //=======================================================================
2000 //function : ContigousEdgeCouple
2001 //purpose  : 
2002 //=======================================================================
2003
2004 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2005 {
2006   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2007   return myContigousEdges(index);
2008 }
2009
2010 //=======================================================================
2011 //function : IsSectionBound
2012 //purpose  : 
2013 //=======================================================================
2014
2015 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2016 {
2017   if(myContigSecBound.IsBound(section)) {
2018     return Standard_True;
2019   }
2020   else {
2021     return Standard_False;
2022   }
2023 }
2024
2025 //=======================================================================
2026 //function : SectionToBoundary
2027 //purpose  : 
2028 //=======================================================================
2029
2030 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2031 {
2032   Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2033   return TopoDS::Edge(myContigSecBound(section));
2034 }
2035 //=======================================================================
2036 //function : NbDeletedFaces
2037 //purpose  : 
2038 //=======================================================================
2039  Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2040 {
2041   return myLittleFace.Extent();
2042 }
2043
2044 //=======================================================================
2045 //function : DeletedFace
2046 //purpose  : 
2047 //=======================================================================
2048 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2049 {
2050   Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2051   return TopoDS::Face(myLittleFace(index));
2052 }
2053
2054 //=======================================================================
2055 //function : NbDegeneratedShapes
2056 //purpose  : 
2057 //=======================================================================
2058
2059 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2060 {
2061   return myDegenerated.Extent();
2062 }
2063
2064 //=======================================================================
2065 //function : DegeneratedShape
2066 //purpose  : 
2067 //=======================================================================
2068
2069 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2070 {
2071   Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2072   return myDegenerated(index);
2073 }
2074
2075 //=======================================================================
2076 //function : IsDegenerated
2077 //purpose  : 
2078 //=======================================================================
2079
2080 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2081 {
2082   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2083   // Degenerated face
2084   if (aShape.ShapeType() == TopAbs_FACE)
2085     return NewShape.IsNull();
2086   if (NewShape.IsNull()) return Standard_False;
2087   // Degenerated edge
2088   if (NewShape.ShapeType() == TopAbs_EDGE)
2089     return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2090   // Degenerated wire
2091   if (NewShape.ShapeType() == TopAbs_WIRE) {
2092     Standard_Boolean isDegenerated = Standard_True;
2093     for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2094       isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2095     return isDegenerated;
2096   }
2097   return Standard_False;
2098 }
2099   
2100 //=======================================================================
2101 //function : IsModified
2102 //purpose  : 
2103 //=======================================================================
2104
2105 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2106 {
2107   TopoDS_Shape NewShape = aShape;
2108   if (myOldShapes.Contains(aShape)) 
2109     NewShape = myOldShapes.FindFromKey(aShape);
2110   if(!NewShape.IsSame(aShape)) return Standard_True;
2111   return Standard_False;
2112 }
2113
2114 //=======================================================================
2115 //function : Modified
2116 //purpose  : 
2117 //=======================================================================
2118
2119 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2120
2121   if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2122   //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2123   return aShape;
2124 }
2125
2126 //=======================================================================
2127 //function : IsModifiedSubShape
2128 //purpose  : 
2129 //=======================================================================
2130
2131 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2132 {
2133   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2134   if(!NewShape.IsSame(aShape)) return Standard_True;
2135   return Standard_False;
2136 }
2137
2138 //=======================================================================
2139 //function : ModifiedSubShape
2140 //purpose  : 
2141 //=======================================================================
2142
2143 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2144
2145   return myReShape->Apply(aShape);
2146 }
2147
2148 //=======================================================================
2149 //function : Dump
2150 //purpose  : 
2151 //=======================================================================
2152
2153 void BRepBuilderAPI_Sewing::Dump() const
2154 {
2155   Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2156   TopTools_MapOfShape mapVertices, mapEdges;
2157   for (i = 1; i <= NbBounds; i++) {
2158     TopoDS_Shape bound = myBoundFaces.FindKey(i);
2159     if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2160     else NbSections++;
2161     TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2162     for (; aExp.More(); aExp.Next()) {
2163       TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2164       mapEdges.Add(E);
2165       TopoDS_Vertex V1, V2;
2166       TopExp::Vertices(E,V1,V2);
2167       mapVertices.Add(V1);
2168       mapVertices.Add(V2);
2169     }
2170   }
2171   cout << " " << endl;
2172   cout << "                        Informations                        " << endl;
2173   cout << " ===========================================================" << endl;
2174   cout << " " << endl;
2175   cout << " Number of input shapes      : " << myOldShapes.Extent() << endl;
2176   cout << " Number of actual shapes     : " << myNbShapes << endl;
2177   cout << " Number of Bounds            : " << NbBounds << endl;
2178   cout << " Number of Sections          : " << NbSections << endl;
2179   cout << " Number of Edges             : " << mapEdges.Extent() << endl;
2180   cout << " Number of Vertices          : " << myNbVertices << endl;
2181   cout << " Number of Nodes             : " << mapVertices.Extent() << endl;
2182   cout << " Number of Free Edges        : " << myFreeEdges.Extent() << endl;
2183   cout << " Number of Contigous Edges   : " << myContigousEdges.Extent() << endl;
2184   cout << " Number of Multiple Edges    : " << myMultipleEdges.Extent() << endl;
2185   cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2186   cout << " ===========================================================" << endl;
2187   cout << " " << endl;
2188 }
2189
2190 //=======================================================================
2191 //function : FaceAnalysis
2192 //purpose  : Remove
2193 //           Modifies:
2194 //                      myNbShapes
2195 //                      myOldShapes
2196 //
2197 //           Constructs:
2198 //                      myDegenerated
2199 //=======================================================================
2200
2201 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2202 {
2203   if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2204     Add(myShape);
2205     myShape.Nullify();
2206   }
2207
2208   BRep_Builder B;
2209   TopTools_MapOfShape SmallEdges;
2210   TopTools_DataMapOfShapeListOfShape GluedVertices;
2211   Standard_Integer i = 1;
2212   Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2213   for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2214     for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2215
2216       // Retrieve current face
2217       TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2218       TopoDS_Face face = TopoDS::Face(aTmpShape);
2219       Standard_Integer nbEdges = 0, nbSmall = 0;
2220
2221       // Build replacing face
2222       aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2223       TopoDS_Face nface = TopoDS::Face(aTmpShape);
2224       Standard_Boolean isFaceChanged = Standard_False;
2225
2226       TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2227       for (; witer.More(); witer.Next()) {
2228
2229         // Retrieve current wire
2230         aTmpShape = witer.Value(); //for porting
2231         if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2232         TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2233
2234         // Build replacing wire
2235         aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2236         TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2237         Standard_Boolean isWireChanged = Standard_False;
2238
2239         TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2240         for (; eiter.More(); eiter.Next()) {
2241
2242           // Retrieve current edge
2243           aTmpShape = eiter.Value(); //for porting
2244           TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2245           nbEdges++;
2246
2247           // Process degenerated edge
2248           if (BRep_Tool::Degenerated(edge)) {
2249             B.Add(nwire,edge); // Old edge kept
2250             myDegenerated.Add(edge);
2251             nbSmall++;
2252             continue;
2253           }
2254
2255           Standard_Boolean isSmall = SmallEdges.Contains(edge);
2256           if (!isSmall) {
2257
2258             // Check for small edge
2259             Standard_Real first, last;
2260             Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2261             if (c3d.IsNull()) {
2262 #ifdef DEB
2263               cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2264 #endif
2265             }
2266             else {
2267               // Evaluate curve compactness
2268               const Standard_Integer npt = 5;
2269               gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2270               Standard_Real dist, maxdist = 0.0;
2271               Standard_Real delta = (last - first)/(npt - 1);
2272               for (Standard_Integer idx = 0; idx < npt; idx++) {
2273                 dist = cp.Distance(c3d->Value(first + idx*delta));
2274                 if (maxdist < dist) maxdist = dist;
2275               }
2276               isSmall = (2.*maxdist <= MinTolerance());
2277               /*try {
2278                 GeomAdaptor_Curve cAdapt(c3d);
2279                 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2280                 isSmall = (length <= MinTolerance());
2281               }
2282               catch (Standard_Failure) {
2283 #ifdef DEB
2284                 cout << "Warning: Possibly small edge can be sewed: ";
2285                 Standard_Failure::Caught()->Print(cout); cout << endl;
2286 #endif
2287               }*/
2288             }
2289
2290             if (isSmall) {
2291
2292               // Store small edge in the map
2293               SmallEdges.Add(edge);
2294
2295               TopoDS_Vertex v1, v2;
2296               TopExp::Vertices(edge,v1,v2);
2297               TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2298
2299               // Store glued vertices
2300               if (!nv1.IsSame(v1)) {
2301                 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2302                 // First vertex was already glued
2303                 if (!nv2.IsSame(v2)) {
2304                   // Merge lists of glued vertices
2305                   if (!nv1.IsSame(nv2)) {
2306                     TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2307                     for (; liter.More(); liter.Next()) {
2308                       TopoDS_Shape v = liter.Value();
2309                       myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2310                       vlist1.Append(v);
2311                     }
2312                     GluedVertices.UnBind(nv2);
2313                   }
2314                 }
2315                 else {
2316                   // Add second vertex to the existing list
2317                   vlist1.Append(v2);
2318                   myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2319                 }
2320               }
2321               else if (!nv2.IsSame(v2)) {
2322                 // Add first vertex to the existing list
2323                 GluedVertices(nv2).Append(v1);
2324                 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2325               }
2326               else if (!v1.IsSame(v2)) {
2327                 // Record new glued vertices
2328                 TopoDS_Vertex nv;
2329                 B.MakeVertex(nv);
2330                 TopTools_ListOfShape vlist;
2331                 vlist.Append(v1);
2332                 vlist.Append(v2);
2333                 GluedVertices.Bind(nv,vlist);
2334                 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2335                 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2336               }
2337             }
2338           }
2339
2340           // Replace small edge
2341           if (isSmall) {
2342 #ifdef DEB
2343             cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2344 #endif
2345             nbSmall++;
2346             // Create new degenerated edge
2347             aTmpShape = edge.Oriented(TopAbs_FORWARD);
2348             TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2349             Standard_Real pfirst, plast;
2350             Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2351             if (!c2d.IsNull()) {
2352               TopoDS_Edge nedge;
2353               B.MakeEdge(nedge);
2354               B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2355               B.Range(nedge,pfirst,plast);
2356               B.Degenerated(nedge,Standard_True);
2357               TopoDS_Vertex v1, v2;
2358               TopExp::Vertices(fedge,v1,v2);
2359               B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2360               B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2361               B.Add(nwire,nedge.Oriented(edge.Orientation()));
2362               myDegenerated.Add(nedge);
2363             }
2364             isWireChanged = Standard_True;
2365           }
2366           else B.Add(nwire,edge); // Old edge kept
2367         }
2368
2369         // Record wire in the new face
2370         if (isWireChanged) {
2371           B.Add(nface,nwire.Oriented(wire.Orientation()));
2372           isFaceChanged = Standard_True;
2373         }
2374         else B.Add(nface,wire);
2375       }
2376
2377       // Remove small face
2378       if (nbSmall == nbEdges) {
2379 #ifdef DEB
2380         cout << "Warning: Small face removed by FaceAnalysis" << endl;
2381 #endif
2382         myLittleFace.Add(face);
2383         myReShape->Remove(face);
2384       }
2385       else if (isFaceChanged) {
2386
2387         myReShape->Replace(face,nface.Oriented(face.Orientation()));
2388       }
2389     }
2390   }
2391
2392   // Update glued vertices
2393   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2394   for (; miter.More(); miter.Next()) {
2395     TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2396     gp_XYZ coord(0.,0.,0.);
2397     Standard_Integer nbPoints = 0;
2398     const TopTools_ListOfShape& vlist = miter.Value();
2399     TopTools_ListIteratorOfListOfShape liter1(vlist);
2400     for (; liter1.More(); liter1.Next()) {
2401       coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2402       nbPoints++;
2403     }
2404     if (nbPoints) {
2405       gp_Pnt vp(coord / nbPoints);
2406       Standard_Real tol = 0.0, mtol = 0.0;
2407       TopTools_ListIteratorOfListOfShape liter2(vlist);
2408       for (; liter2.More(); liter2.Next()) {
2409         Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2410         if (mtol < vtol) mtol = vtol;
2411         vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2412         if (tol < vtol) tol = vtol;
2413       }
2414       B.UpdateVertex(vnew,vp,tol+mtol);
2415     }
2416   }
2417
2418   // Update input shapes
2419   for (i = 1; i <= myOldShapes.Extent(); i++)
2420     myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2421 }
2422
2423 //=======================================================================
2424 //function : FindFreeBoundaries
2425 //purpose  : Constructs :
2426 //                      myBoundFaces     (bound = list of faces) - REFERENCE
2427 //                      myVertexNode     (vertex = node)
2428 //                      myVertexNodeFree (floating vertex = node)
2429 //
2430 //=======================================================================
2431
2432 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2433 {
2434   // Take into account the context shape if needed
2435   TopTools_IndexedMapOfShape NewShapes;
2436   if (!myShape.IsNull()) {
2437     if (myOldShapes.IsEmpty()) {
2438       Add(myShape);
2439       myShape.Nullify();
2440     }
2441     else {
2442       TopoDS_Shape newShape = myReShape->Apply(myShape);
2443       if (!newShape.IsNull()) NewShapes.Add(newShape);
2444     }
2445   }
2446   // Create map Edge -> Faces
2447   TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2448   Standard_Integer i, nbShapes = myOldShapes.Extent();
2449   for (i = 1; i <= nbShapes; i++) {
2450     // Retrieve new shape
2451     TopoDS_Shape shape = myOldShapes(i);
2452     if (shape.IsNull()) continue;
2453     NewShapes.Add(shape);
2454     // Explore shape to find all boundaries
2455     for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2456       TopoDS_Shape edge = eExp.Current();
2457       if (!EdgeFaces.Contains(edge)) {
2458         TopTools_ListOfShape listFaces;
2459         EdgeFaces.Add(edge,listFaces);
2460       }
2461     }
2462   }
2463   // Fill map Edge -> Faces
2464   nbShapes = NewShapes.Extent();
2465    TopTools_MapOfShape mapFaces;
2466   for (i = 1; i <= nbShapes; i++) {
2467     // Explore shape to find all faces
2468     TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2469     for (; fExp.More(); fExp.Next()) {
2470       TopoDS_Shape face = fExp.Current();
2471       if(mapFaces.Contains(face)) continue;
2472       else 
2473         mapFaces.Add(face);
2474       // Explore face to find all boundaries
2475       for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2476         if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2477         for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2478           
2479           TopoDS_Shape edge = aIIe.Value();
2480           
2481           if (EdgeFaces.Contains(edge)) {
2482             EdgeFaces.ChangeFromKey(edge).Append(face);
2483             //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2484             //Standard_Boolean isContained = Standard_False;
2485             //TopTools_ListIteratorOfListOfShape itf(listFaces);
2486             //for (; itf.More() && !isContained; itf.Next())
2487             //  isContained = face.IsSame(itf.Value());
2488             //if (!isContained) listFaces.Append(face);
2489           }
2490         }
2491       }
2492     }
2493   }
2494   // Find free boundaries
2495   nbShapes = EdgeFaces.Extent();
2496   for (i = 1; i <= nbShapes; i++) {
2497     TopTools_ListOfShape& listFaces = EdgeFaces(i);
2498     Standard_Integer nbFaces = listFaces.Extent();
2499     TopoDS_Shape edge    = EdgeFaces.FindKey(i);
2500     if(edge.Orientation() == TopAbs_INTERNAL)
2501           continue;
2502     Standard_Boolean isSeam = Standard_False;
2503     if (nbFaces == 1) {
2504       TopoDS_Face face = TopoDS::Face(listFaces.First());
2505       isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2506       if (isSeam) {
2507         ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2508         //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2509         //if(!isSeam) {
2510           BRep_Builder aB;
2511           TopoDS_Shape anewEdge = edge.EmptyCopied();
2512           TopoDS_Iterator aItV(edge);
2513           for( ; aItV.More() ; aItV.Next())
2514             aB.Add(anewEdge,aItV.Value());
2515           
2516
2517
2518           Standard_Real first2d,last2d;
2519           Handle(Geom2d_Curve) c2dold = 
2520             BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2521
2522           Handle(Geom2d_Curve) c2d;
2523           BRep_Builder B;
2524           B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2525           B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2526           
2527           Standard_Real aFirst, aLast;
2528           BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2529           aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2530           aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2531           myReShape->Replace(edge,anewEdge);
2532           edge = anewEdge;
2533           
2534         //}
2535            isSeam = Standard_False;
2536       }
2537     }
2538     Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2539     Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2540     if (isBound || isBoundFloat) {
2541       // Ignore degenerated edge
2542       if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2543       // Ignore edge with internal vertices
2544      // Standard_Integer nbVtx = 0;
2545      // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2546      // if (nbVtx != 2) continue;
2547       // Add to BoundFaces
2548       TopTools_ListOfShape listFacesCopy;
2549       listFacesCopy.Append(listFaces);
2550       myBoundFaces.Add(edge,listFacesCopy);
2551       // Process edge vertices
2552       TopoDS_Vertex vFirst, vLast;
2553       TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2554       if(vFirst.IsNull() || vLast.IsNull()) continue;
2555       if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2556         continue;
2557       if (isBound) {
2558         // Add to VertexNode
2559         if (!myVertexNode.Contains(vFirst))
2560           myVertexNode.Add(vFirst,vFirst);
2561         if (!myVertexNode.Contains(vLast))
2562           myVertexNode.Add(vLast,vLast);
2563       }
2564       else {
2565         // Add to VertexNodeFree
2566         if (!myVertexNodeFree.Contains(vFirst))
2567           myVertexNodeFree.Add(vFirst,vFirst);
2568         if (!myVertexNodeFree.Contains(vLast))
2569           myVertexNodeFree.Add(vLast,vLast);
2570       }
2571     }
2572   }
2573 }
2574
2575 //=======================================================================
2576 //function : VerticesAssembling
2577 //purpose  : Modifies :
2578 //                      myVertexNode     (nodes glued)
2579 //                      myVertexNodeFree (nodes glued)
2580 //                      myNodeSections   (lists of sections merged for glued nodes)
2581 //
2582 //=======================================================================
2583
2584 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2585                                        const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2586                                        TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2587                                        TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2588 {
2589   Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2590
2591   // Create new nodes
2592   BRep_Builder B;
2593   TopTools_DataMapOfShapeShape OldNodeNewNode;
2594   TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2595   for (i = 1; i <= nbNearest; i++) {
2596     // Retrieve a pair of nodes to merge
2597     TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2598     TopoDS_Shape oldnode2 = NodeNearestNode(i);
2599     // Second node should also be in the map
2600     if (!NodeNearestNode.Contains(oldnode2)) continue;
2601     // Get new node for old node #1
2602     if (OldNodeNewNode.IsBound(oldnode1)) {
2603       TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2604       if (OldNodeNewNode.IsBound(oldnode2)) {
2605         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2606         if (!newnode1.IsSame(newnode2)) {
2607           // Change data for new node #2
2608           TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2609           TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2610           for (; itn.More(); itn.Next()) {
2611             TopoDS_Shape node2 = itn.Value();
2612             lnode1.Append(node2);
2613             OldNodeNewNode(node2) = newnode1;
2614           }
2615           NewNodeOldNodes.UnBind(newnode2);
2616         }
2617       }
2618       else {
2619         // Old node #2 is not bound - add to old node #1
2620         OldNodeNewNode.Bind(oldnode2,newnode1);
2621         NewNodeOldNodes(newnode1).Append(oldnode2);
2622       }
2623     }
2624     else {
2625       if (OldNodeNewNode.IsBound(oldnode2)) {
2626         // Old node #1 is not bound - add to old node #2
2627         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2628         OldNodeNewNode.Bind(oldnode1,newnode2);
2629         NewNodeOldNodes(newnode2).Append(oldnode1);
2630       }
2631       else {
2632         // Nodes are not bound - create new node
2633         TopoDS_Vertex newnode;
2634         B.MakeVertex(newnode);
2635         OldNodeNewNode.Bind(oldnode1,newnode);
2636         OldNodeNewNode.Bind(oldnode2,newnode);
2637         TopTools_ListOfShape lnodes;
2638         lnodes.Append(oldnode1);
2639         lnodes.Append(oldnode2);
2640         NewNodeOldNodes.Bind(newnode,lnodes);
2641       }
2642     }
2643   }
2644
2645   // Stop if no new nodes created
2646   if (!NewNodeOldNodes.Extent()) return Standard_False;
2647
2648   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2649   for (; iter1.More(); iter1.Next()) {
2650     const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2651     // Calculate new node center point
2652     gp_XYZ theCoordinates(0.,0.,0.);
2653     TopTools_ListOfShape lvert; // Accumulate node vertices
2654     TopTools_MapOfShape medge;
2655     TopTools_ListOfShape ledge; // Accumulate node edges
2656     // Iterate on old nodes
2657     TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2658     for (; itn.More(); itn.Next()) {
2659       const TopoDS_Shape& oldnode = itn.Value();
2660       // Iterate on node vertices
2661       TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2662       for (; itv.More(); itv.Next()) {
2663         TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2664         // Change node for vertex
2665         aVertexNode.ChangeFromKey(vertex) = newnode;
2666         // Accumulate coordinates
2667         theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2668         lvert.Append(vertex);
2669       }
2670       // Iterate on node edges
2671       const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2672       TopTools_ListIteratorOfListOfShape ite(edges);
2673       for (; ite.More(); ite.Next()) {
2674         TopoDS_Shape edge = ite.Value();
2675         if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2676       }
2677       // Unbind old node edges
2678       aNodeEdges.UnBind(oldnode);
2679     }
2680     // Bind new node edges
2681     aNodeEdges.Bind(newnode,ledge);
2682     gp_Pnt center(theCoordinates / lvert.Extent());
2683     // Calculate new node tolerance
2684     Standard_Real toler = 0.0;
2685     TopTools_ListIteratorOfListOfShape itv(lvert);
2686     for (; itv.More(); itv.Next()) {
2687       const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2688       Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2689       if (toler < t) toler = t;
2690     }
2691     // Update new node parameters
2692     B.UpdateVertex(newnode,center,toler);
2693   }
2694
2695   return Standard_True;
2696 }
2697
2698 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2699                                          const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2700                                          const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2701 {
2702   //Case of floating edges
2703   if (face1.IsNull())
2704     return (!IsClosedShape(e1,vtx1,vtx2));
2705
2706   // Find wires containing given edges
2707   TopoDS_Shape wire1, wire2;
2708   TopExp_Explorer itw(face1,TopAbs_WIRE);
2709   for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2710     TopoDS_Iterator ite(itw.Current(),Standard_False);
2711     for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2712       if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2713       if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2714     }
2715   }
2716   Standard_Integer Status = 0;
2717   if (!wire1.IsNull() && !wire2.IsNull()) {
2718     if (wire1.IsSame(wire2)) {
2719       for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2720         TopoDS_Vertex ve1,ve2;
2721         TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2722         if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2723             (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2724           return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2725       }
2726       if (IsClosedShape(wire1,vtx1,vtx2)) {
2727         TopoDS_Vertex V1, V2;
2728         TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2729         Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2730                                         (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2731         if (!isEndVertex) Status = 1;
2732       }
2733       else Status = 1;
2734     }
2735     else Status = -1;
2736   }
2737   return Status;
2738 }
2739
2740 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2741                                      TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2742                                      const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2743                                      const Standard_Real Tolerance,
2744                                      const Handle(Message_ProgressIndicator)& theProgress)
2745 {
2746   Standard_Integer i, nbVertices = aVertexNode.Extent();
2747   // Create map of node -> vertices
2748   TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2749   BRepBuilderAPI_CellFilter aFilter (Tolerance);
2750   BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2751   for (i = 1; i <= nbVertices; i++) {
2752     TopoDS_Shape vertex = aVertexNode.FindKey(i);
2753     TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2754     if (NodeVertices.Contains(node)) {
2755       NodeVertices.ChangeFromKey(node).Append(vertex);
2756     }
2757     else {
2758       TopTools_ListOfShape vlist;
2759       vlist.Append(vertex);
2760       NodeVertices.Add(node,vlist);
2761       gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2762       aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2763       anInspector.Add (aPnt.XYZ());
2764     }
2765   }
2766   Standard_Integer nbNodes = NodeVertices.Extent();
2767 #ifdef DEB
2768   cout << "Glueing " << nbNodes << " nodes..." << endl;
2769 #endif
2770   // Merge nearest nodes
2771   TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2772   Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2773   for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2774     TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2775     // Find near nodes
2776     gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2777     anInspector.SetCurrent (pt1.XYZ());
2778     gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2779     gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2780     aFilter.Inspect (aPntMin, aPntMax, anInspector);
2781     if (anInspector.ResInd().IsEmpty()) continue;
2782     // Retrieve list of edges for the first node
2783     const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2784     // Explore list of near nodes and fill the sequence of glued nodes
2785     TopTools_SequenceOfShape SeqNodes;
2786     TopTools_ListOfShape listNodesSameEdge;
2787     //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2788     TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2789     for (; iter1.More(); iter1.Next()) {
2790       TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2791       if (node1 == node2) continue;
2792       // Retrieve list of edges for the second node
2793       const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2794       // Check merging condition for the pair of nodes
2795       Standard_Integer Status = 0, isSameEdge = Standard_False;
2796       // Explore edges of the first node
2797       TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2798       for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2799         const TopoDS_Shape& e1 = Ie1.Value();
2800         // Obtain real vertex from edge
2801         TopoDS_Shape v1 = node1;
2802         { //szv: Use brackets to destroy local variables
2803           TopoDS_Vertex ov1, ov2;
2804           TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2805           if (aVertexNode.Contains(ov1)) {
2806             if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2807           }
2808           if (aVertexNode.Contains(ov2)) {
2809             if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2810           }
2811         }
2812         // Create map of faces for e1
2813         TopTools_MapOfShape Faces1;
2814         const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2815         if (lfac1.Extent()) {
2816           TopTools_ListIteratorOfListOfShape itf(lfac1);
2817           for (; itf.More(); itf.Next())
2818             if (!itf.Value().IsNull())
2819               Faces1.Add(itf.Value());
2820         }
2821         // Explore edges of the second node
2822         TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2823         for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2824           const TopoDS_Shape& e2 = Ie2.Value();
2825           // Obtain real vertex from edge
2826           TopoDS_Shape v2 = node2;
2827           { //szv: Use brackets to destroy local variables
2828             TopoDS_Vertex ov1, ov2;
2829             TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2830             if (aVertexNode.Contains(ov1)) {
2831               if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2832             }
2833             if (aVertexNode.Contains(ov2)) {
2834               if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2835             }
2836           }
2837           // Explore faces for e2
2838           const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2839           if (lfac2.Extent()) {
2840             TopTools_ListIteratorOfListOfShape itf(lfac2);
2841             for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2842               // Check merging conditions for the same face
2843               if (Faces1.Contains(itf.Value())) {
2844                 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2845                 if (stat == 1) isSameEdge = Standard_True;
2846                 else Status = stat;
2847               }
2848             }
2849           }
2850           else if (Faces1.IsEmpty() && e1 == e2) {
2851             Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2852             if (stat == 1) isSameEdge = Standard_True;
2853             else Status = stat;
2854             break;
2855           }
2856         }
2857       }
2858       if (Status) continue;
2859       if (isSameEdge) listNodesSameEdge.Append(node2);
2860       // Append near node to the sequence
2861       gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2862       Standard_Real dist = pt1.Distance(pt2);
2863       if (dist < Tolerance) {
2864         Standard_Boolean isIns = Standard_False;
2865         for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2866           gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2867           if (dist < pt1.Distance(pt)) {
2868             SeqNodes.InsertBefore(kk,node2);
2869             isIns = Standard_True;
2870           }
2871         }
2872         if (!isIns) SeqNodes.Append(node2);
2873       }
2874     }
2875     if (SeqNodes.Length()) {
2876       // Remove nodes near to some other from the same edge
2877       if (listNodesSameEdge.Extent()) {
2878         TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2879         for (; lInt.More(); lInt.Next()) {
2880           const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2881           gp_Pnt p2 = BRep_Tool::Pnt(n2);
2882           for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2883             const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2884             if (n1 != n2) {
2885               gp_Pnt p1 = BRep_Tool::Pnt(n1);
2886               if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2887             }
2888             SeqNodes.Remove(k);
2889           }
2890         }
2891       }
2892       // Bind nearest node if at least one exists
2893       if (SeqNodes.Length())
2894         NodeNearestNode.Add(node1,SeqNodes.First());
2895     }
2896     anInspector.ClearResList();
2897   }
2898
2899   // Create new nodes for chained nearest nodes
2900   if (NodeNearestNode.IsEmpty()) return Standard_False;
2901
2902   return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2903 }
2904
2905 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2906 {
2907   Standard_Integer nbVert = myVertexNode.Extent();
2908   Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2909   Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2910   if (nbVert || nbVertFree) {
2911     // Fill map node -> sections
2912     Standard_Integer i;
2913     for (i = 1; i <= myBoundFaces.Extent(); i++) {
2914       TopoDS_Shape bound = myBoundFaces.FindKey(i);
2915       for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2916         TopoDS_Shape node = itv.Value();
2917         if (myNodeSections.IsBound(node))
2918           myNodeSections(node).Append(bound);
2919         else {
2920           TopTools_ListOfShape lbnd;
2921           lbnd.Append(bound);
2922           myNodeSections.Bind(node,lbnd);
2923         }
2924       }
2925     }
2926     // Glue vertices
2927     if (nbVert) {
2928 #ifdef DEB
2929       cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2930 #endif
2931       while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2932     }
2933     if (!aPS.More())
2934       return;
2935     aPS.Next();
2936     if (nbVertFree) {
2937 #ifdef DEB
2938       cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2939 #endif
2940       while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2941     }
2942   }
2943 }
2944
2945 //=======================================================================
2946 //function : replaceNMVertices
2947 //purpose  : internal use (static)
2948 //=======================================================================
2949 static void replaceNMVertices(const TopoDS_Edge& theEdge, 
2950                               const TopoDS_Vertex& theV1,
2951                               const TopoDS_Vertex& theV2,
2952                               const Handle(BRepTools_ReShape)& theReShape)
2953 {
2954   //To keep NM vertices on edge
2955   TopTools_SequenceOfShape aSeqNMVert;
2956   TColStd_SequenceOfReal aSeqNMPars;
2957   Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2958   if(!hasNMVert)
2959     return;
2960   Standard_Real first, last;
2961   BRep_Tool::Range(theEdge, first, last);
2962   TopLoc_Location aLoc;
2963   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2964   if(c3d.IsNull())
2965     return;
2966   TopTools_SequenceOfShape aEdVert;
2967   TColStd_SequenceOfReal aEdParams;
2968   Standard_Integer i =1, nb = aSeqNMPars.Length();
2969     
2970   for( ; i <= nb;i++) {
2971     Standard_Real apar = aSeqNMPars.Value(i);
2972     if(fabs(apar - first) <= Precision::PConfusion()) {
2973       theReShape->Replace(aSeqNMVert.Value(i),theV1);
2974       continue;
2975     }
2976     if(fabs(apar - last) <= Precision::PConfusion()) {
2977       theReShape->Replace(aSeqNMVert.Value(i),theV2);
2978       continue;
2979     }
2980     TopoDS_Shape aV = aSeqNMVert.Value(i);
2981     Standard_Integer j =1;
2982     for( ; j <= aEdParams.Length();j++) {
2983       Standard_Real apar2 = aEdParams.Value(j);
2984       if(fabs(apar - apar2) <= Precision::PConfusion()) {
2985         theReShape->Replace(aV,aEdVert.Value(j));
2986         break;
2987       }
2988       else if(apar < apar2) {
2989         TopoDS_Shape anewV = aV.EmptyCopied();
2990         aEdVert.InsertBefore(j,anewV);
2991         aEdParams.InsertBefore(j,apar);
2992         BRep_ListOfPointRepresentation& alistrep = 
2993           (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
2994         Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2995         alistrep.Append(aPRep);
2996         theReShape->Replace(aV,anewV);
2997         break;
2998       }
2999     }
3000     if (j > aEdParams.Length()) {
3001       TopoDS_Shape anewV = aV.EmptyCopied();
3002       aEdVert.Append(anewV);
3003       aEdParams.Append(apar);
3004       BRep_ListOfPointRepresentation& alistrep = 
3005         (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3006       Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3007       alistrep.Append(aPRep);
3008       theReShape->Replace(aV,anewV);
3009     }
3010   }
3011   
3012   Standard_Integer newnb = aEdParams.Length();
3013   if(newnb < nb) {
3014     
3015     TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3016     TopAbs_Orientation anOri = theEdge.Orientation();
3017     anewEdge.Orientation(TopAbs_FORWARD);
3018     BRep_Builder aB;
3019     aB.Add(anewEdge,theV1);
3020     aB.Add(anewEdge,theV2);
3021     
3022     for( i =1; i <= aEdVert.Length();i++) 
3023       aB.Add(anewEdge,aEdVert.Value(i));
3024     anewEdge.Orientation(anOri);
3025     theReShape->Replace(theEdge,anewEdge);
3026   }
3027  
3028 }
3029
3030 //=======================================================================
3031 //function : ReplaceEdge
3032 //purpose  : internal use (static)
3033 //=======================================================================
3034
3035 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3036                         const TopoDS_Shape& theNewShape,
3037                         const Handle(BRepTools_ReShape)& aReShape)
3038 {
3039   TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3040   TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3041   if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3042   
3043
3044   aReShape->Replace(oldShape,newShape);
3045   TopoDS_Vertex V1old,V2old,V1new,V2new;
3046   TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3047   TopAbs_Orientation Orold = oldShape.Orientation();
3048   TopAbs_Orientation Ornew = Orold;
3049   if (newShape.ShapeType() == TopAbs_EDGE) {
3050     TopoDS_Edge aEn = TopoDS::Edge(newShape);
3051     TopExp::Vertices(aEn,V1new,V2new);
3052     Ornew = aEn.Orientation();
3053     replaceNMVertices(aEn,V1new,V2new,aReShape);
3054   }
3055   else if (newShape.ShapeType() == TopAbs_WIRE) {
3056     for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3057       TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3058       Ornew = ed.Orientation();
3059       TopoDS_Vertex aV1,aV2;
3060       TopExp::Vertices(ed,aV1,aV2);
3061       replaceNMVertices(ed,aV1,aV2,aReShape);
3062       if (V1new.IsNull()) 
3063         V1new = aV1;
3064       V2new =aV2;
3065     }
3066   }
3067   
3068   V1new.Orientation(V1old.Orientation());
3069   V2new.Orientation(V2old.Orientation());
3070   if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3071     aReShape->Replace(V1old,V1new);
3072     return;
3073   }
3074   if (Orold == Ornew) {
3075     V1new.Orientation(V1old.Orientation());
3076     V2new.Orientation(V2old.Orientation());
3077     if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3078       aReShape->Replace(V1old,V1new);
3079     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3080       aReShape->Replace(V2old,V2new);
3081   }
3082   else {
3083     V1new.Orientation(V2old.Orientation());
3084     V2new.Orientation(V1old.Orientation());
3085     if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) 
3086       aReShape->Replace(V1old,V2new);
3087     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3088       aReShape->Replace(V2old,V1new);
3089   }
3090 }
3091
3092 //=======================================================================
3093 //function : Merging
3094 //purpose  : Modifies :
3095 //                   myHasFreeBound
3096 //
3097 //=======================================================================
3098
3099 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */, 
3100                                     const Handle(Message_ProgressIndicator)& thePI)
3101 {
3102   BRep_Builder B;
3103   //  TopTools_MapOfShape MergedEdges;
3104   Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3105   for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3106
3107     TopoDS_Shape bound = myBoundFaces.FindKey(i);
3108
3109     // If bound was already merged - continue
3110     if (myMergedEdges.Contains(bound)) continue;
3111
3112     if (!myBoundFaces(i).Extent()) {
3113       // Merge free edge - only vertices
3114       TopoDS_Vertex no1, no2;
3115       TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3116       TopoDS_Shape nno1 = no1, nno2 = no2;
3117       if (myVertexNodeFree.Contains(no1))
3118         nno1 = myVertexNodeFree.FindFromKey(no1);
3119       if (myVertexNodeFree.Contains(no2))
3120         nno2 = myVertexNodeFree.FindFromKey(no2);
3121       if (!no1.IsSame(nno1)) {
3122         nno1.Orientation(no1.Orientation());
3123         myReShape->Replace(no1,nno1);
3124       }
3125       if (!no2.IsSame(nno2)) {
3126         nno2.Orientation(no2.Orientation());
3127         myReShape->Replace(no2,nno2);
3128       }
3129       myMergedEdges.Add(bound);
3130       continue;
3131     }
3132
3133     // Check for previous splitting, build replacing wire
3134     TopoDS_Wire BoundWire;
3135     Standard_Boolean isPrevSplit = Standard_False;
3136     Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3137     if (hasCuttingSections) {
3138       B.MakeWire(BoundWire);
3139       BoundWire.Orientation(bound.Orientation());
3140       // Iterate on cutting sections
3141       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3142       for (; its.More(); its.Next()) {
3143         TopoDS_Shape section = its.Value();
3144         B.Add(BoundWire,section);
3145         if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3146       }
3147     }
3148
3149     // Merge with bound
3150     TopTools_DataMapOfShapeShape MergedWithBound;
3151     if (!isPrevSplit) {
3152       // Obtain sequence of edges merged with bound
3153       TopTools_SequenceOfShape seqMergedWithBound;
3154       TColStd_SequenceOfInteger seqMergedWithBoundOri;
3155       if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3156         // Store bound in the map
3157         MergedWithBound.Bind(bound,bound);
3158         // Iterate on edges merged with bound
3159         Standard_Integer ii = 1;
3160         while (ii <= seqMergedWithBound.Length()) {
3161           TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3162           // Remove edge if recorded as merged
3163           Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || 
3164             MergedWithBound.IsBound(iedge));
3165           if (!isRejected) {
3166             if (myBoundSections.IsBound(iedge)) {
3167               // Edge is splitted - check sections
3168               TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3169               for (; lit.More() && !isRejected; lit.Next()) {
3170                 const TopoDS_Shape& sec = lit.Value();
3171                 // Remove edge (bound) if at least one of its sections already merged
3172                 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3173               }
3174             }
3175             if (!isRejected) {
3176               if (mySectionBound.IsBound(iedge)) {
3177                 // Edge is a section - check bound
3178                 const TopoDS_Shape& bnd = mySectionBound(iedge);
3179                 // Remove edge (section) if its bound already merged
3180                 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3181               }
3182             }
3183           }
3184           // To the next merged edge
3185           if (isRejected) {
3186             // Remove rejected edge
3187             seqMergedWithBound.Remove(ii);
3188             seqMergedWithBoundOri.Remove(ii);
3189           }
3190           else {
3191             // Process accepted edge
3192             MergedWithBound.Bind(iedge,iedge);
3193             ii++;
3194           }
3195         }
3196         Standard_Integer nbMerged = seqMergedWithBound.Length();
3197         if (nbMerged) {
3198           // Create same parameter edge
3199           TopTools_MapOfShape ActuallyMerged;
3200           TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3201             seqMergedWithBoundOri,
3202             ActuallyMerged,myReShape);
3203           Standard_Boolean isForward = Standard_False;
3204           if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3205           // Process actually merged edges
3206           Standard_Integer nbActuallyMerged = 0;
3207           for (ii = 1; ii <= nbMerged; ii++) {
3208             TopoDS_Shape iedge = seqMergedWithBound(ii);
3209             if (ActuallyMerged.Contains(iedge)) {
3210               nbActuallyMerged++;
3211               // Record merged edge in the map
3212               TopAbs_Orientation orient = iedge.Orientation();
3213               if (!isForward) orient = TopAbs::Reverse(orient);
3214               if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3215               MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3216             }
3217             else MergedWithBound.UnBind(iedge);
3218           }
3219           if (nbActuallyMerged) {
3220             // Record merged bound in the map
3221             TopAbs_Orientation orient = bound.Orientation();
3222             if (!isForward) orient = TopAbs::Reverse(orient);
3223             MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3224           }
3225           nbMerged = nbActuallyMerged;
3226         }
3227         // Remove bound from the map if not finally merged
3228         if (!nbMerged) MergedWithBound.UnBind(bound);
3229       }
3230     }
3231     Standard_Boolean isMerged = MergedWithBound.Extent();
3232
3233     // Merge with cutting sections
3234     Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3235     TopTools_DataMapOfShapeShape MergedWithSections;
3236     if (hasCuttingSections) {
3237       // Iterate on cutting sections
3238       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3239       for (; its.More(); its.Next()) {
3240         // Retrieve cutting section
3241         TopoDS_Shape section = its.Value();
3242         // Skip section if already merged
3243         if (myMergedEdges.Contains(section)) continue;
3244         // Merge cutting section
3245         TopTools_SequenceOfShape seqMergedWithSection;
3246         TColStd_SequenceOfInteger seqMergedWithSectionOri;
3247         if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3248           // Store section in the map
3249           MergedWithSections.Bind(section,section);
3250           // Iterate on edges merged with section
3251           Standard_Integer ii = 1;
3252           while (ii <= seqMergedWithSection.Length()) {
3253             TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3254             // Remove edge if recorded as merged
3255             Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3256             if (!isRejected) {
3257               if (myBoundSections.IsBound(iedge)) {
3258                 // Edge is splitted - check sections
3259                 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3260                 for (; lit.More() && !isRejected; lit.Next()) {
3261                   const TopoDS_Shape& sec = lit.Value();
3262                   // Remove edge (bound) if at least one of its sections already merged
3263                   isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3264                 }
3265               }
3266               if (!isRejected) {
3267                 if (mySectionBound.IsBound(iedge)) {
3268                   // Edge is a section - check bound
3269                   const TopoDS_Shape& bnd = mySectionBound(iedge);
3270                   // Remove edge (section) if its bound already merged
3271                   isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3272                 }
3273               }
3274             }
3275             // To the next merged edge
3276             if (isRejected) {
3277               // Remove rejected edge
3278               seqMergedWithSection.Remove(ii);
3279               seqMergedWithSectionOri.Remove(ii);
3280             }
3281             else {
3282               // Process accepted edge
3283               MergedWithSections.Bind(iedge,iedge);
3284               ii++;
3285             }
3286           }
3287           Standard_Integer nbMerged = seqMergedWithSection.Length();
3288           if (nbMerged) {
3289             // Create same parameter edge
3290             TopTools_MapOfShape ActuallyMerged;
3291             TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3292               seqMergedWithSectionOri,
3293               ActuallyMerged,SectionsReShape);
3294             Standard_Boolean isForward = Standard_False;
3295             if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3296             // Process actually merged edges
3297             Standard_Integer nbActuallyMerged = 0;
3298             for (ii = 1; ii <= nbMerged; ii++) {
3299               TopoDS_Shape iedge = seqMergedWithSection(ii);
3300               if (ActuallyMerged.Contains(iedge)) {
3301                 nbActuallyMerged++;
3302                 // Record merged edge in the map
3303                 TopAbs_Orientation orient = iedge.Orientation();
3304                 if (!isForward) orient = TopAbs::Reverse(orient);
3305                 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3306                 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3307                 MergedWithSections.ChangeFind(iedge) = oedge;
3308                 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3309               }
3310               else MergedWithSections.UnBind(iedge);
3311             }
3312             if (nbActuallyMerged) {
3313               // Record merged section in the map
3314               TopAbs_Orientation orient = section.Orientation();
3315               if (!isForward) orient = TopAbs::Reverse(orient);
3316               TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3317               MergedWithSections.ChangeFind(section) = oedge;
3318               ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3319             }
3320             nbMerged = nbActuallyMerged;
3321           }
3322           // Remove section from the map if not finally merged
3323           if (!nbMerged) MergedWithSections.UnBind(section);
3324         }
3325         else if (isMerged) {
3326           // Reject merging of sections
3327           MergedWithSections.Clear();
3328           break;
3329         }
3330       }
3331     }
3332     Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3333
3334     if (!isMerged && !isMergedSplit) {
3335       // Nothing was merged in this iteration
3336       if (isPrevSplit) {
3337         // Replace previously splitted bound
3338         myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3339       }
3340       //      else if (hasCuttingSections) {
3341       //        myBoundSections.UnBind(bound); //szv: are you sure ???
3342       //      }
3343       continue;
3344     }
3345
3346     // Set splitting flag
3347     Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3348
3349     // Choose between bound and sections merging
3350     if (isMerged && isMergedSplit && !isPrevSplit) {
3351       // Fill map of&n