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