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