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