0025748: Parallel version of progress indicator
[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_TEdge.hxx>
55 #include <BRep_TVertex.hxx>
56 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
57 #include <BRepBuilderAPI_CellFilter.hxx>
58 #include <BRepBuilderAPI_Sewing.hxx>
59 #include <BRepBuilderAPI_VertexInspector.hxx>
60 #include <BRepLib.hxx>
61 #include <BRepTools.hxx>
62 #include <BRepTools_Quilt.hxx>
63 #include <BRepTools_ReShape.hxx>
64 #include <BSplCLib.hxx>
65 #include <Extrema_ExtPC.hxx>
66 #include <GCPnts_AbscissaPoint.hxx>
67 #include <GCPnts_UniformAbscissa.hxx>
68 #include <GCPnts_UniformDeflection.hxx>
69 #include <Geom2d_BezierCurve.hxx>
70 #include <Geom2d_BSplineCurve.hxx>
71 #include <Geom2d_Curve.hxx>
72 #include <Geom2d_Line.hxx>
73 #include <Geom2d_TrimmedCurve.hxx>
74 #include <Geom2dAdaptor_Curve.hxx>
75 #include <Geom2dConvert.hxx>
76 #include <Geom_BezierCurve.hxx>
77 #include <Geom_BSplineCurve.hxx>
78 #include <Geom_Curve.hxx>
79 #include <Geom_Line.hxx>
80 #include <Geom_OffsetSurface.hxx>
81 #include <Geom_RectangularTrimmedSurface.hxx>
82 #include <Geom_Surface.hxx>
83 #include <GeomAdaptor_Curve.hxx>
84 #include <GeomAdaptor_Surface.hxx>
85 #include <GeomLib.hxx>
86 #include <gp_Pnt.hxx>
87 #include <gp_Vec.hxx>
88 #include <Message_ProgressScope.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_IndexedMapOfInteger.hxx>
102 #include <TColStd_ListIteratorOfListOfInteger.hxx>
103 #include <TColStd_ListOfInteger.hxx>
104 #include <TColStd_MapOfInteger.hxx>
105 #include <TColStd_SequenceOfReal.hxx>
106 #include <TopAbs.hxx>
107 #include <TopExp.hxx>
108 #include <TopExp_Explorer.hxx>
109 #include <TopLoc_Location.hxx>
110 #include <TopoDS.hxx>
111 #include <TopoDS_Compound.hxx>
112 #include <TopoDS_Edge.hxx>
113 #include <TopoDS_Face.hxx>
114 #include <TopoDS_Iterator.hxx>
115 #include <TopoDS_Shape.hxx>
116 #include <TopoDS_Shell.hxx>
117 #include <TopoDS_Vertex.hxx>
118 #include <TopoDS_Wire.hxx>
119 #include <TopTools_Array1OfShape.hxx>
120 #include <TopTools_DataMapOfShapeListOfShape.hxx>
121 #include <TopTools_ListIteratorOfListOfShape.hxx>
122 #include <TopTools_ListOfShape.hxx>
123 #include <TopTools_MapOfShape.hxx>
124 #include <TopTools_SequenceOfShape.hxx>
125
126 IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_Sewing,Standard_Transient)
127
128 //#include <LocalAnalysis_SurfaceContinuity.hxx>
129 //=======================================================================
130 //function : SameRange
131 //purpose  : 
132 //=======================================================================
133 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
134                                                 const Standard_Real FirstOnCurve,
135                                                 const Standard_Real LastOnCurve,
136                                                 const Standard_Real RequestedFirst,
137                                                 const Standard_Real RequestedLast) const
138 {
139   Handle(Geom2d_Curve) NewCurvePtr;
140   try {
141     
142     GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
143                        RequestedFirst,RequestedLast,NewCurvePtr);
144   }
145   catch (Standard_Failure const& anException) {
146 #ifdef OCCT_DEBUG
147     std::cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
148     anException.Print(std::cout); std::cout << std::endl;
149 #endif
150     (void)anException;
151   }
152   return NewCurvePtr;
153 }
154
155 //=======================================================================
156 //function : WhichFace
157 //purpose  : Give the face whose edge is the border
158 //=======================================================================
159
160 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
161 {
162   TopoDS_Shape bound = theEdg;
163   if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
164   if (myBoundFaces.Contains(bound)) {
165     Standard_Integer i = 1;
166     TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
167     for (; itf.More(); itf.Next(), i++)
168       if (i == index) return TopoDS::Face(itf.Value());
169   }
170   return TopoDS_Face();
171 }
172
173 //=======================================================================
174 //function : IsClosedShape
175 //purpose  : 
176 //=======================================================================
177
178 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
179                                       const TopoDS_Shape& v1, const TopoDS_Shape& v2)
180 {
181   Standard_Real TotLength = 0.0;
182   TopExp_Explorer aexp;
183   for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
184     TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
185     if (aedge.IsNull()) continue;
186     TopoDS_Vertex ve1,ve2;
187     TopExp::Vertices(aedge,ve1,ve2);
188     if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
189     if (BRep_Tool::Degenerated(aedge)) continue;
190     Standard_Real first,last;
191     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
192     if (!c3d.IsNull()) {
193       GeomAdaptor_Curve cAdapt(c3d);
194       Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
195       TotLength += length;
196       if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
197     }
198   }
199   if (TotLength > 0.0) {
200     gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
201     gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
202     return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
203   }
204   return Standard_False;
205 }
206
207 //=======================================================================
208 //function : IsClosedByIsos
209 //purpose  : 
210 //=======================================================================
211 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
212                                        const Handle(Geom2d_Curve)& acrv2d,
213                                        const Standard_Real f2d,
214                                        const  Standard_Real l2d,
215                                        const Standard_Boolean isUIsos) 
216 {
217   Standard_Boolean isClosed = Standard_False;
218  
219   gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ? 
220                      acrv2d->Value(f2d) :  acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
221   gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ? 
222                      acrv2d->Value(l2d) :  acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
223   Handle(Geom_Curve) aCrv1;
224   Handle(Geom_Curve) aCrv2;
225   if(isUIsos) {
226     aCrv1 = thesurf->UIso(psurf1.X());
227     aCrv2 = thesurf->UIso(psurf2.X());
228   }
229   else {
230     aCrv1 = thesurf->VIso(psurf1.Y());
231     aCrv2 = thesurf->VIso(psurf2.Y());
232   }
233   gp_Pnt p11,p1m,p12,p21,p2m,p22;
234   Standard_Real af1 = aCrv1->FirstParameter();
235   Standard_Real al1 = aCrv1->LastParameter();
236   Standard_Real af2 = aCrv2->FirstParameter();
237   Standard_Real al2 = aCrv2->LastParameter();
238   aCrv1->D0(af1,p11);
239   aCrv1->D0((af1+al1)*0.5,p1m);
240   aCrv1->D0(al1,p12);
241   aCrv2->D0(af2,p21);
242   aCrv2->D0((af2+al2)*0.5,p2m);
243   aCrv2->D0(al2,p22);
244   isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() < 
245                (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
246               ((p21.XYZ() - p22.XYZ()).Modulus() < 
247                (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
248   return isClosed;
249 }
250 //=======================================================================
251 //function : IsUClosedSurface
252 //purpose  : 
253 //=======================================================================
254
255 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
256                                                    const TopoDS_Shape& theEdge,
257                                                    const TopLoc_Location& theloc) const
258 {
259   Handle(Geom_Surface) tmpsurf = surf;
260   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
261     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
262   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
263     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
264   else {
265     Standard_Boolean isClosed = tmpsurf->IsUClosed();
266     if(!isClosed) {
267       Standard_Real f2d, l2d;
268       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
269       if(!acrv2d.IsNull())
270         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
271       
272     }
273     return isClosed;
274   }
275   return IsUClosedSurface(tmpsurf,theEdge,theloc);
276   //return surf->IsUClosed();
277 }
278
279 //=======================================================================
280 //function : IsVClosedSurface
281 //purpose  : 
282 //=======================================================================
283
284 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
285                                                    const TopoDS_Shape& theEdge,
286                                                    const TopLoc_Location& theloc) const
287 {
288   Handle(Geom_Surface) tmpsurf = surf;
289   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
290     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
291   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
292     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
293   else {
294     Standard_Boolean isClosed = tmpsurf->IsVClosed();
295     if(!isClosed) {
296       Standard_Real f2d, l2d;
297       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
298       if(!acrv2d.IsNull())
299         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
300     }
301     return isClosed;
302   }
303   return IsVClosedSurface(tmpsurf,theEdge,theloc);
304   //return surf->IsVClosed();
305 }
306
307 //=======================================================================
308 //function : SameParameter
309 //purpose  : internal use
310 //=======================================================================
311
312 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
313 {
314   try {
315     
316     BRepLib::SameParameter(edge);
317   }
318   catch (Standard_Failure const& anException) {
319 #ifdef OCCT_DEBUG
320     std::cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
321     anException.Print(std::cout); std::cout << std::endl;
322 #endif
323     (void)anException;
324   }
325 }
326
327 //=======================================================================
328 //function : SameParameterEdge
329 //purpose  : internal use
330 //           Merge the Sequence Of Section on one edge.
331 //           This function keep the curve3d,curve2d,range and parametrization
332 //           from the first section, and report and made sameparameter the
333 //           pcurves of the other function.
334 //           This function works when the are not more than two Pcurves
335 //           on a same face.
336 //=======================================================================
337
338 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
339                                                const TopTools_SequenceOfShape& seqEdges,
340                                                const TColStd_SequenceOfBoolean& seqForward,
341                                                TopTools_MapOfShape& mapMerged,
342                                                const Handle(BRepTools_ReShape)& locReShape)
343 {
344   // Retrieve reference section
345   TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
346   TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
347   aTmpShape = locReShape->Apply(Edge1);
348   if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
349   Standard_Boolean isDone = Standard_False;
350
351   // Create data structures for temporary merged edges
352   TopTools_ListOfShape listFaces1;
353   TopTools_MapOfShape MergedFaces;
354
355   if (mySewing) {
356
357     // Fill MergedFaces with faces of Edge1
358     TopoDS_Shape bnd1 = edge;
359     if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
360     if (myBoundFaces.Contains(bnd1)) {
361       TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
362       for (; itf.More(); itf.Next())
363         if (MergedFaces.Add(itf.Value()))
364           listFaces1.Append(itf.Value());
365     }
366   }
367   else {
368
369     // Create presentation edge
370     TopoDS_Vertex V1, V2;
371     TopExp::Vertices(Edge1,V1,V2);
372     if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
373     if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
374
375     TopoDS_Edge NewEdge = Edge1;
376     NewEdge.EmptyCopy();
377
378     // Add the vertices
379     BRep_Builder aBuilder;
380     TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
381     aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
382     aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
383
384     Edge1 = NewEdge;
385   }
386
387   Standard_Boolean isForward = Standard_True;
388
389   // Merge candidate sections
390   for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
391
392     // Retrieve candidate section
393     TopoDS_Shape oedge2 = seqEdges(i);
394
395     if (mySewing) {
396
397       aTmpShape = myReShape->Apply(oedge2); //for porting
398       TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
399       aTmpShape = locReShape->Apply(Edge2);
400       if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
401
402       // Calculate relative orientation
403       Standard_Boolean Orientation = seqForward(i);
404       if (!isForward) Orientation = !Orientation;
405
406       // Retrieve faces information for the second edge
407       TopoDS_Shape bnd2 = oedge2;
408       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
409       if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
410       const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
411
412       Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
413       TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
414       if (NewEdge.IsNull()) continue;
415
416       // Record faces information for the temporary merged edge
417       TopTools_ListIteratorOfListOfShape itf(listFaces2);
418       for (; itf.More(); itf.Next())
419         if (MergedFaces.Add(itf.Value()))
420           listFaces1.Append(itf.Value());
421
422       // Record merged section orientation
423       if (!Orientation && whichSec != 1)
424         isForward = isForward? Standard_False : Standard_True;
425       Edge1 = NewEdge;
426     }
427
428     // Append actually merged edge
429     mapMerged.Add(oedge2);
430     isDone = Standard_True;
431
432     if (!myNonmanifold) break;
433   }
434
435   if (isDone) {
436     // Change result orientation
437     Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
438   }
439   else Edge1.Nullify();
440
441   return Edge1;
442 }
443
444 //=======================================================================
445 //function : SameParameterEdge
446 //purpose  : internal use
447 //=======================================================================
448 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
449                                        TopTools_SequenceOfShape& theSeqNMVert,
450                                        TColStd_SequenceOfReal& theSeqPars)
451 {
452   TopoDS_Iterator aItV(theEdge,Standard_False);
453   for( ; aItV.More(); aItV.Next()) {
454     if(aItV.Value().Orientation() == TopAbs_INTERNAL || 
455         aItV.Value().Orientation() == TopAbs_EXTERNAL)
456     theSeqNMVert.Append(aItV.Value());
457   }
458   Standard_Integer nbV = theSeqNMVert.Length();
459   if(!nbV)
460     return Standard_False;
461   Standard_Real first, last;
462   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
463   GeomAdaptor_Curve GAC(c3d);
464   Extrema_ExtPC locProj;
465   locProj.Initialize(GAC, first, last);
466   gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
467
468   
469   for (Standard_Integer i = 1; i <= nbV; i++) {
470     TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
471     gp_Pnt pt = BRep_Tool::Pnt(aV);
472     
473     Standard_Real distF2 = pfirst.SquareDistance(pt);
474     Standard_Real distL2 = plast.SquareDistance(pt);
475     Standard_Real apar = (distF2 > distL2 ? last : first);
476     // Project current point on curve
477     locProj.Perform(pt);
478     if (locProj.IsDone() && locProj.NbExt() > 0) {
479           Standard_Real dist2Min = Min(distF2,distL2);
480           Standard_Integer ind, indMin = 0;
481           for (ind = 1; ind <= locProj.NbExt(); ind++) {
482             Standard_Real dProj2 = locProj.SquareDistance(ind);
483             if (dProj2 < dist2Min) { 
484           indMin = ind; dist2Min = dProj2; 
485         }
486       }
487       if(indMin) 
488         apar = locProj.Point(indMin).Parameter();
489          
490       theSeqPars.Append(apar);  
491         
492     }
493   }
494   return Standard_True;
495 }
496
497 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
498                                    TopoDS_Vertex& theNewV)
499 {
500   Standard_Integer m, n;
501   Standard_Real aR[2], dR, aD, aEps;
502   TopoDS_Vertex aV[2];
503   gp_Pnt aP[2];
504   BRep_Builder aBB;
505   //
506   aEps = RealEpsilon();
507   aV[0] = theV1;
508   aV[1] = theV2;
509   for (m = 0; m < 2; ++m) {
510     aP[m] = BRep_Tool::Pnt(aV[m]);
511     aR[m] = BRep_Tool::Tolerance(aV[m]);
512     }  
513     //
514   m=0; // max R
515   n=1; // min R
516   if (aR[0] < aR[1]) {
517     m=1;
518     n=0;
519   }
520   //
521   dR = aR[m] - aR[n]; // dR >= 0.
522   gp_Vec aVD(aP[m], aP[n]);
523   aD = aVD.Magnitude();
524   //
525   if (aD <= dR || aD < aEps) { 
526     aBB.MakeVertex (theNewV, aP[m], aR[m]);
527   }
528   else {
529     Standard_Real aRr;
530     gp_XYZ aXYZr;
531     gp_Pnt aPr;
532     //
533     aRr = 0.5 * (aR[m] + aR[n] + aD);
534     aXYZr = 0.5 * (aP[m].XYZ() + aP[n].XYZ() - aVD.XYZ() * (dR/aD));
535     aPr.SetXYZ(aXYZr);
536     //
537     aBB.MakeVertex (theNewV, aPr, aRr);
538   }
539   return;
540 }
541
542 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
543                                    TopoDS_Vertex theV3, TopoDS_Vertex& theNewV)
544 {
545   Standard_Real aDi, aDmax;
546   gp_Pnt aCenter;
547   gp_Pnt aP[3];
548   Standard_Real aR[3];
549   TopoDS_Vertex aV[3];
550   gp_XYZ aXYZ(0.,0.,0.);
551   aV[0] = theV1;
552   aV[1] = theV2;
553   aV[2] = theV3;
554   for (Standard_Integer i = 0; i < 3; ++i) {
555     aP[i] = BRep_Tool::Pnt(aV[i]);
556     aR[i] = BRep_Tool::Tolerance(aV[i]);
557     aXYZ = aXYZ + aP[i].XYZ();
558   }
559   //
560   aXYZ.Divide(3.0);
561   aCenter.SetXYZ(aXYZ);
562   //
563   aDmax=-1.;
564   for ( Standard_Integer i = 0; i < 3; ++i) {
565     aDi = aCenter.Distance(aP[i]);
566     aDi += aR[i];
567     if (aDi > aDmax)
568       aDmax = aDi;
569   }
570
571   BRep_Builder aBB;
572   aBB.MakeVertex (theNewV, aCenter, aDmax);
573   return;
574 }
575
576 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
577                                                const TopoDS_Edge& edgeLast,
578                                                const TopTools_ListOfShape& listFacesFirst,
579                                                const TopTools_ListOfShape& listFacesLast,
580                                                const Standard_Boolean secForward, 
581                                                Standard_Integer& whichSec,
582                                                const Standard_Boolean firstCall)
583 {
584   // Do not process floating edges
585   if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
586
587   // Sort input edges
588   TopoDS_Edge edge1, edge2;
589   if (firstCall) {
590     // Take the longest edge as first
591     Standard_Real f, l;
592     Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
593     GeomAdaptor_Curve cAdapt1(c3d1);
594     Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
595     Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
596     GeomAdaptor_Curve cAdapt2(c3d2);
597     Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
598     if (len1 < len2) {
599       edge1 = edgeLast;
600       edge2 = edgeFirst;
601       whichSec = 2;
602     }
603     else {
604       edge1 = edgeFirst;
605       edge2 = edgeLast;
606       whichSec = 1;
607     }
608   }
609   else {
610     if (whichSec == 1) {
611       edge1 = edgeLast;
612       edge2 = edgeFirst;
613       whichSec = 2;
614     }
615     else {
616       edge1 = edgeFirst;
617       edge2 = edgeLast;
618       whichSec = 1;
619     }
620   }
621
622   Standard_Real first, last;
623   BRep_Tool::Range(edge1, first, last);
624   BRep_Builder aBuilder;
625
626   //To keep NM vertices on edge
627   TopTools_SequenceOfShape aSeqNMVert;
628   TColStd_SequenceOfReal aSeqNMPars;
629   findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
630   findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
631
632   // Create new edge
633   TopoDS_Edge edge;
634   aBuilder.MakeEdge(edge);
635   edge.Orientation( edge1.Orientation());
636  
637
638   // Retrieve edge curve
639   TopLoc_Location loc3d;
640   Standard_Real first3d, last3d;
641   Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
642   if (!loc3d.IsIdentity()) {
643     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
644     c3d->Transform(loc3d.Transformation());
645   }
646   aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
647   aBuilder.Range(edge, first, last);
648   aBuilder.SameRange(edge, Standard_False); //Standard_True
649   aBuilder.SameParameter(edge, Standard_False);
650   // Create and add new vertices
651   {
652     TopoDS_Vertex V1New, V2New;
653
654     // Retrieve original vertices from edges
655     TopoDS_Vertex V11,V12,V21,V22;
656     TopExp::Vertices(edge1,V11,V12);
657     TopExp::Vertices(edge2,V21,V22);
658
659     //check that edges merged valid way (for edges having length less than specified
660     //tolerance
661     // Check if edges are closed
662     Standard_Boolean isClosed1 = V11.IsSame(V12);
663     Standard_Boolean isClosed2 = V21.IsSame(V22);
664     if(!isClosed1 && !isClosed2)
665     {
666       if(secForward )
667       {
668         if( V11.IsSame(V22) || V12.IsSame(V21) )
669           return TopoDS_Edge();
670       }
671       else
672       {
673         if( V11.IsSame(V21) || V12.IsSame(V22) )
674           return TopoDS_Edge();
675       }
676     }
677
678     //szv: do not reshape here!!!
679     //V11 = TopoDS::Vertex(myReShape->Apply(V11));
680     //V12 = TopoDS::Vertex(myReShape->Apply(V12));
681     //V21 = TopoDS::Vertex(myReShape->Apply(V21));
682     //V22 = TopoDS::Vertex(myReShape->Apply(V22));
683
684     //Standard_Boolean isRev = Standard_False;
685     if (isClosed1 || isClosed2) {
686       // at least one of the edges is closed
687       if (isClosed1 && isClosed2) {
688         // both edges are closed
689         ComputeToleranceVertex(V11, V21, V1New);
690       }
691       else if (isClosed1) {
692         // only first edge is closed
693         ComputeToleranceVertex(V22, V21, V11, V1New);
694       }
695       else {
696         // only second edge is closed
697         ComputeToleranceVertex(V11, V12, V21, V1New);
698       }
699       V2New = V1New;
700     }
701     else {
702       // both edges are open
703       Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) :  V11.IsSame(V22) );
704       Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
705       if (secForward) {
706         //case if vertices already sewed
707         if(!isOldFirst)
708         {
709           ComputeToleranceVertex(V11, V21, V1New);
710         }
711         if(!isOldLast)
712         {
713           ComputeToleranceVertex(V12, V22, V2New);
714         }
715       }
716       else {
717         if(!isOldFirst)
718         {
719           ComputeToleranceVertex(V11, V22, V1New);
720         }
721         if(!isOldLast)
722         {
723           ComputeToleranceVertex(V12, V21, V2New);
724         }
725       }
726       if(isOldFirst)
727         V1New = V11;
728
729       if(isOldLast)
730         V2New = V12;
731     }
732     // Add the vertices in the good sense
733     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
734     TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
735     aBuilder.Add(anEdge,aLocalEdge);
736     aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
737     aBuilder.Add(anEdge,aLocalEdge);
738
739     Standard_Integer k =1;
740     for( ; k <= aSeqNMVert.Length(); k++)
741       aBuilder.Add(anEdge,aSeqNMVert.Value(k));
742
743   }
744
745   // Retrieve second PCurves
746   TopLoc_Location loc2;
747   Handle(Geom_Surface) surf2;
748   
749   //Handle(Geom2d_Curve) c2d2, c2d21;
750   //  Standard_Real firstOld, lastOld;
751
752   TopTools_ListIteratorOfListOfShape itf2;
753   if (whichSec == 1) itf2.Initialize(listFacesLast);
754   else               itf2.Initialize(listFacesFirst);
755   Standard_Boolean isResEdge = Standard_False;
756   TopoDS_Face fac2;
757   for (; itf2.More(); itf2.Next()) {
758     Handle(Geom2d_Curve) c2d2, c2d21;
759     Standard_Real firstOld, lastOld;
760     fac2 = TopoDS::Face(itf2.Value());
761
762     surf2 = BRep_Tool::Surface(fac2, loc2);
763     Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
764       BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
765     if (isSeam2) {
766       if (!myNonmanifold) return TopoDS_Edge();
767       TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
768       c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
769     }
770     c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
771     if (c2d2.IsNull() && c2d21.IsNull()) continue;
772
773     if (!c2d21.IsNull()) {
774       c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
775       if (!secForward) {
776         if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
777           c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
778         Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
779         Standard_Real last2d = lastOld;   //c2dTmp->LastParameter();
780         firstOld = c2d21->ReversedParameter(last2d);
781         lastOld = c2d21->ReversedParameter(first2d);
782         c2d21->Reverse();
783       }
784       c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
785     }
786
787     // Make second PCurve sameRange with the 3d curve
788     c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
789     
790     if (!secForward) {
791       if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
792         c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
793       Standard_Real first2d = firstOld; 
794       Standard_Real last2d = lastOld;   
795       firstOld = c2d2->ReversedParameter(last2d);
796       lastOld = c2d2->ReversedParameter(first2d);
797       c2d2->Reverse();
798     }
799
800     c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
801     if (c2d2.IsNull()) continue;
802
803     // Add second PCurve
804     Standard_Boolean isSeam = Standard_False;
805     TopAbs_Orientation Ori = TopAbs_FORWARD;
806     //Handle(Geom2d_Curve) c2d1, c2d11;
807
808     TopTools_ListIteratorOfListOfShape itf1;
809     if (whichSec == 1) itf1.Initialize(listFacesFirst);
810     else               itf1.Initialize(listFacesLast);
811     for (; itf1.More() && !isSeam; itf1.Next()) {
812       Handle(Geom2d_Curve) c2d1, c2d11;
813       const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
814
815       TopLoc_Location loc1;
816       Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
817       
818       Standard_Real first2d, last2d;
819       Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
820         BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
821       c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
822       Ori = edge1.Orientation();
823       if (fac1.Orientation() == TopAbs_REVERSED) 
824         Ori = TopAbs::Reverse(Ori);
825
826       if (isSeam1) {
827         if (!myNonmanifold) return TopoDS_Edge();
828         TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
829         c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
830         //if(fac1.Orientation() == TopAbs_REVERSED) //
831         if(Ori == TopAbs_FORWARD)
832           aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
833         else
834           aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
835       }
836       else  aBuilder.UpdateEdge(edge,c2d1,fac1,0);
837
838       if (c2d1.IsNull() && c2d11.IsNull()) continue;
839
840       if (surf2 == surf1) {
841         // Merge sections which are on the same face
842         if (!loc2.IsDifferent(loc1)) {
843           Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
844           Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
845           if (uclosed || vclosed) {
846             Standard_Real pf = c2d1->FirstParameter();
847             //      Standard_Real pl = c2d1->LastParameter();
848             gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
849             //      gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
850             gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
851             gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
852             Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
853             Standard_Real U1, U2, V1, V2;
854             surf2->Bounds(U1, U2, V1, V2);
855             isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
856               (vclosed && aDist > 0.75*(fabs(V2-V1))));
857             if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
858           }
859         }
860       }
861
862       isResEdge = Standard_True;
863       if (isSeam) {
864         if (Ori == TopAbs_FORWARD)
865           aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
866         else
867           aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
868       }
869       else if (isSeam2) {
870         TopAbs_Orientation InitOri  = edge2.Orientation();
871         TopAbs_Orientation SecOri  = edge.Orientation();
872         if (fac2.Orientation() == TopAbs_REVERSED) {
873
874           InitOri = TopAbs::Reverse(InitOri);
875           SecOri = TopAbs::Reverse(SecOri);
876         }
877         if(!secForward)
878           InitOri = TopAbs::Reverse(InitOri);
879
880         if (InitOri == TopAbs_FORWARD)
881           aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
882         else
883           aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
884       } 
885       else {
886         aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
887       }
888     }
889   }
890   Standard_Real tolReached = Precision::Infinite();
891   Standard_Boolean isSamePar = Standard_False; 
892   try
893   {
894     if( isResEdge)
895       SameParameter(edge);
896     
897
898     if( BRep_Tool::SameParameter(edge))
899     {
900       isSamePar = Standard_True;
901       tolReached = BRep_Tool::Tolerance(edge);
902     }
903   }
904   
905   catch(Standard_Failure const&)
906   {
907     isSamePar = Standard_False;
908   }
909  
910  
911   if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
912     Standard_Integer whichSecn = whichSec;
913     // Try to merge on the second section
914     Standard_Boolean second_ok = Standard_False;
915     TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
916       secForward,whichSecn,Standard_False);
917     if( !s_edge.IsNull())
918     {
919       Standard_Real tolReached_2  = BRep_Tool::Tolerance(s_edge);
920       second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
921       if( second_ok)
922       {
923         edge = s_edge;
924         whichSec = whichSecn;
925         tolReached = tolReached_2;
926       }
927     }
928
929     if (!second_ok && !edge.IsNull()) {
930
931       GeomAdaptor_Curve c3dAdapt(c3d);
932
933       // Discretize edge curve
934       Standard_Integer i, j, nbp = 23;
935       Standard_Real deltaT = (last3d - first3d) / (nbp -1);
936       TColgp_Array1OfPnt c3dpnt(1,nbp);
937       for (i = 1; i <= nbp; i++) 
938         c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT);
939
940       Standard_Real dist = 0., maxTol = -1.0;
941       Standard_Boolean more = Standard_True;
942
943       for (j = 1; more; j++) {
944         Handle(Geom2d_Curve) c2d2;
945         BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
946             
947         more = !c2d2.IsNull();
948         if (more) {
949           Handle(Geom_Surface) aS = surf2;
950           if(!loc2.IsIdentity())
951             aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
952
953           Standard_Real dist2 = 0.;
954           deltaT = (last - first) / (nbp - 1);
955           for (i = 1; i <= nbp; i++) {
956             gp_Pnt2d aP2d =  c2d2->Value(first + (i -1)*deltaT);
957             gp_Pnt aP2(0.,0.,0.);
958             aS->D0(aP2d.X(),aP2d.Y(), aP2);
959             gp_Pnt aP1 = c3dpnt(i);
960             dist = aP2.SquareDistance(aP1);
961             if (dist > dist2) 
962               dist2 = dist;
963           }
964           maxTol = Max(sqrt(dist2) * (1. + 1e-7), Precision::Confusion());
965         }
966       }
967       if (maxTol >= 0. && maxTol < tolReached)
968       {
969         if (tolReached > MaxTolerance())
970         {
971           // Set tolerance directly to overwrite too large tolerance
972           static_cast<BRep_TEdge*>(edge.TShape().get())->Tolerance(maxTol);
973         }
974         else
975         {
976           // just update tolerance with computed distance
977           aBuilder.UpdateEdge(edge, maxTol);
978         }
979       }
980       aBuilder.SameParameter(edge,Standard_True);
981     }
982   }
983
984   Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
985   if (tolEdge1 > MaxTolerance()) edge.Nullify();
986   return edge;
987 }
988
989 //=======================================================================
990 // function : EvaluateAngulars
991 // purpose  : internal use
992 //=======================================================================
993
994 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
995                                        TColStd_Array1OfBoolean& secForward,
996                                        TColStd_Array1OfReal& tabAng,
997                                        const Standard_Integer indRef) const
998 {
999   tabAng.Init(-1.0);
1000
1001   Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
1002
1003   TopoDS_Edge edge;
1004   TopoDS_Face face;
1005   TopLoc_Location loc;
1006   Standard_Real first, last;
1007   Handle(Geom_Curve) c3d;
1008   Handle(Geom2d_Curve) c2d;
1009   Handle(Geom_Surface) surf;
1010   TColgp_Array1OfVec normRef(1,npt);
1011
1012   for (i = indRef; i <= lengSec; i++) {
1013
1014     edge = TopoDS::Edge(sequenceSec(i));
1015
1016     TopoDS_Shape bnd = edge;
1017     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1018     if (myBoundFaces.Contains(bnd)) {
1019       face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
1020       surf = BRep_Tool::Surface(face,loc);
1021       if (!loc.IsIdentity()) {
1022         surf = Handle(Geom_Surface)::DownCast(surf->Copy());
1023         surf->Transform(loc.Transformation());
1024       }
1025       c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
1026     }
1027     else if (i == indRef) return;
1028     else continue;
1029
1030     c3d = BRep_Tool::Curve(edge, loc, first, last);
1031     if (!loc.IsIdentity()) {
1032       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1033       c3d->Transform(loc.Transformation());
1034     }
1035
1036     GeomAdaptor_Curve adapt(c3d);
1037     GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1038
1039     Standard_Real cumulateAngular = 0.0;
1040     Standard_Integer nbComputedAngle = 0;
1041
1042     for (j = 1; j <= npt; j++) {
1043       gp_Pnt2d P;
1044       c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1045       gp_Vec w1, w2;
1046       gp_Pnt unused;
1047       surf->D1(P.X(), P.Y(), unused, w1, w2);
1048       gp_Vec n = w1^w2; // Compute the normal vector
1049       if (i == indRef) normRef(j) = n;
1050       else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1051         nbComputedAngle++;
1052         Standard_Real angular = n.Angle(normRef(j));
1053         if (angular > M_PI/2.) angular = M_PI - angular;
1054         cumulateAngular += angular;
1055       }
1056     }
1057
1058     if (nbComputedAngle)
1059       tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1060   }
1061 }
1062
1063 //=======================================================================
1064 // function : EvaluateDistances
1065 // purpose  : internal use
1066 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1067 // Remarks (lengSec - indRef) must be >= 1 
1068 //=======================================================================
1069 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1070                                               TColStd_Array1OfBoolean& secForward,
1071                                               TColStd_Array1OfReal& tabDst,
1072                                               TColStd_Array1OfReal& arrLen,
1073                                               TColStd_Array1OfReal& tabMinDist,
1074                                               const Standard_Integer indRef) const
1075 {
1076   secForward.Init(Standard_True);
1077   tabDst.Init(-1.0);
1078   arrLen.Init(0.);
1079   tabMinDist.Init(Precision::Infinite());
1080   const Standard_Integer npt = 8; // Number of points for curve discretization
1081   TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1082
1083   Standard_Integer i, j, lengSec = sequenceSec.Length();
1084   TColgp_SequenceOfPnt seqSec;
1085
1086   Handle(Geom_Curve) c3dRef;
1087   Standard_Real firstRef=0., lastRef=0.;
1088   
1089   for (i = indRef; i <= lengSec; i++) {
1090
1091     // reading of the edge (attention for the first one: reference)
1092     const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1093
1094     TopLoc_Location loc;
1095     Standard_Real first, last;
1096     Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1097     if (c3d.IsNull()) continue;
1098     if (!loc.IsIdentity()) {
1099       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1100       c3d->Transform(loc.Transformation());
1101     }
1102
1103     if (i == indRef) {
1104       c3dRef = c3d; firstRef = first; lastRef = last;
1105     }
1106
1107     Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1108     Standard_Real aMinDist = Precision::Infinite();
1109
1110     Standard_Real T, deltaT = (last - first) / (npt - 1);
1111     Standard_Real aLenSec2 = 0.;
1112    
1113     Standard_Integer nbFound = 0;
1114     for (j = 1; j <= npt; j++) {
1115
1116       // Uniform parameter on curve
1117       if (j == 1) T = first;
1118       else if (j == npt) T = last;
1119       else T = first + (j - 1) * deltaT;
1120
1121       // Take point on curve
1122       gp_Pnt pt = c3d->Value(T);
1123      
1124       if (i == indRef) {
1125         ptsRef(j) = pt;
1126         if(j > 1)
1127           aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1128       }
1129       else {
1130         ptsSec(j) = pt;
1131         //protection to avoid merging with small sections
1132         if(j > 1)
1133           aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1134         // To evaluate mutual orientation and distance
1135         dist = pt.Distance(ptsRef(j));
1136         if(aMinDist > dist)
1137           aMinDist = dist;
1138         if (distFor < dist) distFor = dist;
1139         dist = pt.Distance(ptsRef(npt-j+1));
1140    
1141         if(aMinDist > dist)
1142           aMinDist = dist;
1143         if (distRev < dist) distRev = dist;
1144
1145         // Check that point lays between vertices of reference curve
1146         const gp_Pnt &p11 = ptsRef(1);
1147         const gp_Pnt &p12 = ptsRef(npt);
1148         const gp_Vec aVec1(pt,p11);
1149         const gp_Vec aVec2(pt,p12);
1150         const gp_Vec aVecRef(p11,p12);
1151         if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1152           nbFound++;
1153       }
1154     }
1155
1156     Standard_Real aLenSec = sqrt(aLenSec2);
1157     
1158     //if(aLenSec < myMinTolerance )
1159      // continue;
1160     arrLen.SetValue(i,aLenSec);
1161     // Record mutual orientation
1162     Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1163     secForward(i) = isForward;
1164
1165     dist = (isForward? distFor : distRev);
1166     if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1167     {
1168       tabDst(i) = dist;
1169       tabMinDist(i) = aMinDist;
1170     }
1171     else
1172     {
1173       nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1174       TColgp_Array1OfPnt arrProj(1, npt);
1175       TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1176       if( arrLen(indRef) >= arrLen(i)) 
1177         ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1178       else
1179         ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1180       for( j = 1; j <= npt; j++ )
1181       {
1182         if(arrDist(j) < 0.)
1183           continue;
1184         if(dist < arrDist(j))
1185           dist = arrDist(j);
1186         if( aMinDist > arrDist(j))
1187           aMinDist = arrDist(j);
1188         nbFound++;
1189       }
1190       if(nbFound > 1)
1191       {
1192         tabDst(i) = dist;
1193         tabMinDist(i) =  aMinDist;
1194       }
1195     }
1196   }
1197
1198   /*
1199   // Project distant points
1200   Standard_Integer nbFailed = seqSec.Length();
1201   if (!nbFailed) return;
1202
1203   TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1204   for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1205   TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1206
1207   ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1208
1209   // Process distant sections
1210   Standard_Integer idx1 = 1;
1211   for (i = indRef + 1; i <= lengSec; i++) {
1212
1213     // Skip section if already evaluated
1214     if (tabDst(i) >= 0.0) continue;
1215
1216     Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1217
1218     Standard_Integer idx2 = (idx1 - 1)*npt;
1219
1220     for (j = 1; j <= npt; j++) {
1221
1222       dist = arrDist(idx2 + j);
1223       // If point is not projected - stop evaluation
1224       if (dist < 0.0) { distMax = -1.0; break; }
1225       if (distMax < dist) distMax = dist;
1226       if(aMinDist > dist) aMinDist = dist;
1227     }
1228
1229     // If section is close - record distance
1230     if (distMax >= 0.0) {
1231       if (secForward(i)) {
1232         dist = arrPnt(idx2+1).Distance(ptsRef(1));
1233         if (distMax < dist) distMax = dist;
1234         if(aMinDist > dist) aMinDist = dist;
1235         dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1236         if (distMax < dist) distMax = dist;
1237         if(aMinDist > dist) aMinDist = dist;
1238       }
1239       else {
1240         dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1241         if (distMax < dist) distMax = dist;
1242         if(aMinDist > dist) aMinDist = dist;
1243         dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1244         if (distMax < dist) distMax = dist;
1245         if(aMinDist > dist) aMinDist = dist;
1246       }
1247
1248       if (distMax < myTolerance) 
1249       {
1250         tabDst(i) = distMax;
1251         tabMinDist(i) = aMinDist;
1252       }
1253     }
1254
1255     idx1++; // To the next distant curve
1256   }*/
1257 }
1258
1259 //=======================================================================
1260 //function : IsMergedClosed
1261 //purpose  :  internal use
1262 //=======================================================================
1263
1264 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1265                                                  const TopoDS_Edge& Edge2,
1266                                                  const TopoDS_Face& face) const
1267 {
1268   // Check for closed surface
1269   TopLoc_Location loc;
1270   Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1271   Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1272   Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1273   if (!isUClosed && !isVClosed) return Standard_False;
1274   // Check condition on closed surface
1275   /*
1276   Standard_Real first1,last1,first2,last2;
1277   Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1278   Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1279   if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1280   */
1281   Standard_Real first2d1,last2d1,first2d2,last2d2;
1282   Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1283   Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1284   if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1285   /*
1286   gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1287   gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1288   Standard_Real dist = p1.Distance(p2);
1289   gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1290   gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1291   Standard_Real dist2d = p12d.Distance(p22d);
1292   GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1293   Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1294   return (dist2d*0.2 >= distSurf);
1295   */
1296   Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1297   Standard_Real SUmin, SUmax, SVmin, SVmax;
1298   Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1299   Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1300   { //szv: Use brackets to destroy local variables
1301     Bnd_Box2d B1, B2;
1302     Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1303     BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1304     BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1305     B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1306     B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1307     Standard_Real du, dv;
1308     du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1309     isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1310     du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1311     isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1312     surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1313   }
1314   if (isUClosed && isVLongC1 && isVLongC2) {
1315     // Do not merge if not overlapped by V
1316     Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1317     if (dist < 0.0) {
1318       Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1319       Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1320       if (distOuter <= distInner) return Standard_True;
1321     }
1322   }
1323   if (isVClosed && isULongC1 && isULongC2) {
1324     // Do not merge if not overlapped by U
1325     Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1326     if (dist < 0.0) {
1327       Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1328       Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1329       if (distOuter <= distInner) return Standard_True;
1330     }
1331   }
1332   return Standard_False;
1333 }
1334
1335 //=======================================================================
1336 //function : AnalysisNearestEdges
1337 //purpose  : 
1338 //=======================================================================
1339
1340 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1341                                                  TColStd_SequenceOfInteger& seqIndCandidate,
1342                                                  TColStd_SequenceOfBoolean& seqOrientations,
1343                                                  const Standard_Boolean evalDist)
1344 {
1345
1346   Standard_Integer workIndex = seqIndCandidate.First();
1347   TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1348   TopoDS_Shape bnd = workedge;
1349   TopTools_ListOfShape workfaces;
1350   if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1351   if (myBoundFaces.Contains(bnd)) 
1352     workfaces = myBoundFaces.FindFromKey(bnd);
1353   if(workfaces.IsEmpty()) return;
1354   TopTools_MapOfShape mapFaces;
1355   TopTools_ListIteratorOfListOfShape lIt;
1356   for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1357     mapFaces.Add(lIt.Value());
1358   TColStd_SequenceOfInteger seqNotCandidate;
1359   TColStd_SequenceOfInteger seqNewForward;
1360   // Separates edges belonging the same face as work edge 
1361   // for exception of edges belonging closed faces 
1362
1363   seqNotCandidate.Append(workIndex);
1364   for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1365     Standard_Integer index = seqIndCandidate.Value(i);
1366     Standard_Boolean isRemove = Standard_False;
1367     if(index == workIndex) {
1368       seqIndCandidate.Remove(i);
1369       seqOrientations.Remove(i);
1370       isRemove = Standard_True;
1371     }
1372     if(!isRemove) {
1373       TopoDS_Shape bnd2 = sequenceSec.Value(index);
1374       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1375
1376       if(myBoundFaces.Contains(bnd2)) {
1377         const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1378         Standard_Boolean isMerged = Standard_True;
1379         for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1380           if(mapFaces.Contains(lIt.Value())) {
1381             TopLoc_Location loc;
1382             Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1383             isMerged = ((IsUClosedSurface(surf,bnd2,loc) ||  IsVClosedSurface(surf,bnd2,loc)) && 
1384               IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1385           }
1386         }
1387         if(!isMerged) {
1388           seqNotCandidate.Append(index);
1389           seqIndCandidate.Remove(i);
1390           seqOrientations.Remove(i);
1391           isRemove = Standard_True;
1392         }
1393       }
1394       else {
1395         seqIndCandidate.Remove(i);
1396         seqOrientations.Remove(i);
1397         isRemove = Standard_True;
1398       }
1399     }
1400     if(!isRemove) i++;  
1401   }
1402   if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1403   if(!evalDist) return;
1404   TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1405   TColStd_MapOfInteger MapIndex;
1406   TColStd_SequenceOfInteger seqForward;
1407
1408   // Definition and removing edges wich are not candidate for work edge 
1409   // ( they have other nearest edges belonging to the work face) 
1410   for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1411     Standard_Integer index1 = seqNotCandidate.Value(k);
1412     TopoDS_Shape edge = sequenceSec.Value(index1);
1413     TopTools_SequenceOfShape tmpSeq;
1414     tmpSeq.Append(edge);
1415     for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++) 
1416       tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1417
1418     Standard_Integer lengSec = tmpSeq.Length();
1419     TColStd_Array1OfBoolean tabForward(1,lengSec);
1420     TColStd_Array1OfReal tabDist(1,lengSec);
1421     TColStd_Array1OfReal arrLen(1,lengSec);
1422     TColStd_Array1OfReal tabMinDist(1,lengSec);
1423     for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++) 
1424       tabDist(i1) =-1;
1425
1426     EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1427     if(k == 1) {
1428       for(Standard_Integer n = 1; n < lengSec; n++) {
1429         if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1430           MapIndex.Add(n);
1431           continue;
1432         }
1433         TotTabDist(k,n) = tabDist(n+1 );
1434         seqForward.Append(tabForward(n+1) ? 1:0);
1435       }
1436     }
1437     else {
1438       for(Standard_Integer n = 1; n < lengSec; n++) {
1439         if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1440         if(tabDist(n+1) < TotTabDist(1,n)) {
1441           MapIndex.Add(n);
1442         }
1443       }
1444     }
1445   }
1446
1447   Standard_Integer i2 = seqIndCandidate.Length();
1448   for( ; i2 >=1 ; i2--)
1449   {
1450     if(MapIndex.Contains(i2))
1451     { 
1452       seqIndCandidate.Remove(i2);
1453       seqOrientations.Remove(i2);
1454     }
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_SequenceOfBoolean& 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_Boolean ori = arrForward(i);
1523         for (Standard_Integer 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_SequenceOfBoolean seqOrientationsNew;
1560     seqCandidates.Prepend(1);
1561     seqOrientations.Prepend(Standard_True);
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;
1662       TColStd_SequenceOfBoolean seqOrientations1;
1663       Standard_Boolean isFound =
1664         FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1665       mapReference.RemoveLast(); // Pop candidate from the map
1666       if (isFound) isFound = (seqCandidates1.Length() > 0);
1667       if (isFound) {
1668         Standard_Integer indCandidate1 = seqCandidates1.First();
1669         // If indReference is the best candidate for indCandidate
1670         // then indCandidate is the best candidate for indReference
1671         if (indCandidate1 == indReference) break;
1672         // If some other reference in the map is the best candidate for indCandidate
1673         // then assume that reference is the best candidate for indReference
1674         if (mapReference.Contains(indCandidate1)) {
1675           seqCandidates.Prepend(indCandidate1);
1676           nbCandidates++;
1677           break;
1678         }
1679         isFound = Standard_False;
1680       }
1681       if (!isFound) {
1682         // Remove candidate #1
1683         seqCandidates.Remove(1);
1684         seqOrientations.Remove(1);
1685         nbCandidates--;
1686       }
1687     }
1688   }
1689   //gka
1690   if(nbCandidates > 0)
1691   {
1692     Standard_Integer anInd = seqCandidates.Value(1);
1693     TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1694     TopoDS_Shape bnd = Edge2;
1695     if (mySectionBound.IsBound(bnd)) 
1696       bnd = mySectionBound(bnd);
1697     //gka
1698     if (myBoundFaces.Contains(bnd)) {
1699       Standard_Boolean isOK = Standard_True;
1700       TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1701       for (; itf2.More() && isOK; itf2.Next()) {
1702         const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1703         // Check whether condition is satisfied
1704         isOK = !Faces1.Contains(Face2);
1705         if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1706       }
1707       if(!isOK)
1708         return Standard_False;
1709     }
1710   }
1711   return (nbCandidates > 0);
1712 }
1713
1714 //=======================================================================
1715 //function : Constructor
1716 //purpose  : 
1717 //=======================================================================
1718
1719 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1720                                  const Standard_Boolean optionSewing,
1721                                  const Standard_Boolean optionAnalysis,
1722                                  const Standard_Boolean optionCutting,
1723                                  const Standard_Boolean optionNonmanifold)
1724 {
1725   myReShape = new BRepTools_ReShape;
1726   Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1727 }
1728
1729 //=======================================================================
1730 //function : Init
1731 //purpose  : Initialise Talerance, and options sewing, faceAnalysis and cutting
1732 //=======================================================================
1733
1734 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1735                            const Standard_Boolean optionSewing,
1736                            const Standard_Boolean optionAnalysis,
1737                            const Standard_Boolean optionCutting,
1738                            const Standard_Boolean optionNonmanifold)
1739 {
1740   // Set tolerance and Perform options
1741   myTolerance      = Max (tolerance, Precision::Confusion());
1742   mySewing         = optionSewing;
1743   myAnalysis       = optionAnalysis;
1744   myCutting        = optionCutting;
1745   myNonmanifold    = optionNonmanifold;
1746   // Set min and max tolerances
1747   myMinTolerance   = myTolerance * 1e-4; //szv: proposal
1748   if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1749   myMaxTolerance   = Precision::Infinite();
1750   // Set other modes
1751   myFaceMode           = Standard_True;
1752   myFloatingEdgesMode  = Standard_False;
1753   //myCuttingFloatingEdgesMode = Standard_False; //gka
1754   mySameParameterMode  = Standard_True;
1755   myLocalToleranceMode = Standard_False;
1756   mySewedShape.Nullify();
1757   // Load empty shape
1758   Load(TopoDS_Shape());
1759 }
1760
1761 //=======================================================================
1762 //function : Load
1763 //purpose  : Loads the context shape
1764 //=======================================================================
1765
1766 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1767 {
1768   myReShape->Clear();
1769   if (theShape.IsNull()) myShape.Nullify();
1770   else myShape = myReShape->Apply(theShape);
1771   mySewedShape.Nullify();
1772   // Nullify flags and counters
1773   myNbShapes = myNbEdges = myNbVertices = 0;
1774   // Clear all maps
1775   myOldShapes.Clear();
1776   //myOldFaces.Clear();
1777   myDegenerated.Clear();
1778   myFreeEdges.Clear();
1779   myMultipleEdges.Clear();
1780   myContigousEdges.Clear();
1781   myContigSecBound.Clear();
1782   myBoundFaces.Clear();
1783   myBoundSections.Clear();
1784   myVertexNode.Clear();
1785   myVertexNodeFree.Clear();
1786   myNodeSections.Clear();
1787   myCuttingNode.Clear();
1788   mySectionBound.Clear();
1789   myLittleFace.Clear();
1790 }
1791
1792 //=======================================================================
1793 //function : Add
1794 //purpose  : 
1795 //=======================================================================
1796
1797 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1798 {
1799   if (aShape.IsNull()) return;
1800   TopoDS_Shape oShape = myReShape->Apply(aShape);
1801   myOldShapes.Add(aShape,oShape);
1802   myNbShapes = myOldShapes.Extent();
1803 }
1804
1805 //=======================================================================
1806 //function : Perform
1807 //purpose  : 
1808 //=======================================================================
1809
1810 #ifdef OCCT_DEBUG
1811 #include <OSD_Timer.hxx>
1812 #endif
1813
1814 void BRepBuilderAPI_Sewing::Perform(const Message_ProgressRange& theProgress)
1815 {
1816   const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1817   Message_ProgressScope aPS (theProgress, "Sewing", aNumberOfStages);
1818 #ifdef OCCT_DEBUG
1819   Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1820   OSD_Chronometer chr_total, chr_local;
1821   chr_total.Reset();
1822   chr_total.Start();
1823 #endif
1824
1825   // face analysis
1826   if (myAnalysis)
1827   {
1828 #ifdef OCCT_DEBUG
1829     std::cout << "Begin face analysis..." << std::endl;
1830     chr_local.Reset();
1831     chr_local.Start();
1832 #endif
1833     FaceAnalysis (aPS.Next());
1834     if (!aPS.More())
1835       return;
1836 #ifdef OCCT_DEBUG
1837     chr_local.Stop();
1838     chr_local.Show(t_analysis);
1839     std::cout << "Face analysis finished after " << t_analysis << " s" << std::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       std::cout << "Begin vertices assembling..." << std::endl;
1853       chr_local.Reset();
1854       chr_local.Start();
1855 #endif
1856       VerticesAssembling (aPS.Next());
1857       if (!aPS.More())
1858         return;
1859 #ifdef OCCT_DEBUG
1860       chr_local.Stop();
1861       chr_local.Show(t_assembling);
1862       std::cout << "Vertices assembling finished after " << t_assembling << " s" << std::endl;
1863 #endif
1864       if (myCutting)
1865       {
1866 #ifdef OCCT_DEBUG
1867         std::cout << "Begin cutting..." << std::endl;
1868         chr_local.Reset();
1869         chr_local.Start();
1870 #endif
1871         Cutting (aPS.Next());
1872         if (!aPS.More())
1873           return;
1874 #ifdef OCCT_DEBUG
1875         chr_local.Stop();
1876         chr_local.Show(t_cutting);
1877         std::cout << "Cutting finished after " << t_cutting << " s" << std::endl;
1878 #endif
1879       }
1880 #ifdef OCCT_DEBUG
1881       std::cout << "Begin merging..." << std::endl;
1882       chr_local.Reset();
1883       chr_local.Start();
1884 #endif
1885       Merging (Standard_True, aPS.Next());
1886       if (!aPS.More())
1887         return;
1888 #ifdef OCCT_DEBUG
1889       chr_local.Stop();
1890       chr_local.Show(t_merging);
1891       std::cout << "Merging finished after " << t_merging << " s" << std::endl;
1892 #endif
1893     }
1894     else
1895     {
1896       aPS.Next();
1897       if (myCutting)
1898         aPS.Next();
1899       aPS.Next();
1900       if (!aPS.More())
1901         return;
1902     }
1903
1904     if (mySewing)
1905     {
1906
1907 #ifdef OCCT_DEBUG
1908       std::cout << "Creating sewed shape..." << std::endl;
1909 #endif
1910       // examine the multiple edges if any and process sameparameter for edges if necessary
1911       EdgeProcessing (aPS.Next());
1912       if (!aPS.More())
1913         return;
1914       CreateSewedShape();
1915       if (!aPS.More())
1916       {
1917         mySewedShape.Nullify();
1918         return;
1919       }
1920
1921       EdgeRegularity (aPS.Next());
1922
1923       if (mySameParameterMode && myFaceMode)
1924         SameParameterShape();
1925       if (!aPS.More())
1926       {
1927         mySewedShape.Nullify();
1928         return;
1929       }
1930 #ifdef OCCT_DEBUG
1931       std::cout << "Sewed shape created" << std::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   std::cout << "Sewing finished!" << std::endl;
1947   std::cout << " analysis time   : " << t_analysis << " s" << std::endl;
1948   std::cout << " assembling time : " << t_assembling << " s" << std::endl;
1949   std::cout << " cutting time    : " << t_cutting << " s" << std::endl;
1950   std::cout << " merging time    : " << t_merging << " s" << std::endl;
1951   std::cout << "Total time       : " << t_total << " s" << std::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   std::cout << " " << std::endl;
2204   std::cout << "                        Informations                        " << std::endl;
2205   std::cout << " ===========================================================" << std::endl;
2206   std::cout << " " << std::endl;
2207   std::cout << " Number of input shapes      : " << myOldShapes.Extent() << std::endl;
2208   std::cout << " Number of actual shapes     : " << myNbShapes << std::endl;
2209   std::cout << " Number of Bounds            : " << NbBounds << std::endl;
2210   std::cout << " Number of Sections          : " << NbSections << std::endl;
2211   std::cout << " Number of Edges             : " << mapEdges.Extent() << std::endl;
2212   std::cout << " Number of Vertices          : " << myNbVertices << std::endl;
2213   std::cout << " Number of Nodes             : " << mapVertices.Extent() << std::endl;
2214   std::cout << " Number of Free Edges        : " << myFreeEdges.Extent() << std::endl;
2215   std::cout << " Number of Contigous Edges   : " << myContigousEdges.Extent() << std::endl;
2216   std::cout << " Number of Multiple Edges    : " << myMultipleEdges.Extent() << std::endl;
2217   std::cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << std::endl;
2218   std::cout << " ===========================================================" << std::endl;
2219   std::cout << " " << std::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 Message_ProgressRange& theProgress)
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_IndexedDataMapOfShapeListOfShape GluedVertices;
2243   Standard_Integer i = 1;
2244   Message_ProgressScope aPS (theProgress, "Shape analysis", myOldShapes.Extent());
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               std::cout << "Warning: Possibly small edge can be sewed: No 3D curve" << std::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                 std::cout << "Warning: Possibly small edge can be sewed: ";
2317                 Standard_Failure::Caught()->Print(std::cout); std::cout << std::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.ChangeFromKey(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.FindFromKey(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.RemoveKey(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.ChangeFromKey(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.Add(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             std::cout << "Warning: Small edge made degenerated by FaceAnalysis" << std::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         std::cout << "Warning: Small face removed by FaceAnalysis" << std::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_IndexedDataMapOfShapeListOfShape::Iterator aMIter(GluedVertices);
2426   for (; aMIter.More(); aMIter.Next()) {
2427     const TopoDS_Vertex& vnew = TopoDS::Vertex(aMIter.Key());
2428     gp_XYZ coord(0.,0.,0.);
2429     Standard_Integer nbPoints = 0;
2430     const TopTools_ListOfShape& vlist = aMIter.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     const 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       const 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       const 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           const 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   TopTools_IndexedDataMapOfShapeListOfShape::Iterator anIterEF(EdgeFaces);
2528   for (; anIterEF.More(); anIterEF.Next()) {
2529     TopTools_ListOfShape& listFaces = anIterEF.ChangeValue();
2530     Standard_Integer nbFaces = listFaces.Extent();
2531     TopoDS_Shape edge = anIterEF.Key();
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   // Create new nodes
2622   BRep_Builder B;
2623   TopTools_DataMapOfShapeShape OldNodeNewNode;
2624   TopTools_IndexedDataMapOfShapeListOfShape NewNodeOldNodes;
2625   TopTools_IndexedDataMapOfShapeShape::Iterator anIter(NodeNearestNode);
2626   for (; anIter.More(); anIter.Next()) {
2627     // Retrieve a pair of nodes to merge
2628     const TopoDS_Shape& oldnode1 = anIter.Key();
2629     const TopoDS_Shape& oldnode2 = anIter.Value();
2630     // Second node should also be in the map
2631     if (!NodeNearestNode.Contains(oldnode2)) continue;
2632     // Get new node for old node #1
2633     if (OldNodeNewNode.IsBound(oldnode1)) {
2634       const TopoDS_Shape& newnode1 = OldNodeNewNode(oldnode1);
2635       if (OldNodeNewNode.IsBound(oldnode2)) {
2636         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2637         if (!newnode1.IsSame(newnode2)) {
2638           // Change data for new node #2
2639           TopTools_ListOfShape& lnode1 = NewNodeOldNodes.ChangeFromKey(newnode1);
2640           TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes.FindFromKey(newnode2));
2641           for (; itn.More(); itn.Next()) {
2642             const TopoDS_Shape& node2 = itn.Value();
2643             lnode1.Append(node2);
2644             OldNodeNewNode(node2) = newnode1;
2645           }
2646           NewNodeOldNodes.RemoveKey(newnode2);
2647         }
2648       }
2649       else {
2650         // Old node #2 is not bound - add to old node #1
2651         OldNodeNewNode.Bind(oldnode2,newnode1);
2652         NewNodeOldNodes.ChangeFromKey(newnode1).Append(oldnode2);
2653       }
2654     }
2655     else {
2656       if (OldNodeNewNode.IsBound(oldnode2)) {
2657         // Old node #1 is not bound - add to old node #2
2658         const TopoDS_Shape& newnode2 = OldNodeNewNode(oldnode2);
2659         OldNodeNewNode.Bind(oldnode1,newnode2);
2660         NewNodeOldNodes.ChangeFromKey(newnode2).Append(oldnode1);
2661       }
2662       else {
2663         // Nodes are not bound - create new node
2664         TopoDS_Vertex newnode;
2665         B.MakeVertex(newnode);
2666         OldNodeNewNode.Bind(oldnode1,newnode);
2667         OldNodeNewNode.Bind(oldnode2,newnode);
2668         TopTools_ListOfShape lnodes;
2669         lnodes.Append(oldnode1);
2670         lnodes.Append(oldnode2);
2671         NewNodeOldNodes.Add(newnode,lnodes);
2672       }
2673     }
2674   }
2675
2676   // Stop if no new nodes created
2677   if (!NewNodeOldNodes.Extent()) return Standard_False;
2678
2679   TopTools_IndexedDataMapOfShapeListOfShape::Iterator anIter1(NewNodeOldNodes);
2680   for (; anIter1.More(); anIter1.Next()) {
2681     const TopoDS_Vertex& newnode = TopoDS::Vertex(anIter1.Key());
2682     // Calculate new node center point
2683     gp_XYZ theCoordinates(0.,0.,0.);
2684     TopTools_ListOfShape lvert; // Accumulate node vertices
2685     TopTools_MapOfShape medge;
2686     TopTools_ListOfShape ledge; // Accumulate node edges
2687     // Iterate on old nodes
2688     TopTools_ListIteratorOfListOfShape itn(anIter1.Value());
2689     for (; itn.More(); itn.Next()) {
2690       const TopoDS_Shape& oldnode = itn.Value();
2691       // Iterate on node vertices
2692       TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2693       for (; itv.More(); itv.Next()) {
2694         const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2695         // Change node for vertex
2696         aVertexNode.ChangeFromKey(vertex) = newnode;
2697         // Accumulate coordinates
2698         theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2699         lvert.Append(vertex);
2700       }
2701       // Iterate on node edges
2702       const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2703       TopTools_ListIteratorOfListOfShape ite(edges);
2704       for (; ite.More(); ite.Next()) {
2705         const TopoDS_Shape& edge = ite.Value();
2706         if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2707       }
2708       // Unbind old node edges
2709       aNodeEdges.UnBind(oldnode);
2710     }
2711     // Bind new node edges
2712     aNodeEdges.Bind(newnode,ledge);
2713     gp_Pnt center(theCoordinates / lvert.Extent());
2714     // Calculate new node tolerance
2715     Standard_Real toler = 0.0;
2716     TopTools_ListIteratorOfListOfShape itv(lvert);
2717     for (; itv.More(); itv.Next()) {
2718       const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2719       Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2720       if (toler < t) toler = t;
2721     }
2722     // Update new node parameters
2723     B.UpdateVertex(newnode,center,toler);
2724   }
2725
2726   return Standard_True;
2727 }
2728
2729 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2730                                          const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2731                                          const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2732 {
2733   //Case of floating edges
2734   if (face1.IsNull())
2735     return (!IsClosedShape(e1,vtx1,vtx2));
2736
2737   // Find wires containing given edges
2738   TopoDS_Shape wire1, wire2;
2739   TopExp_Explorer itw(face1,TopAbs_WIRE);
2740   for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2741     TopoDS_Iterator ite(itw.Current(),Standard_False);
2742     for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2743       if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2744       if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2745     }
2746   }
2747   Standard_Integer Status = 0;
2748   if (!wire1.IsNull() && !wire2.IsNull()) {
2749     if (wire1.IsSame(wire2)) {
2750       for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2751         TopoDS_Vertex ve1,ve2;
2752         TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2753         if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2754             (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2755           return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2756       }
2757       if (IsClosedShape(wire1,vtx1,vtx2)) {
2758         TopoDS_Vertex V1, V2;
2759         TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2760         Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2761                                         (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2762         if (!isEndVertex) Status = 1;
2763       }
2764       else Status = 1;
2765     }
2766     else Status = -1;
2767   }
2768   return Status;
2769 }
2770
2771 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2772                                      TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2773                                      const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2774                                      const Standard_Real Tolerance,
2775                                      const Message_ProgressRange& theProgress)
2776 {
2777   // Create map of node -> vertices
2778   TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2779   BRepBuilderAPI_CellFilter aFilter (Tolerance);
2780   BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2781   TopTools_IndexedDataMapOfShapeShape::Iterator anIter1(aVertexNode);
2782   for (; anIter1.More(); anIter1.Next()) {
2783     const TopoDS_Shape& vertex = anIter1.Key();
2784     const TopoDS_Vertex& node = TopoDS::Vertex(anIter1.Value());
2785     if (NodeVertices.Contains(node)) {
2786       NodeVertices.ChangeFromKey(node).Append(vertex);
2787     }
2788     else {
2789       TopTools_ListOfShape vlist;
2790       vlist.Append(vertex);
2791       NodeVertices.Add(node,vlist);
2792       gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2793       aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2794       anInspector.Add (aPnt.XYZ());
2795     }
2796   }
2797   Standard_Integer nbNodes = NodeVertices.Extent();
2798 #ifdef OCCT_DEBUG
2799   std::cout << "Glueing " << nbNodes << " nodes..." << std::endl;
2800 #endif
2801   // Merge nearest nodes
2802   TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2803   Message_ProgressScope aPS (theProgress, "Glueing nodes", nbNodes, Standard_True);
2804   for (Standard_Integer i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2805     const TopoDS_Vertex& node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2806     // Find near nodes
2807     gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2808     anInspector.SetCurrent (pt1.XYZ());
2809     gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2810     gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2811     aFilter.Inspect (aPntMin, aPntMax, anInspector);
2812     if (anInspector.ResInd().IsEmpty()) continue;
2813     // Retrieve list of edges for the first node
2814     const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2815     // Explore list of near nodes and fill the sequence of glued nodes
2816     TopTools_SequenceOfShape SeqNodes;
2817     TopTools_ListOfShape listNodesSameEdge;
2818     //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2819     TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2820     for (; iter1.More(); iter1.Next()) {
2821       const TopoDS_Vertex& node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2822       if (node1 == node2) continue;
2823       // Retrieve list of edges for the second node
2824       const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2825       // Check merging condition for the pair of nodes
2826       Standard_Integer Status = 0, isSameEdge = Standard_False;
2827       // Explore edges of the first node
2828       TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2829       for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2830         const TopoDS_Shape& e1 = Ie1.Value();
2831         // Obtain real vertex from edge
2832         TopoDS_Shape v1 = node1;
2833         { //szv: Use brackets to destroy local variables
2834           TopoDS_Vertex ov1, ov2;
2835           TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2836           if (aVertexNode.Contains(ov1)) {
2837             if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2838           }
2839           if (aVertexNode.Contains(ov2)) {
2840             if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2841           }
2842         }
2843         // Create map of faces for e1
2844         TopTools_MapOfShape Faces1;
2845         const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2846         if (lfac1.Extent()) {
2847           TopTools_ListIteratorOfListOfShape itf(lfac1);
2848           for (; itf.More(); itf.Next())
2849             if (!itf.Value().IsNull())
2850               Faces1.Add(itf.Value());
2851         }
2852         // Explore edges of the second node
2853         TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2854         for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2855           const TopoDS_Shape& e2 = Ie2.Value();
2856           // Obtain real vertex from edge
2857           TopoDS_Shape v2 = node2;
2858           { //szv: Use brackets to destroy local variables
2859             TopoDS_Vertex ov1, ov2;
2860             TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2861             if (aVertexNode.Contains(ov1)) {
2862               if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2863             }
2864             if (aVertexNode.Contains(ov2)) {
2865               if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2866             }
2867           }
2868           // Explore faces for e2
2869           const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2870           if (lfac2.Extent()) {
2871             TopTools_ListIteratorOfListOfShape itf(lfac2);
2872             for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2873               // Check merging conditions for the same face
2874               if (Faces1.Contains(itf.Value())) {
2875                 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2876                 if (stat == 1) isSameEdge = Standard_True;
2877                 else Status = stat;
2878               }
2879             }
2880           }
2881           else if (Faces1.IsEmpty() && e1 == e2) {
2882             Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2883             if (stat == 1) isSameEdge = Standard_True;
2884             else Status = stat;
2885             break;
2886           }
2887         }
2888       }
2889       if (Status) continue;
2890       if (isSameEdge) listNodesSameEdge.Append(node2);
2891       // Append near node to the sequence
2892       gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2893       Standard_Real dist = pt1.Distance(pt2);
2894       if (dist < Tolerance) {
2895         Standard_Boolean isIns = Standard_False;
2896         for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2897           gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2898           if (dist < pt1.Distance(pt)) {
2899             SeqNodes.InsertBefore(kk,node2);
2900             isIns = Standard_True;
2901           }
2902         }
2903         if (!isIns) SeqNodes.Append(node2);
2904       }
2905     }
2906     if (SeqNodes.Length()) {
2907       // Remove nodes near to some other from the same edge
2908       if (listNodesSameEdge.Extent()) {
2909         TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2910         for (; lInt.More(); lInt.Next()) {
2911           const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2912           gp_Pnt p2 = BRep_Tool::Pnt(n2);
2913           for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2914             const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2915             if (n1 != n2) {
2916               gp_Pnt p1 = BRep_Tool::Pnt(n1);
2917               if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2918             }
2919             SeqNodes.Remove(k);
2920           }
2921         }
2922       }
2923       // Bind nearest node if at least one exists
2924       if (SeqNodes.Length())
2925         NodeNearestNode.Add(node1,SeqNodes.First());
2926     }
2927     anInspector.ClearResList();
2928   }
2929
2930   // Create new nodes for chained nearest nodes
2931   if (NodeNearestNode.IsEmpty()) return Standard_False;
2932
2933   return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2934 }
2935
2936 void BRepBuilderAPI_Sewing::VerticesAssembling(const Message_ProgressRange& theProgress)
2937 {
2938   Standard_Integer nbVert = myVertexNode.Extent();
2939   Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2940   Message_ProgressScope aPS (theProgress, "Vertices assembling", 2);
2941   if (nbVert || nbVertFree) {
2942     // Fill map node -> sections
2943     Standard_Integer i;
2944     for (i = 1; i <= myBoundFaces.Extent(); i++) {
2945       TopoDS_Shape bound = myBoundFaces.FindKey(i);
2946       for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2947         TopoDS_Shape node = itv.Value();
2948         if (myNodeSections.IsBound(node))
2949           myNodeSections(node).Append(bound);
2950         else {
2951           TopTools_ListOfShape lbnd;
2952           lbnd.Append(bound);
2953           myNodeSections.Bind(node,lbnd);
2954         }
2955       }
2956     }
2957     // Glue vertices
2958     if (nbVert) {
2959 #ifdef OCCT_DEBUG
2960       std::cout << "Assemble " << nbVert << " vertices on faces..." << std::endl;
2961 #endif
2962       while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, aPS.Next()));
2963     }
2964     if (!aPS.More())
2965       return;
2966     if (nbVertFree) {
2967 #ifdef OCCT_DEBUG
2968       std::cout << "Assemble " << nbVertFree << " vertices on floating edges..." << std::endl;
2969 #endif
2970       while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, aPS.Next()));
2971     }
2972   }
2973 }
2974
2975 //=======================================================================
2976 //function : replaceNMVertices
2977 //purpose  : internal use (static)
2978 //=======================================================================
2979 static void replaceNMVertices(const TopoDS_Edge& theEdge, 
2980                               const TopoDS_Vertex& theV1,
2981                               const TopoDS_Vertex& theV2,
2982                               const Handle(BRepTools_ReShape)& theReShape)
2983 {
2984   //To keep NM vertices on edge
2985   TopTools_SequenceOfShape aSeqNMVert;
2986   TColStd_SequenceOfReal aSeqNMPars;
2987   Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2988   if(!hasNMVert)
2989     return;
2990   Standard_Real first, last;
2991   BRep_Tool::Range(theEdge, first, last);
2992   TopLoc_Location aLoc;
2993   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2994   if(c3d.IsNull())
2995     return;
2996   TopTools_SequenceOfShape aEdVert;
2997   TColStd_SequenceOfReal aEdParams;
2998   Standard_Integer i =1, nb = aSeqNMPars.Length();
2999     
3000   for( ; i <= nb;i++) {
3001     Standard_Real apar = aSeqNMPars.Value(i);
3002     if(fabs(apar - first) <= Precision::PConfusion()) {
3003       theReShape->Replace(aSeqNMVert.Value(i),theV1);
3004       continue;
3005     }
3006     if(fabs(apar - last) <= Precision::PConfusion()) {
3007       theReShape->Replace(aSeqNMVert.Value(i),theV2);
3008       continue;
3009     }
3010     TopoDS_Shape aV = aSeqNMVert.Value(i);
3011     Standard_Integer j =1;
3012     for( ; j <= aEdParams.Length();j++) {
3013       Standard_Real apar2 = aEdParams.Value(j);
3014       if(fabs(apar - apar2) <= Precision::PConfusion()) {
3015         theReShape->Replace(aV,aEdVert.Value(j));
3016         break;
3017       }
3018       else if(apar < apar2) {
3019         TopoDS_Shape anewV = aV.EmptyCopied();
3020         aEdVert.InsertBefore(j,anewV);
3021         aEdParams.InsertBefore(j,apar);
3022         BRep_ListOfPointRepresentation& alistrep = 
3023           (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
3024         Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3025         alistrep.Append(aPRep);
3026         theReShape->Replace(aV,anewV);
3027         break;
3028       }
3029     }
3030     if (j > aEdParams.Length()) {
3031       TopoDS_Shape anewV = aV.EmptyCopied();
3032       aEdVert.Append(anewV);
3033       aEdParams.Append(apar);
3034       BRep_ListOfPointRepresentation& alistrep = 
3035         (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3036       Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3037       alistrep.Append(aPRep);
3038       theReShape->Replace(aV,anewV);
3039     }
3040   }
3041   
3042   Standard_Integer newnb = aEdParams.Length();
3043   if(newnb < nb) {
3044     
3045     TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3046     TopAbs_Orientation anOri = theEdge.Orientation();
3047     anewEdge.Orientation(TopAbs_FORWARD);
3048     BRep_Builder aB;
3049     aB.Add(anewEdge,theV1);
3050     aB.Add(anewEdge,theV2);
3051     
3052     for( i =1; i <= aEdVert.Length();i++) 
3053       aB.Add(anewEdge,aEdVert.Value(i));
3054     anewEdge.Orientation(anOri);
3055     theReShape->Replace(theEdge,anewEdge);
3056   }
3057  
3058 }
3059
3060 //=======================================================================
3061 //function : ReplaceEdge
3062 //purpose  : internal use (static)
3063 //=======================================================================
3064
3065 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3066                         const TopoDS_Shape& theNewShape,
3067                         const Handle(BRepTools_ReShape)& aReShape)
3068 {
3069   TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3070   TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3071   if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3072   
3073
3074   aReShape->Replace(oldShape,newShape);
3075   TopoDS_Vertex V1old,V2old,V1new,V2new;
3076   TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3077   TopAbs_Orientation Orold = oldShape.Orientation();
3078   TopAbs_Orientation Ornew = Orold;
3079   if (newShape.ShapeType() == TopAbs_EDGE) {
3080     TopoDS_Edge aEn = TopoDS::Edge(newShape);
3081     TopExp::Vertices(aEn,V1new,V2new);
3082     Ornew = aEn.Orientation();
3083     replaceNMVertices(aEn,V1new,V2new,aReShape);
3084   }
3085   else if (newShape.ShapeType() == TopAbs_WIRE) {
3086     for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3087       TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3088       Ornew = ed.Orientation();
3089       TopoDS_Vertex aV1,aV2;
3090       TopExp::Vertices(ed,aV1,aV2);
3091       replaceNMVertices(ed,aV1,aV2,aReShape);
3092       if (V1new.IsNull()) 
3093         V1new = aV1;
3094       V2new =aV2;
3095     }
3096   }
3097   
3098   V1new.Orientation(V1old.Orientation());
3099   V2new.Orientation(V2old.Orientation());
3100   if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3101     aReShape->Replace(V1old,V1new);
3102     return;
3103   }
3104   if (Orold == Ornew) {
3105     V1new.Orientation(V1old.Orientation());
3106     V2new.Orientation(V2old.Orientation());
3107     if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3108       aReShape->Replace(V1old,V1new);
3109     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3110       aReShape->Replace(V2old,V2new);
3111   }
3112   else {
3113     V1new.Orientation(V2old.Orientation());
3114     V2new.Orientation(V1old.Orientation());
3115     if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) 
3116       aReShape->Replace(V1old,V2new);
3117     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3118       aReShape->Replace(V2old,V1new);
3119   }
3120 }
3121
3122 //=======================================================================
3123 //function : Merging
3124 //purpose  : Modifies :
3125 //                   myHasFreeBound
3126 //
3127 //=======================================================================
3128
3129 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */, 
3130                                     const Message_ProgressRange& theProgress)
3131 {
3132   BRep_Builder B;
3133   //  TopTools_MapOfShape MergedEdges;
3134   Message_ProgressScope aPS (theProgress, "Merging bounds", myBoundFaces.Extent());
3135   TopTools_IndexedDataMapOfShapeListOfShape::Iterator anIterB(myBoundFaces);
3136   for (; anIterB.More() && aPS.More(); anIterB.Next(), aPS.Next()) {
3137
3138     const TopoDS_Shape& bound = anIterB.Key();
3139
3140     // If bound was already merged - continue
3141     if (myMergedEdges.Contains(bound)) continue;
3142
3143     if (!anIterB.Value().Extent()) {
3144       // Merge free edge - only vertices
3145       TopoDS_Vertex no1, no2;
3146       TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3147       TopoDS_Shape nno1 = no1, nno2 = no2;
3148       if (myVertexNodeFree.Contains(no1))
3149         nno1 = myVertexNodeFree.FindFromKey(no1);
3150       if (myVertexNodeFree.Contains(no2))
3151         nno2 = myVertexNodeFree.FindFromKey(no2);
3152       if (!no1.IsSame(nno1)) {
3153         nno1.Orientation(no1.Orientation());
3154         myReShape->Replace(no1,nno1);
3155       }
3156       if (!no2.IsSame(nno2)) {
3157         nno2.Orientation(no2.Orientation());
3158         myReShape->Replace(no2,nno2);
3159       }
3160       myMergedEdges.Add(bound);
3161       continue;
3162     }
3163
3164     // Check for previous splitting, build replacing wire
3165     TopoDS_Wire BoundWire;
3166     Standard_Boolean isPrevSplit = Standard_False;
3167     Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3168     if (hasCuttingSections) {
3169       B.MakeWire(BoundWire);
3170       BoundWire.Orientation(bound.Orientation());
3171       // Iterate on cutting sections
3172       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3173       for (; its.More(); its.Next()) {
3174         TopoDS_Shape section = its.Value();
3175         B.Add(BoundWire,section);
3176         if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3177       }
3178     }
3179
3180     // Merge with bound
3181     TopTools_IndexedDataMapOfShapeShape MergedWithBound;
3182     if (!isPrevSplit) {
3183       // Obtain sequence of edges merged with bound
3184       TopTools_SequenceOfShape seqMergedWithBound;
3185       TColStd_SequenceOfBoolean seqMergedWithBoundOri;
3186       if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3187         // Store bound in the map
3188         MergedWithBound.Add(bound,bound);
3189         // Iterate on edges merged with bound
3190         Standard_Integer ii = 1;
3191         while (ii <= seqMergedWithBound.Length()) {
3192           TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3193           // Remove edge if recorded as merged
3194           Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || 
3195                                          MergedWithBound.Contains(iedge));
3196           if (!isRejected) {
3197             if (myBoundSections.IsBound(iedge)) {
3198               // Edge is splitted - check sections
3199               TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3200               for (; lit.More() && !isRejected; lit.Next()) {
3201                 const TopoDS_Shape& sec = lit.Value();
3202                 // Remove edge (bound) if at least one of its sections already merged
3203                 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.Contains(sec));
3204               }
3205             }
3206             if (!isRejected) {
3207               if (mySectionBound.IsBound(iedge)) {
3208                 // Edge is a section - check bound
3209                 const TopoDS_Shape& bnd = mySectionBound(iedge);
3210                 // Remove edge (section) if its bound already merged
3211                 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.Contains(bnd));
3212               }
3213             }
3214           }
3215           // To the next merged edge
3216           if (isRejected) {
3217             // Remove rejected edge
3218             seqMergedWithBound.Remove(ii);
3219             seqMergedWithBoundOri.Remove(ii);
3220           }
3221           else {
3222             // Process accepted edge
3223             MergedWithBound.Add(iedge,iedge);
3224             ii++;
3225           }
3226         }
3227         Standard_Integer nbMerged = seqMergedWithBound.Length();
3228         if (nbMerged) {
3229           // Create same parameter edge
3230           TopTools_MapOfShape ActuallyMerged;
3231           TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3232             seqMergedWithBoundOri,
3233             ActuallyMerged,myReShape);
3234           Standard_Boolean isForward = Standard_False;
3235           if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3236           // Process actually merged edges
3237           Standard_Integer nbActuallyMerged = 0;
3238           for (ii = 1; ii <= nbMerged; ii++) {
3239             const TopoDS_Shape& iedge = seqMergedWithBound(ii);
3240             if (ActuallyMerged.Contains(iedge)) {
3241               nbActuallyMerged++;
3242               // Record merged edge in the map
3243               TopAbs_Orientation orient = iedge.Orientation();
3244               if (!isForward) orient = TopAbs::Reverse(orient);
3245               if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3246               MergedWithBound.ChangeFromKey(iedge) = MergedEdge.Oriented(orient);
3247             }
3248             else
3249               MergedWithBound.RemoveKey(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.ChangeFromKey(bound) = MergedEdge.Oriented(orient);
3256           }
3257           nbMerged = nbActuallyMerged;
3258         }
3259         // Remove bound from the map if not finally merged
3260         if (!nbMerged)
3261           MergedWithBound.RemoveKey(bound);
3262       }
3263     }
3264     const Standard_Boolean isMerged = !MergedWithBound.IsEmpty();
3265
3266     // Merge with cutting sections
3267     Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3268     TopTools_IndexedDataMapOfShapeShape MergedWithSections;
3269     if (hasCuttingSections) {
3270       // Iterate on cutting sections
3271       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3272       for (; its.More(); its.Next()) {
3273         // Retrieve cutting section
3274         TopoDS_Shape section = its.Value();
3275         // Skip section if already merged
3276         if (myMergedEdges.Contains(section)) continue;
3277         // Merge cutting section
3278         TopTools_SequenceOfShape seqMergedWithSection;
3279         TColStd_SequenceOfBoolean seqMergedWithSectionOri;
3280         if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3281           // Store section in the map
3282           MergedWithSections.Add(section,section);
3283           // Iterate on edges merged with section
3284           Standard_Integer ii = 1;
3285           while (ii <= seqMergedWithSection.Length()) {
3286             TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3287             // Remove edge if recorded as merged
3288             Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3289                                            MergedWithSections.Contains(iedge));
3290             if (!isRejected) {
3291               if (myBoundSections.IsBound(iedge)) {
3292                 // Edge is splitted - check sections
3293                 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3294                 for (; lit.More() && !isRejected; lit.Next()) {
3295                   const TopoDS_Shape& sec = lit.Value();
3296                   // Remove edge (bound) if at least one of its sections already merged
3297                   isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.Contains(sec));
3298                 }
3299               }
3300               if (!isRejected) {
3301                 if (mySectionBound.IsBound(iedge)) {
3302                   // Edge is a section - check bound
3303                   const TopoDS_Shape& bnd = mySectionBound(iedge);
3304                   // Remove edge (section) if its bound already merged
3305                   isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.Contains(bnd));
3306                 }
3307               }
3308             }
3309             // To the next merged edge
3310             if (isRejected) {
3311               // Remove rejected edge
3312               seqMergedWithSection.Remove(ii);
3313               seqMergedWithSectionOri.Remove(ii);
3314             }
3315             else {
3316               // Process accepted edge
3317               MergedWithSections.Add(iedge, iedge);
3318               ii++;
3319             }
3320           }
3321           Standard_Integer nbMerged = seqMergedWithSection.Length();
3322           if (nbMerged) {
3323             // Create same parameter edge
3324             TopTools_MapOfShape ActuallyMerged;
3325             TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3326               seqMergedWithSectionOri,
3327               ActuallyMerged,SectionsReShape);
3328             Standard_Boolean isForward = Standard_False;
3329             if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3330             // Process actually merged edges
3331             Standard_Integer nbActuallyMerged = 0;
3332             for (ii = 1; ii <= nbMerged; ii++) {
3333               const TopoDS_Shape& iedge = seqMergedWithSection(ii);
3334               if (ActuallyMerged.Contains(iedge)) {
3335                 nbActuallyMerged++;
3336                 // Record merged edge in the map
3337                 TopAbs_Orientation orient = iedge.Orientation();
3338                 if (!isForward) orient = TopAbs::Reverse(orient);
3339                 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3340                 const TopoDS_Shape& oedge = MergedEdge.Oriented(orient);
3341                 MergedWithSections.ChangeFromKey(iedge) = oedge;
3342                 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3343               }
3344               else
3345                 MergedWithSections.RemoveKey(iedge);
3346             }
3347             if (nbActuallyMerged) {
3348               // Record merged section in the map
3349               TopAbs_Orientation orient = section.Orientation();
3350               if (!isForward) orient = TopAbs::Reverse(orient);
3351               const TopoDS_Shape& oedge = MergedEdge.Oriented(orient);
3352               MergedWithSections.ChangeFromKey(section) = oedge;
3353               ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3354             }
3355             nbMerged = nbActuallyMerged;
3356           }
3357    &