0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / TopOpeBRepDS / TopOpeBRepDS_BuildTool.cxx
1 // Created on: 1993-06-17
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Surface.hxx>
20 #include <ElCLib.hxx>
21 #include <Extrema_ExtPC.hxx>
22 #include <Extrema_POnCurv.hxx>
23 #include <Geom2d_BezierCurve.hxx>
24 #include <Geom2d_BSplineCurve.hxx>
25 #include <Geom2d_Circle.hxx>
26 #include <Geom2d_Conic.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom2d_Ellipse.hxx>
29 #include <Geom2d_Hyperbola.hxx>
30 #include <Geom2d_Line.hxx>
31 #include <Geom2d_OffsetCurve.hxx>
32 #include <Geom2d_Parabola.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <Geom_BezierCurve.hxx>
35 #include <Geom_BSplineCurve.hxx>
36 #include <Geom_Circle.hxx>
37 #include <Geom_Conic.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Geom_Ellipse.hxx>
40 #include <Geom_Hyperbola.hxx>
41 #include <Geom_Line.hxx>
42 #include <Geom_OffsetCurve.hxx>
43 #include <Geom_Parabola.hxx>
44 #include <Geom_Plane.hxx>
45 #include <Geom_SphericalSurface.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Geom_TrimmedCurve.hxx>
48 #include <GeomAdaptor_Curve.hxx>
49 #include <GeomAPI_ProjectPointOnCurve.hxx>
50 #include <GeomAPI_ProjectPointOnSurf.hxx>
51 #include <gp.hxx>
52 #include <gp_Pnt.hxx>
53 #include <gp_Pnt2d.hxx>
54 #include <gp_Vec2d.hxx>
55 #include <Precision.hxx>
56 #include <Standard_NotImplemented.hxx>
57 #include <Standard_ProgramError.hxx>
58 #include <TCollection_AsciiString.hxx>
59 #include <TopAbs.hxx>
60 #include <TopExp.hxx>
61 #include <TopExp_Explorer.hxx>
62 #include <TopLoc_Location.hxx>
63 #include <TopoDS.hxx>
64 #include <TopoDS_Edge.hxx>
65 #include <TopoDS_Face.hxx>
66 #include <TopoDS_Shape.hxx>
67 #include <TopoDS_Vertex.hxx>
68 #include <TopOpeBRepDS_BuildTool.hxx>
69 #include <TopOpeBRepDS_Curve.hxx>
70 #include <TopOpeBRepDS_DataStructure.hxx>
71 #include <TopOpeBRepDS_Dumper.hxx>
72 #include <TopOpeBRepDS_HDataStructure.hxx>
73 #include <TopOpeBRepDS_Point.hxx>
74 #include <TopOpeBRepDS_Surface.hxx>
75 #include <TopOpeBRepDS_SurfaceCurveInterference.hxx>
76 #include <TopOpeBRepTool_GeomTool.hxx>
77 #include <TopOpeBRepTool_OutCurveType.hxx>
78 #include <TopOpeBRepTool_ShapeTool.hxx>
79
80 // includes especially needed by the static Project function
81 #ifdef DRAW
82 #include <TopOpeBRepDS_DRAW.hxx>
83 #include <Geom2d_Curve.hxx>
84 #endif
85
86 Standard_EXPORT Handle(Geom2d_Curve) BASISCURVE2D(const Handle(Geom2d_Curve)& C);
87
88 Standard_Boolean FUN_UisoLineOnSphe
89 (const TopoDS_Shape& F,
90  const Handle(Geom2d_Curve)& PC)
91 {  
92   if (PC.IsNull()) return Standard_False;
93
94   Handle(Geom_Surface) SSS = TopOpeBRepTool_ShapeTool::BASISSURFACE(TopoDS::Face(F));
95   Handle(Geom2d_Curve) LLL = ::BASISCURVE2D(PC);
96   Handle(Standard_Type) TS = SSS->DynamicType();
97   Handle(Standard_Type) T2 = LLL->DynamicType();
98   Standard_Boolean issphere = (TS == STANDARD_TYPE(Geom_SphericalSurface)); 
99   Standard_Boolean isline2d = (T2 == STANDARD_TYPE(Geom2d_Line));
100   Standard_Boolean isisoU = Standard_False;
101   if (issphere && isline2d) {
102     Handle(Geom2d_Line) L = Handle(Geom2d_Line)::DownCast(LLL);
103     const gp_Dir2d& d = L->Direction();
104     isisoU = (Abs(d.X()) < Precision::Parametric(Precision::Confusion()));
105   }
106   return isisoU;
107 }
108
109 //=======================================================================
110 //function : TopOpeBRepDS_BuildTool
111 //purpose  : 
112 //=======================================================================
113
114 TopOpeBRepDS_BuildTool::TopOpeBRepDS_BuildTool():
115 myCurveTool(TopOpeBRepTool_APPROX),
116 myOverWrite(Standard_True),
117 myTranslate(Standard_True)
118 {
119 }
120
121 //=======================================================================
122 //function : TopOpeBRepDS_BuildTool
123 //purpose  : 
124 //=======================================================================
125
126 TopOpeBRepDS_BuildTool::TopOpeBRepDS_BuildTool
127   (const TopOpeBRepTool_OutCurveType O) : 
128 myCurveTool(O),
129 myOverWrite(Standard_True),
130 myTranslate(Standard_True)
131 {
132 }
133
134 //=======================================================================
135 //function : TopOpeBRepDS_BuildTool
136 //purpose  : 
137 //=======================================================================
138
139 TopOpeBRepDS_BuildTool::TopOpeBRepDS_BuildTool
140   (const TopOpeBRepTool_GeomTool& GT) : 
141 myCurveTool(GT),
142 myOverWrite(Standard_True),
143 myTranslate(Standard_True)
144 {
145 }
146
147 Standard_Boolean TopOpeBRepDS_BuildTool::OverWrite()const
148 {
149   return myOverWrite;
150 }
151
152 void TopOpeBRepDS_BuildTool::OverWrite(const Standard_Boolean O)
153 {
154   myOverWrite = O;
155 }
156
157 Standard_Boolean TopOpeBRepDS_BuildTool::Translate()const
158 {
159   return myTranslate;
160 }
161
162 void TopOpeBRepDS_BuildTool::Translate(const Standard_Boolean T)
163 {
164   myTranslate = T;
165 }
166
167 //=======================================================================
168 //function : GetGeomTool
169 //purpose  : 
170 //=======================================================================
171
172 const TopOpeBRepTool_GeomTool& TopOpeBRepDS_BuildTool::GetGeomTool() const 
173 {
174   const TopOpeBRepTool_GeomTool& GT = myCurveTool.GetGeomTool();
175   return GT;
176 }
177
178 //=======================================================================
179 //function : ChangeGeomTool
180 //purpose  : 
181 //=======================================================================
182
183 TopOpeBRepTool_GeomTool& TopOpeBRepDS_BuildTool::ChangeGeomTool()
184 {
185   TopOpeBRepTool_GeomTool& GT = myCurveTool.ChangeGeomTool();
186   return GT;
187 }
188
189 //=======================================================================
190 //function : MakeVertex
191 //purpose  : 
192 //=======================================================================
193
194 void  TopOpeBRepDS_BuildTool::MakeVertex(TopoDS_Shape& V, 
195                                          const TopOpeBRepDS_Point& P)const 
196 {
197   myBuilder.MakeVertex(TopoDS::Vertex(V),P.Point(),P.Tolerance());
198 }
199
200 //=======================================================================
201 //function : MakeEdge
202 //purpose  : 
203 //=======================================================================
204
205 void  TopOpeBRepDS_BuildTool::MakeEdge(TopoDS_Shape& E, 
206                                        const TopOpeBRepDS_Curve& C)const 
207 {
208   // Gestion des courbes nulles pour carreaux pointus
209   // RLE 28-6-94
210
211   if (C.Curve().IsNull()) {
212     myBuilder.MakeEdge(TopoDS::Edge(E));
213     myBuilder.Degenerated(TopoDS::Edge(E),Standard_True);
214     return;
215   }
216
217   const Handle(Geom_Curve)& GC = C.Curve();
218   myBuilder.MakeEdge(TopoDS::Edge(E),GC,C.Tolerance());
219
220   Standard_Boolean addorigin = Standard_False;
221   Standard_Boolean setrange  = Standard_False;
222
223   if (addorigin) {
224     if ( GC->IsClosed() ) {
225       // in case of a closed curve, insert in E a vertex located at the origin
226       // of the curve C.
227       TopoDS_Vertex V;
228       Standard_Real first = GC->FirstParameter();
229       gp_Pnt P = GC->Value(first);
230       myBuilder.MakeVertex(V,P,C.Tolerance());
231       myBuilder.Add(E,V);
232       V.Reverse();
233       myBuilder.Add(E,V);
234       
235       // If the curve is a degree 1 bspline set the range to 1 .. NbPoles
236       Handle(Geom_BSplineCurve) BSC = Handle(Geom_BSplineCurve)::DownCast(GC);
237       if (!BSC.IsNull()) {
238         if (BSC->Degree() == 1) {
239           myBuilder.Range(TopoDS::Edge(E),1,BSC->NbPoles());
240         }
241       }
242     }
243   }
244
245   if (setrange) {
246     Standard_Real first,last;
247     Standard_Boolean rangedef = C.Range(first,last);
248     if (rangedef) {
249       Range(E,first,last);
250     }
251   }
252 }
253
254 //=======================================================================
255 //function : MakeEdge
256 //purpose  : 
257 //=======================================================================
258
259 void  TopOpeBRepDS_BuildTool::MakeEdge
260 (TopoDS_Shape& E, 
261  const TopOpeBRepDS_Curve& C,
262  const TopOpeBRepDS_DataStructure& BDS) const
263 {
264   // Gestion des courbes nulles pour carreaux pointus
265   // RLE 28-6-94
266
267   TopoDS_Edge& EE = TopoDS::Edge(E);
268
269   if (C.Curve().IsNull()) {
270     myBuilder.MakeEdge(EE);
271     myBuilder.Degenerated(EE,Standard_True);
272     
273     // Creation d'une arete avec PCurve connectee a la BDS Curve 
274     // JYL 22-09-94
275     Handle(TopOpeBRepDS_Interference) I = C.GetSCI1();
276     Handle(TopOpeBRepDS_SurfaceCurveInterference) SCI;
277     SCI=Handle(TopOpeBRepDS_SurfaceCurveInterference)::DownCast(I);
278     Standard_Integer iS = SCI->Support();
279     const TopOpeBRepDS_Surface& DSS = BDS.Surface(iS);
280     const Handle(Geom_Surface)& GS  = DSS.Surface();
281     const Handle(Geom2d_Curve)& PC  = SCI->PCurve();
282     myBuilder.UpdateEdge(EE,PC,GS,TopLoc_Location(),DSS.Tolerance());
283     return;
284   }
285   else {
286     const Handle(Geom_Curve)& GC = C.Curve();
287     myBuilder.MakeEdge(EE,GC,C.Tolerance());
288   }
289
290 }
291
292 //=======================================================================
293 //function : MakeEdge
294 //purpose  : 
295 //=======================================================================
296
297 void  TopOpeBRepDS_BuildTool::MakeEdge
298 (TopoDS_Shape& E, 
299  const Handle(Geom_Curve)& C,
300  const Standard_Real Tol)const 
301 {
302   myBuilder.MakeEdge(TopoDS::Edge(E),C,Tol);
303 }
304
305
306 //=======================================================================
307 //function : MakeEdge
308 //purpose  : 
309 //=======================================================================
310
311 void  TopOpeBRepDS_BuildTool::MakeEdge(TopoDS_Shape& E) const
312 {
313   myBuilder.MakeEdge(TopoDS::Edge(E));
314 }
315
316
317 //=======================================================================
318 //function : MakeWire
319 //purpose  : 
320 //=======================================================================
321
322 void  TopOpeBRepDS_BuildTool::MakeWire(TopoDS_Shape& W)const 
323 {
324   myBuilder.MakeWire(TopoDS::Wire(W));
325 }
326
327
328 //=======================================================================
329 //function : MakeFace
330 //purpose  : 
331 //=======================================================================
332
333 void  TopOpeBRepDS_BuildTool::MakeFace(TopoDS_Shape& F, 
334                                        const TopOpeBRepDS_Surface& S)const 
335 {
336   myBuilder.MakeFace(TopoDS::Face(F),S.Surface(),S.Tolerance());
337 }
338
339
340 //=======================================================================
341 //function : MakeShell
342 //purpose  : 
343 //=======================================================================
344
345 void  TopOpeBRepDS_BuildTool::MakeShell(TopoDS_Shape& Sh)const 
346 {
347   myBuilder.MakeShell(TopoDS::Shell(Sh));
348 }
349
350
351 //=======================================================================
352 //function : MakeSolid
353 //purpose  : 
354 //=======================================================================
355
356 void  TopOpeBRepDS_BuildTool::MakeSolid(TopoDS_Shape& S)const 
357 {
358   myBuilder.MakeSolid(TopoDS::Solid(S));
359 }
360
361
362 //=======================================================================
363 //function : CopyEdge
364 //purpose  : 
365 //=======================================================================
366
367 void  TopOpeBRepDS_BuildTool::CopyEdge(const TopoDS_Shape& Ein, 
368                                        TopoDS_Shape& Eou)const 
369 {
370
371   // Splendide evolution de BRep_Curve3D::BRep_Curve3D(Geom_Curve,Location)
372   // apres modification de la primitive Sphere pour parametrisation de 
373   // l'arete meridienne en -pi/2,+pi/2.
374   // Ein est l'arete de couture complete d'une sphere complete
375   // BRep_Tool::Range(Ein) --> -pi/2,+pi/2
376   // BRep_Tool::Range(Ein.EmptyCopied()) --> 0,2pi
377   // NYI reflexion sur la notion de Range d'une arete et de la geometrie
378   // NYI sous jacente dans le cas ou, par construction, les vertex d'une
379   // NYI arete on des valeurs de parametre HORS des bornes [first,last] de la
380   // NYI courbe 3D support de l'arete (cas de l'arete de couture d'une sphere)
381   // On redefinit desormais le range de l'arete Eou, a la place de se 
382   // contenter du simplissime Eou = Ein.EmptyCopied();
383   // merci les amis : correction bug PRO2586
384
385   Standard_Real f,l;
386   TopoDS_Edge E1 = TopoDS::Edge(Ein); 
387   BRep_Tool::Range(E1,f,l);
388   Eou = Ein.EmptyCopied();
389   TopoDS_Edge E2 = TopoDS::Edge(Eou); 
390   myBuilder.Range(E2,f,l);
391 }
392
393
394 //=======================================================================
395 //function : GetOrientedEdgeVertices
396 //purpose  : 
397 //=======================================================================
398
399 void TopOpeBRepDS_BuildTool::GetOrientedEdgeVertices
400 (TopoDS_Edge& E,
401  TopoDS_Vertex& Vmin, TopoDS_Vertex& Vmax,
402  Standard_Real& Parmin, Standard_Real& Parmax) const
403 {
404   if ( E.Orientation() == TopAbs_FORWARD) 
405     TopExp::Vertices(E,Vmin,Vmax);
406   else
407     TopExp::Vertices(E,Vmax,Vmin);
408   if ( !Vmin.IsNull() && !Vmax.IsNull()) {  
409     Parmin = BRep_Tool::Parameter(Vmin,E);
410     Parmax = BRep_Tool::Parameter(Vmax,E);
411   }
412 }
413
414 //=======================================================================
415 //function : UpdateEdgeCurveTol
416 //purpose  : 
417 //=======================================================================
418
419 void TopOpeBRepDS_BuildTool::UpdateEdgeCurveTol
420 //(const TopoDS_Face& F1,const TopoDS_Face& F2,
421 (const TopoDS_Face& ,const TopoDS_Face& ,
422  TopoDS_Edge& E, const Handle(Geom_Curve)& C3Dnew,
423 // const Standard_Real tol3d,
424  const Standard_Real ,
425 // const Standard_Real tol2d1,
426  const Standard_Real ,
427 // const Standard_Real tol2d2,
428  const Standard_Real ,
429  Standard_Real& newtol,
430  Standard_Real& newparmin,
431  Standard_Real& newparmax) const
432
433 {
434   if (C3Dnew.IsNull()) return;
435   BRep_Builder BB;
436
437   // newtol = max des tolerances atteintes en 3d
438 // JMB le 06 Juillet 1999
439 // les valeurs tol3d et tol2d1,tol2d2 proviennent des approx. Dans la version 2.0 de CasCade, 
440 // elles n'etaient pas calculees et on renvoyait systematiquement les valeurs initiales (a savoir)
441 // 1.E-7. Dans la version 2.1 de CasCade, ces valeurs sont desormais calculees selon un calcul
442 // d'erreur dans les Approx. Malheureusement, il apparait que ce calcul d'erreur renvoit dans la
443 // plupart des cas de tres grosses valeurs (parfois de l'ordre de 1.E-1). Ce qui amenait la topologie
444 // a coder des tolerances enormes dans les pieces resultats rendant celles-ci inexpoitables.
445 // De plus on essayait de rafiner la tolerance en appelant les UResolution sur les surfaces support.
446 // sur des surfaces tres particulieres, ce UREsolution n'a plus aucun sens et peut amener a des valeurs
447 // abberantes.
448 // On decide donc de laisser la tolerance de l'edge telle qu'elle est afin d'avoir un comportement similaire
449 // a 2.0. Jusqu'a present on a constate que des problemes avec la methode de calcul d'erreur des approx.
450
451
452   newtol = 1.E-7;
453 //  Standard_Real r1,r2;
454 //  r1 = TopOpeBRepTool_ShapeTool::Resolution3d(F1,tol2d1);
455 //  r2 = TopOpeBRepTool_ShapeTool::Resolution3d(F2,tol2d2);
456 //  newtol=tol3d;
457 //  if (r1>newtol) newtol=r1;
458 //  if (r2>newtol) newtol=r2;
459
460 //  newtol *= 1.5;
461
462   TopoDS_Vertex Vmin,Vmax; Standard_Real parmin,parmax;
463   GetOrientedEdgeVertices(E,Vmin,Vmax,parmin,parmax);
464   
465   Standard_Real tolmin=BRep_Tool::Tolerance(Vmin);
466   if(newtol>tolmin) tolmin=newtol;
467   Standard_Real tolmax=BRep_Tool::Tolerance(Vmax);
468   if(newtol>tolmax) tolmax=newtol;
469
470
471 //  newparmin=C3Dnew->FirstParameter(); // -merge 04-07-97
472 //  newparmax=C3Dnew->LastParameter(); // -merge 04-07-97
473
474  // +merge 04-07-97
475   Handle(Geom_TrimmedCurve) GTC = Handle(Geom_TrimmedCurve)::DownCast(C3Dnew);
476   if(GTC.IsNull()) {
477     Handle(Geom_BSplineCurve) GBSC = Handle(Geom_BSplineCurve)::DownCast(C3Dnew);
478     if(GBSC.IsNull()) {
479       newparmin = parmin;
480       newparmax = parmax;
481     } else {
482       newparmin=C3Dnew->FirstParameter();
483       newparmax=C3Dnew->LastParameter();
484     } 
485   } else {
486     newparmin=C3Dnew->FirstParameter();
487     newparmax=C3Dnew->LastParameter();
488   } // +merge 04-07-97
489
490   if (Vmin.Orientation() == TopAbs_FORWARD) { 
491     BB.UpdateVertex(Vmin,newparmin,E,tolmin);
492     BB.UpdateVertex(Vmax,newparmax,E,tolmax);
493   }
494   else {
495     BB.UpdateVertex(Vmin,newparmax,E,tolmin);
496     BB.UpdateVertex(Vmax,newparmin,E,tolmax);
497   }
498   
499 //  DSBT.Curve3D(E,C3Dnew,newtol);  // -merge 04-07-97
500   Curve3D(E,C3Dnew,newtol);
501   
502   // projection des vertex INTERNAL de E pour parametrage
503   // sur la nouvelle courbe C3Dnew de l'arete E
504   TopExp_Explorer exi(E,TopAbs_VERTEX);
505   for (;exi.More(); exi.Next() ) {
506     const TopoDS_Vertex& vi = TopoDS::Vertex(exi.Current());
507     if ( vi.Orientation() != TopAbs_INTERNAL ) continue;
508     gp_Pnt P = BRep_Tool::Pnt(vi);
509     Standard_Real tolvi=TopOpeBRepTool_ShapeTool::Tolerance(vi);
510     GeomAPI_ProjectPointOnCurve dm(P,C3Dnew,newparmin,newparmax);
511     Standard_Boolean dmdone = dm.Extrema().IsDone();
512     if ( dmdone ) {
513       if ( dm.NbPoints() ) {
514         Standard_Real newpar = dm.LowerDistanceParameter();
515         BB.UpdateVertex(vi,newpar,E,tolvi);
516       }
517     }
518   } // INTERNAL vertex
519 }
520
521 //=======================================================================
522 //function : ApproxCurves
523 //purpose  : 
524 //=======================================================================
525
526 void  TopOpeBRepDS_BuildTool::ApproxCurves
527 (const TopOpeBRepDS_Curve& C,
528  TopoDS_Edge& E,
529  Standard_Integer& inewC,
530  const Handle(TopOpeBRepDS_HDataStructure)& HDS) const
531 {
532   TopOpeBRepDS_Curve newC1;
533   inewC = HDS->MakeCurve(C,newC1);
534   TopOpeBRepDS_Curve& newC = HDS->ChangeCurve(inewC);
535
536   // C1 curves have been approximated by BSplines of degree 1 :
537   // compute new geometry on curves.
538
539   const TopoDS_Face& F1 = TopoDS::Face(newC.Shape1());
540   const TopoDS_Face& F2 = TopoDS::Face(newC.Shape2());
541   
542   const Handle(Geom_Curve)& C3D = C.Curve();
543   const Handle(Geom2d_Curve)& PC1 = C.Curve1();
544   const Handle(Geom2d_Curve)& PC2 = C.Curve2();
545
546   // Vmin,Vmax = bounding vertices of edge <E>
547   // and their parameters parmin,parmax .
548
549   TopoDS_Vertex Vmin,Vmax;Standard_Real parmin,parmax;
550   GetOrientedEdgeVertices(E,Vmin,Vmax,parmin,parmax);
551
552   Handle(Geom_Curve)   C3Dnew;
553   Handle(Geom2d_Curve) PC1new;
554   Handle(Geom2d_Curve) PC2new;
555   Standard_Real tolreached3d,tolreached2d;
556   
557   Standard_Boolean approxMade = myCurveTool.MakeCurves(parmin,parmax,
558                          C3D,PC1,PC2,F1,F2,
559                          C3Dnew,PC1new,PC2new,
560                          tolreached3d,tolreached2d);
561
562   Standard_Real newtol,newparmin,newparmax;
563   // MSV Nov 12, 2001: if approx failed than leave old curves of degree 1
564   if (!approxMade) {
565     newtol = BRep_Tool::Tolerance(E);
566     newparmin = parmin;
567     newparmax = parmax;
568     C3Dnew = C3D;
569     PC1new = PC1;
570     PC2new = PC2;
571   }
572   else {
573     UpdateEdgeCurveTol
574       (F1,F2,E,C3Dnew,tolreached3d,tolreached2d,tolreached2d,
575        newtol,newparmin,newparmax);
576   }
577
578   if (!C3Dnew.IsNull()) {
579     newC.DefineCurve(C3Dnew,newtol,Standard_False);
580     newC.SetRange(newparmin,newparmax);
581   }
582
583   if (!PC1new.IsNull()) newC.Curve1(PC1new);
584   if (!PC2new.IsNull()) newC.Curve2(PC2new);
585 }
586
587
588 //=======================================================================
589 //function : ComputePCurves
590 //purpose  : 
591 //=======================================================================
592 Standard_Boolean FUN_getUV
593 (const Handle(Geom_Surface) surf,
594  const Handle(Geom_Curve) C3D,
595  const Standard_Real par3d,
596  Standard_Real& u0,
597  Standard_Real& v0)
598 {
599   gp_Pnt P3d; C3D->D0(par3d,P3d);
600   GeomAPI_ProjectPointOnSurf pons(P3d,surf);
601   if (pons.NbPoints() < 1) return Standard_False;
602   pons.LowerDistanceParameters(u0,v0);
603   return Standard_True;
604 }
605
606 Standard_Boolean FUN_reversePC
607 (Handle(Geom2d_Curve) PCnew,
608  const TopoDS_Face& F,
609  const gp_Pnt& P3DC3D,
610  const Standard_Real par2d,
611  const Standard_Real tol)
612 {
613   gp_Pnt2d P2D; PCnew->D0(par2d,P2D);
614   BRepAdaptor_Surface BAS(F,Standard_False);
615   gp_Pnt P3D = BAS.Value(P2D.X(),P2D.Y());
616   Standard_Boolean PCreversed = Standard_False;
617   Standard_Boolean sam = P3D.IsEqual(P3DC3D,tol);
618   PCreversed = !sam;
619
620   if ( PCreversed ) {
621     Handle(Geom2d_Curve) PC = ::BASISCURVE2D(PCnew);
622     if (!PC.IsNull()) {
623       Handle(Geom2d_Line) L = Handle(Geom2d_Line)::DownCast(PC);
624       gp_Dir2d d = L->Direction();
625       d.Reverse();
626       L->SetDirection(d);
627     }
628   }
629   return PCreversed;
630 }
631 Standard_Boolean FUN_makeUisoLineOnSphe
632 (const TopoDS_Face& F, // with geometry the spherical surface
633  const Handle(Geom_Curve) C3D, 
634  Handle(Geom2d_Curve) PCnew,
635  const Standard_Real tol3d)
636 {
637   // p3df,p3dl : C3d first and last parameters
638   Standard_Real p3df = C3D->FirstParameter();
639   Standard_Real p3dl = C3D->LastParameter();
640
641   // u0,v0 : C3d(par3d) UV parameters
642   Standard_Real deltainf = 0.243234, deltasup = 0.543345;
643   Standard_Real par3dinf = (1-deltainf)*p3df + deltainf*p3dl;
644   Standard_Real par3dsup = (1-deltasup)*p3df + deltasup*p3dl;
645   Standard_Real uinf,vinf,usup,vsup;
646   Handle(Geom_Surface) surf = BRep_Tool::Surface(F);
647   if (!FUN_getUV(surf,C3D,par3dinf,uinf,vinf)) return Standard_False;
648   if (!FUN_getUV(surf,C3D,par3dsup,usup,vsup)) return Standard_False;
649   Standard_Real tol = Precision::Parametric(tol3d);
650   if (Abs(uinf-usup) > tol) return Standard_False;
651
652   Standard_Boolean isvgrowing = (vsup - vinf > -tol);
653   gp_Dir2d vdir;
654   if (isvgrowing) vdir = gp_Dir2d(0,1);
655   else            vdir = gp_Dir2d(0,-1);
656   
657   gp_Pnt2d origin(uinf,vinf);
658   origin.Translate(gp_Vec2d(vdir).Scaled(p3df-par3dinf));
659   Handle(Geom2d_Curve) PC = ::BASISCURVE2D(PCnew);
660   if (!PC.IsNull()) {  
661     Handle(Geom2d_Line) L = Handle(Geom2d_Line)::DownCast(PC); 
662     L->SetLin2d(gp_Lin2d(origin,vdir));
663   } // (!PC.IsNull())
664   
665   return Standard_True;
666 }
667
668 void TopOpeBRepDS_BuildTool::ComputePCurves
669 (const TopOpeBRepDS_Curve& C,
670  TopoDS_Edge& E,
671  TopOpeBRepDS_Curve& newC,
672  const Standard_Boolean comppc1,
673  const Standard_Boolean comppc2,
674  const Standard_Boolean compc3d) const
675 {
676   const TopoDS_Face& F1 = TopoDS::Face(newC.Shape1());
677   const TopoDS_Face& F2 = TopoDS::Face(newC.Shape2());
678   
679   const Handle(Geom_Curve)& C3D = C.Curve();
680
681   // get bounding vertices Vmin,Vmax supported by the new edge <E>
682   // and their corresponding parameters parmin,parmax .
683
684   TopoDS_Vertex Vmin,Vmax;Standard_Real parmin,parmax;
685   GetOrientedEdgeVertices(E,Vmin,Vmax,parmin,parmax);
686
687   Handle(Geom2d_Curve) PC1new;
688   Handle(Geom2d_Curve) PC2new;
689   
690   if(C3D.IsNull()) {
691     Standard_Real tolreached2d1 = Precision::Confusion(), tolreached2d2 = Precision::Confusion(), r1, r2, tol=Precision::Confusion();
692     if (comppc1) PC1new = myCurveTool.MakePCurveOnFace(F1,C3D,tolreached2d1);
693     if (comppc2) PC2new = myCurveTool.MakePCurveOnFace(F2,C3D,tolreached2d2);
694     
695     r1 = TopOpeBRepTool_ShapeTool::Resolution3d(F1,tolreached2d1);
696     r2 = TopOpeBRepTool_ShapeTool::Resolution3d(F2,tolreached2d2);
697     tol = Max(tol,r1);
698     tol = Max(tol,r2);
699     newC.Tolerance(tol);
700     
701     if (!PC1new.IsNull()) newC.Curve1(PC1new);
702     if (!PC2new.IsNull()) newC.Curve2(PC2new);
703
704     return;
705   }
706   
707   Handle(Geom_Curve) C3Dnew = C3D;
708   
709   if ( C3D->IsPeriodic() ) {
710     // ellipse on cone : periodize parmin,parmax
711     Standard_Real period = C3D->LastParameter() - C3D->FirstParameter();
712     Standard_Real f,l;
713     if (Vmin.Orientation() == TopAbs_FORWARD) { f = parmin; l = parmax; }
714     else {                                      f = parmax; l = parmin; }
715     parmin = f; parmax = l;
716     ElCLib::AdjustPeriodic(f,f+period,Precision::PConfusion(),parmin,parmax);
717     if (compc3d) C3Dnew = new Geom_TrimmedCurve(C3D,parmin,parmax);
718     
719   }
720   
721   Standard_Real tolreached3d = C.Tolerance();
722   Standard_Real tolreached2d1 = C.Tolerance();
723   Standard_Real tolreached2d2 = C.Tolerance();
724   
725   if (comppc1) PC1new = myCurveTool.MakePCurveOnFace(F1,C3Dnew,tolreached2d1);
726   if (comppc2) PC2new = myCurveTool.MakePCurveOnFace(F2,C3Dnew,tolreached2d2);
727   
728   Standard_Real newtol,newparmin,newparmax;
729   UpdateEdgeCurveTol(F1,F2,E,C3Dnew,tolreached3d,tolreached2d1,tolreached2d2,
730                      newtol,newparmin,newparmax);
731   
732     // xpu : suite merge : 07-07-97
733     // xpu : 17-06-97
734     // Rmq : C1.Curve<i>() ne sert plus qu'a determiner si la courbe
735     //       est une isos de la sphere
736     // NYI : enlever FUN_reversePC
737     Standard_Boolean UisoLineOnSphe1 = Standard_False;
738     UisoLineOnSphe1 = ::FUN_UisoLineOnSphe(F1,PC1new);
739     if (UisoLineOnSphe1) ::FUN_makeUisoLineOnSphe(F1,C3Dnew,PC1new,newtol);
740
741     Standard_Boolean UisoLineOnSphe2 = Standard_False;
742     UisoLineOnSphe2 = ::FUN_UisoLineOnSphe(F2,PC2new);
743     if (UisoLineOnSphe2) ::FUN_makeUisoLineOnSphe(F2,C3Dnew,PC2new,newtol);
744     // xpu : 17-06-97
745     // xpu : suite merge : 07-07-97
746
747   if (!C3Dnew.IsNull()) {
748     newC.Curve(C3Dnew,newtol);
749     newC.SetRange(newparmin, newparmax);
750   }
751   if (!PC1new.IsNull()) newC.Curve1(PC1new);
752   if (!PC2new.IsNull()) newC.Curve2(PC2new);
753 }
754
755 //=======================================================================
756 //function : PutPCurves
757 //purpose  : 
758 //=======================================================================
759
760 void  TopOpeBRepDS_BuildTool::PutPCurves
761 (const TopOpeBRepDS_Curve& newC,
762  TopoDS_Edge& E,
763  const Standard_Boolean comppc1,
764  const Standard_Boolean comppc2) const
765 {
766
767   TopoDS_Face& F1 = *((TopoDS_Face*)(void*)&(TopoDS::Face(newC.Shape1())));
768   Handle(Geom2d_Curve) PC1 = newC.Curve1();
769   if (!PC1.IsNull() && comppc1) {
770     PCurve(F1,E,PC1);
771   }
772   
773   TopoDS_Face& F2 = *((TopoDS_Face*)(void*)&(TopoDS::Face(newC.Shape2())));
774   Handle(Geom2d_Curve) PC2 = newC.Curve2();
775   if (!PC2.IsNull() && comppc2) {
776     PCurve(F2,E,PC2);
777   }
778   
779 }
780
781 //=======================================================================
782 //function : RecomputeCurves
783 //purpose  : 
784 //=======================================================================
785
786 void  TopOpeBRepDS_BuildTool::RecomputeCurves
787 (const TopOpeBRepDS_Curve& C,
788 // const TopoDS_Edge& oldE,
789  const TopoDS_Edge& ,
790  TopoDS_Edge& E,
791  Standard_Integer& inewC,
792  const Handle(TopOpeBRepDS_HDataStructure)& HDS) const
793 {
794   const TopOpeBRepTool_GeomTool& GT = myCurveTool.GetGeomTool();
795   const Standard_Boolean compc3d = GT.CompC3D();
796   const Standard_Boolean comppc1 = GT.CompPC1();
797   const Standard_Boolean comppc2 = GT.CompPC2();
798   const Standard_Boolean comppc = comppc1 || comppc2;
799   const Standard_Boolean iswalk = C.IsWalk();
800   const Standard_Boolean approx = Approximation();
801   
802   const Handle(Geom_Curve)& C3D = C.Curve();
803   if (comppc1 && C.Shape1().IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 2");
804   if (comppc2 && C.Shape2().IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 3");
805   TopoDS_Vertex Vmin,Vmax; TopExp::Vertices(E,Vmin,Vmax);
806   if ( Vmin.IsNull() ) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 4");
807   if ( Vmax.IsNull() ) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 5");
808   
809   if (iswalk && approx) {
810     if (compc3d && C3D.IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 1");
811     ApproxCurves(C, E, inewC, HDS);
812     TopOpeBRepDS_Curve& newC = HDS->ChangeCurve(inewC);
813     PutPCurves(newC, E, comppc1, comppc2);
814   }
815 //  else if (iswalk && interpol) {
816 //    InterpolCurves(C, E, inewC, comppc1, comppc2, HDS);
817 //    TopOpeBRepDS_Curve& newC = HDS->ChangeCurve(inewC);
818 //    PutPCurves(newC, E, comppc1, comppc2);
819 //  }
820
821   else {
822     if (comppc) {
823       TopOpeBRepDS_Curve newC1;
824       inewC = HDS->MakeCurve(C,newC1);
825       TopOpeBRepDS_Curve& newC = HDS->ChangeCurve(inewC);
826       if(iswalk && !approx) {
827         if (compc3d && C3D.IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 1");
828         newC.Curve1(C.Curve1());
829         newC.Curve2(C.Curve2());
830       }
831       else
832         ComputePCurves(C, E, newC, comppc1, comppc2, compc3d);  
833       PutPCurves(newC, E, comppc1, comppc2);
834     }
835   }
836 }
837
838 //=======================================================================
839 //function : CopyFace
840 //purpose  : 
841 //=======================================================================
842
843 void  TopOpeBRepDS_BuildTool::CopyFace(const TopoDS_Shape& Fin, 
844                                        TopoDS_Shape& Fou)const 
845 {
846   Fou = Fin.EmptyCopied();
847 }
848
849
850 //=======================================================================
851 //function : AddEdgeVertex
852 //purpose  : 
853 //=======================================================================
854
855 void  TopOpeBRepDS_BuildTool::AddEdgeVertex(const TopoDS_Shape& Ein, 
856                                             TopoDS_Shape& Eou, 
857                                             const TopoDS_Shape& V)const 
858 {
859   myBuilder.Add(Eou,V);
860   TopoDS_Edge e1 = TopoDS::Edge(Ein);
861   TopoDS_Edge e2 = TopoDS::Edge(Eou);
862   TopoDS_Vertex v1 = TopoDS::Vertex(V);
863   myBuilder.Transfert(e1,e2,v1,v1);
864 }
865
866
867 //=======================================================================
868 //function : AddEdgeVertex
869 //purpose  : 
870 //=======================================================================
871
872 void  TopOpeBRepDS_BuildTool::AddEdgeVertex(TopoDS_Shape& E, 
873                                             const TopoDS_Shape& V)const 
874 {
875   myBuilder.Add(E,V);
876 }
877
878
879 //=======================================================================
880 //function : AddWireEdge
881 //purpose  : 
882 //=======================================================================
883
884 void  TopOpeBRepDS_BuildTool::AddWireEdge(TopoDS_Shape& W, 
885                                           const TopoDS_Shape& E)const 
886 {
887   myBuilder.Add(W,E);
888 }
889
890
891 //=======================================================================
892 //function : AddFaceWire
893 //purpose  : 
894 //=======================================================================
895
896 void  TopOpeBRepDS_BuildTool::AddFaceWire(TopoDS_Shape& F, 
897                                           const TopoDS_Shape& W)const 
898 {
899   myBuilder.Add(F,W);
900 }
901
902
903 //=======================================================================
904 //function : AddShellFace
905 //purpose  : 
906 //=======================================================================
907
908 void  TopOpeBRepDS_BuildTool::AddShellFace(TopoDS_Shape& Sh, 
909                                            const TopoDS_Shape& F)const 
910 {
911   myBuilder.Add(Sh,F);
912 }
913
914
915 //=======================================================================
916 //function : AddSolidShell
917 //purpose  : 
918 //=======================================================================
919
920 void  TopOpeBRepDS_BuildTool::AddSolidShell(TopoDS_Shape& S, 
921                                             const TopoDS_Shape& Sh)const 
922 {
923   myBuilder.Add(S,Sh);
924 }
925
926
927 //=======================================================================
928 //function : Parameter
929 //purpose  : 
930 //=======================================================================
931
932 void  TopOpeBRepDS_BuildTool::Parameter(const TopoDS_Shape& E, 
933                                         const TopoDS_Shape& V, 
934                                         const Standard_Real P)const 
935 {
936   const TopoDS_Edge&   e = TopoDS::Edge(E);
937   const TopoDS_Vertex& v = TopoDS::Vertex(V);
938   Standard_Real p = P;
939
940   // 13/07/95 : 
941   TopLoc_Location loc; Standard_Real f,l;
942   Handle(Geom_Curve) C = BRep_Tool::Curve(e,loc,f,l);
943   if ( !C.IsNull() && C->IsPeriodic()) {
944     Standard_Real per = C->Period();
945
946     TopAbs_Orientation oV=TopAbs_FORWARD;
947
948     TopExp_Explorer exV(e,TopAbs_VERTEX);
949     for (; exV.More(); exV.Next()) {
950       const TopoDS_Vertex& vofe = TopoDS::Vertex(exV.Current());
951       if ( vofe.IsSame(v) ) {
952         oV = vofe.Orientation();
953         break;
954       }
955     }
956     if ( exV.More() ) {
957       if ( oV == TopAbs_REVERSED ) {
958         if ( p < f ) {
959           Standard_Real pp = ElCLib::InPeriod(p,f,f+per);
960           p = pp;
961         }
962       }
963     }
964   }
965
966   myBuilder.UpdateVertex(v,p,e,
967                          0);   // NYI : Tol on new vertex ?? 
968 }
969
970 //=======================================================================
971 //function : Range
972 //purpose  : 
973 //=======================================================================
974
975 void  TopOpeBRepDS_BuildTool::Range(const TopoDS_Shape& E, 
976                                     const Standard_Real first,
977                                     const Standard_Real last)const 
978 {
979   myBuilder.Range(TopoDS::Edge(E),first,last);
980 }
981
982
983 //=======================================================================
984 //function : UpdateEdge
985 //purpose  : 
986 //=======================================================================
987
988 void  TopOpeBRepDS_BuildTool::UpdateEdge(const TopoDS_Shape& Ein,
989                                          TopoDS_Shape& Eou)const
990 {
991   TopLoc_Location loc;
992   Standard_Real f1,l1;
993   Standard_Real f2,l2;
994   Handle(Geom_Curve) Cin = BRep_Tool::Curve(TopoDS::Edge(Ein),loc,f1,l1);
995   Handle(Geom_Curve) Cou = BRep_Tool::Curve(TopoDS::Edge(Eou),loc,f2,l2);
996   if (Cin.IsNull() || Cou.IsNull()) return;
997   
998   if ( Cou->IsPeriodic() ) {
999     Standard_Real f2n = f2, l2n = l2;
1000     if ( l2n <= f2n ) {
1001       ElCLib::AdjustPeriodic(f1,l1,Precision::PConfusion(),f2n,l2n);
1002       Range(Eou,f2n,l2n);
1003     }
1004   }
1005 }
1006
1007 //=======================================================================
1008 //function : Project
1009 //purpose  : project a vertex on a curve
1010 //=======================================================================
1011
1012 static Standard_Boolean Project(const Handle(Geom_Curve)& C,
1013                                 const TopoDS_Vertex& V,
1014                                 Standard_Real& p)
1015 {
1016   gp_Pnt P = BRep_Tool::Pnt(V);
1017   Standard_Real tol = BRep_Tool::Tolerance(V);
1018   GeomAdaptor_Curve GAC(C);
1019   Extrema_ExtPC extrema(P,GAC);
1020   if (extrema.IsDone()) {
1021     Standard_Integer i,n = extrema.NbExt();
1022     for (i = 1; i <= n; i++) {
1023       if (extrema.IsMin(i)) {
1024         Extrema_POnCurv EPOC = extrema.Point(i);
1025         if (P.Distance(EPOC.Value()) <= tol) {
1026           p = EPOC.Parameter();
1027           return Standard_True;
1028         }
1029       }
1030     }
1031   }
1032   return Standard_False;
1033 }
1034
1035
1036 //=======================================================================
1037 //function : Parameter
1038 //purpose  : 
1039 //=======================================================================
1040
1041 void  TopOpeBRepDS_BuildTool::Parameter(const TopOpeBRepDS_Curve& C,
1042                                         TopoDS_Shape& E,
1043                                         TopoDS_Shape& V)const 
1044 {
1045   Standard_Real newparam;
1046   Project(C.Curve(),TopoDS::Vertex(V),newparam);
1047   Parameter(E,V,newparam);
1048 }
1049
1050
1051 //=======================================================================
1052 //function : Curve3D
1053 //purpose  : 
1054 //=======================================================================
1055
1056 void  TopOpeBRepDS_BuildTool::Curve3D
1057 (TopoDS_Shape& E, 
1058  const Handle(Geom_Curve)& C,
1059  const Standard_Real Tol)const 
1060 {
1061   myBuilder.UpdateEdge(TopoDS::Edge(E),
1062                        C,
1063                        Tol);
1064 }
1065
1066
1067 //=======================================================================
1068 //function : TranslateOnPeriodic
1069 //purpose  : 
1070 //=======================================================================
1071
1072 void TopOpeBRepDS_BuildTool::TranslateOnPeriodic
1073   (TopoDS_Shape& F,
1074    TopoDS_Shape& E,
1075    Handle(Geom2d_Curve)& PC) const
1076 {
1077   // get range C3Df,C3Dl of 3d curve C3D of E
1078   TopLoc_Location L; 
1079   Standard_Real C3Df,C3Dl;
1080 //  Handle(Geom_Curve) C3D = BRep_Tool::Curve(TopoDS::Edge(E),L,C3Df,C3Dl);
1081   Handle(Geom_Curve) C3D = BRep_Tool::Curve(TopoDS::Edge(E),C3Df,C3Dl); // 13-07-97: xpu
1082  
1083   Standard_Real first = C3Df, last = C3Dl;
1084   if (C3D->IsPeriodic()) {
1085     if ( last < first ) last += Abs(first - last);
1086   }
1087
1088   // jyl-xpu : 13-06-97 : 
1089   // if <PC> is U isoline on sphere, a special parametrization
1090   // is to provide, we compute <PC> (which is a line) bounds 
1091   // with C3D bounds.
1092   Standard_Boolean UisoLineOnSphe = FUN_UisoLineOnSphe(F,PC);
1093   Standard_Boolean newv = Standard_True;
1094
1095   Standard_Real du,dv;
1096
1097   gp_Pnt2d ptest;
1098   Standard_Real t =(first+last)*.5;
1099   PC->D0(t,ptest);
1100   Standard_Real u1 = ptest.X(), u2 = u1;
1101   Standard_Real v1 = ptest.Y(), v2 = v1;
1102
1103   if (newv) {
1104     if (UisoLineOnSphe) {
1105       Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(E),C3Df,C3Dl);
1106       GeomAdaptor_Curve GC(c3d); gp_Pnt p3dtest = GC.Value(t);
1107       Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(F));
1108       GeomAPI_ProjectPointOnSurf pons(p3dtest,surf);
1109       if (!(pons.NbPoints() < 1))
1110         pons.LowerDistanceParameters(u2,v2);
1111     } else TopOpeBRepTool_ShapeTool::AdjustOnPeriodic(F,u2,v2);
1112   }
1113   if (!newv) TopOpeBRepTool_ShapeTool::AdjustOnPeriodic(F,u2,v2);
1114   du = u2 - u1, dv = v2 - v1;    
1115
1116   if ( du != 0. || dv != 0.) {
1117     // translate curve PC of du,dv
1118     Handle(Geom2d_Curve) PCT = Handle(Geom2d_Curve)::DownCast(PC->Copy());
1119     PCT->Translate(gp_Vec2d(du,dv));
1120     PC = PCT;
1121   }
1122 }
1123
1124
1125 // RLE - IAB 16 june 94
1126 // should be provided by the BRep_Builder
1127
1128 Standard_EXPORT void TopOpeBRepDS_SetThePCurve(const BRep_Builder& B,
1129                                                TopoDS_Edge& E,
1130                                                const TopoDS_Face& F,
1131                                                const TopAbs_Orientation O,
1132                                                const Handle(Geom2d_Curve)& C)
1133 {
1134   // check if there is already a pcurve on non planar faces
1135   Standard_Real f,l;
1136   Handle(Geom2d_Curve) OC;
1137   TopLoc_Location SL;
1138   Handle(Geom_Plane) GP = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(F,SL));
1139   if (GP.IsNull())
1140     OC = BRep_Tool::CurveOnSurface(E,F,f,l);
1141
1142   if (OC.IsNull()) 
1143     B.UpdateEdge(E,C,F,Precision::Confusion());
1144   else {
1145     Standard_Boolean degen = BRep_Tool::Degenerated(E);
1146     if(!degen){
1147       if (O == TopAbs_REVERSED) 
1148         B.UpdateEdge(E,OC,C,F,Precision::Confusion());
1149       else 
1150         B.UpdateEdge(E,C,OC,F,Precision::Confusion());
1151     }
1152   }
1153 }
1154
1155 //=======================================================================
1156 //function : PCurve
1157 //purpose  : 
1158 //=======================================================================
1159
1160 void  TopOpeBRepDS_BuildTool::PCurve(TopoDS_Shape& F, 
1161                                      TopoDS_Shape& E, 
1162                                      const Handle(Geom2d_Curve)& PC)const 
1163 {
1164   if ( ! PC.IsNull() ) {
1165     TopoDS_Face FF = TopoDS::Face(F);
1166     TopoDS_Edge EE = TopoDS::Edge(E);
1167     Handle(Geom2d_Curve) PCT = PC;
1168
1169     // pour iab, ajout de Translate
1170     Standard_Boolean tran = myTranslate;
1171
1172     // xpu : 13-06-97 : 
1173     // recompute twice the pcurve boundaries if OverWrite
1174     // if the pcurve <PC> is U isoline on sphere -> to avoid.
1175     Standard_Boolean UisoLineOnSphe = FUN_UisoLineOnSphe(F,PC);
1176     Standard_Boolean overwrite = UisoLineOnSphe? Standard_False:myOverWrite;
1177     // xpu : 13-06-97
1178
1179     if (tran)      
1180       TranslateOnPeriodic(F,E,PCT);  
1181
1182     if (overwrite) 
1183       myBuilder.UpdateEdge(EE,PCT,FF,0);
1184     else           
1185       TopOpeBRepDS_SetThePCurve(myBuilder,EE,FF,E.Orientation(),PCT);
1186
1187     // parametrage sur la nouvelle courbe 2d
1188     TopExp_Explorer exi(E,TopAbs_VERTEX);
1189     for (;exi.More(); exi.Next() ) {
1190       const TopoDS_Vertex& vi = TopoDS::Vertex(exi.Current());
1191       if ( vi.Orientation() != TopAbs_INTERNAL ) continue;
1192       Standard_Real tolvi = TopOpeBRepTool_ShapeTool::Tolerance(vi);
1193       // NYI tester l'existence d'au moins
1194       // NYI un parametrage de vi sur EE (en 3d ou en 2d) 
1195       // NYI --> a faire dans BRep_Tool
1196       Standard_Real newpar = BRep_Tool::Parameter(vi,EE);
1197       myBuilder.UpdateVertex(vi,newpar,EE,FF,tolvi);
1198     } // INTERNAL vertex
1199   }
1200 }
1201
1202 //=======================================================================
1203 //function : PCurve
1204 //purpose  : 
1205 //=======================================================================
1206
1207 void  TopOpeBRepDS_BuildTool::PCurve(TopoDS_Shape& F, 
1208                                      TopoDS_Shape& E, 
1209                                      const TopOpeBRepDS_Curve& CDS,
1210                                      const Handle(Geom2d_Curve)& PC)const
1211 {
1212   if ( ! PC.IsNull() ) {
1213     TopoDS_Face FF = TopoDS::Face(F);
1214     TopoDS_Edge EE = TopoDS::Edge(E);
1215
1216     Handle(Geom2d_Curve) PCT = PC;
1217     Standard_Real    CDSmin,CDSmax;
1218     Standard_Boolean rangedef = CDS.Range(CDSmin,CDSmax);
1219
1220     
1221     TopLoc_Location L; Standard_Real Cf,Cl;
1222     Handle(Geom_Curve) C = BRep_Tool::Curve(EE,L,Cf,Cl);
1223       
1224     if (!C.IsNull()){
1225       Standard_Boolean deca = (Abs(Cf - CDSmin) > Precision::PConfusion());
1226       Handle(Geom2d_Line) line2d = Handle(Geom2d_Line)::DownCast(PCT);
1227       Standard_Boolean isline2d = !line2d.IsNull();
1228       Standard_Boolean tran=(rangedef && deca && C->IsPeriodic() && isline2d);
1229       if (tran) {
1230         TopLoc_Location Loc;
1231         const Handle(Geom_Surface) Surf = BRep_Tool::Surface(FF,Loc);
1232         Standard_Boolean isUperio = Surf->IsUPeriodic();
1233         Standard_Boolean isVperio = Surf->IsVPeriodic();
1234         gp_Dir2d dir2d = line2d->Direction();
1235         Standard_Real delta;
1236         if (isUperio && dir2d.IsParallel(gp::DX2d(),Precision::Angular())) {
1237           delta = (CDSmin - Cf) * dir2d.X();
1238           PCT->Translate(gp_Vec2d(delta,0.));
1239         }
1240         else if(isVperio && dir2d.IsParallel(gp::DY2d(),Precision::Angular())){
1241           delta = (CDSmin - Cf) * dir2d.Y();
1242           PCT->Translate(gp_Vec2d(0.,delta));
1243         }
1244       }
1245     }
1246     
1247     TopOpeBRepDS_SetThePCurve(myBuilder,EE,FF,E.Orientation(),PCT);
1248   }
1249 }
1250
1251
1252 //=======================================================================
1253 //function : Orientation
1254 //purpose  : 
1255 //=======================================================================
1256
1257 void  TopOpeBRepDS_BuildTool::Orientation(TopoDS_Shape& S, 
1258                                           const TopAbs_Orientation O)const 
1259 {
1260   S.Orientation(O);
1261 }
1262
1263
1264 //=======================================================================
1265 //function : Orientation
1266 //purpose  : 
1267 //=======================================================================
1268
1269 TopAbs_Orientation  TopOpeBRepDS_BuildTool::Orientation
1270   (const TopoDS_Shape& S) const
1271 {
1272   return S.Orientation();
1273 }
1274
1275 //=======================================================================
1276 //function : Closed
1277 //purpose  : 
1278 //=======================================================================
1279
1280 void  TopOpeBRepDS_BuildTool::Closed(TopoDS_Shape& S, 
1281                                      const Standard_Boolean B)const 
1282 {
1283   S.Closed(B);
1284 }
1285
1286
1287 //=======================================================================
1288 //function : Approximation
1289 //purpose  : 
1290 //=======================================================================
1291
1292 Standard_Boolean TopOpeBRepDS_BuildTool::Approximation() const
1293 {
1294   return myCurveTool.GetGeomTool().TypeC3D() != TopOpeBRepTool_BSPLINE1;
1295 }
1296
1297 void TopOpeBRepDS_BuildTool::UpdateSurface(const TopoDS_Shape& F,const Handle(Geom_Surface)& SU) const
1298 {
1299   BRep_Builder BB;
1300   TopLoc_Location L;
1301   Standard_Real tol = BRep_Tool::Tolerance(TopoDS::Face(F));
1302   BB.UpdateFace(TopoDS::Face(F),SU,L,tol);
1303 }
1304
1305 void TopOpeBRepDS_BuildTool::UpdateSurface(const TopoDS_Shape& E,const TopoDS_Shape& oldF,
1306                                            const TopoDS_Shape& newF) const
1307 {
1308   BRep_Builder BB;
1309   Standard_Real f,l;
1310   const Handle(Geom2d_Curve)& PC = BRep_Tool::CurveOnSurface(TopoDS::Edge(E),TopoDS::Face(oldF),f,l);
1311   Standard_Real tol = BRep_Tool::Tolerance(TopoDS::Face(oldF));
1312   BB.UpdateEdge(TopoDS::Edge(E),PC,TopoDS::Face(newF),tol);
1313 }
1314
1315
1316 /* // - merge 04-07-97
1317 //=======================================================================
1318 //function : RecomputeCurve
1319 //purpose  : 
1320 //=======================================================================
1321
1322 void  TopOpeBRepDS_BuildTool::RecomputeCurve
1323 (const TopOpeBRepDS_Curve& C1,
1324  TopoDS_Shape& E,
1325  TopOpeBRepDS_Curve& C2 ) const
1326 {
1327   // - C1 curves have been approximated by BSplines of degree 1 :
1328   // or
1329   // - C1.Curve() is non projectable on at least one of the original
1330   // intersecting faces.
1331
1332   const TopOpeBRepTool_GeomTool& GT = myCurveTool.GetGeomTool();
1333   Standard_Boolean compc3d = GT.CompC3D();
1334   Standard_Boolean comppc1 = GT.CompPC1();
1335   Standard_Boolean comppc2 = GT.CompPC2();
1336   
1337   const Handle(Geom_Curve)& C3D = C1.Curve();
1338   if (compc3d && C3D.IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 1");
1339   if (comppc1 && C2.Shape1().IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 2");
1340   if (comppc2 && C2.Shape2().IsNull()) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 3");
1341   TopoDS_Vertex Vmin,Vmax; TopExp::Vertices(TopoDS::Edge(E),Vmin,Vmax);
1342   if ( Vmin.IsNull() ) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 4");
1343   if ( Vmax.IsNull() ) throw Standard_ProgramError("TopOpeBRepDS_BuildTool::RecomputeCurve 5");
1344
1345   Standard_Boolean kbspl1 = Standard_False;
1346   Handle(Geom_BSplineCurve) BS = Handle(Geom_BSplineCurve)::DownCast(C3D);
1347   if (!BS.IsNull()) kbspl1 = (BS->Degree() == 1);
1348   if (kbspl1) RecomputeBSpline1Curve(C1,E,C2);
1349   else        RecomputeCurveOnCone(C1,E,C2);
1350 }
1351
1352 //=======================================================================
1353 //function : RecomputeBSpline1Curve
1354 //purpose  : 
1355 //=======================================================================
1356
1357 void  TopOpeBRepDS_BuildTool::RecomputeBSpline1Curve
1358 (const TopOpeBRepDS_Curve& C1,
1359  TopoDS_Shape& EE,
1360  TopOpeBRepDS_Curve& C2) const
1361 {
1362   // C1 curves have been approximated by BSplines of degree 1 :
1363   // compute new geometry on curves.
1364
1365   TopoDS_Edge& E = TopoDS::Edge(EE);
1366
1367   const TopOpeBRepTool_GeomTool& GT = myCurveTool.GetGeomTool();
1368   TopOpeBRepTool_OutCurveType typec3d = GT.TypeC3D();
1369   Standard_Boolean compc3d =            GT.CompC3D();
1370   Standard_Boolean comppc1 =            GT.CompPC1();
1371   Standard_Boolean comppc2 =            GT.CompPC2();
1372
1373   const TopoDS_Face& F1 = TopoDS::Face(C2.Shape1());
1374   const TopoDS_Face& F2 = TopoDS::Face(C2.Shape2());
1375   
1376   const Handle(Geom_Curve)&   C3D = C1.Curve();
1377   const Handle(Geom2d_Curve)& PC1 = C1.Curve1();
1378   const Handle(Geom2d_Curve)& PC2 = C1.Curve2();
1379
1380   // Vmin,Vmax = bounding vertices of edge <E>
1381   // and their parameters parmin,parmax .
1382
1383   TopoDS_Vertex Vmin,Vmax; Standard_Real parmin,parmax;
1384   ::GetOrientedEdgeVertices(E,Vmin,Vmax,parmin,parmax);
1385
1386  
1387   Handle(Geom_Curve)   C3Dnew;
1388   Handle(Geom2d_Curve) PC1new;
1389   Handle(Geom2d_Curve) PC2new;
1390   Standard_Real tolreached3d,tolreached2d;
1391
1392   if ( typec3d == TopOpeBRepTool_BSPLINE1 ) {
1393     if ( compc3d ) {
1394       C3Dnew = Handle(Geom_BSplineCurve)::DownCast(C3D->Copy());
1395       (Handle(Geom_BSplineCurve)::DownCast(C3Dnew))->Segment(parmin,parmax);
1396     }
1397     if ( comppc1 && (!PC1.IsNull()) ) {
1398       PC1new = Handle(Geom2d_BSplineCurve)::DownCast(PC1->Copy());
1399       (Handle(Geom2d_BSplineCurve)::DownCast(PC1new))->Segment(parmin,parmax);
1400     }
1401     if ( comppc2 && (!PC2.IsNull()) ) {
1402       PC2new = Handle(Geom2d_BSplineCurve)::DownCast(PC2->Copy());
1403       (Handle(Geom2d_BSplineCurve)::DownCast(PC2new))->Segment(parmin,parmax);
1404     }
1405   }
1406
1407   else if ( typec3d == TopOpeBRepTool_APPROX ) {
1408     if (!comppc1 || !comppc2) throw Standard_NotImplemented("DSBuildToolAPPROX");
1409     myCurveTool.MakeCurves(parmin,parmax,
1410                            C3D,PC1,PC2,F1,F2,
1411                            C3Dnew,PC1new,PC2new,
1412                            tolreached3d,tolreached2d);
1413   }
1414
1415   else if ( typec3d == TopOpeBRepTool_INTERPOL ) {
1416     throw Standard_NotImplemented("DSBuildToolINTERPOL");
1417   }
1418
1419   Standard_Real newtol,newparmin,newparmax;
1420   ::FUN_updateEDGECURVETOL
1421     (*this,F1,F2,E,C3Dnew,tolreached3d,tolreached2d,tolreached2d,
1422      newtol,newparmin,newparmax);
1423   
1424   if (!C3Dnew.IsNull()) {
1425     C2.DefineCurve(C3Dnew,newtol,Standard_False);
1426     C2.SetRange(newparmin,newparmax);
1427   }
1428   if (!PC1new.IsNull()) C2.Curve1(PC1new);
1429   if (!PC2new.IsNull()) C2.Curve2(PC2new);
1430 }
1431
1432
1433 //=======================================================================
1434 //function : RecomputeCurveOnCone
1435 //purpose  : 
1436 //=======================================================================
1437
1438 void  TopOpeBRepDS_BuildTool::RecomputeCurveOnCone
1439   (const TopOpeBRepDS_Curve& C1,
1440    TopoDS_Shape&             EE,
1441    TopOpeBRepDS_Curve&       C2 ) const
1442 {
1443   // C1 Pcurves have not been computed because C1 Curve is not projectable
1444   // on one at least of the intersecting faces giving C1 Curve.
1445   // (see TopOpeBRepTool_CurveTool::IsProjectable())
1446
1447   TopoDS_Edge& E = TopoDS::Edge(EE);
1448   
1449   const TopOpeBRepTool_GeomTool& GT = myCurveTool.GetGeomTool();
1450   TopOpeBRepTool_OutCurveType typec3d = GT.TypeC3D();
1451   Standard_Boolean compc3d =            GT.CompC3D();
1452   Standard_Boolean comppc1 =            GT.CompPC1();
1453   Standard_Boolean comppc2 =            GT.CompPC2();
1454   
1455   const TopoDS_Face& F1 = TopoDS::Face(C2.Shape1());
1456   const TopoDS_Face& F2 = TopoDS::Face(C2.Shape2());
1457   
1458   const Handle(Geom_Curve)&   C3D = C1.Curve();
1459   const Handle(Geom2d_Curve)& PC1 = C1.Curve1();
1460   const Handle(Geom2d_Curve)& PC2 = C1.Curve2();
1461
1462   // get bounding vertices Vmin,Vmax supported by the new edge <E>
1463   // and their corresponding parameters parmin,parmax .
1464
1465   TopoDS_Vertex Vmin,Vmax; Standard_Real parmin,parmax;
1466   ::GetOrientedEdgeVertices(E,Vmin,Vmax,parmin,parmax);
1467
1468   if ( C3D->IsPeriodic() ) {
1469     // ellipse on cone : periodize parmin,parmax
1470     Standard_Real period = C3D->LastParameter() - C3D->FirstParameter();
1471     Standard_Real f,l;
1472     if (Vmin.Orientation() == TopAbs_FORWARD) { f = parmin; l = parmax; }
1473     else {                                      f = parmax; l = parmin; }
1474     parmin = f; parmax = l;
1475     ElCLib::AdjustPeriodic(f,f+period,Precision::PConfusion(),parmin,parmax);
1476   }
1477   
1478   Handle(Geom_TrimmedCurve) C3Dnew;
1479   Handle(Geom2d_Curve) PC1new;
1480   Handle(Geom2d_Curve) PC2new;
1481   Standard_Real tolreached3d = C1.Tolerance();
1482   Standard_Real tolreached2d1 = C1.Tolerance();
1483   Standard_Real tolreached2d2 = C1.Tolerance();
1484   if (compc3d) C3Dnew = new Geom_TrimmedCurve(C3D,parmin,parmax);
1485   if (comppc1) PC1new = myCurveTool.MakePCurveOnFace(F1,C3Dnew,tolreached2d1);
1486   if (comppc2) PC2new = myCurveTool.MakePCurveOnFace(F2,C3Dnew,tolreached2d2);
1487
1488 #ifdef DRAW
1489   if (tBUTO) {FUN_draw(F1); FUN_draw(F2); FUN_draw(E);}
1490 #endif
1491
1492   Standard_Real newtol,newparmin,newparmax;
1493   FUN_updateEDGECURVETOL
1494   (*this,F1,F2,E,C3Dnew,tolreached3d,tolreached2d1,tolreached2d2,
1495    newtol,newparmin,newparmax);
1496
1497 //   jyl : 16-06-97
1498 //  Standard_Real fac = 0.3798123578771;
1499 //  Standard_Real tol = newtol;
1500 //  Standard_Real par3d = (1-fac)*newparmin + (fac)*newparmax;
1501 //  Standard_Real par2d = par3d - newparmin;
1502 //
1503 //  gp_Pnt P3DC3D;       C3D->D0(par3d,P3DC3D);
1504 //
1505 //  Standard_Boolean UisoLineOnSphe1 = Standard_False;
1506 //  UisoLineOnSphe1 = ::FUN_UisoLineOnSphe(F1,PC1new);
1507 //  if (UisoLineOnSphe1) {
1508 //    Standard_Real isrev1 = 
1509 //      ::FUN_reversePC(PC1new,F1,P3DC3D,par2d,tol);
1510 //    
1511 //
1512 //  }
1513 //
1514 //  Standard_Boolean UisoLineOnSphe2 = Standard_False;
1515 //  UisoLineOnSphe2 = ::FUN_UisoLineOnSphe(F2,PC2new);
1516 //  if (UisoLineOnSphe2) {
1517 //    Standard_Real isrev2 = 
1518 //     ::FUN_reversePC(PC2new,F2,P3DC3D,par2d,tol);
1519 //
1520 //  }
1521
1522   // xpu : 17-06-97
1523   // Rmq : C1.Curve<i>() ne sert plus qu'a determiner si la courbe
1524   //       est une isos de la sphere
1525   // NYI : enlever FUN_reversePC
1526   Standard_Boolean UisoLineOnSphe1 = Standard_False;
1527   UisoLineOnSphe1 = ::FUN_UisoLineOnSphe(F1,PC1new);
1528   if (UisoLineOnSphe1) {
1529     ::FUN_makeUisoLineOnSphe(F1,C3Dnew,PC1new,newtol);
1530   }
1531   Standard_Boolean UisoLineOnSphe2 = Standard_False;
1532   UisoLineOnSphe2 = ::FUN_UisoLineOnSphe(F2,PC2new);
1533   if (UisoLineOnSphe2) {
1534     ::FUN_makeUisoLineOnSphe(F2,C3Dnew,PC2new,newtol);
1535   } // xpu : 17-06-97
1536
1537   if (!C3Dnew.IsNull()) C2.Curve(C3Dnew,newtol);
1538   if (!PC1new.IsNull()) C2.Curve1(PC1new);
1539   if (!PC2new.IsNull()) C2.Curve2(PC2new);
1540 }*/ // - merge 04-07-97
1541
1542