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