0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / LocOpe / LocOpe_Generator.cxx
1 // Created on: 1996-01-09
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 // Modifed:     Portage NT 7-5-97 DPF (return NewParameter)
18
19 #include <LocOpe_Generator.ixx>
20
21 #include <TopTools_MapOfShape.hxx>
22 #include <TopTools_DataMapOfShapeShape.hxx>
23 #include <TopTools_DataMapOfShapeListOfShape.hxx>
24 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
25 #include <TopTools_ListIteratorOfListOfShape.hxx>
26 #include <TopTools_MapIteratorOfMapOfShape.hxx>
27 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
28 #include <TopoDS_Iterator.hxx>
29 #include <TopoDS_Solid.hxx>
30 #include <TopoDS_Wire.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Vertex.hxx>
33
34
35 #include <TopExp_Explorer.hxx>
36
37 #include <gp_Pln.hxx>
38 #include <gp_Cylinder.hxx>
39
40 #include <BRep_Builder.hxx>
41 #include <BRep_Tool.hxx>
42 #include <BRepAlgo_Loop.hxx>
43
44 #include <Geom_Surface.hxx>
45 #include <Geom_RectangularTrimmedSurface.hxx>
46 #include <Geom_Plane.hxx>
47 #include <Geom_CylindricalSurface.hxx>
48 #include <Geom_Curve.hxx>
49 #include <Geom_TrimmedCurve.hxx>
50 #include <Geom_Line.hxx>
51 #include <Geom_Circle.hxx>
52 #include <Geom2d_Curve.hxx>
53
54 #include <LocOpe_BuildShape.hxx>
55
56 #include <TopoDS.hxx>
57 #include <TopExp.hxx>
58 #include <BRepTools.hxx>
59 #include <GeomProjLib.hxx>
60 #include <ElCLib.hxx>
61 #include <Precision.hxx>
62
63 static Standard_Boolean ToFuse(const TopoDS_Face& ,
64                                const TopoDS_Face&);
65
66
67 static Standard_Boolean ToFuse(const TopoDS_Edge& ,
68                                const TopoDS_Edge&);
69
70
71 static Standard_Boolean ToFuse(const TopoDS_Edge&,
72                                const TopoDS_Face&,
73                                const TopoDS_Vertex&,
74                                const TopTools_MapOfShape&);
75
76 static Standard_Real NewParameter(const TopoDS_Edge&,
77                                   const TopoDS_Vertex&,
78                                   const TopoDS_Edge&,
79                                   const TopoDS_Vertex&);
80
81
82 //=======================================================================
83 //function : Perform
84 //purpose  : 
85 //=======================================================================
86
87 void LocOpe_Generator::Perform(const Handle(LocOpe_GeneratedShape)& G)
88 {
89   if (myShape.IsNull()) {
90     Standard_NullObject::Raise();
91   }
92   myDone = Standard_False;
93   myRes.Nullify();
94 //  myDescFaces.Clear();
95   myModShapes.Clear();
96 //  myFFromE.Clear();
97
98   const TopTools_ListOfShape& ledges = G->GeneratingEdges();
99
100   // On genere une liste des faces a gauche du wire. Equivalent du LeftOf.
101   // Attention : il faudra bien propager pour ne pas oublier des faces
102   // a l`interieur
103
104   TopExp_Explorer exp, exp2, exp3;
105   TopTools_MapOfShape theLeft; // Faces a gauche
106
107   TopTools_MapOfShape GEdg,GVtx; // Edges et vertex generateurs
108
109   TopTools_ListIteratorOfListOfShape itl,itl2;
110
111
112   for (itl.Initialize(ledges); itl.More(); itl.Next()) {
113     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
114     
115     GEdg.Add(edg);
116     for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
117       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
118       if (!GVtx.Contains(vtx)) {
119         GVtx.Add(vtx);
120       }
121     }
122     for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
123       const TopoDS_Face& fac = TopoDS::Face(exp2.Current());
124       for (exp3.Init(fac,TopAbs_EDGE); exp3.More(); exp3.Next()) {
125         if (exp3.Current().IsSame(edg) && 
126             exp3.Current().Orientation() == edg.Orientation()) {
127           theLeft.Add(fac);
128           TopTools_ListOfShape emptylist;
129           if(!myModShapes.IsBound(fac)) {
130             myModShapes.Bind(fac,emptylist);
131           }  
132           break;
133         }
134       }
135       if (exp3.More()) {
136         break;
137       }
138     }
139   }
140
141   TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
142   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
143
144   TopTools_DataMapOfShapeListOfShape theEEMap;
145   TopTools_DataMapOfShapeListOfShape theFFMap;
146   TopTools_MapOfShape toRemove;
147   TopTools_MapIteratorOfMapOfShape itm;
148   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itf;
149
150   // recherche des fusions de faces
151   for (itm.Initialize(GEdg); itm.More(); itm.Next()) {
152     const TopoDS_Edge& edg = TopoDS::Edge(itm.Key());
153     if (!theEFMap.Contains(edg)) {
154       continue;
155     }
156     for (itl2.Initialize(theEFMap.FindFromKey(edg));itl2.More();itl2.Next()){
157       if (!theLeft.Contains(itl2.Value())) {
158         break;
159       }
160     }
161     if (!itl2.More()) { // edge "interne" au shell, ou bord libre
162     }
163     else {
164       const TopoDS_Face& fac = TopoDS::Face(itl2.Value());
165       TopoDS_Face facbis = G->Generated(edg);
166       if (ToFuse(fac,facbis)) {
167         // On recherche si une face a deja fusionne avec facbis
168         Standard_Boolean facbisfound = Standard_False;
169         for (itf.Initialize(theFFMap); itf.More(); itf.Next()) {
170           if (itf.Key().IsSame(fac)) {
171             continue;
172           }
173           for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
174             if (itl.Value().IsSame(facbis)) {
175               facbisfound = Standard_True;
176               break;
177             }
178           }
179           if (facbisfound) {
180             theFFMap(itf.Key()).Append(fac);
181             toRemove.Add(fac);
182             toRemove.Add(edg);
183             break;
184           }
185         }
186
187         if (!facbisfound) {
188           if (!theFFMap.IsBound(fac)) {
189             TopTools_ListOfShape thelist;
190             theFFMap.Bind(fac, thelist);
191           }
192           for (itl.Initialize(theFFMap(fac)); itl.More(); itl.Next()) {
193             if (itl.Value().IsSame(facbis)) {
194               break;
195             }
196           }
197           if (!itl.More()) {
198             theFFMap(fac).Append(facbis);
199           }
200           toRemove.Add(edg);
201           toRemove.Add(facbis);
202         }
203       }
204       else { // face generee par edg : on la marque.
205 //      myFFromE.Bind(edg,facbis);
206       }
207     }
208   }
209
210
211   // Il faut ici ajouter dans toRemove les edges de connexites entre faces
212   // a fusionner avec une meme face de base
213
214 //  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itf(theFFMap);
215   itf.Initialize(theFFMap);
216   for (; itf.More(); itf.Next()) {
217     for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
218       for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
219         const TopoDS_Edge& ed = TopoDS::Edge(exp.Current());
220         if (toRemove.Contains(ed)) {
221           continue;
222         }
223         for (itl2.Initialize(itf.Value()); itl2.More(); itl2.Next()) {
224           if (!itl2.Value().IsSame(itl.Value())) {
225             for (exp2.Init(itl2.Value(),TopAbs_EDGE);exp2.More();exp2.Next()) {
226               if (ed.IsSame(exp2.Current())) {
227                 toRemove.Add(ed);
228                 break;
229               }
230             }
231             if (exp2.More()) {
232               break;
233             }
234           }
235         }
236       }
237     }
238   }
239
240   TopTools_ListOfShape RebuildFace;
241   TopTools_MapOfShape mapTreated;
242   TopTools_DataMapOfShapeShape DontFuse;
243   TopAbs_Orientation orient,orface;
244
245   for (itf.Reset(); itf.More(); itf.Next()) {
246     const TopoDS_Face& fac = TopoDS::Face(itf.Key());
247     for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
248       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
249       if (mapTreated.Contains(edg)) {
250         continue; // on saute l`edge
251       }
252
253       mapTreated.Add(edg);
254       for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
255         const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
256         if (GVtx.Contains(vtx)) {
257           TopoDS_Edge edgbis = G->Generated(vtx);
258
259           if ((edgbis.IsNull() || BRep_Tool::Degenerated(edgbis)) ||
260 //            toRemove.Contains(edgbis) ||
261               !ToFuse(edg,edgbis)) {
262             continue;
263           }
264 // a voir
265           if (BRepTools::IsReallyClosed(edg,fac)) {
266             if (!theEEMap.IsBound(edg)) {
267               TopTools_ListOfShape thelist1;
268               theEEMap.Bind(edg, thelist1);
269               theEEMap(edg).Append(edgbis);
270               toRemove.Add(edgbis); // toujours vrai pour edge double
271               Standard_Boolean FuseEdge = Standard_True;
272               TopoDS_Vertex Vf,Vl;
273               TopExp::Vertices(edg,Vf,Vl);
274               Standard_Boolean ConnectLast = (Vl.IsSame(vtx));
275               for (exp3.Init(fac.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
276                    exp3.More(); exp3.Next()) {
277                 const TopoDS_Edge& eee = TopoDS::Edge(exp3.Current());
278                 orient = eee.Orientation();
279                 if (!eee.IsSame(edg)) {
280                   TopExp::Vertices(eee,Vf,Vl);
281                   if ((Vf.IsSame(vtx) || Vl.IsSame(vtx)) &&
282                       !toRemove.Contains(eee)) {
283                     FuseEdge = Standard_False;
284                     // On recherche celui qu`il ne faut pas fusionner
285                     
286                     if ((Vf.IsSame(vtx) && orient == TopAbs_FORWARD) ||
287                         (Vl.IsSame(vtx) && orient == TopAbs_REVERSED)) {
288                       if (ConnectLast) {
289                         DontFuse.Bind(edg,fac.Oriented(TopAbs_FORWARD));
290                       }
291                       else {
292                         DontFuse.Bind(edg,fac.Oriented(TopAbs_REVERSED));
293                       }
294                     }
295                     else {
296                       if (ConnectLast) {
297                         DontFuse.Bind(edg,fac.Oriented(TopAbs_REVERSED));
298                       }
299                       else {
300                         DontFuse.Bind(edg,fac.Oriented(TopAbs_FORWARD));
301                       }
302                     }
303                     break;
304                   }
305                 }
306               }
307               if (FuseEdge) {
308                 toRemove.Add(vtx);
309               }
310             }
311           }
312
313
314           else {
315 /*  A VOIR
316           if (!BRep_Tool::IsClosed(edg,fac)) {
317 */          
318             if (!theEEMap.IsBound(edg)) {
319               TopTools_ListOfShape thelist2;
320               theEEMap.Bind(edg, thelist2);
321             }
322             theEEMap(edg).Append(edgbis);
323             const TopTools_ListOfShape& L = theEEMap(edg);
324             TopTools_ListIteratorOfListOfShape Lit(L);
325             Standard_Boolean OK = Standard_True;
326             for (; Lit.More(); Lit.Next()) {
327               if (Lit.Value().IsSame(edgbis)) {
328                 OK = Standard_False;
329                 break;
330               }
331             }
332             if (OK) theEEMap(edg).Append(edgbis);
333             
334             itl.Initialize(theEFMap.FindFromKey(edg));
335             Standard_Boolean FuseEdge = ToFuse(edg,fac,vtx,toRemove);
336             if (!FuseEdge) {
337               DontFuse.Bind(edg,fac);
338             }
339             else {
340               for (; itl.More(); itl.Next()) {
341                 if (!itl.Value().IsSame(fac)) {
342                   if (theFFMap.IsBound(itl.Value())) { 
343                     FuseEdge = ToFuse(edg,TopoDS::Face(itl.Value()),
344                                       vtx,toRemove);
345                     // edge a fusionner
346                     if (FuseEdge) {
347                       toRemove.Add(vtx);
348                     }
349                     else {
350                       if (toRemove.Contains(vtx)) {
351                         toRemove.Remove(vtx);
352                       }
353                       DontFuse.Bind(edg,itl.Value());
354                     }
355                   }
356                   else { // on marque comme face a reconstruire
357                     RebuildFace.Append(itl.Value());
358                     if (toRemove.Contains(vtx)) {
359                       toRemove.Remove(vtx);
360                     }
361                     DontFuse.Bind(edg,itl.Value());
362                   }
363                   
364                   break;
365                 }
366               }
367             }
368           }
369         }
370       }
371     }
372   }
373
374
375
376   for (itl.Initialize(RebuildFace); itl.More(); itl.Next()) {
377     TopTools_ListOfShape thelist3;
378     theFFMap.Bind(itl.Value(), thelist3);
379   }
380
381   BRep_Builder B;
382   TopoDS_Face newface;
383   TopoDS_Wire outw,newwire;
384   TopoDS_Edge newedg;
385   TopoDS_Vertex newvtx;
386   TopLoc_Location loc;
387   Standard_Real tol,prm,f,l, Uminc = 0.,Umaxc = 0.;
388   gp_Pnt2d pf,pl;
389
390   Handle(Geom_Surface) S;
391   Handle(Geom_Plane) P;
392   Handle(Geom_Curve) C;
393
394   // Fusion des edges
395   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape ite(theEEMap);
396   for (; ite.More(); ite.Next()) {
397     Standard_Boolean KeepNewEdge = Standard_False;
398     const TopoDS_Edge& edg = TopoDS::Edge(ite.Key());
399     BRep_Tool::Range(edg,f,l);
400     TopoDS_Shape aLocalEdge = edg.EmptyCopied();
401     newedg = TopoDS::Edge(aLocalEdge);
402 //    newedg = TopoDS::Edge(edg.EmptyCopied());
403     newedg.Orientation(TopAbs_FORWARD);
404     for (exp.Init(edg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
405          exp.More(); exp.Next()) {
406       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
407       prm = BRep_Tool::Parameter(vtx,edg);
408
409       newvtx.Nullify();
410       for (itl.Initialize(theEEMap(edg)); itl.More(); itl.Next()) {
411         const TopoDS_Edge& edgbis = TopoDS::Edge(itl.Value());
412         for (exp2.Init(edgbis,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
413           if (exp2.Current().IsSame(vtx)) {
414             break;
415           }
416         }
417         if (exp2.More()) {
418           for (exp2.ReInit(); exp2.More(); exp2.Next()) {
419             if (!exp2.Current().IsSame(vtx)) {
420               newvtx = TopoDS::Vertex(exp2.Current());
421               prm = NewParameter(edg,vtx,newedg,newvtx);
422               break;
423             }
424           }
425           break;
426         }
427       }
428
429       if (toRemove.Contains(vtx) ||
430           (prm <l && prm > f)) {
431         B.Add(newedg,newvtx.Oriented(vtx.Orientation()));
432         tol = BRep_Tool::Tolerance(newvtx);
433         B.UpdateVertex(newvtx,prm,newedg,tol);
434         toRemove.Add(itl.Value()); // i-e edgbis
435         KeepNewEdge = Standard_True;
436       }
437       else {
438         B.Add(newedg,vtx.Oriented(vtx.Orientation()));
439         tol = BRep_Tool::Tolerance(vtx);
440         B.UpdateVertex(vtx,prm,newedg,tol);
441       }
442     }
443     if (KeepNewEdge) {
444       TopTools_ListOfShape emptylist;
445       if(!myModShapes.IsBound(edg)) {
446         myModShapes.Bind(edg,emptylist);
447       }  
448       myModShapes(edg).Append(newedg);
449       toRemove.Add(edg);
450     }
451   }
452
453   TopTools_MapOfShape EdgAdded;
454
455   // Fusion des faces, ou reconstruction
456   for (itf.Reset();itf.More(); itf.Next()) {
457     const TopoDS_Face& fac = TopoDS::Face(itf.Key());
458     Standard_Boolean ModFace = Standard_False;
459     TopTools_ListOfShape listofedg;
460
461     EdgAdded.Clear();
462
463     for(exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
464       if (exp.Current().IsSame(fac)) {
465         break;
466       }
467     }
468     orface = exp.Current().Orientation();
469     TopoDS_Shape aLocalFace = fac.EmptyCopied();
470     newface = TopoDS::Face(aLocalFace);
471 //    newface = TopoDS::Face(fac.EmptyCopied());
472     newface.Orientation(TopAbs_FORWARD);
473     S = BRep_Tool::Surface(fac);
474     if (S->DynamicType()== STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
475       S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
476     }
477     P = Handle(Geom_Plane)::DownCast(S);
478     TopoDS_Wire wir;
479     for (exp.Init(fac.Oriented(TopAbs_FORWARD),TopAbs_WIRE); 
480          exp.More(); exp.Next()) {
481       wir = TopoDS::Wire(exp.Current());
482       for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
483         const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
484         if (toRemove.Contains(edg) || myModShapes.IsBound(edg) ) {
485           break;
486         }
487       }
488       if (!exp2.More()) { // wire non modifie
489 //      B.Add(newface,wir.Oriented(wir.Orientation()));
490         for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
491           listofedg.Append(exp2.Current());
492         }
493       }
494       else {
495         if (!ModFace) { 
496
497           // Petit truc crad pour les p-curves sur les cylindres...
498           if (P.IsNull()) {
499             Standard_Real Vminc,Vmaxc;
500             BRepTools::UVBounds(fac,Uminc,Umaxc,Vminc,Vmaxc);
501           }
502
503
504           // premier passage : on met les wires non touches des faces 
505           // en vis a vis
506
507           for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
508             TopoDS_Face facbis = TopoDS::Face(itl.Value());
509             for (itl2.Initialize(G->OrientedFaces());itl2.More();itl2.Next()) {
510               if (itl2.Value().IsSame(facbis)) {
511                 break;
512               }
513             }
514             if (itl2.More()) {
515               orient = itl2.Value().Orientation();
516               facbis.Orientation(orient);
517             }
518             else { // on fusionne avec une autre face du shape...
519               for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
520                 if (exp2.Current().IsSame(facbis)) {
521                   facbis.Orientation(exp2.Current().Orientation());
522                   break;
523                 }
524               }
525             }
526             
527             for (exp3.Init(facbis,TopAbs_WIRE); exp3.More(); exp3.Next()) {
528               for (exp2.Init(exp3.Current(),TopAbs_EDGE); 
529                    exp2.More(); exp2.Next()) {
530                 if (toRemove.Contains(exp2.Current())) {
531                   break;
532                 }
533               }
534               if (!exp2.More()) {
535                 TopoDS_Wire theNew;
536                 B.MakeWire(theNew); // FORWARD
537                 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
538                   const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
539                   
540                   orient = TopAbs::Compose(orface,edg.Orientation());
541 //                B.Add(theNew,edg.Oriented(or));
542                   listofedg.Append(edg.Oriented(orient));
543                   EdgAdded.Add(edg);
544                   if (P.IsNull()) {  
545                     // on met les courbes 2d si on n`est pas sur un plan
546                     // on ne devrait pas avoir de pb d`edge de couture. 
547                     tol = BRep_Tool::Tolerance(edg);
548                     C = BRep_Tool::Curve(edg,loc,f,l);
549                     if (!loc.IsIdentity()) {
550                       Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
551                       C = Handle(Geom_Curve)::DownCast (GG);
552                     }
553                     if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
554                       C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
555                     }
556                     
557                     Handle(Geom2d_Curve) C2d = GeomProjLib::Curve2d(C,f,l,S,tol);
558
559                     // Tentative de recalage dans la facette
560                     pf = C2d->Value(f);
561                     pl = C2d->Value(l);
562                     Standard_Real tttol = Precision::Angular();
563                     while (Min(pf.X(),pl.X()) >= Umaxc-tttol) {
564                       C2d->Translate(gp_Vec2d(-2.*M_PI,0));
565                       pf = C2d->Value(f);
566                       pl = C2d->Value(l);
567                     }
568
569                     while (Max(pf.X(),pl.X()) <= Uminc+tttol) {
570                       C2d->Translate(gp_Vec2d(2.*M_PI,0));
571                       pf = C2d->Value(f);
572                       pl = C2d->Value(l);
573                     }
574
575                     if (!BRepTools::IsReallyClosed(edg,facbis)) {
576                       B.UpdateEdge(edg,C2d,newface,tol);
577                     }
578                     //          else {
579                     //            cout << "Edge double bizarre... " << endl;
580                     //          }
581                   }
582                 }
583 //              B.Add(newface,theNew);
584               }
585             }
586           }
587           ModFace = Standard_True;
588         }
589         
590         // reconstruction du wire
591         //B.MakeWire(newwire);
592
593         Handle(Geom2d_Curve) C2d,C2d1;
594     
595 //      for (exp2.Init(wir.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
596         for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
597           const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
598           orient = edg.Orientation();
599           if (!toRemove.Contains(edg) && !theEEMap.IsBound(edg)) {
600 //          B.Add(newwire,edg.Oriented(or));
601 //            listofedg.Append(edg.Oriented(or));
602             listofedg.Append(edg);
603           }
604           else if (myModShapes.IsBound(edg) || theEEMap.IsBound(edg)) {
605             if (myModShapes.IsBound(edg)) {
606               newedg = TopoDS::Edge(myModShapes(edg).First());
607             }
608             else {
609               newedg = edg;
610             }
611 //          B.Add(newwire,newedg.Oriented(or));
612             listofedg.Append(newedg.Oriented(orient));
613             C = BRep_Tool::Curve(newedg,loc,f,l);
614             if (!loc.IsIdentity()) {
615               Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
616               C = Handle(Geom_Curve)::DownCast (GG);
617             }
618             if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
619               C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
620             }
621             if (P.IsNull()) { // on met les courbes 2d si on n`est pas 
622                               // sur un plan
623 //            TopAbs_Orientation oredonfafw = TopAbs::Compose(or,orsav);
624               TopAbs_Orientation oredonfafw = orient;
625               tol = BRep_Tool::Tolerance(newedg);
626               TopoDS_Shape aLocalEdge = edg.Oriented(oredonfafw);
627               TopoDS_Shape aLocalFace = fac.Oriented(TopAbs_FORWARD);
628               C2d = BRep_Tool::CurveOnSurface
629                 (TopoDS::Edge(aLocalEdge),TopoDS::Face(aLocalFace),f,l);
630 //            C2d = BRep_Tool::CurveOnSurface
631 //              (TopoDS::Edge(edg.Oriented(oredonfafw)),
632 //               TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
633 //               f,l);
634
635               if (!BRepTools::IsReallyClosed(edg,fac)) {
636                 B.UpdateEdge(newedg,C2d,newface,tol);
637               }
638               else if (C2d1.IsNull()){
639                 C2d1 = C2d;
640               }
641               else {
642 //              if (TopAbs::Compose(orsav,or) == TopAbs_FORWARD) {
643                 if (orient == TopAbs_FORWARD) {
644                   B.UpdateEdge(newedg,C2d,C2d1,newface,tol);
645                 }
646                 else {
647                   B.UpdateEdge(newedg,C2d1,C2d,newface,tol);
648                 }
649               }
650             }
651             Standard_Boolean AddPart = Standard_False;
652             if (DontFuse.IsBound(edg)) {
653               if (!BRepTools::IsReallyClosed(edg,fac)) {
654                 if (DontFuse(edg).IsSame(fac)) {
655                   if (myModShapes.IsBound(edg)) {
656                     AddPart = Standard_True;
657                   }
658                 }
659                 else if (!toRemove.Contains(edg)) {
660                   AddPart = Standard_True;
661                 }
662
663               }
664               else {
665                 if (myModShapes.IsBound(edg)) { // edg raccourci
666 //                if (TopAbs::Compose(orsav,or)==DontFuse(edg).Orientation()){
667                   if (orient == DontFuse(edg).Orientation()){
668                     AddPart = Standard_True;
669                   }
670                 }
671                 else {
672 //                if (TopAbs::Compose(orsav,or) == 
673                   if (orient == 
674                       TopAbs::Reverse(DontFuse(edg).Orientation())) {
675                     AddPart = Standard_True;
676                   }
677                 }
678               }
679             }  
680             if (AddPart) {
681               itl2.Initialize(theEEMap(edg));
682               gp_Vec dir1,dir2;
683               for (; itl2.More(); itl2.Next()) {
684                 if (EdgAdded.Contains(itl2.Value())) {
685                   continue;
686                 }
687                 const TopoDS_Edge& edgbis = TopoDS::Edge(itl2.Value());
688                 TopoDS_Iterator it1(newedg),it2;
689                 for (; it1.More(); it1.Next()) {
690                   for (it2.Initialize(edgbis); it2.More(); it2.Next()) {
691                     if (it1.Value().IsSame(it2.Value())) {
692                       break;
693                     }
694                   }
695                   if (it2.More()) {
696                     break;
697                   }
698                 }
699
700                 if (it1.More()) {
701                   gp_Pnt ptbid;
702                   Standard_Real prmvt = 
703                     BRep_Tool::Parameter(TopoDS::Vertex(it1.Value()),newedg);
704                   C->D1(prmvt,ptbid,dir1);
705
706
707                   C = BRep_Tool::Curve(edgbis,loc,f,l);
708                   if (!loc.IsIdentity()) {
709                     Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
710                     C = Handle(Geom_Curve)::DownCast (GG);
711                   }
712                   if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
713                     C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
714                   }
715                   prmvt = 
716                     BRep_Tool::Parameter(TopoDS::Vertex(it1.Value()),edgbis);
717                   C->D1(prmvt,ptbid,dir2);
718                 }
719                 else {
720                   dir1 = dir2 = gp_Vec(1,0,0);
721                 }
722                 EdgAdded.Add(edgbis);
723                 if (dir1.Dot(dir2) <0.) {
724 //                B.Add(newwire,edgbis.Oriented(TopAbs::Reverse(or)));
725                   listofedg.Append(edgbis.Oriented(TopAbs::Reverse(orient)));
726                 }
727                 else {
728 //                B.Add(newwire,edgbis.Oriented(or));
729                   listofedg.Append(edgbis.Oriented(orient));              
730                 }
731
732                 
733                 if (P.IsNull()) {
734                   // on met les courbes 2d si on n`est pas sur un plan
735                   // C est la courbe de edgbis, f et l s`y rapportent
736                   Handle(Geom2d_Curve) PTC = GeomProjLib::Curve2d(C,f,l,S,tol);
737                   if (S->IsUPeriodic()) {
738                     Standard_Real Uref;
739                     if (DontFuse.IsBound(edg)) {
740                       TopAbs_Orientation oredge = DontFuse(edg).Orientation();
741                       if (myModShapes.IsBound(edg)) { // edge raccourci...
742                         TopoDS_Shape aLocalShape = edg.Oriented(oredge);
743                         TopoDS_Shape aLocalFace  = fac.Oriented(TopAbs_FORWARD);
744                         BRep_Tool::
745                         UVPoints(TopoDS::Edge(aLocalShape),TopoDS::Face(aLocalFace),pf,pl);
746 //                      BRep_Tool::
747 //                      UVPoints(TopoDS::Edge(edg.Oriented(oredge)),
748 //                               TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
749 //                               pf,pl);
750                       }
751                       else {
752                         TopoDS_Shape aLocalShape = edg.Oriented(TopAbs::Reverse(oredge));
753                         TopoDS_Shape aLocalFace  = fac.Oriented(TopAbs_FORWARD);
754                         BRep_Tool::
755                         UVPoints(TopoDS::Edge(aLocalShape),TopoDS::Face(aLocalFace),pf,pl);
756 //                      BRep_Tool::
757 //                      UVPoints(TopoDS::Edge(edg.Oriented(TopAbs::Reverse(oredge))),
758 //                               TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
759 //                               pf,pl);
760                       }
761                       Uref = pf.X();
762                     }
763                     else {
764                       BRep_Tool::UVPoints(edg,fac,pf,pl);
765                       Uref = pf.X();
766                     }
767                     
768                     Standard_Real NewU = (PTC->Value(f)).X();
769                     
770 //                  if(abs(NewU - Uref) > Epsilon(S->UPeriod()))   {
771                     if(fabs(NewU - Uref) > Epsilon(S->UPeriod()))   {
772                       PTC -> Translate(gp_Vec2d((Uref - NewU), 0.));
773                     }
774                   }
775
776                   B.UpdateEdge(edgbis,PTC,newface,tol);
777                 }
778               }
779             }
780           }
781         }
782         
783         // Recuperation des edges sur les faces a fusionner.
784
785 // ICICICICI
786
787 //      orface = TopAbs::Compose(orsav,orface);
788
789         Standard_Boolean includeinw = Standard_False;
790         for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
791           TopoDS_Face facbis = TopoDS::Face(itl.Value());
792           Standard_Boolean genface = Standard_True;
793           for (itl2.Initialize(G->OrientedFaces()); itl2.More(); itl2.Next()) {
794             if (itl2.Value().IsSame(facbis)) {
795               break;
796             }
797           }
798           if (itl2.More()) {
799             orient = itl2.Value().Orientation();
800             facbis.Orientation(orient);
801           }
802           else { // on fusionne avec une autre face du shape...
803             genface = Standard_False;
804             for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
805               if (exp2.Current().IsSame(facbis)) {
806                 facbis.Orientation(exp2.Current().Orientation());
807                 break;
808               }
809             }
810           }
811
812           for (exp3.Init(facbis,TopAbs_WIRE); exp3.More(); exp3.Next()) {
813             for (exp2.Init(exp3.Current(),TopAbs_EDGE); 
814                  exp2.More(); exp2.Next()) {
815               if (toRemove.Contains(exp2.Current())) {
816                 break;
817               }
818             }
819             if (genface) {
820               includeinw = Standard_True;
821             }
822             else {
823               Standard_Boolean includeinw = Standard_False;
824               if (exp2.More()) {
825                 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
826                   if (!toRemove.Contains(exp2.Current())) {
827                     continue;
828                   }
829                   TopoDS_Vertex VF,VL;
830                   TopExp::Vertices(TopoDS::Edge(exp2.Current()),VF,VL);
831                   TopExp_Explorer exp4;
832                   for (exp4.Init(wir,TopAbs_VERTEX); 
833 //                for (TopExp_Explorer exp4(wir,TopAbs_VERTEX); 
834                        exp4.More(); exp4.Next()) {
835                     if (exp4.Current().IsSame(VF) ||
836                         exp4.Current().IsSame(VL)) {
837                       includeinw = Standard_True;
838                       break;
839                     }
840                   }
841                   if (includeinw) {
842                     break;
843                   }
844                 }
845               }
846             }
847             
848             if (!includeinw) {
849               continue;
850             }
851             
852             for (exp2.ReInit(); exp2.More(); exp2.Next()) {
853               const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
854               if (!toRemove.Contains(edg) && !EdgAdded.Contains(edg)) {
855                 
856                 orient = TopAbs::Compose(orface,edg.Orientation());
857                 //              B.Add(newwire,edg.Oriented(or));
858                 listofedg.Append(edg.Oriented(orient));
859                 EdgAdded.Add(edg);
860                 if (P.IsNull()) {  
861                   // on met les courbes 2d si on n`est pas sur un plan
862                   // on ne devrait pas avoir de pb d`edge de couture. 
863                   tol = BRep_Tool::Tolerance(edg);
864                   C = BRep_Tool::Curve(edg,loc,f,l);
865                   if (!loc.IsIdentity()) {
866                     Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
867                     C = Handle(Geom_Curve)::DownCast (GG);
868                   }
869                   if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
870                     C =  Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
871                   }
872                   
873                   C2d = GeomProjLib::Curve2d(C,f,l,S,tol);
874
875                   // Tentative de recalage dans la facette
876                   pf = C2d->Value(f);
877                   pl = C2d->Value(l);
878                   Standard_Real tttol = Precision::Angular();
879                   while (Min(pf.X(),pl.X()) >= Umaxc - tttol) {
880                     C2d->Translate(gp_Vec2d(-2.*M_PI,0));
881                     pf = C2d->Value(f);
882                     pl = C2d->Value(l);
883                   }
884                   
885                   while (Max(pf.X(),pl.X()) <= Uminc + tttol) {
886                     C2d->Translate(gp_Vec2d(2.*M_PI,0));
887                     pf = C2d->Value(f);
888                     pl = C2d->Value(l);
889                   }
890
891                   if (!BRepTools::IsReallyClosed(edg,facbis)) {
892                     B.UpdateEdge(edg,C2d,newface,tol);
893                   }
894                   //            else {
895                   //              cout << "Edge double bizarre... " << endl;
896                   //            }
897                 }
898               }
899             }
900           }
901         }
902       }
903     }
904     if (!listofedg.IsEmpty()) {
905       BRepAlgo_Loop L;
906       L.Init(newface);
907       L.AddConstEdges(listofedg);
908       L.Perform();
909       L.WiresToFaces();
910       const TopTools_ListOfShape& listoffaces = L.NewFaces();
911       toRemove.Add(fac);
912       //      if (!HasWire) {
913       //        newface.Nullify();
914       //      }
915       myModShapes.Bind(fac,listoffaces);
916       for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
917         myModShapes.Bind(itl.Value(),listoffaces);
918       }
919     }
920   }
921
922 /* JAG 16.09.96 : on utilise LocOpe_BuildShape
923   TopoDS_Shell theShell;
924   B.MakeShell(theShell);
925   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
926     const TopoDS_Face& fac = TopoDS::Face(exp.Current());
927     if (!theLeft.Contains(fac)) {
928       if (!toRemove.Contains(exp.Current())) {
929         B.Add(theShell,fac);
930         myModShapes.Bind(fac,fac);
931       }
932       else if (!myModShapes(fac).IsNull())  {
933         B.Add(theShell, myModShapes(fac).Oriented(fac.Orientation()));
934       }
935     }
936   }
937
938
939   TopAbs_Orientation orsolid = myShape.Orientation();
940   for (itl.Initialize(G->OrientedFaces()); itl.More(); itl.Next()) {
941     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
942     if (toRemove.Contains(fac)) {
943       continue;
944     }
945
946     if (orsolid == TopAbs_FORWARD) {
947       B.Add(theShell,fac);
948     }
949     else {
950       B.Add(theShell,fac.Reversed());
951     }
952     myModShapes.Bind(fac,fac);
953
954   }
955
956   B.MakeSolid(TopoDS::Solid(myRes));
957   B.Add(myRes,theShell);
958   myRes.Orientation(orsolid);
959
960 */
961
962   // 06.11.96
963   // Debug temporaire. Il faudra prevoir un syntaxe de BuildShape
964   // qui impose une ori de certaines faces.
965
966   TopoDS_Face FaceRefOri;
967
968   TopTools_ListOfShape lfres;
969   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
970     const TopoDS_Face& fac = TopoDS::Face(exp.Current());
971     if (!theLeft.Contains(fac)) {
972       if (!toRemove.Contains(exp.Current())) {
973         lfres.Append(fac);
974         if(!myModShapes.IsBound(fac)) {
975           TopTools_ListOfShape emptylist;
976           myModShapes.Bind(fac, emptylist);
977         }
978         myModShapes(fac).Append(fac);
979         if (FaceRefOri.IsNull()) {
980           FaceRefOri = fac;
981         }
982       }
983       else if (myModShapes.IsBound(fac))  {
984         lfres.Append(myModShapes(fac).First().Oriented(fac.Orientation()));
985       }
986     }
987   }
988
989
990   TopAbs_Orientation orsolid = myShape.Orientation();
991   for (itl.Initialize(G->OrientedFaces()); itl.More(); itl.Next()) {
992     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
993     if (toRemove.Contains(fac)) {
994       continue;
995     }
996
997     if (orsolid == TopAbs_FORWARD) {
998       lfres.Append(fac);
999     }
1000     else {
1001       lfres.Append(fac.Reversed());
1002     }
1003     if(!myModShapes.IsBound(fac)) {
1004       TopTools_ListOfShape emptylist;
1005       myModShapes.Bind(fac, emptylist);
1006     }
1007     myModShapes(fac).Append(fac);
1008   }
1009
1010   LocOpe_BuildShape BS(lfres);
1011   myRes = BS.Shape();
1012   // Suite debug du 06.11.96
1013   if (myRes.ShapeType() == TopAbs_SOLID) {
1014     for (exp.Init(myRes,TopAbs_FACE); exp.More(); exp.Next()) {
1015       if (exp.Current().IsSame(FaceRefOri)) {
1016         break;
1017       }
1018     }
1019     if (exp.More() && 
1020         exp.Current().Orientation() != FaceRefOri.Orientation()) {
1021       //        ---C++: return const&   ---C++: return const&   ---C++: return const&Si un seul Shell , on change son orientation
1022       TopoDS_Solid NewSol;
1023       B.MakeSolid(NewSol);
1024       exp.Init(myRes,TopAbs_SHELL);
1025       B.Add(NewSol,exp.Current().Reversed());
1026       myRes.Nullify();
1027       myRes = NewSol;
1028     }
1029   }
1030
1031
1032   // recodage des regularites qui existaient sur le shape colle
1033   
1034   
1035
1036   myDone = Standard_True;
1037 }
1038
1039 //=======================================================================
1040 //function : DescendantFace
1041 //purpose  : 
1042 //=======================================================================
1043
1044  const TopTools_ListOfShape& LocOpe_Generator::DescendantFace(const TopoDS_Face& F)
1045 {
1046  // TopTools_ListOfShape list;
1047
1048   if (!myDone) {StdFail_NotDone::Raise();}
1049   return myModShapes(F);
1050 }
1051
1052 //=======================================================================
1053 //function : ToFuse
1054 //purpose  : 
1055 //=======================================================================
1056
1057 Standard_Boolean ToFuse(const TopoDS_Face& F1,
1058                         const TopoDS_Face& F2)
1059 {
1060   if (F1.IsNull() || F2.IsNull()) {
1061     return Standard_False;
1062   }
1063
1064   Handle(Geom_Surface) S1,S2;
1065   TopLoc_Location loc1, loc2;
1066   Handle(Standard_Type) typS1,typS2;
1067   const Standard_Real tollin = Precision::Confusion();
1068   const Standard_Real tolang = Precision::Angular();
1069
1070   S1 = BRep_Tool::Surface(F1,loc1);
1071   S2 = BRep_Tool::Surface(F2,loc2);
1072
1073   typS1 = S1->DynamicType();
1074   typS2 = S2->DynamicType();
1075
1076   if (typS1 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1077     S1 =  Handle(Geom_RectangularTrimmedSurface)::DownCast (S1)->BasisSurface();
1078     typS1 = S1->DynamicType();
1079   }
1080
1081   if (typS2 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1082     S2 =  Handle(Geom_RectangularTrimmedSurface)::DownCast (S2)->BasisSurface();
1083     typS2 = S2->DynamicType();
1084   }
1085
1086   if (typS1 != typS2) {
1087     return Standard_False;
1088   }
1089
1090
1091   Standard_Boolean ValRet = Standard_False;
1092   if (typS1 == STANDARD_TYPE(Geom_Plane)) {
1093
1094     gp_Pln pl1( Handle(Geom_Plane)::DownCast (S1)->Pln());
1095     gp_Pln pl2( Handle(Geom_Plane)::DownCast (S2)->Pln());
1096
1097     pl1.Transform(loc1.Transformation());
1098     pl2.Transform(loc2.Transformation());
1099
1100     if (pl1.Position().IsCoplanar(pl2.Position(),tollin,tolang)) {
1101       ValRet = Standard_True;
1102     }
1103   }
1104
1105   return ValRet;
1106 }
1107
1108
1109 //=======================================================================
1110 //function : ToFuse
1111 //purpose  : 
1112 //=======================================================================
1113
1114 Standard_Boolean ToFuse(const TopoDS_Edge& E1,
1115                         const TopoDS_Edge& E2)
1116 {
1117
1118   if (E1.IsNull() || E2.IsNull()) {
1119     return Standard_False;
1120   }
1121
1122   Handle(Geom_Curve) C1,C2;
1123   TopLoc_Location loc1, loc2;
1124   Handle(Standard_Type) typC1,typC2;
1125   const Standard_Real tollin = Precision::Confusion();
1126   const Standard_Real tolang = Precision::Angular();
1127   Standard_Real f,l;
1128
1129   C1 = BRep_Tool::Curve(E1,loc1,f,l);
1130   if (!loc1.IsIdentity()) {
1131     Handle(Geom_Geometry) CC1 = C1->Transformed(loc1.Transformation());
1132     C1 = Handle(Geom_Curve)::DownCast (CC1);
1133   }
1134
1135   C2 = BRep_Tool::Curve(E2,loc2,f,l);
1136   if (!loc2.IsIdentity()) {
1137     Handle(Geom_Geometry) CC2 = C2->Transformed(loc2.Transformation());
1138     C2 = Handle(Geom_Curve)::DownCast (CC2);
1139   }
1140
1141   typC1 = C1->DynamicType();
1142   typC2 = C2->DynamicType();
1143
1144   if (typC1 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1145     C1 =  Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
1146     typC1 = C1->DynamicType();
1147   }
1148   if (typC2 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1149     C2 =  Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
1150     typC2 = C2->DynamicType();
1151   }
1152
1153   if (typC1 != typC2) {
1154     return Standard_False;
1155   }
1156
1157   Standard_Boolean ValRet = Standard_False;
1158   if (typC1 == STANDARD_TYPE(Geom_Line)) {
1159     gp_Lin li1( Handle(Geom_Line)::DownCast (C1)->Lin());
1160     gp_Lin li2( Handle(Geom_Line)::DownCast (C2)->Lin());
1161
1162     if (li1.Position().IsCoaxial(li2.Position(),tolang,tollin)) {
1163       ValRet = Standard_True;
1164     }
1165   }
1166
1167   return ValRet;
1168 }
1169
1170
1171 //=======================================================================
1172 //function : ToFuse
1173 //purpose  : 
1174 //=======================================================================
1175
1176 Standard_Boolean ToFuse(const TopoDS_Edge& E,
1177                         const TopoDS_Face& F,
1178                         const TopoDS_Vertex& V,
1179                         const TopTools_MapOfShape& toRemove)
1180 {
1181   TopoDS_Vertex Vf,Vl;
1182   TopExp_Explorer exp;
1183   for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
1184 //  for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
1185     const TopoDS_Edge& eee = TopoDS::Edge(exp.Current());
1186     if (!eee.IsSame(E)) {
1187       TopExp::Vertices(eee,Vf,Vl);
1188       if ((Vf.IsSame(V) || Vl.IsSame(V)) &&
1189           !toRemove.Contains(eee)) {
1190         return Standard_False;
1191       }
1192     }
1193   }
1194   return Standard_True;
1195 }
1196
1197
1198 //=======================================================================
1199 //function : NewParameter
1200 //purpose  : 
1201 //=======================================================================
1202
1203 Standard_Real NewParameter(const TopoDS_Edge& Edg,
1204                            const TopoDS_Vertex& Vtx,
1205                            const TopoDS_Edge& NewEdg,
1206                            const TopoDS_Vertex& NewVtx)
1207 {
1208
1209   Handle(Geom_Curve) C;
1210   TopLoc_Location loc;
1211   Handle(Standard_Type) typC;
1212   Standard_Real f,l;
1213
1214   gp_Pnt P = BRep_Tool::Pnt(NewVtx);
1215
1216   C = BRep_Tool::Curve(Edg,loc,f,l);
1217   if (!loc.IsIdentity()) {
1218     Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
1219     C = Handle(Geom_Curve)::DownCast (GG);
1220   }
1221   typC = C->DynamicType();
1222   if (typC == STANDARD_TYPE(Geom_TrimmedCurve)) {
1223     C =  Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
1224     typC = C->DynamicType();
1225   }
1226
1227   if (typC == STANDARD_TYPE(Geom_Line)) {
1228     return ElCLib::Parameter( Handle(Geom_Line)::DownCast (C)->Lin(),P);
1229   }
1230   else if (typC == STANDARD_TYPE(Geom_Circle)) {
1231     Standard_Real prm = ElCLib::Parameter
1232       ( Handle(Geom_Circle)::DownCast (C)->Circ(),P);
1233     // Vtx vient d`une exploration de Edg orientee FORWARD
1234
1235     TopAbs_Orientation orient = TopAbs::Reverse(Vtx.Orientation());
1236     if (orient == TopAbs_FORWARD || orient == TopAbs_REVERSED) {
1237 //      for (TopExp_Explorer exp(NewEdg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
1238       TopExp_Explorer exp(NewEdg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX) ;
1239       for ( ; exp.More(); exp.Next()) {
1240         if (exp.Current().Orientation() == orient) {
1241           break;
1242         }
1243       }
1244       if (exp.More()) {
1245         Standard_Real prmmax = BRep_Tool::Parameter
1246           (TopoDS::Vertex(exp.Current()),NewEdg);
1247         if (Abs(prmmax - prm) <= Epsilon(2.*M_PI)) {
1248           if (orient == TopAbs_REVERSED) {
1249             prm -= 2.*M_PI;
1250           }
1251           else {
1252             prm += 2.*M_PI;
1253           }
1254         }
1255       }
1256     }
1257     return prm;
1258   }
1259   return 0;
1260 }