54a44a106152f49f085159828c5da5ea25a00408
[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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <BRepClass_FaceExplorer.hxx>
22 #include <BRepLib_MakeFace.hxx>
23 #include <BRepLib_MakeWire.hxx>
24 #include <BRepTools.hxx>
25 #include <BRepTools_WireExplorer.hxx>
26 #include <BRepTopAdaptor_FClass2d.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <gp_Dir2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <LocOpe.hxx>
32 #include <LocOpe_SplitShape.hxx>
33 #include <Precision.hxx>
34 #include <Standard_ConstructionError.hxx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <Standard_NoSuchObject.hxx>
37 #include <StdFail_NotDone.hxx>
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Iterator.hxx>
44 #include <TopoDS_Shape.hxx>
45 #include <TopoDS_Vertex.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
48 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
49 #include <TopTools_DataMapOfShapeInteger.hxx>
50 #include <TopTools_DataMapOfShapeListOfShape.hxx>
51 #include <TopTools_DataMapOfShapeShape.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include <TopTools_ListOfShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
56 #include <TopTools_MapIteratorOfMapOfShape.hxx>
57 #include <TopTools_MapOfOrientedShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
59
60 static Standard_Boolean IsInside(const TopoDS_Face&,
61                                  const TopoDS_Wire&,
62                                  const TopoDS_Wire&);
63
64 static Standard_Boolean IsInside(const TopoDS_Face&,
65                                  const TopoDS_Wire&);
66
67 static void GetDirection(const TopoDS_Edge&,
68                          const TopoDS_Face&,
69                          Standard_Real&,
70                          gp_Pnt2d&,
71                          gp_Vec2d&);
72
73 static void ChoixUV(const TopoDS_Edge&,
74                     const TopoDS_Face&,
75                     const TopTools_IndexedMapOfShape&,
76                     TopoDS_Edge&,
77                     gp_Pnt2d&,
78                     gp_Vec2d&,
79                     const Standard_Real tol);
80
81 static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
82                                     const TopoDS_Vertex&,
83                                     const TopoDS_Face&,
84                                     const TopTools_ListOfShape&);
85
86 inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, 
87                                const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
88 {
89   //  Standard_Real tol = Precision::Confusion();
90   //  return P1.SquareDistance(P2) < 10*tol;
91   //gka
92   Standard_Boolean isSame = Standard_True;
93   if(theBAS.IsUPeriodic())
94     isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5);
95   if(theBAS.IsVPeriodic())
96     isSame = (isSame && (fabs(P1.Y() - P2.Y()) < theBAS.VPeriod() *0.5));
97   return isSame;
98   //return P1.SquareDistance(P2) < tol * tol; //IFV
99 }
100
101
102
103 //=======================================================================
104 //function : Init
105 //purpose  : 
106 //=======================================================================
107
108 void LocOpe_SplitShape::Init(const TopoDS_Shape& S)
109 {
110   myDone = Standard_False;
111   myShape = S;
112   myDblE.Clear();
113   myMap.Clear();
114   Put(myShape);
115 }
116
117
118 //=======================================================================
119 //function : CanSplit
120 //purpose  : 
121 //=======================================================================
122
123 Standard_Boolean LocOpe_SplitShape::CanSplit(const TopoDS_Edge& E) const
124 {
125   if (myDone) {
126     return Standard_False;
127   }
128   if (myMap.IsEmpty()) {
129     return Standard_False;
130   }
131
132   if (!myMap.IsBound(E)) {
133     return Standard_False;
134   }
135
136   // On verifie que l`edge n`appartient pas a un wire deja reconstruit
137   TopExp_Explorer exp;  
138   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMap);
139   for (; itm.More(); itm.Next()) {
140     if (itm.Key().ShapeType() == TopAbs_WIRE && !itm.Value().IsEmpty()) {
141       for (exp.Init(itm.Key(),TopAbs_EDGE); exp.More(); exp.Next()) {
142         if (exp.Current().IsSame(E)) {
143           return Standard_False;
144         }
145       }
146     }
147   }
148   return Standard_True;
149 }
150
151
152 //=======================================================================
153 //function : Add
154 //purpose  : 
155 //=======================================================================
156
157 void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
158                             const Standard_Real P,
159                             const TopoDS_Edge& E)
160 {
161   if (!CanSplit(E)) {
162     Standard_ConstructionError::Raise();
163   }
164
165   BRep_Builder B;
166   TopTools_ListOfShape& le = myMap(E);
167   if (le.IsEmpty()) {
168     le.Append(E);
169   }
170   TopTools_ListIteratorOfListOfShape itl(le);
171   Standard_Real f,l;
172
173   for (; itl.More(); itl.Next()) {
174     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
175     BRep_Tool::Range(edg,f,l);
176     if (P>f && P <l) {
177       break;
178     }
179   }
180   if (!itl.More()) {
181     Standard_ConstructionError::Raise();
182   }
183   TopoDS_Edge edg = TopoDS::Edge(itl.Value());
184   le.Remove(itl);
185   if (V.Orientation() == TopAbs_FORWARD ||
186     V.Orientation() == TopAbs_REVERSED) {
187
188       TopoDS_Shape aLocalShape = edg.EmptyCopied();
189       TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
190       aLocalShape = edg.EmptyCopied();
191       TopoDS_Edge E2 = TopoDS::Edge(aLocalShape);
192       //    TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
193       //    TopoDS_Edge E2 = TopoDS::Edge(edg.EmptyCopied());
194       E1.Orientation(TopAbs_FORWARD);
195       E2.Orientation(TopAbs_FORWARD);
196       TopoDS_Vertex newVtx = V;
197       newVtx.Orientation(TopAbs_REVERSED);
198       B.Add(E1,newVtx);
199       B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V));
200       newVtx.Orientation(TopAbs_FORWARD);
201       B.Add(E2,newVtx);
202       B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V));
203       edg.Orientation(TopAbs_FORWARD);
204       TopExp_Explorer exp;
205       for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
206         //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
207         const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
208         f = BRep_Tool::Parameter(vtx,edg);
209         if (f < P) {
210           B.Add(E1,vtx);
211           B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
212         }
213         else {
214           B.Add(E2,vtx);
215           B.UpdateVertex(vtx,f,E2,BRep_Tool::Tolerance(vtx));
216         }
217       }
218       le.Append(E1);
219       le.Append(E2);
220   }
221   else {
222     TopoDS_Shape aLocalShape = edg.EmptyCopied();
223     TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
224     //    TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
225     TopExp_Explorer exp;
226     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
227       //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
228       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
229       f = BRep_Tool::Parameter(vtx,edg);
230       B.Add(E1,vtx);
231       B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
232     }
233     B.Add(E1,V);
234     B.UpdateVertex(V,P,E1,BRep_Tool::Tolerance(V));
235     le.Append(E1);
236   }
237 }
238
239 //=======================================================================
240 //function : Add
241 //purpose  : adds the list of wires on the face <F>
242 //=======================================================================
243
244 void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
245                             const TopoDS_Face& F)
246 {
247
248   if (myDone) {
249     Standard_ConstructionError::Raise();
250   }
251
252   TopTools_ListOfShape& lf = myMap(F);
253   if (lf.IsEmpty()) {
254     Rebuild(F);
255   }
256
257   // On cherche la face descendante de F qui continent le wire
258   lf = myMap(F);
259   TopTools_ListIteratorOfListOfShape itl(lf);
260   TopoDS_Vertex Vfirst,Vlast;
261
262   BRepTools::Update(F);
263
264   for (; itl.More(); itl.Next())
265   {
266     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
267     Standard_Boolean AllWiresInside = Standard_True;
268     TopTools_ListIteratorOfListOfShape itwires(Lwires);
269     for (; itwires.More(); itwires.Next())
270     {
271       const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value());
272       if (!IsInside(fac, aWire))
273       {
274         AllWiresInside = Standard_False;
275         break;
276       }
277     }
278     if (AllWiresInside)
279       break;
280   }
281   if (!itl.More()) {
282     Standard_ConstructionError::Raise();
283   }
284
285   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
286   FaceRef.Orientation(TopAbs_FORWARD);
287   lf.Remove(itl);
288
289   TopTools_ListOfShape NewWires;
290
291   TopTools_DataMapOfShapeInteger SectionsTimes;
292   for (itl.Initialize(Lwires); itl.More(); itl.Next())
293     SectionsTimes.Bind(itl.Value(), 2);
294   
295   TopTools_ListOfShape BreakVertices;
296   TopTools_ListOfShape BreakOnWires;
297
298   TopTools_DataMapOfShapeShape VerWireMap;
299   Standard_Integer i;
300   TopExp_Explorer ExploF, ExploW;
301   for (itl.Initialize(Lwires); itl.More(); itl.Next())
302   {
303     const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value());
304     TopoDS_Vertex Ver [2];
305     TopExp::Vertices(aSection, Ver[0], Ver[1]);
306     for (i = 0; i < 2; i++)
307     {
308       if (VerWireMap.IsBound(Ver[i]))
309         continue;
310       for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
311       {
312         const TopoDS_Shape& aWire = ExploF.Current();
313         TopoDS_Shape aVer;
314         for (ExploW.Init(aWire, TopAbs_VERTEX); ExploW.More(); ExploW.Next())
315         {
316           aVer = ExploW.Current();
317           if (aVer.IsSame(Ver[i]))
318             break;
319         }
320         if (aVer.IsSame(Ver[i]))
321         {
322           VerWireMap.Bind(aVer, aWire);
323           break;
324         }
325       }
326     }
327   }  
328   
329   TopTools_DataMapOfShapeListOfShape VerSecMap;
330   for (itl.Initialize(Lwires); itl.More(); itl.Next())
331   {
332     const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value());
333     TopoDS_Vertex V1, V2;
334     TopExp::Vertices(aWire, V1, V2);
335     TopTools_ListOfShape LW1, LW2;
336     if (!VerSecMap.IsBound(V1))
337       VerSecMap.Bind(V1, LW1);
338     VerSecMap(V1).Append(aWire);
339     if (!VerSecMap.IsBound(V2))
340       VerSecMap.Bind(V2, LW2);
341     VerSecMap(V2).Append(aWire);
342   }
343
344   //TopTools_IndexedDataMapOfShapeShape InnerTouchingWiresOnVertex;
345   
346   TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
347   TopoDS_Wire CurWire = outerW;
348   BRepLib_MakeWire *MW;
349   MW = new BRepLib_MakeWire();
350   BRepTools_WireExplorer wexp(CurWire, FaceRef);
351   for (;;)
352   {
353     TopoDS_Vertex theStartVertex = wexp.CurrentVertex(), CurVertex;
354     TopoDS_Edge CurEdge = wexp.Current();
355     TopoDS_Edge LastEdge = CurEdge;
356     MW->Add(CurEdge);
357     TopoDS_Wire aSectionWire;
358     TopoDS_Vertex aBreakVertex;
359     wexp.Next();
360     if (!wexp.More())
361       wexp.Init(CurWire, FaceRef);
362     for (;;)
363     {
364       if (MW->Wire().Closed())
365         break;
366       CurVertex = wexp.CurrentVertex();
367       if (VerSecMap.IsBound(CurVertex))
368       {
369         TopoDS_Shape aLocalWire = ChooseDirection(LastEdge, CurVertex, FaceRef, VerSecMap(CurVertex));
370         aSectionWire = TopoDS::Wire(aLocalWire);
371         break;
372       }
373       CurEdge = wexp.Current();
374       MW->Add(CurEdge);
375       LastEdge = CurEdge;
376       wexp.Next();
377       if (!wexp.More())
378         wexp.Init(CurWire, FaceRef);
379     }
380     if (MW->Wire().Closed())
381     {
382       NewWires.Append(MW->Wire());
383       theStartVertex = TopoDS::Vertex(BreakVertices.First());
384       BreakVertices.RemoveFirst();
385       CurWire = TopoDS::Wire(BreakOnWires.First());
386       BreakOnWires.RemoveFirst();
387       wexp.Init(CurWire, FaceRef);
388       while (!wexp.CurrentVertex().IsSame(theStartVertex))
389         wexp.Next();
390       MW = new BRepLib_MakeWire();
391       continue;
392     }
393     aBreakVertex = CurVertex;
394     BreakVertices.Append(aBreakVertex);
395     BreakOnWires.Append(CurWire);
396     for (;;)
397     {
398       MW->Add(aSectionWire);
399       (SectionsTimes(aSectionWire))--;
400       if (SectionsTimes(aSectionWire) == 0)
401         SectionsTimes.UnBind(aSectionWire);
402       if (MW->Wire().Closed())
403       {
404         NewWires.Append(MW->Wire());
405         if (SectionsTimes.IsEmpty())
406           break;
407         theStartVertex = TopoDS::Vertex(BreakVertices.First());
408         BreakVertices.RemoveFirst();
409         CurWire = TopoDS::Wire(BreakOnWires.First());
410         BreakOnWires.RemoveFirst();
411         wexp.Init(CurWire, FaceRef);
412         while (!wexp.CurrentVertex().IsSame(theStartVertex))
413           wexp.Next();
414         MW = new BRepLib_MakeWire();
415         break;
416       }
417       else
418       {
419         TopoDS_Vertex V1, V2, aStartVertex;
420         TopExp::Vertices(aSectionWire, V1, V2);
421         aStartVertex = (V1.IsSame(aBreakVertex))? V2 : V1;
422         CurWire = TopoDS::Wire(VerWireMap(aStartVertex));
423         
424         wexp.Init(CurWire, FaceRef);
425         while (!wexp.CurrentVertex().IsSame(aStartVertex))
426           wexp.Next();
427             
428         const TopTools_ListOfShape& Lsections = VerSecMap(aStartVertex);
429         if (Lsections.Extent() == 1)
430           break;
431         
432         //else: choose the way
433         TopoDS_Wire NextSectionWire =
434           TopoDS::Wire((aSectionWire.IsSame(Lsections.First()))? Lsections.Last() : Lsections.First());
435         
436         Standard_Integer Times = 0;
437         TopTools_DataMapIteratorOfDataMapOfShapeShape itVW(VerWireMap);
438         for (; itVW.More(); itVW.Next())
439           if (itVW.Value().IsSame(CurWire))
440             Times++;
441         if (Times == 1) //it is inner touching wire
442         {
443           //InnerTouchingWiresOnVertex.Bind(aWire, aStartVertex);
444         }
445         else
446           {
447             //we have to choose the direction
448             TopoDS_Edge aStartEdge = wexp.Current();
449             TopTools_ListOfShape Ldirs;
450             Ldirs.Append(aStartEdge);
451             Ldirs.Append(NextSectionWire);
452             TopoDS_Shape theDirection = ChooseDirection(aSectionWire, aStartVertex, FaceRef, Ldirs);
453             if (theDirection.IsSame(aStartEdge))
454               break;
455           }
456         aSectionWire = NextSectionWire;
457         aBreakVertex = aStartVertex;
458       } //end of else (MW is not closed)
459     } //end of for (;;) (loop on section wires)
460     if (SectionsTimes.IsEmpty())
461       break;
462   } //end of global for (;;)
463
464   TopTools_ListOfShape NewFaces;
465   BRep_Builder BB;
466   for (itl.Initialize(NewWires); itl.More(); itl.Next())
467   {
468     TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
469     TopoDS_Face aNewFace = TopoDS::Face(aLocalFace);
470     aNewFace.Orientation(TopAbs_FORWARD);
471     BB.Add(aNewFace, itl.Value());
472     NewFaces.Append(aNewFace);
473   }
474
475   //Inserting holes
476   TopTools_ListOfShape Holes;
477   for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
478   {
479     const TopoDS_Shape& aWire = ExploF.Current();
480     ExploW.Init(aWire, TopAbs_EDGE);
481     TopoDS_Shape anEdge = ExploW.Current();
482     Standard_Boolean found = Standard_False;
483     for (itl.Initialize(NewWires); itl.More(); itl.Next())
484     {
485       const TopoDS_Shape& aNewWire = itl.Value();
486       for (ExploW.Init(aNewWire, TopAbs_EDGE); ExploW.More(); ExploW.Next())
487       {
488         if (anEdge.IsSame(ExploW.Current()))
489         {
490           found = Standard_True;
491           break;
492         }
493       }
494       if (found)
495         break;
496     }
497     if (!found)
498       Holes.Append(aWire);
499   }
500   TopTools_ListIteratorOfListOfShape itlNewF;
501   for (itl.Initialize(Holes); itl.More(); itl.Next())
502   {
503     const TopoDS_Wire& aHole = TopoDS::Wire(itl.Value());
504     for (itlNewF.Initialize(NewFaces); itlNewF.More(); itlNewF.Next())
505     {
506       TopoDS_Face& aNewFace = TopoDS::Face(itlNewF.Value());
507       if (IsInside(aNewFace, aHole))
508       {
509         BB.Add(aNewFace, aHole);
510         break;
511       }
512     }
513   }
514
515   //Update "myMap"
516   lf.Append(NewFaces);
517
518   //Update of descendants of wires
519   for (ExploF.Init(F, TopAbs_WIRE); ExploF.More(); ExploF.Next())
520   {
521     TopTools_ListOfShape& ls = myMap(ExploF.Current());
522     ls.Clear();
523   }
524   ///////////////////
525   
526   // JAG 10.11.95 Codage des regularites
527   for (itl.Initialize(Lwires); itl.More(); itl.Next())
528     for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next())
529     {
530       const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current());
531       if (!BRep_Tool::HasContinuity(edg,F,F)) {
532         BB.Continuity(edg,F,F,GeomAbs_CN);
533       }
534     }
535 }
536
537
538 //=======================================================================
539 //function : Add
540 //purpose  : 
541 //=======================================================================
542
543 void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
544                             const TopoDS_Face& F)
545 {
546
547   if (myDone) {
548     Standard_ConstructionError::Raise();
549   }
550
551
552   TopExp_Explorer exp;
553   TopTools_ListOfShape& lf = myMap(F);
554   if (lf.IsEmpty()) {
555     Rebuild(F);
556   }
557   try {
558     OCC_CATCH_SIGNALS
559     if (!LocOpe::Closed(W,F)) {
560       AddOpenWire(W,F);
561     }
562     else {
563       AddClosedWire(W,F);
564     }
565   } catch (Standard_Failure ) {
566 #ifdef OCCT_DEBUG
567     cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<endl;
568 #endif
569     return;
570   }
571   // JAG 10.11.95 Codage des regularites
572   BRep_Builder B;
573   for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
574     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
575     if (!BRep_Tool::HasContinuity(edg,F,F)) {
576       B.Continuity(edg,F,F,GeomAbs_CN);
577     }
578   }
579 }
580
581
582
583 //=======================================================================
584 //function : AddClosedWire
585 //purpose  : 
586 //=======================================================================
587
588 void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
589                                       const TopoDS_Face& F)
590 {
591   TopExp_Explorer exp;
592
593   // On cherche la face descendante de F qui continent le wire
594   TopTools_ListOfShape& lf = myMap(F);
595   TopTools_ListIteratorOfListOfShape itl(lf);
596   TopoDS_Wire outerW;
597   for (; itl.More(); itl.Next()) {
598     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
599     /*
600     outerW = BRepTools::OuterWire(fac);
601     if (IsInside(F,W,outerW)) {
602     break;
603     }
604     */
605     if (IsInside(fac,W)) {
606       break;
607     }
608
609   }
610   if (!itl.More()) {
611     Standard_ConstructionError::Raise();
612   }
613
614   BRep_Builder B;
615
616   TopAbs_Orientation orWire = W.Orientation();
617   TopoDS_Shape aLocalFace = F.EmptyCopied();
618   TopoDS_Face newFace = TopoDS::Face(aLocalFace);
619   //  TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
620   newFace.Orientation(TopAbs_FORWARD);
621   B.Add(newFace,W);
622   //  GProp_GProps GP;
623   //  BRepGProp::SurfaceProperties (newFace,GP);
624   //  if (GP.Mass() < 0) {
625   BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
626   if (classif.PerformInfinitePoint() == TopAbs_IN) {
627     //le wire donne defini un trou
628     aLocalFace = F.EmptyCopied();
629     newFace = TopoDS::Face(aLocalFace);
630     //    newFace = TopoDS::Face(F.EmptyCopied());
631     newFace.Orientation(TopAbs_FORWARD);
632     orWire = TopAbs::Reverse(orWire);
633     B.Add(newFace,W.Oriented(orWire));
634   }
635
636   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
637   FaceRef.Orientation(TopAbs_FORWARD);
638   lf.Remove(itl);
639
640   aLocalFace = FaceRef.EmptyCopied();
641   TopoDS_Face newRef = TopoDS::Face(aLocalFace);
642   //  TopoDS_Face newRef = TopoDS::Face(FaceRef.EmptyCopied());
643   newRef.Orientation(TopAbs_FORWARD);
644
645   // On suppose que les edges du wire ont des courbes 2d. 
646   // Comme on ne change pas de surface de base, pas besoin d`UpdateEdge.
647
648   for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
649     exp.More(); exp.Next()) {
650       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
651       if (IsInside(F,wir,W)) {
652         B.Add(newFace,wir);
653       }
654       else {
655         B.Add(newRef,wir);
656       }
657   }
658   B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire)));
659   lf.Append(newRef);
660   lf.Append(newFace);
661
662 }
663
664
665 //=======================================================================
666 //function : AddOpenWire
667 //purpose  : 
668 //=======================================================================
669
670 void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
671                                     const TopoDS_Face& F)
672 {
673   // On cherche la face descendante de F qui continent le wire
674   TopTools_ListOfShape& lf = myMap(F);
675   TopTools_ListIteratorOfListOfShape itl(lf);
676   TopoDS_Vertex Vfirst,Vlast;
677
678   BRepTools::Update(F);
679
680   Standard_Real tolf, toll, tol1;
681
682   TopoDS_Shape aLocalShape = W.Oriented(TopAbs_FORWARD);
683   TopExp::Vertices(TopoDS::Wire(aLocalShape),Vfirst,Vlast);
684
685   tolf = BRep_Tool::Tolerance(Vfirst);
686   toll = BRep_Tool::Tolerance(Vlast);
687   tol1 = Max(tolf, toll);
688
689
690   TopExp_Explorer exp,exp2;  
691
692   TopoDS_Wire wfirst,wlast;
693   for (; itl.More(); itl.Next()) {
694     TopoDS_Face fac = TopoDS::Face(itl.Value());
695     if (!IsInside(fac,W)) {
696       continue;
697     }
698     
699     fac.Orientation(TopAbs_FORWARD);
700     Standard_Boolean ffound = Standard_False;
701     Standard_Boolean lfound = Standard_False;
702     for (exp.Init(fac,TopAbs_WIRE); exp.More(); exp.Next()) {
703       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
704       for (exp2.Init(wir,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
705         if (!ffound && exp2.Current().IsSame(Vfirst)) {
706           ffound = Standard_True;
707           wfirst = wir;
708         }
709         else if (!lfound && exp2.Current().IsSame(Vlast)) {
710           lfound = Standard_True;
711           wlast = wir;
712         }
713         if (ffound && lfound) {
714           break;
715         }
716       }
717       if (exp2.More()) {
718         break;
719       }
720     }
721     if (exp.More()) {
722       break;
723     }
724   }
725   if (!itl.More()) {
726     Standard_ConstructionError::Raise();
727   }
728
729   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
730   FaceRef.Orientation(TopAbs_FORWARD);
731   lf.Remove(itl);
732   BRep_Builder B;
733
734   BRepAdaptor_Surface BAS(FaceRef, Standard_False);
735
736   Standard_Boolean IsPeriodic = BAS.IsUPeriodic() || BAS.IsVPeriodic();
737
738   tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
739
740   if (wfirst.IsSame(wlast)) {
741     // on cree 2 faces en remplacement de itl.Value()
742     // Essai JAG
743     TopTools_ListOfShape WiresFirst;
744     for (exp.Init(wfirst,TopAbs_EDGE); exp.More(); exp.Next()) {
745       if (BRep_Tool::IsClosed(TopoDS::Edge(exp.Current()),FaceRef)) {
746         myDblE.Add(exp.Current());
747       }
748       WiresFirst.Append(exp.Current());      
749     }
750
751     TopAbs_Orientation orient;
752     TopoDS_Wire newW1,newW2;
753     B.MakeWire(newW1);
754     newW1.Orientation(TopAbs_FORWARD);
755     B.MakeWire(newW2);
756     newW2.Orientation(TopAbs_FORWARD);
757
758     Standard_Integer nbE = 0;    
759     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
760          exp.More(); exp.Next()) {
761       nbE++;
762       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
763       orient = edg.Orientation();      
764       WiresFirst.Append(edg);
765       WiresFirst.Append(edg.Oriented(TopAbs::Reverse(orient)));
766       myDblE.Add(edg);
767     }    
768
769     TopTools_IndexedMapOfShape PossE;
770     TopTools_MapOfOrientedShape MapE;
771     TopoDS_Vertex vdeb,vfin;
772     Standard_Integer nbPoss;
773
774     // On recherche l`edge contenant Vlast
775     TopoDS_Edge LastEdge;
776     gp_Pnt2d pfirst,plast;
777     gp_Vec2d dlast;
778     Handle(Geom2d_Curve) C2d;
779     Standard_Real f,l;
780
781     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
782          exp.More(); exp.Next()) {
783       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
784       for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
785         if (exp2.Current().IsSame(Vfirst)) {
786           break;
787         }
788       }
789       if (exp2.More()) {
790         LastEdge = edg;
791         LastEdge.Orientation(edg.Orientation());
792         break;
793       }
794     }
795
796     TopoDS_Shape aLocalFace = FaceRef.Oriented(wfirst.Orientation());
797     C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
798
799     if (LastEdge.Orientation() == TopAbs_FORWARD) {
800       pfirst = C2d->Value(f);
801     }
802     else {
803       pfirst = C2d->Value(l);
804     }
805
806     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
807          exp.More(); exp.Next()) {
808       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
809       if( nbE>1 && edg.IsSame(LastEdge) )
810         continue;
811       for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
812         if (exp2.Current().IsSame(Vlast)) {
813           break;
814         }
815       }
816       if (exp2.More()) {
817         LastEdge = edg;
818         LastEdge.Orientation(edg.Orientation());
819         break;
820       }
821     }
822     aLocalFace  = FaceRef.Oriented(wfirst.Orientation());
823     C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
824     Standard_Real dpar = (l - f)*0.01;
825  
826     if (LastEdge.Orientation() == TopAbs_FORWARD) {
827       C2d->D1(l,plast,dlast);
828       if (dlast.Magnitude() < gp::Resolution())
829       {
830         gp_Pnt2d PrevPnt = C2d->Value(l - dpar);
831         dlast.SetXY(plast.XY() - PrevPnt.XY());
832       }
833     }
834     else {
835       C2d->D1(f,plast,dlast);
836       if (dlast.Magnitude() < gp::Resolution())
837       {
838         gp_Pnt2d NextPnt = C2d->Value(f + dpar);
839         dlast.SetXY(NextPnt.XY() - plast.XY());
840       }
841       dlast.Reverse();
842     }
843
844     Standard_Boolean cond;
845
846     if(IsPeriodic) {
847
848       cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS));
849     }
850     else {
851       cond = !(Vfirst.IsSame(Vlast));
852     }
853         
854     while (cond) {      
855       PossE.Clear();
856       
857       // On enchaine par la fin      
858       TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
859       for (; lexp.More(); lexp.Next()) {
860         const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());        
861
862         orient = edg.Orientation();
863         TopExp::Vertices(edg,vdeb,vfin);
864         if (orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) {
865           PossE.Add(edg.Oriented(orient));
866         }
867         else if (orient == TopAbs_REVERSED && Vlast.IsSame(vfin)) {
868           PossE.Add(edg.Oriented(orient));
869         }
870       }
871       nbPoss = PossE.Extent();
872       if (nbPoss == 0)
873       {
874         break;
875       }
876
877       TopoDS_Edge aNextEdge;
878       if (nbPoss == 1) {
879         aNextEdge = TopoDS::Edge (PossE.FindKey (1));
880         TopoDS_Shape aLocalFaceTemp  = FaceRef.Oriented(wfirst.Orientation());
881         C2d = BRep_Tool::CurveOnSurface(aNextEdge,
882                                         TopoDS::Face(aLocalFaceTemp), f, l);
883         Standard_Real dparnew = (l - f)*0.01;
884
885         if (aNextEdge.Orientation() == TopAbs_FORWARD) {
886           C2d->D1(l,plast,dlast);
887           if (dlast.Magnitude() < gp::Resolution())
888           {
889             gp_Pnt2d PrevPnt = C2d->Value(l - dparnew);
890             dlast.SetXY(plast.XY() - PrevPnt.XY());
891           }
892         }
893         else {
894           C2d->D1(f,plast,dlast);
895           if (dlast.Magnitude() < gp::Resolution())
896           {
897             gp_Pnt2d NextPnt = C2d->Value(f + dparnew);
898             dlast.SetXY(NextPnt.XY() - plast.XY());
899           }
900           dlast.Reverse();
901         }
902       }
903       else if (nbPoss > 1) {
904         // Faire choix en U,V...
905         TopoDS_Shape aLocalFaceTemp  = FaceRef.Oriented(wfirst.Orientation());
906         
907         ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE,
908                 aNextEdge, plast, dlast, toll);
909       }
910
911       if (nbPoss >= 1) {
912         if (aNextEdge.IsNull())
913         {
914           // loop is not closed. Split is not possible
915           Standard_ConstructionError::Raise("Split is not possible: split loop is not closed"); 
916         }
917
918         if (MapE.Contains(aNextEdge)) 
919           break;
920         B.Add(newW1, aNextEdge);
921         MapE.Add(aNextEdge);        
922         LastEdge = aNextEdge;
923         
924         if (LastEdge.Orientation() == TopAbs_FORWARD) {
925           Vlast = TopExp::LastVertex(LastEdge);
926         }
927         else {
928           Vlast = TopExp::FirstVertex(LastEdge);
929         }
930         
931         toll = BRep_Tool::Tolerance(Vlast);
932         tol1 = Max(tolf, toll);
933         
934       }
935       //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur
936       else{
937         cout<<"erreur Spliter : pas de chainage du wire"<<endl;
938         Standard_ConstructionError::Raise();        
939       }
940       //fin MODIF.
941       
942       tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
943       
944     }
945     
946     TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
947     for (; lexp.More(); lexp.Next()) {    
948       const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());
949       if (!MapE.Contains(edg)) {
950         B.Add(newW2,edg);
951         MapE.Add(edg);
952       }
953     }        
954    
955     TopoDS_Face newF1,newF2;
956     aLocalFace = FaceRef.EmptyCopied();
957     newF1 = TopoDS::Face(aLocalFace);
958     newF1.Orientation(TopAbs_FORWARD);
959     aLocalFace = FaceRef.EmptyCopied();
960     newF2 = TopoDS::Face(aLocalFace);
961     newF2.Orientation(TopAbs_FORWARD);
962     
963     // modifs JAG 97.05.28
964
965     B.Add(newF1,newW1);
966     //BRepTools::Write(newF1, "k:/queries/WrongBOP/NewF1.brep");
967     B.Add(newF2,newW2);
968     //BRepTools::Write(newF2, "k:/queries/WrongBOP/NewF2.brep");
969     
970     for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); exp.More(); exp.Next()) {
971       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
972       if (!wir.IsSame(wfirst)) {
973         if (IsInside(newF1, wir)) {
974           B.Add(newF1,wir);
975         }
976         else if (IsInside(newF2, wir)) {
977           B.Add(newF2,wir);
978         }
979         else {
980           // Ce wire est ni dans newF2 ni dans newF1
981           // Peut etre faut il construire une troisieme face
982           cout << "WARNING: LocOpe_SPlitShape : Ce wire est ni dans newF2 ni dans newF1" << endl;
983         }
984       }
985     }
986     lf.Append(newF1);
987     lf.Append(newF2);
988     
989     // Mise a jour des descendants des wires
990     for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
991       TopTools_ListOfShape& ls = myMap(exp.Current());
992       itl.Initialize(ls);
993       for (; itl.More(); itl.Next()) {
994         if (itl.Value().IsSame(wfirst)) {
995           break;
996         }
997       }
998       if (itl.More()) { // on a trouve le wire
999         ls.Remove(itl);
1000         ls.Append(newW1);
1001         ls.Append(newW2);
1002       }
1003     }
1004   }
1005   else {
1006     // on ne cree qu`une seule face
1007     TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
1008     TopoDS_Wire newWire;
1009     TopoDS_Face newFace;
1010     B.MakeWire(newWire);
1011     newWire.Orientation(TopAbs_FORWARD);
1012     TopAbs_Orientation orient,orRelat;
1013
1014     if (wfirst.Orientation() == wlast.Orientation()) {
1015       orRelat = TopAbs_FORWARD;
1016     }
1017     else {
1018       orRelat = TopAbs_REVERSED;
1019     }
1020
1021     if (wlast.IsSame(outerW)) {
1022       wlast = wfirst;
1023       wfirst = outerW;
1024     }
1025     
1026     // Edges de wfirst
1027     for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1028          exp.More(); exp.Next()) {
1029       B.Add(newWire,TopoDS::Edge(exp.Current()));
1030     }
1031
1032     // Edges de wlast
1033     for (exp.Init(wlast.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1034          exp.More(); exp.Next()) {
1035       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1036       orient = TopAbs::Compose(edg.Orientation(),orRelat);
1037       B.Add(newWire,edg.Oriented(orient));
1038     }
1039     
1040
1041     // Edges du wire ajoute, et dans les 2 sens
1042     for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1043          exp.More(); exp.Next()) {
1044       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1045       orient = edg.Orientation();
1046       B.Add(newWire,edg.Oriented(orient));
1047       B.Add(newWire,edg.Oriented(TopAbs::Reverse(orient)));
1048       myDblE.Add(edg.Oriented(orient));
1049     }
1050     
1051     // on refait une face
1052
1053     TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
1054     newFace = TopoDS::Face(aLocalFace);
1055     //    newFace = TopoDS::Face(FaceRef.EmptyCopied());
1056     FaceRef.Orientation(TopAbs_FORWARD);
1057     for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); 
1058          exp.More(); exp.Next()) {
1059       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
1060       if (wir.IsSame(wfirst)) {
1061         B.Add(newFace,newWire.Oriented(wir.Orientation()));
1062       }
1063       else if (!wir.IsSame(wlast)) {
1064         B.Add(newFace,wir);
1065       }
1066     }
1067     lf.Append(newFace);
1068     
1069     // Mise a jour des descendants des wires
1070     for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
1071       TopTools_ListOfShape& ls = myMap(exp.Current());
1072       itl.Initialize(ls);
1073       Standard_Boolean touch = Standard_False;
1074       while (itl.More()) {
1075         if (itl.Value().IsSame(wfirst) || itl.Value().IsSame(wlast)) {
1076           ls.Remove(itl);
1077           touch = Standard_True;
1078         }
1079         else {
1080           itl.Next();
1081         }
1082       }
1083       if (touch) {
1084         ls.Append(newWire);
1085       }
1086       
1087     }
1088   }
1089 }
1090
1091
1092 //=======================================================================
1093 //function : LeftOf
1094 //purpose  : 
1095 //=======================================================================
1096
1097 const TopTools_ListOfShape& LocOpe_SplitShape::LeftOf(const TopoDS_Wire& W,
1098                                                       const TopoDS_Face& F)
1099 {
1100   if (myShape.IsNull()) {
1101     Standard_NoSuchObject::Raise();
1102   }
1103
1104   TopExp_Explorer exp,expw,expf;
1105   exp.Init(myShape,TopAbs_FACE);
1106   for (; exp.More(); exp.Next()) {
1107     if (exp.Current().IsSame(F)) {
1108       break;
1109     }
1110   }
1111   if (!exp.More()) {
1112     Standard_NoSuchObject::Raise();
1113   }
1114   myLeft.Clear();
1115
1116   const TopoDS_Face& theFace = TopoDS::Face(exp.Current());
1117   TopAbs_Orientation orFace = theFace.Orientation();
1118   TopTools_ListIteratorOfListOfShape itl,itl2;
1119
1120   for (expw.Init(W,TopAbs_EDGE); expw.More(); expw.Next()) {
1121     const TopoDS_Edge& edg = TopoDS::Edge(expw.Current());
1122     for (itl.Initialize(myMap(theFace)); itl.More(); itl.Next()) {
1123       TopoDS_Face fac = TopoDS::Face(itl.Value());
1124       fac.Orientation(orFace);
1125       for (expf.Init(fac,TopAbs_EDGE); expf.More(); expf.Next()) {
1126         const TopoDS_Edge& edgbis = TopoDS::Edge(expf.Current());
1127         if (edgbis.IsSame(edg) && 
1128           edgbis.Orientation() == edg.Orientation()) {
1129             for (itl2.Initialize(myLeft); itl2.More(); itl2.Next()) {
1130               if (itl2.Value().IsSame(fac)) {
1131                 break;
1132               }
1133             }
1134             if (!itl2.More()) { // la face n`est pas deja presente
1135               myLeft.Append(fac);
1136             }
1137             break;
1138         }
1139       }
1140       if (expf.More()) { // face found
1141         break;
1142       }
1143     }
1144   }
1145   return myLeft;
1146 }
1147
1148
1149 //=======================================================================
1150 //function : DescendantShapes
1151 //purpose  : 
1152 //=======================================================================
1153
1154 const TopTools_ListOfShape& LocOpe_SplitShape::DescendantShapes
1155 (const TopoDS_Shape& S)
1156 {
1157   if (!myDone) {
1158     Rebuild(myShape);
1159     myDone = Standard_True;
1160   }
1161 #ifdef OCCT_DEBUG
1162   if (!myDblE.IsEmpty()) {
1163     cout << "Le shape comporte des faces invalides" << endl;
1164   }
1165 #endif
1166   return myMap(S);
1167 }
1168
1169
1170
1171 //=======================================================================
1172 //function : Put
1173 //purpose  : 
1174 //=======================================================================
1175
1176 void LocOpe_SplitShape::Put(const TopoDS_Shape& S)
1177 {
1178   if (!myMap.IsBound(S)) {
1179     TopTools_ListOfShape thelist;
1180     myMap.Bind(S, thelist);
1181     if (S.ShapeType() != TopAbs_VERTEX) {
1182       for(TopoDS_Iterator theIterator(S);theIterator.More();
1183         theIterator.Next()) {
1184           Put(theIterator.Value());
1185       }
1186     }
1187     else {
1188       myMap(S).Append(S);
1189     }
1190   }
1191 }
1192
1193
1194 //=======================================================================
1195 //function : Rebuild
1196 //purpose  : 
1197 //=======================================================================
1198
1199 Standard_Boolean LocOpe_SplitShape::Rebuild(const TopoDS_Shape& S)
1200
1201 {
1202
1203   TopTools_ListIteratorOfListOfShape itr(myMap(S));
1204   if (itr.More()) {
1205     if (itr.Value().IsSame(S)) {
1206       return Standard_False;
1207     }
1208     return Standard_True;
1209   }
1210   Standard_Boolean rebuild = Standard_False;
1211   TopoDS_Iterator it;
1212   for(it.Initialize(S); it.More(); it.Next()) {
1213     rebuild = Rebuild(it.Value()) || rebuild;
1214   }
1215
1216   if (rebuild) {
1217     BRep_Builder B;
1218     TopoDS_Shape result = S.EmptyCopied();
1219     TopAbs_Orientation orient;
1220     for(it.Initialize(S); it.More(); it.Next()) {
1221       orient = it.Value().Orientation();
1222       for (itr.Initialize(myMap(it.Value())); itr.More(); itr.Next()) {
1223         B.Add(result,itr.Value().Oriented(orient));
1224       }
1225     }
1226     // Assign "Closed" flag for Wires and Shells only
1227     if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL)
1228       result.Closed (BRep_Tool::IsClosed(result));
1229     myMap(S).Append(result);
1230   }
1231   else {
1232     myMap(S).Append(S);
1233   }
1234   return rebuild;
1235 }
1236
1237
1238
1239 //=======================================================================
1240 //function : IsInside
1241 //purpose  : 
1242 //=======================================================================
1243
1244 static Standard_Boolean IsInside(const TopoDS_Face& F,
1245                                  const TopoDS_Wire& W1,
1246                                  const TopoDS_Wire& W2)
1247 {
1248   // Attention, c`est tres boeuf !!!!
1249   BRep_Builder B;
1250   TopoDS_Shape aLocalShape = F.EmptyCopied();
1251   TopoDS_Face newFace = TopoDS::Face(aLocalShape);
1252   //  TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
1253
1254   //TopAbs_Orientation orWire = W2.Orientation();
1255     
1256   newFace.Orientation(TopAbs_FORWARD);
1257   B.Add(newFace,W2);
1258   //  GProp_GProps GP;
1259   //  BRepGProp::SurfaceProperties(newFace,GP);
1260   //  if (GP.Mass() < 0) {
1261   BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
1262   Standard_Boolean Reversed = Standard_False;
1263   if (classif.PerformInfinitePoint() == TopAbs_IN) {
1264     //le wire donne defini un trou
1265     //    newFace = TopoDS::Face(F.EmptyCopied());
1266     //    newFace.Orientation(TopAbs_FORWARD);
1267     //    orWire = TopAbs::Reverse(orWire);
1268     //    B.Add(newFace,W2.Oriented(orWire));
1269     Reversed = Standard_True;
1270   }
1271
1272   //  Standard_Real U,V;
1273   TopExp_Explorer exp(W1,TopAbs_EDGE);
1274   const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1275   TopExp_Explorer exp2(edg,TopAbs_VERTEX);
1276   const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
1277   Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
1278   Standard_Real f,l;
1279   Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1280   if(C2d.IsNull()) {
1281 #ifdef OCCT_DEBUG
1282           cout << "Edge is not on surface" <<endl;
1283 #endif
1284       return Standard_False;
1285   }
1286   gp_Pnt2d pt2d(C2d->Value(prm));
1287   //  BRepClass_FaceClassifier classif(newFace,pt2d,Precision::PConfusion());
1288   //  return (classif.State() == TopAbs_IN);
1289   if (!Reversed) {
1290     return (classif.Perform(pt2d) == TopAbs_IN);
1291   }
1292   else {
1293     return (classif.Perform(pt2d) == TopAbs_OUT);
1294   }
1295 }
1296
1297
1298 //=======================================================================
1299 //function : IsInside
1300 //purpose  : 
1301 //=======================================================================
1302
1303 static Standard_Boolean IsInside(const TopoDS_Face& F,
1304                                  const TopoDS_Wire& W)
1305 {
1306   // Attention, c`est tres boeuf !!!!
1307   TopExp_Explorer exp(W,TopAbs_EDGE);
1308   for( ; exp.More(); exp.Next()) {
1309     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1310     //  TopExp_Explorer exp2(edg,TopAbs_VERTEX);
1311     //  const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
1312     //  Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
1313     Standard_Real f,l,prm;
1314     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1315     if (!Precision::IsNegativeInfinite(f) && 
1316       !Precision::IsPositiveInfinite(l)) {
1317         prm = (f+l)/2.;
1318     }
1319     else {
1320       if (Precision::IsNegativeInfinite(f) && 
1321         Precision::IsPositiveInfinite(l)){
1322           prm = 0.;
1323       }
1324       else if (Precision::IsNegativeInfinite(f)) {
1325         prm = l-1.;
1326       }
1327       else {
1328         prm = f+1.;
1329       }
1330     }
1331
1332     gp_Pnt2d pt2d(C2d->Value(prm));
1333     //  BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion());
1334     //  return (classif.State() != TopAbs_OUT);
1335     BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion());
1336     TopAbs_State stat = classif.Perform(pt2d);
1337     //  return (classif.Perform(pt2d) != TopAbs_OUT);
1338     if(stat == TopAbs_OUT) return Standard_False;
1339
1340     if(stat == TopAbs_ON) {
1341       Standard_Integer nbPnt =10;
1342       Standard_Integer nbOut =0,nbIn =0,nbOn=0;
1343       Standard_Integer j =1;
1344       for( ; j<= nbPnt ; j++)
1345       {
1346         //check neighbouring point
1347         //prm = .66 * prm + .34 * l;
1348         prm = f + (l-f)/nbPnt*(j-1);
1349         pt2d = C2d->Value(prm);
1350         stat = classif.Perform(pt2d);
1351         if(stat == TopAbs_OUT ) 
1352           nbOut++;
1353         else if(stat == TopAbs_IN)
1354           nbIn++;
1355         else
1356           nbOn++;
1357       }
1358       if(nbOut > nbIn + nbOn)
1359         return Standard_False;
1360     }
1361   }
1362   return Standard_True;
1363 }
1364
1365 //=======================================================================
1366 //function : GetDirection
1367 //purpose  : 
1368 //=======================================================================
1369 static void GetDirection(const TopoDS_Edge& theEdge,
1370                          const TopoDS_Face& theFace,
1371                          Standard_Real& theTol,
1372                          gp_Pnt2d& thePnt,
1373                          gp_Vec2d& theDir)
1374 {
1375   Standard_Real aFirst, aLast;
1376   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface (theEdge, theFace, aFirst, aLast);
1377
1378   TopAbs_Orientation anOr = theEdge.Orientation();
1379   TopoDS_Vertex aVtx;
1380   if (anOr == TopAbs_FORWARD)
1381   {
1382     aVtx = TopExp::FirstVertex (theEdge);
1383     aC2d->D0 (aFirst, thePnt);
1384   }
1385   else
1386   {
1387     aVtx = TopExp::LastVertex (theEdge);
1388     aC2d->D0 (aLast, thePnt);
1389   }
1390
1391   BRepAdaptor_Surface aSurf (theFace, Standard_False);
1392   theTol = BRep_Tool::Tolerance (aVtx);
1393   Standard_Real aTol = Max (aSurf.UResolution (theTol), aSurf.VResolution (theTol));
1394   aTol = Min (aTol, (aLast - aFirst)*0.1);
1395
1396   gp_Pnt2d aP2d;
1397
1398   if (anOr == TopAbs_FORWARD)
1399   {
1400       aFirst += aTol;
1401       aC2d->D0 (aFirst, aP2d);
1402   }
1403   else
1404   {
1405       aLast -= aTol;
1406       aC2d->D0 (aLast, aP2d);
1407   }
1408   theDir = gp_Vec2d (thePnt, aP2d);
1409 }
1410
1411 //=======================================================================
1412 //function : ChoixUV
1413 //purpose  : 
1414 //=======================================================================
1415
1416 static void ChoixUV(const TopoDS_Edge& Last,
1417                     const TopoDS_Face& F,
1418                     const TopTools_IndexedMapOfShape& Poss,
1419                     TopoDS_Edge& theResEdge,
1420                     gp_Pnt2d& plst,
1421                     gp_Vec2d& dlst,
1422                     const Standard_Real toll)
1423 {
1424
1425   Standard_Real f,l;
1426   gp_Pnt2d p2d;
1427   gp_Vec2d v2d;
1428   gp_Pnt aPCur, aPlst;
1429
1430   BRepAdaptor_Surface surf(F,Standard_False); // no restriction
1431   surf.D0 (plst.X(), plst.Y(), aPlst);
1432
1433   Standard_Real tol;
1434
1435   gp_Dir2d ref2d(dlst);
1436
1437   Handle(Geom2d_Curve) C2d;
1438   Standard_Real dpar;
1439
1440   Standard_Integer index = 0, imin=0;
1441   Standard_Real  angmax = -M_PI, dist, ang;
1442
1443
1444   for (index = 1; index <= Poss.Extent(); index++) {
1445     TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index));
1446     GetDirection (anEdge, F, tol, p2d, v2d);
1447
1448     surf.D0 (p2d.X(), p2d.Y(), aPCur);
1449
1450     tol = Max(toll, tol); tol *= tol;
1451
1452     dist = aPCur.SquareDistance(aPlst);
1453
1454     if (!Last.IsSame(anEdge)) {
1455       ang = ref2d.Angle(gp_Dir2d(v2d));
1456     }
1457     else {
1458       ang = -M_PI;
1459     }
1460
1461     if ((dist - tol < Epsilon(1.0))  && (ang > angmax)) {
1462       imin = index;
1463       angmax = ang;
1464     }
1465   }
1466
1467   if (imin)
1468   {
1469     theResEdge = TopoDS::Edge (Poss.FindKey (imin));
1470     C2d = BRep_Tool::CurveOnSurface (theResEdge, F, f, l);
1471     dpar = (l - f)*0.01;
1472     if (theResEdge.Orientation() == TopAbs_FORWARD)
1473     {
1474       C2d->D1 (l, plst, dlst);
1475       if (dlst.Magnitude() < gp::Resolution())
1476       {
1477         gp_Pnt2d PrevPnt = C2d->Value(l - dpar);
1478         dlst.SetXY(plst.XY() - PrevPnt.XY());
1479       }
1480     }
1481     else
1482     {
1483       C2d->D1 (f, plst, dlst);
1484       if (dlst.Magnitude() < gp::Resolution())
1485       {
1486         gp_Pnt2d NextPnt = C2d->Value(f + dpar);
1487         dlst.SetXY(NextPnt.XY() - plst.XY());
1488       }
1489       dlst.Reverse();
1490     }
1491   }
1492
1493 }
1494
1495 //=======================================================================
1496 //function : ChooseDirection
1497 //purpose  : 
1498 //=======================================================================
1499
1500 static TopoDS_Shape ChooseDirection(const TopoDS_Shape& RefDir,
1501                                     const TopoDS_Vertex& RefVertex,
1502                                     const TopoDS_Face& theFace,
1503                                     const TopTools_ListOfShape& Ldirs)
1504 {
1505   TopExp_Explorer Explo(RefDir, TopAbs_EDGE);
1506   TopoDS_Edge RefEdge;
1507   TopoDS_Vertex V1, V2;
1508   TopAbs_Orientation anOr = TopAbs_FORWARD;
1509   for (; Explo.More(); Explo.Next())
1510   {
1511     RefEdge = TopoDS::Edge(Explo.Current());
1512     TopExp::Vertices(RefEdge, V1, V2);
1513     if (V1.IsSame(RefVertex))
1514     {
1515       anOr = TopAbs_REVERSED;
1516       break;
1517     }
1518     else if (V2.IsSame(RefVertex))
1519     {
1520       anOr = TopAbs_FORWARD;
1521       break;
1522     }
1523   }
1524   
1525   Standard_Real RefFirst, RefLast;
1526   Handle(Geom2d_Curve) RefCurve = BRep_Tool::CurveOnSurface(RefEdge, theFace, RefFirst, RefLast);
1527   gp_Pnt2d RefPnt;
1528   gp_Vec2d RefVec;
1529
1530   //Standard_Real RefPar = (RefEdge.Orientation() == TopAbs_FORWARD)? RefLast : RefFirst;
1531   Standard_Real RefPar = (anOr == TopAbs_FORWARD)? RefLast : RefFirst;
1532   RefCurve->D1(RefPar, RefPnt, RefVec);
1533   if (anOr == TopAbs_FORWARD)
1534     RefVec.Reverse();
1535
1536   Handle(Geom2d_Curve) aCurve;
1537   Standard_Real aFirst, aLast, aPar;
1538   gp_Vec2d aVec;
1539   Standard_Real MinAngle = RealLast(), anAngle;
1540   TopoDS_Shape TargetDir;
1541   TopTools_ListIteratorOfListOfShape itl(Ldirs);
1542   for (; itl.More(); itl.Next())
1543   {
1544     const TopoDS_Shape& aShape = itl.Value();
1545     TopoDS_Edge anEdge;
1546     for (Explo.Init(aShape, TopAbs_EDGE); Explo.More(); Explo.Next())
1547     {
1548       anEdge = TopoDS::Edge(Explo.Current());
1549       TopExp::Vertices(anEdge, V1, V2);
1550       if (V1.IsSame(RefVertex))
1551       {
1552         anOr = TopAbs_FORWARD;
1553         break;
1554       }
1555       else if (V2.IsSame(RefVertex))
1556       {
1557         anOr = TopAbs_REVERSED;
1558         break;
1559       }
1560     }
1561     aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, aFirst, aLast);
1562     aPar = (anOr == TopAbs_FORWARD)? aFirst : aLast;
1563     aCurve->D1(aPar, RefPnt, aVec);
1564     if (anOr == TopAbs_REVERSED)
1565       aVec.Reverse();
1566     anAngle = aVec.Angle(RefVec);
1567     if (anAngle < 0.)
1568       anAngle += 2.*M_PI;
1569
1570     if (anAngle < MinAngle)
1571     {
1572       MinAngle = anAngle;
1573       TargetDir = aShape;
1574     }
1575   }
1576
1577   return TargetDir;
1578 }