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