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