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