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