8b26897e673f11e5bc0ec303df92ed8c476d26c6
[occt.git] / src / LocOpe / LocOpe_SplitShape.cxx
1 // File:        LocOpe_SplitShape.cxx
2 // Created:     Tue Jun 27 16:37:40 1995
3 // Author:      Jacques GOUSSARD
4 //              <jag@bravox>
5
6
7 #include <LocOpe_SplitShape.ixx>
8
9 #include <TopTools_ListOfShape.hxx>
10 #include <TopTools_ListIteratorOfListOfShape.hxx>
11 #include <TopTools_MapOfShape.hxx>
12 #include <TopTools_DataMapOfShapeListOfShape.hxx>
13 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
14 #include <TopTools_MapIteratorOfMapOfShape.hxx>
15 #include <TopoDS_Iterator.hxx>
16 #include <TopExp_Explorer.hxx>
17 #include <BRep_Builder.hxx>
18 #include <TopoDS_Vertex.hxx>
19 #include <BRepLib_MakeFace.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepTools.hxx>
22 #include <BRep_Builder.hxx>
23
24 #include <BRepClass_FaceExplorer.hxx>
25 #include <BRepTopAdaptor_FClass2d.hxx>
26 #include <BRepAdaptor_Surface.hxx>
27
28 #include <Geom2d_Curve.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <gp_Dir2d.hxx>
32 #include <TopoDS.hxx>
33 #include <TopExp.hxx>
34 #include <Precision.hxx>
35 #include <BRepTools.hxx>
36 #include <LocOpe.hxx>
37 #include <Standard_ErrorHandler.hxx>
38
39 static Standard_Boolean IsInside(const TopoDS_Face&,
40                                  const TopoDS_Wire&,
41                                  const TopoDS_Wire&);
42
43 static Standard_Boolean IsInside(const TopoDS_Face&,
44                                  const TopoDS_Wire&);
45
46 static void ChoixUV(const TopoDS_Edge&,
47                     const TopoDS_Face&,
48                     const TopTools_MapOfShape&,
49                     TopTools_MapIteratorOfMapOfShape&,
50                     gp_Pnt2d&,
51                     gp_Vec2d&,
52                     const Standard_Real tol);
53
54 inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, 
55                                const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
56 {
57   //  Standard_Real tol = Precision::Confusion();
58   //  return P1.SquareDistance(P2) < 10*tol;
59   //gka
60   Standard_Boolean isSame = Standard_True;
61   if(theBAS.IsUPeriodic())
62     isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5);
63   if(theBAS.IsVPeriodic())
64     isSame = (isSame && (fabs(P1.Y() - P2.Y()) < theBAS.VPeriod() *0.5));
65   return isSame;
66   //return P1.SquareDistance(P2) < tol * tol; //IFV
67 }
68
69
70
71 //=======================================================================
72 //function : Init
73 //purpose  : 
74 //=======================================================================
75
76 void LocOpe_SplitShape::Init(const TopoDS_Shape& S)
77 {
78   myDone = Standard_False;
79   myShape = S;
80   myDblE.Clear();
81   myMap.Clear();
82   Put(myShape);
83 }
84
85
86 //=======================================================================
87 //function : CanSplit
88 //purpose  : 
89 //=======================================================================
90
91 Standard_Boolean LocOpe_SplitShape::CanSplit(const TopoDS_Edge& E) const
92 {
93   if (myDone) {
94     return Standard_False;
95   }
96   if (myMap.IsEmpty()) {
97     return Standard_False;
98   }
99
100   if (!myMap.IsBound(E)) {
101     return Standard_False;
102   }
103
104   // On verifie que l`edge n`appartient pas a un wire deja reconstruit
105   TopExp_Explorer exp;  
106   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMap);
107   for (; itm.More(); itm.Next()) {
108     if (itm.Key().ShapeType() == TopAbs_WIRE && !itm.Value().IsEmpty()) {
109       for (exp.Init(itm.Key(),TopAbs_EDGE); exp.More(); exp.Next()) {
110         if (exp.Current().IsSame(E)) {
111           return Standard_False;
112         }
113       }
114     }
115   }
116   return Standard_True;
117 }
118
119
120 //=======================================================================
121 //function : Add
122 //purpose  : 
123 //=======================================================================
124
125 void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
126                             const Standard_Real P,
127                             const TopoDS_Edge& E)
128 {
129   if (!CanSplit(E)) {
130     Standard_ConstructionError::Raise();
131   }
132
133   BRep_Builder B;
134   TopTools_ListOfShape& le = myMap(E);
135   if (le.IsEmpty()) {
136     le.Append(E);
137   }
138   TopTools_ListIteratorOfListOfShape itl(le);
139   Standard_Real f,l;
140
141   for (; itl.More(); itl.Next()) {
142     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
143     BRep_Tool::Range(edg,f,l);
144     if (P>f && P <l) {
145       break;
146     }
147   }
148   if (!itl.More()) {
149     Standard_ConstructionError::Raise();
150   }
151   TopoDS_Edge edg = TopoDS::Edge(itl.Value());
152   le.Remove(itl);
153   if (V.Orientation() == TopAbs_FORWARD ||
154     V.Orientation() == TopAbs_REVERSED) {
155
156       TopoDS_Shape aLocalShape = edg.EmptyCopied();
157       TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
158       aLocalShape = edg.EmptyCopied();
159       TopoDS_Edge E2 = TopoDS::Edge(aLocalShape);
160       //    TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
161       //    TopoDS_Edge E2 = TopoDS::Edge(edg.EmptyCopied());
162       E1.Orientation(TopAbs_FORWARD);
163       E2.Orientation(TopAbs_FORWARD);
164       TopoDS_Vertex newVtx = V;
165       newVtx.Orientation(TopAbs_REVERSED);
166       B.Add(E1,newVtx);
167       B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V));
168       newVtx.Orientation(TopAbs_FORWARD);
169       B.Add(E2,newVtx);
170       B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V));
171       edg.Orientation(TopAbs_FORWARD);
172       TopExp_Explorer exp;
173       for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
174         //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
175         const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
176         f = BRep_Tool::Parameter(vtx,edg);
177         if (f < P) {
178           B.Add(E1,vtx);
179           B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
180         }
181         else {
182           B.Add(E2,vtx);
183           B.UpdateVertex(vtx,f,E2,BRep_Tool::Tolerance(vtx));
184         }
185       }
186       le.Append(E1);
187       le.Append(E2);
188   }
189   else {
190     TopoDS_Shape aLocalShape = edg.EmptyCopied();
191     TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
192     //    TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
193     TopExp_Explorer exp;
194     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
195       //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
196       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
197       f = BRep_Tool::Parameter(vtx,edg);
198       B.Add(E1,vtx);
199       B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
200     }
201     B.Add(E1,V);
202     B.UpdateVertex(V,P,E1,BRep_Tool::Tolerance(V));
203     le.Append(E1);
204   }
205 }
206
207
208
209 //=======================================================================
210 //function : Add
211 //purpose  : 
212 //=======================================================================
213
214 void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
215                             const TopoDS_Face& F)
216 {
217
218   if (myDone) {
219     Standard_ConstructionError::Raise();
220   }
221
222
223   TopExp_Explorer exp;
224   TopTools_ListOfShape& lf = myMap(F);
225   if (lf.IsEmpty()) {
226     Rebuild(F);
227   }
228   try {
229     OCC_CATCH_SIGNALS
230     if (!LocOpe::Closed(W,F)) {
231       AddOpenWire(W,F);
232     }
233     else {
234       AddClosedWire(W,F);
235     }
236   } catch (Standard_Failure ) {
237 #ifdef DEB
238     cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<endl;
239 #endif
240     return;
241   }
242   // JAG 10.11.95 Codage des regularites
243   BRep_Builder B;
244   for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
245     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
246     if (!BRep_Tool::HasContinuity(edg,F,F)) {
247       B.Continuity(edg,F,F,GeomAbs_CN);
248     }
249   }
250 }
251
252
253
254 //=======================================================================
255 //function : AddClosedWire
256 //purpose  : 
257 //=======================================================================
258
259 void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
260                                       const TopoDS_Face& F)
261 {
262   TopExp_Explorer exp;
263
264   // On cherche la face descendante de F qui continent le wire
265   TopTools_ListOfShape& lf = myMap(F);
266   TopTools_ListIteratorOfListOfShape itl(lf);
267   TopoDS_Wire outerW;
268   for (; itl.More(); itl.Next()) {
269     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
270     /*
271     outerW = BRepTools::OuterWire(fac);
272     if (IsInside(F,W,outerW)) {
273     break;
274     }
275     */
276     if (IsInside(fac,W)) {
277       break;
278     }
279
280   }
281   if (!itl.More()) {
282     Standard_ConstructionError::Raise();
283   }
284
285   BRep_Builder B;
286
287   TopAbs_Orientation orWire = W.Orientation();
288   TopoDS_Shape aLocalFace = F.EmptyCopied();
289   TopoDS_Face newFace = TopoDS::Face(aLocalFace);
290   //  TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
291   newFace.Orientation(TopAbs_FORWARD);
292   B.Add(newFace,W);
293   //  GProp_GProps GP;
294   //  BRepGProp::SurfaceProperties (newFace,GP);
295   //  if (GP.Mass() < 0) {
296   BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
297   if (classif.PerformInfinitePoint() == TopAbs_IN) {
298     //le wire donne defini un trou
299     aLocalFace = F.EmptyCopied();
300     newFace = TopoDS::Face(aLocalFace);
301     //    newFace = TopoDS::Face(F.EmptyCopied());
302     newFace.Orientation(TopAbs_FORWARD);
303     orWire = TopAbs::Reverse(orWire);
304     B.Add(newFace,W.Oriented(orWire));
305   }
306
307   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
308   FaceRef.Orientation(TopAbs_FORWARD);
309   lf.Remove(itl);
310
311   aLocalFace = FaceRef.EmptyCopied();
312   TopoDS_Face newRef = TopoDS::Face(aLocalFace);
313   //  TopoDS_Face newRef = TopoDS::Face(FaceRef.EmptyCopied());
314   newRef.Orientation(TopAbs_FORWARD);
315
316   // On suppose que les edges du wire ont des courbes 2d. 
317   // Comme on ne change pas de surface de base, pas besoin d`UpdateEdge.
318
319   for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
320     exp.More(); exp.Next()) {
321       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
322       if (IsInside(F,wir,W)) {
323         B.Add(newFace,wir);
324       }
325       else {
326         B.Add(newRef,wir);
327       }
328   }
329   B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire)));
330   lf.Append(newRef);
331   lf.Append(newFace);
332
333 }
334
335
336 //=======================================================================
337 //function : AddOpenWire
338 //purpose  : 
339 //=======================================================================
340
341 void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
342                                     const TopoDS_Face& F)
343 {
344   // On cherche la face descendante de F qui continent le wire
345   TopTools_ListOfShape& lf = myMap(F);
346   TopTools_ListIteratorOfListOfShape itl(lf);
347   TopoDS_Vertex Vfirst,Vlast;
348
349   BRepTools::Update(F);
350
351   //  TopExp::Vertices(W,Vfirst,Vlast);
352
353   Standard_Real tolf, toll, tol1;
354
355   TopoDS_Shape aLocalShape = W.Oriented(TopAbs_FORWARD);
356   TopExp::Vertices(TopoDS::Wire(aLocalShape),Vfirst,Vlast);
357   //  TopExp::Vertices(TopoDS::Wire(W.Oriented(TopAbs_FORWARD)),Vfirst,Vlast);
358
359   tolf = BRep_Tool::Tolerance(Vfirst);
360   toll = BRep_Tool::Tolerance(Vlast);
361   tol1 = Max(tolf, toll);
362
363
364   TopExp_Explorer exp,exp2;
365
366   TopoDS_Wire wfirst,wlast;
367   for (; itl.More(); itl.Next()) {
368     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
369     if (!IsInside(fac,W)) {
370       continue;
371     }
372
373     Standard_Boolean ffound = Standard_False;
374     Standard_Boolean lfound = Standard_False;
375     for (exp.Init(fac,TopAbs_WIRE); exp.More(); exp.Next()) {
376       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
377       for (exp2.Init(wir,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
378         if (!ffound && exp2.Current().IsSame(Vfirst)) {
379           ffound = Standard_True;
380           wfirst = wir;
381         }
382         else if (!lfound && exp2.Current().IsSame(Vlast)) {
383           lfound = Standard_True;
384           wlast = wir;
385         }
386         if (ffound && lfound) {
387           break;
388         }
389       }
390       if (exp2.More()) {
391         break;
392       }
393     }
394     if (exp.More()) {
395       break;
396     }
397   }
398   if (!itl.More()) {
399     Standard_ConstructionError::Raise();
400   }
401
402   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
403   FaceRef.Orientation(TopAbs_FORWARD);
404   lf.Remove(itl);
405   BRep_Builder B;
406
407   BRepAdaptor_Surface BAS(FaceRef, Standard_False);
408
409   Standard_Boolean IsPeriodic = BAS.IsUPeriodic() || BAS.IsVPeriodic();
410
411   tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
412
413   if (wfirst.IsSame(wlast)) {
414     // on cree 2 faces en remplacement de itl.Value()
415     // Essai JAG
416
417     for (exp.Init(wfirst,TopAbs_EDGE); exp.More(); exp.Next()) {
418       if (BRep_Tool::IsClosed(TopoDS::Edge(exp.Current()),FaceRef)) {
419         myDblE.Add(exp.Current());
420       }
421     }
422
423     TopAbs_Orientation orient;
424     TopoDS_Wire newW1,newW2;
425     B.MakeWire(newW1);
426     newW1.Orientation(TopAbs_FORWARD);
427     B.MakeWire(newW2);
428     newW2.Orientation(TopAbs_FORWARD);
429
430     Standard_Integer nbE = 0;
431     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
432          exp.More(); exp.Next()) {
433       nbE++;
434       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
435       orient = edg.Orientation();
436       B.Add(newW1,edg);
437       B.Add(newW2,edg.Oriented(TopAbs::Reverse(orient)));
438     }
439
440     TopTools_MapOfShape MapE, PossE;
441     TopTools_MapIteratorOfMapOfShape itm;
442     TopoDS_Vertex vdeb,vfin;
443     Standard_Integer nbPoss;
444
445     // On recherche l`edge contenant Vlast
446     TopoDS_Edge LastEdge;
447     gp_Pnt2d pfirst,plast;
448     gp_Vec2d dlast;
449     Handle(Geom2d_Curve) C2d;
450     Standard_Real f,l;
451
452     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
453          exp.More(); exp.Next()) {
454       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
455       for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
456         if (exp2.Current().IsSame(Vfirst)) {
457           break;
458         }
459       }
460       if (exp2.More()) {
461         LastEdge = edg;
462         LastEdge.Orientation(edg.Orientation());
463         break;
464       }
465     }
466
467     TopoDS_Shape aLocalFace = FaceRef.Oriented(wfirst.Orientation());
468     C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
469     //    C2d = BRep_Tool::CurveOnSurface
470     //      (LastEdge,
471     //       TopoDS::Face(FaceRef.Oriented(wfirst.Orientation())),
472     //       f,l);
473     if (LastEdge.Orientation() == TopAbs_FORWARD) {
474       pfirst = C2d->Value(f);
475     }
476     else {
477       pfirst = C2d->Value(l);
478     }
479
480     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
481          exp.More(); exp.Next()) {
482       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
483       if( nbE>1 && edg.IsSame(LastEdge) )
484         continue;
485       for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
486         if (exp2.Current().IsSame(Vlast)) {
487           break;
488         }
489       }
490       if (exp2.More()) {
491         LastEdge = edg;
492         LastEdge.Orientation(edg.Orientation());
493         break;
494       }
495     }
496     aLocalFace  = FaceRef.Oriented(wfirst.Orientation());
497     C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
498     //    C2d = BRep_Tool::CurveOnSurface
499     //      (LastEdge,
500     //       TopoDS::Face(FaceRef.Oriented(wfirst.Orientation())),
501     //       f,l);
502     if (LastEdge.Orientation() == TopAbs_FORWARD) {
503       C2d->D1(l,plast,dlast);
504       //      plast = C2d->Value(l);
505     }
506     else {
507       //      plast = C2d->Value(f);
508       C2d->D1(f,plast,dlast);
509       dlast.Reverse();
510     }
511
512     Standard_Boolean cond;
513
514     if(IsPeriodic) {
515
516       cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS));
517     }
518     else {
519       cond = !(Vfirst.IsSame(Vlast));
520     }
521
522     while (cond) {
523       PossE.Clear();
524       
525       // On enchaine par la fin
526       for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
527            exp.More(); exp.Next()) {
528         const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
529         if (MapE.Contains(edg) && !myDblE.Contains(edg)) {
530           continue;
531         }
532
533         orient = edg.Orientation();
534         TopExp::Vertices(edg,vdeb,vfin);
535         if (orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) {
536           PossE.Add(edg.Oriented(orient));
537         }
538         else if (orient == TopAbs_REVERSED && Vlast.IsSame(vfin)) {
539           PossE.Add(edg.Oriented(orient));
540         }
541       }
542       nbPoss = PossE.Extent();
543       if (nbPoss == 1) {
544         itm.Initialize(PossE);
545         TopoDS_Shape aLocalFace  = FaceRef.Oriented(wfirst.Orientation());
546         C2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(itm.Key()),
547                                         TopoDS::Face(aLocalFace), f, l);
548         //      C2d = BRep_Tool::CurveOnSurface
549         //        (TopoDS::Edge(itm.Key()),
550         //         TopoDS::Face(FaceRef.Oriented(wfirst.Orientation())),
551         //         f,l);
552         if (itm.Key().Orientation() == TopAbs_FORWARD) {
553           //      plast = C2d->Value(l);
554           C2d->D1(l,plast,dlast);
555         }
556         else {
557           //      plast = C2d->Value(f);
558           C2d->D1(f,plast,dlast);
559           dlast.Reverse();
560         }
561       }
562       else if (nbPoss > 1) {
563         // Faire choix en U,V...
564         TopoDS_Shape aLocalFace  = FaceRef.Oriented(wfirst.Orientation());
565         
566         toll = Max(BAS.UResolution(toll), BAS.VResolution(toll));
567         
568         ChoixUV(LastEdge, TopoDS::Face(aLocalFace), PossE,
569                 itm, plast, dlast, toll);
570         //      ChoixUV(LastEdge,
571         //              TopoDS::Face(FaceRef.Oriented(wfirst.Orientation())),
572         //              PossE,
573         //              itm,
574         //              plast,
575         //              dlast, toll);
576
577       }
578
579       if (nbPoss >= 1) {
580         B.Add(newW1,itm.Key());
581         if (MapE.Contains(itm.Key())) {
582           myDblE.Remove(itm.Key());
583         }
584         else {
585           MapE.Add(itm.Key());
586         }
587         LastEdge = TopoDS::Edge(itm.Key());
588         if (LastEdge.Orientation() == TopAbs_FORWARD) {
589           Vlast = TopExp::LastVertex(LastEdge);
590         }
591         else {
592           Vlast = TopExp::FirstVertex(LastEdge);
593         }
594         
595         toll = BRep_Tool::Tolerance(Vlast);
596         tol1 = Max(tolf, toll);
597         
598       }
599       //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur
600       else{
601         cout<<"erreur Spliter : pas de chainage du wire"<<endl;
602         Standard_ConstructionError::Raise();
603       }
604       //fin MODIF.
605       
606       tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
607       
608       if(IsPeriodic) {
609         cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS));
610       }
611       else {
612         cond = !(Vfirst.IsSame(Vlast));
613       }
614       
615     }
616     
617     for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
618          exp.More(); exp.Next()) {
619       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
620       if (!MapE.Contains(edg)) {
621         B.Add(newW2,edg);
622         MapE.Add(edg);
623       }
624       else if (myDblE.Contains(edg)) {
625         for (itm.Initialize(MapE); itm.More(); itm.Next()) {
626           const TopoDS_Edge& edg2 = TopoDS::Edge(itm.Key());
627           if (edg.IsSame(edg2) && edg.Orientation() != edg2.Orientation()) {
628             B.Add(newW2,edg);
629             myDblE.Remove(edg);
630           }
631         }
632       }
633     }
634     
635     TopoDS_Face newF1,newF2;
636     aLocalFace = FaceRef.EmptyCopied();
637     newF1 = TopoDS::Face(aLocalFace);
638     newF1.Orientation(TopAbs_FORWARD);
639     aLocalFace = FaceRef.EmptyCopied();
640     newF2 = TopoDS::Face(aLocalFace);
641     //    newF2 = TopoDS::Face(FaceRef.EmptyCopied());
642     newF2.Orientation(TopAbs_FORWARD);
643     
644     // modifs JAG 97.05.28
645 #ifdef DEB
646     TopAbs_Orientation orfila;
647 #else
648     TopAbs_Orientation orfila=TopAbs_FORWARD;
649 #endif
650     for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); 
651          exp.More(); exp.Next()) {
652       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
653       if (wir.IsSame(wfirst)) {
654         orfila = exp.Current().Orientation();
655         break;
656       }
657     }
658     
659     B.Add(newF1,newW1.Oriented(orfila));
660     B.Add(newF2,newW2.Oriented(orfila));
661     //    Standard_Boolean exch = Standard_False;
662     BRepTopAdaptor_FClass2d classif(newF1,Precision::PConfusion());
663     if (classif.PerformInfinitePoint() == TopAbs_OUT) {
664       BRepTopAdaptor_FClass2d classi(newF2,Precision::PConfusion());
665       if (classi.PerformInfinitePoint() == TopAbs_IN) {
666         TopoDS_Face tempF = newF2;
667         newF2 = newF1;
668         newF1 = tempF;
669       }
670     }
671     
672     for (exp.ReInit(); exp.More(); exp.Next()) {
673       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
674       if (!wir.IsSame(wfirst)) {
675         //      if (IsInside(F,wir,newW1) || IsInside(F,newW1,wir)) {
676         if (IsInside(newF1, wir)) {
677           B.Add(newF1,wir);
678         }
679         else if (IsInside(newF2, wir)) {
680           B.Add(newF2,wir);
681         }
682         else {
683           // Ce wire est ni dans newF2 ni dans newF1
684           // Peut etre faut il construire une troisieme face
685           cout << "WARNING: LocOpe_SPlitShape : Ce wire est ni dans newF2 ni dans newF1" << endl;
686         }
687       }
688     }
689     lf.Append(newF1);
690     lf.Append(newF2);
691     
692     // Mise a jour des descendants des wires
693     for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
694       TopTools_ListOfShape& ls = myMap(exp.Current());
695       itl.Initialize(ls);
696       for (; itl.More(); itl.Next()) {
697         if (itl.Value().IsSame(wfirst)) {
698           break;
699         }
700       }
701       if (itl.More()) { // on a trouve le wire
702         ls.Remove(itl);
703         ls.Append(newW1);
704         ls.Append(newW2);
705       }
706     }
707   }
708   else {
709     // on ne cree qu`une seule face
710     TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
711     TopoDS_Wire newWire;
712     TopoDS_Face newFace;
713     B.MakeWire(newWire);
714     newWire.Orientation(TopAbs_FORWARD);
715     TopAbs_Orientation orient,orRelat;
716
717     if (wfirst.Orientation() == wlast.Orientation()) {
718       orRelat = TopAbs_FORWARD;
719     }
720     else {
721       orRelat = TopAbs_REVERSED;
722     }
723
724     if (wlast.IsSame(outerW)) {
725       wlast = wfirst;
726       wfirst = outerW;
727     }
728     
729     // Edges de wfirst
730     for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
731          exp.More(); exp.Next()) {
732       B.Add(newWire,TopoDS::Edge(exp.Current()));
733     }
734
735     // Edges de wlast
736     for (exp.Init(wlast.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
737          exp.More(); exp.Next()) {
738       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
739       orient = TopAbs::Compose(edg.Orientation(),orRelat);
740       B.Add(newWire,edg.Oriented(orient));
741     }
742     
743
744     // Edges du wire ajoute, et dans les 2 sens
745     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
746          exp.More(); exp.Next()) {
747       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
748       orient = edg.Orientation();
749       B.Add(newWire,edg.Oriented(orient));
750       B.Add(newWire,edg.Oriented(TopAbs::Reverse(orient)));
751       myDblE.Add(edg.Oriented(orient));
752     }
753     
754     // on refait une face
755
756     TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
757     newFace = TopoDS::Face(aLocalFace);
758     //    newFace = TopoDS::Face(FaceRef.EmptyCopied());
759     FaceRef.Orientation(TopAbs_FORWARD);
760     for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); 
761          exp.More(); exp.Next()) {
762       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
763       if (wir.IsSame(wfirst)) {
764         B.Add(newFace,newWire.Oriented(wir.Orientation()));
765       }
766       else if (!wir.IsSame(wlast)) {
767         B.Add(newFace,wir);
768       }
769     }
770     lf.Append(newFace);
771     
772     // Mise a jour des descendants des wires
773     for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
774       TopTools_ListOfShape& ls = myMap(exp.Current());
775       itl.Initialize(ls);
776       Standard_Boolean touch = Standard_False;
777       while (itl.More()) {
778         if (itl.Value().IsSame(wfirst) || itl.Value().IsSame(wlast)) {
779           ls.Remove(itl);
780           touch = Standard_True;
781         }
782         else {
783           itl.Next();
784         }
785       }
786       if (touch) {
787         ls.Append(newWire);
788       }
789       
790     }
791   }
792 }
793
794
795 //=======================================================================
796 //function : LeftOf
797 //purpose  : 
798 //=======================================================================
799
800 const TopTools_ListOfShape& LocOpe_SplitShape::LeftOf(const TopoDS_Wire& W,
801                                                       const TopoDS_Face& F)
802 {
803   if (myShape.IsNull()) {
804     Standard_NoSuchObject::Raise();
805   }
806
807   TopExp_Explorer exp,expw,expf;
808   exp.Init(myShape,TopAbs_FACE);
809   for (; exp.More(); exp.Next()) {
810     if (exp.Current().IsSame(F)) {
811       break;
812     }
813   }
814   if (!exp.More()) {
815     Standard_NoSuchObject::Raise();
816   }
817   myLeft.Clear();
818
819   const TopoDS_Face& theFace = TopoDS::Face(exp.Current());
820   TopAbs_Orientation orFace = theFace.Orientation();
821   TopTools_ListIteratorOfListOfShape itl,itl2;
822
823   for (expw.Init(W,TopAbs_EDGE); expw.More(); expw.Next()) {
824     const TopoDS_Edge& edg = TopoDS::Edge(expw.Current());
825     for (itl.Initialize(myMap(theFace)); itl.More(); itl.Next()) {
826       TopoDS_Face fac = TopoDS::Face(itl.Value());
827       fac.Orientation(orFace);
828       for (expf.Init(fac,TopAbs_EDGE); expf.More(); expf.Next()) {
829         const TopoDS_Edge& edgbis = TopoDS::Edge(expf.Current());
830         if (edgbis.IsSame(edg) && 
831           edgbis.Orientation() == edg.Orientation()) {
832             for (itl2.Initialize(myLeft); itl2.More(); itl2.Next()) {
833               if (itl2.Value().IsSame(fac)) {
834                 break;
835               }
836             }
837             if (!itl2.More()) { // la face n`est pas deja presente
838               myLeft.Append(fac);
839             }
840             break;
841         }
842       }
843       if (expf.More()) { // face found
844         break;
845       }
846     }
847   }
848   return myLeft;
849 }
850
851
852 //=======================================================================
853 //function : DescendantShapes
854 //purpose  : 
855 //=======================================================================
856
857 const TopTools_ListOfShape& LocOpe_SplitShape::DescendantShapes
858 (const TopoDS_Shape& S)
859 {
860   if (!myDone) {
861     Rebuild(myShape);
862     myDone = Standard_True;
863   }
864 #ifdef DEB
865   if (!myDblE.IsEmpty()) {
866     cout << "Le shape comporte des faces invalides" << endl;
867   }
868 #endif
869   return myMap(S);
870 }
871
872
873
874 //=======================================================================
875 //function : Put
876 //purpose  : 
877 //=======================================================================
878
879 void LocOpe_SplitShape::Put(const TopoDS_Shape& S)
880 {
881   if (!myMap.IsBound(S)) {
882     TopTools_ListOfShape thelist;
883     myMap.Bind(S, thelist);
884     if (S.ShapeType() != TopAbs_VERTEX) {
885       for(TopoDS_Iterator theIterator(S);theIterator.More();
886         theIterator.Next()) {
887           Put(theIterator.Value());
888       }
889     }
890     else {
891       myMap(S).Append(S);
892     }
893   }
894 }
895
896
897 //=======================================================================
898 //function : Rebuild
899 //purpose  : 
900 //=======================================================================
901
902 Standard_Boolean LocOpe_SplitShape::Rebuild(const TopoDS_Shape& S)
903
904 {
905
906   TopTools_ListIteratorOfListOfShape itr(myMap(S));
907   if (itr.More()) {
908     if (itr.Value().IsSame(S)) {
909       return Standard_False;
910     }
911     return Standard_True;
912   }
913   Standard_Boolean rebuild = Standard_False;
914   TopoDS_Iterator it;
915   for(it.Initialize(S); it.More(); it.Next()) {
916     rebuild = Rebuild(it.Value()) || rebuild;
917   }
918
919   if (rebuild) {
920     BRep_Builder B;
921     TopoDS_Shape result = S.EmptyCopied();
922     TopAbs_Orientation orient;
923     for(it.Initialize(S); it.More(); it.Next()) {
924       orient = it.Value().Orientation();
925       for (itr.Initialize(myMap(it.Value())); itr.More(); itr.Next()) {
926         B.Add(result,itr.Value().Oriented(orient));
927       }
928     }
929     myMap(S).Append(result);
930   }
931   else {
932     myMap(S).Append(S);
933   }
934   return rebuild;
935 }
936
937
938
939 //=======================================================================
940 //function : IsInside
941 //purpose  : 
942 //=======================================================================
943
944 static Standard_Boolean IsInside(const TopoDS_Face& F,
945                                  const TopoDS_Wire& W1,
946                                  const TopoDS_Wire& W2)
947 {
948   // Attention, c`est tres boeuf !!!!
949   BRep_Builder B;
950   TopoDS_Shape aLocalShape = F.EmptyCopied();
951   TopoDS_Face newFace = TopoDS::Face(aLocalShape);
952   //  TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
953 #ifdef DEB
954   TopAbs_Orientation orWire =
955 #endif
956     W2.Orientation();
957   newFace.Orientation(TopAbs_FORWARD);
958   B.Add(newFace,W2);
959   //  GProp_GProps GP;
960   //  BRepGProp::SurfaceProperties(newFace,GP);
961   //  if (GP.Mass() < 0) {
962   BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
963   Standard_Boolean Reversed = Standard_False;
964   if (classif.PerformInfinitePoint() == TopAbs_IN) {
965     //le wire donne defini un trou
966     //    newFace = TopoDS::Face(F.EmptyCopied());
967     //    newFace.Orientation(TopAbs_FORWARD);
968     //    orWire = TopAbs::Reverse(orWire);
969     //    B.Add(newFace,W2.Oriented(orWire));
970     Reversed = Standard_True;
971   }
972
973   //  Standard_Real U,V;
974   TopExp_Explorer exp(W1,TopAbs_EDGE);
975   const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
976   TopExp_Explorer exp2(edg,TopAbs_VERTEX);
977   const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
978   Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
979   Standard_Real f,l;
980   Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
981   if(C2d.IsNull()) {
982 #ifdef DEB
983           cout << "Edge is not on surface" <<endl;
984 #endif
985       return Standard_False;
986   }
987   gp_Pnt2d pt2d(C2d->Value(prm));
988   //  BRepClass_FaceClassifier classif(newFace,pt2d,Precision::PConfusion());
989   //  return (classif.State() == TopAbs_IN);
990   if (!Reversed) {
991     return (classif.Perform(pt2d) == TopAbs_IN);
992   }
993   else {
994     return (classif.Perform(pt2d) == TopAbs_OUT);
995   }
996 }
997
998
999 //=======================================================================
1000 //function : IsInside
1001 //purpose  : 
1002 //=======================================================================
1003
1004 static Standard_Boolean IsInside(const TopoDS_Face& F,
1005                                  const TopoDS_Wire& W)
1006 {
1007   // Attention, c`est tres boeuf !!!!
1008   TopExp_Explorer exp(W,TopAbs_EDGE);
1009   for( ; exp.More(); exp.Next()) {
1010     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1011     //  TopExp_Explorer exp2(edg,TopAbs_VERTEX);
1012     //  const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
1013     //  Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
1014     Standard_Real f,l,prm;
1015     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1016     if (!Precision::IsNegativeInfinite(f) && 
1017       !Precision::IsPositiveInfinite(l)) {
1018         prm = (f+l)/2.;
1019     }
1020     else {
1021       if (Precision::IsNegativeInfinite(f) && 
1022         Precision::IsPositiveInfinite(l)){
1023           prm = 0.;
1024       }
1025       else if (Precision::IsNegativeInfinite(f)) {
1026         prm = l-1.;
1027       }
1028       else {
1029         prm = f+1.;
1030       }
1031     }
1032
1033     gp_Pnt2d pt2d(C2d->Value(prm));
1034     //  BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion());
1035     //  return (classif.State() != TopAbs_OUT);
1036     BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion());
1037     Standard_Boolean stat = classif.Perform(pt2d);
1038     //  return (classif.Perform(pt2d) != TopAbs_OUT);
1039     if(stat == TopAbs_OUT) return Standard_False;
1040
1041     if(stat == TopAbs_ON) {
1042       Standard_Integer nbPnt =10;
1043       Standard_Integer nbOut =0,nbIn =0,nbOn=0;
1044       Standard_Integer j =1;
1045       for( ; j<= nbPnt ; j++)
1046       {
1047         //check neighbouring point
1048         //prm = .66 * prm + .34 * l;
1049         prm = f + (l-f)/nbPnt*(j-1);
1050         pt2d = C2d->Value(prm);
1051         stat = classif.Perform(pt2d);
1052         if(stat == TopAbs_OUT ) 
1053           nbOut++;
1054         else if(stat == TopAbs_IN)
1055           nbIn++;
1056         else
1057           nbOn++;
1058       }
1059       if(nbOut > nbIn + nbOn)
1060         return Standard_False;
1061     }
1062   }
1063   return Standard_True;
1064 }
1065
1066
1067 //=======================================================================
1068 //function : ChoixUV
1069 //purpose  : 
1070 //=======================================================================
1071
1072 static void ChoixUV(const TopoDS_Edge& Last,
1073                     const TopoDS_Face& F,
1074                     const TopTools_MapOfShape& Poss,
1075                     TopTools_MapIteratorOfMapOfShape& It,
1076                     gp_Pnt2d& plst,
1077                     gp_Vec2d& dlst,
1078                     const Standard_Real toll)
1079 {
1080
1081   Standard_Real f,l;
1082   //  gp_Pnt2d p2d,psav;
1083   gp_Pnt2d p2d;
1084   gp_Vec2d v2d;
1085
1086   BRepAdaptor_Surface surf(F,Standard_False); // no restriction
1087   //  Standard_Real tol = Precision::PConfusion() //BRep_Tool::Tolerance(Last));
1088
1089   Standard_Real tol;
1090
1091   TopoDS_Vertex vtx;
1092
1093   gp_Dir2d ref2d(dlst);
1094
1095   Handle(Geom2d_Curve) C2d;
1096
1097   Standard_Integer index = 0, imin=0;
1098   Standard_Real  angmax = -M_PI, dist, ang;
1099
1100
1101   for (It.Initialize(Poss); It.More(); It.Next()) {
1102     index++;
1103     C2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(It.Key()),F,f,l);
1104     if (It.Key().Orientation() == TopAbs_FORWARD) {
1105       //      p2d = C2d->Value(f);
1106       C2d->D1(f,p2d,v2d);
1107       vtx = TopExp::FirstVertex(TopoDS::Edge(It.Key()));
1108     }
1109     else {
1110       //      p2d = C2d->Value(l);
1111       C2d->D1(l,p2d,v2d);
1112       v2d.Reverse();
1113       vtx = TopExp::LastVertex(TopoDS::Edge(It.Key()));
1114     }
1115
1116     if (surf.IsUPeriodic())
1117       if ((fabs(p2d.Y() - plst.Y()) <= toll) || 
1118         ((surf.IsVPeriodic())             && 
1119         (fabs(fabs(p2d.Y() - plst.Y()) - surf.VPeriod()) <= toll)))
1120         if (fabs(p2d.X() - plst.X() - surf.UPeriod()) <= toll)
1121           p2d.SetX(p2d.X() - surf.UPeriod());
1122         else if (fabs(plst.X() - p2d.X() - surf.UPeriod()) <= toll)
1123           p2d.SetX(p2d.X() + surf.UPeriod());
1124
1125     if (surf.IsVPeriodic())
1126       if (fabs(p2d.X() - plst.X()) <= toll)
1127         if (fabs(p2d.Y() - plst.Y() - surf.VPeriod()) <= toll)
1128           p2d.SetY(p2d.Y() - surf.VPeriod());
1129         else if (fabs(plst.Y() - p2d.Y() - surf.VPeriod()) <= toll)
1130           p2d.SetY(p2d.Y() + surf.VPeriod());
1131
1132     tol = BRep_Tool::Tolerance(vtx);
1133     tol = Max(surf.UResolution(tol), surf.VResolution(tol));
1134     tol = Max(toll, tol); tol *= tol;
1135
1136     dist = p2d.SquareDistance(plst);
1137
1138     if (!Last.IsSame(It.Key())) {
1139       ang = ref2d.Angle(gp_Dir2d(v2d));
1140     }
1141     else {
1142       ang = -M_PI;
1143     }
1144
1145     //if ((dist < dmin - tol) ||
1146     //(dist <= dmin+tol && ang > angmax)) {
1147     if ((dist < tol)  && (ang > angmax)) {
1148       imin = index;
1149       //      dmin = dist;
1150       angmax = ang;
1151     }
1152   }
1153
1154   for (index = 1, It.Initialize(Poss); It.More(); It.Next()) {
1155     if (index == imin) {
1156       C2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(It.Key()),F,f,l);
1157       if (It.Key().Orientation() == TopAbs_FORWARD) {
1158         //      plst = C2d->Value(l);
1159         C2d->D1(l,plst,dlst);
1160       }
1161       else {
1162         //      plst = C2d->Value(f);
1163         C2d->D1(f,plst,dlst);
1164         dlst.Reverse();
1165       }
1166       break;
1167     }
1168     index++;
1169   }
1170
1171 }