0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / StepToTopoDS / StepToTopoDS_TranslateEdge.cxx
1 // Created on: 1995-01-03
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 //:o0 abv 16.02.99: POLYLINE allowed as 3d curve of edge
18 //gka,abv 05.04.99: S4136: improving tolerance management, eliminate BRepAPI::Precision()
19
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepLib.hxx>
23 #include <BRepLib_MakeEdge.hxx>
24 #include <GCPnts_AbscissaPoint.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <Geom_CartesianPoint.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom_Surface.hxx>
30 #include <GeomAbs_Shape.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <gp_Dir.hxx>
33 #include <gp_Lin.hxx>
34 #include <gp_Vec.hxx>
35 #include <Precision.hxx>
36 #include <ShapeAnalysis_Curve.hxx>
37 #include <ShapeConstruct_Curve.hxx>
38 #include <StdFail_NotDone.hxx>
39 #include <StepGeom_CartesianPoint.hxx>
40 #include <StepGeom_Curve.hxx>
41 #include <StepGeom_Pcurve.hxx>
42 #include <StepGeom_Polyline.hxx>
43 #include <StepGeom_SurfaceCurve.hxx>
44 #include <StepRepr_DefinitionalRepresentation.hxx>
45 #include <StepShape_Edge.hxx>
46 #include <StepShape_EdgeCurve.hxx>
47 #include <StepShape_OrientedEdge.hxx>
48 #include <StepShape_Vertex.hxx>
49 #include <StepShape_VertexPoint.hxx>
50 #include <StepToGeom.hxx>
51 #include <StepToTopoDS.hxx>
52 #include <StepToTopoDS_GeometricTool.hxx>
53 #include <StepToTopoDS_NMTool.hxx>
54 #include <StepToTopoDS_Tool.hxx>
55 #include <StepToTopoDS_TranslateEdge.hxx>
56 #include <StepToTopoDS_TranslateVertex.hxx>
57 #include <TCollection_HAsciiString.hxx>
58 #include <TopoDS.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Shape.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <Transfer_TransientProcess.hxx>
63 #include <UnitsMethods.hxx>
64 #include <Standard_Failure.hxx>
65
66 //#include <StepGeom_Polyline.hxx>
67 //#include <TransferBRep.hxx>
68 //:d8
69 // Used in I-DEAS-like STP processing (ssv; 15.11.2010)
70 //#define DEBUG
71 // ============================================================================
72 // Method  : DecodeMakeEdgeError
73 // Purpose : 
74 // ============================================================================
75 static void DecodeMakeEdgeError(const BRepLib_MakeEdge&   ME,
76                                 const Handle(Standard_Transient)& orig,
77                                 const Handle(Geom_Curve)& myCurve,
78                                 const TopoDS_Vertex&      V1,
79                                 const TopoDS_Vertex&      V2,
80                                 const Standard_Real&      U1,
81                                 const Standard_Real&      U2,
82                                 StepToTopoDS_Tool&   aTool,
83                                 const Handle(StepShape_TopologicalRepresentationItem)& /*tobind*/)
84 {
85   (void)U1, (void)U2; // avoid compiler warning
86
87   Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
88
89 #ifdef OCCT_DEBUG
90   std::cout << "------------------------------------" << std::endl;
91   std::cout << "MakeEdge Error  : " << ME.Error()<<" - ";
92 #endif
93   switch(ME.Error())
94     {
95     case (BRepLib_EdgeDone): return;
96     case (BRepLib_PointProjectionFailed):
97       TP->AddFail(orig," Point Projection failed");
98       break;
99     case (BRepLib_ParameterOutOfRange):
100       TP->AddFail(orig," Parameter Out Of Range");
101       break;
102     case (BRepLib_DifferentPointsOnClosedCurve):
103       TP->AddFail(orig," Different Points on Closed Curve");
104       break;
105     case (BRepLib_PointWithInfiniteParameter):
106       TP->AddFail(orig," Point with infinite Parameter");
107       break;
108     case (BRepLib_DifferentsPointAndParameter):
109       if (!ShapeConstruct_Curve().AdjustCurve
110           (myCurve,BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2),Standard_True,Standard_True))
111         TP->AddFail(orig," Different Points and Parameters");
112        else TP->AddWarning(orig,"Different Points and Parameters, adjusted");
113       break;
114     case (BRepLib_LineThroughIdenticPoints):
115       TP->AddFail(orig," Line through identic Points");
116       break;
117     }
118 #ifdef OCCT_DEBUG
119   std::cout << "Original Type   : " << orig->DynamicType() << std::endl;
120   std::cout << "3D Curve Type   : " << myCurve->DynamicType() << std::endl;
121   std::cout << "First Parameter : " << U1 << std::endl;
122   gp_Pnt p1 = BRep_Tool::Pnt(V1);
123 //  std::cout << "First Point     : ";
124   std::cout << "First Vertex    : "<<p1.X()<<"  "<<p1.Y()<<"  "<<p1.Z()<<"  ";
125   std::cout << "Distance Point - Vertex : ";
126   Standard_Real d1 = p1.Distance(myCurve->Value(U1)); 
127   std::cout << d1 << std::endl;
128   std::cout << "Last  Parameter : " << U2 << std::endl;
129   gp_Pnt p2 = BRep_Tool::Pnt(V2);
130 //  std::cout << "Last  Point     : ";
131   std::cout << "Last  Vertex    : "<<p2.X()<<"  "<<p2.Y()<<"  "<<p2.Z()<<"  ";
132   std::cout << "Distance Point - Vertex : ";
133   Standard_Real d2 = BRep_Tool::Pnt(V2).Distance(myCurve->Value(U2)); 
134   std::cout << d2 << std::endl;
135 #endif
136 }
137
138 // ============================================================================
139 // Method  : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge
140 // Purpose : Empty Constructor
141 // ============================================================================
142
143 static Handle(Geom_Curve) MakeCurve
144   (const Handle(StepGeom_Curve)& C1, const Handle(Transfer_TransientProcess) TP)
145 {
146   Handle(Geom_Curve) C2 = Handle(Geom_Curve)::DownCast (TP->FindTransient(C1));
147   if (!C2.IsNull()) return C2;
148   C2 = StepToGeom::MakeCurve (C1);
149   if (! C2.IsNull())
150     TP->BindTransient (C1,C2);
151   return C2;
152 }
153
154 static TopoDS_Edge  MakeEdge
155   (const Handle(Geom_Curve)& C3D,
156    const TopoDS_Vertex& V1, const TopoDS_Vertex& V2,
157    const Standard_Real U1, const Standard_Real U2)
158 {
159   BRep_Builder B;
160   TopoDS_Edge E;
161   B.MakeEdge (E,C3D,Precision::Confusion());
162   B.Add (E,V1);  B.Add (E,V2);
163   B.UpdateVertex(V1, U1, E, 0.);
164   B.UpdateVertex(V2, U2, E, 0.);
165   return E;
166 }
167
168 // ============================================================================
169 // Method  : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
170 // Purpose : 
171 // ============================================================================
172
173 StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
174 : myError(StepToTopoDS_TranslateEdgeOther)
175 {
176   done = Standard_False;
177 }
178
179 // ============================================================================
180 // Method  : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
181 // Purpose : Constructor with an Edge and a Tool
182 // ============================================================================
183
184 StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge(const Handle(StepShape_Edge)& E, 
185                                                        StepToTopoDS_Tool& T, 
186                                                        StepToTopoDS_NMTool& NMTool)
187 {
188   Init(E, T, NMTool);
189 }
190
191 // ============================================================================
192 // Method  : Init
193 // Purpose : Init with an Edge and a Tool.
194 //           This method builds an Edge With 2 Vertices and 2 Parameters.
195 //           The Edge is always build like FORWARD (BRepLib_MakeEdge)
196 // ============================================================================
197
198 void StepToTopoDS_TranslateEdge::Init(const Handle(StepShape_Edge)& aEdge, 
199                                       StepToTopoDS_Tool& aTool,
200                                       StepToTopoDS_NMTool& NMTool)
201 {
202   Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
203
204   Handle(StepShape_OrientedEdge) OE = 
205     Handle(StepShape_OrientedEdge)::DownCast(aEdge);
206   Handle(StepShape_Edge) wEdge = aEdge;
207   if ( ! OE.IsNull() ) wEdge = OE->EdgeElement();
208   Handle(StepShape_EdgeCurve) EC = Handle(StepShape_EdgeCurve)::DownCast(wEdge);
209   
210   if (aTool.IsBound(EC)) {
211     myResult = aTool.Find(EC);
212     if (BRep_Tool::Degenerated(TopoDS::Edge(myResult))) {
213       TP->AddWarning(EC,"Degenerated Edge in several faces : transferred for each face");
214     }
215     else {
216       myError  = StepToTopoDS_TranslateEdgeDone;
217       done     = Standard_True;
218 //:S4136      B.SameRange(TopoDS::Edge(myResult), Standard_False);    //:a5 abv 11 Feb 98
219 //:S4136      B.SameParameter(TopoDS::Edge(myResult), Standard_False);//:a5
220       return;
221     }
222   }
223
224   // [BEGIN] Proceed with non-manifold cases (ssv; 12.11.2010)
225   if ( NMTool.IsActive() && NMTool.IsBound(EC) ) {
226     TopoDS_Shape existingShape = NMTool.Find(EC);
227     // Reverse shape's orientation if needed
228     if ( !OE->Orientation() )
229       existingShape.Reverse();
230     myResult = existingShape;
231     myError = StepToTopoDS_TranslateEdgeDone;
232     done = Standard_True;
233     return;
234   }
235   // [END] Proceed with non-manifold cases (ssv; 12.11.2010)
236
237   // [BEGIN] Proceed with I-DEAS-like STP (ssv; 15.11.2010)
238   const Handle(TCollection_HAsciiString) anECName = EC->Name();
239   if ( NMTool.IsIDEASCase() && !anECName.IsNull() && !anECName->IsEmpty() &&
240        NMTool.IsBound(anECName->String()) ) {
241     TopoDS_Shape existingShape = NMTool.Find(anECName->String());
242     // Reverse shape's orientation if needed
243     if ( !OE->Orientation() )
244       existingShape.Reverse();
245     // Register Edge for final processing (I-DEAS case)
246     NMTool.RegisterNMEdge(existingShape);
247     myResult = existingShape;
248     myError = StepToTopoDS_TranslateEdgeDone;
249     done = Standard_True;
250     return;
251   }
252   // [END] Proceed with I-DEAS-like STP (ssv; 15.11.2010)
253
254   BRep_Builder B;
255
256   Handle(StepGeom_Curve) C = EC->EdgeGeometry();
257   if( C.IsNull())
258   {
259     TP->AddFail(EC," Geom Curve in EdgeCurve is equal to 0");
260     myError = StepToTopoDS_TranslateEdgeOther;
261     done = Standard_False;
262     return;
263   }
264   TopoDS_Edge E;
265   Handle(StepShape_Vertex) Vstart, Vend;
266
267   // -----------------------------------------------------------
268   // Extract the start and end Vertices corresponding to FORWARD
269   // (following the geometrical sense)
270   // -----------------------------------------------------------
271
272   Standard_Boolean EdgeCurveSameSense = EC->SameSense();
273   
274   if (EdgeCurveSameSense) {
275     Vstart = EC->EdgeStart();
276     Vend   = EC->EdgeEnd();
277   }
278   else {
279     Vend   = EC->EdgeStart();
280     Vstart = EC->EdgeEnd();
281   }
282
283   TopoDS_Vertex V1, V2;
284
285   StepToTopoDS_TranslateVertex myTranVertex1(Vstart, aTool, NMTool);
286   StepToTopoDS_TranslateVertex myTranVertex2(Vend, aTool, NMTool);
287
288   if (myTranVertex1.IsDone()) {
289     V1 = TopoDS::Vertex(myTranVertex1.Value());
290     V1.Orientation(TopAbs_FORWARD);
291   }
292   if (Vend == Vstart) {
293     V2 = V1;
294     V2.Orientation(TopAbs_REVERSED);
295   }
296   else if (myTranVertex2.IsDone()) {
297     V2 = TopoDS::Vertex(myTranVertex2.Value());
298     V2.Orientation(TopAbs_REVERSED);
299   }
300   done = Standard_True;
301   
302   // ----------------------------------------------------------
303   // --- The EdgeCurve Geometry is of StepGeom_Curve Type
304   // --- It can be : * a Pcurve : no 3D curve is constructed
305   // ---             * a Surface Curve, Intersection Curve
306   // ---               or a Seam Curve
307   // ---             * a 3D Curve
308   // ----------------------------------------------------------
309   
310   if ( C->IsKind(STANDARD_TYPE(StepGeom_Pcurve))) {
311     B.MakeEdge(E);
312 //:S4136    B.UpdateEdge (E,preci);
313     B.Add(E, V1);
314     B.Add(E, V2);
315   }
316   else if (C->IsKind(STANDARD_TYPE(StepGeom_SurfaceCurve)) ) {
317     // For SeamCurve and IntersectionCurve types
318     // --- The Edge Geometry is a Surface Curve ---
319     // ---     (3d + 2 Pcurve Or Surface)       ---
320     Handle(StepGeom_SurfaceCurve) Sc =
321       Handle(StepGeom_SurfaceCurve)::DownCast(C);
322     Handle(StepGeom_Curve) C1 = Sc->Curve3d();
323       MakeFromCurve3D (C1,EC,Vend,Precision(), E,V1,V2 , aTool);
324   }
325   else {
326     // --- The Edge Geometry is a Single 3d Curve ---
327     MakeFromCurve3D (C,EC,Vend,Precision(), E,V1,V2 , aTool);
328   }
329   // Force set flags SameRange and SameParameter to Standard_False
330   if (done) {
331 //:S4136    B.SameRange(E, Standard_False);
332 //:S4136    B.SameParameter(E, Standard_False);
333     aTool.Bind(EC,E);
334
335     // Bind Edge in NM tool (ssv; 15.11.2010)
336     if ( NMTool.IsActive() ) {
337       NMTool.Bind(EC, E);
338       if ( NMTool.IsIDEASCase() && !anECName.IsNull() && !anECName->IsEmpty() )
339         NMTool.Bind(anECName->String(), E);
340     }
341
342     myResult = E;
343     myError = StepToTopoDS_TranslateEdgeDone;
344   }
345 }
346
347
348 // ============================================================================
349 // Method  : MakeFromCurve3D
350 // Purpose : case of a Curve 3D (alone or in SurfaceCurve)
351 // ============================================================================
352
353 // auxiliary function
354 //:e6 abv 16 Apr 98: ProSTEP TR8, r0601_sy.stp, #14907
355 static void GetCartesianPoints ( const Handle(StepShape_EdgeCurve)& EC, 
356                                  gp_Pnt &P1, gp_Pnt &P2)
357 {
358   for ( Standard_Integer i=1; i<=2; i++ ) {
359     const Handle(StepShape_Vertex) V = ((i == 1) == EC->SameSense() ? EC->EdgeStart() : EC->EdgeEnd() );
360     const Handle(StepShape_VertexPoint) VP = Handle(StepShape_VertexPoint)::DownCast(V);
361     if ( VP.IsNull() ) continue;
362     const Handle(StepGeom_CartesianPoint) P = Handle(StepGeom_CartesianPoint)::DownCast(VP->VertexGeometry());
363     Handle(Geom_CartesianPoint) CP = StepToGeom::MakeCartesianPoint (P);
364     ( i==1 ? P1 : P2 ) = CP->Pnt();
365   }
366 }
367
368 // ============================================================================
369 // Method  : StepToTopoDS_TranslateEdge::MakeFromCurve3D()
370 // Purpose : 
371 // ============================================================================
372
373 void  StepToTopoDS_TranslateEdge::MakeFromCurve3D
374   (const Handle(StepGeom_Curve)& C3D, const Handle(StepShape_EdgeCurve)& EC,
375    const Handle(StepShape_Vertex)&  Vend,
376    const Standard_Real preci, TopoDS_Edge& E,
377    TopoDS_Vertex& V1, TopoDS_Vertex& V2,
378    StepToTopoDS_Tool&   aTool)
379 {
380   Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
381   Handle(Geom_Curve) C1 = MakeCurve(C3D,TP);
382   if (C1.IsNull()) {
383     TP->AddFail(C3D," Make Geom_Curve (3D) failed");
384     myError = StepToTopoDS_TranslateEdgeOther;
385     done = Standard_False;
386     return;
387   }
388     // -- Statistics -- -> No Warning message
389   aTool.AddContinuity (C1);
390   BRep_Builder B;
391   Standard_Real temp1,temp2, U1,U2;
392   gp_Pnt pproj;
393   gp_Pnt pv1 = BRep_Tool::Pnt(V1);
394   gp_Pnt pv2 = BRep_Tool::Pnt(V2);
395
396   //:e6 abv
397   gp_Pnt pnt1 = pv1, pnt2 = pv2;
398   if ( V1.IsSame ( V2 ) ) GetCartesianPoints ( EC, pnt1, pnt2 );
399   ShapeAnalysis_Curve sac;
400   temp1 = sac.Project (C1,pnt1,preci,pproj,U1,Standard_False);
401   temp2 = sac.Project (C1,pnt2,preci,pproj,U2,Standard_False);
402
403   if (!StepToTopoDS_GeometricTool::UpdateParam3d(C1, U1, U2, preci))
404     TP->AddWarning(C3D,"Update of 3D-Parameters has failed");
405
406   //:d5: instead of AdjustCurve above which is incorrect if U1 and U2 are not ends
407   GeomAdaptor_Curve aCA(C1);
408   gp_Pnt pU1 = aCA.Value ( U1 ), pU2 = aCA.Value ( U2 );
409   temp1 = pU1.Distance ( pv1 );
410   temp2 = pU2.Distance ( pv2 );
411   if ( temp1 > preci || temp2 > preci ) {
412     TP->AddWarning (C3D,"Poor result from projection vertex / curve 3d");
413   }
414   B.UpdateVertex ( V1, 1.000001*temp1 ); //:h6 abv 14 Jul 98: PRO8845 #2746: *=1.0001
415   B.UpdateVertex ( V2, 1.000001*temp2 ); //:h6
416   
417   BRepLib_MakeEdge ME(C1, V1, V2, U1, U2);
418   if (ME.IsDone()) {
419     E = ME.Edge();
420     B.Range ( E, U1, U2 ); // abv 14 Mar 00: trj3_pm1-ug.stp #91739, edge 2
421   }
422   else {
423     if (ME.Error() == BRepLib_DifferentPointsOnClosedCurve) {
424       // The Edge could be closed and trimmed by 2 Different vertices
425       if (C1->IsClosed()) {
426         // Attention : topology updating
427         aTool.Bind (Vend,V1);
428         TopoDS_Shape aLocalShape = V1.Reversed();
429         V2 = TopoDS::Vertex(aLocalShape);
430         ME.Init(C1, V1, V2, U1, U2);
431         if (ME.IsDone()) {
432           TP->AddWarning(EC, "Wrong topology corrected : Closed Edge with TWO different Vertices");
433           E = ME.Edge();
434         }
435         else {
436           DecodeMakeEdgeError(ME, C3D, C1, V1, V2, U1, U2, aTool, EC);
437           E = MakeEdge (C1,V1,V2,U1,U2);
438           myError = StepToTopoDS_TranslateEdgeDone;
439           done = Standard_True;
440           //            return;               
441         }
442       }
443       else {
444         // Then, this is should be coded as degenerated
445         // To be performed later !!!
446         myError = StepToTopoDS_TranslateEdgeDone;
447         //  Bon, on la fait cette petite edge, mais faudra repasser
448         //  pour l enlever ET FUSIONNER LES VERTEX, pour tout le shell !
449         //  courbe trop petite pour etre mise -> fait planter
450         done = Standard_True;
451         if (!V1.IsSame(V2)) {
452           TP->AddFail(EC, "This edge has null arc length");
453           gp_Pnt P1 = BRep_Tool::Pnt(V1);
454           gp_Pnt P2 = BRep_Tool::Pnt(V2);
455           gp_Vec avec (P1,P2);  gp_Dir adir (avec);  gp_Lin alin (P1,adir);
456           C1 = new Geom_Line (alin);
457           U1 = 0.;  U2 = P1.Distance(P2);
458           E = MakeEdge (C1,V1,V2,U1,U2);//,preci
459         } 
460         else {
461           TP->AddFail(EC,"NULL EDGE, SKIPPED");
462           myResult.Nullify();
463           return;         
464         }
465       }
466     }
467     else {
468       DecodeMakeEdgeError(ME, C3D, C1, V1, V2, U1, U2, aTool, EC);
469       E = MakeEdge (C1,V1,V2,U1,U2);
470       myError = StepToTopoDS_TranslateEdgeDone;
471       done = Standard_True;
472     }
473   }
474 }
475
476
477 // ============================================================================
478 // Method  : MakePCurve
479 // Purpose : Computes an individual pcurve (i.e. curve 2d)
480 // ============================================================================
481 Handle(Geom2d_Curve)  StepToTopoDS_TranslateEdge::MakePCurve
482   (const Handle(StepGeom_Pcurve)& PCU, const Handle(Geom_Surface)& ConvSurf) const
483 {
484   Handle(Geom2d_Curve) C2d;
485   const Handle(StepRepr_DefinitionalRepresentation) DRI = PCU->ReferenceToCurve();
486   if( DRI.IsNull()) return C2d;
487   const Handle(StepGeom_Curve) StepCurve = Handle(StepGeom_Curve)::DownCast(DRI->ItemsValue(1));
488   try
489   {
490     C2d = StepToGeom::MakeCurve2d (StepCurve);
491     if (! C2d.IsNull()) {
492     // -- if the surface is a RectangularTrimmedSurface, 
493     // -- send the BasisSurface.
494      C2d = UnitsMethods::DegreeToRadian(C2d, ConvSurf);
495     }
496     
497   }
498   catch(Standard_Failure const&)
499   {
500     return C2d;
501   }
502   return C2d;
503 }
504
505
506 // ============================================================================
507 // Method  : Value
508 // Purpose : Returns the mapped edge
509 // ============================================================================
510
511 const TopoDS_Shape& StepToTopoDS_TranslateEdge::Value() const 
512 {
513   StdFail_NotDone_Raise_if (!done, "StepToTopoDS_TranslateEdge::Value() - no result");
514   return myResult;
515 }
516
517 // ============================================================================
518 // Method  : Error
519 // Purpose : Returns the error code
520 // ============================================================================
521
522 StepToTopoDS_TranslateEdgeError StepToTopoDS_TranslateEdge::Error() const
523 {
524   return myError;
525 }