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