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