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