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 //=======================================================================
TopOpeBRepBuild_CorrectFace2d()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 //=======================================================================
TopOpeBRepBuild_CorrectFace2d(const TopoDS_Face & aFace,const TopTools_IndexedMapOfOrientedShape & anAvoidMap,TopTools_IndexedDataMapOfShapeShape & aMap)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 //=======================================================================
SetMapOfTrans2dInfo(TopTools_IndexedDataMapOfShapeShape & aMap)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 //=======================================================================
MapOfTrans2dInfo()86   TopTools_IndexedDataMapOfShapeShape& TopOpeBRepBuild_CorrectFace2d::MapOfTrans2dInfo ()
87 {
88   return *(TopTools_IndexedDataMapOfShapeShape*) myMap;
89 }
90 //=======================================================================
91 // function :TopOpeBRepBuild_CorrectFace2d::Face
92 // purpose:
93 //=======================================================================
Face() const94   const TopoDS_Face& TopOpeBRepBuild_CorrectFace2d::Face() const
95 {
96   return myFace;
97 }
98 
99 //=======================================================================
100 // function :TopOpeBRepBuild_CorrectFace2d::IsDone
101 // purpose:
102 //=======================================================================
IsDone() const103   Standard_Boolean TopOpeBRepBuild_CorrectFace2d::IsDone() const
104 {
105   return myIsDone;
106 }
107 //=======================================================================
108 // function :TopOpeBRepBuild_CorrectFace2d::ErrorStatus
109 // purpose:
110 //=======================================================================
ErrorStatus() const111   Standard_Integer TopOpeBRepBuild_CorrectFace2d::ErrorStatus() const
112 {
113   return myErrorStatus;
114 }
115 //=======================================================================
116 // function :TopOpeBRepBuild_CorrectFace2d::CorrectedFace
117 // purpose:
118 //=======================================================================
CorrectedFace() const119   const TopoDS_Face& TopOpeBRepBuild_CorrectFace2d::CorrectedFace() const
120 {
121   return myCorrectedFace;
122 }
123 //=======================================================================
124 // function :TopOpeBRepBuild_CorrectFace2d::BuildCopyData
125 // purpose:
126 //=======================================================================
BuildCopyData(const TopoDS_Face & aFace,const TopTools_IndexedMapOfOrientedShape & anAvoidMap,TopoDS_Face & aCopyFace,TopTools_IndexedMapOfOrientedShape & aCopyAvoidMap,const Standard_Boolean aNeedToUsePMap)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 //=======================================================================
CheckFace()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 contains 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 //=======================================================================
ConnectWire(TopoDS_Face & aCopyFace,const TopTools_IndexedMapOfOrientedShape & aCopyAvoidMap,const Standard_Boolean aTryFlag)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 //=======================================================================
Perform()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 contains 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 //=======================================================================
MakeRightWire()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 //=======================================================================
GetP2dFL(const TopoDS_Face & aF,const TopoDS_Edge & anEdge,gp_Pnt2d & P2dF,gp_Pnt2d & P2dL)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 //=======================================================================
MakeHeadList(const TopoDS_Shape & aFirstEdge,TopTools_ListOfShape & HeadList) const648   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 //=======================================================================
CheckList(const TopoDS_Face & aFace,TopTools_ListOfShape & HeadList)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 //=======================================================================
TranslateCurve2d(const TopoDS_Edge & anE,const TopoDS_Face & aFace,const gp_Vec2d & aTrV,Handle (Geom2d_Curve)& aC2DOut)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 //=======================================================================
OuterWire(TopoDS_Wire & anOuterWire) const791   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 //=======================================================================
BndBoxWire(const TopoDS_Wire & aWire,Bnd_Box2d & B2d) const819   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 //=======================================================================
MoveWire2d(TopoDS_Wire & aWire,const gp_Vec2d & aTrV)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 //=======================================================================
MoveWires2d(TopoDS_Wire & anOuterWire)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 //=======================================================================
UpdateEdge(const TopoDS_Edge & ECopy,const Handle (Geom2d_Curve)& C,const TopoDS_Face & F,const Standard_Real Tol)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 //=======================================================================
UpdateEdge(const TopoDS_Edge & ECopy,const Handle (Geom2d_Curve)& C1,const Handle (Geom2d_Curve)& C2,const TopoDS_Face & F,const Standard_Real Tol)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 
1040