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