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