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