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