0024177: Eliminate CLang compiler warning -Wlogical-op-parentheses (&& within ||)
[occt.git] / src / LocOpe / LocOpe_SplitDrafts.cxx
1 // Created on: 1996-10-02
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <LocOpe_SplitDrafts.ixx>
24
25 #include <TopExp_Explorer.hxx>
26 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
27
28 #include <BRep_Builder.hxx>
29 #include <BRep_Tool.hxx>
30
31 #include <BRepTools_Substitution.hxx>
32
33 #include <LocOpe_WiresOnShape.hxx>
34 #include <LocOpe_Spliter.hxx>
35 #include <LocOpe_SplitShape.hxx>
36 #include <LocOpe_FindEdges.hxx>
37 #include <LocOpe_BuildShape.hxx>
38
39
40 #include <TopoDS_Vertex.hxx>
41 #include <TopoDS_Edge.hxx>
42
43 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
45
46 #include <IntAna_QuadQuadGeo.hxx>
47 #include <IntCurveSurface_HInter.hxx>
48 #include <IntCurveSurface_IntersectionPoint.hxx>
49 #include <IntCurveSurface_IntersectionSegment.hxx>
50 #include <GeomInt_IntSS.hxx>
51 #include <Extrema_ExtPC.hxx>
52 #include <GeomAdaptor_HCurve.hxx>
53 #include <GeomAdaptor_HSurface.hxx>
54 #include <GeomAdaptor_Curve.hxx>
55 #include <GeomAdaptor_Surface.hxx>
56
57 #include <Geom_Surface.hxx>
58 #include <Geom_RectangularTrimmedSurface.hxx>
59 #include <Geom_Plane.hxx>
60 #include <Geom_Curve.hxx>
61 #include <Geom_TrimmedCurve.hxx>
62 #include <Geom_Line.hxx>
63
64 #include <Geom2d_Curve.hxx>
65 #include <Geom2d_Line.hxx>
66 #include <gp_Pnt2d.hxx>
67 #include <gp_Vec2d.hxx>
68
69 #include <GeomFill_Pipe.hxx>
70
71 #include <GProp_GProps.hxx>
72
73 #include <Standard_ConstructionError.hxx>
74
75 #include <TopoDS.hxx>
76 #include <TopExp.hxx>
77 #include <Precision.hxx>
78 #include <BRepGProp.hxx>
79 #include <gp.hxx>
80
81 static Standard_Boolean NewPlane(const TopoDS_Face&,
82                                  const gp_Dir&,
83                                  const gp_Pln&,
84                                  const Standard_Real,
85                                  gp_Pln&,
86                                  gp_Ax1&,
87                                  const Standard_Boolean);
88
89 static void MakeFace(TopoDS_Face&,
90                      TopTools_ListOfShape&);
91
92 static TopoDS_Edge  NewEdge(const TopoDS_Edge&,
93                             const TopoDS_Face&,
94                             const Handle(Geom_Surface)&,
95                             const TopoDS_Vertex&,
96                             const TopoDS_Vertex&);
97
98
99 static Standard_Boolean Contains(const TopTools_ListOfShape&,
100                                  const TopoDS_Shape&);
101
102
103 //=======================================================================
104 //function : Init
105 //purpose  : 
106 //=======================================================================
107
108 void LocOpe_SplitDrafts::Init(const TopoDS_Shape& S)
109 {
110   myShape = S;
111   myResult.Nullify();
112   myMap.Clear();
113 }
114
115 //=======================================================================
116 //function : Perform
117 //purpose  : 
118 //=======================================================================
119
120 void LocOpe_SplitDrafts::Perform(const TopoDS_Face& F,
121                                  const TopoDS_Wire& W,
122                                  const gp_Dir& Extr,
123                                  const gp_Pln& NPl,
124                                  const Standard_Real Angle)
125 {
126   Perform(F,W,Extr,NPl,Angle,Extr,NPl,Angle,Standard_True,Standard_False);
127 }
128
129
130 //=======================================================================
131 //function : Perform
132 //purpose  : 
133 //=======================================================================
134
135 void LocOpe_SplitDrafts::Perform(const TopoDS_Face& F,
136                                  const TopoDS_Wire& W,
137                                  const gp_Dir& Extrg,
138                                  const gp_Pln& NPlg,
139                                  const Standard_Real Angleg,
140                                  const gp_Dir& Extrd,
141                                  const gp_Pln& NPld,
142                                  const Standard_Real Angled,
143                                  const Standard_Boolean ModLeft,
144                                  const Standard_Boolean ModRight)
145
146 {
147   Standard_Integer j ;
148
149   myResult.Nullify();
150   myMap.Clear();
151   if (myShape.IsNull() || F.IsNull() || W.IsNull()) {
152     Standard_NullObject::Raise();
153   }    
154
155   if (!ModLeft && !ModRight) {
156     Standard_ConstructionError::Raise();
157   }
158
159   TopAbs_Orientation OriF = TopAbs_FORWARD;
160
161   Standard_Boolean FinS = Standard_False;
162   TopExp_Explorer exp,exp2;
163   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
164     const TopoDS_Shape& fac = exp.Current();
165     TopTools_ListOfShape thelist;
166     myMap.Bind(fac, thelist);
167     if (fac.IsSame(F)) {
168       OriF = fac.Orientation();
169       FinS = Standard_True;
170     }
171   }
172
173   if (!FinS) {
174     cout << "LocOpe_SplitDrafts:!Fins Standard_ConstructionError::Raise()" << endl;
175     Standard_ConstructionError::Raise();
176   }    
177
178   gp_Pln NewPlg,NewPld;
179   gp_Ax1 NormalFg,NormalFd;
180   TopoDS_Shape aLocalFace = F.Oriented(OriF);
181
182   if (!NewPlane(TopoDS::Face(aLocalFace),
183                 Extrg,NPlg,Angleg,NewPlg,NormalFg,ModLeft) ||
184       !NewPlane(TopoDS::Face(aLocalFace),
185                 Extrd,NPld,Angled,NewPld,NormalFd,ModRight)) {
186     //  if (!NewPlane(TopoDS::Face(F.Oriented(OriF)),
187     //          Extrg,NPlg,Angleg,NewPlg,NormalFg,ModLeft) ||
188 //      !NewPlane(TopoDS::Face(F.Oriented(OriF)),
189     //          Extrd,NPld,Angled,NewPld,NormalFd,ModRight)) {
190     return;
191   }
192
193
194   TopTools_ListIteratorOfListOfShape itl;
195   BRep_Builder B;
196
197   Handle(Geom_Surface) NewSg = new Geom_Plane(NewPlg);
198   Handle(Geom_Surface) NewSd = new Geom_Plane(NewPld);
199   Handle(Geom_Line) theLinePipe = new Geom_Line(NormalFg); // ou NormalFd
200   GeomInt_IntSS i2s(NewSg,NewSd,Precision::Confusion());
201
202   TopTools_MapOfShape theMap;
203   Handle(GeomAdaptor_HCurve) HAC = new GeomAdaptor_HCurve;
204   GeomAdaptor_Curve AC;
205   Handle(GeomAdaptor_HSurface) HAS = new GeomAdaptor_HSurface;
206   GeomAdaptor_Surface AS;
207   IntCurveSurface_HInter intcs;
208
209   TopoDS_Wire theW = W;
210   if (i2s.IsDone() && i2s.NbLines() > 0) {
211     // on split le wire" << endl;
212
213     GeomFill_Pipe thePipe;
214     thePipe.GenerateParticularCase(Standard_True);
215     thePipe.Init(theLinePipe,i2s.Line(1));
216     thePipe.Perform(Standard_True);
217
218     Handle(Geom_Surface) Spl = thePipe.Surface();
219     AS.Load(Spl);
220     HAS->Set(AS);
221     
222     LocOpe_SplitShape splw(W);
223
224     for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
225       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
226       if (theMap.Add(edg)) {
227         TopLoc_Location Loc;
228         Standard_Real f,l;
229         Handle(Geom_Curve) C = BRep_Tool::Curve(edg,f,l);
230         AC.Load(C);
231         HAC->Set(AC);
232         intcs.Perform(HAC,HAS);
233         if (!intcs.IsDone()) {
234           continue; // voir ce qu`on peut faire de mieux
235         }
236
237         if (intcs.NbSegments() >= 2) {
238           continue; // Not yet implemented...and probably never"
239         }
240
241         if (intcs.NbSegments() == 1) {
242           const IntCurveSurface_IntersectionPoint& P1 = 
243             intcs.Segment(1).FirstPoint();
244           const IntCurveSurface_IntersectionPoint& P2 = 
245             intcs.Segment(1).SecondPoint();
246           const gp_Pnt& pf = P1.Pnt();
247           const gp_Pnt& pl = P2.Pnt();
248           TopoDS_Vertex Vf,Vl;
249           TopExp::Vertices(edg,Vf,Vl);
250           gp_Pnt Pf = BRep_Tool::Pnt(Vf);
251           gp_Pnt Pl = BRep_Tool::Pnt(Vl);
252           Standard_Real Tolf = BRep_Tool::Tolerance(Vf);
253           Standard_Real Toll = BRep_Tool::Tolerance(Vl);
254           Tolf *= Tolf;
255           Toll *= Toll;
256
257           Standard_Real dff = pf.SquareDistance(Pf);
258           Standard_Real dfl = pf.SquareDistance(Pl);
259           Standard_Real dlf = pl.SquareDistance(Pf);
260           Standard_Real dll = pl.SquareDistance(Pl);
261
262           if ((dff <= Tolf && dll <= Toll) ||
263               (dlf <= Tolf && dfl <= Toll)) {
264             continue;
265           }
266           else {
267             // on segmente edg en pf et pl
268             TopoDS_Vertex Vnewf,Vnewl;
269             B.MakeVertex(Vnewf,pf,Precision::Confusion());
270             B.MakeVertex(Vnewl,pl,Precision::Confusion());
271             if (P1.W() >= f && P1.W() <= l &&
272                 P2.W() >= f && P2.W() <= l) {
273               splw.Add(Vnewf,P1.W(),edg);
274               splw.Add(Vnewl,P2.W(),edg);
275             }
276             else {
277               continue;
278             }
279           }
280         }
281         else if (intcs.NbPoints() != 0) {
282           TopoDS_Vertex Vf,Vl;
283           TopExp::Vertices(edg,Vf,Vl);
284           gp_Pnt Pf = BRep_Tool::Pnt(Vf);
285           gp_Pnt Pl = BRep_Tool::Pnt(Vl);
286           Standard_Real Tolf = BRep_Tool::Tolerance(Vf);
287           Standard_Real Toll = BRep_Tool::Tolerance(Vl);
288           Tolf *= Tolf;
289           Toll *= Toll;
290
291           for (Standard_Integer i = 1; i <= intcs.NbPoints(); i++) {
292             const IntCurveSurface_IntersectionPoint& Pi = intcs.Point(i);
293             const gp_Pnt& pi = Pi.Pnt();
294             Standard_Real dif = pi.SquareDistance(Pf);
295             Standard_Real dil = pi.SquareDistance(Pl);
296             if (dif <= Tolf) {
297             }
298             else if (dil <= Toll) {
299             }
300             else {
301               if (Pi.W() >= f && Pi.W() <= l) {
302                 TopoDS_Vertex Vnew;
303                 B.MakeVertex(Vnew,pi,Precision::Confusion());
304                 splw.Add(Vnew,Pi.W(),edg);
305               }
306             }
307           }
308         }
309       }
310     }
311
312     const TopTools_ListOfShape& lres = splw.DescendantShapes(W);
313     if (lres.Extent() != 1) {
314       return;
315     }
316
317     if (!W.IsSame(lres.First())) {
318       theW.Nullify();
319       theW = TopoDS::Wire(lres.First());
320     }
321
322     for (exp.ReInit(); exp.More(); exp.Next()) {
323       if (!myMap.IsBound(exp.Current())) {
324         TopTools_ListOfShape thelist1;
325         myMap.Bind(exp.Current(), thelist1);
326         for (itl.Initialize(splw.DescendantShapes(exp.Current())); 
327              itl.More(); itl.Next()) {
328           myMap(exp.Current()).Append(itl.Value());
329         }
330         for (exp2.Init(exp.Current(),TopAbs_VERTEX);exp2.More();exp2.Next()) {
331           if (!myMap.IsBound(exp2.Current())) {
332             TopTools_ListOfShape thelist2;
333             myMap.Bind(exp2.Current(), thelist2);
334             myMap(exp2.Current()).Append(exp2.Current());
335           }
336         }
337       }
338     }
339   }
340   else {
341     for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
342       if (!myMap.IsBound(exp.Current())) {
343         TopTools_ListOfShape thelist3;
344         myMap.Bind(exp.Current(), thelist3);
345         myMap(exp.Current()).Append(exp.Current());
346         for (exp2.Init(exp.Current(),TopAbs_VERTEX);exp2.More();exp2.Next()) {
347           if (!myMap.IsBound(exp2.Current())) {
348             TopTools_ListOfShape thelist4;
349             myMap.Bind(exp2.Current(), thelist4);
350             myMap(exp2.Current()).Append(exp2.Current());
351           }
352         }
353       }
354     }
355   }
356
357   // On split la face par le wire
358   
359   Handle(LocOpe_WiresOnShape) WonS = new LocOpe_WiresOnShape(myShape);
360   LocOpe_Spliter Spls(myShape);
361   WonS->Bind(theW,F);
362
363 // JAG Le code suivant marchera apres integration de thick0
364 //  LocOpe_FindEdges fined(W,F);
365 //  for (fined.InitIterator(); fined.More(); fined.Next()) {
366 //    WonS->Bind(fined.EdgeFrom(),fined.EdgeTo());
367 //  }
368
369   Spls.Perform(WonS);
370   if (!Spls.IsDone()) {
371     return;
372   }
373
374   TopoDS_Shape Res = Spls.ResultingShape();
375   const TopTools_ListOfShape& theLeft = Spls.DirectLeft();
376
377   // Descendants
378   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
379     const TopoDS_Shape& fac = exp.Current();
380     for (itl.Initialize(Spls.DescendantShapes(fac)); itl.More(); itl.Next()) {
381       myMap(fac).Append(itl.Value());
382     }
383   }
384
385   TopTools_DataMapOfShapeShape MapW;
386   for (exp.Init(theW,TopAbs_EDGE); exp.More(); exp.Next()) {
387     if (!MapW.IsBound(exp.Current())) {
388       MapW.Bind(exp.Current(),TopoDS_Shape());
389       for (exp2.Init(exp.Current(),TopAbs_VERTEX); exp2.More(); exp2.Next()) {
390         if (!MapW.IsBound(exp2.Current())) {
391           MapW.Bind(exp2.Current(),TopoDS_Shape());
392         }
393
394       }
395     }
396   }
397   
398
399
400   TopTools_IndexedDataMapOfShapeListOfShape theMapEF;
401   TopExp::MapShapesAndAncestors(Res,TopAbs_EDGE,TopAbs_FACE,theMapEF);
402
403   // On stocke les geometries potentiellement generees par les edges
404   TopTools_IndexedDataMapOfShapeShape MapEV; // genere
405   TopTools_DataMapOfShapeListOfShape MapSg,MapSd; // image a gauche et a droite
406
407   Standard_Integer Nbedges,index;
408   for (itl.Initialize(myMap(F)); itl.More(); itl.Next()) {
409     const TopoDS_Shape& fac = TopoDS::Face(itl.Value());
410     for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
411       const TopoDS_Shape& edg = exp.Current();
412       if (MapEV.FindIndex(edg) != 0) {
413         continue;
414       }
415       if (MapW.IsBound(edg)) { // edge du wire initial
416         TopLoc_Location Loc;
417         Standard_Real f,l;
418         Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(edg),Loc,f,l);
419         if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
420           C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
421         }
422         C = Handle(Geom_Curve)::
423           DownCast(C->Transformed(Loc.Transformation()));
424
425         GeomFill_Pipe thePipe;
426         thePipe.GenerateParticularCase(Standard_True);
427         thePipe.Init(theLinePipe,C);
428         thePipe.Perform(Standard_True);
429
430         Handle(Geom_Surface) thePS = thePipe.Surface();
431         if (thePS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
432           thePS = Handle(Geom_RectangularTrimmedSurface)::DownCast(thePS)
433             ->BasisSurface();
434         }
435
436         TopoDS_Face NewFace;
437         B.MakeFace(NewFace,thePS,Precision::Confusion());
438         MapEV.Add(edg,NewFace);
439       }
440       else { // on recupere la face.
441         index = theMapEF.FindIndex(edg);
442         if (theMapEF(index).Extent() != 2) {
443           return; // NotDone
444         }
445         TopoDS_Face theFace;
446         if (theMapEF(index).First().IsSame(fac)) {
447           MapEV.Add(edg,theMapEF(index).Last());
448         }
449         else {
450           MapEV.Add(edg,theMapEF(index).First());
451         }
452       }
453     }
454   }
455
456
457   TopTools_DataMapOfShapeShape MapSonS;
458
459   Nbedges = MapEV.Extent();
460   for (index = 1; index <= Nbedges; index++) {
461     for (exp.Init(MapEV.FindKey(index),TopAbs_VERTEX); 
462          exp.More(); exp.Next()) {
463       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
464       if (MapEV.FindIndex(vtx)!= 0) {
465         continue;
466       }
467
468       // Localisation du vertex :
469       //    - entre 2 edges d`origine : on recupere l`edge qui n`est 
470       //                                pas dans F
471       //    - entre 2 edges du wire   : droite
472       //    - mixte                   : intersection de surfaces
473       for ( j = 1; j<=Nbedges; j++) {
474         if (j == index) {
475           continue;
476         }
477         for (exp2.Init(MapEV.FindKey(j),TopAbs_VERTEX);
478              exp2.More(); exp2.Next()) {
479           const TopoDS_Shape& vtx2 = exp2.Current();
480           if (vtx2.IsSame(vtx)) {
481             break;
482           }
483         }
484         if (exp2.More()) {
485           break;
486         }
487       }
488       Standard_Integer Choice = 0;
489       const TopoDS_Shape& edg1 = MapEV.FindKey(index);
490       TopoDS_Shape edg2;
491       if (j <= Nbedges) {
492         edg2 = MapEV.FindKey(j);
493       }
494       else {
495         edg2 = edg1;
496       }
497       if (MapW.IsBound(edg1)) {
498         if (j>Nbedges) { // doit correspondre a edge ferme
499           Choice = 2; // droite
500         }
501         else if (MapW.IsBound(MapEV.FindKey(j))) {
502           Choice = 2; // droite
503         }
504         else {
505           Choice = 3; // mixte
506         }
507       }
508       else {
509         if (j>Nbedges) { // doit correspondre a edge ferme
510           Choice = 1; // edge a retrouver
511         }
512         else if (!MapW.IsBound(MapEV.FindKey(j))) {
513           Choice = 1; // edge a retrouver
514         }
515         else {
516           Choice = 3; // mixte
517         }
518       }
519       Handle(Geom_Curve) Newc;
520       Handle(Geom2d_Curve) newCs1,newCs2;
521       Standard_Real knownp=0;
522       TopoDS_Edge Ebind;
523       switch (Choice) {
524       case 1:
525         {
526           for (exp2.Init(Res,TopAbs_EDGE); exp2.More(); exp2.Next()) {
527             if (exp2.Current().IsSame(edg1) || exp2.Current().IsSame(edg2)) {
528               continue;
529             }
530 //          for (TopExp_Explorer exp3(exp2.Current().Oriented(TopAbs_FORWARD),
531             TopExp_Explorer exp3(exp2.Current().Oriented(TopAbs_FORWARD),
532                                       TopAbs_VERTEX) ;
533             for ( ; exp3.More(); exp3.Next())  {
534               if (exp3.Current().IsSame(vtx)) {
535                 break;
536               }
537             }
538             if (exp3.More()) {
539               break;
540             }
541           }
542           if (exp2.More()) {
543             Standard_Real f,l;
544             TopLoc_Location Loc;
545             Newc = BRep_Tool::Curve(TopoDS::Edge(exp2.Current()),Loc,f,l);
546             Newc = Handle(Geom_Curve)::DownCast
547               (Newc->Transformed(Loc.Transformation()));
548             Ebind = TopoDS::Edge(exp2.Current());
549             knownp = BRep_Tool::Parameter(vtx,Ebind);
550           }
551           else { // droite ??? il vaudrait mieux sortir
552             return;
553
554 //          gp_Lin theLine(NormalFg);
555 //          theLine.Translate(NormalF.Location(),BRep_Tool::Pnt(vtx));
556 //          Newc = new Geom_Line(theLine);
557 //          knownp = 0.;
558           }
559         }
560         break;
561       case 2:
562         {
563           gp_Lin theLine(NormalFg);
564           theLine.Translate(NormalFg.Location(),BRep_Tool::Pnt(vtx));
565           Newc = new Geom_Line(theLine);
566           knownp = 0.;
567         }
568         break;
569       case 3:
570         {
571           const TopoDS_Face& F1 = TopoDS::Face(MapEV.FindFromKey(edg1));
572           const TopoDS_Face& F2 = TopoDS::Face(MapEV.FindFromKey(edg2));
573           Handle(Geom_Surface) S1 = BRep_Tool::Surface(F1);
574           Handle(Geom_Surface) S2 = BRep_Tool::Surface(F2);
575           Standard_Boolean AppS1 = Standard_False;
576           Standard_Boolean AppS2 = Standard_False;
577           if (S1->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
578             AppS1 = Standard_True;
579           }
580           if (S2->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
581             AppS2 = Standard_True;
582           }
583           i2s.Perform(S1,S2,Precision::Confusion(),Standard_True,AppS1,AppS2);
584           if (!i2s.IsDone() || i2s.NbLines() <= 0) {
585             return;
586           }
587         
588           Standard_Real pmin=0, Dist2, Dist2Min, Glob2Min = RealLast();
589           GeomAdaptor_Curve TheCurve;
590
591           Standard_Integer i,imin,k;
592           gp_Pnt pv = BRep_Tool::Pnt(vtx);
593           imin = 0;
594           for (i=1; i<= i2s.NbLines(); i++) {
595             TheCurve.Load(i2s.Line(i));
596             Extrema_ExtPC myExtPC(pv,TheCurve);
597
598             if (myExtPC.IsDone()) {
599               gp_Pnt p1b,p2b;
600               Standard_Real thepmin = TheCurve.FirstParameter();
601               myExtPC.TrimmedSquareDistances(Dist2Min,Dist2,p1b,p2b);
602               if (Dist2 < Dist2Min) {
603                 thepmin = TheCurve.LastParameter();
604               }
605               for (k=1; k<=myExtPC.NbExt(); k++) {
606                 Dist2 = myExtPC.SquareDistance(k);
607                 if (Dist2 < Dist2Min) {
608                   Dist2Min = Dist2;
609                   thepmin = myExtPC.Point(k).Parameter();
610                 }
611               }
612               
613               if (Dist2Min  < Glob2Min) {
614                 Glob2Min = Dist2Min;
615                 pmin = thepmin;
616                 imin = i;
617               }
618             }
619           }
620           if (imin == 0) {
621             return;
622           }
623           
624           Newc = i2s.Line(imin);
625           knownp = pmin;
626           if (AppS1) {
627             newCs1 = i2s.LineOnS1(imin);
628           }
629           if (AppS2) {
630             newCs2 = i2s.LineOnS2(imin);
631           }
632         }
633         break;
634       }
635
636
637       // Determination des vertex par intersection sur Plg ou/et Pld
638
639       AC.Load(Newc);
640       HAC->Set(AC);
641       Standard_Integer nbfois = 2;
642       TopoDS_Vertex vtx1,vtx2;
643       Standard_Real p1=0,p2=0;
644       Standard_Boolean IsLeft=Standard_False;
645       if (Choice == 1) { 
646         // edge retrouve : on ne fait qu`une seule intersection
647         // il faut utiliser Plg ou Pld
648
649         Standard_Integer indedgf = theMapEF.FindIndex(edg1);
650         for (itl.Initialize(theMapEF(indedgf)); itl.More(); itl.Next()) {
651           if (Contains(myMap(F),itl.Value())) {
652             if (Contains(theLeft,itl.Value())) {
653               AS.Load(NewSg);
654               IsLeft = Standard_True;
655             }
656             else {
657               AS.Load(NewSd);
658               IsLeft = Standard_False;
659             }
660             
661             nbfois = 1;
662             vtx2 = vtx;
663             p2 = knownp;
664             break;
665           }
666         }
667         if (!itl.More()) {
668           cout << "LocOpe_SplitDrafts: betite probleme "<< endl;
669           return;
670         }
671
672       }
673       else {
674         AS.Load(NewSg);
675       }
676
677       for (Standard_Integer it = 1; it<=nbfois; it++) {
678         if (it == 2) {
679           AS.Load(NewSd);
680         }
681         HAS->Set(AS);
682
683         intcs.Perform(HAC,HAS);
684         if (!intcs.IsDone()) {
685           return; // voir ce qu`on peut faire de mieux
686         }
687         Standard_Integer imin = 1;
688         Standard_Real delta = Abs(knownp - intcs.Point(1).W());
689         for (Standard_Integer i = 2;  i<= intcs.NbPoints(); i++) {
690           Standard_Real newdelta =  Abs(knownp - intcs.Point(i).W());
691           if (newdelta < delta) {
692             imin = i;
693             delta = newdelta;
694           }
695         }
696         if (it == 1) {
697           B.MakeVertex(vtx1,intcs.Point(imin).Pnt(),Precision::Confusion());
698           p1 = intcs.Point(imin).W();
699           knownp = p1;
700         }
701         else {
702           B.MakeVertex(vtx2,intcs.Point(imin).Pnt(),Precision::Confusion());
703           p2 = intcs.Point(imin).W();
704         }
705       }
706       if (Abs(p1-p2) > Precision::PConfusion()) {
707         TopoDS_Edge NewEdge;
708         B.MakeEdge(NewEdge,Newc,Precision::Confusion());
709         if (p1 < p2) {
710           B.Add(NewEdge,vtx1.Oriented(TopAbs_FORWARD));
711           B.Add(NewEdge,vtx2.Oriented(TopAbs_REVERSED));
712         }
713         else {
714           B.Add(NewEdge,vtx1.Oriented(TopAbs_REVERSED));
715           B.Add(NewEdge,vtx2.Oriented(TopAbs_FORWARD));
716         }
717         B.UpdateVertex(vtx1,p1,NewEdge,Precision::Confusion());
718         B.UpdateVertex(vtx2,p2,NewEdge,Precision::Confusion());
719         if (!newCs1.IsNull()) {
720           B.UpdateEdge(NewEdge,newCs1,
721                        TopoDS::Face(MapEV.FindFromKey(edg1)),
722                        Precision::Confusion());
723         }
724
725         if (!newCs2.IsNull()) {
726           B.UpdateEdge(NewEdge,newCs2,
727                        TopoDS::Face(MapEV.FindFromKey(edg2)),
728                        Precision::Confusion());
729         }
730
731       
732         MapEV.Add(vtx,NewEdge);
733
734         if (Choice == 1) {
735           TopoDS_Shape aLocalEdge = Ebind.EmptyCopied();
736           TopoDS_Edge NE = TopoDS::Edge(aLocalEdge);
737 //        TopoDS_Edge NE = TopoDS::Edge(Ebind.EmptyCopied());
738           for (exp2.Init(Ebind,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
739             const TopoDS_Vertex& thevtx = TopoDS::Vertex(exp2.Current());
740             if (thevtx.IsSame(vtx)) {
741               B.Add(NE,vtx1.Oriented(thevtx.Orientation()));
742               B.UpdateVertex(vtx1,p1,NE,Precision::Confusion());
743             }
744             else {
745               B.Add(NE,thevtx);
746               Standard_Real theprm = BRep_Tool::Parameter(thevtx,Ebind);
747               B.UpdateVertex(thevtx,theprm,NE,BRep_Tool::Tolerance(thevtx));
748             }
749           }
750           MapSonS.Bind(Ebind,NE.Oriented(TopAbs_FORWARD));
751           if (IsLeft) {
752             TopTools_ListOfShape thelist5;
753             MapSg.Bind(vtx, thelist5);
754             MapSg(vtx).Append(vtx1);
755           }
756           else {
757             TopTools_ListOfShape thelist6;
758             MapSd.Bind(vtx, thelist6);
759             MapSd(vtx).Append(vtx1);
760           }
761         }
762         else {
763           TopTools_ListOfShape thelist7, thelist8;
764           MapSg.Bind(vtx, thelist7);
765           MapSd.Bind(vtx, thelist8);
766           MapSg(vtx).Append(vtx1);
767           MapSd(vtx).Append(vtx2);
768         }
769       }
770       else {
771         MapEV.Add(vtx,vtx2); // on peut avoir vtx2 = vtx si choix == 1
772         if (Choice == 1) {
773           if (IsLeft) {
774             TopTools_ListOfShape thelist9;
775             MapSg.Bind(vtx, thelist9);
776             MapSg(vtx).Append(vtx);
777           }
778           else {
779             TopTools_ListOfShape thelist10;
780             MapSd.Bind(vtx, thelist10);
781             MapSd(vtx).Append(vtx);
782           }
783         }
784         else {
785           TopTools_ListOfShape thelist11, thelist12;
786           MapSg.Bind(vtx, thelist11);
787           MapSd.Bind(vtx, thelist12);
788           MapSg(vtx).Append(vtx2);
789           MapSd(vtx).Append(vtx2);
790         }
791       }
792     }
793   }
794
795
796   theMap.Clear();
797   for (exp.Init(theW,TopAbs_EDGE); exp.More(); exp.Next()) {
798     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
799     if (!theMap.Add(edg)) { // precaution sans doute inutile...
800       continue;
801     }
802     Standard_Integer indedg = MapEV.FindIndex(edg);
803     TopoDS_Face& GenF = TopoDS::Face(MapEV(indedg));
804     TopTools_ListOfShape thelist13, thelist14;
805     MapSg.Bind(edg, thelist13);  // genere a gauche
806     MapSd.Bind(edg, thelist14);  // genere a droite
807     TopoDS_Vertex Vf,Vl;
808     TopoDS_Shape aLocalEdge = edg.Oriented(TopAbs_FORWARD);
809     TopExp::Vertices(TopoDS::Edge(aLocalEdge),Vf,Vl);
810 //    TopExp::Vertices(TopoDS::Edge(edg.Oriented(TopAbs_FORWARD)),Vf,Vl);
811     TopoDS_Shape Gvf = MapEV.FindFromKey(Vf); 
812     TopoDS_Shape Gvl = MapEV.FindFromKey(Vl); 
813
814 /* Le code suivant est OK. On essaie de l`ameliorer
815
816     if (Gvf.ShapeType() == TopAbs_VERTEX &&
817         Gvl.ShapeType() == TopAbs_VERTEX) {
818       // en fait on doit pouvoir avoir 1 face a 2 cotes...
819       if (Gvf.IsSame(Vf)) {
820         MapW(edg) = edg;
821         MapSg(edg).Append(edg.Oriented(TopAbs_FORWARD));
822         MapSd(edg).Append(edg.Oriented(TopAbs_FORWARD));
823       }
824       else {
825         TopoDS_Edge NewEdg = NewEdge(edg,
826                                      GenF,NewSg,
827                                      TopoDS::Vertex(Gvf),
828                                      TopoDS::Vertex(Gvl));
829         if (NewEdg.IsNull()) {
830           return;
831         }
832         MapW(edg) = NewEdg;
833         MapSg(edg).Append(NewEdg);
834         MapSd(edg).Append(NewEdg);
835       }
836     }
837     else if (Gvf.ShapeType() == TopAbs_VERTEX  ||
838              Gvl.ShapeType() == TopAbs_VERTEX) {      // face triangulaire
839       TopoDS_Vertex Vfd,Vld,Vfg,Vlg;
840       if (Gvf.ShapeType() == TopAbs_VERTEX) {
841         Vfg = TopoDS::Vertex(Gvf);
842         Vfd = Vfg;
843         Vlg = TopoDS::Vertex(MapSg(Vl).First());
844         Vld = TopoDS::Vertex(MapSd(Vl).First());
845       }
846       else {
847         Vlg = TopoDS::Vertex(Gvl);
848         Vld = Vlg;
849         Vfg = TopoDS::Vertex(MapSg(Vf).First());
850         Vfd = TopoDS::Vertex(MapSd(Vf).First());
851       }
852
853       TopoDS_Edge NewEdgg = NewEdge(edg,GenF,NewSg,Vfg,Vlg);
854       if (NewEdgg.IsNull()) {
855         return;
856       }
857
858       TopoDS_Edge NewEdgd = NewEdge(edg,GenF,NewSd,Vfd,Vld);
859       if (NewEdgg.IsNull()) {
860         return;
861       }
862       MapSg(edg).Append(NewEdgg);
863       MapSd(edg).Append(NewEdgd);
864
865       TopTools_ListOfShape theedges;
866       theedges.Append(NewEdgg);
867       theedges.Append(NewEdgd);
868       if (Gvf.ShapeType() == TopAbs_EDGE) {
869         theedges.Append(Gvf);
870       }
871       else {//if (Gvl.ShapeType() == TopAbs_EDGE) {
872         theedges.Append(Gvl);
873       }
874       MakeFace(GenF,theedges);
875       MapW(edg) = GenF;
876     }
877     else {
878       // une face a 4 cotes
879       TopoDS_Vertex Vfd,Vld,Vfg,Vlg;
880
881       Vfg = TopoDS::Vertex(MapSg(Vf).First());
882       Vfd = TopoDS::Vertex(MapSd(Vf).First());
883       Vlg = TopoDS::Vertex(MapSg(Vl).First());
884       Vld = TopoDS::Vertex(MapSd(Vl).First());
885       
886       TopoDS_Vertex VVf1,VVl1,VVf2,VVl2;
887       TopExp::Vertices(TopoDS::Edge(Gvf.Oriented(TopAbs_FORWARD)),VVf1,VVl1);
888       TopExp::Vertices(TopoDS::Edge(Gvl.Oriented(TopAbs_FORWARD)),VVf2,VVl2);
889
890       TopoDS_Edge NewEdgg = NewEdge(edg,GenF,NewSg,Vfg,Vlg);
891       if (NewEdgg.IsNull()) {
892         return;
893       }
894       
895       TopoDS_Edge NewEdgd = NewEdge(edg,GenF,NewSd,Vfd,Vld);
896       if (NewEdgd.IsNull()) {
897         return;
898       }
899
900       if ((VVf1.IsSame(Vfg) && VVf2.IsSame(Vlg)) ||
901           (VVf1.IsSame(Vfd) && VVf2.IsSame(Vld))) {
902         // 4 cotes
903         MapSg(edg).Append(NewEdgg);
904         MapSd(edg).Append(NewEdgd);
905         
906         TopTools_ListOfShape theedges;
907         theedges.Append(NewEdgg);
908         theedges.Append(NewEdgd);
909         theedges.Append(Gvf);
910         theedges.Append(Gvl);
911         
912         MakeFace(GenF,theedges);
913         MapW(edg) = GenF;
914       }
915       else {
916 #ifdef DEB
917         cout << "Pb d'analyse" << endl;
918 #endif
919         return;
920       }
921     }
922 */
923     // nouveau code
924
925     TopoDS_Vertex Vfd,Vld,Vfg,Vlg;
926     if (Gvf.ShapeType() == TopAbs_VERTEX) {
927       Vfg = TopoDS::Vertex(Gvf);
928       Vfd = Vfg;
929     }
930     else {
931       Vfg = TopoDS::Vertex(MapSg(Vf).First());
932       Vfd = TopoDS::Vertex(MapSd(Vf).First());
933     }
934     if (Gvl.ShapeType() == TopAbs_VERTEX) {
935       Vlg = TopoDS::Vertex(Gvl);
936       Vld = Vlg;
937     }
938     else {
939       Vlg = TopoDS::Vertex(MapSg(Vl).First());
940       Vld = TopoDS::Vertex(MapSd(Vl).First());
941     }
942
943     TopoDS_Edge NewEdgg = NewEdge(edg,GenF,NewSg,Vfg,Vlg);
944     if (NewEdgg.IsNull()) {
945       return;
946     }
947     
948     TopoDS_Edge NewEdgd = NewEdge(edg,GenF,NewSd,Vfd,Vld);
949     if (NewEdgg.IsNull()) {
950       return;
951     }
952
953     Standard_Boolean isedg = Standard_False;
954     if (Gvf.ShapeType() == TopAbs_VERTEX &&
955         Gvl.ShapeType() == TopAbs_VERTEX) {
956       // edg ou face a 2 cotes
957
958       // Comparaison NewEdgg et NewEdgd
959       Standard_Real fg,lg,fd,ld;
960       Handle(Geom_Curve) Cg = BRep_Tool::Curve(NewEdgg,fg,lg);
961       Handle(Geom_Curve) Cd = BRep_Tool::Curve(NewEdgd,fd,ld);
962       Standard_Real prmg = (fg+lg)/2.;
963       Standard_Real prmd = (fd+ld)/2.;
964       gp_Pnt pg = Cg->Value(prmg);
965       gp_Pnt pd = Cd->Value(prmd);
966       Standard_Real Tol = Max(BRep_Tool::Tolerance(NewEdgg),
967                               BRep_Tool::Tolerance(NewEdgg));
968       if (pg.SquareDistance(pd) <= Tol*Tol) {
969         isedg = Standard_True;
970         // raffinement pour essayer de partager l`edge de depart...
971         Standard_Boolean modified = Standard_True;
972         if (Gvf.IsSame(Vf) && Gvl.IsSame(Vl)) {
973           // Comparaison avec l`edge de depart
974           Cd = BRep_Tool::Curve(edg,fd,ld);
975           prmd = (fd+ld)/2.;
976           pd = Cd->Value(prmd);
977           Tol = Max(BRep_Tool::Tolerance(NewEdgg),
978                     BRep_Tool::Tolerance(edg));
979           if (pg.SquareDistance(pd) <= Tol*Tol) {
980             modified = Standard_False;
981           }
982         }
983
984         if (!modified) {
985           MapW(edg) = edg;
986           MapSg(edg).Append(edg);
987           MapSd(edg).Append(edg);
988         }
989         else {
990           MapW(edg) = NewEdgg;
991           MapSg(edg).Append(NewEdgg);
992           MapSd(edg).Append(NewEdgg);
993         }
994       }
995     }
996
997     if (!isedg) {
998       // face a 2 ou 3 ou 4 cotes
999       MapSg(edg).Append(NewEdgg);
1000       MapSd(edg).Append(NewEdgd);
1001       
1002       TopTools_ListOfShape theedges;
1003       theedges.Append(NewEdgg);
1004       theedges.Append(NewEdgd);
1005       if (Gvf.ShapeType() == TopAbs_EDGE) {
1006         theedges.Append(Gvf);
1007       }
1008       if (Gvl.ShapeType() == TopAbs_EDGE) {
1009         theedges.Append(Gvl);
1010       }
1011       MakeFace(GenF,theedges);
1012       MapW(edg) = GenF;
1013     }
1014
1015   }
1016
1017
1018   TopTools_MapOfShape mapedgadded;
1019   TopTools_ListOfShape thefaces;
1020
1021   for (itl.Initialize(myMap(F)); itl.More(); itl.Next()) {
1022     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
1023     theMap.Clear();
1024     TopoDS_Face DrftFace; // elle est FORWARD
1025     Standard_Boolean IsLeft;
1026     if (Contains(theLeft,fac)) {
1027       B.MakeFace(DrftFace,NewSg,BRep_Tool::Tolerance(fac));
1028       IsLeft = Standard_True;
1029     }
1030     else {
1031       B.MakeFace(DrftFace,NewSd,BRep_Tool::Tolerance(fac));
1032       IsLeft = Standard_False;
1033     }
1034     
1035     TopExp_Explorer exp3;
1036     for (exp3.Init(fac.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
1037          exp3.More(); exp3.Next()) {
1038       const TopoDS_Shape& wir = exp3.Current();
1039       TopoDS_Wire NewWireOnF;
1040       B.MakeWire(NewWireOnF);
1041       for (exp.Init(wir.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1042            exp.More(); exp.Next()) {
1043         const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1044         if (!theMap.Add(edg)) { // precaution sans doute inutile...
1045           continue;
1046         }
1047         if (MapW.IsBound(edg)) { // edge du wire d`origine
1048           TopTools_ListIteratorOfListOfShape itld;
1049           TopAbs_Orientation ored = edg.Orientation();
1050           if (IsLeft) {
1051             itld.Initialize(MapSg(edg));
1052           }
1053           else {
1054             itld.Initialize(MapSd(edg));
1055           }
1056           for (; itld.More(); itld.Next()) {
1057             if (itld.Value().Orientation() == TopAbs_REVERSED) {
1058               ored = TopAbs::Reverse(ored);
1059             }
1060             TopoDS_Shape aLocalEdge = itld.Value().Oriented(ored);
1061             B.Add(NewWireOnF,TopoDS::Edge(aLocalEdge));
1062 //          B.Add(NewWireOnF,TopoDS::Edge(itld.Value().Oriented(ored)));
1063           }
1064         }
1065         else {
1066           Handle(Geom_Surface) NewS;
1067           if (IsLeft) {
1068             NewS = NewSg;
1069           }
1070           else {
1071             NewS = NewSd;
1072           }
1073           Standard_Integer indedg = MapEV.FindIndex(edg);
1074           const TopoDS_Face& GenF = TopoDS::Face(MapEV(indedg));
1075           TopoDS_Vertex Vf,Vl;
1076           TopoDS_Shape aLocalEdge = edg.Oriented(TopAbs_FORWARD);
1077           TopExp::Vertices(TopoDS::Edge(aLocalEdge),Vf,Vl);
1078 //        TopExp::Vertices(TopoDS::Edge(edg.Oriented(TopAbs_FORWARD)),Vf,Vl);
1079           TopoDS_Shape Gvf = MapEV.FindFromKey(Vf); 
1080           TopoDS_Shape Gvl = MapEV.FindFromKey(Vl); 
1081           if (Gvf.ShapeType() == TopAbs_VERTEX &&
1082               Gvl.ShapeType() == TopAbs_VERTEX) {
1083             if (!Gvf.IsSame(Vf) || !Gvl.IsSame(Vl)) {
1084               TopoDS_Edge NewEdg = NewEdge(edg,GenF,NewS,
1085                                            TopoDS::Vertex(Gvf),
1086                                            TopoDS::Vertex(Gvl));
1087               if (NewEdg.IsNull()) {
1088                 return;
1089               }
1090
1091               MapSonS.Bind(edg,NewEdg);
1092
1093               if (NewEdg.Orientation() == TopAbs_REVERSED) {
1094                 NewEdg.Orientation(TopAbs::Reverse(edg.Orientation()));
1095               }
1096               else {
1097                 NewEdg.Orientation(edg.Orientation());
1098               }         
1099               B.Add(NewWireOnF,NewEdg);
1100             }
1101             else { // Frozen???
1102               B.Add(NewWireOnF,edg);
1103             }
1104           }
1105           else {
1106             TopoDS_Vertex Vff,Vll;
1107             if (Gvf.ShapeType() == TopAbs_VERTEX) {
1108               Vff = TopoDS::Vertex(Gvf);
1109             }
1110             else {
1111               if (IsLeft) {
1112                 Vff = TopoDS::Vertex(MapSg(Vf).First());
1113               }
1114               else {
1115                 Vff = TopoDS::Vertex(MapSd(Vf).First());
1116               }
1117             }
1118             if (Gvl.ShapeType() == TopAbs_VERTEX) {
1119               Vll = TopoDS::Vertex(Gvl);
1120             }
1121             else {
1122               if (IsLeft) {
1123                 Vll = TopoDS::Vertex(MapSg(Vl).First());
1124               }
1125               else {
1126                 Vll = TopoDS::Vertex(MapSd(Vl).First());
1127               }
1128             }
1129             
1130             TopoDS_Edge NewEdg = NewEdge(edg,GenF,NewS,Vff,Vll);
1131             if (NewEdg.IsNull()) {
1132               return;
1133             }
1134
1135             if (!MapW.IsBound(Vf) && !MapW.IsBound(Vl)) {
1136               MapSonS.Bind(edg,NewEdg);
1137             }
1138 //          else if (MapW.IsBound(Vf) && MapW.IsBound(Vl)) {
1139               
1140
1141 //          }
1142             else {
1143               if (MapW.IsBound(Vf)) {
1144                 if (Gvf.ShapeType() != TopAbs_EDGE || 
1145                     mapedgadded.Contains(Gvf)) {
1146                   MapSonS.Bind(edg,NewEdg);
1147                 }
1148                 else {
1149                   TopoDS_Wire NewWir;
1150                   B.MakeWire(NewWir);
1151                   B.Add(NewWir,NewEdg);
1152
1153                   TopoDS_Vertex Vf2,Vl2;
1154                   TopExp::Vertices(TopoDS::Edge(Gvf),Vf2,Vl2);
1155
1156                   //TopAbs_Orientation ornw = NewEdg.Orientation();
1157
1158                   // ici bug orientation : voir tspdrft6
1159
1160 //                if ((ornw == TopAbs_FORWARD && Vl2.IsSame(Vff)) ||
1161 //                    (ornw == TopAbs_REVERSED && Vl2.IsSame(Vll))) {
1162                   if (Vl2.IsSame(Vff)) {
1163                     B.Add(NewWir,Gvf.Oriented(TopAbs_FORWARD));
1164                   }
1165                   else {
1166                     B.Add(NewWir,Gvf.Oriented(TopAbs_REVERSED));
1167                   }
1168                   mapedgadded.Add(Gvf);
1169                   MapSonS.Bind(edg,NewWir); // NewWire est FORWARD
1170                 }
1171               }
1172               else {
1173                 if (Gvl.ShapeType() != TopAbs_EDGE ||
1174                     mapedgadded.Contains(Gvl)) {
1175                   MapSonS.Bind(edg,NewEdg);
1176                 }
1177                 else {
1178                   TopoDS_Wire NewWir;
1179                   B.MakeWire(NewWir);
1180                   B.Add(NewWir,NewEdg);
1181
1182                   TopoDS_Vertex Vf2,Vl2;
1183                   TopExp::Vertices(TopoDS::Edge(Gvl),Vf2,Vl2);
1184
1185                   //TopAbs_Orientation ornw = NewEdg.Orientation();
1186
1187                   // ici bug orientation : voir tspdrft6
1188
1189 //                if ((ornw == TopAbs_FORWARD && Vl2.IsSame(Vff)) ||
1190 //                    (ornw == TopAbs_REVERSED && Vl2.IsSame(Vll))) {
1191                   if (Vf2.IsSame(Vll)) {
1192                     B.Add(NewWir,Gvl.Oriented(TopAbs_FORWARD));
1193                   }
1194                   else {
1195                     B.Add(NewWir,Gvl.Oriented(TopAbs_REVERSED));
1196                   }
1197                   mapedgadded.Add(Gvl);
1198                   MapSonS.Bind(edg,NewWir); // NewWire est FORWARD
1199                 }
1200               }
1201             }
1202             if (NewEdg.Orientation() == TopAbs_REVERSED) {
1203               NewEdg.Orientation(TopAbs::Reverse(edg.Orientation()));
1204             }
1205             else {
1206               NewEdg.Orientation(edg.Orientation());
1207             }           
1208             B.Add(NewWireOnF,NewEdg);
1209           }
1210         }
1211       }
1212       B.Add(DrftFace,NewWireOnF.Oriented(wir.Orientation()));
1213     }
1214     thefaces.Append(DrftFace);
1215   }
1216
1217   BRepTools_Substitution theSubs;
1218   TopTools_DataMapIteratorOfDataMapOfShapeShape itdmss;
1219   for (itdmss.Initialize(MapSonS);
1220        itdmss.More(); itdmss.Next()) {
1221     TopTools_ListOfShape lsubs;
1222     for (exp.Init(itdmss.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
1223       lsubs.Append(exp.Current());
1224     }
1225     theSubs.Substitute(itdmss.Key(),lsubs);
1226   }
1227
1228   // on reconstruit les faces
1229   for (exp.Init(Res,TopAbs_FACE); exp.More(); exp.Next()) {
1230     if (Contains(myMap(F),exp.Current())) {
1231       continue;
1232     }
1233     theSubs.Build(exp.Current());
1234   }
1235
1236   // Stockage des descendants
1237 //  for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdmsls(myMap);
1238   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdmsls(myMap) ;
1239   for ( ; itdmsls.More(); itdmsls.Next()) {
1240     if (itdmsls.Key().ShapeType() == TopAbs_EDGE) {
1241       TopTools_ListOfShape thedesc;
1242       theMap.Clear();
1243       for (itl.Initialize(itdmsls.Value());itl.More(); itl.Next()) {
1244         if (theMap.Add(MapW(itl.Value()))) {
1245           thedesc.Append(MapW(itl.Value()));
1246         }
1247       }
1248       myMap(itdmsls.Key()) = thedesc;
1249     }
1250     else if (itdmsls.Key().IsSame(F)) {
1251       myMap(F).Clear();
1252       for (itl.Initialize(thefaces); itl.More(); itl.Next()) {
1253         myMap(F).Append(itl.Value());
1254       }
1255     }
1256     else {
1257       TopTools_ListOfShape thedesc;
1258       theMap.Clear();
1259       for (itl.Initialize(itdmsls.Value());itl.More(); itl.Next()) {
1260         if (theSubs.IsCopied(itl.Value())) {
1261           if (theSubs.Copy(itl.Value()).Extent() != 1) {
1262 #ifdef DEB
1263             cout << "Invalid number of descendant" << endl;
1264 #endif
1265             return;
1266           }
1267           else {
1268             if (theMap.Add(theSubs.Copy(itl.Value()).First())) {
1269               thedesc.Append(theSubs.Copy(itl.Value()).First());
1270             }
1271           }
1272         }
1273         else if (theMap.Add(itl.Value())) {
1274           thedesc.Append(itl.Value());
1275         }
1276       }
1277       myMap(itdmsls.Key()) = thedesc;
1278     }
1279   }
1280
1281   theMap.Clear();
1282   thefaces.Clear();
1283   for (itdmsls.Initialize(myMap);itdmsls.More(); itdmsls.Next()) {
1284     for (itl.Initialize(itdmsls.Value());itl.More(); itl.Next()) {
1285       if (itl.Value().ShapeType() == TopAbs_FACE &&
1286           theMap.Add(itl.Value())) {
1287         thefaces.Append(itl.Value());
1288       }
1289     }
1290   }
1291   LocOpe_BuildShape BS(thefaces);
1292   myResult = BS.Shape();
1293 }
1294
1295
1296 //=======================================================================
1297 //function : Shape
1298 //purpose  : 
1299 //=======================================================================
1300
1301 const TopoDS_Shape& LocOpe_SplitDrafts::Shape () const
1302 {
1303   if (myResult.IsNull()) {
1304     StdFail_NotDone::Raise();
1305   }
1306   return myResult;
1307 }
1308
1309 //=======================================================================
1310 //function : ShapesFromShape
1311 //purpose  : 
1312 //=======================================================================
1313
1314 const TopTools_ListOfShape& LocOpe_SplitDrafts::ShapesFromShape 
1315    (const TopoDS_Shape& S) const
1316 {
1317   if (myResult.IsNull()) {
1318     StdFail_NotDone::Raise();
1319   }
1320   return myMap(S);
1321 }
1322
1323
1324 //=======================================================================
1325 //function : NewPlane
1326 //purpose  : 
1327 //=======================================================================
1328
1329 static Standard_Boolean NewPlane(const TopoDS_Face& F,
1330                                  const gp_Dir& Extr,
1331                                  const gp_Pln& Neutr,
1332                                  const Standard_Real Ang,
1333                                  gp_Pln& Newpl,
1334                                  gp_Ax1& NormalF,
1335                                  const Standard_Boolean Modify)
1336 {
1337
1338
1339   // Determination du nouveau plan incline
1340   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
1341   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1342     S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
1343   }
1344   Handle(Geom_Plane) P = Handle(Geom_Plane)::DownCast(S);
1345   if (P.IsNull()) {
1346     return Standard_False;
1347   }
1348
1349   gp_Pln Plorig = P->Pln();
1350   if (!Modify) {
1351     Newpl = Plorig;
1352     NormalF = Newpl.Axis();
1353     if ((Newpl.Direct() && F.Orientation() == TopAbs_REVERSED) ||
1354        (!Newpl.Direct() && F.Orientation() == TopAbs_FORWARD)) {
1355       NormalF.Reverse();
1356     }
1357     return Standard_True;
1358   }
1359
1360   gp_Ax1 Axe;
1361   Standard_Real Theta;
1362
1363   IntAna_QuadQuadGeo i2pl(Plorig,Neutr,
1364                           Precision::Angular(),Precision::Confusion());
1365   
1366   if (i2pl.IsDone() && i2pl.TypeInter() == IntAna_Line) {
1367     gp_Lin LinInters = i2pl.Line(1);
1368     gp_Dir nx = LinInters.Direction();
1369     NormalF = Plorig.Axis();
1370     gp_Dir ny = NormalF.Direction().Crossed(nx);
1371     Standard_Real a = Extr.Dot(nx);
1372     if (Abs(a) <=1-Precision::Angular()) { 
1373       Standard_Real b = Extr.Dot(ny);
1374       Standard_Real c = Extr.Dot(NormalF.Direction());
1375       Standard_Boolean direct(Plorig.Direct());
1376       TopAbs_Orientation Oris = F.Orientation();
1377       if ((direct && Oris == TopAbs_REVERSED) ||
1378           (!direct && Oris == TopAbs_FORWARD)) {
1379         b = -b;
1380         c = -c;
1381         NormalF.Reverse();
1382       }
1383       Standard_Real denom = Sqrt(1-a*a);
1384       Standard_Real Sina = Sin(Ang);
1385       if (denom>Abs(Sina)) {
1386         Standard_Real phi = ATan2(b/denom,c/denom);
1387         Standard_Real theta0 = ACos(Sina/denom); 
1388         Theta = theta0 - phi;
1389         if (Cos(Theta) <0.) {
1390           Theta = -theta0 -phi;
1391         }
1392         Axe = LinInters.Position();
1393         Newpl = Plorig.Rotated(Axe,Theta);
1394         return Standard_True;
1395       }
1396     }
1397   }
1398   cout << "fin newplane return standard_false" << endl;
1399   return Standard_False;
1400 }
1401
1402
1403 //=======================================================================
1404 //function : MakeFace
1405 //purpose  : 
1406 //=======================================================================
1407
1408 static void MakeFace(TopoDS_Face& F,
1409                      TopTools_ListOfShape& ledg)
1410 {
1411
1412   // ledg est une liste d'edge
1413
1414   BRep_Builder B;
1415
1416   // Verification de l`existence des p-curves. Celles qui manquent
1417   // correspondent necessairement a des isos (et meme des iso u).
1418
1419   Standard_Real f,l;
1420 //  for (TopTools_ListIteratorOfListOfShape itl(ledg); 
1421   TopTools_ListIteratorOfListOfShape itl(ledg) ;
1422   for ( ; itl.More(); itl.Next()) {
1423     TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
1424     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1425     if (C2d.IsNull()) {
1426       BRep_Tool::Range(edg,f,l);
1427       TopoDS_Vertex V1,V2;
1428       TopExp::Vertices(edg,V1,V2);
1429         TopTools_ListIteratorOfListOfShape itl2;
1430       for (itl2.Initialize(ledg); 
1431            itl2.More(); itl2.Next()) {
1432         const TopoDS_Edge& edg2 = TopoDS::Edge(itl2.Value());
1433         if (edg2.IsSame(edg)) {
1434           continue;
1435         }
1436         TopoDS_Vertex Vp1,Vp2;
1437         TopExp::Vertices(edg2,Vp1,Vp2);
1438         if (Vp1.IsSame(V1) || Vp2.IsSame(V1) ||
1439             Vp1.IsSame(V2) || Vp2.IsSame(V2)) {
1440           Standard_Real f2,l2;
1441           Handle(Geom2d_Curve) C22d = BRep_Tool::CurveOnSurface(edg2,F,f2,l2);
1442           if (!C22d.IsNull()) {
1443             gp_Pnt2d pt2d;
1444             if (Vp1.IsSame(V1)) {
1445               pt2d = C22d->Value(f2);
1446               pt2d.SetY(pt2d.Y()-f);
1447             }
1448             else if (Vp2.IsSame(V1)) {
1449               pt2d = C22d->Value(l2);
1450               pt2d.SetY(pt2d.Y()-f);
1451             }
1452             else if (Vp1.IsSame(V2)) {
1453               pt2d = C22d->Value(f2);
1454               pt2d.SetY(pt2d.Y()-l);
1455             }
1456             else if (Vp2.IsSame(V2)) {
1457               pt2d = C22d->Value(l2);
1458               pt2d.SetY(pt2d.Y()-l);
1459             }
1460             C2d = new Geom2d_Line(pt2d,gp::DY2d());
1461             B.UpdateEdge(edg,C2d,F,BRep_Tool::Tolerance(edg));
1462             break;
1463           }
1464         }
1465       }
1466       if (C2d.IsNull()) {
1467         cout << "Ca merde violemment" << endl;
1468       }
1469     }
1470   }
1471
1472   TopTools_ListOfShape lwires;
1473   Standard_Boolean alldone = ledg.IsEmpty();
1474   while (!alldone) {
1475     TopoDS_Wire Wnew;
1476     B.MakeWire(Wnew);
1477     TopoDS_Shape aLocalShape = ledg.First();
1478     const TopoDS_Edge& edg = TopoDS::Edge(aLocalShape);
1479 //    const TopoDS_Edge& edg = TopoDS::Edge(ledg.First());
1480     TopoDS_Vertex VFirst,VLast;
1481     if (edg.Orientation() == TopAbs_FORWARD) {
1482       TopExp::Vertices(edg,VFirst,VLast);
1483     }
1484     else {
1485       TopExp::Vertices(edg,VLast,VFirst);
1486     }
1487     B.Add(Wnew,edg);
1488     ledg.RemoveFirst();
1489     // on suppose VFirst et VLast non nuls
1490     Standard_Boolean wdone = (ledg.IsEmpty() || VFirst.IsSame(VLast));
1491     while (!wdone) {
1492       TopoDS_Vertex VF,VL;
1493
1494       TopAbs_Orientation oredg = TopAbs_FORWARD;
1495
1496       for (itl.Initialize(ledg); itl.More(); itl.Next()) {
1497         const TopoDS_Edge& edg2 = TopoDS::Edge(itl.Value());
1498         TopoDS_Shape aLocalShape  = edg2.Oriented(TopAbs_FORWARD);
1499         TopExp::Vertices(TopoDS::Edge(aLocalShape),VF,VL);
1500 //      TopExp::Vertices(TopoDS::Edge(edg2.Oriented(TopAbs_FORWARD)),VF,VL);
1501         if (VF.IsSame(VLast)) {
1502           VLast = VL;
1503           oredg = TopAbs_FORWARD;
1504           break;
1505         }
1506         else if (VL.IsSame(VFirst)) {
1507           VFirst = VF;
1508           oredg = TopAbs_FORWARD;
1509           break;
1510         }
1511         else if (VF.IsSame(VFirst)) {
1512           VFirst = VL;
1513           oredg = TopAbs_REVERSED;
1514           break;
1515         }
1516         else if (VL.IsSame(VLast)) {
1517           VLast = VF;
1518           oredg = TopAbs_REVERSED;
1519           break;
1520         }
1521
1522       }
1523       if (!itl.More()) {
1524         wdone = Standard_True;
1525       }
1526       else {
1527         TopoDS_Shape aLocalShape = itl.Value().Oriented(oredg);
1528         B.Add(Wnew,TopoDS::Edge(aLocalShape));
1529 //      B.Add(Wnew,TopoDS::Edge(itl.Value().Oriented(oredg)));
1530         ledg.Remove(itl);
1531         wdone = (ledg.IsEmpty() || VFirst.IsSame(VLast));
1532       }
1533     }
1534     lwires.Append(Wnew);
1535     alldone = ledg.IsEmpty();
1536   }
1537
1538
1539
1540
1541   F.Orientation(TopAbs_FORWARD);
1542   for (itl.Initialize(lwires); itl.More(); itl.Next()) {
1543     TopoDS_Shape aLocalShape = F.EmptyCopied();
1544     TopoDS_Face NewFace = TopoDS::Face(aLocalShape);
1545 //    TopoDS_Face NewFace = TopoDS::Face(F.EmptyCopied());
1546     B.Add(NewFace,itl.Value());
1547     GProp_GProps GP;
1548     BRepGProp::SurfaceProperties(NewFace,GP);
1549     if (GP.Mass() < 0) {
1550       itl.Value().Reverse();
1551     }
1552   }
1553   if (lwires.Extent() == 1) {
1554     B.Add(F,lwires.First());
1555   }
1556   else {
1557     cout << "Not yet implemented : nbwire >= 2" << endl;
1558   }
1559
1560 }
1561
1562
1563 //=======================================================================
1564 //function : Contains
1565 //purpose  : 
1566 //=======================================================================
1567
1568 static Standard_Boolean Contains(const TopTools_ListOfShape& ll,
1569                                  const TopoDS_Shape& s)
1570 {
1571   TopTools_ListIteratorOfListOfShape itl;
1572   for (itl.Initialize(ll); itl.More(); itl.Next()) {
1573     if (itl.Value().IsSame(s)) {
1574       return Standard_True;
1575     }
1576   }
1577   return Standard_False;
1578 }
1579
1580
1581
1582 //=======================================================================
1583 //function : Contains
1584 //purpose  : 
1585 //=======================================================================
1586
1587 static TopoDS_Edge  NewEdge(const TopoDS_Edge& edg,
1588                             const TopoDS_Face& F,
1589                             const Handle(Geom_Surface)& NewS,
1590                             const TopoDS_Vertex& V1,
1591                             const TopoDS_Vertex& V2)
1592 {
1593   TopoDS_Edge NewEdg;
1594   Handle(Geom_Surface) S1 = BRep_Tool::Surface(F);
1595   Standard_Boolean AppS1 = Standard_False;
1596   if (S1->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
1597     AppS1 = Standard_True;
1598   }
1599
1600
1601   GeomInt_IntSS i2s(S1,NewS,Precision::Confusion(),Standard_True,AppS1);
1602   if (!i2s.IsDone() || i2s.NbLines() <= 0) {
1603     return NewEdg;
1604   }
1605
1606   BRep_Builder B;
1607 //  Standard_Real pmin, Dist, DistMin;
1608   Standard_Real Dist2, Dist2Min;
1609   Standard_Real prmf=0,prml=0;
1610   GeomAdaptor_Curve TheCurve;
1611         
1612   Standard_Integer i,imin,k;
1613   gp_Pnt pvf = BRep_Tool::Pnt(V1);
1614   gp_Pnt pvl = BRep_Tool::Pnt(V2);
1615   imin = 0;
1616   for (i=1; i<= i2s.NbLines(); i++) {
1617     TheCurve.Load(i2s.Line(i));
1618     Extrema_ExtPC myExtPC(pvf,TheCurve);
1619     
1620     if (myExtPC.IsDone()) {
1621       gp_Pnt p1b,p2b;
1622       Standard_Real thepmin = TheCurve.FirstParameter();
1623       myExtPC.TrimmedSquareDistances(Dist2Min,Dist2,p1b,p2b);
1624       if (Dist2 < Dist2Min && !TheCurve.IsPeriodic()) {
1625         Dist2Min = Dist2;
1626         thepmin = TheCurve.LastParameter();
1627       }
1628       for (k=1; k<=myExtPC.NbExt(); k++) {
1629         Dist2 = myExtPC.SquareDistance(k);
1630         if (Dist2 < Dist2Min) {
1631           Dist2Min = Dist2;
1632           thepmin = myExtPC.Point(k).Parameter();
1633         }
1634       }
1635       
1636       if (Dist2Min  <= Precision::SquareConfusion()) {
1637         prmf = thepmin;
1638         myExtPC.Perform(pvl);
1639         if (myExtPC.IsDone()) {
1640           thepmin = TheCurve.LastParameter();
1641           myExtPC.TrimmedSquareDistances(Dist2,Dist2Min,p1b,p2b);
1642           if (Dist2 < Dist2Min && !TheCurve.IsClosed()) {
1643             Dist2Min = Dist2;
1644             thepmin = TheCurve.FirstParameter();
1645           }
1646           for (k=1; k<=myExtPC.NbExt(); k++) {
1647             Dist2 = myExtPC.SquareDistance(k);
1648             if (Dist2 < Dist2Min) {
1649               Dist2Min = Dist2;
1650               thepmin = myExtPC.Point(k).Parameter();
1651             }
1652           }
1653           
1654       if (Dist2Min  <= Precision::SquareConfusion()) {
1655             prml = thepmin;
1656             break;
1657           }
1658         }
1659       }
1660     }
1661   }
1662
1663   if (i <= i2s.NbLines()) {
1664     Standard_Boolean rev = Standard_False;
1665     TopoDS_Vertex Vf = V1;
1666     TopoDS_Vertex Vl = V2;
1667     Handle(Geom_Curve) Cimg = i2s.Line(i);
1668     Handle(Geom2d_Curve) Cimg2d;
1669     if (AppS1) {
1670       Cimg2d = i2s.LineOnS1(i);
1671     }
1672
1673     if (Cimg->IsPeriodic()) {
1674
1675       Standard_Real period = Cimg->Period();
1676       Standard_Real imf = Cimg->FirstParameter();
1677       Standard_Real iml = Cimg->LastParameter();
1678
1679       Standard_Real f,l;
1680       BRep_Tool::Range(edg,f,l);
1681       Standard_Real delt = l-f;
1682       Standard_Real delt1 = Abs(prml-prmf);
1683       Standard_Real delt2 = Abs(period-delt1);
1684       
1685       if (delt1 == 0 || delt2 == 0) {
1686 //      prmf = 0;
1687 //      prml = period;
1688         prmf = imf;
1689         prml = iml;
1690       }
1691       else {
1692         if (Abs(delt1-delt) > Abs(delt2-delt)) {
1693           // le bon ecart est delt2...
1694           if (prml > prmf) {
1695             if (prml < iml) {
1696               prmf += period;
1697             }
1698             else {
1699               prml -= period;
1700             }
1701           }
1702           else {
1703             if (prmf < iml) {
1704               prml += period;
1705             }
1706             else {
1707               prmf -= period;
1708             }
1709           }
1710         }
1711         else if (Abs(delt1-delt) < Abs(delt2-delt)) {
1712           if (prmf >= iml && prml >= iml) {
1713             prmf -= period;
1714             prml -= period;
1715           }
1716           else if (prmf <= imf && prml <= imf) {
1717             prmf += period;
1718             prml += period;
1719           }
1720         }
1721         else { // egalite; on priveligie l'ordre f,l
1722           if (prmf > prml) {
1723             prmf -= period;
1724           }
1725           if (prmf >= iml && prml >= iml) {
1726             prmf -= period;
1727             prml -= period;
1728           }
1729           else if (prmf <= imf && prml <= imf) {
1730             prmf += period;
1731             prml += period;
1732           }
1733         }
1734       }
1735 #ifdef DEB
1736       Standard_Real ptol = Precision::PConfusion();
1737       if (prmf < imf - ptol || prmf > iml + ptol ||
1738           prml < imf - ptol || prml > iml + ptol) {
1739         cout << "Ca ne va pas aller" << endl;
1740       }
1741 #endif
1742
1743
1744     }
1745
1746     if (S1->IsUPeriodic()) {
1747
1748       Standard_Real speriod = S1->UPeriod();
1749 //      Standard_Real f,l;
1750       gp_Pnt2d pf,pl;
1751       pf = Cimg2d->Value(prmf);
1752       pl = Cimg2d->Value(prml);
1753
1754       Standard_Real Uf = pf.X();
1755       Standard_Real Ul = pl.X();
1756       Standard_Real ptra = 0.0;
1757
1758       Standard_Real Ustart = Min(Uf,Ul);
1759       while (Ustart < -Precision::PConfusion()) {
1760         Ustart += speriod;
1761         ptra += speriod;
1762       }
1763       while (Ustart > speriod - Precision::PConfusion()) {
1764         Ustart -= speriod;
1765         ptra -= speriod;
1766       }
1767       if (ptra != 0) {
1768         Cimg2d->Translate(gp_Vec2d(ptra,0.));
1769       }
1770
1771
1772     }
1773     if (prmf < prml) {
1774       Vf.Orientation(TopAbs_FORWARD);
1775       Vl.Orientation(TopAbs_REVERSED);
1776     }
1777     else {
1778       Vf.Orientation(TopAbs_REVERSED);
1779       Vl.Orientation(TopAbs_FORWARD);
1780       rev = Standard_True;;
1781     }
1782
1783     B.MakeEdge(NewEdg,Cimg,Precision::Confusion());
1784
1785     B.Add(NewEdg,Vf);
1786     B.Add(NewEdg,Vl);
1787     B.UpdateVertex(Vf,prmf,NewEdg,Precision::Confusion());
1788     B.UpdateVertex(Vl,prml,NewEdg,Precision::Confusion());
1789     if (AppS1) {
1790       B.UpdateEdge(NewEdg,Cimg2d,F,Precision::Confusion());
1791     }
1792
1793
1794     if (rev) {
1795       NewEdg.Orientation(TopAbs_REVERSED);
1796     }
1797   }
1798   return NewEdg;
1799 }