0024023: Revamp the OCCT Handle -- general
[occt.git] / src / StepToTopoDS / StepToTopoDS_TranslateEdgeLoop.cxx
1 // Created on: 1995-03-29
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1995-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 // gka 21.08.98 PRO7656
18 // gka 15.12.98 UKI60591 #1274560
19 //pdn 18.12.98 to keep pcurves
20 //:o0 abv 16.02.99: POLYLINE allowed as 3d curve of edge
21 //:   abv 07.04.99: S4136: improve tolerance management and dealing with pcurves
22 //    rln 02.06.99 removing #include <StepToTopoDS_DegeneratedTool.hxx>
23 //    smh 31.01.01 BUC60810 : IsNull protection
24 #include <StepToTopoDS_TranslateEdgeLoop.ixx>
25
26 #include <StepToTopoDS.hxx>
27 #include <StepToTopoDS_TranslateVertex.hxx>
28 #include <StepToTopoDS_TranslateEdge.hxx>
29 #include <StepToTopoDS_GeometricTool.hxx>
30 #include <ShapeAnalysis_Curve.hxx>
31 #include <StepToGeom_MakeCurve2d.hxx>
32 #include <StepToGeom_MakeCurve.hxx>
33
34 #include <Geom_RectangularTrimmedSurface.hxx>
35
36 #include <StepShape_EdgeLoop.hxx>
37 #include <StepShape_Edge.hxx>
38 #include <StepShape_OrientedEdge.hxx>
39 #include <StepShape_Vertex.hxx>
40 #include <StepGeom_Curve.hxx>
41 #include <StepShape_EdgeCurve.hxx>
42 #include <StepGeom_Pcurve.hxx>
43 #include <StepGeom_SurfaceCurve.hxx>
44 #include <StepRepr_DefinitionalRepresentation.hxx>
45 #include <StepGeom_PcurveOrSurface.hxx>
46
47 #include <BRep_Builder.hxx>
48 #include <BRep_Tool.hxx>
49
50 #include <TopoDS.hxx>
51 #include <TopoDS_Wire.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Vertex.hxx>
54
55 #include <BRep_TEdge.hxx>
56 #include <BRep_CurveRepresentation.hxx>
57 #include <BRep_ListOfCurveRepresentation.hxx>
58 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
59
60 #include <TopExp_Explorer.hxx>
61 #include <TopExp.hxx>
62
63 #include <TopLoc_Location.hxx>
64 #include <TopAbs.hxx>
65
66 #include <Geom_Surface.hxx>
67 #include <Geom_Plane.hxx>
68 #include <Geom_Curve.hxx>
69
70 #include <Geom2d_Curve.hxx>
71 #include <Geom2d_BoundedCurve.hxx>
72 #include <Geom2d_Line.hxx>
73
74 #include <gp_Pnt.hxx>
75 #include <gp_Pnt2d.hxx>
76
77 #include <Precision.hxx>
78 #include <Interface_Static.hxx>
79 #include <Transfer_TransientProcess.hxx>
80 #include <TopoDS_Iterator.hxx>
81 #include <ShapeFix_EdgeProjAux.hxx>
82 #include <ShapeAnalysis_Edge.hxx>
83 #include <ShapeExtend_WireData.hxx>
84 #include <ShapeBuild_Edge.hxx>
85
86 #include <ShapeAlgo.hxx>
87 #include <ShapeAlgo_AlgoContainer.hxx>
88 #include <ShapeAlgo_ToolContainer.hxx>
89 #include <XSAlgo.hxx>
90 #include <XSAlgo_AlgoContainer.hxx>
91 #include <ElCLib.hxx>
92 #include <Standard_ErrorHandler.hxx>
93 #include <StepGeom_Polyline.hxx>
94
95 // ============================================================================
96 // Method  : RemoveSinglePCurve
97 // Purpose : 
98 // ============================================================================
99
100 static void RemoveSinglePCurve (const TopoDS_Edge& aEdge, const TopoDS_Face& aFace)
101 {
102   ShapeBuild_Edge().RemovePCurve (aEdge, aFace);
103 }
104
105 // ============================================================================
106 // Method  : RemovePCurves
107 // Purpose : 
108 // ============================================================================
109
110 static void RemovePCurves(const TopoDS_Wire& aWire, const TopoDS_Face& aFace)
111 {
112   TopExp_Explorer EdgeExp(aWire, TopAbs_EDGE);
113   while (EdgeExp.More()) {
114     const TopoDS_Edge& myEdge = TopoDS::Edge(EdgeExp.Current());
115     RemoveSinglePCurve(myEdge,aFace);
116     EdgeExp.Next();
117   }
118 }
119
120 // ============================================================================
121 // Method  : CheckPCurves
122 // Purpose : Checks the pcurves topological trimming parameter consistency
123 //           and deviation between 2D ans 3D  
124 // ============================================================================
125
126 static void CheckPCurves (TopoDS_Wire& aWire, const TopoDS_Face& aFace,
127                           const Standard_Boolean isPlane,const Standard_Real preci )
128 {
129   if (isPlane) { RemovePCurves (aWire,aFace);return; }
130   BRep_Builder B;
131   Standard_Real w1, w2, cf, cl;
132   Handle(Geom_Surface) mySurf = BRep_Tool::Surface(aFace);
133   
134   Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData ( aWire );
135   for (Standard_Integer i = 1; i <= sbwd->NbEdges(); i++) {
136     const TopoDS_Edge& myEdge = sbwd->Edge(i);
137 //    B.SameRange( myEdge, Standard_True );
138 //    B.SameParameter ( myEdge, Standard_True ); 
139     
140     // First Check : 2D Parameters on Edge :
141     // Case 1 : w1 == w2 illegal => Drop the PCurve
142     // Case 2 : on bounded curve w1 < FirstParameter => w1 = FirstParameter
143     //                           w2 > LastParameter  => w2 = LastParameter
144
145     Handle(Geom2d_Curve) thePC;
146     ShapeAnalysis_Edge sae;
147     if (!sae.PCurve (myEdge, aFace, thePC, w1, w2, Standard_False )) {
148       continue;
149     }
150     cf = thePC->FirstParameter();
151     cl = thePC->LastParameter();
152     
153     if (w1 == w2) {
154       RemoveSinglePCurve(myEdge,aFace);
155 #ifdef OCCT_DEBUG
156       cout<<"Removing pcuve w1=w2"<<endl;
157 #endif      
158       continue;
159     }
160
161     if (w1 < cf) {
162       B.Range(myEdge, aFace, cf, w2);
163       w1 = cf;
164     }
165     if (w2 > cl) {
166       B.Range(myEdge, aFace, w1, cl);      
167       w2 = cf;
168     }
169
170     if (w1 > w2 && mySurf->IsUPeriodic())
171     {
172       Standard_Real u1,u2,v1,v2;
173       mySurf->Bounds(u1,u2,v1,v2);
174       ElCLib::AdjustPeriodic(u1, u2, 
175         Min(Abs(w2-w1)/2,Precision::PConfusion()), 
176         w1, w2);
177       B.Range(myEdge, aFace, w1, w2);   
178     }
179
180     
181     // advanced check
182     XSAlgo::AlgoContainer()->CheckPCurve (myEdge, aFace, preci, sbwd->IsSeam(i) );
183   }
184 }
185
186 // ============================================================================
187 // Method  : StepToTopoDS_TranslateEdgeLoop::StepToTopoDS_TranslateEdgeLoop
188 // Purpose : Empty Constructor
189 // ============================================================================
190
191 StepToTopoDS_TranslateEdgeLoop::StepToTopoDS_TranslateEdgeLoop()
192 {
193   done = Standard_False;
194 }
195
196 // ============================================================================
197 // Method  : StepToTopoDS_TranslateEdgeLoop::StepToTopoDS_TranslateEdgeLoop
198 // Purpose : Constructor with a FaceSurface and a Tool
199 // ============================================================================
200
201 StepToTopoDS_TranslateEdgeLoop::StepToTopoDS_TranslateEdgeLoop(const Handle(StepShape_FaceBound)& FB, 
202                                                                const TopoDS_Face& Face,
203                                                                const Handle(Geom_Surface)& GeomSurf,
204                                                                const Handle(StepGeom_Surface)& StepSurf,
205                                                                const Standard_Boolean sameSense,
206                                                                StepToTopoDS_Tool& T,
207                                                                StepToTopoDS_NMTool& NMTool) {
208   Init(FB, Face, GeomSurf, StepSurf, sameSense, T, NMTool);
209 }
210
211 // ============================================================================
212 // Method  : Init
213 // Purpose : Init with a EdgeLoop and a Tool
214 // ============================================================================
215
216 void StepToTopoDS_TranslateEdgeLoop::Init(const Handle(StepShape_FaceBound)& FaceBound, 
217                                           const TopoDS_Face& Face,
218                                           const Handle(Geom_Surface)& GeomSurf,
219                                           const Handle(StepGeom_Surface)& StepSurf,
220                                           const Standard_Boolean sameSense,
221                                           StepToTopoDS_Tool& aTool,
222                                           StepToTopoDS_NMTool& NMTool) {
223   done = Standard_True;
224   Handle(StepShape_EdgeLoop) EL = 
225     Handle(StepShape_EdgeLoop)::DownCast(FaceBound->Bound());
226
227   if (aTool.IsBound(EL)) {
228     myResult = TopoDS::Wire(aTool.Find(EL));
229     myError  = StepToTopoDS_TranslateEdgeLoopDone;
230     done     = Standard_True;
231     return;
232   }
233   Standard_Integer modepcurve = Interface_Static::IVal("read.surfacecurve.mode");
234 //  0,1 : suivre le code,  2 : ne prendre que pcurve,  3 : ne prendre que C3D
235
236   BRep_Builder B;
237   Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
238   
239   Standard_Real preci = Precision();
240   TopoDS_Wire   W;
241   TopoDS_Edge   E;
242   TopoDS_Vertex V;
243
244 //  Standard_Real U1,U2, U1a, U1b, U2a, U2b;
245   
246   Standard_Boolean isSeam, isLikeSeam;
247   
248   Handle(StepShape_Edge)         StepEdge, StepEdge1;
249   Handle(StepShape_OrientedEdge) OrEdge1, OrEdge2;
250   Handle(StepGeom_Curve) StepCurve, StepCurve1, StepCurve2;
251 //  Handle(StepGeom_Pcurve) StepPCurve, StepPCurve1, StepPCurve2;
252   Handle(StepRepr_DefinitionalRepresentation) DRI, Dri1, Dri2;
253   
254   Handle(Geom2d_Curve) C2d, C2d1, C2d2, WhichC2d1, WhichC2d2;
255 // unused  gp_Pnt Pdeb, Pmil, Pfin, pV1, pV2;
256   
257   TopoDS_Edge   suspectE; //:f1, degEdge; 
258   
259   Standard_Integer j, NbEdge = EL->NbEdgeList();
260   if( NbEdge == 0) {
261     TP->AddWarning(EL,"Wire not done. EdgeLoop does not contain edges.");
262     done = Standard_False;
263     return;
264   }
265 // PTV 16.09.2000 
266 // default value set as Standard_True (if not correct see logic of algorithm).
267   Standard_Boolean hasPcurve = Standard_True;
268   Standard_Boolean isPlane = GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane));
269   Handle(Geom_Surface) ConvSurf = GeomSurf;
270   if (GeomSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
271     Handle(Geom_RectangularTrimmedSurface) theRTS =
272       Handle(Geom_RectangularTrimmedSurface)::DownCast(GeomSurf);
273     ConvSurf = theRTS->BasisSurface();
274   }
275
276   aTool.ComputePCurve(Standard_False);
277   
278   // What is the Wire Orientation
279   Standard_Boolean ForwardWire = FaceBound->Orientation();
280
281   // --- Initialize target Wire ---
282
283   B.MakeWire(W);
284
285 //  Standard_Integer lastpcurve = 0;
286
287   // -----------------------------------------------
288   // Preparation : Make Vertices + Curves3d
289   //  Hence, a closed curve limited by distinct vertices
290   //  will give a unique vertex (if same coords)
291   //
292   // In addition : detect shared PCurve (cf SYRKO)
293   //  This case may not be processed, PCurves has to be recomputed from scratch
294   // -----------------------------------------------
295 //  Standard_Integer theSame = 1; //gka 15.12.98
296   
297   for (j=1; j<=NbEdge; j++ ) {
298     OrEdge1  = EL->EdgeListValue(j);
299     StepEdge = OrEdge1->EdgeElement();
300 //    if(j>1 && StepEdge == StepEdge1) theSame++; //gka 15.12.98
301     StepEdge1 = StepEdge;                         //
302     Handle(StepShape_EdgeCurve) EC = Handle(StepShape_EdgeCurve)::DownCast(StepEdge);
303     Handle(StepGeom_Curve) C = EC->EdgeGeometry();
304     if (!C.IsNull()){
305       if (C->IsKind(STANDARD_TYPE(StepGeom_SurfaceCurve))) {
306         Handle(StepGeom_SurfaceCurve) Sc = Handle(StepGeom_SurfaceCurve)::DownCast(C);
307         C = Sc->Curve3d();
308 //      if (modepcurve != 3) {
309 //      lastpcurve = StepToTopoDS_GeometricTool::PCurve (Sc,StepSurf,StepPCurve1);
310 //      if (StepPCurve1 == StepPCurve) modepcurve = -1;
311 //      StepPCurve = StepPCurve1;
312 //      }
313       }
314     }
315 ////    else if (C->IsKind(STANDARD_TYPE(StepGeom_Polyline))) {  }
316 //    else if (C->IsKind(STANDARD_TYPE(StepGeom_Pcurve))) {
317 //      if (modepcurve != 3) {
318 //      if (C == StepPCurve) modepcurve = -1;
319 //      StepPCurve = Handle(StepGeom_Pcurve)::DownCast(C);
320 //      }
321 //    }
322     Handle(Geom_Curve) C1;
323     if (!C.IsNull()) {
324       try
325       {
326         OCC_CATCH_SIGNALS
327         C1 = Handle(Geom_Curve)::DownCast (TP->FindTransient(C));
328         if (C1.IsNull()) {
329           if (StepToGeom_MakeCurve::Convert(C,C1))
330             TP->BindTransient (C,C1);
331           else
332             TP->AddWarning(C,"Could not convert a curve. Curve definition is incorrect");
333         }
334       }
335       catch (Standard_Failure)
336       {
337         TP->AddFail(C,"Exeption was raised. Curve geometry definition is incorrect");
338 #ifdef OCCT_DEBUG
339   cout << "Warning: StepToTopoDS_TranslateEdgeLoop: Exception: ";
340   Standard_Failure::Caught()->Print(cout); cout << endl;
341 #endif
342       }
343     }
344
345     Handle(StepShape_Vertex) Vstart, Vend;
346     if (EC->SameSense()) {
347       Vstart = EC->EdgeStart();
348       Vend   = EC->EdgeEnd();
349     }
350     else {
351       Vend   = EC->EdgeStart();
352       Vstart = EC->EdgeEnd();
353     }
354
355     Standard_Boolean istV = aTool.IsBound(Vstart);
356     Standard_Boolean iseV = aTool.IsBound(Vend);
357     TopoDS_Vertex V1, V2;
358     StepToTopoDS_TranslateVertex myTranVertex1(Vstart, aTool, NMTool);
359     StepToTopoDS_TranslateVertex myTranVertex2(Vend, aTool, NMTool);
360
361     if (myTranVertex1.IsDone()) {
362       V1 = TopoDS::Vertex(myTranVertex1.Value());
363     }
364 //    if (Vend == Vstart) {  cas normal deja assure par aTool
365 //      aTool.Bind (Vend,V1);
366 //    }
367 //    else
368     if (myTranVertex2.IsDone()) {
369       V2 = TopoDS::Vertex(myTranVertex2.Value());
370       gp_Pnt p1 = BRep_Tool::Pnt(V1);
371       gp_Pnt p2 = BRep_Tool::Pnt(V2);
372       if (p1.Distance(p2) <= Precision::Confusion() ) { //:S4136: preci) {
373         Standard_Boolean Fixed = Standard_True;
374         if(!iseV) aTool.Bind(Vend,V1); //gka 21.08.1998 bug PRO7656 
375         else if(!istV)  aTool.Bind (Vstart,V2);
376         else aTool.Bind (Vend,V1);
377         //Fixed = Standard_False;
378         //aTool.Bind (Vend,V1);
379         if (!C1.IsNull() && !C1->IsClosed() && Fixed)
380           TP->AddWarning(EL->EdgeListValue(j),
381                          "Vertex of same coordinates, set confused");
382       }
383     }
384   }
385 //  if (NbEdge!=1 && theSame == NbEdge) {
386 //    TP->AddWarning(EL,"Wire was ignored. All edges are the same.");
387 //    done = Standard_False;
388 //    return;
389 //  }
390 //  Fixed=Standard_True;
391 //  if (modepcurve == -1) {
392 //    modepcurve = 3;
393 //    TP->AddWarning(EL,"Shared Pcurve not allowed, Pcurves are recomputed");
394 //  }
395
396   //:f6 abv 29 Apr 98: BUC50070 #3815: make sure that each two edges are
397   // connected by the same vertex; else check that vertices confuse
398   // and make it be one vertex
399   // NOTE: this is done only for the case if at least one of edges 
400   // was not yet translated; else nothing will help
401   for (j=1; j<=NbEdge; j++ ) {
402     OrEdge1  = EL->EdgeListValue ( j );
403     OrEdge2  = EL->EdgeListValue ( j < NbEdge ? j + 1 : 1 );
404     Handle(StepShape_EdgeCurve) EC1 = 
405       Handle(StepShape_EdgeCurve)::DownCast ( OrEdge1->EdgeElement() );
406     Handle(StepShape_EdgeCurve) EC2 = 
407       Handle(StepShape_EdgeCurve)::DownCast ( OrEdge2->EdgeElement() );
408
409     Handle(StepShape_Vertex) Vs1, Vs2,Vs11,Vs22;
410     Vs1 = ( OrEdge1->Orientation() ? EC1->EdgeEnd() : EC1->EdgeStart() );
411     Vs2 = ( OrEdge2->Orientation() ? EC2->EdgeStart() : EC2->EdgeEnd() );
412
413     Vs11 = ( OrEdge1->Orientation() ?  EC1->EdgeStart() : EC1->EdgeEnd());
414     Vs22 = ( OrEdge2->Orientation() ?  EC2->EdgeEnd() : EC2->EdgeStart() );
415
416     if((Vs1 == Vs2) || (Vs1 == Vs22) || (Vs2 == Vs11) || (Vs22 == Vs11)) continue;
417     //??    if ( Vs1.IsSame(Vs2) ) continue; // OK
418
419     StepToTopoDS_TranslateVertex myTranVertex1 (Vs1, aTool, NMTool);
420     StepToTopoDS_TranslateVertex myTranVertex2 (Vs2, aTool, NMTool);
421
422     TopoDS_Vertex V1, V2;
423     if ( myTranVertex1.IsDone() ) 
424       V1 = TopoDS::Vertex ( myTranVertex1.Value() );
425     if ( myTranVertex2.IsDone() ) 
426       V2 = TopoDS::Vertex ( myTranVertex2.Value() );
427     if ( V1.IsNull() || V2.IsNull() ) continue; // not treated
428     if ( V1.IsSame(V2) ) continue; // OK
429
430     gp_Pnt p1 = BRep_Tool::Pnt(V1);
431     gp_Pnt p2 = BRep_Tool::Pnt(V2);
432     Standard_Boolean locFixed = Standard_True;
433     if (p1.Distance(p2) <= preci) {
434       if ( ! aTool.IsBound ( EC1 ) ) aTool.Bind ( Vs1, V2 );
435       else if ( ! aTool.IsBound ( EC2 ) ) aTool.Bind ( Vs2, V1 );
436       else locFixed = Standard_False;
437     }
438     else locFixed = Standard_False;
439     if ( locFixed ) TP->AddWarning(EL,"Adjacent edges do not have common vertex; set confused");
440     else TP->AddWarning(EL,"Adjacent edges are not connected");
441   }
442
443   // -----------------------------------------------
444   // Iteration on each Oriented Edge of the EdgeLoop
445   // -----------------------------------------------
446
447   for (j=1; j<=NbEdge; j++ ) {
448
449     Standard_Boolean ThereIsLikeSeam = Standard_False;
450     
451 #ifdef OCCT_DEBUG
452     cout << "      Processing Edge :" << j << endl;
453 #endif
454
455     OrEdge1  = EL->EdgeListValue(j);
456     StepEdge = OrEdge1->EdgeElement();
457     Handle(StepShape_EdgeCurve) EC = Handle(StepShape_EdgeCurve)::DownCast(StepEdge);
458     
459     // ----------------
460     // Map the StepEdge
461     // ----------------
462     
463     StepToTopoDS_TranslateEdge myTranEdge;
464     
465     myTranEdge.SetPrecision(preci);
466     myTranEdge.SetMaxTol(MaxTol());
467     myTranEdge.Init(OrEdge1, aTool, NMTool);
468
469     if (myTranEdge.IsDone()) {
470       
471       E = TopoDS::Edge(myTranEdge.Value());
472       if (E.IsNull()) continue;  // NULL, on saute
473
474       Handle(StepGeom_Curve) C = EC->EdgeGeometry();
475
476       if (OrEdge1->Orientation() && EC->SameSense()) 
477         E.Orientation(TopAbs_FORWARD);
478       else if (!OrEdge1->Orientation() && !EC->SameSense())
479         E.Orientation(TopAbs_FORWARD);
480       else E.Orientation(TopAbs_REVERSED);
481
482       isSeam = isLikeSeam = Standard_False;
483       
484       // ------------------------------------------
485       // Map the StepEdge parametric representation
486       // ------------------------------------------
487
488       // --------------------------------------------
489       // CASE 1 : The Edge Geometry is of Pcurve Type
490       // --------------------------------------------
491       if (C.IsNull())
492       {
493         aTool.ComputePCurve(Standard_True);
494         hasPcurve = Standard_False;
495       }
496       else if (C->IsKind(STANDARD_TYPE(StepGeom_Pcurve))) {
497         Handle(StepGeom_Pcurve) StepPCurve = Handle(StepGeom_Pcurve)::DownCast(C);
498         C2d = myTranEdge.MakePCurve (StepPCurve,ConvSurf);
499         // -- Statistics --
500         aTool.AddContinuity (C2d);
501       }
502
503       // -----------------------------------------
504       // CASE 2 : The curve is a SurfaceCurve i.e. 
505       //           - a 3D Curve (mandatory)
506       //           - 2 PCurveOrSurface
507       //   If modepcurve = 3, PCurve are ignored here
508       // -----------------------------------------
509
510       else if (modepcurve == 3) {
511         aTool.ComputePCurve(Standard_True);
512         hasPcurve = Standard_False;
513       }
514       else if (C->IsKind(STANDARD_TYPE(StepGeom_SurfaceCurve)) ) {
515         // recouvre les cas SeamCurve et IntersectionCurve
516         
517         Handle(StepGeom_SurfaceCurve) SurfCurve =
518           Handle(StepGeom_SurfaceCurve)::DownCast(C);
519
520         Handle(StepGeom_Pcurve) StepPCurve, StepPCurve1, StepPCurve2;
521         Standard_Integer lastpcurve = StepToTopoDS_GeometricTool::PCurve(SurfCurve,StepSurf,StepPCurve,0);
522         hasPcurve = !StepPCurve.IsNull();
523
524         // De toute facon, on recalcule
525
526         if (isPlane) hasPcurve = Standard_False;
527
528         // -------------------------------------------
529         // ---        Special Mapping Cases :      ---
530         // ---   the SurfaceCurve is a SeamCurve   ---
531         // ---        or is like a seam curve      ---
532         // ---         (see CATIA cylinder)        ---
533         // -------------------------------------------
534         isLikeSeam = StepToTopoDS_GeometricTool::IsLikeSeam(SurfCurve,StepSurf,StepEdge,EL);
535
536         isSeam = StepToTopoDS_GeometricTool::IsSeamCurve(SurfCurve, StepSurf,StepEdge, EL);
537         
538         if (isSeam || isLikeSeam) {
539           // isLikeSeam = Two faces on the same Surface
540           StepPCurve1 = SurfCurve->AssociatedGeometryValue(1).Pcurve();
541           StepPCurve2 = SurfCurve->AssociatedGeometryValue(2).Pcurve();
542           if (StepPCurve1.IsNull() || StepPCurve2.IsNull()) hasPcurve = Standard_False; //smh : BUC60810
543           else {
544             C2d1 = myTranEdge.MakePCurve (StepPCurve1,ConvSurf);
545             C2d2 = myTranEdge.MakePCurve (StepPCurve2,ConvSurf);
546             hasPcurve = (!C2d1.IsNull() && !C2d2.IsNull());
547           }
548
549           if (isLikeSeam) {
550             suspectE = E;
551             ThereIsLikeSeam = Standard_True;
552             hasPcurve = Standard_True;
553           }
554         }
555         else if (hasPcurve) {
556 //  GeometricTool : Pcurve a retourne StepPCurve
557           while (lastpcurve > 0) {
558             C2d1 = myTranEdge.MakePCurve (StepPCurve,ConvSurf);
559             if (C2d1.IsNull()) {
560               hasPcurve = Standard_False;
561               break;
562             }
563             else C2d = C2d1;
564             lastpcurve = StepToTopoDS_GeometricTool::PCurve(SurfCurve,StepSurf,StepPCurve,lastpcurve);
565             // -- Statistics --
566             aTool.AddContinuity (C2d);
567           }
568         }
569         if (!hasPcurve) {
570           // The edge geometry has no 2D representation
571           aTool.ComputePCurve(Standard_True);
572         }
573       }
574       
575       // ----------------------------------------------------------
576       // CASE 3 : The EdgeCurve Geometry is not a Pcurve 
577       //          nor a SurfaceCurve (i.e. it is a single 3D curve)
578       // ----------------------------------------------------------
579
580       else {
581         aTool.ComputePCurve(Standard_True);
582         hasPcurve = Standard_False;
583       }
584       
585       // ----------------------------------
586       // update the edge with the pcurve(s)
587       // ----------------------------------
588
589       if (hasPcurve && (isSeam || ThereIsLikeSeam)) {
590
591       // -----------------------------------------------------------
592       // The Edge is a Seam Edge : The pcurve wich is FORWARD has to
593       //                           be identified
594       // -----------------------------------------------------------
595       
596         if ((!C2d1.IsNull()) && (!C2d2.IsNull())) {
597           TopAbs_Orientation CumulO, EdgeO, WireO, FaceO;
598           EdgeO = E.Orientation();
599           if (ForwardWire)  WireO = TopAbs_FORWARD;
600           else              WireO = TopAbs_REVERSED;
601           if (sameSense) FaceO = TopAbs_FORWARD;
602           else           FaceO = TopAbs_REVERSED;
603
604           CumulO = TopAbs::Compose(EdgeO, WireO);
605           CumulO = TopAbs::Compose(CumulO, FaceO);
606
607           Standard_Boolean ForwardEdge = (CumulO == TopAbs_FORWARD);
608
609           // if(!ThereIsLikeSeam) ForwardEdge = Standard_True;
610           Standard_Integer forwardPC =
611             ShapeAnalysis_Curve().SelectForwardSeam (C2d1,C2d2);
612           if (forwardPC == 0) {
613             TP->AddFail(StepEdge," Seam curve not mapped");
614             done = Standard_False;
615             myError = StepToTopoDS_TranslateEdgeLoopOther;
616             continue;
617           }
618           else if (!ForwardEdge) forwardPC = 3 - forwardPC;  // inverser 1-2
619
620           if (forwardPC == 1) {
621             if(isSeam) {
622               // When the edge is a Seam, it is better to find the topological
623               // trimming right now. 
624               // Remarque : pour bien faire, il faudrait, si necessaire, recalculer
625               //            les trois courbes de maniere a ce qu`elles soient
626               //            immediatement Same Range et Same Parameter.
627               B.UpdateEdge(E, C2d1, C2d2, Face, 0.);
628 //:S4136              FindParameter(C2d1, C2d2, E, Face, preci);
629             }
630             else
631               B.UpdateEdge(E, C2d1, Face, 0.); //preci
632           }
633           else {
634             if(isSeam) {
635               // When the edge is a Seam, it is better to find the topological
636               // trimming right now. 
637               B.UpdateEdge(E, C2d2, C2d1, Face, 0.);
638 //:S4136              FindParameter(C2d1, C2d2, E, Face, preci);
639             }
640             else
641               B.UpdateEdge(E, C2d2, Face, 0.);
642           }
643         }
644         else {
645           TP->AddFail(StepEdge," Seam curve not mapped");
646           done = Standard_False;
647           myError = StepToTopoDS_TranslateEdgeLoopOther;
648           continue;
649         }
650       }
651       else {
652         
653         // ---------------------------
654         // The Edge is a "normal" edge
655         // ---------------------------
656         
657         if (hasPcurve) {
658           if ( !C2d.IsNull() && !isLikeSeam ) {
659             B.UpdateEdge(E, C2d, Face, 0.);
660           }
661           else {
662             TP->AddFail(StepEdge," Edge: Trimming of 2D curve failed");
663             //    cout << "2D curve type : " << C2d->DynamicType() << endl;
664             done = Standard_False;
665             myError = StepToTopoDS_TranslateEdgeLoopOther;
666             continue;
667           }
668         }
669       }
670
671       if (!E.IsNull()) {
672 //      B.Add(W,E);   -- DABORD regarder degeneree manquante !!!
673       }
674       else {
675         TP->AddFail(StepEdge," an Edge not mapped");
676         done = Standard_False;
677         myError = StepToTopoDS_TranslateEdgeLoopOther;
678 //      continue;
679       }
680     }
681     else { // The Edge is Not mapped => switch to next wire ?
682       TP->AddFail(StepEdge," an Edge not mapped");
683       done = Standard_False;
684       myError = StepToTopoDS_TranslateEdgeLoopOther;
685 //      continue;
686     }
687
688     if (done) B.Add (W,E);  // on le fait ici. Sauf si erreur rencontree ... !
689     else {
690       Handle(StepShape_Vertex) Vs1, Vs2;
691       Vs1 = StepEdge->EdgeStart();
692       Vs2 = StepEdge->EdgeEnd();
693       if(!Vs1.IsNull() && !Vs2.IsNull() && Vs1==Vs2) {
694         done = Standard_True;
695         TP->AddFail(EL," Edge with equal vertices failed, scipped");
696       }
697     }
698   }
699
700   // The EdgeLoop is binded in the Wire
701
702   if (!done) {
703     TP->AddFail(EL,"At least one edge failed : wire not done");
704     return;
705   }
706   W.Closed (BRep_Tool::IsClosed (W));
707   aTool.Bind(EL, W);
708   
709   // ----------------------------------------------
710   // Computes the 2D parameter of Vertices on Edges
711   // ----------------------------------------------
712   //pdn compute parameter of Vertices using progecting
713   if (!aTool.ComputePCurve()) 
714     for (TopoDS_Iterator EdgeIt(W);EdgeIt.More();EdgeIt.Next()){
715       TopoDS_Edge edge = TopoDS::Edge(EdgeIt.Value());
716       Handle(ShapeFix_EdgeProjAux) myEdgePro = ShapeAlgo::AlgoContainer()->ToolContainer()->EdgeProjAux();
717       myEdgePro->Init (Face, edge);
718       myEdgePro->Compute(preci);
719       if (myEdgePro->IsFirstDone() && myEdgePro->IsLastDone()) {
720         if (Abs (myEdgePro->FirstParam() - myEdgePro->LastParam()) < Precision::PConfusion())
721           continue;
722         B.Range(edge, Face,myEdgePro->FirstParam(), myEdgePro->LastParam());
723       }
724       else {
725         RemoveSinglePCurve(edge, Face);
726 #ifdef OCCT_DEBUG
727         cout <<"Removing after prj"<<endl;
728 #endif
729       }
730     }       
731     
732   myResult = W;
733   myError  = StepToTopoDS_TranslateEdgeLoopDone;
734   done     = Standard_True;
735   //  Check des PCurves SYSTEMATIQUE, s il n y en a que quelques unes
736 //  if (isPlane) RemovePCurves (W, Face);
737 // else         CheckPCurves  (W, Face);
738   CheckPCurves  (W, Face,isPlane,preci);
739
740   // --------------------------------------------      
741   // Control the UVLoop (Closed and Head To Tail)
742   // --------------------------------------------
743   
744 //  StepToTopoDS_GeometricToolError tError = 
745 //    StepToTopoDS_GeometricTool::CloseUV(W, Face, aTool);
746 //  if(tError != StepToTopoDS_GeometricToolDone) {
747 //    TP->AddWarning(StepEdge,StepToTopoDS::DecodeGeometricToolError(tError));
748 //  }
749   return;
750 }
751
752
753 // ============================================================================
754 // Method  : Value 
755 // Purpose : Return the mapped Shape
756 // ============================================================================
757
758 const TopoDS_Shape& StepToTopoDS_TranslateEdgeLoop::Value() const 
759 {
760   StdFail_NotDone_Raise_if(!done,"");
761   return myResult;
762 }
763
764 // ============================================================================
765 // Method  : Error
766 // Purpose : Return the TranslateEdgeLoop error
767 // ============================================================================
768
769 StepToTopoDS_TranslateEdgeLoopError StepToTopoDS_TranslateEdgeLoop::Error() const
770 {
771   return myError;
772 }
773