d6a4df89b5c3e430ec706e52bfbdbe159aa69183
[occt.git] / src / LocOpe / LocOpe_WiresOnShape.cxx
1 // Created on: 1996-01-11
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
22
23 #include <LocOpe_WiresOnShape.ixx>
24
25 #include <TopExp_Explorer.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <TopTools_MapOfShape.hxx>
29 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32
33 #include <GeomAPI_ProjectPointOnCurve.hxx>
34 #include <GeomAdaptor_Surface.hxx>
35 #include <Geom_Curve.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <Geom_RectangularTrimmedSurface.hxx>
39 #include <Geom2d_Curve.hxx>
40
41 #include <gp_Pnt2d.hxx>
42 #include <gp_Vec2d.hxx>
43 #include <gp_Vec.hxx>
44
45 #include <TopoDS.hxx>
46 #include <TopExp.hxx>
47 #include <BRepTools.hxx>
48 #include <GeomProjLib.hxx>
49 #include <LocOpe.hxx>
50 #include <Precision.hxx>
51
52 #include <Standard_ConstructionError.hxx>
53 #include <TopoDS_Compound.hxx>
54 #include <BRepLib.hxx>
55
56 static Standard_Boolean Project(const TopoDS_Vertex&,
57                                 const TopoDS_Face&,
58                                 TopoDS_Edge&,
59                                 Standard_Real&);
60
61 static Standard_Real Project(const TopoDS_Vertex&,
62                              const TopoDS_Edge&);
63
64
65 static void PutPCurve(const TopoDS_Edge&,
66                       const TopoDS_Face&);
67
68
69 static void PutPCurves(const TopoDS_Edge&,
70                        const TopoDS_Edge&,
71                        const TopoDS_Shape&);
72
73
74 //=======================================================================
75 //function : LocOpe_WiresOnShape
76 //purpose  : 
77 //=======================================================================
78
79 LocOpe_WiresOnShape::LocOpe_WiresOnShape(const TopoDS_Shape& S):
80    myShape(S),myDone(Standard_False)
81 {}
82
83
84
85 //=======================================================================
86 //function : Init
87 //purpose  : 
88 //=======================================================================
89
90 void LocOpe_WiresOnShape::Init(const TopoDS_Shape& S)
91 {
92    myShape = S;
93    myDone = Standard_False;
94    myMap.Clear();
95    myMapEF.Clear();
96 }
97
98
99
100 //=======================================================================
101 //function : Bind
102 //purpose  : 
103 //=======================================================================
104
105 void LocOpe_WiresOnShape::Bind(const TopoDS_Wire& W,
106                                const TopoDS_Face& F)
107 {
108   for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) {
109     Bind(TopoDS::Edge(exp.Current()),F);
110   }
111 }
112
113
114 //=======================================================================
115 //function : Bind
116 //purpose  : 
117 //=======================================================================
118
119 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& E,
120                                const TopoDS_Face& F)
121 {
122 //  if (!myMapEF.IsBound(E)) {
123   if (!myMapEF.Contains(E)) {
124 //    for (TopExp_Explorer exp(F,TopAbs_EDGE);exp.More();exp.Next()) {
125     TopExp_Explorer exp(F,TopAbs_EDGE) ;
126     for ( ;exp.More();exp.Next()) {
127       if (exp.Current().IsSame(E)) {
128         break;
129       }
130     }
131     if (!exp.More()) {
132 //      myMapEF.Bind(E,F);
133       myMapEF.Add(E,F);
134     }
135   }
136   else {
137     Standard_ConstructionError::Raise();
138   }
139 }
140
141
142 //=======================================================================
143 //function : Bind
144 //purpose  : 
145 //=======================================================================
146
147 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& Ewir,
148                                const TopoDS_Edge& Efac)
149 {
150   if (Ewir.IsSame(Efac)) {
151     return;
152   }
153   myMap.Bind(Ewir,Efac);
154 }
155
156
157 //=======================================================================
158 //function : BindAll
159 //purpose  : 
160 //=======================================================================
161
162 void LocOpe_WiresOnShape::BindAll()
163 {
164   if (myDone) {
165     return;
166   }
167   TopTools_MapOfShape theMap;
168
169   // Detection des vertex a projeter ou a "binder" avec des vertex existants
170   TopTools_DataMapOfShapeShape mapV;
171   TopTools_DataMapIteratorOfDataMapOfShapeShape ite(myMap);
172   TopExp_Explorer exp,exp2;
173   for (; ite.More(); ite.Next()) {
174     const TopoDS_Edge& eref = TopoDS::Edge(ite.Key());
175     const TopoDS_Edge& eimg = TopoDS::Edge(ite.Value());
176
177     PutPCurves(eref,eimg,myShape);
178
179     for (exp.Init(eref,TopAbs_VERTEX); exp.More(); exp.Next()) {
180       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
181       if (!theMap.Contains(vtx)) { // pas deja traite
182         for (exp2.Init(eimg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
183           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
184           if (vtx2.IsSame(vtx)) {
185             break;
186           }
187           else if (BRepTools::Compare(vtx,vtx2)) {
188             mapV.Bind(vtx,vtx2);
189             break;
190           }
191         }
192         if (!exp2.More()) {
193           mapV.Bind(vtx,eimg);
194         }
195         theMap.Add(vtx);
196       }
197     }
198   }
199   
200   for (ite.Initialize(mapV); ite.More(); ite.Next()) {
201     myMap.Bind(ite.Key(),ite.Value());
202   }
203
204   // Il faut s`occuper maintenant des vertex "de changement de face", 
205   // et des vertex "libres"
206 //  TopTools_DataMapIteratorOfDataMapOfShapeShape ite2;
207
208 //  for (ite.Initialize(myMapEF); ite.More(); ite.Next()) {
209 //    const TopoDS_Edge& edg = TopoDS::Edge(ite.Key());
210 //    const TopoDS_Face& fac = TopoDS::Face(ite.Value());
211   for (Standard_Integer Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
212     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
213     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
214     // JAG 02.02.96 : On verifie les pcurves...
215
216     PutPCurve(edg,fac);
217
218     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
219       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
220       if (theMap.Contains(vtx)) {
221         continue;
222       }
223       TopoDS_Edge Epro;
224       Standard_Real prm;
225       Standard_Boolean ok = Project(vtx,fac,Epro,prm);
226       if (ok) {
227         for (exp2.Init(Epro,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
228           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
229           if (vtx2.IsSame(vtx)) {
230             break;
231           }
232           else if (BRepTools::Compare(vtx,vtx2)) {
233             myMap.Bind(vtx,vtx2);
234             break;
235           }
236         }
237         if (!exp2.More()) {
238           myMap.Bind(vtx,Epro);
239         }
240         theMap.Add(vtx);
241       }
242     }
243   }
244
245 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:50 2001 Begin
246   for (ite.Initialize(myMap); ite.More(); ite.Next())
247     if ((ite.Key()).ShapeType() == TopAbs_EDGE)
248       myMapEF.Add(ite.Key(),ite.Value());
249 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:52 2001 End
250
251
252   myDone = Standard_True;
253
254 }
255
256
257 //=======================================================================
258 //function : InitEdgeIterator
259 //purpose  : 
260 //=======================================================================
261
262 void LocOpe_WiresOnShape::InitEdgeIterator()
263 {
264   BindAll();
265 //  myIt.Initialize(myMapEF);
266   myIndex = 1;
267 }
268
269
270 //=======================================================================
271 //function : MoreEdge
272 //purpose  : 
273 //=======================================================================
274
275 Standard_Boolean LocOpe_WiresOnShape::MoreEdge()
276 {
277 //  return myIt.More();
278   return (myIndex <= myMapEF.Extent());
279 }
280
281
282 //=======================================================================
283 //function : Edge
284 //purpose  : 
285 //=======================================================================
286
287 TopoDS_Edge LocOpe_WiresOnShape::Edge()
288 {
289 //  return TopoDS::Edge(myIt.Key());
290   return TopoDS::Edge(myMapEF.FindKey(myIndex));
291 }
292
293
294 //=======================================================================
295 //function : Face
296 //purpose  : 
297 //=======================================================================
298
299 TopoDS_Face LocOpe_WiresOnShape::OnFace()
300 {
301 //  return TopoDS::Face(myIt.Value());
302   return TopoDS::Face(myMapEF(myIndex));
303 }
304
305
306 //=======================================================================
307 //function : OnEdge
308 //purpose  : 
309 //=======================================================================
310
311 Standard_Boolean LocOpe_WiresOnShape::OnEdge(TopoDS_Edge& E)
312 {
313 //  if (myMap.IsBound(myIt.Key())) {
314   if (myMap.IsBound(myMapEF.FindKey(myIndex))) {
315 //    E = TopoDS::Edge(myMap(myIt.Key()));
316     E = TopoDS::Edge(myMap(myMapEF.FindKey(myIndex)));
317     return Standard_True;
318   }
319   return Standard_False;
320 }
321
322
323
324
325 //=======================================================================
326 //function : NextEdge
327 //purpose  : 
328 //=======================================================================
329
330 void LocOpe_WiresOnShape::NextEdge()
331 {
332 //  myIt.Next();
333   myIndex++;
334 }
335
336
337
338 //=======================================================================
339 //function : OnVertex
340 //purpose  : 
341 //=======================================================================
342
343 Standard_Boolean LocOpe_WiresOnShape::OnVertex(const TopoDS_Vertex& Vw,
344                                                TopoDS_Vertex& Vs)
345 {
346   if (myMap.IsBound(Vw)) {
347     if (myMap(Vw).ShapeType() == TopAbs_VERTEX) {
348       Vs = TopoDS::Vertex(myMap(Vw));
349       return Standard_True;
350     }
351     return Standard_False;
352   }
353   return Standard_False;
354 }
355
356
357
358
359 //=======================================================================
360 //function : OnEdge
361 //purpose  : 
362 //=======================================================================
363
364 Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
365                                           TopoDS_Edge& Ed,
366                                           Standard_Real& prm)
367 {
368   if (!myMap.IsBound(V) ||
369       myMap(V).ShapeType() == TopAbs_VERTEX) {
370     return Standard_False;
371   }
372   
373   Ed = TopoDS::Edge(myMap(V));
374   prm = Project(V,Ed);
375   return Standard_True;
376 }
377
378
379 //=======================================================================
380 //function : Project
381 //purpose  : 
382 //=======================================================================
383
384 Standard_Boolean Project(const TopoDS_Vertex& V,
385                          const TopoDS_Face& F,
386                          TopoDS_Edge& theEdge,
387                          Standard_Real& param)
388 {
389   Handle(Geom_Curve) C;
390   TopLoc_Location Loc;
391   Standard_Real f,l;
392
393   Standard_Real dmin = RealLast();
394   gp_Pnt toproj(BRep_Tool::Pnt(V));
395   Standard_Boolean valret = Standard_False;
396   GeomAPI_ProjectPointOnCurve proj;
397
398   for (TopExp_Explorer exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
399        exp.More(); exp.Next()) {
400     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
401     if (!BRep_Tool::Degenerated(edg)) {
402       C = BRep_Tool::Curve(edg,Loc,f,l);
403       if (!Loc.IsIdentity()) {
404         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
405         C = *((Handle(Geom_Curve)*)&GG);
406       }
407       proj.Init(toproj,C,f,l);
408       if (proj.NbPoints() > 0) {
409         if (proj.LowerDistance() < dmin) {
410           theEdge = edg;
411           theEdge.Orientation(edg.Orientation());
412           dmin = proj.LowerDistance();
413           param = proj.LowerDistanceParameter();
414         }
415       }
416     }
417   }
418
419   if(theEdge.IsNull())
420     return Standard_False;
421
422   Standard_Real ttol = BRep_Tool::Tolerance(V) + BRep_Tool::Tolerance(theEdge);
423   if (dmin <= ttol) {
424     valret = Standard_True;
425     BRep_Builder B;
426     B.UpdateVertex(V, Max(dmin, BRep_Tool::Tolerance(V)));
427   }
428 #ifdef DEB_MESH
429   else {
430     cout <<"LocOpe_WiresOnShape::Project --> le vertex projete est a une "; 
431     cout <<"distance / la face = "<<dmin <<" superieure a la tolerance = "<<ttol<<endl;
432   }
433 #endif
434   return valret;
435 }
436
437 //=======================================================================
438 //function : Project
439 //purpose  : 
440 //=======================================================================
441
442 Standard_Real Project(const TopoDS_Vertex& V,
443                       const TopoDS_Edge& theEdge)
444 {
445   Handle(Geom_Curve) C;
446   TopLoc_Location Loc;
447   Standard_Real f,l;
448
449   gp_Pnt toproj(BRep_Tool::Pnt(V));
450   GeomAPI_ProjectPointOnCurve proj;
451
452   C = BRep_Tool::Curve(theEdge,Loc,f,l);
453   if (!Loc.IsIdentity()) {
454     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
455     C = *((Handle(Geom_Curve)*)&GG);
456   }
457   proj.Init(toproj,C,f,l);
458   
459
460   return proj.LowerDistanceParameter();
461 }
462
463
464 //=======================================================================
465 //function : PutPCurve
466 //purpose  : 
467 //=======================================================================
468
469 void PutPCurve(const TopoDS_Edge& Edg,
470                const TopoDS_Face& Fac)
471 {
472   BRep_Builder B;
473   TopLoc_Location LocFac;
474
475   Handle(Geom_Surface) S = BRep_Tool::Surface(Fac, LocFac);
476   Handle(Standard_Type) styp = S->DynamicType();
477
478   if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
479     S = (*((Handle(Geom_RectangularTrimmedSurface)*)&(S)))->BasisSurface();
480     styp = S->DynamicType();
481   }
482
483   if (styp == STANDARD_TYPE(Geom_Plane)) {
484     return;
485   }
486
487   Standard_Real Umin,Umax,Vmin,Vmax;
488   BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
489
490   Standard_Real f,l;
491
492   //if (!BRep_Tool::CurveOnSurface(Edg,Fac,f,l).IsNull()) {
493   //  return;
494   //}
495   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(Edg,Fac,f,l);
496   if ( !aC2d.IsNull() ) {
497     gp_Pnt2d p2d;
498     aC2d->D0(f,p2d);
499     Standard_Boolean IsIn = Standard_True;
500     if ( ( p2d.X() < Umin-Precision::PConfusion() ) || 
501          ( p2d.X() > Umax+Precision::PConfusion() ) )
502       IsIn = Standard_False;
503     if ( ( p2d.Y() < Vmin-Precision::PConfusion() ) || 
504          ( p2d.Y() > Vmax+Precision::PConfusion() ) )
505       IsIn = Standard_False;
506     aC2d->D0(l,p2d);
507     if ( ( p2d.X() < Umin-Precision::PConfusion() ) || 
508          ( p2d.X() > Umax+Precision::PConfusion() ) )
509       IsIn = Standard_False;
510     if ( ( p2d.Y() < Vmin-Precision::PConfusion() ) || 
511          ( p2d.Y() > Vmax+Precision::PConfusion() ) )
512       IsIn = Standard_False;
513     if (IsIn)
514       return;
515   }
516
517   TopLoc_Location Loc;
518   Handle(Geom_Curve) C = BRep_Tool::Curve(Edg,Loc,f,l);
519   if (!Loc.IsIdentity()) {
520     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
521     C = *((Handle(Geom_Curve)*)&GG);
522   }
523
524   if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
525     C = new Geom_TrimmedCurve(C,f,l);
526   }
527
528   S = BRep_Tool::Surface(Fac);
529
530   // Compute the tol2d
531   Standard_Real tol3d = Max(BRep_Tool::Tolerance(Edg),
532                             BRep_Tool::Tolerance(Fac));
533   GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
534   Standard_Real TolU  = Gas.UResolution(tol3d);
535   Standard_Real TolV  = Gas.VResolution(tol3d);
536   Standard_Real tol2d = Max(TolU,TolV);
537
538   Handle(Geom2d_Curve) C2d = 
539     GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
540  if(C2d.IsNull()) 
541        return;
542   gp_Pnt2d pf(C2d->Value(f));
543   gp_Pnt2d pl(C2d->Value(l));
544   gp_Pnt PF,PL;
545   S->D0(pf.X(),pf.Y(),PF);
546   S->D0(pl.X(),pl.Y(),PL);
547   TopoDS_Vertex V1,V2;
548   if (Edg.Orientation() == TopAbs_REVERSED) {
549     V1 = TopExp::LastVertex(Edg);
550     V1.Reverse();
551   }
552   else {
553     V1 = TopExp::FirstVertex (Edg);
554   }
555   if (Edg.Orientation() == TopAbs_REVERSED) {
556     V2 = TopExp::FirstVertex(Edg);
557     V2.Reverse();
558   }
559   else {
560     V2 = TopExp::LastVertex (Edg);
561   }
562
563   if(!V1.IsNull() && V2.IsNull()) {
564     //Handling of internal vertices
565     Standard_Real old1 = BRep_Tool::Tolerance (V1);
566     Standard_Real old2 = BRep_Tool::Tolerance (V2);
567     gp_Pnt pnt1 = BRep_Tool::Pnt (V1);
568     gp_Pnt pnt2 = BRep_Tool::Pnt (V2);
569     Standard_Real tol1 = pnt1.Distance(PF);
570     Standard_Real tol2 = pnt2.Distance(PL);
571     B.UpdateVertex(V1,Max(old1,tol1));
572     B.UpdateVertex(V2,Max(old2,tol2));
573   }
574
575   if (S->IsUPeriodic()) {
576     Standard_Real up   = S->UPeriod();
577     Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
578     Standard_Integer nbtra = 0;
579     Standard_Real theUmin = Min(pf.X(),pl.X());
580     Standard_Real theUmax = Max(pf.X(),pl.X());
581
582     if (theUmin < Umin-tolu) {
583       while (theUmin < Umin-tolu) {
584         theUmin += up;
585         nbtra++;
586       }
587     }
588     else if (theUmax > Umax+tolu) {
589       while (theUmax > Umax+tolu) {
590         theUmax -= up;
591         nbtra--;
592       }
593     }
594
595 /*
596     if (theUmin > Umax-tolu) {
597       while (theUmin > Umax-tolu) {
598         theUmin -= up;
599         nbtra--;
600       }
601     }
602     else if (theUmax < Umin+tolu) {
603       while (theUmax < Umin+tolu) {
604         theUmax += up;
605         nbtra++;
606       }
607     }
608 */
609     if (nbtra !=0) {
610       C2d->Translate(gp_Vec2d(nbtra*up,0.));
611     }
612   }    
613
614   if (S->IsVPeriodic()) {
615     Standard_Real vp   = S->VPeriod();
616     Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
617     Standard_Integer nbtra = 0;
618     Standard_Real theVmin = Min(pf.Y(),pl.Y());
619     Standard_Real theVmax = Max(pf.Y(),pl.Y());
620
621     if (theVmin < Vmin-tolv) {
622       while (theVmin < Vmin-tolv) {
623         theVmin += vp; theVmax += vp;
624         nbtra++;
625       }
626     }
627     else if (theVmax > Vmax+tolv) {
628       while (theVmax > Vmax+tolv) {
629         theVmax -= vp; theVmin -= vp;
630         nbtra--;
631       }
632     }
633 /*
634     if (theVmin > Vmax-tolv) {
635       while (theVmin > Vmax-tolv) {
636         theVmin -= vp;
637         nbtra--;
638       }
639     }
640     else if (theVmax < Vmin+tolv) {
641       while (theVmax < Vmin+tolv) {
642         theVmax += vp;
643         nbtra++;
644       }
645     }
646 */
647     if (nbtra !=0) {
648       C2d->Translate(gp_Vec2d(0.,nbtra*vp));
649     }
650   }
651   B.UpdateEdge(Edg,C2d,Fac,BRep_Tool::Tolerance(Edg));
652   
653   B.SameParameter(Edg,Standard_False);
654   BRepLib::SameParameter(Edg,tol2d); 
655 }
656
657
658 //=======================================================================
659 //function : PutPCurves
660 //purpose  : 
661 //=======================================================================
662
663 void PutPCurves(const TopoDS_Edge& Efrom,
664                 const TopoDS_Edge& Eto,
665                 const TopoDS_Shape& myShape)
666 {
667
668   TopTools_ListOfShape Lfaces;
669   TopExp_Explorer exp,exp2;
670
671   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
672     for (exp2.Init(exp.Current(), TopAbs_EDGE); exp2.More();exp2.Next()) {
673       if (exp2.Current().IsSame(Eto)) {
674         Lfaces.Append(exp.Current());
675       }
676     }
677   }
678
679   if (Lfaces.Extent() != 1 && Lfaces.Extent() !=2) {
680     Standard_ConstructionError::Raise();
681   }
682
683   // soit bord libre, soit connexite entre 2 faces, eventuellement edge closed
684
685   if (Lfaces.Extent() ==1) {
686     return; // sera fait par PutPCurve.... on l`espere
687   }
688
689   BRep_Builder B;
690   Handle(Geom_Surface) S;
691   Handle(Standard_Type) styp;
692   Handle(Geom_Curve) C;
693   Standard_Real Umin,Umax,Vmin,Vmax;
694   Standard_Real f,l;
695   TopLoc_Location Loc, LocFac;
696
697   if (!Lfaces.First().IsSame(Lfaces.Last())) {
698     TopTools_ListIteratorOfListOfShape itl(Lfaces);
699     for (; itl.More(); itl.Next()) {
700       const TopoDS_Face& Fac = TopoDS::Face(itl.Value());
701
702       if (!BRep_Tool::CurveOnSurface(Efrom,Fac,f,l).IsNull()) {
703         continue;
704       }
705       S = BRep_Tool::Surface(Fac, LocFac);
706       styp = S->DynamicType();
707       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
708         S = (*((Handle(Geom_RectangularTrimmedSurface)*)&(S)))->BasisSurface();
709         styp = S->DynamicType();
710       }
711       if (styp == STANDARD_TYPE(Geom_Plane)) {
712         continue;
713       }
714
715             
716       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
717       C = BRep_Tool::Curve(Efrom,Loc,f,l);
718       if (!Loc.IsIdentity()) {
719         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
720         C = *((Handle(Geom_Curve)*)&GG);
721       }
722       
723       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
724         C = new Geom_TrimmedCurve(C,f,l);
725       }
726     
727       S = BRep_Tool::Surface(Fac);
728
729       // Compute the tol2d
730       Standard_Real tol3d = Max(BRep_Tool::Tolerance(Efrom),
731                                 BRep_Tool::Tolerance(Fac));
732       GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
733       Standard_Real TolU  = Gas.UResolution(tol3d);
734       Standard_Real TolV  = Gas.VResolution(tol3d);
735       Standard_Real tol2d = Max(TolU,TolV);
736
737       Handle(Geom2d_Curve) C2d = 
738         GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
739      if(C2d.IsNull())
740        return;
741
742       gp_Pnt2d pf(C2d->Value(f));
743       gp_Pnt2d pl(C2d->Value(l));
744       
745       if (S->IsUPeriodic()) {
746         Standard_Real up   = S->UPeriod();
747         Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
748         Standard_Integer nbtra = 0;
749         Standard_Real theUmin = Min(pf.X(),pl.X());
750         Standard_Real theUmax = Max(pf.X(),pl.X());
751
752         if (theUmin < Umin-tolu) {
753           while (theUmin < Umin-tolu) {
754             theUmin += up; theUmax += up;
755             nbtra++;
756           }
757         }
758         else if (theUmax > Umax+tolu) {
759           while (theUmax > Umax+tolu) {
760             theUmax -= up; theUmin -= up;
761             nbtra--;
762           }
763         }
764 /*
765         if (theUmin > Umax+tolu) {
766           while (theUmin > Umax+tolu) {
767             theUmin -= up;
768             nbtra--;
769           }
770         }
771         else if (theUmax < Umin-tolu) {
772           while (theUmax < Umin-tolu) {
773             theUmax += up;
774             nbtra++;
775           }
776         }
777 */
778         if (nbtra !=0) {
779           C2d->Translate(gp_Vec2d(nbtra*up,0.));
780         }
781       }    
782       
783       if (S->IsVPeriodic()) {
784         Standard_Real vp   = S->VPeriod();
785         Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
786         Standard_Integer nbtra = 0;
787         Standard_Real theVmin = Min(pf.Y(),pl.Y());
788         Standard_Real theVmax = Max(pf.Y(),pl.Y());
789
790         if (theVmin < Vmin-tolv) {
791           while (theVmin < Vmin-tolv) {
792             theVmin += vp; theVmax += vp;
793             nbtra++;
794           }
795         }
796         else if (theVmax > Vmax+tolv) {
797           while (theVmax > Vmax+tolv) {
798             theVmax -= vp; theVmin -= vp;
799             nbtra--;
800           }
801         }
802 /*
803         if (theVmin > Vmax+tolv) {
804           while (theVmin > Vmax+tolv) {
805             theVmin -= vp;
806             nbtra--;
807           }
808         }
809         else if (theVmax < Vmin-tolv) {
810           while (theVmax < Vmin-tolv) {
811             theVmax += vp;
812             nbtra++;
813           }
814         }
815 */
816         if (nbtra !=0) {
817           C2d->Translate(gp_Vec2d(0.,nbtra*vp));
818         }
819       }
820       B.UpdateEdge(Efrom,C2d,Fac,BRep_Tool::Tolerance(Efrom));
821     }
822   }
823
824   else {
825     const TopoDS_Face& Fac = TopoDS::Face(Lfaces.First());
826     if (!BRep_Tool::IsClosed(Eto,Fac)) {
827       Standard_ConstructionError::Raise();
828     }
829
830     TopoDS_Shape aLocalE = Efrom.Oriented(TopAbs_FORWARD);
831     TopoDS_Shape aLocalF = Fac.Oriented(TopAbs_FORWARD);
832     Handle(Geom2d_Curve) c2dff = 
833       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
834                                 TopoDS::Face(aLocalF),
835                                 f,l);
836
837 //    Handle(Geom2d_Curve) c2dff = 
838 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_FORWARD)),
839 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
840 //                              f,l);
841     
842     aLocalE = Efrom.Oriented(TopAbs_REVERSED);
843     aLocalF = Fac.Oriented(TopAbs_FORWARD);
844     Handle(Geom2d_Curve) c2dfr = 
845       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
846                                 TopoDS::Face(aLocalF),
847                                 f,l);
848 //    Handle(Geom2d_Curve) c2dfr = 
849 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_REVERSED)),
850 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
851 //                              f,l);
852     
853     aLocalE = Eto.Oriented(TopAbs_FORWARD);
854     aLocalF = Fac.Oriented(TopAbs_FORWARD);
855     Handle(Geom2d_Curve) c2dtf = 
856       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
857                                 TopoDS::Face(aLocalF),
858                                 f,l);
859
860 //    Handle(Geom2d_Curve) c2dtf = 
861 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_FORWARD)),
862 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
863 //                              f,l);
864     aLocalE = Eto.Oriented(TopAbs_REVERSED);
865     aLocalF = Fac.Oriented(TopAbs_FORWARD);
866     Handle(Geom2d_Curve) c2dtr = 
867       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
868                                 TopoDS::Face(aLocalF),
869                                 f,l);
870 //    Handle(Geom2d_Curve) c2dtr = 
871 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_REVERSED)),
872 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
873 //                              f,l);
874
875     gp_Pnt2d ptf(c2dtf->Value(f)); // sur courbe frw
876     gp_Pnt2d ptr(c2dtr->Value(f)); // sur courbe rev
877
878     Standard_Boolean isoU = (Abs(ptf.Y()-ptr.Y())<Epsilon(ptf.X())); // meme V
879
880     // Efrom et Eto dans le meme sens???
881
882     C = BRep_Tool::Curve(Efrom,Loc,f,l);
883     if (!Loc.IsIdentity()) {
884       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
885       C = *((Handle(Geom_Curve)*)&GG);
886     }
887
888     gp_Pnt pt;
889     gp_Vec d1f,d1t;
890
891     C->D1(f,pt,d1f);
892
893     Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),Eto);
894     
895     C = BRep_Tool::Curve(Eto,Loc,f,l);
896     if (!Loc.IsIdentity()) {
897       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
898       C = *((Handle(Geom_Curve)*)&GG);
899     }
900     
901     C->D1(prmproj,pt,d1t);
902
903     Standard_Real SameOri = (d1t.Dot(d1f)>0.); 
904
905
906     if (c2dff.IsNull() && c2dfr.IsNull()) {
907       S = BRep_Tool::Surface(Fac);
908       styp = S->DynamicType();
909       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
910         S = (*((Handle(Geom_RectangularTrimmedSurface)*)&(S)))->BasisSurface();
911         styp = S->DynamicType();
912       }
913       
914       C = BRep_Tool::Curve(Efrom,Loc,f,l);
915       if (!Loc.IsIdentity()) {
916         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
917         C = *((Handle(Geom_Curve)*)&GG);
918       }
919       
920       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
921         C = new Geom_TrimmedCurve(C,f,l);
922       }
923
924       // Compute the tol2d
925       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
926
927       Standard_Real tol3d = Max(BRep_Tool::Tolerance(Efrom),
928                                 BRep_Tool::Tolerance(Fac));
929       GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
930       Standard_Real TolU  = Gas.UResolution(tol3d);
931       Standard_Real TolV  = Gas.VResolution(tol3d);
932       Standard_Real tol2d = Max(TolU,TolV);
933     
934       Handle(Geom2d_Curve) C2d = 
935         GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
936       c2dff = C2d;
937       c2dfr = C2d;
938     }
939     else if (c2dfr.IsNull()) {
940       c2dfr = c2dff;
941
942     }
943     else if (c2dff.IsNull()) {
944       c2dff = c2dfr;
945     }
946
947     BRep_Tool::Range(Efrom,f,l);
948
949     gp_Pnt2d p2f = c2dff->Value(f);
950     gp_Pnt2d p2r = c2dfr->Value(f);
951
952     if (isoU) {
953       if (SameOri) {
954         if (Abs(ptf.X()-p2f.X()) > Epsilon(ptf.X())) {
955           c2dff = Handle(Geom2d_Curve)::DownCast
956             (c2dff->Translated(gp_Vec2d(ptf.X()-p2f.X(),0.)));
957         }
958         if (Abs(ptr.X()-p2r.X()) > Epsilon(ptr.X())) {
959           c2dfr = Handle(Geom2d_Curve)::DownCast
960             (c2dfr->Translated(gp_Vec2d(ptr.X()-p2r.X(),0.)));
961         }
962       }
963       else {
964         if (Abs(ptr.X()-p2f.X()) > Epsilon(ptr.X())) {
965           c2dff = Handle(Geom2d_Curve)::DownCast
966             (c2dff->Translated(gp_Vec2d(ptr.X()-p2f.X(),0.)));
967         }
968         
969         if (Abs(ptf.X()-p2r.X()) > Epsilon(ptf.X())) {
970           c2dfr = Handle(Geom2d_Curve)::DownCast
971             (c2dfr->Translated(gp_Vec2d(ptf.X()-p2r.X(),0.)));
972         }
973       }
974
975       // on est bien en U, recalage si periodique en V a faire
976
977
978
979     }
980     
981     else { // !isoU soit isoV
982       if (SameOri) {
983         if (Abs(ptf.Y()-p2f.Y()) > Epsilon(ptf.Y())) {
984           c2dff = Handle(Geom2d_Curve)::DownCast
985             (c2dff->Translated(gp_Vec2d(0.,ptf.Y()-p2f.Y())));
986         }
987         if (Abs(ptr.Y()-p2r.Y()) > Epsilon(ptr.Y())) {
988           c2dfr = Handle(Geom2d_Curve)::DownCast
989             (c2dfr->Translated(gp_Vec2d(0.,ptr.Y()-p2r.Y())));
990         }
991       }
992       else {
993         if (Abs(ptr.Y()-p2f.Y()) > Epsilon(ptr.Y())) {
994           c2dff = Handle(Geom2d_Curve)::DownCast
995             (c2dff->Translated(gp_Vec2d(0.,ptr.Y()-p2f.Y())));
996         }
997         if (Abs(ptf.Y()-p2r.Y()) > Epsilon(ptf.Y())) {
998           c2dfr = Handle(Geom2d_Curve)::DownCast
999             (c2dfr->Translated(gp_Vec2d(0.,ptf.Y()-p2r.Y())));
1000         }
1001       }
1002       // on est bien en V, recalage si periodique en U a faire
1003
1004     }
1005     B.UpdateEdge(Efrom,c2dff,c2dfr,Fac,BRep_Tool::Tolerance(Efrom));
1006   }
1007 }
1008