0022747: Progress indicator in sewing algorithm
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_Sewing.cxx
1 // File:        BRepBuilderAPI_Sewing.cxx
2 // Created:        Fri Mar 24 09:45:44 1995
3 // Author:        Jing Cheng MEI
4 //                <mei@junon>
5 // dcl          CCI60011 : Correction of degeneratedSection
6 //              Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
7 // dcl          Thu Aug 20 09:24:49 1998
8 //              Suppression of little faces.
9 // dcl          Fri Aug  7 15:27:46 1998
10 //                Refection of function SameParameter Edge.
11 //              Merge on the edge which has the less of poles.
12 //              Suppression of the Connected Edge function.
13 // dcl          Tue Jun  9 14:21:53 1998
14 //              Do not merge edge if they belong the same face
15 //              Tolerance management in VerticesAssembling
16 //              Tolerance management in Cutting
17 // dcl          Thu May 14 15:51:46 1998
18 //              optimization of cutting
19 // dcl          Thu May 7  15:51:46 1998
20 //              Add of cutting option
21 //              Add of SameParameter call
22
23
24 //-- lbr April 1 97
25 //-- dpf December 10 1997 Processing of pcurve collections
26
27 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode 
28 //rln 02.02.99 BUC60449 Protection against exception on NT
29
30 #define TEST 1
31
32 #include <BRepBuilderAPI_Sewing.ixx>
33
34 #include <Bnd_Box.hxx>
35 #include <Bnd_Box2d.hxx>
36 #include <Bnd_HArray1OfBox.hxx>
37 #include <BndLib_Add2dCurve.hxx>
38 #include <BndLib_Add3dCurve.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRep_Tool.hxx>
41 #include <BRepLib.hxx>
42 #include <BRepTools_Quilt.hxx>
43 #include <BSplCLib.hxx>
44 #include <Extrema_ExtPC.hxx>
45 #include <GCPnts_AbscissaPoint.hxx>
46 #include <GCPnts_UniformAbscissa.hxx>
47 #include <GCPnts_UniformDeflection.hxx>
48 #include <Geom2d_BezierCurve.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_Curve.hxx>
51 #include <Geom2d_Line.hxx>
52 #include <Geom2d_TrimmedCurve.hxx>
53 #include <Geom2dAdaptor_Curve.hxx>
54 #include <Geom2dConvert.hxx>
55 #include <Geom_BezierCurve.hxx>
56 #include <Geom_BSplineCurve.hxx>
57 #include <Geom_Curve.hxx>
58 #include <Geom_Line.hxx>
59 #include <Geom_Surface.hxx>
60 #include <GeomAdaptor_Curve.hxx>
61 #include <GeomAdaptor_Surface.hxx>
62 #include <GeomLib.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Vec.hxx>
65 //#include <LocalAnalysis_SurfaceContinuity.hxx>
66 #include <Precision.hxx>
67 #include <Standard_ErrorHandler.hxx>
68 #include <Standard_Failure.hxx>
69 #include <TColgp_Array1OfVec.hxx>
70 #include <TColgp_SequenceOfPnt.hxx>
71 #include <TColStd_Array1OfInteger.hxx>
72 #include <TColStd_Array1OfReal.hxx>
73 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
74 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
75 #include <TColStd_IndexedMapOfInteger.hxx>
76 #include <TColStd_ListIteratorOfListOfInteger.hxx>
77 #include <TColStd_ListOfInteger.hxx>
78 #include <TColStd_MapOfInteger.hxx>
79 #include <TColStd_SequenceOfReal.hxx>
80 #include <TopAbs.hxx>
81 #include <TopExp.hxx>
82 #include <TopExp_Explorer.hxx>
83 #include <TopLoc_Location.hxx>
84 #include <TopoDS.hxx>
85 #include <TopoDS_Edge.hxx>
86 #include <TopoDS_Iterator.hxx>
87 #include <TopoDS_Shape.hxx>
88 #include <TopoDS_Vertex.hxx>
89 #include <TopoDS_Wire.hxx>
90 #include <TopoDS_Shell.hxx>
91 #include <TopTools_Array1OfShape.hxx>
92 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
93 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
94 #include <TopTools_DataMapOfShapeInteger.hxx>
95 #include <TopTools_DataMapOfShapeListOfShape.hxx>
96 #include <TopTools_ListIteratorOfListOfShape.hxx>
97 #include <TopTools_ListOfShape.hxx>
98 #include <TopTools_MapIteratorOfMapOfShape.hxx>
99 #include <TopTools_MapOfShape.hxx>
100 #include <TopTools_SequenceOfShape.hxx>
101 #include <TopoDS_Compound.hxx>
102 #include <TColStd_Array2OfReal.hxx>
103 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
104 #include <BRepTools.hxx>
105 #include <Geom_RectangularTrimmedSurface.hxx>
106 #include <Geom_OffsetSurface.hxx>
107 #include <BRep_PointOnCurve.hxx>
108 #include <BRep_ListOfPointRepresentation.hxx>
109 #include <BRep_TVertex.hxx>
110 #include <Message_ProgressSentry.hxx>
111
112 static void SortBox (const Handle(Bnd_HArray1OfBox) hSetBoxes,
113                      const Bnd_Box& aBox,
114                      TColStd_ListOfInteger& listIndex)
115 {
116   Standard_Integer i, nbBoxes = hSetBoxes->Length();
117   for (i = 1; i <= nbBoxes; i++)
118     if (!aBox.IsOut(hSetBoxes->Value(i)))
119       listIndex.Append(i);
120 }
121
122 //=======================================================================
123 //function : SameRange
124 //purpose  : 
125 //=======================================================================
126
127 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
128                                                 const Standard_Real FirstOnCurve,
129                                                 const Standard_Real LastOnCurve,
130                                                 const Standard_Real RequestedFirst,
131                                                 const Standard_Real RequestedLast) const
132 {
133   Handle(Geom2d_Curve) NewCurvePtr;
134   try {
135     
136     GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
137                        RequestedFirst,RequestedLast,NewCurvePtr);
138   }
139   catch (Standard_Failure) {
140 #ifdef DEB
141     cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
142     Standard_Failure::Caught()->Print(cout); cout << endl;
143 #endif
144   }
145   return NewCurvePtr;
146 }
147
148 //=======================================================================
149 //function : WhichFace
150 //purpose  : Give the face whose edge is the border
151 //=======================================================================
152
153 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
154 {
155   TopoDS_Shape bound = theEdg;
156   if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
157   if (myBoundFaces.Contains(bound)) {
158     Standard_Integer i = 1;
159     TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
160     for (; itf.More(); itf.Next(), i++)
161       if (i == index) return TopoDS::Face(itf.Value());
162   }
163   return TopoDS_Face();
164 }
165
166 //=======================================================================
167 //function : IsClosedShape
168 //purpose  : 
169 //=======================================================================
170
171 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
172                                       const TopoDS_Shape& v1, const TopoDS_Shape& v2)
173 {
174   Standard_Real TotLength = 0.0;
175   TopExp_Explorer aexp;
176   for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
177     TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
178     if (aedge.IsNull()) continue;
179     TopoDS_Vertex ve1,ve2;
180     TopExp::Vertices(aedge,ve1,ve2);
181     if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
182     if (BRep_Tool::Degenerated(aedge)) continue;
183     Standard_Real first,last;
184     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
185     if (!c3d.IsNull()) {
186       GeomAdaptor_Curve cAdapt(c3d);
187       Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
188       TotLength += length;
189       if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
190     }
191   }
192   if (TotLength > 0.0) {
193     gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
194     gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
195     return (p1.Distance(p2) < TotLength/(1.2 * PI));
196   }
197   return Standard_False;
198 }
199
200 //=======================================================================
201 //function : IsClosedByIsos
202 //purpose  : 
203 //=======================================================================
204 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
205                                        const Handle(Geom2d_Curve)& acrv2d,
206                                        const Standard_Real f2d,
207                                        const  Standard_Real l2d,
208                                        const Standard_Boolean isUIsos) 
209 {
210   Standard_Boolean isClosed = Standard_False;
211  
212   gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ? 
213                      acrv2d->Value(f2d) :  acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
214   gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ? 
215                      acrv2d->Value(l2d) :  acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
216   Handle(Geom_Curve) aCrv1;
217   Handle(Geom_Curve) aCrv2;
218   if(isUIsos) {
219     aCrv1 = thesurf->UIso(psurf1.X());
220     aCrv2 = thesurf->UIso(psurf2.X());
221   }
222   else {
223     aCrv1 = thesurf->VIso(psurf1.Y());
224     aCrv2 = thesurf->VIso(psurf2.Y());
225   }
226   gp_Pnt p11,p1m,p12,p21,p2m,p22;
227   Standard_Real af1 = aCrv1->FirstParameter();
228   Standard_Real al1 = aCrv1->LastParameter();
229   Standard_Real af2 = aCrv2->FirstParameter();
230   Standard_Real al2 = aCrv2->LastParameter();
231   aCrv1->D0(af1,p11);
232   aCrv1->D0((af1+al1)*0.5,p1m);
233   aCrv1->D0(al1,p12);
234   aCrv2->D0(af2,p21);
235   aCrv2->D0((af2+al2)*0.5,p2m);
236   aCrv2->D0(al2,p22);
237   isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() < 
238                (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
239               ((p21.XYZ() - p22.XYZ()).Modulus() < 
240                (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
241   return isClosed;
242 }
243 //=======================================================================
244 //function : IsUClosedSurface
245 //purpose  : 
246 //=======================================================================
247
248 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
249                                                    const TopoDS_Shape& theEdge,
250                                                    const TopLoc_Location& theloc) const
251 {
252   Handle(Geom_Surface) tmpsurf = surf;
253   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
254     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
255   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
256     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
257   else {
258     Standard_Boolean isClosed = tmpsurf->IsUClosed();
259     if(!isClosed) {
260       Standard_Real f2d, l2d;
261       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
262       if(!acrv2d.IsNull())
263         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
264       
265     }
266     return isClosed;
267   }
268   return IsUClosedSurface(tmpsurf,theEdge,theloc);
269   //return surf->IsUClosed();
270 }
271
272 //=======================================================================
273 //function : IsVClosedSurface
274 //purpose  : 
275 //=======================================================================
276
277 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
278                                                    const TopoDS_Shape& theEdge,
279                                                    const TopLoc_Location& theloc) const
280 {
281   Handle(Geom_Surface) tmpsurf = surf;
282   if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
283     tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
284   else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) 
285     tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
286   else {
287     Standard_Boolean isClosed = tmpsurf->IsVClosed();
288     if(!isClosed) {
289       Standard_Real f2d, l2d;
290       Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
291       if(!acrv2d.IsNull())
292         isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
293     }
294     return isClosed;
295   }
296   return IsVClosedSurface(tmpsurf,theEdge,theloc);
297   //return surf->IsVClosed();
298 }
299
300 //=======================================================================
301 //function : SameParameter
302 //purpose  : internal use
303 //=======================================================================
304
305 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
306 {
307   try {
308     
309     BRepLib::SameParameter(edge);
310   }
311   catch (Standard_Failure) {
312 #ifdef DEB
313     cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
314     Standard_Failure::Caught()->Print(cout); cout << endl;
315 #endif
316   }
317 }
318
319 //=======================================================================
320 //function : SameParameterEdge
321 //purpose  : internal use
322 //           Merge the Sequence Of Section on one edge.
323 //           This function keep the curve3d,curve2d,range and parametrization
324 //           from the first section, and report and made sameparameter the
325 //           pcurves of the other function.
326 //           This function works when the are not more than two Pcurves
327 //           on a same face.
328 //=======================================================================
329
330 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
331                                                const TopTools_SequenceOfShape& seqEdges,
332                                                const TColStd_SequenceOfInteger& seqForward,
333                                                TopTools_MapOfShape& mapMerged,
334                                                const Handle(BRepTools_ReShape)& locReShape)
335 {
336   // Retrieve reference section
337   TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
338   TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
339   aTmpShape = locReShape->Apply(Edge1);
340   if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
341   Standard_Boolean isDone = Standard_False;
342
343   // Create data structures for temporary merged edges
344   TopTools_ListOfShape listFaces1;
345   TopTools_MapOfShape MergedFaces;
346
347   if (mySewing) {
348
349     // Fill MergedFaces with faces of Edge1
350     TopoDS_Shape bnd1 = edge;
351     if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
352     if (myBoundFaces.Contains(bnd1)) {
353       TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
354       for (; itf.More(); itf.Next())
355         if (MergedFaces.Add(itf.Value()))
356           listFaces1.Append(itf.Value());
357     }
358   }
359   else {
360
361     // Create presentation edge
362     TopoDS_Vertex V1, V2;
363     TopExp::Vertices(Edge1,V1,V2);
364     if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
365     if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
366
367     TopoDS_Edge NewEdge = Edge1;
368     NewEdge.EmptyCopy();
369
370     // Add the vertices
371     BRep_Builder aBuilder;
372     TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
373     aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
374     aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
375
376     Edge1 = NewEdge;
377   }
378
379   Standard_Boolean isForward = Standard_True;
380
381   // Merge candidate sections
382   for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
383
384     // Retrieve candidate section
385     TopoDS_Shape oedge2 = seqEdges(i);
386
387     if (mySewing) {
388
389       aTmpShape = myReShape->Apply(oedge2); //for porting
390       TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
391       aTmpShape = locReShape->Apply(Edge2);
392       if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
393
394       // Calculate relative orientation
395       Standard_Integer Orientation = seqForward(i);
396       if (!isForward) Orientation = (Orientation? 0 : 1);
397
398       // Retrieve faces information for the second edge
399       TopoDS_Shape bnd2 = oedge2;
400       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
401       if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
402       const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
403
404       Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
405       TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
406       if (NewEdge.IsNull()) continue;
407
408       // Record faces information for the temporary merged edge
409       TopTools_ListIteratorOfListOfShape itf(listFaces2);
410       for (; itf.More(); itf.Next())
411         if (MergedFaces.Add(itf.Value()))
412           listFaces1.Append(itf.Value());
413
414       // Record merged section orientation
415       if (!Orientation && whichSec != 1)
416         isForward = isForward? Standard_False : Standard_True;
417       Edge1 = NewEdge;
418     }
419
420     // Append actually merged edge
421     mapMerged.Add(oedge2);
422     isDone = Standard_True;
423
424     if (!myNonmanifold) break;
425   }
426
427   if (isDone) {
428     // Change result orientation
429     Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
430   }
431   else Edge1.Nullify();
432
433   return Edge1;
434 }
435
436 //=======================================================================
437 //function : SameParameterEdge
438 //purpose  : internal use
439 //=======================================================================
440 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
441                                        TopTools_SequenceOfShape& theSeqNMVert,
442                                        TColStd_SequenceOfReal& theSeqPars)
443 {
444   TopoDS_Iterator aItV(theEdge,Standard_False);
445   for( ; aItV.More(); aItV.Next()) {
446     if(aItV.Value().Orientation() == TopAbs_INTERNAL || 
447         aItV.Value().Orientation() == TopAbs_EXTERNAL)
448     theSeqNMVert.Append(aItV.Value());
449   }
450   Standard_Integer nbV = theSeqNMVert.Length();
451   if(!nbV)
452     return Standard_False;
453   Standard_Real first, last;
454   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
455   GeomAdaptor_Curve GAC(c3d);
456   Extrema_ExtPC locProj;
457   locProj.Initialize(GAC, first, last);
458   gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
459
460   
461   for (Standard_Integer i = 1; i <= nbV; i++) {
462     TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
463     gp_Pnt pt = BRep_Tool::Pnt(aV);
464     
465     Standard_Real distF2 = pfirst.SquareDistance(pt);
466     Standard_Real distL2 = plast.SquareDistance(pt);
467     Standard_Real apar = (distF2 > distL2 ? last : first);
468     // Project current point on curve
469     locProj.Perform(pt);
470     if (locProj.IsDone() && locProj.NbExt() > 0) {
471           Standard_Real dist2Min = Min(distF2,distL2);
472           Standard_Integer ind, indMin = 0;
473           for (ind = 1; ind <= locProj.NbExt(); ind++) {
474             Standard_Real dProj2 = locProj.SquareDistance(ind);
475             if (dProj2 < dist2Min) { 
476           indMin = ind; dist2Min = dProj2; 
477         }
478       }
479       if(indMin) 
480         apar = locProj.Point(indMin).Parameter();
481          
482       theSeqPars.Append(apar);  
483         
484     }
485   }
486   return Standard_True;
487 }
488
489 static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
490 {
491   return (dist * 0.5 + Tol1 + Tol2);
492 }
493
494 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
495                                                const TopoDS_Edge& edgeLast,
496                                                const TopTools_ListOfShape& listFacesFirst,
497                                                const TopTools_ListOfShape& listFacesLast,
498                                                const Standard_Boolean secForward, 
499                                                Standard_Integer& whichSec,
500                                                const Standard_Boolean firstCall)
501 {
502   // Do not process floating edges
503   if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
504
505   // Sort input edges
506   TopoDS_Edge edge1, edge2;
507   if (firstCall) {
508     // Take the longest edge as first
509     Standard_Real f, l;
510     Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
511     GeomAdaptor_Curve cAdapt1(c3d1);
512     Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
513     Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
514     GeomAdaptor_Curve cAdapt2(c3d2);
515     Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
516     if (len1 < len2) {
517       edge1 = edgeLast;
518       edge2 = edgeFirst;
519       whichSec = 2;
520     }
521     else {
522       edge1 = edgeFirst;
523       edge2 = edgeLast;
524       whichSec = 1;
525     }
526   }
527   else {
528     if (whichSec == 1) {
529       edge1 = edgeLast;
530       edge2 = edgeFirst;
531       whichSec = 2;
532     }
533     else {
534       edge1 = edgeFirst;
535       edge2 = edgeLast;
536       whichSec = 1;
537     }
538   }
539
540   Standard_Real first, last;
541   BRep_Tool::Range(edge1, first, last);
542   BRep_Builder aBuilder;
543
544   //To keep NM vertices on edge
545   TopTools_SequenceOfShape aSeqNMVert;
546   TColStd_SequenceOfReal aSeqNMPars;
547   findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
548   findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
549
550   // Create new edge
551   TopoDS_Edge edge;
552   aBuilder.MakeEdge(edge);
553   edge.Orientation( edge1.Orientation());
554  
555
556   // Retrieve edge curve
557   TopLoc_Location loc3d;
558   Standard_Real first3d, last3d;
559   Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
560   if (!loc3d.IsIdentity()) {
561     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
562     c3d->Transform(loc3d.Transformation());
563   }
564   aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
565   aBuilder.Range(edge, first, last);
566   aBuilder.SameRange(edge, Standard_False); //Standard_True
567   aBuilder.SameParameter(edge, Standard_False);
568   // Create and add new vertices
569   {
570     TopoDS_Vertex V1New, V2New;
571
572     // Retrieve original vertices from edges
573     TopoDS_Vertex V11,V12,V21,V22;
574     TopExp::Vertices(edge1,V11,V12);
575     TopExp::Vertices(edge2,V21,V22);
576
577     // Check that edges are merged correctly (for edges having length less than specified tolerance)
578     if(secForward)
579     {
580       if( V11.IsSame(V22) || V12.IsSame(V21) )
581         return TopoDS_Edge();
582     }
583     else
584     {
585       if( V11.IsSame(V21) || V12.IsSame(V22) )
586         return TopoDS_Edge();
587     }
588
589     //szv: do not reshape here!!!
590     //V11 = TopoDS::Vertex(myReShape->Apply(V11));
591     //V12 = TopoDS::Vertex(myReShape->Apply(V12));
592     //V21 = TopoDS::Vertex(myReShape->Apply(V21));
593     //V22 = TopoDS::Vertex(myReShape->Apply(V22));
594
595     gp_Pnt p11 = BRep_Tool::Pnt(V11);
596     gp_Pnt p12 = BRep_Tool::Pnt(V12);
597     gp_Pnt p21 = BRep_Tool::Pnt(V21); 
598     gp_Pnt p22 = BRep_Tool::Pnt(V22);
599
600     // Check if edges are closed
601     Standard_Boolean isClosed1 = V11.IsSame(V12);
602     Standard_Boolean isClosed2 = V21.IsSame(V22);
603
604     //Standard_Boolean isRev = Standard_False;
605     gp_Pnt pfirst;
606     Standard_Real Tol1 = 0.;
607     if (isClosed1 || isClosed2) {
608       // at least one of the edges is closed
609       if (isClosed1 && isClosed2) {
610         // both edges are closed
611         pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
612         gp_Vec v1 =  p21.XYZ() - p11.XYZ();
613         Standard_Real d1 = v1.Magnitude();
614         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
615         //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
616       }
617       else if (isClosed1) {
618         // only first edge is closed
619         gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
620             pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
621         gp_Vec v1 =  p22.XYZ() - p21.XYZ();
622         Standard_Real d1 = v1.Magnitude();
623         Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
624         gp_Vec v2 =  p11.XYZ() - pt;
625         Standard_Real d2 = v2.Magnitude();
626         Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
627         //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
628         //Tol1 = Max(pfirst.Distance(p11),Tol1);
629       }
630       else {
631         // only second edge is closed
632         gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
633             pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
634         gp_Vec v1 =  p11.XYZ() - p12.XYZ();
635         Standard_Real d1 = v1.Magnitude();
636         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
637         gp_Vec v2 =  p21.XYZ() - pt;
638         Standard_Real d2 = v2.Magnitude();
639         Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
640         //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
641         //Tol1 = Max(pfirst.Distance(p21),Tol1);
642       }
643       aBuilder.MakeVertex(V1New,pfirst,Tol1);
644       V2New = V1New;
645     }
646     else {
647       // both edges are open
648       gp_Pnt plast;
649       Standard_Real Tol2 = 0.;
650       if (secForward) {
651             pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
652             plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
653         gp_Vec v1 =  p21.XYZ() - p11.XYZ();
654         Standard_Real d1 = v1.Magnitude();
655         gp_Vec v2 =  p22.XYZ() - p12.XYZ();
656         Standard_Real d2 = v2.Magnitude();
657         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
658         Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
659
660 //      Tol1 = Max(Max(pfirst.Distance(p11),pfirst.Distance(p21)),
661 //                 Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21)));
662 //      Tol2 = Max(Max(plast.Distance(p12),plast.Distance(p22)),
663 //                 Max(BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22)));
664       }
665       else {
666             pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
667             plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
668         
669         gp_Vec v1 =  p22.XYZ() - p11.XYZ();
670         Standard_Real d1 = v1.Magnitude();
671         gp_Vec v2 =  p21.XYZ() - p12.XYZ();
672         Standard_Real d2 = v2.Magnitude();
673         Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
674         Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
675 //        Tol1 = Max(Max(pfirst.Distance(p11),pfirst.Distance(p22)),
676 //                 Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22)));
677 //      Tol2 = Max(Max(plast.Distance(p12),plast.Distance(p21)),
678 //                 Max(BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21)));
679       }
680       //gp_Pnt pcu;
681       ///c3d->D0(first3d,pcu);
682       //Tol1 = Max(pfirst.Distance(pcu) + Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
683       aBuilder.MakeVertex(V1New,pfirst,Tol1);
684       //c3d->D0(last3d,pcu);
685       //Tol2 = plast.Distance(pcu);
686       aBuilder.MakeVertex(V2New,plast,Tol2);
687     }
688
689     // Add the vertices in the good sense
690     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
691     TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
692     aBuilder.Add(anEdge,aLocalEdge);
693     aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
694     aBuilder.Add(anEdge,aLocalEdge);
695
696     Standard_Integer k =1;
697     for( ; k <= aSeqNMVert.Length(); k++)
698       aBuilder.Add(anEdge,aSeqNMVert.Value(k));
699
700   }
701
702   // Retrieve second PCurves
703   TopLoc_Location loc2;
704   Handle(Geom_Surface) surf2;
705   //Handle(Geom2d_Curve) c2d2, c2d21;
706   //  Standard_Real firstOld, lastOld;
707
708   TopTools_ListIteratorOfListOfShape itf2;
709   if (whichSec == 1) itf2.Initialize(listFacesLast);
710   else               itf2.Initialize(listFacesFirst);
711   Standard_Boolean isResEdge = Standard_False;
712   for (; itf2.More(); itf2.Next()) {
713     Handle(Geom2d_Curve) c2d2, c2d21;
714     Standard_Real firstOld, lastOld;
715     const TopoDS_Face& fac2 = TopoDS::Face(itf2.Value());
716
717     surf2 = BRep_Tool::Surface(fac2, loc2);
718     Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
719                                 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
720     if (isSeam2) {
721       if (!myNonmanifold) return TopoDS_Edge();
722       TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
723       c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
724     }
725     c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
726     if (c2d2.IsNull() && c2d21.IsNull()) continue;
727
728     if (!c2d21.IsNull()) {
729       c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
730       if (!secForward) {
731         if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
732           c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
733         Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
734         Standard_Real last2d = lastOld;   //c2dTmp->LastParameter();
735         firstOld = c2d21->ReversedParameter(last2d);
736         lastOld = c2d21->ReversedParameter(first2d);
737         c2d21->Reverse();
738       }
739       c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
740     }
741
742     // Make second PCurve sameRange with the 3d curve
743     c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
744
745     if (!secForward) {
746       if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
747         c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
748       Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
749       Standard_Real last2d = lastOld;   //c2dTmp->LastParameter();
750       firstOld = c2d2->ReversedParameter(last2d);
751       lastOld = c2d2->ReversedParameter(first2d);
752       c2d2->Reverse();
753     }
754
755     c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
756     if (c2d2.IsNull()) continue;
757     
758     // Add second PCurve
759     Standard_Boolean isSeam = Standard_False;
760     TopAbs_Orientation Ori = TopAbs_FORWARD;
761     //Handle(Geom2d_Curve) c2d1, c2d11;
762
763     TopTools_ListIteratorOfListOfShape itf1;
764     if (whichSec == 1) itf1.Initialize(listFacesFirst);
765     else               itf1.Initialize(listFacesLast);
766     for (; itf1.More() && !isSeam; itf1.Next()) {
767       Handle(Geom2d_Curve) c2d1, c2d11;
768       const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
769
770       TopLoc_Location loc1;
771       Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
772       Standard_Real first2d, last2d;
773       Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
774                                   BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
775       c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
776       Ori = edge1.Orientation();
777       if (fac1.Orientation() == TopAbs_REVERSED) 
778         Ori = TopAbs::Reverse(Ori);
779       
780       if (isSeam1) {
781         if (!myNonmanifold) return TopoDS_Edge();
782         TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
783         c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
784         //if(fac1.Orientation() == TopAbs_REVERSED) //
785         if(Ori == TopAbs_FORWARD)
786           aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
787         else
788           aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
789       }
790       else  aBuilder.UpdateEdge(edge,c2d1,fac1,0);
791       
792       if (c2d1.IsNull() && c2d11.IsNull()) continue;
793
794       //Ori = edge1.Orientation();
795       //if (fac1.Orientation() == TopAbs_REVERSED) TopAbs::Reverse(Ori);
796
797       if (surf2 == surf1) {
798         // Merge sections which are on the same face
799         if (!loc2.IsDifferent(loc1)) {
800           Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
801           Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
802           if (uclosed || vclosed) {
803             Standard_Real pf = c2d1->FirstParameter();
804 //          Standard_Real pl = c2d1->LastParameter();
805             gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
806 //          gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
807             gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
808             gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
809             Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
810             Standard_Real U1, U2, V1, V2;
811             surf2->Bounds(U1, U2, V1, V2);
812             isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
813                       (vclosed && aDist > 0.75*(fabs(V2-V1))));
814             if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
815           }
816         }
817       }
818      
819       isResEdge = Standard_True;
820       if (isSeam) {
821         if (Ori == TopAbs_FORWARD)
822           aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
823         else
824           aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
825       }
826       else if (isSeam2) {
827         TopAbs_Orientation InitOri  = edge2.Orientation();
828          TopAbs_Orientation SecOri  = edge.Orientation();
829         if (fac2.Orientation() == TopAbs_REVERSED) {
830           
831           InitOri = TopAbs::Reverse(InitOri);
832           SecOri = TopAbs::Reverse(SecOri);
833         }
834         if(!secForward)
835           InitOri = TopAbs::Reverse(InitOri);
836         
837         if (InitOri == TopAbs_FORWARD)
838           aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
839         else
840           aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
841       } 
842       else {
843         aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
844       }
845       
846     }
847   }
848   if(isResEdge)
849   // Try to make the edge sameparameter
850     SameParameter(edge);
851
852   //  Standard_Real tolReached = BRep_Tool::Tolerance(edge);
853   //if (!BRep_Tool::SameParameter(edge)) return edge; //gka ????????
854
855   if (firstCall && (!BRep_Tool::SameParameter(edge) || !isResEdge)) {
856     Standard_Integer whichSecn = whichSec;
857     // Try to merge on the second section
858     Standard_Boolean second_ok = Standard_True;
859     TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
860                                            secForward,whichSecn,Standard_False);
861     //if (s_edge.IsNull()) return s_edge; // gka version for free edges
862     if (s_edge.IsNull()) second_ok = Standard_False;
863     else if (!BRep_Tool::SameParameter(s_edge)) second_ok = Standard_False;
864     else {
865       edge = s_edge;
866       whichSec = whichSecn;
867     }
868
869     if (!second_ok) {
870
871       GeomAdaptor_Curve c3dAdapt(c3d);
872
873       // Discretize edge curve
874       Standard_Integer i, j, nbp = 15;
875       Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
876       TColgp_Array1OfPnt c3dpnt(1,nbp);
877       for (i = 1; i <= nbp; i++) c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
878
879       Standard_Real u, v, dist, maxTol = -1.0;
880       Standard_Boolean more = Standard_True;
881
882       for (j = 1; more; j++) {
883         Handle(Geom2d_Curve) c2d2;
884         BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
885         more = !c2d2.IsNull();
886         if (more) {
887
888           deltaT = (last - first) / (nbp + 1);
889           for (i = 1; i <= nbp; i++) {
890             c2d2->Value(first + i*deltaT).Coord(u,v);
891             dist = surf2->Value(u,v).Distance(c3dpnt(i));
892             if (dist > maxTol) maxTol = dist;
893           }
894         }
895       }
896
897       if (maxTol >= 0.) aBuilder.UpdateEdge(edge, maxTol);
898       aBuilder.SameParameter(edge,Standard_True);
899     }
900   }
901
902   BRepLib::EncodeRegularity(edge,0.01);
903   Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
904   if (tolEdge1 > MaxTolerance()) edge.Nullify();
905   return edge;
906 }
907
908 //=======================================================================
909 // function : EvaluateAngulars
910 // purpose  : internal use
911 //=======================================================================
912
913 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
914                                        TColStd_Array1OfBoolean& secForward,
915                                        TColStd_Array1OfReal& tabAng,
916                                        const Standard_Integer indRef) const
917 {
918   tabAng.Init(-1.0);
919
920   Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
921
922   TopoDS_Edge edge;
923   TopoDS_Face face;
924   TopLoc_Location loc;
925   Standard_Real first, last;
926   Handle(Geom_Curve) c3d;
927   Handle(Geom2d_Curve) c2d;
928   Handle(Geom_Surface) surf;
929   TColgp_Array1OfVec normRef(1,npt);
930
931   for (i = indRef; i <= lengSec; i++) {
932
933     edge = TopoDS::Edge(sequenceSec(i));
934
935     TopoDS_Shape bnd = edge;
936     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
937     if (myBoundFaces.Contains(bnd)) {
938       face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
939       surf = BRep_Tool::Surface(face,loc);
940       if (!loc.IsIdentity()) {
941         surf = Handle(Geom_Surface)::DownCast(surf->Copy());
942         surf->Transform(loc.Transformation());
943       }
944       c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
945     }
946     else if (i == indRef) return;
947     else continue;
948
949     c3d = BRep_Tool::Curve(edge, loc, first, last);
950     if (!loc.IsIdentity()) {
951       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
952       c3d->Transform(loc.Transformation());
953     }
954
955     GeomAdaptor_Curve adapt(c3d);
956     GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
957
958     Standard_Real cumulateAngular = 0.0;
959     Standard_Integer nbComputedAngle = 0;
960
961     for (j = 1; j <= npt; j++) {
962       gp_Pnt2d P;
963       c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
964       gp_Vec w1, w2;
965       gp_Pnt unused;
966       surf->D1(P.X(), P.Y(), unused, w1, w2);
967       gp_Vec n = w1^w2; // Compute the normal vector
968       if (i == indRef) normRef(j) = n;
969       else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
970         nbComputedAngle++;
971         Standard_Real angular = n.Angle(normRef(j));
972         if (angular > PI/2.) angular = PI - angular;
973         cumulateAngular += angular;
974       }
975     }
976
977     if (nbComputedAngle)
978       tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
979   }
980 }
981
982 //=======================================================================
983 // function : EvaluateDistances
984 // purpose  : internal use
985 // Evaluate distance beetween edges with indice indRef and the following edges in the list
986 // Remarks (lengSec - indRef) must be >= 1 
987 //=======================================================================
988 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
989                                               TColStd_Array1OfBoolean& secForward,
990                                               TColStd_Array1OfReal& tabDst,
991                                               TColStd_Array1OfReal& arrLen,
992                                               TColStd_Array1OfReal& tabMinDist,
993                                               const Standard_Integer indRef) const
994 {
995   secForward.Init(Standard_True);
996   tabDst.Init(-1.0);
997   arrLen.Init(0.);
998   tabMinDist.Init(Precision::Infinite());
999   const Standard_Integer npt = 8; // Number of points for curve discretization
1000   TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1001
1002   Standard_Integer i, j, lengSec = sequenceSec.Length();
1003   TColgp_SequenceOfPnt seqSec;
1004
1005   Handle(Geom_Curve) c3dRef;
1006   Standard_Real firstRef=0., lastRef=0.;
1007   Standard_Integer nbFound = 0;
1008   for (i = indRef; i <= lengSec; i++) {
1009
1010     // reading of the edge (attention for the first one: reference)
1011     const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1012
1013     TopLoc_Location loc;
1014     Standard_Real first, last;
1015     Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1016     if (!loc.IsIdentity()) {
1017       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1018       c3d->Transform(loc.Transformation());
1019     }
1020
1021     if (i == indRef) {
1022       c3dRef = c3d; firstRef = first; lastRef = last;
1023     }
1024
1025     Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1026     Standard_Real aMinDist = Precision::Infinite();
1027
1028     Standard_Real T, deltaT = (last - first) / (npt - 1);
1029     Standard_Real aLenSec2 = 0.;
1030     Standard_Boolean isFound = (indRef == i);
1031     for (j = 1; j <= npt; j++) {
1032
1033       // Uniform parameter on curve
1034       if (j == 1) T = first;
1035       else if (j == npt) T = last;
1036       else T = first + (j - 1) * deltaT;
1037
1038       // Take point on curve
1039       gp_Pnt pt = c3d->Value(T);
1040      
1041       if (i == indRef) {
1042         ptsRef(j) = pt;
1043         if(j > 1)
1044           aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1045       }
1046       else {
1047         ptsSec(j) = pt;
1048         //protection to avoid merging with small sections
1049         if(j > 1)
1050           aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1051         // To evaluate mutual orientation and distance
1052         dist = pt.Distance(ptsRef(j));
1053         if(aMinDist > dist)
1054           aMinDist = dist;
1055         if (distFor < dist) distFor = dist;
1056         dist = pt.Distance(ptsRef(npt-j+1));
1057    
1058         if(aMinDist > dist)
1059           aMinDist = dist;
1060         if (distRev < dist) distRev = dist;
1061
1062         // Check that point lays between vertices of reference curve
1063         const gp_Pnt &p11 = ptsRef(1);
1064         const gp_Pnt &p12 = ptsRef(npt);
1065         const gp_Vec aVec1(pt,p11);
1066         const gp_Vec aVec2(pt,p12);
1067         const gp_Vec aVecRef(p11,p12);
1068         if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1069           nbFound++;
1070       }
1071     }
1072
1073     Standard_Real aLenSec = sqrt(aLenSec2);
1074     
1075     //if(aLenSec < myMinTolerance )
1076      // continue;
1077     arrLen.SetValue(i,aLenSec);
1078     // Record mutual orientation
1079     Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1080     secForward(i) = isForward;
1081
1082     dist = (isForward? distFor : distRev);
1083     if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1084     {
1085       tabDst(i) = dist;
1086       tabMinDist(i) = aMinDist;
1087     }
1088     else
1089     {
1090       nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1091       TColgp_Array1OfPnt arrProj(1, npt);
1092       TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1093       if( arrLen(indRef) >= arrLen(i)) 
1094         ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1095       else
1096         ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1097       for( j = 1; j <= npt; j++ )
1098       {
1099         if(arrDist(j) < 0. || arrDist(j) > myTolerance)
1100           continue;
1101         if(dist < arrDist(j))
1102           dist = arrDist(j);
1103         if( aMinDist > arrDist(j))
1104           aMinDist = arrDist(j);
1105         nbFound++;
1106       }
1107       if(nbFound > 1)
1108       {
1109         tabDst(i) = dist;
1110         tabMinDist(i) =  aMinDist;
1111       }
1112     }
1113   }
1114
1115   /*
1116   // Project distant points
1117   Standard_Integer nbFailed = seqSec.Length();
1118   if (!nbFailed) return;
1119
1120   TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1121   for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1122   TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1123
1124   ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1125
1126   // Process distant sections
1127   Standard_Integer idx1 = 1;
1128   for (i = indRef + 1; i <= lengSec; i++) {
1129
1130     // Skip section if already evaluated
1131     if (tabDst(i) >= 0.0) continue;
1132
1133     Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1134
1135     Standard_Integer idx2 = (idx1 - 1)*npt;
1136
1137     for (j = 1; j <= npt; j++) {
1138
1139       dist = arrDist(idx2 + j);
1140       // If point is not projected - stop evaluation
1141       if (dist < 0.0) { distMax = -1.0; break; }
1142       if (distMax < dist) distMax = dist;
1143       if(aMinDist > dist) aMinDist = dist;
1144     }
1145
1146     // If section is close - record distance
1147     if (distMax >= 0.0) {
1148       if (secForward(i)) {
1149         dist = arrPnt(idx2+1).Distance(ptsRef(1));
1150         if (distMax < dist) distMax = dist;
1151         if(aMinDist > dist) aMinDist = dist;
1152         dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1153         if (distMax < dist) distMax = dist;
1154         if(aMinDist > dist) aMinDist = dist;
1155       }
1156       else {
1157         dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1158         if (distMax < dist) distMax = dist;
1159         if(aMinDist > dist) aMinDist = dist;
1160         dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1161         if (distMax < dist) distMax = dist;
1162         if(aMinDist > dist) aMinDist = dist;
1163       }
1164
1165       if (distMax < myTolerance) 
1166       {
1167         tabDst(i) = distMax;
1168         tabMinDist(i) = aMinDist;
1169       }
1170     }
1171
1172     idx1++; // To the next distant curve
1173   }*/
1174 }
1175
1176 //=======================================================================
1177 //function : IsMergedClosed
1178 //purpose  :  internal use
1179 //=======================================================================
1180
1181 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1182                                                  const TopoDS_Edge& Edge2,
1183                                                  const TopoDS_Face& face) const
1184 {
1185   // Check for closed surface
1186   TopLoc_Location loc;
1187   Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1188   Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1189   Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1190   if (!isUClosed && !isVClosed) return Standard_False;
1191   // Check condition on closed surface
1192   /*
1193   Standard_Real first1,last1,first2,last2;
1194   Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1195   Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1196   if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1197   */
1198   Standard_Real first2d1,last2d1,first2d2,last2d2;
1199   Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1200   Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1201   if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1202   /*
1203   gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1204   gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1205   Standard_Real dist = p1.Distance(p2);
1206   gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1207   gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1208   Standard_Real dist2d = p12d.Distance(p22d);
1209   GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1210   Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1211   return (dist2d*0.2 >= distSurf);
1212   */
1213   Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1214   Standard_Real SUmin, SUmax, SVmin, SVmax;
1215   Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1216   Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1217   { //szv: Use brackets to destroy local variables
1218     Bnd_Box2d B1, B2;
1219     Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1220     BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1221     BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1222     B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1223     B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1224     Standard_Real du, dv;
1225     du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1226     isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1227     du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1228     isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1229     surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1230   }
1231   if (isUClosed && isVLongC1 && isVLongC2) {
1232     // Do not merge if not overlapped by V
1233     Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1234     if (dist < 0.0) {
1235       Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1236       Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1237       if (distOuter <= distInner) return Standard_True;
1238     }
1239   }
1240   if (isVClosed && isULongC1 && isULongC2) {
1241     // Do not merge if not overlapped by U
1242     Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1243     if (dist < 0.0) {
1244       Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1245       Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1246       if (distOuter <= distInner) return Standard_True;
1247     }
1248   }
1249   return Standard_False;
1250 }
1251
1252 //=======================================================================
1253 //function : AnalysisNearestEdges
1254 //purpose  : 
1255 //=======================================================================
1256
1257 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1258                                                  TColStd_SequenceOfInteger& seqIndCandidate,
1259                                                  TColStd_SequenceOfInteger& seqOrientations,
1260                                                  const Standard_Boolean evalDist)
1261 {
1262
1263   Standard_Integer workIndex = seqIndCandidate.First();
1264   TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1265   TopoDS_Shape bnd = workedge;
1266   TopTools_ListOfShape workfaces;
1267   if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1268   if (myBoundFaces.Contains(bnd)) 
1269     workfaces = myBoundFaces.FindFromKey(bnd);
1270   if(workfaces.IsEmpty()) return;
1271   TopTools_MapOfShape mapFaces;
1272   TopTools_ListIteratorOfListOfShape lIt;
1273   for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1274     mapFaces.Add(lIt.Value());
1275   TColStd_SequenceOfInteger seqNotCandidate;
1276   TColStd_SequenceOfInteger seqNewForward;
1277   // Separates edges belonging the same face as work edge 
1278   // for exception of edges belonging closed faces 
1279
1280   seqNotCandidate.Append(workIndex);
1281   for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1282     Standard_Integer index = seqIndCandidate.Value(i);
1283     Standard_Boolean isRemove = Standard_False;
1284     if(index == workIndex) {
1285       seqIndCandidate.Remove(i);
1286       seqOrientations.Remove(i);
1287       isRemove = Standard_True;
1288     }
1289     if(!isRemove) {
1290       TopoDS_Shape bnd2 = sequenceSec.Value(index);
1291       if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1292
1293       if(myBoundFaces.Contains(bnd2)) {
1294         const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1295         Standard_Boolean isMerged = Standard_True;
1296         for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1297           if(mapFaces.Contains(lIt.Value())) {
1298             TopLoc_Location loc;
1299             Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1300             isMerged = ((IsUClosedSurface(surf,bnd2,loc) ||  IsVClosedSurface(surf,bnd2,loc)) && 
1301               IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1302           }
1303         }
1304         if(!isMerged) {
1305           seqNotCandidate.Append(index);
1306           seqIndCandidate.Remove(i);
1307           seqOrientations.Remove(i);
1308           isRemove = Standard_True;
1309         }
1310       }
1311       else {
1312         seqIndCandidate.Remove(i);
1313         seqOrientations.Remove(i);
1314         isRemove = Standard_True;
1315       }
1316     }
1317     if(!isRemove) i++;  
1318   }
1319   if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1320   if(!evalDist) return;
1321   TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1322   TColStd_MapOfInteger MapIndex;
1323   TColStd_SequenceOfInteger seqForward;
1324
1325   // Definition and removing edges wich are not candidate for work edge 
1326   // ( they have other nearest edges belonging to the work face) 
1327   for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1328     Standard_Integer index1 = seqNotCandidate.Value(k);
1329     TopoDS_Shape edge = sequenceSec.Value(index1);
1330     TopTools_SequenceOfShape tmpSeq;
1331     tmpSeq.Append(edge);
1332     for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++) 
1333       tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1334
1335     Standard_Integer lengSec = tmpSeq.Length();
1336     TColStd_Array1OfBoolean tabForward(1,lengSec);
1337     TColStd_Array1OfReal tabDist(1,lengSec);
1338     TColStd_Array1OfReal arrLen(1,lengSec);
1339     TColStd_Array1OfReal tabMinDist(1,lengSec);
1340     for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++) 
1341       tabDist(i1) =-1;
1342
1343     EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1344     if(k == 1) {
1345       for(Standard_Integer n = 1; n < lengSec; n++) {
1346         if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1347           MapIndex.Add(n);
1348           continue;
1349         }
1350         TotTabDist(k,n) = tabDist(n+1 );
1351         seqForward.Append(tabForward(n+1) ? 1:0);
1352       }
1353     }
1354     else {
1355       for(Standard_Integer n = 1; n < lengSec; n++) {
1356         if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1357         if(tabDist(n+1) < TotTabDist(1,n)) {
1358           MapIndex.Add(n);
1359         }
1360       }
1361     }
1362
1363   }
1364
1365   Standard_Integer i2 = seqIndCandidate.Length();
1366   for( ; i2 >=1 ; i2--)
1367   {
1368     if(MapIndex.Contains(i2))
1369     { 
1370       seqIndCandidate.Remove(i2);
1371       seqOrientations.Remove(i2);
1372     }
1373
1374   }
1375   //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1376   //  seqIndCandidate.Remove(IMap.Key());
1377   //  seqOrientations.Remove(IMap.Key());
1378   //}
1379 }
1380
1381 //=======================================================================
1382 //function : FindCandidates
1383 //purpose  : internal use
1384 //=======================================================================
1385
1386 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1387                                                        TColStd_IndexedMapOfInteger& mapReference,
1388                                                        TColStd_SequenceOfInteger& seqCandidates,
1389                                                        TColStd_SequenceOfInteger& seqOrientations)
1390 {
1391   Standard_Integer i, nbSections = seqSections.Length();
1392   if(nbSections <= 1)
1393     return Standard_False;
1394   // Retrieve last reference index
1395   Standard_Integer indReference = mapReference(mapReference.Extent());
1396   Standard_Integer nbCandidates = 0;
1397   TopTools_MapOfShape Faces1;
1398   //if (nbSections > 1) {
1399
1400   TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1401
1402   // Retrieve faces for reference section
1403
1404   { //szv: Use brackets to destroy local variables
1405     TopoDS_Shape bnd = Edge1;
1406     if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1407     if (myBoundFaces.Contains(bnd)) {
1408       TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1409       for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1410     }
1411   }
1412
1413   // Check merging conditions for candidates and remove unsatisfactory
1414   TopTools_SequenceOfShape seqSectionsNew;
1415   TColStd_SequenceOfInteger seqCandidatesNew;
1416   for (i = 1; i <= nbSections; i++) {
1417     if (i == indReference) {
1418       seqSectionsNew.Prepend(Edge1);
1419       seqCandidatesNew.Prepend(i);
1420     }
1421     else {
1422       const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1423       //gka
1424       seqSectionsNew.Append(Edge2);
1425       seqCandidatesNew.Append(i);
1426       /*TopoDS_Shape bnd = Edge2;
1427       if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1428       //gka
1429       if (myBoundFaces.Contains(bnd)) {
1430       Standard_Boolean isOK = Standard_True;
1431       TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1432       for (; itf2.More() && isOK; itf2.Next()) {
1433       const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1434       // Check whether condition is satisfied
1435       isOK = !Faces1.Contains(Face2);
1436       if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1437       }
1438       if (isOK) {
1439       seqSectionsNew.Append(Edge2);
1440       seqCandidatesNew.Append(i);
1441       }
1442       }*/
1443     }
1444   }
1445
1446   Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1447   if (nbSectionsNew > 1) {
1448
1449     // Evaluate distances between reference and other sections
1450     TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1451     TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1452     TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1453     TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1454     EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1455
1456     // Fill sequence of candidate indices sorted by distance
1457     for (i = 2; i <= nbSectionsNew; i++) {
1458       if (arrDistance(i) >= 0.0 && arrLen(i) > myMinTolerance) {
1459         // Reference section is connected to section #i
1460         Standard_Boolean isInserted = Standard_False;
1461         Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1462         for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1463           Standard_Integer aInd = seqCandidates.Value(j);//debug
1464           Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1465           //if (arrDistance(i) <= arrDistance(seqCandidates.Value(j))) {
1466           if( aDelta < Precision::Confusion()) {
1467
1468             if(fabs(aDelta) > RealSmall() || 
1469               arrMinDist(i) < arrMinDist(seqCandidates.Value(j))) 
1470             {
1471               seqCandidates.InsertBefore(j,i);
1472               seqOrientations.InsertBefore(j,ori);
1473               isInserted = Standard_True;
1474             }
1475           }
1476         }
1477         if (!isInserted) {
1478           seqCandidates.Append(i);
1479           seqOrientations.Append(ori);
1480         }
1481       }
1482     }
1483
1484     // Replace candidate indices
1485     nbCandidates = seqCandidates.Length();
1486     for (i = 1; i <= nbCandidates; i++)
1487       seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1488   }
1489   //}
1490
1491   if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1492
1493   if (myNonmanifold && nbCandidates >1) {
1494     TColStd_SequenceOfInteger seqNewCandidates;
1495     TColStd_SequenceOfInteger seqOrientationsNew;
1496     seqCandidates.Prepend(1);
1497     seqOrientations.Prepend(1);
1498     for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1499       AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1500       if(k == 1 && !seqCandidates.Length()) return Standard_False;
1501       if(seqCandidates.Length()) {
1502         seqNewCandidates.Append(seqCandidates.First());
1503         seqOrientationsNew.Append(seqOrientations.First()); 
1504       }
1505     }
1506     seqCandidates.Prepend(seqNewCandidates);
1507     seqOrientations.Prepend(seqOrientationsNew);
1508     return Standard_True;
1509   }
1510   else {
1511
1512     // For manifold case leave only one candidate from equidistant candidates
1513     /*Standard_Integer minIndex = seqCandidateIndex.First();
1514     Standard_Real minDistance = arrDistance(minIndex);
1515
1516     // Find equidistant candidates
1517     TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1518     for (i = 2; i <= nbCandidates; i++) {
1519     Standard_Integer index = seqCandidateIndex(i);
1520     if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1521     seqEqDistantIndex.Append(index);
1522     }
1523
1524     Standard_Integer eqLen = seqEqDistantIndex.Length();
1525     if (eqLen > 2) {
1526
1527     // Fill map of faces which equidistant sections belong to
1528     TopTools_MapOfShape mapFace;
1529     for (i = 1; i <= eqLen; i++) {
1530     Standard_Integer index = seqEqDistantIndex.Value(i);
1531     if (isCandidate(index)) {
1532     mapFace.Add(arrFace(index));
1533     }
1534     }
1535
1536     // Non Manifold case
1537     // Edges are merged by pair among a face continuity C1 criterion
1538     if (mapFace.Extent() == eqLen) {
1539
1540     tabDist.Init(-1);
1541     tabMinInd.Init(-1);
1542     min=10000000.;
1543     //indMin = -1;
1544     Standard_Integer indMin = -1;// To check if the edge can be merged.
1545     // Computation of distances between the edges.
1546     TopTools_SequenceOfShape seqSh;
1547     Standard_Integer nbInd = EqDistSeq.Length();
1548     TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1549     seqSh.Append(sequenceSec.Value(1));
1550     for (j = 2; j <= EqDistSeq.Length(); j++) {
1551     Standard_Integer index = EqDistSeq.Value(j);
1552     tmptabForward(j) = tabForward(index);
1553     seqSh.Append(sequenceSec.Value(index));
1554     }
1555
1556     EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1557
1558     for(j=2; j <= seqSh.Length(); j++) {
1559     if (tabDist(j) > -1.) {  // if edge(j) is connected to edge(i)
1560     if (min > tabDist(j)) {
1561     min = tabDist(j);
1562     indMin = j;
1563     }
1564     }
1565     }
1566
1567     //  Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1568     if (indMin > 0) {
1569     seqSh.Remove(indMin);
1570     for(j =2; j <= tmpSeq.Length(); ) {
1571     TopoDS_Shape sh = tmpSeq.Value(j);
1572     Standard_Boolean isRem = Standard_False;
1573     for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1574     if(seqSh.Value(k) == sh) {
1575     isRem = Standard_True;
1576     break;
1577     }
1578     }
1579     if(isRem) {
1580     tmpSeq.Remove(j);
1581     tabMinForward.Remove(j); // = -1;
1582     } 
1583     else j++;
1584     }
1585     }
1586     }
1587     }*/
1588
1589     // Find the best approved candidate
1590     while (nbCandidates) {
1591       // Retrieve first candidate
1592       Standard_Integer indCandidate = seqCandidates.First();
1593       // Candidate is approved if it is in the map
1594       if (mapReference.Contains(indCandidate)) break;
1595       // Find candidates for candidate #indCandidate
1596       mapReference.Add(indCandidate); // Push candidate in the map
1597       TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1598       Standard_Boolean isFound =
1599         FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1600       mapReference.RemoveLast(); // Pop candidate from the map
1601       if (isFound) isFound = (seqCandidates1.Length() > 0);
1602       if (isFound) {
1603         Standard_Integer indCandidate1 = seqCandidates1.First();
1604         // If indReference is the best candidate for indCandidate
1605         // then indCandidate is the best candidate for indReference
1606         if (indCandidate1 == indReference) break;
1607         // If some other reference in the map is the best candidate for indCandidate
1608         // then assume that reference is the best candidate for indReference
1609         if (mapReference.Contains(indCandidate1)) {
1610           seqCandidates.Prepend(indCandidate1);
1611           nbCandidates++;
1612           break;
1613         }
1614         isFound = Standard_False;
1615       }
1616       if (!isFound) {
1617         // Remove candidate #1
1618         seqCandidates.Remove(1);
1619         seqOrientations.Remove(1);
1620         nbCandidates--;
1621       }
1622     }
1623   }
1624   //gka
1625   if(nbCandidates > 0)
1626   {
1627     Standard_Integer anInd = seqCandidates.Value(1);
1628     TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1629     TopoDS_Shape bnd = Edge2;
1630     if (mySectionBound.IsBound(bnd)) 
1631       bnd = mySectionBound(bnd);
1632     //gka
1633     if (myBoundFaces.Contains(bnd)) {
1634       Standard_Boolean isOK = Standard_True;
1635       TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1636       for (; itf2.More() && isOK; itf2.Next()) {
1637         const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1638         // Check whether condition is satisfied
1639         isOK = !Faces1.Contains(Face2);
1640         if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1641       }
1642       if(!isOK)
1643         return Standard_False;
1644     }
1645   }
1646   return (nbCandidates > 0);
1647 }
1648
1649 //=======================================================================
1650 //function : Constructor
1651 //purpose  : 
1652 //=======================================================================
1653
1654 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1655                                  const Standard_Boolean optionSewing,
1656                                  const Standard_Boolean optionAnalysis,
1657                                  const Standard_Boolean optionCutting,
1658                                  const Standard_Boolean optionNonmanifold)
1659 {
1660   myReShape = new BRepTools_ReShape;
1661   Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1662 }
1663
1664 //=======================================================================
1665 //function : Init
1666 //purpose  : Initialise Talerance, and options sewing, faceAnalysis and cutting
1667 //=======================================================================
1668
1669 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1670                            const Standard_Boolean optionSewing,
1671                            const Standard_Boolean optionAnalysis,
1672                            const Standard_Boolean optionCutting,
1673                            const Standard_Boolean optionNonmanifold)
1674 {
1675   // Set tolerance and Perform options
1676   myTolerance      = tolerance;
1677   mySewing         = optionSewing;
1678   myAnalysis       = optionAnalysis;
1679   myCutting        = optionCutting;
1680   myNonmanifold    = optionNonmanifold;
1681   // Set min and max tolerances
1682   myMinTolerance   = tolerance*1e-4; //szv: proposal
1683   if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1684   myMaxTolerance   = Precision::Infinite();
1685   // Set other modes
1686   myFaceMode           = Standard_True;
1687   myFloatingEdgesMode  = Standard_False;
1688   //myCuttingFloatingEdgesMode = Standard_False; //gka
1689   mySameParameterMode  = Standard_True;
1690   myLocalToleranceMode = Standard_False;
1691   mySewedShape.Nullify();
1692   // Load empty shape
1693   Load(TopoDS_Shape());
1694 }
1695
1696 //=======================================================================
1697 //function : Load
1698 //purpose  : Loads the context shape
1699 //=======================================================================
1700
1701 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1702 {
1703   myReShape->Clear();
1704   if (theShape.IsNull()) myShape.Nullify();
1705   else myShape = myReShape->Apply(theShape);
1706   mySewedShape.Nullify();
1707   // Nullify flags and counters
1708   myNbShapes = myNbEdges = myNbVertices = 0;
1709   // Clear all maps
1710   myOldShapes.Clear();
1711   //myOldFaces.Clear();
1712   myDegenerated.Clear();
1713   myFreeEdges.Clear();
1714   myMultipleEdges.Clear();
1715   myContigousEdges.Clear();
1716   myContigSecBound.Clear();
1717   myBoundFaces.Clear();
1718   myBoundSections.Clear();
1719   myVertexNode.Clear();
1720   myVertexNodeFree.Clear();
1721   myNodeSections.Clear();
1722   myCuttingNode.Clear();
1723   mySectionBound.Clear();
1724   myLittleFace.Clear();
1725 }
1726
1727 //=======================================================================
1728 //function : Add
1729 //purpose  : 
1730 //=======================================================================
1731
1732 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1733 {
1734   if (aShape.IsNull()) return;
1735   TopoDS_Shape oShape = myReShape->Apply(aShape);
1736   myOldShapes.Add(aShape,oShape);
1737   myNbShapes = myOldShapes.Extent();
1738 }
1739
1740 //=======================================================================
1741 //function : Perform
1742 //purpose  : 
1743 //=======================================================================
1744
1745 #ifdef DEB
1746 #include <OSD_Timer.hxx>
1747 #endif
1748
1749 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1750 {
1751   const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1752   Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1753 #ifdef DEB
1754   Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1755   OSD_Chronometer chr_total, chr_local;
1756   chr_total.Reset();
1757   chr_total.Start();
1758 #endif
1759
1760   // face analysis
1761   if (myAnalysis)
1762   {
1763 #if DEB
1764     cout << "Begin face analysis..." << endl;
1765     chr_local.Reset();
1766     chr_local.Start();
1767 #endif
1768     FaceAnalysis (thePI);
1769     if (!aPS.More())
1770       return;
1771     aPS.Next();
1772 #if DEB
1773     chr_local.Stop();
1774     chr_local.Show(t_analysis);
1775     cout << "Face analysis finished after " << t_analysis << " s" << endl;
1776 #endif
1777   }
1778
1779   if (myNbShapes || !myShape.IsNull())
1780   {
1781
1782     FindFreeBoundaries();
1783
1784     if (myBoundFaces.Extent())
1785     {
1786
1787 #if DEB
1788       cout << "Begin vertices assembling..." << endl;
1789       chr_local.Reset();
1790       chr_local.Start();
1791 #endif
1792       VerticesAssembling (thePI);
1793       if (!aPS.More())
1794         return;
1795       aPS.Next();
1796 #if DEB
1797       chr_local.Stop();
1798       chr_local.Show(t_assembling);
1799       cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1800 #endif
1801       if (myCutting)
1802       {
1803 #if DEB
1804         cout << "Begin cutting..." << endl;
1805         chr_local.Reset();
1806         chr_local.Start();
1807 #endif
1808         Cutting (thePI);
1809         if (!aPS.More())
1810           return;
1811         aPS.Next();
1812 #if DEB
1813         chr_local.Stop();
1814         chr_local.Show(t_cutting);
1815         cout << "Cutting finished after " << t_cutting << " s" << endl;
1816 #endif
1817       }
1818 #if DEB
1819       cout << "Begin merging..." << endl;
1820       chr_local.Reset();
1821       chr_local.Start();
1822 #endif
1823       Merging (Standard_True, thePI);
1824       if (!aPS.More())
1825         return;
1826       aPS.Next();
1827 #if DEB
1828       chr_local.Stop();
1829       chr_local.Show(t_merging);
1830       cout << "Merging finished after " << t_merging << " s" << endl;
1831 #endif
1832     }
1833     else
1834     {
1835       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1836       if (myCutting)
1837         aPS.Next( 1, Handle(TCollection_HAsciiString)());
1838       aPS.Next( 1, Handle(TCollection_HAsciiString)());
1839       if (!aPS.More())
1840         return;
1841     }
1842
1843     if (mySewing)
1844     {
1845
1846 #if DEB
1847       cout << "Creating sewed shape..." << endl;
1848 #endif
1849       // examine the multiple edges if any and process sameparameter for edges if necessary
1850       EdgeProcessing (thePI);
1851       if (!aPS.More())
1852         return;
1853       CreateSewedShape();
1854       if (!aPS.More())
1855       {
1856         mySewedShape.Nullify();
1857         return;
1858       }
1859       if (mySameParameterMode && myFaceMode)
1860         SameParameterShape();
1861       if (!aPS.More())
1862       {
1863         mySewedShape.Nullify();
1864         return;
1865       }
1866 #if DEB
1867       cout << "Sewed shape created" << endl;
1868 #endif
1869     }
1870
1871     // create edge informations for output
1872     CreateOutputInformations();
1873     if (!aPS.More())
1874     {
1875       mySewedShape.Nullify();
1876       return;
1877     }
1878   }
1879 #if DEB
1880   chr_total.Stop();
1881   chr_total.Show(t_total);
1882   cout << "Sewing finished!" << endl;
1883   cout << " analysis time   : " << t_analysis << " s" << endl;
1884   cout << " assembling time : " << t_assembling << " s" << endl;
1885   cout << " cutting time    : " << t_cutting << " s" << endl;
1886   cout << " merging time    : " << t_merging << " s" << endl;
1887   cout << "Total time       : " << t_total << " s" << endl;
1888 #endif
1889 }
1890
1891 //=======================================================================
1892 //function : SewedShape
1893 //purpose  : give the sewed shape
1894 //           if a null shape, reasons:
1895 //             -- no useable input shapes : all input shapes are degenerated
1896 //             -- has multiple edges
1897 //=======================================================================
1898
1899 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1900 {
1901   return mySewedShape;
1902 }
1903
1904 //=======================================================================
1905 //function : NbFreeEdges
1906 //purpose  : 
1907 //=======================================================================
1908
1909 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1910 {
1911   return myFreeEdges.Extent();
1912 }
1913
1914 //=======================================================================
1915 //function : FreeEdge
1916 //purpose  : 
1917 //=======================================================================
1918
1919 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1920 {
1921   Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1922   return TopoDS::Edge(myFreeEdges(index));
1923 }
1924
1925 //=======================================================================
1926 //function : NbMultipleEdges
1927 //purpose  : 
1928 //=======================================================================
1929
1930 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1931 {
1932   return myMultipleEdges.Extent();
1933 }
1934
1935 //=======================================================================
1936 //function : MultipleEdge
1937 //purpose  : 
1938 //=======================================================================
1939
1940 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1941 {
1942   Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1943   return TopoDS::Edge(myMultipleEdges(index));
1944 }
1945
1946 //=======================================================================
1947 //function : NbContigousEdges
1948 //purpose  : 
1949 //=======================================================================
1950
1951 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1952 {
1953   return myContigousEdges.Extent();
1954 }
1955
1956 //=======================================================================
1957 //function : ContigousEdge
1958 //purpose  : 
1959 //=======================================================================
1960
1961 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
1962 {
1963   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
1964   return TopoDS::Edge(myContigousEdges.FindKey(index));
1965 }
1966
1967 //=======================================================================
1968 //function : ContigousEdgeCouple
1969 //purpose  : 
1970 //=======================================================================
1971
1972 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
1973 {
1974   Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
1975   return myContigousEdges(index);
1976 }
1977
1978 //=======================================================================
1979 //function : IsSectionBound
1980 //purpose  : 
1981 //=======================================================================
1982
1983 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
1984 {
1985   if(myContigSecBound.IsBound(section)) {
1986     return Standard_True;
1987   }
1988   else {
1989     return Standard_False;
1990   }
1991 }
1992
1993 //=======================================================================
1994 //function : SectionToBoundary
1995 //purpose  : 
1996 //=======================================================================
1997
1998 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
1999 {
2000   Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2001   return TopoDS::Edge(myContigSecBound(section));
2002 }
2003 //=======================================================================
2004 //function : NbDeletedFaces
2005 //purpose  : 
2006 //=======================================================================
2007  Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2008 {
2009   return myLittleFace.Extent();
2010 }
2011
2012 //=======================================================================
2013 //function : DeletedFace
2014 //purpose  : 
2015 //=======================================================================
2016 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2017 {
2018   Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2019   return TopoDS::Face(myLittleFace(index));
2020 }
2021
2022 //=======================================================================
2023 //function : NbDegeneratedShapes
2024 //purpose  : 
2025 //=======================================================================
2026
2027 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2028 {
2029   return myDegenerated.Extent();
2030 }
2031
2032 //=======================================================================
2033 //function : DegeneratedShape
2034 //purpose  : 
2035 //=======================================================================
2036
2037 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2038 {
2039   Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2040   return myDegenerated(index);
2041 }
2042
2043 //=======================================================================
2044 //function : IsDegenerated
2045 //purpose  : 
2046 //=======================================================================
2047
2048 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2049 {
2050   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2051   // Degenerated face
2052   if (aShape.ShapeType() == TopAbs_FACE)
2053     return NewShape.IsNull();
2054   if (NewShape.IsNull()) return Standard_False;
2055   // Degenerated edge
2056   if (NewShape.ShapeType() == TopAbs_EDGE)
2057     return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2058   // Degenerated wire
2059   if (NewShape.ShapeType() == TopAbs_WIRE) {
2060     Standard_Boolean isDegenerated = Standard_True;
2061     for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2062       isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2063     return isDegenerated;
2064   }
2065   return Standard_False;
2066 }
2067   
2068 //=======================================================================
2069 //function : IsModified
2070 //purpose  : 
2071 //=======================================================================
2072
2073 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2074 {
2075   TopoDS_Shape NewShape = aShape;
2076   if (myOldShapes.Contains(aShape)) 
2077     NewShape = myOldShapes.FindFromKey(aShape);
2078   if(!NewShape.IsSame(aShape)) return Standard_True;
2079   return Standard_False;
2080 }
2081
2082 //=======================================================================
2083 //function : Modified
2084 //purpose  : 
2085 //=======================================================================
2086
2087 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2088
2089   if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2090   //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2091   return aShape;
2092 }
2093
2094 //=======================================================================
2095 //function : IsModifiedSubShape
2096 //purpose  : 
2097 //=======================================================================
2098
2099 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2100 {
2101   TopoDS_Shape NewShape = myReShape->Apply(aShape);
2102   if(!NewShape.IsSame(aShape)) return Standard_True;
2103   return Standard_False;
2104 }
2105
2106 //=======================================================================
2107 //function : ModifiedSubShape
2108 //purpose  : 
2109 //=======================================================================
2110
2111 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2112
2113   return myReShape->Apply(aShape);
2114 }
2115
2116 //=======================================================================
2117 //function : Dump
2118 //purpose  : 
2119 //=======================================================================
2120
2121 void BRepBuilderAPI_Sewing::Dump() const
2122 {
2123   Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2124   TopTools_MapOfShape mapVertices, mapEdges;
2125   for (i = 1; i <= NbBounds; i++) {
2126     TopoDS_Shape bound = myBoundFaces.FindKey(i);
2127     if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2128     else NbSections++;
2129     TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2130     for (; aExp.More(); aExp.Next()) {
2131       TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2132       mapEdges.Add(E);
2133       TopoDS_Vertex V1, V2;
2134       TopExp::Vertices(E,V1,V2);
2135       mapVertices.Add(V1);
2136       mapVertices.Add(V2);
2137     }
2138   }
2139   cout << " " << endl;
2140   cout << "                        Informations                        " << endl;
2141   cout << " ===========================================================" << endl;
2142   cout << " " << endl;
2143   cout << " Number of input shapes      : " << myOldShapes.Extent() << endl;
2144   cout << " Number of actual shapes     : " << myNbShapes << endl;
2145   cout << " Number of Bounds            : " << NbBounds << endl;
2146   cout << " Number of Sections          : " << NbSections << endl;
2147   cout << " Number of Edges             : " << mapEdges.Extent() << endl;
2148   cout << " Number of Vertices          : " << myNbVertices << endl;
2149   cout << " Number of Nodes             : " << mapVertices.Extent() << endl;
2150   cout << " Number of Free Edges        : " << myFreeEdges.Extent() << endl;
2151   cout << " Number of Contigous Edges   : " << myContigousEdges.Extent() << endl;
2152   cout << " Number of Multiple Edges    : " << myMultipleEdges.Extent() << endl;
2153   cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2154   cout << " ===========================================================" << endl;
2155   cout << " " << endl;
2156 }
2157
2158 //=======================================================================
2159 //function : FaceAnalysis
2160 //purpose  : Remove
2161 //           Modifies:
2162 //                      myNbShapes
2163 //                      myOldShapes
2164 //
2165 //           Constructs:
2166 //                      myDegenerated
2167 //=======================================================================
2168
2169 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2170 {
2171   if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2172     Add(myShape);
2173     myShape.Nullify();
2174   }
2175
2176   BRep_Builder B;
2177   TopTools_MapOfShape SmallEdges;
2178   TopTools_DataMapOfShapeListOfShape GluedVertices;
2179   Standard_Integer i = 1;
2180   Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2181   for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2182     for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2183
2184       // Retrieve current face
2185       TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2186       TopoDS_Face face = TopoDS::Face(aTmpShape);
2187       Standard_Integer nbEdges = 0, nbSmall = 0;
2188
2189       // Build replacing face
2190       aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2191       TopoDS_Face nface = TopoDS::Face(aTmpShape);
2192       Standard_Boolean isFaceChanged = Standard_False;
2193
2194       TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2195       for (; witer.More(); witer.Next()) {
2196
2197         // Retrieve current wire
2198         aTmpShape = witer.Value(); //for porting
2199         if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2200         TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2201
2202         // Build replacing wire
2203         aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2204         TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2205         Standard_Boolean isWireChanged = Standard_False;
2206
2207         TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2208         for (; eiter.More(); eiter.Next()) {
2209
2210           // Retrieve current edge
2211           aTmpShape = eiter.Value(); //for porting
2212           TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2213           nbEdges++;
2214
2215           // Process degenerated edge
2216           if (BRep_Tool::Degenerated(edge)) {
2217             B.Add(nwire,edge); // Old edge kept
2218             myDegenerated.Add(edge);
2219             nbSmall++;
2220             continue;
2221           }
2222
2223           Standard_Boolean isSmall = SmallEdges.Contains(edge);
2224           if (!isSmall) {
2225
2226             // Check for small edge
2227             Standard_Real first, last;
2228             Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2229             if (c3d.IsNull()) {
2230 #ifdef DEB
2231               cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2232 #endif
2233             }
2234             else {
2235               // Evaluate curve compactness
2236               const Standard_Integer npt = 5;
2237               gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2238               Standard_Real dist, maxdist = 0.0;
2239               Standard_Real delta = (last - first)/(npt - 1);
2240               for (Standard_Integer idx = 0; idx < npt; idx++) {
2241                 dist = cp.Distance(c3d->Value(first + idx*delta));
2242                 if (maxdist < dist) maxdist = dist;
2243               }
2244               isSmall = (2.*maxdist <= MinTolerance());
2245               /*try {
2246                 GeomAdaptor_Curve cAdapt(c3d);
2247                 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2248                 isSmall = (length <= MinTolerance());
2249               }
2250               catch (Standard_Failure) {
2251 #ifdef DEB
2252                 cout << "Warning: Possibly small edge can be sewed: ";
2253                 Standard_Failure::Caught()->Print(cout); cout << endl;
2254 #endif
2255               }*/
2256             }
2257
2258             if (isSmall) {
2259
2260               // Store small edge in the map
2261               SmallEdges.Add(edge);
2262
2263               TopoDS_Vertex v1, v2;
2264               TopExp::Vertices(edge,v1,v2);
2265               TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2266
2267               // Store glued vertices
2268               if (!nv1.IsSame(v1)) {
2269                 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2270                 // First vertex was already glued
2271                 if (!nv2.IsSame(v2)) {
2272                   // Merge lists of glued vertices
2273                   if (!nv1.IsSame(nv2)) {
2274                     TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2275                     for (; liter.More(); liter.Next()) {
2276                       TopoDS_Shape v = liter.Value();
2277                       myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2278                       vlist1.Append(v);
2279                     }
2280                     GluedVertices.UnBind(nv2);
2281                   }
2282                 }
2283                 else {
2284                   // Add second vertex to the existing list
2285                   vlist1.Append(v2);
2286                   myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2287                 }
2288               }
2289               else if (!nv2.IsSame(v2)) {
2290                 // Add first vertex to the existing list
2291                 GluedVertices(nv2).Append(v1);
2292                 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2293               }
2294               else if (!v1.IsSame(v2)) {
2295                 // Record new glued vertices
2296                 TopoDS_Vertex nv;
2297                 B.MakeVertex(nv);
2298                 TopTools_ListOfShape vlist;
2299                 vlist.Append(v1);
2300                 vlist.Append(v2);
2301                 GluedVertices.Bind(nv,vlist);
2302                 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2303                 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2304               }
2305             }
2306           }
2307
2308           // Replace small edge
2309           if (isSmall) {
2310 #ifdef DEB
2311             cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2312 #endif
2313             nbSmall++;
2314             // Create new degenerated edge
2315             aTmpShape = edge.Oriented(TopAbs_FORWARD);
2316             TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2317             Standard_Real pfirst, plast;
2318             Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2319             if (!c2d.IsNull()) {
2320               TopoDS_Edge nedge;
2321               B.MakeEdge(nedge);
2322               B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2323               B.Range(nedge,pfirst,plast);
2324               B.Degenerated(nedge,Standard_True);
2325               TopoDS_Vertex v1, v2;
2326               TopExp::Vertices(fedge,v1,v2);
2327               B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2328               B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2329               B.Add(nwire,nedge.Oriented(edge.Orientation()));
2330               myDegenerated.Add(nedge);
2331             }
2332             isWireChanged = Standard_True;
2333           }
2334           else B.Add(nwire,edge); // Old edge kept
2335         }
2336
2337         // Record wire in the new face
2338         if (isWireChanged) {
2339           B.Add(nface,nwire.Oriented(wire.Orientation()));
2340           isFaceChanged = Standard_True;
2341         }
2342         else B.Add(nface,wire);
2343       }
2344
2345       // Remove small face
2346       if (nbSmall == nbEdges) {
2347 #ifdef DEB
2348         cout << "Warning: Small face removed by FaceAnalysis" << endl;
2349 #endif
2350         myLittleFace.Add(face);
2351         myReShape->Remove(face);
2352       }
2353       else if (isFaceChanged) {
2354
2355         myReShape->Replace(face,nface.Oriented(face.Orientation()));
2356       }
2357     }
2358   }
2359
2360   // Update glued vertices
2361   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2362   for (; miter.More(); miter.Next()) {
2363     TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2364     gp_XYZ coord(0.,0.,0.);
2365     Standard_Integer nbPoints = 0;
2366     const TopTools_ListOfShape& vlist = miter.Value();
2367     TopTools_ListIteratorOfListOfShape liter1(vlist);
2368     for (; liter1.More(); liter1.Next()) {
2369       coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2370       nbPoints++;
2371     }
2372     if (nbPoints) {
2373       gp_Pnt vp(coord / nbPoints);
2374       Standard_Real tol = 0.0, mtol = 0.0;
2375       TopTools_ListIteratorOfListOfShape liter2(vlist);
2376       for (; liter2.More(); liter2.Next()) {
2377         Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2378         if (mtol < vtol) mtol = vtol;
2379         vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2380         if (tol < vtol) tol = vtol;
2381       }
2382       B.UpdateVertex(vnew,vp,tol+mtol);
2383     }
2384   }
2385
2386   // Update input shapes
2387   for (i = 1; i <= myOldShapes.Extent(); i++)
2388     myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2389 }
2390
2391 //=======================================================================
2392 //function : FindFreeBoundaries
2393 //purpose  : Constructs :
2394 //                      myBoundFaces     (bound = list of faces) - REFERENCE
2395 //                      myVertexNode     (vertex = node)
2396 //                      myVertexNodeFree (floating vertex = node)
2397 //
2398 //=======================================================================
2399
2400 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2401 {
2402   // Take into account the context shape if needed
2403   TopTools_IndexedMapOfShape NewShapes;
2404   if (!myShape.IsNull()) {
2405     if (myOldShapes.IsEmpty()) {
2406       Add(myShape);
2407       myShape.Nullify();
2408     }
2409     else {
2410       TopoDS_Shape newShape = myReShape->Apply(myShape);
2411       if (!newShape.IsNull()) NewShapes.Add(newShape);
2412     }
2413   }
2414   // Create map Edge -> Faces
2415   TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2416   Standard_Integer i, nbShapes = myOldShapes.Extent();
2417   for (i = 1; i <= nbShapes; i++) {
2418     // Retrieve new shape
2419     TopoDS_Shape shape = myOldShapes(i);
2420     if (shape.IsNull()) continue;
2421     NewShapes.Add(shape);
2422     // Explore shape to find all boundaries
2423     for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2424       TopoDS_Shape edge = eExp.Current();
2425       if (!EdgeFaces.Contains(edge)) {
2426         TopTools_ListOfShape listFaces;
2427         EdgeFaces.Add(edge,listFaces);
2428       }
2429     }
2430   }
2431   // Fill map Edge -> Faces
2432   nbShapes = NewShapes.Extent();
2433    TopTools_MapOfShape mapFaces;
2434   for (i = 1; i <= nbShapes; i++) {
2435     // Explore shape to find all faces
2436     TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2437     for (; fExp.More(); fExp.Next()) {
2438       TopoDS_Shape face = fExp.Current();
2439       if(mapFaces.Contains(face)) continue;
2440       else 
2441         mapFaces.Add(face);
2442       // Explore face to find all boundaries
2443       for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2444         if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2445         for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2446           
2447           TopoDS_Shape edge = aIIe.Value();
2448           
2449           if (EdgeFaces.Contains(edge)) {
2450             EdgeFaces.ChangeFromKey(edge).Append(face);
2451             //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2452             //Standard_Boolean isContained = Standard_False;
2453             //TopTools_ListIteratorOfListOfShape itf(listFaces);
2454             //for (; itf.More() && !isContained; itf.Next())
2455             //  isContained = face.IsSame(itf.Value());
2456             //if (!isContained) listFaces.Append(face);
2457           }
2458         }
2459       }
2460     }
2461   }
2462   // Find free boundaries
2463   nbShapes = EdgeFaces.Extent();
2464   for (i = 1; i <= nbShapes; i++) {
2465     TopTools_ListOfShape& listFaces = EdgeFaces(i);
2466     Standard_Integer nbFaces = listFaces.Extent();
2467     TopoDS_Shape edge    = EdgeFaces.FindKey(i);
2468     if(edge.Orientation() == TopAbs_INTERNAL)
2469           continue;
2470     Standard_Boolean isSeam = Standard_False;
2471     if (nbFaces == 1) {
2472       TopoDS_Face face = TopoDS::Face(listFaces.First());
2473       isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2474       if (isSeam) {
2475         ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2476         //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2477         //if(!isSeam) {
2478           BRep_Builder aB;
2479           TopoDS_Shape anewEdge = edge.EmptyCopied();
2480           TopoDS_Iterator aItV(edge);
2481           for( ; aItV.More() ; aItV.Next())
2482             aB.Add(anewEdge,aItV.Value());
2483           
2484
2485
2486           Standard_Real first2d,last2d;
2487           Handle(Geom2d_Curve) c2dold = 
2488             BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2489
2490           Handle(Geom2d_Curve) c2d;
2491           BRep_Builder B;
2492           B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2493           B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2494           
2495           Standard_Real aFirst, aLast;
2496           BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2497           aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2498           aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2499           myReShape->Replace(edge,anewEdge);
2500           edge = anewEdge;
2501           
2502         //}
2503            isSeam = Standard_False;
2504       }
2505     }
2506     Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2507     Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2508     if (isBound || isBoundFloat) {
2509       // Ignore degenerated edge
2510       if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2511       // Ignore edge with internal vertices
2512      // Standard_Integer nbVtx = 0;
2513      // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2514      // if (nbVtx != 2) continue;
2515       // Add to BoundFaces
2516       TopTools_ListOfShape listFacesCopy;
2517       listFacesCopy.Append(listFaces);
2518       myBoundFaces.Add(edge,listFacesCopy);
2519       // Process edge vertices
2520       TopoDS_Vertex vFirst, vLast;
2521       TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2522       if(vFirst.IsNull() || vLast.IsNull()) continue;
2523       if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2524         continue;
2525       if (isBound) {
2526         // Add to VertexNode
2527         if (!myVertexNode.Contains(vFirst))
2528           myVertexNode.Add(vFirst,vFirst);
2529         if (!myVertexNode.Contains(vLast))
2530           myVertexNode.Add(vLast,vLast);
2531       }
2532       else {
2533         // Add to VertexNodeFree
2534         if (!myVertexNodeFree.Contains(vFirst))
2535           myVertexNodeFree.Add(vFirst,vFirst);
2536         if (!myVertexNodeFree.Contains(vLast))
2537           myVertexNodeFree.Add(vLast,vLast);
2538       }
2539     }
2540   }
2541 }
2542
2543 //=======================================================================
2544 //function : VerticesAssembling
2545 //purpose  : Modifies :
2546 //                      myVertexNode     (nodes glued)
2547 //                      myVertexNodeFree (nodes glued)
2548 //                      myNodeSections   (lists of sections merged for glued nodes)
2549 //
2550 //=======================================================================
2551
2552 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2553                                        const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2554                                        TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2555                                        TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2556 {
2557   Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2558
2559   // Create new nodes
2560   BRep_Builder B;
2561   TopTools_DataMapOfShapeShape OldNodeNewNode;
2562   TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2563   for (i = 1; i <= nbNearest; i++) {
2564     // Retrieve a pair of nodes to merge
2565     TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2566     TopoDS_Shape oldnode2 = NodeNearestNode(i);
2567     // Second node should also be in the map
2568     if (!NodeNearestNode.Contains(oldnode2)) continue;
2569     // Get new node for old node #1
2570     if (OldNodeNewNode.IsBound(oldnode1)) {
2571       TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2572       if (OldNodeNewNode.IsBound(oldnode2)) {
2573         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2574         if (!newnode1.IsSame(newnode2)) {
2575           // Change data for new node #2
2576           TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2577           TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2578           for (; itn.More(); itn.Next()) {
2579             TopoDS_Shape node2 = itn.Value();
2580             lnode1.Append(node2);
2581             OldNodeNewNode(node2) = newnode1;
2582           }
2583           NewNodeOldNodes.UnBind(newnode2);
2584         }
2585       }
2586       else {
2587         // Old node #2 is not bound - add to old node #1
2588         OldNodeNewNode.Bind(oldnode2,newnode1);
2589         NewNodeOldNodes(newnode1).Append(oldnode2);
2590       }
2591     }
2592     else {
2593       if (OldNodeNewNode.IsBound(oldnode2)) {
2594         // Old node #1 is not bound - add to old node #2
2595         TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2596         OldNodeNewNode.Bind(oldnode1,newnode2);
2597         NewNodeOldNodes(newnode2).Append(oldnode1);
2598       }
2599       else {
2600         // Nodes are not bound - create new node
2601         TopoDS_Vertex newnode;
2602         B.MakeVertex(newnode);
2603         OldNodeNewNode.Bind(oldnode1,newnode);
2604         OldNodeNewNode.Bind(oldnode2,newnode);
2605         TopTools_ListOfShape lnodes;
2606         lnodes.Append(oldnode1);
2607         lnodes.Append(oldnode2);
2608         NewNodeOldNodes.Bind(newnode,lnodes);
2609       }
2610     }
2611   }
2612
2613   // Stop if no new nodes created
2614   if (!NewNodeOldNodes.Extent()) return Standard_False;
2615
2616   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2617   for (; iter1.More(); iter1.Next()) {
2618     const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2619     // Calculate new node center point
2620     gp_XYZ theCoordinates(0.,0.,0.);
2621     TopTools_ListOfShape lvert; // Accumulate node vertices
2622     TopTools_MapOfShape medge;
2623     TopTools_ListOfShape ledge; // Accumulate node edges
2624     // Iterate on old nodes
2625     TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2626     for (; itn.More(); itn.Next()) {
2627       const TopoDS_Shape& oldnode = itn.Value();
2628       // Iterate on node vertices
2629       TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2630       for (; itv.More(); itv.Next()) {
2631         TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2632         // Change node for vertex
2633         aVertexNode.ChangeFromKey(vertex) = newnode;
2634         // Accumulate coordinates
2635         theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2636         lvert.Append(vertex);
2637       }
2638       // Iterate on node edges
2639       const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2640       TopTools_ListIteratorOfListOfShape ite(edges);
2641       for (; ite.More(); ite.Next()) {
2642         TopoDS_Shape edge = ite.Value();
2643         if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2644       }
2645       // Unbind old node edges
2646       aNodeEdges.UnBind(oldnode);
2647     }
2648     // Bind new node edges
2649     aNodeEdges.Bind(newnode,ledge);
2650     gp_Pnt center(theCoordinates / lvert.Extent());
2651     // Calculate new node tolerance
2652     Standard_Real toler = 0.0;
2653     TopTools_ListIteratorOfListOfShape itv(lvert);
2654     for (; itv.More(); itv.Next()) {
2655       const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2656       Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2657       if (toler < t) toler = t;
2658     }
2659     // Update new node parameters
2660     B.UpdateVertex(newnode,center,toler);
2661   }
2662
2663   return Standard_True;
2664 }
2665
2666 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2667                                          const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2668                                          const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2669 {
2670   //Case of floating edges
2671   if (face1.IsNull())
2672     return (!IsClosedShape(e1,vtx1,vtx2));
2673
2674   // Find wires containing given edges
2675   TopoDS_Shape wire1, wire2;
2676   TopExp_Explorer itw(face1,TopAbs_WIRE);
2677   for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2678     TopoDS_Iterator ite(itw.Current(),Standard_False);
2679     for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2680       if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2681       if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2682     }
2683   }
2684   Standard_Integer Status = 0;
2685   if (!wire1.IsNull() && !wire2.IsNull()) {
2686     if (wire1.IsSame(wire2)) {
2687       for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2688         TopoDS_Vertex ve1,ve2;
2689         TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2690         if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2691             (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2692           return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2693       }
2694       if (IsClosedShape(wire1,vtx1,vtx2)) {
2695         TopoDS_Vertex V1, V2;
2696         TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2697         Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2698                                         (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2699         if (!isEndVertex) Status = 1;
2700       }
2701       else Status = 1;
2702     }
2703     else Status = -1;
2704   }
2705   return Status;
2706 }
2707
2708 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2709                                      TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2710                                      const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2711                                      const Standard_Real Tolerance,
2712                                      const Handle(Message_ProgressIndicator)& theProgress)
2713 {
2714   Standard_Integer i, nbVertices = aVertexNode.Extent();
2715   // Create map of node -> vertices
2716   TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2717   for (i = 1; i <= nbVertices; i++) {
2718     TopoDS_Shape vertex = aVertexNode.FindKey(i);
2719     TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2720     if (NodeVertices.Contains(node)) {
2721       NodeVertices.ChangeFromKey(node).Append(vertex);
2722     }
2723     else {
2724       TopTools_ListOfShape vlist;
2725       vlist.Append(vertex);
2726       NodeVertices.Add(node,vlist);
2727     }
2728   }
2729   Standard_Integer nbNodes = NodeVertices.Extent();
2730 #ifdef DEB
2731   cout << "Glueing " << nbNodes << " nodes..." << endl;
2732 #endif
2733   // Create array of boxes with nodes
2734   Handle(Bnd_HArray1OfBox) hSetBoxes = new Bnd_HArray1OfBox(1,nbNodes);
2735   Bnd_Box aBox;
2736   Standard_Real eps = Tolerance*0.5;
2737   for (i = 1; i <= nbNodes; i++) {
2738     gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(NodeVertices.FindKey(i)));
2739     aBox.Set(pt);
2740     aBox.Enlarge(eps);
2741     hSetBoxes->SetValue(i,aBox);
2742   }
2743   // Merge nearest nodes
2744   TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2745   Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2746   for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2747     TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2748     // Find near nodes
2749     TColStd_ListOfInteger listIndex;
2750     SortBox(hSetBoxes,hSetBoxes->Value(i),listIndex);
2751     if (listIndex.IsEmpty()) continue;
2752     // Retrieve list of edges for the first node
2753     const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2754     // Explore list of near nodes and fill the sequence of glued nodes
2755     TopTools_SequenceOfShape SeqNodes;
2756     TopTools_ListOfShape listNodesSameEdge;
2757     gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2758     TColStd_ListIteratorOfListOfInteger iter1(listIndex);
2759     for (; iter1.More(); iter1.Next()) {
2760       TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2761       if (node1 == node2) continue;
2762       // Retrieve list of edges for the second node
2763       const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2764       // Check merging condition for the pair of nodes
2765       Standard_Integer Status = 0, isSameEdge = Standard_False;
2766       // Explore edges of the first node
2767       TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2768       for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2769         const TopoDS_Shape& e1 = Ie1.Value();
2770         // Obtain real vertex from edge
2771         TopoDS_Shape v1 = node1;
2772         { //szv: Use brackets to destroy local variables
2773           TopoDS_Vertex ov1, ov2;
2774           TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2775           if (aVertexNode.Contains(ov1)) {
2776             if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2777           }
2778           if (aVertexNode.Contains(ov2)) {
2779             if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2780           }
2781         }
2782         // Create map of faces for e1
2783         TopTools_MapOfShape Faces1;
2784         const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2785         if (lfac1.Extent()) {
2786           TopTools_ListIteratorOfListOfShape itf(lfac1);
2787           for (; itf.More(); itf.Next())
2788             if (!itf.Value().IsNull())
2789               Faces1.Add(itf.Value());
2790         }
2791         // Explore edges of the second node
2792         TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2793         for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2794           const TopoDS_Shape& e2 = Ie2.Value();
2795           // Obtain real vertex from edge
2796           TopoDS_Shape v2 = node2;
2797           { //szv: Use brackets to destroy local variables
2798             TopoDS_Vertex ov1, ov2;
2799             TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2800             if (aVertexNode.Contains(ov1)) {
2801               if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2802             }
2803             if (aVertexNode.Contains(ov2)) {
2804               if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2805             }
2806           }
2807           // Explore faces for e2
2808           const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2809           if (lfac2.Extent()) {
2810             TopTools_ListIteratorOfListOfShape itf(lfac2);
2811             for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2812               // Check merging conditions for the same face
2813               if (Faces1.Contains(itf.Value())) {
2814                 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2815                 if (stat == 1) isSameEdge = Standard_True;
2816                 else Status = stat;
2817               }
2818             }
2819           }
2820           else if (Faces1.IsEmpty() && e1 == e2) {
2821             Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2822             if (stat == 1) isSameEdge = Standard_True;
2823             else Status = stat;
2824             break;
2825           }
2826         }
2827       }
2828       if (Status) continue;
2829       if (isSameEdge) listNodesSameEdge.Append(node2);
2830       // Append near node to the sequence
2831       gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2832       Standard_Real dist = pt1.Distance(pt2);
2833       if (dist < Tolerance) {
2834         Standard_Boolean isIns = Standard_False;
2835         for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2836           gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2837           if (dist < pt1.Distance(pt)) {
2838             SeqNodes.InsertBefore(kk,node2);
2839             isIns = Standard_True;
2840           }
2841         }
2842         if (!isIns) SeqNodes.Append(node2);
2843       }
2844     }
2845     if (SeqNodes.Length()) {
2846       // Remove nodes near to some other from the same edge
2847       if (listNodesSameEdge.Extent()) {
2848         TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2849         for (; lInt.More(); lInt.Next()) {
2850           const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2851           gp_Pnt p2 = BRep_Tool::Pnt(n2);
2852           for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2853             const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2854             if (n1 != n2) {
2855               gp_Pnt p1 = BRep_Tool::Pnt(n1);
2856               if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2857             }
2858             SeqNodes.Remove(k);
2859           }
2860         }
2861       }
2862       // Bind nearest node if at least one exists
2863       if (SeqNodes.Length())
2864         NodeNearestNode.Add(node1,SeqNodes.First());
2865     }
2866   }
2867
2868   // Create new nodes for chained nearest nodes
2869   if (NodeNearestNode.IsEmpty()) return Standard_False;
2870   hSetBoxes.Nullify();
2871
2872   return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2873 }
2874
2875 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2876 {
2877   Standard_Integer nbVert = myVertexNode.Extent();
2878   Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2879   Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2880   if (nbVert || nbVertFree) {
2881     // Fill map node -> sections
2882     Standard_Integer i;
2883     for (i = 1; i <= myBoundFaces.Extent(); i++) {
2884       TopoDS_Shape bound = myBoundFaces.FindKey(i);
2885       for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2886         TopoDS_Shape node = itv.Value();
2887         if (myNodeSections.IsBound(node))
2888           myNodeSections(node).Append(bound);
2889         else {
2890           TopTools_ListOfShape lbnd;
2891           lbnd.Append(bound);
2892           myNodeSections.Bind(node,lbnd);
2893         }
2894       }
2895     }
2896     // Glue vertices
2897     if (nbVert) {
2898 #ifdef DEB
2899       cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2900 #endif
2901       while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2902     }
2903     if (!aPS.More())
2904       return;
2905     aPS.Next();
2906     if (nbVertFree) {
2907 #ifdef DEB
2908       cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2909 #endif
2910       while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2911     }
2912   }
2913 }
2914
2915 //=======================================================================
2916 //function : replaceNMVertices
2917 //purpose  : internal use (static)
2918 //=======================================================================
2919 static void replaceNMVertices(const TopoDS_Edge& theEdge, 
2920                               const TopoDS_Vertex& theV1,
2921                               const TopoDS_Vertex& theV2,
2922                               const Handle(BRepTools_ReShape)& theReShape)
2923 {
2924   //To keep NM vertices on edge
2925   TopTools_SequenceOfShape aSeqNMVert;
2926   TColStd_SequenceOfReal aSeqNMPars;
2927   Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2928   if(!hasNMVert)
2929     return;
2930   Standard_Real first, last;
2931   BRep_Tool::Range(theEdge, first, last);
2932   TopLoc_Location aLoc;
2933   Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2934   if(c3d.IsNull())
2935     return;
2936   TopTools_SequenceOfShape aEdVert;
2937   TColStd_SequenceOfReal aEdParams;
2938   Standard_Integer i =1, nb = aSeqNMPars.Length();
2939     
2940   for( ; i <= nb;i++) {
2941     Standard_Real apar = aSeqNMPars.Value(i);
2942     if(fabs(apar - first) <= Precision::PConfusion()) {
2943       theReShape->Replace(aSeqNMVert.Value(i),theV1);
2944       continue;
2945     }
2946     if(fabs(apar - last) <= Precision::PConfusion()) {
2947       theReShape->Replace(aSeqNMVert.Value(i),theV2);
2948       continue;
2949     }
2950     TopoDS_Shape aV = aSeqNMVert.Value(i);
2951     Standard_Integer j =1;
2952     for( ; j <= aEdParams.Length();j++) {
2953       Standard_Real apar2 = aEdParams.Value(j);
2954       if(fabs(apar - apar2) <= Precision::PConfusion()) {
2955         theReShape->Replace(aV,aEdVert.Value(j));
2956         break;
2957       }
2958       else if(apar < apar2) {
2959         TopoDS_Shape anewV = aV.EmptyCopied();
2960         aEdVert.InsertBefore(j,anewV);
2961         aEdParams.InsertBefore(j,apar);
2962         BRep_ListOfPointRepresentation& alistrep = 
2963           (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
2964         Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2965         alistrep.Append(aPRep);
2966         theReShape->Replace(aV,anewV);
2967         break;
2968       }
2969     }
2970     if (j > aEdParams.Length()) {
2971       TopoDS_Shape anewV = aV.EmptyCopied();
2972       aEdVert.Append(anewV);
2973       aEdParams.Append(apar);
2974       BRep_ListOfPointRepresentation& alistrep = 
2975         (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
2976       Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2977       alistrep.Append(aPRep);
2978       theReShape->Replace(aV,anewV);
2979     }
2980   }
2981   
2982   Standard_Integer newnb = aEdParams.Length();
2983   if(newnb < nb) {
2984     
2985     TopoDS_Shape anewEdge = theEdge.EmptyCopied();
2986     TopAbs_Orientation anOri = theEdge.Orientation();
2987     anewEdge.Orientation(TopAbs_FORWARD);
2988     BRep_Builder aB;
2989     aB.Add(anewEdge,theV1);
2990     aB.Add(anewEdge,theV2);
2991     
2992     for( i =1; i <= aEdVert.Length();i++) 
2993       aB.Add(anewEdge,aEdVert.Value(i));
2994     anewEdge.Orientation(anOri);
2995     theReShape->Replace(theEdge,anewEdge);
2996   }
2997  
2998 }
2999
3000 //=======================================================================
3001 //function : ReplaceEdge
3002 //purpose  : internal use (static)
3003 //=======================================================================
3004
3005 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3006                         const TopoDS_Shape& theNewShape,
3007                         const Handle(BRepTools_ReShape)& aReShape)
3008 {
3009   TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3010   TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3011   if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3012   
3013
3014   aReShape->Replace(oldShape,newShape);
3015   TopoDS_Vertex V1old,V2old,V1new,V2new;
3016   TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3017   TopAbs_Orientation Orold = oldShape.Orientation();
3018   TopAbs_Orientation Ornew = Orold;
3019   if (newShape.ShapeType() == TopAbs_EDGE) {
3020     TopoDS_Edge aEn = TopoDS::Edge(newShape);
3021     TopExp::Vertices(aEn,V1new,V2new);
3022     Ornew = aEn.Orientation();
3023     replaceNMVertices(aEn,V1new,V2new,aReShape);
3024   }
3025   else if (newShape.ShapeType() == TopAbs_WIRE) {
3026     for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3027       TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3028       Ornew = ed.Orientation();
3029       TopoDS_Vertex aV1,aV2;
3030       TopExp::Vertices(ed,aV1,aV2);
3031       replaceNMVertices(ed,aV1,aV2,aReShape);
3032       if (V1new.IsNull()) 
3033         V1new = aV1;
3034       V2new =aV2;
3035     }
3036   }
3037   
3038   V1new.Orientation(V1old.Orientation());
3039   V2new.Orientation(V2old.Orientation());
3040   if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3041     aReShape->Replace(V1old,V1new);
3042     return;
3043   }
3044   if (Orold == Ornew) {
3045     V1new.Orientation(V1old.Orientation());
3046     V2new.Orientation(V2old.Orientation());
3047     if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3048       aReShape->Replace(V1old,V1new);
3049     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3050       aReShape->Replace(V2old,V2new);
3051   }
3052   else {
3053     V1new.Orientation(V2old.Orientation());
3054     V2new.Orientation(V1old.Orientation());
3055     if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) 
3056       aReShape->Replace(V1old,V2new);
3057     if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3058       aReShape->Replace(V2old,V1new);
3059   }
3060 }
3061
3062 //=======================================================================
3063 //function : Merging
3064 //purpose  : Modifies :
3065 //                   myHasFreeBound
3066 //
3067 //=======================================================================
3068
3069 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */, 
3070                                     const Handle(Message_ProgressIndicator)& thePI)
3071 {
3072   BRep_Builder B;
3073   //  TopTools_MapOfShape MergedEdges;
3074   Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3075   for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3076
3077     TopoDS_Shape bound = myBoundFaces.FindKey(i);
3078
3079     // If bound was already merged - continue
3080     if (myMergedEdges.Contains(bound)) continue;
3081
3082     if (!myBoundFaces(i).Extent()) {
3083       // Merge free edge - only vertices
3084       TopoDS_Vertex no1, no2;
3085       TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3086       TopoDS_Shape nno1 = no1, nno2 = no2;
3087       if (myVertexNodeFree.Contains(no1))
3088         nno1 = myVertexNodeFree.FindFromKey(no1);
3089       if (myVertexNodeFree.Contains(no2))
3090         nno2 = myVertexNodeFree.FindFromKey(no2);
3091       if (!no1.IsSame(nno1)) {
3092         nno1.Orientation(no1.Orientation());
3093         myReShape->Replace(no1,nno1);
3094       }
3095       if (!no2.IsSame(nno2)) {
3096         nno2.Orientation(no2.Orientation());
3097         myReShape->Replace(no2,nno2);
3098       }
3099       myMergedEdges.Add(bound);
3100       continue;
3101     }
3102
3103     // Check for previous splitting, build replacing wire
3104     TopoDS_Wire BoundWire;
3105     Standard_Boolean isPrevSplit = Standard_False;
3106     Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3107     if (hasCuttingSections) {
3108       B.MakeWire(BoundWire);
3109       BoundWire.Orientation(bound.Orientation());
3110       // Iterate on cutting sections
3111       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3112       for (; its.More(); its.Next()) {
3113         TopoDS_Shape section = its.Value();
3114         B.Add(BoundWire,section);
3115         if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3116       }
3117     }
3118
3119     // Merge with bound
3120     TopTools_DataMapOfShapeShape MergedWithBound;
3121     if (!isPrevSplit) {
3122       // Obtain sequence of edges merged with bound
3123       TopTools_SequenceOfShape seqMergedWithBound;
3124       TColStd_SequenceOfInteger seqMergedWithBoundOri;
3125       if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3126         // Store bound in the map
3127         MergedWithBound.Bind(bound,bound);
3128         // Iterate on edges merged with bound
3129         Standard_Integer ii = 1;
3130         while (ii <= seqMergedWithBound.Length()) {
3131           TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3132           // Remove edge if recorded as merged
3133           Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || 
3134             MergedWithBound.IsBound(iedge));
3135           if (!isRejected) {
3136             if (myBoundSections.IsBound(iedge)) {
3137               // Edge is splitted - check sections
3138               TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3139               for (; lit.More() && !isRejected; lit.Next()) {
3140                 const TopoDS_Shape& sec = lit.Value();
3141                 // Remove edge (bound) if at least one of its sections already merged
3142                 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3143               }
3144             }
3145             if (!isRejected) {
3146               if (mySectionBound.IsBound(iedge)) {
3147                 // Edge is a section - check bound
3148                 const TopoDS_Shape& bnd = mySectionBound(iedge);
3149                 // Remove edge (section) if its bound already merged
3150                 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3151               }
3152             }
3153           }
3154           // To the next merged edge
3155           if (isRejected) {
3156             // Remove rejected edge
3157             seqMergedWithBound.Remove(ii);
3158             seqMergedWithBoundOri.Remove(ii);
3159           }
3160           else {
3161             // Process accepted edge
3162             MergedWithBound.Bind(iedge,iedge);
3163             ii++;
3164           }
3165         }
3166         Standard_Integer nbMerged = seqMergedWithBound.Length();
3167         if (nbMerged) {
3168           // Create same parameter edge
3169           TopTools_MapOfShape ActuallyMerged;
3170           TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3171             seqMergedWithBoundOri,
3172             ActuallyMerged,myReShape);
3173           Standard_Boolean isForward = Standard_False;
3174           if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3175           // Process actually merged edges
3176           Standard_Integer nbActuallyMerged = 0;
3177           for (ii = 1; ii <= nbMerged; ii++) {
3178             TopoDS_Shape iedge = seqMergedWithBound(ii);
3179             if (ActuallyMerged.Contains(iedge)) {
3180               nbActuallyMerged++;
3181               // Record merged edge in the map
3182               TopAbs_Orientation orient = iedge.Orientation();
3183               if (!isForward) orient = TopAbs::Reverse(orient);
3184               if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3185               MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3186             }
3187             else MergedWithBound.UnBind(iedge);
3188           }
3189           if (nbActuallyMerged) {
3190             // Record merged bound in the map
3191             TopAbs_Orientation orient = bound.Orientation();
3192             if (!isForward) orient = TopAbs::Reverse(orient);
3193             MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3194           }
3195           nbMerged = nbActuallyMerged;
3196         }
3197         // Remove bound from the map if not finally merged
3198         if (!nbMerged) MergedWithBound.UnBind(bound);
3199       }
3200     }
3201     Standard_Boolean isMerged = MergedWithBound.Extent();
3202
3203     // Merge with cutting sections
3204     Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3205     TopTools_DataMapOfShapeShape MergedWithSections;
3206     if (hasCuttingSections) {
3207       // Iterate on cutting sections
3208       TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3209       for (; its.More(); its.Next()) {
3210         // Retrieve cutting section
3211         TopoDS_Shape section = its.Value();
3212         // Skip section if already merged
3213         if (myMergedEdges.Contains(section)) continue;
3214         // Merge cutting section
3215         TopTools_SequenceOfShape seqMergedWithSection;
3216         TColStd_SequenceOfInteger seqMergedWithSectionOri;
3217         if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3218           // Store section in the map
3219           MergedWithSections.Bind(section,section);
3220           // Iterate on edges merged with section
3221           Standard_Integer ii = 1;
3222           while (ii <= seqMergedWithSection.Length()) {
3223             TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3224             // Remove edge if recorded as merged
3225             Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3226             if (!isRejected) {
3227               if (myBoundSections.IsBound(iedge)) {
3228                 // Edge is splitted - check sections
3229                 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3230                 for (; lit.More() && !isRejected; lit.Next()) {
3231                   const TopoDS_Shape& sec = lit.Value();
3232                   // Remove edge (bound) if at least one of its sections already merged
3233                   isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3234                 }
3235               }
3236               if (!isRejected) {
3237                 if (mySectionBound.IsBound(iedge)) {
3238                   // Edge is a section - check bound
3239                   const TopoDS_Shape& bnd = mySectionBound(iedge);
3240                   // Remove edge (section) if its bound already merged
3241                   isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3242                 }
3243               }
3244             }
3245             // To the next merged edge
3246             if (isRejected) {
3247               // Remove rejected edge
3248               seqMergedWithSection.Remove(ii);
3249               seqMergedWithSectionOri.Remove(ii);
3250             }
3251             else {
3252               // Process accepted edge
3253               MergedWithSections.Bind(iedge,iedge);
3254               ii++;
3255             }
3256           }
3257           Standard_Integer nbMerged = seqMergedWithSection.Length();
3258           if (nbMerged) {
3259             // Create same parameter edge
3260             TopTools_MapOfShape ActuallyMerged;
3261             TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3262               seqMergedWithSectionOri,
3263               ActuallyMerged,SectionsReShape);
3264             Standard_Boolean isForward = Standard_False;
3265             if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3266             // Process actually merged edges
3267             Standard_Integer nbActuallyMerged = 0;
3268             for (ii = 1; ii <= nbMerged; ii++) {
3269               TopoDS_Shape iedge = seqMergedWithSection(ii);
3270               if (ActuallyMerged.Contains(iedge)) {
3271                 nbActuallyMerged++;
3272                 // Record merged edge in the map
3273                 TopAbs_Orientation orient = iedge.Orientation();
3274                 if (!isForward) orient = TopAbs::Reverse(orient);
3275                 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3276                 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3277                 MergedWithSections.ChangeFind(iedge) = oedge;
3278                 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3279               }
3280               else MergedWithSections.UnBind(iedge);
3281             }
3282             if (nbActuallyMerged) {
3283               // Record merged section in the map
3284               TopAbs_Orientation orient = section.Orientation();
3285               if (!isForward) orient = TopAbs::Reverse(orient);
3286               TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3287               MergedWithSections.ChangeFind(section) = oedge;
3288               ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3289             }
3290             nbMerged = nbActuallyMerged;
3291           }
3292           // Remove section from the map if not finally merged
3293           if (!nbMerged) MergedWithSections.UnBind(section);
3294         }
3295         else if (isMerged) {
3296           // Reject merging of sections
3297           MergedWithSections.Clear();
3298           break;
3299         }
3300       }
3301     }
3302     Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3303
3304     if (!isMerged && !isMergedSplit) {
3305       // Nothing was merged in this iteration
3306       if (isPrevSplit) {
3307         // Replace previously splitted bound
3308         myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3309       }
3310       //      else if (hasCuttingSections) {
3311       //        myBoundSections.UnBind(bound); //szv: are you sure ???
3312       //      }
3313       continue;
3314     }
3315
3316     // Set splitting flag
3317     Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3318
3319     // Choose between bound and sections merging
3320     if (isMerged && isMergedSplit && !isPrevSplit) {
3321       // Fill map of merged cutting sections
3322       TopTools_MapOfShape MapSplitEdges;
3323       TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3324       for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3325         TopoDS_Shape edge = itm.Key();
3326         MapSplitEdges.Add(edge);
3327       }
3328       // Iterate on edges merged with bound
3329       for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3330         // Retrieve edge merged with bound
3331         TopoDS_Shape edge = itm.Key();
3332         // Remove edge from the map
3333         if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3334         if (myBoundSections.IsBound(edge)) {
3335           // Edge has cutting sections
3336           TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3337           for (; its.More(); its.Next()) {
3338             TopoDS_Shape sec = its.Value();
3339             // Remove section from the map
3340             if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3341           }
3342         }
3343       }
3344       // Calculate section merging tolerance
3345       Standard_Real MinSplitTol = RealLast();
3346       TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3347       for (; im.More(); im.Next()) {
3348         TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3349         MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3350       }
3351       // Calculate bound merging tolerance
3352       TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3353       Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3354       isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3355       isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3356     }
3357
3358     if (isSplitted) {
3359       // Merging of cutting sections
3360       //myMergedEdges.Add(bound);
3361       myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3362       TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3363       for (; itm.More(); itm.Next()) {
3364         TopoDS_Shape oldedge = itm.Key();
3365         TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3366         ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3367         myMergedEdges.Add(oldedge);
3368         if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3369
3370       }
3371     }
3372     else {
3373       // Merging of initial bound
3374       TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3375       //myMergedEdges.Add(bound);
3376       for (; itm.More(); itm.Next()) {
3377         TopoDS_Shape oldedge = itm.Key();
3378         TopoDS_Shape newedge = itm.Value();
3379         ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3380         myMergedEdges.Add(oldedge);
3381         if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3382       }
3383       if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3384       if(!myMergedEdges.Contains(bound))
3385         myMergedEdges.Add(bound);
3386     }
3387   }
3388
3389   myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3390   myNodeSections.Clear();
3391   myVertexNode.Clear();
3392   myVertexNodeFree.Clear();
3393   myCuttingNode.Clear();
3394 }
3395
3396 //=======================================================================
3397 //function : MergedNearestEdges
3398 //purpose  : 
3399 //=======================================================================
3400
3401 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3402                                                            TopTools_SequenceOfShape& SeqMergedEdge,
3403                                                            TColStd_SequenceOfInteger& SeqMergedOri)
3404 {
3405   // Retrieve edge nodes
3406   TopoDS_Vertex no1, no2;
3407   TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3408   TopoDS_Shape nno1 = no1, nno2 = no2;
3409   Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3410   Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3411   if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3412   if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3413
3414   // Fill map of nodes connected to the node #1
3415   TopTools_MapOfShape mapVert1;
3416   mapVert1.Add(nno1);
3417   if (myCuttingNode.IsBound(nno1)) {
3418     TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3419     for (; ilv.More(); ilv.Next()) {
3420       TopoDS_Shape v1 = ilv.Value();
3421       mapVert1.Add(v1);
3422       if (!isNode1 && myCuttingNode.IsBound(v1)) {
3423         TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3424         for (; ilvn.More(); ilvn.Next()) {
3425           TopoDS_Shape vn = ilvn.Value();
3426           mapVert1.Add(vn);
3427         }
3428       }
3429     }
3430   }
3431
3432   // Fill map of nodes connected to the node #2
3433   TopTools_MapOfShape mapVert2;
3434   mapVert2.Add(nno2);
3435   if (myCuttingNode.IsBound(nno2)) {
3436     TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3437     for (; ilv.More(); ilv.Next()) {
3438       TopoDS_Shape v1 = ilv.Value();
3439       mapVert2.Add(v1);
3440       if (!isNode2 && myCuttingNode.IsBound(v1)) {
3441         TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3442         for (; ilvn.More(); ilvn.Next()) {
3443           TopoDS_Shape vn = ilvn.Value();
3444           mapVert2.Add(vn);
3445         }
3446       }
3447     }
3448   }
3449
3450   // Find all possible contigous edges
3451   TopTools_SequenceOfShape seqEdges;
3452   seqEdges.Append(edge);
3453   TopTools_MapOfShape mapEdges;
3454   mapEdges.Add(edge);
3455   for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3456     TopoDS_Shape node1 = imv1.Key();
3457     if (!myNodeSections.IsBound(node1)) continue;
3458     TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3459     for (; ilsec.More(); ilsec.Next()) {
3460       TopoDS_Shape sec = ilsec.Value();
3461       if (sec.IsSame(edge)) continue;
3462       // Retrieve section nodes
3463       TopoDS_Vertex vs1, vs2;
3464       TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3465       TopoDS_Shape vs1n = vs1, vs2n = vs2;
3466       if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3467       if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3468       if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3469         (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3470         if (mapEdges.Add(sec)) {
3471           // Check for rejected cutting
3472           Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3473           if(!isRejected && myBoundSections.IsBound(sec))
3474           {
3475             TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3476             for (; its.More() && !isRejected; its.Next()) {
3477               TopoDS_Shape section = its.Value();
3478
3479               if (myMergedEdges.Contains(section)) 
3480                 isRejected = Standard_True;
3481             }
3482           }
3483           if( !isRejected && mySectionBound.IsBound(sec)) {
3484             const TopoDS_Shape& bnd = mySectionBound(sec);
3485             isRejected = (!myBoundSections.IsBound(bnd) ||
3486               myMergedEdges.Contains(bnd));
3487           }
3488
3489           if (!isRejected) seqEdges.Append(sec);
3490         }
3491     }
3492   }
3493
3494   mapEdges.Clear();
3495
3496   Standard_Boolean success = Standard_False;
3497
3498   Standard_Integer nbSection = seqEdges.Length();
3499   if (nbSection > 1) {
3500     // Find the longest edge CCI60011
3501     Standard_Integer i, indRef = 1;
3502     if (myNonmanifold) {
3503       Standard_Real lenRef = 0.;
3504       for (i = 1; i <= nbSection; i++) {
3505         Standard_Real f, l;
3506         Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3507         GeomAdaptor_Curve cAdapt(c3d);
3508         Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3509         if (len > lenRef) { indRef = i; lenRef = len; }
3510       }
3511       if (indRef != 1) {
3512         TopoDS_Shape longEdge = seqEdges(indRef);
3513         seqEdges(indRef) = seqEdges(1);
3514         seqEdges(1) = longEdge;
3515       }
3516     }
3517
3518     // Find merging candidates
3519     TColStd_SequenceOfInteger seqForward;
3520     TColStd_SequenceOfInteger seqCandidates;
3521     TColStd_IndexedMapOfInteger mapReference;
3522     mapReference.Add(1); // Add index of reference section
3523     if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3524       Standard_Integer nbCandidates = seqCandidates.Length();
3525       // Check if reference section is merged reversed
3526       Standard_Boolean toReverse = Standard_False;
3527       if (indRef != 1) {
3528         // Find reference edge in candidates
3529         Standard_Boolean isFound = Standard_False;
3530         for (i = 1; i <= nbCandidates && !isFound; i++) {
3531           isFound = (seqCandidates(i) == indRef);
3532           if (isFound) {
3533             // Record orientation
3534             toReverse = !seqForward(i);
3535             // Restore first edge
3536             seqCandidates(i) = 1;
3537             seqForward(i) = 1;
3538           }
3539         }
3540         // Fail if reference is not in candidates
3541         if (!isFound) return Standard_False;
3542       }
3543       // Record candidate sections
3544       for (i = 1; i <= nbCandidates; i++) {
3545         // Retrieve merged edge
3546         TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3547         Standard_Integer ori =
3548           ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1;
3549         SeqMergedEdge.Append(iedge);
3550         SeqMergedOri.Append(ori);
3551         if (!myNonmanifold) break;
3552       }
3553       success = nbCandidates;
3554     }
3555   }
3556
3557   return success;
3558 }
3559
3560 //=======================================================================
3561 //function : Cutting
3562 //purpose  : Modifies :
3563 //                     myBoundSections
3564 //                     myNodeSections
3565 //                     myCuttingNode
3566 //=======================================================================
3567
3568 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3569 {
3570   Standard_Integer i, nbVertices = myVertexNode.Extent();
3571   if (!nbVertices) return;
3572   // Create a sort box with vertices
3573   Standard_Real eps = myTolerance*0.5;
3574   Handle(Bnd_HArray1OfBox) hSetBoxes = new Bnd_HArray1OfBox(1,nbVertices);
3575   for (i = 1; i <= nbVertices; i++) {
3576     gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3577     Bnd_Box aBox;
3578     aBox.Set(pt);
3579     aBox.Enlarge(eps);
3580     hSetBoxes->ChangeValue(i) = aBox;
3581   }
3582   Handle(Geom_Curve) c3d;
3583   TopLoc_Location loc;
3584   Standard_Real first, last;
3585   // Iterate on all boundaries
3586   Standard_Integer nbBounds = myBoundFaces.Extent();
3587   Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3588   for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3589     const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3590     // Do not cut floating edges
3591     if (!myBoundFaces(i).Extent()) continue;
3592     // Create cutting sections
3593     TopTools_ListOfShape listSections;
3594     { //szv: Use brackets to destroy local variables
3595       // Obtain bound curve
3596       c3d = BRep_Tool::Curve(bound, loc, first, last);
3597       if (!loc.IsIdentity()) {
3598         c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3599         c3d->Transform(loc.Transformation());
3600       }
3601       // Obtain candidate vertices
3602       TopoDS_Vertex V1, V2;
3603       TopTools_IndexedMapOfShape CandidateVertices;
3604       { //szv: Use brackets to destroy local variables
3605         // Create bounding box around curve
3606         Bnd_Box aGlobalBox;
3607         GeomAdaptor_Curve adptC(c3d,first,last);
3608         BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3609         // Sort vertices to find candidates
3610         TColStd_ListOfInteger listIndex;
3611         SortBox(hSetBoxes,aGlobalBox,listIndex);
3612         // Skip bound if no node is in the boundind box
3613         if (!listIndex.Extent()) continue;
3614         // Retrieve bound nodes
3615         TopExp::Vertices(bound,V1,V2);
3616         const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3617         const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3618         // Fill map of candidate vertices
3619         TColStd_ListIteratorOfListOfInteger itl(listIndex);
3620         for (; itl.More(); itl.Next()) {
3621           const Standard_Integer index = itl.Value();
3622           const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3623           if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3624             TopoDS_Shape vertex = myVertexNode.FindKey(index);
3625             CandidateVertices.Add(vertex);
3626           }
3627         }
3628       }
3629       Standard_Integer nbCandidates = CandidateVertices.Extent();
3630       if (!nbCandidates) continue;
3631       // Project vertices on curve
3632       TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3633       TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3634       for (Standard_Integer j = 1; j <= nbCandidates; j++)
3635         arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3636       ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3637       // Create cutting nodes
3638       TopTools_SequenceOfShape seqNode;
3639       TColStd_SequenceOfReal seqPara;
3640       CreateCuttingNodes(CandidateVertices,bound,
3641         V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3642       if (!seqPara.Length()) continue;
3643       // Create cutting sections
3644       CreateSections(bound, seqNode, seqPara, listSections);
3645     }
3646     if (listSections.Extent() > 1) {
3647       // modification of maps:
3648       //                     myBoundSections
3649       TopTools_ListIteratorOfListOfShape its(listSections);
3650       for (; its.More(); its.Next()) {
3651         TopoDS_Shape section = its.Value();
3652         // Iterate on section vertices
3653         for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3654           TopoDS_Shape vertex = itv.Value();
3655           // Convert vertex to node
3656           if (myVertexNode.Contains(vertex))
3657             vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3658           // Update node sections
3659           if (myNodeSections.IsBound(vertex))
3660             myNodeSections.ChangeFind(vertex).Append(section);
3661           else {
3662             TopTools_ListOfShape lsec;
3663             lsec.Append(section);
3664             myNodeSections.Bind(vertex,lsec);
3665           }
3666         }
3667         // Store bound for section
3668         mySectionBound.Bind(section,bound);
3669       }
3670       // Store splitted bound
3671       myBoundSections.Bind(bound,listSections);
3672     }
3673   }
3674 #ifdef DEB
3675   cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3676     << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3677 #endif
3678 }
3679
3680 //=======================================================================
3681 //function : GetSeqEdges
3682 //purpose  : 
3683 //=======================================================================
3684
3685 static void GetSeqEdges(const TopoDS_Shape& edge,
3686                         TopTools_SequenceOfShape& seqEdges,
3687                         TopTools_DataMapOfShapeListOfShape& VertEdge)
3688 {
3689   Standard_Integer numV = 0;
3690   for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3691     TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3692     numV++;
3693     if (VertEdge.IsBound(V1)) {
3694       const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3695       for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3696         TopoDS_Shape edge1 = lIt.Value();
3697         if (edge1.IsSame(edge)) continue;
3698         Standard_Boolean isContained = Standard_False;
3699         Standard_Integer i, index = 1;
3700         for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3701           isContained = seqEdges.Value(i).IsSame(edge1);
3702           if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3703         }
3704         if (!isContained) {
3705           if (numV == 1) seqEdges.InsertBefore(index,edge1);
3706           else seqEdges.InsertAfter(index,edge1);
3707           GetSeqEdges(edge1,seqEdges,VertEdge);
3708         }
3709       }
3710     }
3711   }
3712 }
3713
3714 //=======================================================================
3715 //function : GetFreeWires
3716 //purpose  : 
3717 //=======================================================================
3718
3719 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3720 {
3721   TopTools_DataMapOfShapeListOfShape VertEdge;
3722   TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3723   TopTools_SequenceOfShape seqFreeEdges;
3724   for (; itMap.More(); itMap.Next()) {
3725     TopoDS_Shape edge = itMap.Key();
3726     seqFreeEdges.Append(edge);
3727     for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3728       TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3729       if (VertEdge.IsBound(V1))
3730         VertEdge.ChangeFind(V1).Append(edge);
3731       else {
3732         TopTools_ListOfShape ls;
3733         ls.Append(edge);
3734         VertEdge.Bind(V1,ls);
3735       }
3736     }
3737   }
3738   BRep_Builder B;
3739   Standard_Integer i, j;
3740   for (i = 1; i <= seqFreeEdges.Length(); i++) {
3741     TopTools_SequenceOfShape seqEdges;
3742     TopoDS_Shape edge = seqFreeEdges.Value(i);
3743     if (!MapFreeEdges.Contains(edge)) continue;
3744     seqEdges.Append(edge);
3745     GetSeqEdges(edge,seqEdges,VertEdge);
3746     TopoDS_Wire wire;
3747     B.MakeWire(wire);
3748     for (j = 1; j <= seqEdges.Length(); j++) {
3749       B.Add(wire,seqEdges.Value(j));
3750       MapFreeEdges.Remove(seqEdges.Value(j));
3751     }
3752     seqWires.Append(wire);
3753     if (MapFreeEdges.IsEmpty()) break;
3754   }
3755 }
3756
3757 //=======================================================================
3758 //function :  IsDegeneratedWire
3759 //purpose  :  internal use
3760 //=======================================================================
3761
3762 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3763 {
3764   if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3765   // Get maximal vertices tolerance
3766   TopoDS_Vertex V1,V2;
3767   //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3768   //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3769   Standard_Real wireLength = 0.0;
3770   TopLoc_Location loc;
3771   Standard_Real first, last;
3772   Standard_Integer nume = 0;
3773   Standard_Integer isSmall = 0;
3774   for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3775     nume++;
3776     TopoDS_Shape edge = aIt.Value();
3777     TopoDS_Vertex Ve1,Ve2;
3778     TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3779     if(nume == 1) {
3780       V1 = Ve1;
3781       V2 = Ve2;
3782     }
3783     else {
3784       if(Ve1.IsSame(V1))
3785         V1 = Ve2;
3786       else if(Ve1.IsSame(V2))
3787         V2 = Ve2;
3788       if(Ve2.IsSame(V1))
3789         V1 = Ve1;
3790       else if(Ve2.IsSame(V2))
3791         V2 = Ve1;
3792     }
3793     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3794     if (!c3d.IsNull()) {
3795       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3796       if (!loc.IsIdentity()) {
3797         //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3798         c3d->Transform(loc.Transformation());
3799       }
3800       gp_Pnt pfirst = c3d->Value(first);
3801       gp_Pnt plast = c3d->Value(last);
3802       gp_Pnt pmid = c3d->Value((first +last)*0.5);
3803       Standard_Real length =0;
3804       if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3805         length = pfirst.Distance(plast);
3806       }
3807       else {
3808         GeomAdaptor_Curve cAdapt(c3d);
3809         length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3810       }
3811       Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3812       if(length <= tole) isSmall++;
3813       wireLength += length;
3814     }
3815   }
3816   if(isSmall == nume) return Standard_True;
3817   Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3818   if (wireLength > tol) return Standard_False;
3819   return Standard_True;
3820 }
3821
3822 //=======================================================================
3823 //function :  DegeneratedSection
3824 //purpose  :  internal use
3825 //            create a new degenerated edge if the section is degenerated
3826 //=======================================================================
3827
3828 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3829 {
3830   // Return if section is already degenerated
3831   if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3832
3833   // Retrieve edge curve
3834   TopLoc_Location loc;
3835   Standard_Real first, last;
3836   Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3837   if (c3d.IsNull()) { //gka
3838     BRep_Builder aB;
3839     TopoDS_Edge edge1 = TopoDS::Edge(section);
3840     aB.Degenerated(edge1, Standard_True);
3841     return edge1;
3842   }
3843   if (!loc.IsIdentity()) {
3844     c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3845     c3d->Transform(loc.Transformation());
3846   }
3847
3848   // Test if the new edge is degenerated
3849   TopoDS_Vertex v1,v2;
3850   TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3851   //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3852   //tol = Max(tolerance,tol);
3853
3854   gp_Pnt p1, p2, p3;
3855   p1 = BRep_Tool::Pnt(v1);
3856   p3 = BRep_Tool::Pnt(v2);
3857   c3d->D0(0.5*(first + last),p2);
3858
3859   //Standard_Boolean isDegenerated = Standard_False;
3860   //if (p1.Distance(p3) < tol) {
3861   //GeomAdaptor_Curve cAdapt(c3d);
3862   //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3863   //isDegenerated =  Standard_True; //(length < tol);
3864   //}
3865
3866   TopoDS_Edge edge;
3867   //if (!isDegenerated) return edge;
3868
3869   // processing
3870   BRep_Builder aBuilder;
3871   edge = TopoDS::Edge(section);
3872   edge.EmptyCopy();
3873   if (v1.IsSame(v2)) {      
3874     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3875     aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3876     aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3877   }
3878   else {
3879     TopoDS_Vertex newVertex;
3880     if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3881       newVertex = v1;
3882     else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3883       newVertex = v2;
3884     else {
3885       Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3886       Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3887       Standard_Real newTolerance = Max(d1,d2);
3888       aBuilder.MakeVertex(newVertex, p2, newTolerance);
3889     }
3890     TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3891     aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3892     aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3893   }
3894
3895   BRep_Tool::Range(TopoDS::Edge(section), first, last);
3896   TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3897   aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3898   aBuilder.Degenerated(edge, Standard_True);
3899   Handle(Geom_Curve) aC3dNew;
3900   if (!face.IsNull()) {
3901     Standard_Real af,al;
3902     Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3903     aBuilder.UpdateEdge(edge,aC3dNew,0);
3904     Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3905     if (aC2dn.IsNull())
3906       aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3907   }
3908
3909   return edge;
3910 }
3911
3912 //=======================================================================
3913 //function : EdgeProcessing
3914 //purpose  : modifies :
3915 //                       myNbEdges
3916 //                       myHasMultipleEdge
3917 //                       myHasFreeBound
3918 //           . if multiple edge
3919 //              - length < 100.*myTolerance -> several free edge
3920 //           . if no multiple edge
3921 //              - make the contigous edges sameparameter
3922 //=======================================================================
3923
3924 void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
3925 {
3926   // constructs sectionEdge
3927   TopTools_MapOfShape MapFreeEdges;
3928   TopTools_DataMapOfShapeShape EdgeFace;
3929   Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3930   for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3931     const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3932     const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3933     if (listFaces.Extent() == 1) {
3934       if (myBoundSections.IsBound(bound)) {
3935         TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3936         for (; liter.More(); liter.Next()) {
3937           if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3938             TopoDS_Shape edge = myReShape->Apply(liter.Value());
3939             if (!MapFreeEdges.Contains(edge)) {
3940               TopoDS_Shape face = listFaces.First();
3941               EdgeFace.Bind(edge,face);
3942               MapFreeEdges.Add(edge);
3943             }
3944           }
3945         }
3946       }
3947       else {
3948         if (!myMergedEdges.Contains(bound)) {
3949           TopoDS_Shape edge = myReShape->Apply(bound);
3950           if (!MapFreeEdges.Contains(edge)) {
3951             TopoDS_Shape face = listFaces.First();
3952             EdgeFace.Bind(edge,face);
3953             MapFreeEdges.Add(edge);
3954           }
3955         }
3956       }
3957     }
3958   }
3959
3960   if (!MapFreeEdges.IsEmpty()) {
3961     TopTools_SequenceOfShape seqWires;
3962     GetFreeWires(MapFreeEdges,seqWires);
3963     for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
3964       TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
3965       if (!IsDegeneratedWire(wire)) continue;
3966       for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
3967         TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
3968         TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
3969         TopoDS_Shape face;
3970         if (EdgeFace.IsBound(edge))
3971           face = EdgeFace.Find(edge);
3972         TopoDS_Shape degedge = DegeneratedSection(edge,face);
3973         if (degedge.IsNull()) continue;
3974         if (!degedge.IsSame(edge))
3975           ReplaceEdge(edge,degedge,myReShape);
3976         if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
3977           myDegenerated.Add(degedge);
3978       }
3979     }
3980   }
3981   myMergedEdges.Clear();
3982 }
3983
3984 //=======================================================================
3985 //function : CreateSewedShape
3986 //purpose  : 
3987 //=======================================================================
3988
3989 void BRepBuilderAPI_Sewing::CreateSewedShape()
3990 {
3991   // ---------------------
3992   // create the new shapes
3993   // ---------------------
3994   BRepTools_Quilt aQuilt;
3995   Standard_Boolean isLocal = !myShape.IsNull();
3996   if (isLocal) {
3997     // Local sewing
3998     TopoDS_Shape ns = myReShape->Apply(myShape);
3999     aQuilt.Add(ns);
4000   }
4001   Standard_Integer i;
4002   for (i = 1; i <= myOldShapes.Extent(); i++) {
4003     TopoDS_Shape sh = myOldShapes(i);
4004     if (!sh.IsNull()) {
4005       sh = myReShape->Apply(sh);
4006       myOldShapes(i) = sh;
4007       if (!isLocal) aQuilt.Add(sh);
4008     }
4009   }
4010   TopoDS_Shape aNewShape = aQuilt.Shells();
4011   Standard_Integer numsh = 0;
4012
4013   TopTools_IndexedMapOfShape OldShells;
4014
4015   BRep_Builder aB;
4016   TopoDS_Compound aComp;
4017   aB.MakeCompound(aComp);
4018   for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4019     TopoDS_Shape sh = aExpSh.Value();
4020     Standard_Boolean hasEdges = Standard_False;
4021     if (sh.ShapeType() == TopAbs_SHELL) {
4022       if (myNonmanifold)
4023         hasEdges = !OldShells.Contains(sh);
4024       else {
4025         TopoDS_Shape face;
4026         Standard_Integer numf = 0;
4027         for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4028           face = aExpF.Current();
4029           numf++;
4030         }
4031         if (numf == 1) aB.Add(aComp,face);
4032         else if (numf > 1) aB.Add(aComp,sh);
4033         if (numf) numsh++;
4034       }
4035     }
4036     else if (sh.ShapeType() == TopAbs_FACE) {
4037       if (myNonmanifold) {
4038         TopoDS_Shell ss;
4039         aB.MakeShell(ss);
4040         aB.Add(ss,sh);
4041         sh = ss;
4042         hasEdges = Standard_True;
4043       }
4044       else { aB.Add(aComp,sh); numsh++; }
4045     }
4046     else { aB.Add(aComp,sh); numsh++; }
4047     if (hasEdges) OldShells.Add(sh);
4048   }
4049   // Process collected shells
4050   if (myNonmanifold) {
4051     Standard_Integer nbOldShells = OldShells.Extent();
4052     if (nbOldShells == 1) {
4053       // Single shell - check for single face
4054       TopoDS_Shape sh = OldShells.FindKey(1);
4055       TopoDS_Shape face;
4056       Standard_Integer numf = 0;
4057       for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4058         face = aExpF.Current();
4059         numf++;
4060       }
4061       if (numf == 1) aB.Add(aComp,face);
4062       else if (numf > 1) aB.Add(aComp,sh);
4063       if (numf) numsh++;
4064     }
4065     else if (nbOldShells) {
4066       // Several shells should be merged
4067       TColStd_MapOfInteger IndexMerged;
4068       while (IndexMerged.Extent() < nbOldShells) {
4069         TopoDS_Shell NewShell;
4070         TopTools_MapOfShape NewEdges;
4071         for (i = 1; i <= nbOldShells; i++) {
4072           if (IndexMerged.Contains(i)) continue;
4073           TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4074           if (NewShell.IsNull()) {
4075             BRep_Builder aB;
4076             aB.MakeShell(NewShell);
4077             TopoDS_Iterator aItSS(shell) ;
4078             for( ; aItSS.More(); aItSS.Next())
4079               aB.Add(NewShell,aItSS.Value())
4080               ;
4081             // Fill map of edges
4082             for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4083               TopoDS_Shape edge = eexp.Current();
4084               NewEdges.Add(edge);
4085             }
4086             IndexMerged.Add(i);
4087           }
4088           else {
4089             Standard_Boolean hasSharedEdge = Standard_False;
4090             TopExp_Explorer eexp(shell,TopAbs_EDGE);
4091             for (; eexp.More() && !hasSharedEdge; eexp.Next())
4092               hasSharedEdge = NewEdges.Contains(eexp.Current());
4093             if (hasSharedEdge) {
4094               // Add edges to the map
4095               for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4096                 TopoDS_Shape edge = eexp1.Current();
4097                 NewEdges.Add(edge);
4098               }
4099               // Add faces to the shell
4100               for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4101                 TopoDS_Shape face = fexp.Current();
4102                 aB.Add(NewShell,face);
4103               }
4104               IndexMerged.Add(i);
4105             }
4106           }
4107         }
4108         // Process new shell
4109         TopoDS_Shape face;
4110         Standard_Integer numf = 0;
4111         TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4112         for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4113           face = aExpF.Current();
4114           numf++;
4115         }
4116         if (numf == 1) aB.Add(aComp,face);
4117         else if (numf > 1) aB.Add(aComp,NewShell);
4118         if (numf) numsh++;
4119       }
4120     }
4121   }
4122   if (numsh == 1) {
4123     // Extract single component
4124     TopoDS_Iterator aIt(aComp,Standard_False);
4125     mySewedShape = aIt.Value();
4126   }
4127   else
4128     mySewedShape = aComp;
4129 }
4130
4131 //=======================================================================
4132 //function : CreateOutputInformations
4133 //purpose  : constructs :
4134 //                       myEdgeSections
4135 //                       mySectionBound
4136 //                       myNbFreeEdges
4137 //                       myNbContigousEdges
4138 //                       myNbMultipleEdges
4139 //                       myNbDegenerated
4140 //=======================================================================
4141
4142 void BRepBuilderAPI_Sewing::CreateOutputInformations()
4143 {
4144   // Construct edgeSections
4145   Standard_Integer i;
4146   //TopTools_DataMapOfShapeListOfShape edgeSections;
4147   TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4148   for (i = 1; i <= myBoundFaces.Extent(); i++) {
4149     const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4150     TopTools_ListOfShape lsect;
4151     if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4152     TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4153     for (; aExp.More(); aExp.Next()) {
4154       TopoDS_Shape sec = bound, edge = aExp.Current();
4155       TopTools_ListIteratorOfListOfShape aI(lsect);
4156       for (; aI.More(); aI.Next()) {
4157         const TopoDS_Shape& section = aI.Value();
4158         if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4159       }
4160       if (edgeSections.Contains(edge))
4161         edgeSections.ChangeFromKey(edge).Append(sec);
4162       else {
4163         TopTools_ListOfShape listSec;
4164         listSec.Append(sec);
4165         edgeSections.Add(edge,listSec);
4166       }
4167     }
4168   }
4169
4170   // Fill maps of Free, Contigous and Multiple edges
4171   //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4172   for (i = 1; i <= edgeSections.Extent(); i++) {
4173     const TopoDS_Shape& edge = edgeSections.FindKey(i);
4174     const TopTools_ListOfShape& listSection = edgeSections(i);
4175     if (listSection.Extent() == 1) {
4176       if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4177         myDegenerated.Add(edge);
4178       else
4179         myFreeEdges.Add(edge);
4180     }
4181     else if (listSection.Extent() == 2) {
4182       myContigousEdges.Add(edge,listSection);
4183     }
4184     else {
4185       myMultipleEdges.Add(edge);
4186     }
4187   }
4188
4189   // constructs myContigSectBound
4190   TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4191   for (i = 1; i <= myBoundFaces.Extent(); i++) {
4192     TopoDS_Shape bound = myBoundFaces.FindKey(i);
4193     if (myBoundSections.IsBound(bound)) {
4194       TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4195       for (; iter.More(); iter.Next()) {
4196         TopoDS_Shape section = iter.Value();
4197         if(!myMergedEdges.Contains(section)) continue;
4198         //if (!myReShape->IsRecorded(section)) continue; // section is free
4199         TopoDS_Shape nedge = myReShape->Apply(section);
4200         if (nedge.IsNull()) continue; //szv debug
4201         if (!bound.IsSame(section))
4202           if (myContigousEdges.Contains(nedge))
4203             myContigSecBound.Bind(section, bound);
4204       }
4205     }
4206   }
4207 }
4208
4209 //=======================================================================
4210 //function : ProjectPointsOnCurve
4211 //purpose  : internal use
4212 //=======================================================================
4213
4214 void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4215                                                  const Handle(Geom_Curve)& c3d,
4216                                                  const Standard_Real first,
4217                                                  const Standard_Real last,
4218                                                  TColStd_Array1OfReal& arrDist,
4219                                                  TColStd_Array1OfReal& arrPara,
4220                                                  TColgp_Array1OfPnt& arrProj,
4221                                                  const Standard_Boolean isConsiderEnds) const
4222 {
4223   arrDist.Init(-1.0);
4224
4225   GeomAdaptor_Curve GAC(c3d);
4226   Extrema_ExtPC locProj;
4227   locProj.Initialize(GAC, first, last);
4228   gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4229
4230   for (Standard_Integer i1 = 1; i1 <= arrPnt.Length(); i1++) {
4231     gp_Pnt pt = arrPnt(i1);
4232     Standard_Real worktol = myTolerance;
4233     Standard_Real distF2 = pfirst.SquareDistance(pt);
4234     Standard_Real distL2 = plast.SquareDistance(pt);
4235     Standard_Boolean isProjected = Standard_False;
4236     try {
4237
4238       // Project current point on curve
4239       locProj.Perform(pt);
4240       if (locProj.IsDone() && locProj.NbExt() > 0) {
4241         Standard_Real dist2Min = Min(distF2,distL2);
4242         Standard_Integer ind, indMin = 0;
4243         for (ind = 1; ind <= locProj.NbExt(); ind++) {
4244           Standard_Real dProj2 = locProj.SquareDistance(ind);
4245           if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4246         }
4247         if (indMin) {
4248           isProjected = Standard_True;
4249           Extrema_POnCurv pOnC = locProj.Point(indMin);
4250           Standard_Real paramProj = pOnC.Parameter();
4251           gp_Pnt ptProj = GAC.Value(paramProj);
4252           Standard_Real distProj2 = ptProj.SquareDistance(pt);
4253           if (!locProj.IsMin(indMin)) {
4254             if (Min(distF2,distL2) < dist2Min) {
4255               if (distF2 < distL2) {
4256                 paramProj = first;
4257                 distProj2 = distF2;
4258                 ptProj = pfirst;
4259               }
4260               else {
4261                 paramProj = last;
4262                 distProj2 = distL2;
4263                 ptProj = plast;
4264               }
4265             }
4266           }
4267           if (distProj2 < worktol * worktol) {
4268             arrDist(i1) = sqrt (distProj2);
4269             arrPara(i1) = paramProj;
4270             arrProj(i1) = ptProj;
4271           }
4272         }
4273       }
4274     }
4275     catch (Standard_Failure) {
4276       worktol = MinTolerance();
4277 #ifdef DEB
4278       cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4279       Standard_Failure::Caught()->Print(cout); cout << endl;
4280 #endif
4281     }
4282     if (!isProjected && isConsiderEnds) {
4283       if (Min(distF2,distL2) < worktol * worktol) {
4284         if (distF2 < distL2) {
4285           arrDist(i1) = sqrt (distF2);
4286           arrPara(i1) = first;
4287           arrProj(i1) = pfirst;
4288         }
4289         else {
4290           arrDist(i1) = sqrt (distL2);
4291           arrPara(i1) = last;
4292           arrProj(i1) = plast;
4293         }
4294       }
4295     }
4296   }
4297 }
4298
4299 //=======================================================================
4300 //function : CreateCuttingNodes
4301 //purpose  : internal use
4302 //=======================================================================
4303
4304 void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4305                                                const TopoDS_Shape& bound,
4306                                                const TopoDS_Shape& vfirst,
4307                                                const TopoDS_Shape& vlast,
4308                                                const TColStd_Array1OfReal& arrDist,
4309                                                const TColStd_Array1OfReal& arrPara,
4310                                                const TColgp_Array1OfPnt& arrPnt,
4311                                                TopTools_SequenceOfShape& seqVert,
4312                                                TColStd_SequenceOfReal& seqPara)
4313 {
4314   Standard_Integer i, j, nbProj = MapVert.Extent();
4315
4316   // Reorder projections by distance
4317   TColStd_SequenceOfInteger seqOrderedIndex;
4318   { //szv: Use brackets to destroy local variables
4319     TColStd_SequenceOfReal seqOrderedDistance;
4320     for (i = 1; i <= nbProj; i++) {
4321       Standard_Real distProj = arrDist(i);
4322       if (distProj < 0.0) continue; // Skip vertex if not projected
4323       Standard_Boolean isInserted = Standard_False;
4324       for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4325         isInserted = (distProj < seqOrderedDistance(j));
4326         if (isInserted) {
4327           seqOrderedIndex.InsertBefore(j,i);
4328           seqOrderedDistance.InsertBefore(j,distProj);
4329         }
4330       }
4331       if (!isInserted) {
4332         seqOrderedIndex.Append(i);
4333         seqOrderedDistance.Append(distProj);
4334       }
4335     }
4336   }
4337   nbProj = seqOrderedIndex.Length();
4338   if (!nbProj) return;
4339
4340   BRep_Builder aBuilder;
4341
4342   // Insert two initial vertices (to be removed later)
4343   TColStd_SequenceOfReal seqDist;
4344   TColgp_SequenceOfPnt seqPnt;
4345   { //szv: Use brackets to destroy local variables
4346     // Retrieve bound curve
4347     TopLoc_Location loc;
4348     Standard_Real first,last;
4349     Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4350     if (!loc.IsIdentity()) {
4351       c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4352       c3d->Transform(loc.Transformation());
4353     }
4354     GeomAdaptor_Curve GAC(c3d);
4355     seqVert.Prepend(vfirst); seqVert.Append(vlast);
4356     seqPara.Prepend(first); seqPara.Append(last);
4357     seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4358     seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4359   }
4360
4361   TopTools_DataMapOfShapeShape NodeCuttingVertex;
4362   for (i = 1; i <= nbProj; i++) {
4363
4364     const Standard_Integer index = seqOrderedIndex(i);
4365     Standard_Real disProj = arrDist(index);
4366     gp_Pnt pntProj = arrPnt(index);
4367
4368     // Skip node if already bound to cutting vertex
4369     TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4370     if (NodeCuttingVertex.IsBound(node)) continue;
4371
4372     // Find the closest vertex
4373     Standard_Integer indexMin = 1;
4374     Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4375     for (j = 2; j <= seqPnt.Length(); j++) {
4376       dist = pntProj.Distance(seqPnt(j));
4377       if (dist < distMin) { distMin = dist; indexMin = j; }
4378     }
4379
4380     // Check if current point is close to one of the existent
4381     if (distMin <= Max(disProj*0.1,MinTolerance())) {
4382       // Check distance if close
4383       Standard_Real jdist = seqDist.Value(indexMin);
4384       if (jdist < 0.0) {
4385         // Bind new cutting node (end vertex only)
4386         seqDist.SetValue(indexMin,disProj);
4387         TopoDS_Shape cvertex = seqVert.Value(indexMin);
4388         NodeCuttingVertex.Bind(node,cvertex);
4389       }
4390       else {
4391         // Bind secondary cutting nodes
4392         NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4393       }
4394     }
4395     else {
4396       // Build new cutting vertex
4397       TopoDS_Vertex cvertex;
4398       aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4399       // Bind new cutting vertex
4400       NodeCuttingVertex.Bind(node,cvertex);
4401       // Insert cutting vertex in the sequences
4402       Standard_Real parProj = arrPara(index);
4403       for (j = 2; j <= seqPara.Length(); j++) {
4404         if (parProj <= seqPara.Value(j)) {
4405           seqVert.InsertBefore(j,cvertex);
4406           seqPara.InsertBefore(j,parProj);
4407           seqDist.InsertBefore(j,disProj);
4408           seqPnt.InsertBefore (j,pntProj);
4409           break;
4410         }
4411       }
4412     }
4413   }
4414
4415   // filling map for cutting nodes
4416   TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4417   for (; mit.More(); mit.Next()) {
4418     TopoDS_Shape cnode = mit.Value();
4419     // Skip secondary nodes
4420     if (cnode.IsNull()) continue;
4421     // Obtain vertex node
4422     TopoDS_Shape node = mit.Key();
4423     if (myVertexNode.Contains(cnode)) {
4424       // This is an end vertex
4425       cnode = myVertexNode.FindFromKey(cnode);
4426     }
4427     else {
4428       // Create link: cutting vertex -> node
4429       TopTools_ListOfShape ls;
4430       ls.Append(node);
4431       myCuttingNode.Bind(cnode,ls);
4432     }
4433     // Create link: node -> cutting vertex
4434     if (myCuttingNode.IsBound(node)) {
4435       myCuttingNode.ChangeFind(node).Append(cnode);
4436     }
4437     else {
4438       TopTools_ListOfShape ls;
4439       ls.Append(cnode);
4440       myCuttingNode.Bind(node,ls);
4441     }
4442   }
4443
4444   // Remove two initial vertices
4445   seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4446   seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4447 }
4448
4449 //=======================================================================
4450 //function : CreateSections
4451 //purpose  : internal use
4452 //=======================================================================
4453
4454 void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4455                                            const TopTools_SequenceOfShape& seqNode,
4456                                            const TColStd_SequenceOfReal& seqPara,
4457                                            TopTools_ListOfShape& listEdge)
4458 {
4459   const TopoDS_Edge& sec = TopoDS::Edge(section);
4460   //  TopAbs_Orientation aInitOr = sec.Orientation();
4461
4462
4463   //To keep NM vertices on edge
4464   TopTools_SequenceOfShape aSeqNMVert;
4465   TColStd_SequenceOfReal aSeqNMPars;
4466   findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4467
4468   BRep_Builder aBuilder;
4469
4470   Standard_Real first, last;
4471   BRep_Tool::Range(sec, first, last);
4472
4473   // Create cutting sections
4474   Standard_Real par1, par2;
4475   TopoDS_Shape V1, V2;
4476   Standard_Integer i, len = seqPara.Length() + 1;
4477   for (i = 1; i <= len; i++) {
4478
4479     TopoDS_Edge edge = sec;
4480     edge.EmptyCopy();
4481
4482     if (i == 1) {
4483       par1 = first;
4484       par2 = seqPara(i);
4485       V1 = TopExp::FirstVertex(sec);
4486       V2 = seqNode(i);
4487     }
4488     else if (i == len) {
4489       par1 = seqPara(i-1);
4490       par2 = last;
4491       V1 = seqNode(i-1);
4492       V2 = TopExp::LastVertex(sec);
4493     }
4494     else {
4495       par1 = seqPara(i-1);
4496       par2 = seqPara(i);
4497       V1 = seqNode(i-1);
4498       V2 = seqNode(i);
4499     }
4500
4501     TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4502     TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4503     aTmpShape = V1.Oriented(TopAbs_FORWARD);
4504     aBuilder.Add(aTmpEdge, aTmpShape);
4505     aTmpShape = V2.Oriented(TopAbs_REVERSED);
4506     aBuilder.Add(aTmpEdge, aTmpShape);
4507     aBuilder.Range(aTmpEdge, par1, par2);
4508     //    if(aInitOr == TopAbs_REVERSED)
4509     //      listEdge.Prepend(edge);
4510     //    else
4511
4512     Standard_Integer k =1;
4513     for( ; k <=  aSeqNMPars.Length() ; k++) {
4514       Standard_Real apar = aSeqNMPars.Value(k);
4515       if(apar >= par1 && apar <= par2) {
4516         aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4517         aSeqNMVert.Remove(k);
4518         aSeqNMPars.Remove(k);
4519         k--;
4520       }
4521     }
4522     listEdge.Append(edge);
4523   }
4524
4525   const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4526   if (!listFaces.Extent()) return;
4527
4528   Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4529
4530   // Add cutting pcurves
4531   TopTools_ListIteratorOfListOfShape itf(listFaces);
4532   for (; itf.More(); itf.Next()) {
4533
4534     const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4535
4536     // Retrieve curve on surface
4537     Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4538     Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4539     if (c2d.IsNull()) continue;
4540     Handle(Geom2d_Curve) c2d1;
4541     Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4542
4543     //gka  - Convert to BSpline was commented because
4544     //it is not necessary to create BSpline instead of Lines or cIrcles.
4545     //Besides after conversion circles to BSpline
4546     //it is necessary to recompute parameters of cutting because paramerization of created
4547     //BSpline curve differs from parametrization of circle.
4548
4549     // Convert pcurve to BSpline
4550     /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4551     if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4552     c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4553     }
4554     else {
4555     if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4556     last < (c2d->LastParameter() - Precision::PConfusion())) {
4557     Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4558     c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4559     }
4560     else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4561     }
4562     if (c2dBSP.IsNull()) continue;*/
4563     //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4564
4565     if(isSeam)
4566     {
4567       TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4568
4569       c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4570       if (c2d1.IsNull()) continue;
4571
4572       /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4573       c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4574       }
4575       else {
4576       if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4577       last < (c2d1->LastParameter() - Precision::PConfusion())) {
4578       Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4579       //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4580       }
4581       //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4582
4583       }*/
4584     }
4585
4586     /*first2d = c2dBSP->FirstParameter();
4587     last2d = c2dBSP->LastParameter();
4588
4589     if(!c2dBSP1.IsNull()) {
4590     first2d1 = c2dBSP1->FirstParameter();
4591     last2d1 = c2dBSP1->LastParameter();
4592     }*/
4593
4594     // Update cutting sections
4595     Handle(Geom2d_Curve) c2dNew,c2d1New;
4596     TopTools_ListIteratorOfListOfShape ite(listEdge);
4597     for (; ite.More(); ite.Next()) {
4598
4599       // Retrieve cutting section
4600       const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4601       BRep_Tool::Range(edge, par1, par2);
4602
4603       // Cut BSpline pcurve
4604       // try {
4605       c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4606       //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4607       //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4608       if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4609         c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy()); 
4610         //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4611         //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4612       }
4613       //}
4614       /*catch (Standard_Failure) {
4615       #ifdef DEB
4616       cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4617       Standard_Failure::Caught()->Print(cout); cout << endl;
4618       #endif
4619       Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4620       c2dNew = c2dT;
4621       }*/
4622
4623
4624       if(!isSeam && c2d1New.IsNull())
4625         aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4626       else {
4627         TopAbs_Orientation Ori = edge.Orientation();
4628         if(fac.Orientation() == TopAbs_REVERSED)
4629           Ori = TopAbs::Reverse(Ori);
4630
4631         if(Ori == TopAbs_FORWARD)
4632           aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4633         else
4634           aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4635       }
4636     }
4637   }
4638 }
4639
4640 //=======================================================================
4641 //function : SameParameterShape
4642 //purpose  : 
4643 //=======================================================================
4644
4645 void BRepBuilderAPI_Sewing::SameParameterShape()
4646 {
4647   if (!mySameParameterMode) return;
4648   TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4649   // Le flag sameparameter est a false pour chaque edge cousue
4650   for (; exp.More(); exp.Next()) {
4651     const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4652     try {
4653
4654       BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4655     }
4656     catch (Standard_Failure) {
4657 #ifdef DEB
4658       cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
4659 #endif
4660       continue;
4661     }
4662   }
4663 }