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