0025418: Debug output to be limited to OCC development environment
[occt.git] / src / ShapeFix / ShapeFix_FaceConnect.cxx
1 // Created on: 1999-06-18
2 // Created by: Sergei ZERTCHANINOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <ShapeFix_FaceConnect.ixx>
18
19 #include <Standard_ErrorHandler.hxx>
20 #include <Standard_Failure.hxx>
21
22 #include <TopoDS.hxx>
23 #include <TopoDS_Wire.hxx>
24 #include <TopoDS_Edge.hxx>
25 #include <TopoDS_Vertex.hxx>
26 #include <TopoDS_Iterator.hxx>
27 #include <TopTools_ListOfShape.hxx>
28 #include <TopTools_Array1OfShape.hxx>
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
30 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
31 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
32
33 #include <BRep_Tool.hxx>
34 #include <BRep_Builder.hxx>
35 #include <BRepBuilderAPI_Sewing.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopExp.hxx>
38 #include <gp_Pnt.hxx>
39
40 #include <ShapeBuild_ReShape.hxx>
41
42 #include <ShapeFix_Face.hxx>
43 #include <ShapeFix_Wire.hxx>
44 #include <ShapeAnalysis_Edge.hxx>
45 #include <ShapeAnalysis_WireOrder.hxx>
46 #include <Geom2d_Curve.hxx>
47 #ifdef OCCT_DEBUG
48 #include <TopTools_MapOfShape.hxx>
49 #endif
50
51 //=======================================================================
52 //function : ShapeFix_FaceConnect
53 //=======================================================================
54
55 ShapeFix_FaceConnect::ShapeFix_FaceConnect() {}
56
57 //=======================================================================
58 //function : Connect
59 //purpose  : 
60 //=======================================================================
61
62  Standard_Boolean ShapeFix_FaceConnect::Add(const TopoDS_Face& aFirst,
63                                             const TopoDS_Face& aSecond)
64 {
65   if (!aFirst.IsNull() && !aSecond.IsNull()) {
66     // Process first face
67     if (myConnected.IsBound(aFirst)) {
68       // Find list for the first face
69       TopTools_ListOfShape& theFirstList = myConnected(aFirst);
70       // Append second face to the first list
71       TopTools_ListIteratorOfListOfShape theIter;
72       for ( theIter.Initialize(theFirstList); theIter.More(); theIter.Next() )
73         if (theIter.Value().IsSame(aSecond)) return Standard_True;
74       theFirstList.Append(aSecond);
75     }
76     else {
77       // Append second face to the first list
78       TopTools_ListOfShape theNewFirstList;
79       theNewFirstList.Append(aSecond);
80       myConnected.Bind(aFirst,theNewFirstList);
81     }
82
83     // Process second face if not same
84     if (!aFirst.IsSame(aSecond)) {
85       if (myConnected.IsBound(aSecond)) {
86         // No need to iterate on faces - append first
87         myConnected(aSecond).Append(aFirst);
88       }
89       else {
90         // Append first face to the second list
91         TopTools_ListOfShape theNewSecondList;
92         theNewSecondList.Append(aFirst);
93         myConnected.Bind(aSecond,theNewSecondList);
94       }
95     }
96
97     return Standard_True;
98   }
99
100   return Standard_False;
101 }
102
103 //=======================================================================
104 //function : Build
105 //purpose  : 
106 //=======================================================================
107
108  TopoDS_Shell ShapeFix_FaceConnect::Build (const TopoDS_Shell& shell,
109                                            const Standard_Real sewtoler,
110                                            const Standard_Real fixtoler)
111 {
112   TopoDS_Shell result = shell;
113
114   /***************************************************************
115   / INITIAL PREPARATIONS
116   / Fill map of original free edges,
117   / fill maps of resulting free and shared edges
118   ***************************************************************/
119
120   // Clear maps of free and shared edges
121   myOriFreeEdges.Clear();
122   myResFreeEdges.Clear();
123   myResSharEdges.Clear();
124
125   TopTools_DataMapOfShapeShape theFreeEdges;
126   TopoDS_Shape theEdge, theFace;
127
128   // Fill map of free edges / faces
129   for ( TopoDS_Iterator itf(result); itf.More(); itf.Next() ) {
130     theFace = itf.Value();
131     for ( TopExp_Explorer expe(theFace,TopAbs_EDGE); expe.More(); expe.Next() ) {
132       theEdge = expe.Current();
133       if (theFreeEdges.IsBound(theEdge)) theFreeEdges.UnBind(theEdge);
134       else theFreeEdges.Bind(theEdge,theFace);
135     }
136   }
137
138   // Fill maps of original and resulting edges
139   for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theFEIter( theFreeEdges );
140         theFEIter.More(); theFEIter.Next() ) {
141     // Get pair (face / free edge)
142     theEdge = theFEIter.Key(), theFace = theFEIter.Value();
143     // Process faces with bad connectivities only
144     if (myConnected.IsBound(theFace) &&
145         !BRep_Tool::Degenerated(TopoDS::Edge(theEdge))) {
146       // Add to the map of original free edges
147       if (myOriFreeEdges.IsBound(theFace)) {
148         // Append free edge to the existing list
149         myOriFreeEdges(theFace).Append(theEdge);
150       }
151       else {
152         // Append free edge to the new list
153         TopTools_ListOfShape theNewList;
154         theNewList.Append(theEdge);
155         myOriFreeEdges.Bind(theFace,theNewList);
156       }
157       // Add to the maps of intermediate free and resulting edges
158       if (!myResFreeEdges.IsBound(theEdge)) {
159         TopTools_ListOfShape theFree, theShared;
160         theFree.Append(theEdge);
161         myResFreeEdges.Bind(theEdge,theFree);
162         myResSharEdges.Bind(theEdge,theShared);
163       }
164     }
165   }
166
167   // Clear the temporary map of free edges
168   theFreeEdges.Clear();
169
170 #ifdef OCCT_DEBUG
171   //-------------------------------
172   //szv debug - preparation results
173   //-------------------------------
174   if (!myOriFreeEdges.IsEmpty()) {
175     cout<<endl<<"FACE CONNECT PREPARATION RESULTS:"<<endl;
176     cout<<"---------------------------------"<<endl;
177     Standard_Integer freenum = 0, facenum = 0;
178     for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOFIter( myOriFreeEdges );
179           theOFIter.More(); theOFIter.Next() ) {
180       freenum += theOFIter.Value().Extent();
181       facenum++;
182     }
183     cout<<"TOTAL: "<<facenum<<" faces containing "<<freenum<<" free edges"<<endl;
184   }
185   //-------------------------------
186 #endif
187
188   /***************************************************************
189   / APPLY SEWING ON CONNECTED FACES
190   / Change maps of original free edges and resulting shared edges
191   ***************************************************************/
192
193   if (!myOriFreeEdges.IsEmpty()) {
194
195     // Allocate array of faces to be sewed
196     TopoDS_Shape theFirstFace, theSecondFace;
197     TopTools_Array1OfShape theFacesToSew(1,2);
198     Standard_Integer theNumOfFacesToSew = 0;
199     Standard_Boolean skip_pair = Standard_False;
200
201     TopTools_ListIteratorOfListOfShape theOriginalIter, theResultsIter;
202     TopoDS_Shape theAuxE, theOrigE, theAuxF;
203
204     BRep_Builder theBuilder;
205
206     TopTools_DataMapOfShapeListOfShape theProcessed;
207
208     for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theConnectedIter( myConnected );
209           theConnectedIter.More(); theConnectedIter.Next() ) {
210       // Process first face only if it is in the map of faces / free edges
211       theFirstFace = theConnectedIter.Key();
212       if (myOriFreeEdges.IsBound(theFirstFace)) {
213
214         // Place first face into the array
215         theFacesToSew.SetValue(1,theFirstFace);
216         theNumOfFacesToSew = 1;
217         // Create the list of processed faces
218         TopTools_ListOfShape theProcessedList;
219
220         // Explore the list of connected faces
221         const TopTools_ListOfShape& theConnectedList = theConnectedIter.Value();
222         TopTools_ListIteratorOfListOfShape theConnectedListIter;
223         for ( theConnectedListIter.Initialize(theConnectedList);
224               theConnectedListIter.More(); theConnectedListIter.Next() ) {
225           // Process second face only if it is in the map of faces / free edges
226           theSecondFace = theConnectedListIter.Value();
227           if (myOriFreeEdges.IsBound(theSecondFace)) {
228
229             // Place second face into the array
230             theFacesToSew.SetValue(2,theSecondFace);
231             // Add second face to the list of processed faces
232             theProcessedList.Append(theSecondFace);
233
234             // Skip the pair if already processed
235             skip_pair = Standard_False;
236             if (theProcessed.IsBound(theSecondFace)) {
237               TopTools_ListOfShape& theProcCnxList = theProcessed(theSecondFace);
238               TopTools_ListIteratorOfListOfShape theProcCnxListIter;
239               for ( theProcCnxListIter.Initialize(theProcCnxList);
240                     theProcCnxListIter.More() && !skip_pair; theProcCnxListIter.Next() )
241                 if (theFirstFace.IsSame(theProcCnxListIter.Value()))
242                   skip_pair = Standard_True;
243             }
244             if (!skip_pair) {
245           
246               // Process second face for the pair of different faces only
247               if (theFirstFace.IsSame(theSecondFace)) {
248 #ifdef OCCT_DEBUG
249                 cout<<"Warning: ShapeFix_FaceConnect::Build: Self-connected face"<<endl;
250 #endif
251               }
252               else theNumOfFacesToSew = 2;
253
254               TopTools_DataMapOfShapeShape theSewerWires;
255               BRepBuilderAPI_Sewing theSewer(sewtoler);
256
257               // Prepare set of faces containing free edges
258               Standard_Integer i = 1;
259               for (i=1; i<=theNumOfFacesToSew; i++) {
260                 // Prepare empty face to fill with free edges
261                 TopoDS_Shape theFaceToSew = theFacesToSew(i);
262                 theAuxF = theFaceToSew.EmptyCopied();
263                 // Fill empty face with free edges
264                 for ( theOriginalIter.Initialize(myOriFreeEdges(theFaceToSew));
265                       theOriginalIter.More(); theOriginalIter.Next() ) {
266                   for ( theResultsIter.Initialize(myResFreeEdges(theOriginalIter.Value()));
267                         theResultsIter.More(); theResultsIter.Next() ) {
268                     // Bind free edge to wire to find results later
269                     theAuxE = theResultsIter.Value();
270                     TopoDS_Wire theAuxW;
271                     theBuilder.MakeWire(theAuxW);
272                     theBuilder.Add(theAuxW,theAuxE);
273                     theBuilder.Add(theAuxF,theAuxW);
274                     theSewerWires.Bind(theAuxE,theAuxW);
275                     theSewer.Add(theAuxW);
276                   }
277                 }
278                 // Add constructed face to sewer
279                 theSewer.Add(theAuxF);
280               }
281
282               // Perform sewing on the list of free edges
283               Standard_Boolean sewing_ok = Standard_True;
284               {
285               try { OCC_CATCH_SIGNALS theSewer.Perform(); }
286               catch(Standard_Failure) { sewing_ok = Standard_False; }
287               }
288               if ( sewing_ok )
289                 if (theSewer.SewedShape().IsNull()) sewing_ok = Standard_False;
290
291               if ( sewing_ok ) {
292                 TopTools_DataMapOfShapeShape theResultEdges;
293
294                 // Find modified edges for the faces
295                 for (i=1; i<=theNumOfFacesToSew; i++) {
296                   for ( theOriginalIter.Initialize(myOriFreeEdges(theFacesToSew(i)));
297                         theOriginalIter.More(); theOriginalIter.Next() ) {
298                     // Get original free edge
299                     theOrigE = theOriginalIter.Value();
300                     TopTools_ListOfShape& theOldFreeList = myResFreeEdges(theOrigE);
301                     theResultsIter.Initialize(theOldFreeList);
302                     while ( theResultsIter.More() ) {
303                       theAuxE = theSewerWires(theResultsIter.Value());
304                       // Process modified edges
305                       if (theSewer.IsModified(theAuxE)) {
306                         // Fill map of result edges
307                         for ( TopExp_Explorer expe(theSewer.Modified(theAuxE),TopAbs_EDGE);
308                               expe.More(); expe.Next() ) {
309                           theAuxE = expe.Current();
310                           // Check edge for being shared
311                           if (theResultEdges.IsBound(theAuxE)) {
312                             // Edge was shared - move in results list
313                             myResSharEdges(theResultEdges(theAuxE)).Append(theAuxE);
314                             myResSharEdges(theOrigE).Append(theAuxE);
315                             theResultEdges.UnBind(theAuxE);
316                           }
317                           else theResultEdges.Bind(theAuxE,theOrigE);
318                         }
319                         // Remove modified free edge from the list
320                         theOldFreeList.Remove(theResultsIter);
321                       }
322                       else theResultsIter.Next();
323                     }
324                   }
325                 }
326
327                 // Put free edges back to the lists of results
328                 for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theResIter( theResultEdges );
329                       theResIter.More(); theResIter.Next() ) {
330                   theAuxE = theResIter.Key();
331                   myResFreeEdges(theResIter.Value()).Append(theAuxE);
332                 }
333               }
334             }
335           }
336         }
337
338         // Bind the list of processed faces to the processed face
339         theProcessed.Bind(theFirstFace,theProcessedList);
340       }
341     }
342
343     // Clear the temporary map of processed faces
344     theProcessed.Clear();
345
346 #ifdef OCCT_DEBUG
347     //-------------------------------
348     //szv debug - sewing results
349     //-------------------------------
350     cout<<endl<<"FACE CONNECT SEWING RESULTS:"<<endl;
351     cout<<"----------------------------"<<endl;
352     cout<<"Sewing tolerance was set to "<<sewtoler<<endl;
353     Standard_Integer totfree = 0, totshared = 0;
354     for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOF2Iter( myOriFreeEdges );
355           theOF2Iter.More(); theOF2Iter.Next() ) {
356       TopTools_ListIteratorOfListOfShape theOFL2Iter;
357       for ( theOFL2Iter.Initialize(theOF2Iter.Value());
358             theOFL2Iter.More(); theOFL2Iter.Next() ) {
359         totfree += myResFreeEdges(theOFL2Iter.Value()).Extent();
360         totshared += myResSharEdges(theOFL2Iter.Value()).Extent();
361       }
362     }
363     cout<<"TOTAL: "<<totfree<<" free, "<<totshared<<" shared edges"<<endl;
364     //-------------------------------
365 #endif
366
367     /***************************************************************
368     / PERFORM EDGES REPLACEMENT
369     ***************************************************************/
370
371     TopTools_DataMapOfShapeShape theRepEdges;
372     TopTools_DataMapOfShapeListOfShape theRepVertices;
373     TopTools_DataMapOfShapeShape theOldVertices;
374     TopTools_DataMapOfShapeListOfShape theNewVertices;
375
376     // Replace old edges by resulting ones
377     TopoDS_Wire theNewW;
378     TopoDS_Vertex theOldV1, theOldV2, theNewV1, theNewV2, theNewV;
379     gp_Pnt theOldP1, theOldP2;
380     Standard_Real dist1, dist2, curdist1, curdist2;
381     for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOEIter( myOriFreeEdges );
382           theOEIter.More(); theOEIter.Next() ) {
383       // Iterate on original free edges
384       for ( theOriginalIter.Initialize(theOEIter.Value());
385             theOriginalIter.More(); theOriginalIter.Next() ) {
386         TopoDS_Edge theOldE = TopoDS::Edge(theOriginalIter.Value());
387
388         // Prepare empty wire to add new edges for reshape
389         theBuilder.MakeWire(theNewW);
390
391         // Explore new edges and vertices
392         Standard_Boolean emptywire = Standard_True;
393         for (Standard_Integer i = 1; i<=2; i++) {
394           // Select list of free or shared edges
395           if (i==1) theResultsIter.Initialize(myResFreeEdges(theOldE));
396           else theResultsIter.Initialize(myResSharEdges(theOldE));
397           // Iterate on new edges
398           for ( ; theResultsIter.More(); theResultsIter.Next() ) {
399             theAuxE = theResultsIter.Value();
400             if (!theAuxE.IsSame(theOldE)) {
401               // Add new edge to the wire
402               theBuilder.Add(theNewW,theAuxE);
403               emptywire = Standard_False;
404             }
405           }
406         }
407
408         if (!emptywire) {
409
410           // Get vertices on old and new edges
411           TopExp::Vertices(theOldE,theOldV1,theOldV2);
412           theOldP1 = BRep_Tool::Pnt(theOldV1);
413           theOldP2 = BRep_Tool::Pnt(theOldV2);
414
415           // Process vertices for replacing
416           dist1 = -1.; dist2 = -1.;
417           for ( TopExp_Explorer expv(theNewW,TopAbs_VERTEX);
418                 expv.More(); expv.Next() ) {
419             TopoDS_Vertex theNewVtx = TopoDS::Vertex(expv.Current());
420             gp_Pnt theNewPt = BRep_Tool::Pnt(theNewVtx);
421             curdist1 = theOldP1.Distance(theNewPt);
422             curdist2 = theOldP2.Distance(theNewPt);
423             if (dist1<0 || curdist1<dist1) { dist1 = curdist1; theNewV1 = theNewVtx; }
424             if (dist2<0 || curdist2<dist2) { dist2 = curdist2; theNewV2 = theNewVtx; }
425           }
426
427           // Place results in map for replacing
428           if (!theOldV1.IsSame(theNewV1)) {
429             if (theRepVertices.IsBound(theOldV1)) {
430               TopTools_ListOfShape& theList1 = theRepVertices(theOldV1);
431               TopTools_ListIteratorOfListOfShape theIter1;
432               Standard_Boolean found = Standard_False;
433               for ( theIter1.Initialize(theList1); theIter1.More(); theIter1.Next() )
434                 if (theIter1.Value().IsSame(theNewV1)) { found = Standard_True; break; }
435               if (!found) theList1.Append(theNewV1);
436             }
437             else {
438               TopTools_ListOfShape theNewList1;
439               theNewList1.Append(theNewV1);
440               theRepVertices.Bind(theOldV1,theNewList1);
441             }
442           }
443           if (!theOldV2.IsSame(theNewV2)) {
444             if (theRepVertices.IsBound(theOldV2)) {
445               TopTools_ListOfShape& theList2 = theRepVertices(theOldV2);
446               TopTools_ListIteratorOfListOfShape theIter2;
447               Standard_Boolean found = Standard_False;
448               for ( theIter2.Initialize(theList2); theIter2.More(); theIter2.Next() )
449                 if (theIter2.Value().IsSame(theNewV2)) { found = Standard_True; break; }
450               if (!found) theList2.Append(theNewV2);
451             }
452             else {
453               TopTools_ListOfShape theNewList2;
454               theNewList2.Append(theNewV2);
455               theRepVertices.Bind(theOldV2,theNewList2);
456             }
457           }
458
459           // Bind edge to replace
460           theRepEdges.Bind(theOldE,theNewW);
461         }
462       }
463     }
464
465     if (!theRepEdges.IsEmpty()) {
466
467       Handle(ShapeBuild_ReShape) theReShape = new ShapeBuild_ReShape;
468
469       // Replace edges
470       for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theREIter( theRepEdges );
471             theREIter.More(); theREIter.Next() ) {
472         theReShape->Replace(theREIter.Key()/*.Oriented(TopAbs_FORWARD)*/,
473                             theREIter.Value()/*.Oriented(TopAbs_FORWARD)*/);
474       }
475 //smh#8
476       TopoDS_Shape tmpReShape = theReShape->Apply(result);
477       result = TopoDS::Shell(tmpReShape);
478       if (theReShape->Status(ShapeExtend_OK)) {
479 #ifdef OCCT_DEBUG
480         cout<<"Warning: ShapeFix_FaceConnect::Build: Edges not replaced by ReShape"<<endl;
481 #endif  
482       }
483       else if (theReShape->Status(ShapeExtend_FAIL1)) {
484 #ifdef OCCT_DEBUG
485         cout<<"Error: ShapeFix_FaceConnect::Build: ReShape failed on edges"<<endl;
486 #endif  
487       }
488       else {
489
490         Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire;
491         Handle(ShapeFix_Face) SFF = new ShapeFix_Face;
492         ShapeAnalysis_Edge SAE;
493         Standard_Real f,l;
494         Handle(Geom2d_Curve) c2d;
495         Handle(ShapeExtend_WireData) sewd;
496
497         // Perform necessary fixes on subshapes
498 //smh#8
499         TopoDS_Shape emptyCopiedShell = result.EmptyCopied();
500         TopoDS_Shell theShell = TopoDS::Shell(emptyCopiedShell);
501         for ( TopoDS_Iterator itf1(result); itf1.More(); itf1.Next() ) {
502           TopoDS_Face newface = TopoDS::Face(itf1.Value());
503 //smh#8
504           TopoDS_Shape emptyCopiedFace = newface.EmptyCopied();
505           TopoDS_Face EmpFace = TopoDS::Face(emptyCopiedFace);
506           for ( TopoDS_Iterator itw(newface); itw.More(); itw.Next() ) {
507             if(itw.Value().ShapeType() != TopAbs_WIRE)
508               continue;
509             TopoDS_Wire theWire = TopoDS::Wire(itw.Value());
510
511             sewd = new ShapeExtend_WireData( theWire );
512             ShapeAnalysis_WireOrder SAWO(Standard_False, 0);
513             for (Standard_Integer i = 1; i <= sewd->NbEdges(); i++) {
514
515 //smh#8
516               TopoDS_Shape tmpFace = EmpFace.Oriented(TopAbs_FORWARD);
517               if (!SAE.PCurve(sewd->Edge(i),
518                               TopoDS::Face(tmpFace),
519                               c2d,f,l)) continue;
520               SAWO.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
521             }
522             SAWO.Perform();
523
524             SFW->Load(sewd);
525             SFW->FixReorder(SAWO);
526             SFW->FixReorder();
527
528             SFW->SetFace(EmpFace);
529             SFW->SetPrecision(fixtoler);
530             SFW->SetMaxTolerance(sewtoler);
531
532             SFW->FixEdgeCurves();
533             SFW->FixSelfIntersection();
534             theWire = SFW->Wire();
535             theBuilder.Add(EmpFace,theWire);
536           }
537 // #ifdef AIX  CKY : applies to all platforms
538           SFF->Init(EmpFace);
539 //        SFF->Init(TopoDS::Face(EmpFace));
540
541           TopTools_DataMapOfShapeListOfShape MapWires;
542           MapWires.Clear();
543           if (SFF->FixOrientation(MapWires)) EmpFace = SFF->Face();
544           theBuilder.Add(theShell,EmpFace);
545         }
546         theShell.Closed (BRep_Tool::IsClosed (theShell));
547         result = theShell;
548
549         if (!theRepVertices.IsEmpty()) {
550           
551           // Prepare vertices to replace
552           TopoDS_Shape theOld, theNew, theRep, theAux;
553           for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theRV1Iter( theRepVertices );
554                 theRV1Iter.More(); theRV1Iter.Next() ) {
555             // Get the old vertex, create empty list of replaced vertices
556             theOld = theRV1Iter.Key();
557             TopTools_ListOfShape theNewList;
558             // Explore the list of new vertices
559             TopTools_ListIteratorOfListOfShape theN1Iter;
560             for ( theN1Iter.Initialize(theRV1Iter.Value()); theN1Iter.More(); theN1Iter.Next() ) {
561               theNew = theN1Iter.Value();
562               if (theOldVertices.IsBound(theNew)) {
563                 // Vertex has a replacing vertex in the map
564                 theRep = theOldVertices(theNew);
565                 if (!theRep.IsSame(theOld)) {
566                   // Vertex is not in current list
567                   theOldVertices.Bind(theRep,theOld);
568                   theNewList.Append(theRep);
569                   TopTools_ListIteratorOfListOfShape theN3Iter;
570                   for ( theN3Iter.Initialize(theNewVertices(theRep));
571                         theN3Iter.More(); theN3Iter.Next() ) {
572                     theAux = theN3Iter.Value();
573                     theOldVertices(theAux) = theOld;
574                     theNewList.Append(theAux);
575                   }
576                   theNewVertices.UnBind(theRep);
577                 }
578               }
579               else {
580                 theOldVertices.Bind(theNew,theOld);
581                 theNewList.Append(theNew);
582               }
583             }
584             theNewVertices.Bind(theOld,theNewList);
585           }
586
587           // Update vertices positions and tolerances
588           TopoDS_Vertex theNewVert, theOldVert;
589           for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theRV2Iter( theNewVertices );
590                 theRV2Iter.More(); theRV2Iter.Next() ) {
591             theNewVert = TopoDS::Vertex(theRV2Iter.Key());
592             // Calculate the vertex position
593             gp_Pnt theLBound, theRBound, thePosition;
594             theLBound = theRBound = BRep_Tool::Pnt(theNewVert);
595             TopTools_ListIteratorOfListOfShape theN2Iter;
596             for ( theN2Iter.Initialize(theRV2Iter.Value()); theN2Iter.More(); theN2Iter.Next() ) {
597               thePosition = BRep_Tool::Pnt(TopoDS::Vertex(theN2Iter.Value()));
598               Standard_Real val = thePosition.X();
599               if ( val < theLBound.X() ) theLBound.SetX( val );
600               else if ( val > theRBound.X() ) theRBound.SetX( val );
601               val = thePosition.Y();
602               if ( val < theLBound.Y() ) theLBound.SetY( val );
603               else if ( val > theRBound.Y() ) theRBound.SetY( val );
604               val = thePosition.Z();
605               if ( val < theLBound.Z() ) theLBound.SetZ( val );
606               else if ( val > theRBound.Z() ) theRBound.SetZ( val );
607             }
608             thePosition = gp_Pnt((theLBound.XYZ() + theRBound.XYZ())/2.);
609             Standard_Real theTolerance = 0., curtoler;
610             // Calculate the vertex tolerance
611             for ( theN2Iter.Initialize(theRV2Iter.Value()); theN2Iter.More(); theN2Iter.Next() ) {
612               theOldVert = TopoDS::Vertex(theN2Iter.Value());
613               curtoler = thePosition.Distance(BRep_Tool::Pnt(theOldVert)) +
614                          BRep_Tool::Tolerance(theOldVert);
615               if (curtoler > theTolerance) theTolerance = curtoler;
616             }
617             curtoler = thePosition.Distance(BRep_Tool::Pnt(theNewVert)) +
618                        BRep_Tool::Tolerance(theNewVert);
619             if (curtoler > theTolerance) theTolerance = curtoler;
620             theBuilder.UpdateVertex( theNewVert, thePosition, theTolerance );
621           }
622
623           // Replace vertices
624           theReShape->Clear();
625           for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theNVIter( theOldVertices );
626                 theNVIter.More(); theNVIter.Next() )
627             theReShape->Replace(theNVIter.Key().Oriented(TopAbs_FORWARD),
628                                 theNVIter.Value().Oriented(TopAbs_FORWARD));
629 //smh#8
630           TopoDS_Shape tmpshape = theReShape->Apply(result);
631           result = TopoDS::Shell(tmpshape);
632
633           if (theReShape->Status(ShapeExtend_FAIL1)) {
634 #ifdef OCCT_DEBUG
635             cout<<"Error: ShapeFix_FaceConnect::Build: ReShape failed on vertices"<<endl;
636 #endif  
637           }
638         }
639
640 #ifdef OCCT_DEBUG
641         //-------------------------------
642         //szv debug - reshape results
643         //-------------------------------
644         cout<<endl<<"FACE CONNECT REPLACEMENT RESULTS:"<<endl;
645         cout<<"---------------------------------"<<endl;
646         TopTools_MapOfShape theTmpMap;
647         Standard_Integer toteold = 0, totenew = 0;
648         for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theR1Iter( theRepEdges );
649               theR1Iter.More(); theR1Iter.Next() ) {
650           toteold++;
651           if (!theTmpMap.Contains(theR1Iter.Value())) {
652             theTmpMap.Add(theR1Iter.Value());
653             for ( TopoDS_Iterator itw(TopoDS::Wire(theR1Iter.Value()));
654                   itw.More(); itw.Next() ) totenew++;
655           }
656         }
657         Standard_Integer totvold = 0, totvnew = 0;
658         for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theR2Iter( theOldVertices );
659               theR2Iter.More(); theR2Iter.Next() ) {
660           totvold++;
661           if (!theTmpMap.Contains(theR2Iter.Value())) {
662             theTmpMap.Add(theR2Iter.Value());
663             totvnew++;
664           }
665         }
666         cout<<"TOTAL: "<<toteold<<" edges, "<<totvold<<" vertices replaced by "
667             <<totenew<<" edges, "<<totvnew<<" vertices"<<endl<<endl;
668         //-------------------------------
669 #endif
670
671       }
672     }
673   }
674
675   return result;
676 }
677
678 //=======================================================================
679 //function : Clear
680 //purpose  : 
681 //=======================================================================
682
683  void ShapeFix_FaceConnect::Clear()
684 {
685   myConnected.Clear();
686   myOriFreeEdges.Clear();
687   myResFreeEdges.Clear();
688   myResSharEdges.Clear();
689 }