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