0030850: Visualization, OpenGl_Text - text within trihedron persistence jitters when...
[occt.git] / src / TopOpeBRepBuild / TopOpeBRepBuild_CorrectFace2d.cxx
1 // Created on: 2000-01-26
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Bnd_Box2d.hxx>
18 #include <BndLib_Add2dCurve.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve2d.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepTopAdaptor_FClass2d.hxx>
24 #include <Geom2d_Curve.hxx>
25 #include <Geom2d_TrimmedCurve.hxx>
26 #include <Geom_Surface.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Vec2d.hxx>
30 #include <Precision.hxx>
31 #include <TopExp.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopLoc_Location.hxx>
34 #include <TopoDS.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Face.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopOpeBRepBuild_CorrectFace2d.hxx>
41 #include <TopOpeBRepBuild_Tools2d.hxx>
42 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
43 #include <TopTools_IndexedMapOfShape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TopTools_ListOfShape.hxx>
46 #include <TopTools_SequenceOfShape.hxx>
47
48 //=======================================================================
49 // function :TopOpeBRepBuild_CorrectFace2d::TopOpeBRepBuild_CorrectFace2d
50 // purpose: 
51 //=======================================================================
52 TopOpeBRepBuild_CorrectFace2d::TopOpeBRepBuild_CorrectFace2d()
53 {
54   myIsDone=Standard_False;
55   myErrorStatus=1;
56   
57 }
58 //=======================================================================
59 // function :TopOpeBRepBuild_CorrectFace2d::TopOpeBRepBuild_CorrectFace2d
60 // purpose: 
61 //=======================================================================
62   TopOpeBRepBuild_CorrectFace2d::TopOpeBRepBuild_CorrectFace2d(const TopoDS_Face& aFace,
63                                                              const TopTools_IndexedMapOfOrientedShape& anAvoidMap,
64                                                              TopTools_IndexedDataMapOfShapeShape& aMap)
65 {
66   myFace=aFace;
67   myAvoidMap=anAvoidMap;
68   myIsDone=Standard_False;
69   myErrorStatus=1;
70   myMap=(Standard_Address) &aMap;
71   
72 }
73 //=======================================================================
74 // function : TopOpeBRepBuild_CorrectFace2d::SetMapOfTrans2dInfo
75 // purpose: 
76 //=======================================================================
77   void TopOpeBRepBuild_CorrectFace2d::SetMapOfTrans2dInfo (TopTools_IndexedDataMapOfShapeShape& aMap)
78
79   myMap=(Standard_Address) &aMap;
80 }
81
82 //=======================================================================
83 // function : TopOpeBRepBuild_CorrectFace2d::MapOfTrans2dInfo
84 // purpose: 
85 //=======================================================================
86   TopTools_IndexedDataMapOfShapeShape& TopOpeBRepBuild_CorrectFace2d::MapOfTrans2dInfo () 
87 {
88   return *(TopTools_IndexedDataMapOfShapeShape*) myMap;
89 }
90 //=======================================================================
91 // function :TopOpeBRepBuild_CorrectFace2d::Face
92 // purpose: 
93 //=======================================================================
94   const TopoDS_Face& TopOpeBRepBuild_CorrectFace2d::Face() const
95 {
96   return myFace;
97 }
98
99 //=======================================================================
100 // function :TopOpeBRepBuild_CorrectFace2d::IsDone
101 // purpose: 
102 //=======================================================================
103   Standard_Boolean TopOpeBRepBuild_CorrectFace2d::IsDone() const
104 {
105   return myIsDone;
106 }
107 //=======================================================================
108 // function :TopOpeBRepBuild_CorrectFace2d::ErrorStatus
109 // purpose: 
110 //=======================================================================
111   Standard_Integer TopOpeBRepBuild_CorrectFace2d::ErrorStatus() const
112 {
113   return myErrorStatus;
114 }
115 //=======================================================================
116 // function :TopOpeBRepBuild_CorrectFace2d::CorrectedFace
117 // purpose: 
118 //=======================================================================
119   const TopoDS_Face& TopOpeBRepBuild_CorrectFace2d::CorrectedFace() const
120 {
121   return myCorrectedFace;
122 }
123 //=======================================================================
124 // function :TopOpeBRepBuild_CorrectFace2d::BuildCopyData
125 // purpose: 
126 //=======================================================================
127   void TopOpeBRepBuild_CorrectFace2d::BuildCopyData(const TopoDS_Face& aFace,
128                                                    const TopTools_IndexedMapOfOrientedShape& anAvoidMap,
129                                                    TopoDS_Face& aCopyFace,
130                                                    TopTools_IndexedMapOfOrientedShape& aCopyAvoidMap,
131                                                    const Standard_Boolean aNeedToUsePMap) 
132 {
133   TopTools_IndexedDataMapOfShapeShape EdMap;
134
135   BRep_Builder BB;
136
137   TopTools_IndexedDataMapOfShapeShape* pMap= 
138       (TopTools_IndexedDataMapOfShapeShape*) myMap;
139   //
140   // 1. Copy myFace =>> myCopyFace
141   TopoDS_Shape aLocalShape = aFace.EmptyCopied();
142   aCopyFace=TopoDS::Face(aLocalShape);
143   //  aCopyFace=TopoDS::Face(aFace.EmptyCopied());
144
145   TopExp_Explorer anExpWires(aFace, TopAbs_WIRE);
146   for (; anExpWires.More(); anExpWires.Next()) {
147     const TopoDS_Wire& W=TopoDS::Wire(anExpWires.Current());
148     
149     aLocalShape = W.EmptyCopied();
150     TopoDS_Wire aWire = TopoDS::Wire(aLocalShape);
151     //    TopoDS_Wire aWire = TopoDS::Wire(W.EmptyCopied());
152     
153     TopExp_Explorer anExpEdges(W, TopAbs_EDGE);
154     for (; anExpEdges.More(); anExpEdges.Next()) {
155       const TopoDS_Edge& E = TopoDS::Edge(anExpEdges.Current());
156     
157       if (EdMap.Contains(E)) {
158         TopoDS_Shape anEdge = EdMap.ChangeFromKey(E);
159         anEdge.Orientation(E.Orientation());
160         BB.Add (aWire, anEdge); 
161         continue;
162       }
163
164       if (aNeedToUsePMap) {
165         if (pMap->Contains(E)) {
166           TopoDS_Shape& anEdge=pMap->ChangeFromKey(E);
167           anEdge.Orientation(E.Orientation());
168           EdMap.Add(E, anEdge);
169           BB.Add (aWire, anEdge);
170           continue;
171         }
172       }
173
174       // add edges
175       aLocalShape = E.EmptyCopied();
176       TopoDS_Shape anEdge = TopoDS::Edge(aLocalShape);
177       //      TopoDS_Shape anEdge = TopoDS::Edge(E.EmptyCopied());
178       
179       EdMap.Add(E, anEdge);
180
181       TopExp_Explorer anExpVertices(E, TopAbs_VERTEX);
182       for (; anExpVertices.More(); anExpVertices.Next()) {
183         const TopoDS_Shape& aV=anExpVertices.Current();
184         BB.Add(anEdge, aV);
185       }
186
187       anEdge.Orientation(E.Orientation());
188       BB.Add (aWire, anEdge);
189     }
190     // Add wires
191     aWire.Orientation(W.Orientation());
192     EdMap.Add(W, aWire);
193
194     BB.Add (aCopyFace, aWire);
195   }
196
197   //
198   // 2. Copy myAvoidMap =>> myCopyAvoidMap
199   Standard_Integer i, aNb;
200   aNb=anAvoidMap.Extent();
201
202   for (i=1; i<=aNb; i++) {
203     const TopoDS_Shape& aSh=anAvoidMap(i);
204     
205     if (EdMap.Contains (aSh)) {
206       TopoDS_Shape& aCopyShape=EdMap.ChangeFromKey(aSh);
207       aCopyShape.Orientation(aSh.Orientation());
208       aCopyAvoidMap.Add(aCopyShape);
209     }
210   }
211   
212   //
213   // 3. Inversed EdMap
214   if (aNeedToUsePMap) {
215     aNb=EdMap.Extent();
216     myEdMapInversed.Clear();
217     for (i=1; i<=aNb; i++) {
218       const TopoDS_Shape& aSh    =EdMap.FindKey(i);
219       const TopoDS_Shape& aShCopy=EdMap.FindFromIndex(i);
220       myEdMapInversed.Add (aShCopy, aSh);
221     }
222   }
223 }
224 //=======================================================================
225 // function :TopOpeBRepBuild_CorrectFace2d::CheckFace
226 // purpose: 
227 //=======================================================================
228   void TopOpeBRepBuild_CorrectFace2d::CheckFace() 
229 {
230   //
231   // I. Is the surface periodic
232   TopLoc_Location aLocF;
233   Handle(Geom_Surface) Surf = BRep_Tool::Surface(myCopyFace, aLocF);
234   if (!(Surf->IsUPeriodic() || Surf->IsVPeriodic())) {
235     myIsDone=Standard_True;
236     myErrorStatus=4;
237     return;
238   }
239
240   //modified by NIZHNY-MZV  Mon Apr 24 11:29:56 2000
241   //don't treat torus surfaces
242   if(Surf->IsUPeriodic() && Surf->IsVPeriodic()) {
243     myIsDone=Standard_True;
244     myErrorStatus=4;
245     return;
246   }
247
248   // 
249   // II. Has each wire at least one "licit" edge
250   TopTools_IndexedMapOfOrientedShape aVoidWires;
251   Standard_Integer i, aNbVoidWires, anEdgeExists=0, priz;
252   TopExp_Explorer aFExp,aWExp;
253   aFExp.Init (myCopyFace, TopAbs_WIRE);
254   for (; aFExp.More(); aFExp.Next()) {
255     const TopoDS_Shape& aWire=aFExp.Current();
256     if (myCopyAvoidMap.Contains(aWire)) {
257       anEdgeExists=1;
258       continue;
259     }
260
261     anEdgeExists=0;  
262     aWExp.Init(aWire, TopAbs_EDGE);
263     for (; aWExp.More(); aWExp.Next()) {
264       TopoDS_Shape anEdge=aWExp.Current();
265       if (myCopyAvoidMap.Contains(anEdge)) {
266         anEdgeExists=1;
267         break;
268       }
269     }
270
271     if (!anEdgeExists) {
272       // This is the wire without any "Right" information
273       aVoidWires.Add(aWire);
274     }
275   }
276
277   // For Void Wires . 
278   // We assume the first edge from the wire is non-movable edge
279   // PKV 24-Feb-2000
280   aNbVoidWires=aVoidWires.Extent();
281   for (i=1; i<=aNbVoidWires; i++) {
282     TopTools_IndexedMapOfShape aEM;
283     TopExp::MapShapes(aVoidWires(i), TopAbs_EDGE, aEM);
284     if (aEM.Extent())
285       myCopyAvoidMap.Add (aEM(1));
286   }
287
288   // III. Check all wires to know  whether they are closed or not 
289   aFExp.Init (myCopyFace, TopAbs_WIRE);
290   for (; aFExp.More(); aFExp.Next()) {
291     myCurrentWire = TopoDS::Wire(aFExp.Current());
292     priz=MakeRightWire ();
293     if (priz) {
294       // This myFace contais a wire (myCurrentWire) that is not closed.
295       myIsDone=Standard_True;
296       myErrorStatus=3; 
297       return;
298     }
299   }
300   
301   //
302   // VI. Check connectability wires in 2d
303   TopoDS_Face aCopyFace;
304   TopTools_IndexedMapOfOrientedShape aCopyAvoidMap;
305   
306   // Coping data 
307   BuildCopyData(myCopyFace, myCopyAvoidMap, aCopyFace, aCopyAvoidMap, Standard_False);
308   
309   aFExp.Init (aCopyFace, TopAbs_WIRE);
310   for (; aFExp.More(); aFExp.Next()) {
311     myCurrentWire = TopoDS::Wire(aFExp.Current());
312     if (!aCopyAvoidMap.Contains(myCurrentWire)) {
313       priz=ConnectWire (aCopyFace, aCopyAvoidMap, Standard_True);
314       if (priz) {
315         myIsDone=Standard_True;
316         myErrorStatus=6; 
317         return;
318       }
319     }
320   }
321
322   // Face seems to be OK
323 }
324 //=======================================================================
325 // function : TopOpeBRepBuild_CorrectFace2d::ConnectWire
326 // purpose: 
327 //=======================================================================
328   Standard_Integer TopOpeBRepBuild_CorrectFace2d::ConnectWire (TopoDS_Face& aCopyFace,
329                                                               const TopTools_IndexedMapOfOrientedShape& aCopyAvoidMap,
330                                                               const Standard_Boolean aTryFlag)
331 {
332   BRep_Builder BB;
333   //
334   // 1.Make right order
335   Standard_Integer priz;
336   priz=MakeRightWire ();
337   if (priz) return priz;
338   //
339   // 2. Define the First Edge on the Wire from aCopyAvoidMap
340   Standard_Integer i, aNbEdges=0, aNbAvoidEdgesOnWire;
341   Standard_Real aDMax=0, aR;
342
343   TopExp_Explorer aWExp; 
344   TopoDS_Edge  aFEdge;
345   TopoDS_Shape aFirstEdge;
346   TopTools_IndexedMapOfOrientedShape anAvoidMap;
347   
348   aWExp.Init(myCurrentWire, TopAbs_EDGE);
349   for (; aWExp.More(); aWExp.Next(), aNbEdges++) {
350     TopoDS_Shape anEdge=aWExp.Current(); 
351     if (aCopyAvoidMap.Contains(anEdge))
352       anAvoidMap.Add(anEdge);
353   }
354
355   if (aNbEdges==1)                    // nothing to do with this wire.
356     return 0; 
357
358   aNbAvoidEdgesOnWire=anAvoidMap.Extent();
359   if (aNbAvoidEdgesOnWire==aNbEdges) // nothing to do. all edges on wire are good.
360     return 0; 
361
362   // if  at least one  non-degenerated edge exists 
363   // among anAvoidMap set it as aFirstEdge
364   priz=0;
365   for (i=1; i<=aNbAvoidEdgesOnWire; i++) {
366     const TopoDS_Edge& anEdge=TopoDS::Edge(anAvoidMap(i));
367     if (!BRep_Tool::Degenerated(anEdge)) {
368       aFirstEdge=anEdge;
369       priz=1;
370       break;
371     }
372   }
373
374   
375   if (!priz) {
376     // All of anAvoidMap edges are degenerated
377     // So take the edge with max dist. between 
378     //First and Last 2d points as the First edge
379     //if(aNbAvoidEdgesOnWire != 1)
380      // return 1; //in case of several degenerated edges we cannot connect wire by right way
381     for (i=1; i<=aNbAvoidEdgesOnWire; i++) {
382       gp_Pnt2d PF, PL;
383       const TopoDS_Edge& aDegenEdge=TopoDS::Edge(anAvoidMap(i));
384       GetP2dFL(aCopyFace, aDegenEdge, PF, PL);
385       aR=PF.Distance(PL);
386       if ((aR - aDMax) > 1e-7) {
387         aDMax=aR;
388         aFirstEdge=anAvoidMap(i);
389       }
390     }
391   }
392
393   
394   
395   //
396   // 3. Build HeadList (from myOrderedWireList), where aFirstEdge will be the first
397   TopTools_ListOfShape HeadList;
398   MakeHeadList(aFirstEdge, HeadList);
399   //
400   // 4. Check HeadList to provide toward point-arrow direction
401 //modified by NIZNHY-PKV Mon Apr 24 14:43:20 2000 f
402   //CheckList (HeadList);
403   //modified by NIZNHY-PKV Tue Apr 25 12:08:29 2000CheckList (aCopyFace, HeadList);
404 //modified by NIZNHY-PKV Mon Apr 24 14:43:24 2000t
405   //
406   // 5. Connect Edges
407   TopTools_IndexedMapOfShape anEdMap;
408   gp_Pnt2d PF, PL, PA, PB, PA1, PB1;
409   Handle(Geom2d_Curve) aTrCF, aTrCR, aTrC;
410   Standard_Real aD, aDTolerance=Precision::Confusion();
411
412   TopTools_SequenceOfShape aSeqEdges;
413   
414   TopTools_ListIteratorOfListOfShape anIt;
415   anIt.Initialize(HeadList);
416   for (; anIt.More(); anIt.Next()) 
417     aSeqEdges.Append(anIt.Value());
418   aNbEdges=aSeqEdges.Length();
419
420   //
421   // First Edge
422   TopoDS_Edge aFstEdge=TopoDS::Edge(aSeqEdges(1));
423   GetP2dFL(aCopyFace, aFstEdge, PA, PB);
424   PA1=PA; 
425   PB1=PB;
426
427   for (i=2; i<=aNbEdges; i++) {
428     TopoDS_Edge anEdge= TopoDS::Edge(aSeqEdges(i));
429     GetP2dFL(aCopyFace, anEdge, PF, PL);
430     
431     aD=PF.Distance(PB);
432     if (aD<aDTolerance)  {
433       PA=PF; PB=PL;
434       continue; // nothing to do with the edge cose it already connected
435     }
436     
437     // tralslation's  vector
438     gp_Vec2d aTrV(PF, PB);
439
440     //Begin modified by NIZHNY-MZV  Mon Mar 27 16:04:04 2000
441     //translation vector must be equal to 2PI*n or it is wrong wire
442     Standard_Real U = aTrV.X();
443     Standard_Real V = aTrV.Y();
444
445     BRepAdaptor_Surface BAS(aCopyFace);
446     Standard_Boolean UP = BAS.IsUPeriodic();
447     Standard_Boolean VP = BAS.IsVPeriodic();
448
449     Standard_Boolean nonPU = (fabs(U) < 1e-7) ? Standard_True : Standard_False;
450     Standard_Boolean nonPV = (fabs(V) < 1e-7) ? Standard_True : Standard_False;
451
452     if(!nonPU && UP) {
453       Standard_Real dU = fmod(fabs(U), 2*M_PI);
454       nonPU = (dU > 1e-7 && (2*M_PI - dU > 1e-7)) ? Standard_True : Standard_False;
455     }
456     
457     if(!nonPV && VP) {
458       Standard_Real dV = fmod(fabs(V), 2*M_PI);
459       nonPV = (dV > 1e-7 && (2*M_PI - dV > 1e-7)) ? Standard_True : Standard_False;
460     }
461
462 //    printf("(fmod(fabs(U), 2*M_PI) =%lf\n", (fmod(fabs(U), 2*M_PI)));
463 //    printf(" (fmod(fabs(V), 2*M_PI) > 1e-7)=%lf\n", (fmod(fabs(V), 2*M_PI)));
464     
465     if(nonPU && nonPV && !BRep_Tool::Degenerated(anEdge))
466       return 1;
467     //End modified by NIZHNY-MZV  Mon Mar 27 16:04:11 2000
468
469     if (BRep_Tool::IsClosed(anEdge, aCopyFace)) {
470       // a. Closed edge <--->
471       if (anEdMap.Contains(anEdge)) continue;
472       anEdMap.Add(anEdge); 
473       
474       TopAbs_Orientation anOri = anEdge.Orientation();
475       
476       TopoDS_Edge anEF, anER;
477       if (anOri==TopAbs_FORWARD) {
478         anEF=anEdge;
479         TopoDS_Shape aLocalShape = anEdge.Reversed();
480         anER=TopoDS::Edge(aLocalShape);
481         //      anER=TopoDS::Edge(anEdge.Reversed());
482       }
483       
484       else {
485         anER=anEdge;
486         TopoDS_Shape aLocalShape = anEdge.Reversed();
487         anEF=TopoDS::Edge(aLocalShape);
488         //      anEF=TopoDS::Edge(anEdge.Reversed());
489       }
490       
491       TranslateCurve2d (anEF, aCopyFace, aTrV, aTrCF);
492       TranslateCurve2d (anER, aCopyFace, aTrV, aTrCR);
493
494       if (aTryFlag) // Use Builder in a trying case
495         BB.UpdateEdge(anEdge, aTrCF, aTrCR, aCopyFace, myFaceTolerance);
496
497       else          // Use "False-Builder" otherwise
498         UpdateEdge(anEdge, aTrCF, aTrCR, aCopyFace, myFaceTolerance);
499
500     }
501     
502     else {
503       // b. Usual Edge
504       TranslateCurve2d (anEdge, aCopyFace, aTrV, aTrC);
505       
506       if (aTryFlag) 
507         BB.UpdateEdge(anEdge, aTrC, aCopyFace, myFaceTolerance);
508       else 
509         UpdateEdge(anEdge, aTrC, aCopyFace, myFaceTolerance);
510     }
511     
512     GetP2dFL(aCopyFace, anEdge, PF, PL);
513     
514     PA=PF;  
515     PB=PL;
516
517     ////////////////////////////////////////////
518     // In case of a trying we check the first 
519     // and last 2d point of the contour  
520     if (aTryFlag) {
521       if (i==aNbEdges) {
522         aD=PA1.Distance(PB);
523         if (aD>aDTolerance)
524           return 1;
525       }
526     }
527     ////////////////////////////////////////////
528     
529   } //end of for (i=2; i<=aNbEdges; i++)
530   
531   return 0;
532 }
533
534
535 //=======================================================================
536 // function :TopOpeBRepBuild_CorrectFace2d::Perform
537 // purpose: 
538 //=======================================================================
539   void TopOpeBRepBuild_CorrectFace2d::Perform() 
540 {
541   /////////////
542   // 0. 
543   myCopyAvoidMap.Clear();
544   BuildCopyData(myFace, myAvoidMap, myCopyFace, myCopyAvoidMap, Standard_True);
545   /////////////
546
547   myCorrectedFace=myCopyFace;
548   myCorrectedFace.Orientation(myCopyFace.Orientation());
549   myFaceTolerance=BRep_Tool::Tolerance(myCopyFace);
550   //
551   // 1. Check the input face first
552   CheckFace ();
553   if (myIsDone)
554     return ;
555
556   //
557   // 2. Make all wires connected 
558   Standard_Integer  priz;
559   TopExp_Explorer aFExp;
560
561   aFExp.Init (myCopyFace, TopAbs_WIRE);
562   for (; aFExp.More(); aFExp.Next()) {
563     myCurrentWire = TopoDS::Wire(aFExp.Current());
564     if (!myCopyAvoidMap.Contains(myCurrentWire)) {  
565       priz=ConnectWire (myCopyFace, myCopyAvoidMap, Standard_False);
566       if (priz) {
567         // This myFace contais a wire (myCurrentWire) that is not closed.
568         myIsDone=Standard_False;
569         myErrorStatus=3; 
570         return;
571       }
572     }
573   }
574   // 
575   // 3. Define Outer Wire
576   TopoDS_Wire anOuterWire;
577   priz=OuterWire (anOuterWire);
578   if (priz) {
579     myIsDone=Standard_False;
580     myErrorStatus=5; // can't find outer wire 
581     return;
582   }
583   //
584   // 4. Moving the anOuterWire and other wires in 2d space
585   MoveWires2d(anOuterWire);
586
587   myIsDone=Standard_True;
588   myErrorStatus=0; 
589 }
590
591 //=======================================================================
592 // function : TopOpeBRepBuild_CorrectFace2d::MakeRightWire
593 // purpose: 
594 //=======================================================================
595   Standard_Integer TopOpeBRepBuild_CorrectFace2d::MakeRightWire ()
596 {
597   Standard_Integer aNbEdgesReally=0;
598   myOrderedWireList.Clear();
599  
600   //1. Real amount of the edges on aWire
601   TopExp_Explorer aWExp;
602   aWExp.Init(myCurrentWire, TopAbs_EDGE);
603   for (; aWExp.More(); aWExp.Next()) aNbEdgesReally++;
604   
605   //2. We'll use TopOpeBRepBuild_Tools::Path
606   TopTools_ListOfShape aL;
607   TopOpeBRepBuild_Tools2d::Path (myCurrentWire, aL);
608   if (aL.Extent()!=aNbEdgesReally) {
609     myErrorStatus=4;
610     return 1;
611   }
612
613   //Begin modified by NIZNHY-PKV Tue Apr 25 12:04:45 2000
614   //from path we obtained list in reverse order, so to have right wire
615   //we need to reverse it
616   TopTools_ListOfShape aFL;
617   TopTools_ListIteratorOfListOfShape lit(aL);
618   for(; lit.More(); lit.Next())
619     aFL.Prepend(lit.Value());
620
621   myOrderedWireList=aFL;
622   //End modified by NIZNHY-PKV Tue Apr 25 12:06:45 2000
623   return 0;
624 }
625
626 //=======================================================================
627 // function : TopOpeBRepBuild_CorrectFace2d::GetP2dFL
628 // purpose: 
629 //=======================================================================
630   void TopOpeBRepBuild_CorrectFace2d::GetP2dFL (const TopoDS_Face& aF, const TopoDS_Edge& anEdge, 
631                                                gp_Pnt2d& P2dF, gp_Pnt2d& P2dL)
632 {
633   Standard_Real aFirst, aLast;
634   const Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (anEdge, aF, aFirst, aLast);
635   C2d->D0 (aFirst, P2dF);
636   C2d->D0 (aLast , P2dL);
637   if (anEdge.Orientation()==TopAbs_REVERSED) {
638     gp_Pnt2d P2dTmp;
639     P2dTmp=P2dF; P2dF=P2dL; P2dL=P2dTmp;
640   }
641
642
643
644 //=======================================================================
645 // function :TopOpeBRepBuild_CorrectFace2d::MakeHeadList
646 // purpose: 
647 //=======================================================================
648   void TopOpeBRepBuild_CorrectFace2d::MakeHeadList(const TopoDS_Shape& aFirstEdge,
649                                                   TopTools_ListOfShape& HeadList) const
650 {
651   TopoDS_Shape aFE = aFirstEdge;
652   TopTools_ListOfShape aTailList;
653   TopTools_ListIteratorOfListOfShape anIt;
654   Standard_Integer aFlag=0;
655
656   anIt.Initialize(myOrderedWireList);
657   for (; anIt.More(); anIt.Next()) {
658     const TopoDS_Shape& anEdge=anIt.Value();
659     //modified by NIZHNY-MZV  Mon Mar 27 11:40:00 2000
660     if(aFE.IsNull() && !BRep_Tool::Degenerated(TopoDS::Edge(anEdge)))
661       aFE = anEdge;
662     if (anEdge==aFE) aFlag=1; //turn the switch ON
663     if (aFlag) HeadList.Append(anEdge);
664   }
665   
666   anIt.Initialize(myOrderedWireList);
667   for (; anIt.More(); anIt.Next()) {
668     const TopoDS_Shape& anEdge=anIt.Value();
669     if (anEdge==aFE) break;
670     aTailList.Append(anEdge);
671   }
672   HeadList.Append(aTailList);
673 }
674 //=======================================================================
675 // function :TopOpeBRepBuild_CorrectFace2d::CheckList
676 // purpose: 
677 //=======================================================================
678   void TopOpeBRepBuild_CorrectFace2d::CheckList (const TopoDS_Face& aFace,
679                                                  TopTools_ListOfShape&  HeadList)
680 {
681   TopAbs_Orientation r1;
682   Standard_Real aDTolerance=Precision::Confusion();
683   TopTools_SequenceOfShape aSeq;
684   TopTools_ListIteratorOfListOfShape anIt(HeadList);
685   for (; anIt.More(); anIt.Next()) {
686     aSeq.Append(anIt.Value());
687   }
688
689   r1=aSeq(1).Orientation();
690   Standard_Integer i, aNb=aSeq.Length();
691 //modified by NIZNHY-PKV Mon Apr 24 14:43:57 2000f
692   Standard_Boolean aFirstCheck=Standard_False;
693   if (r1==TopAbs_REVERSED ) {
694     // when the orientation of the first edge is Revesed, 
695     // and when everything in 2d is Ok :
696     // if at least one Forward edge  exists in the List 
697     // we consider that no necessity to reverse 
698     // the list (aFirstCheck=Standard_True) .
699     
700     Standard_Real aD;
701     gp_Pnt2d PF, PL, PA, PB;
702     
703     
704     TopoDS_Edge aFstEdge=TopoDS::Edge(aSeq(1));
705     GetP2dFL(aFace, aFstEdge, PA, PB);
706     for (i=2; i<=aNb; i++) {
707       TopoDS_Edge anEdge= TopoDS::Edge(aSeq(i));
708       GetP2dFL(aFace, anEdge, PF, PL);
709       
710       aD=PF.Distance(PB);
711       if (aD<aDTolerance)  {
712         PA=PF; PB=PL;
713         if (anEdge.Orientation()==TopAbs_FORWARD) {
714           aFirstCheck=Standard_True;
715           break;
716         }
717       }
718     }
719   }
720 //modified by NIZNHY-PKV Mon Apr 24 14:43:59 2000t
721
722   r1=aSeq(1).Orientation();
723
724   TopoDS_Vertex aV1R, aV2F;
725   
726   TopoDS_Edge aFirstEdge=TopoDS::Edge(aSeq(1));
727   TopExp_Explorer anExp;
728   anExp.Init (aFirstEdge, TopAbs_VERTEX);
729   for (; anExp.More(); anExp.Next()) {
730     const TopoDS_Shape& aV1=anExp.Current();
731     if (aV1.Orientation()==TopAbs_REVERSED){
732       aV1R=TopoDS::Vertex(aV1);
733       break;
734     }
735   }
736
737   TopoDS_Edge aSecondEdge=TopoDS::Edge(aSeq(2));
738   anExp.Init (aSecondEdge, TopAbs_VERTEX);
739   for (; anExp.More(); anExp.Next()) {
740     const TopoDS_Shape& aV1=anExp.Current();
741     if (aV1.Orientation()==TopAbs_FORWARD){
742       aV2F=TopoDS::Vertex(aV1);
743       break;
744     }
745   }
746   
747   gp_Pnt P1, P2;
748   P1=BRep_Tool::Pnt(aV1R);
749   P2=BRep_Tool::Pnt(aV2F);
750
751   
752   //modified by NIZNHY-PKV Mon Apr 24 13:24:06 2000 f
753   Standard_Real dist=P1.Distance(P2);
754   if (
755       (!(dist < aDTolerance) && r1==TopAbs_FORWARD)||
756       //(r1==TopAbs_REVERSED)) { 
757      (!aFirstCheck && r1==TopAbs_REVERSED)
758       ) {
759     //modified by NIZNHY-PKV Mon Apr 24 14:28:06 2000 t
760     // We have to reverse the order in list 
761     aSeq.Append(aFirstEdge);
762     HeadList.Clear();
763     aNb=aSeq.Length();
764     for (i=aNb; i>1; i--) { 
765       HeadList.Append(aSeq(i));
766     }
767   }
768 }
769
770 //=======================================================================
771 // function :TopOpeBRepBuild_CorrectFace2d::TranslateCurve2d
772 // purpose: 
773 //=======================================================================
774   void TopOpeBRepBuild_CorrectFace2d::TranslateCurve2d(const TopoDS_Edge& anE,
775                                                       const TopoDS_Face& aFace, 
776                                                       const gp_Vec2d& aTrV, 
777                                                       Handle(Geom2d_Curve)& aC2DOut)
778 {
779   Standard_Real aFirst, aLast;
780   Handle(Geom2d_Curve) C2d=BRep_Tool::CurveOnSurface (anE, aFace, aFirst, aLast);
781   Handle(Geom2d_Curve) aTrC;
782   aTrC = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
783   Handle(Geom2d_TrimmedCurve) newC2D = new Geom2d_TrimmedCurve(aTrC, aFirst, aLast);
784   newC2D -> Translate(aTrV);
785   aC2DOut=newC2D;
786 }
787 //=======================================================================
788 // function :TopOpeBRepBuild_CorrectFace2d::OuterWire
789 // purpose: 
790 //=======================================================================
791   Standard_Integer TopOpeBRepBuild_CorrectFace2d::OuterWire(TopoDS_Wire& anOuterWire) const
792 {
793   TopLoc_Location Loc;
794   Handle(Geom_Surface) Surf = BRep_Tool::Surface(TopoDS::Face(myCorrectedFace), Loc);
795
796   TopExp_Explorer ex(myCorrectedFace, TopAbs_WIRE);
797   for (; ex.More(); ex.Next()) {
798     const TopoDS_Wire& aWire=TopoDS::Wire(ex.Current());
799
800     TopoDS_Face newFace;
801     BRep_Builder BB;
802     BB.MakeFace(newFace, Surf, Loc, myFaceTolerance);
803     BB.Add(newFace, aWire);
804     
805     BRepTopAdaptor_FClass2d aClass2d(newFace, myFaceTolerance);
806     TopAbs_State aState=aClass2d.PerformInfinitePoint();
807     if (aState==TopAbs_OUT) {
808       anOuterWire=aWire;
809       return 0;
810     }
811   }
812   return 1; // such wire is not found
813 }
814
815 //=======================================================================
816 // function :TopOpeBRepBuild_CorrectFace2d::BndBoxWire
817 // purpose: 
818 //=======================================================================
819   void TopOpeBRepBuild_CorrectFace2d::BndBoxWire(const TopoDS_Wire& aWire,
820                                                 Bnd_Box2d& B2d) const
821 {
822   Bnd_Box2d aB2d;
823   TopExp_Explorer aWEx (aWire, TopAbs_EDGE);
824   for (; aWEx.More(); aWEx.Next()) {
825     const TopoDS_Edge& anEdge = TopoDS::Edge(aWEx.Current());
826     Standard_Real aTolE = BRep_Tool::Tolerance(anEdge); 
827     BRepAdaptor_Curve2d aBAC2d (anEdge,myCorrectedFace);
828     BndLib_Add2dCurve::Add(aBAC2d, aTolE, aB2d);
829   }
830   B2d=aB2d;
831 }
832
833 //=======================================================================
834 // function : TopOpeBRepBuild_CorrectFace2d::MoveWire2d
835 // purpose: 
836 //=======================================================================
837   void TopOpeBRepBuild_CorrectFace2d::MoveWire2d (TopoDS_Wire& aWire, 
838                                                  const gp_Vec2d& aTrV)
839 {
840   if (aTrV.Magnitude()<Precision::Confusion()) 
841     return;
842   
843   Standard_Integer i, aNbEdges;
844   TopTools_SequenceOfShape aSeqEdges;
845   TopTools_IndexedMapOfShape anEdMap;
846   Handle(Geom2d_Curve) aTrCF, aTrCR, aTrC;
847   
848   TopExp_Explorer aWExp;
849
850   aWExp.Init(aWire, TopAbs_EDGE);
851   for (; aWExp.More(); aWExp.Next()) {
852     aSeqEdges.Append(aWExp.Current());
853   }
854   aNbEdges=aSeqEdges.Length();
855
856   //
857   // First Edge
858   for (i=1; i<=aNbEdges; i++) {
859     TopoDS_Edge anEdge= TopoDS::Edge(aSeqEdges(i));
860     if (BRep_Tool::IsClosed(anEdge, myCorrectedFace)) {
861       // a. Closed edge <--->
862       if (anEdMap.Contains(anEdge)) continue;
863       anEdMap.Add(anEdge); 
864       
865       TopAbs_Orientation anOri = anEdge.Orientation();
866       
867       TopoDS_Edge anEF, anER;
868
869       if (anOri==TopAbs_FORWARD) {
870         anEF=anEdge;
871         TopoDS_Shape aLocalShape = anEdge.Reversed();
872         anER=TopoDS::Edge(aLocalShape);
873         //      anER=TopoDS::Edge(anEdge.Reversed());
874       }
875       
876       else {
877         anER=anEdge;
878         TopoDS_Shape aLocalShape = anEdge.Reversed();
879         anEF=TopoDS::Edge(aLocalShape);
880         //      anEF=TopoDS::Edge(anEdge.Reversed());
881       }
882       
883       TranslateCurve2d (anEF, myCorrectedFace, aTrV, aTrCF);
884       TranslateCurve2d (anER, myCorrectedFace, aTrV, aTrCR);
885       UpdateEdge(anEdge, aTrCF, aTrCR, myCorrectedFace, myFaceTolerance);
886     }
887     
888     else {
889       // b. Usual Edge
890       TranslateCurve2d (anEdge, myCorrectedFace, aTrV, aTrC);
891       UpdateEdge(anEdge, aTrC, myCorrectedFace, myFaceTolerance);
892     }
893   } //end of for (i=1; i<=aNbEdges; i++)
894 }
895 //=======================================================================
896 // function : TopOpeBRepBuild_CorrectFace2d::MoveWires2d
897 // purpose: 
898 //=======================================================================
899   void TopOpeBRepBuild_CorrectFace2d::MoveWires2d (TopoDS_Wire& anOuterWire)
900
901   Bnd_Box2d B2d, B2dOuterWire;
902   Standard_Real OuterU1,OuterV1,OuterU2,OuterV2, x, a, TwoPI;
903   Standard_Integer b, k;
904   gp_Vec2d aTrV;
905
906   TwoPI=2.*M_PI;
907
908   BndBoxWire(anOuterWire, B2dOuterWire);
909   B2dOuterWire.Get(OuterU1,OuterV1,OuterU2,OuterV2);
910   
911   a=.5*(OuterU1+OuterU2);
912   b=Standard_Integer(-a/TwoPI);
913   k=(a<0.)? 1 : 0;
914   x=(b+k)*TwoPI;
915   //
916   // 1. Move the Outer Wire to [0, 2*PI]
917   aTrV.SetCoord (x, 0.);
918   MoveWire2d (anOuterWire, aTrV);
919  
920   BndBoxWire(anOuterWire, B2dOuterWire);
921   B2dOuterWire.Get(OuterU1,OuterV1,OuterU2,OuterV2);
922   //
923   // 2. Move all other wires into bounding box of the Outer Wire
924   TopExp_Explorer aFExp;
925   aFExp.Init (myCorrectedFace, TopAbs_WIRE);
926   for (; aFExp.More(); aFExp.Next()) {
927     myCurrentWire = TopoDS::Wire(aFExp.Current());
928     if (myCurrentWire!=anOuterWire) {
929       BndBoxWire(myCurrentWire, B2d);
930       Standard_Real u1,v1,u2,v2;
931       B2d.Get(u1,v1,u2,v2);
932       
933       if (B2d.IsOut(B2dOuterWire)) {
934         //printf(" Need to Move\n" );
935         a=u1-OuterU1;
936         b=Standard_Integer(-a/TwoPI);
937         k= (a<0.) ? 1 : 0;
938         x=(b+k)*TwoPI;
939         aTrV.SetCoord (x, 0.);
940         MoveWire2d (myCurrentWire, aTrV);
941       }
942     }
943   }
944 }
945 //=======================================================================
946 // function : TopOpeBRepBuild_CorrectFace2d::UpdateEdge
947 // purpose: 
948 //=======================================================================
949   void TopOpeBRepBuild_CorrectFace2d::UpdateEdge (const TopoDS_Edge& ECopy,
950                                                  const Handle(Geom2d_Curve)& C,
951                                                  const TopoDS_Face& F,
952                                                  const Standard_Real Tol) 
953 {
954   BRep_Builder BB;
955   
956   TopTools_IndexedDataMapOfShapeShape* pMap= 
957     (TopTools_IndexedDataMapOfShapeShape*) myMap;
958   
959   // E is the Original Edge from Original Face.
960   if (myEdMapInversed.Contains(ECopy)) {
961     const TopoDS_Shape& E=myEdMapInversed.FindFromKey(ECopy);
962
963     if (!pMap->Contains(E)) { 
964       TopExp_Explorer anExp;
965       
966       TopoDS_Shape anEdge=E.EmptyCopied();
967       
968       anExp.Init(E, TopAbs_VERTEX);
969       for (; anExp.More(); anExp.Next()) {
970         const TopoDS_Shape& aV=anExp.Current();
971         BB.Add(anEdge, aV);
972       }
973       
974       BB.UpdateEdge(TopoDS::Edge(anEdge), C, F, Tol);
975       pMap->Add(E, anEdge);
976       //printf("pMap->Extent()=%d\n", pMap->Extent());
977     }
978     
979     else {
980       TopoDS_Shape& anEdge=pMap->ChangeFromKey(E);
981       BB.UpdateEdge(TopoDS::Edge(anEdge), C, F, Tol); 
982     }
983   }
984
985   BB.UpdateEdge (ECopy, C, F, Tol);
986 }
987
988
989 //=======================================================================
990 // function : TopOpeBRepBuild_CorrectFace2d::UpdateEdge
991 // purpose: 
992 //=======================================================================
993   void TopOpeBRepBuild_CorrectFace2d::UpdateEdge (const TopoDS_Edge& ECopy,
994                                                  const Handle(Geom2d_Curve)& C1,
995                                                  const Handle(Geom2d_Curve)& C2,
996                                                  const TopoDS_Face& F,
997                                                  const Standard_Real Tol) 
998 {
999   BRep_Builder BB;
1000   
1001   TopTools_IndexedDataMapOfShapeShape* pMap= 
1002     (TopTools_IndexedDataMapOfShapeShape*) myMap;
1003   
1004   // E is the Original Edge from Original Face.
1005   if (myEdMapInversed.Contains(ECopy)) {
1006     const TopoDS_Shape& E=myEdMapInversed.FindFromKey(ECopy);
1007     
1008     if (!pMap->Contains(E)) {
1009       TopoDS_Shape anEdge=E.EmptyCopied();
1010       TopExp_Explorer anExp;
1011       anExp.Init(E, TopAbs_VERTEX);
1012       for (; anExp.More(); anExp.Next()) {
1013         const TopoDS_Shape& aV=anExp.Current();
1014         BB.Add(anEdge, aV);
1015       }
1016       BB.UpdateEdge(TopoDS::Edge(anEdge), C1, C2, F, Tol);
1017       pMap->Add(E, anEdge);
1018       //printf("pMap->Extent()=%d\n", pMap->Extent());
1019     }
1020     
1021     else {
1022       TopoDS_Shape& anEdge=pMap->ChangeFromKey(E);
1023       BB.UpdateEdge(TopoDS::Edge(anEdge), C1, C2, F, Tol);
1024     }
1025   }
1026   
1027   BB.UpdateEdge (ECopy, C1, C2, F, Tol);
1028 }
1029
1030 //
1031 // Description for ErrorStatus
1032 // ErrorStatus=0 : All is done;
1033 // ErrorStatus=1 : Nothing is done;
1034 // ErrorStatus=2 : The wire doesn't contain any licit edges and the wire is not closed;
1035 // ErrorStatus=3 : The face contains a wire that is not connectable
1036 // ErrorStatus=4 : The base surface is not periodic;
1037 // ErrorStatus=5 : an outer wir can not be found;
1038 // ErrorStatus=6 : Wrong  connectability of a wire in 2d
1039