0026457: Failed build with OCCT_DEBUG enabled
[occt.git] / src / TopoDSToStep / TopoDSToStep_MakeStepFace.cxx
1 // Created on: 1994-11-30
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1994-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 // Integration to ensure SCCS base integrity
18 //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp (toruses)
19 // abv 6 Jan 99: TR10: fix by PDN commented (temporarily) because CATIA do not read DEG_TORUSes
20 // rln 19.01.99: uncomment %30 pdn for integration into K4L
21 //szv#4 S4163
22 // abv 30.11.99: fix %30 pdn changed to produce SurfaceOfRevolution instead of DegenerateToroidalSurface
23
24 #include <Bnd_Box2d.hxx>
25 #include <BndLib_Add2dCurve.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepTools.hxx>
28 #include <Geom2d_BezierCurve.hxx>
29 #include <Geom2d_Curve.hxx>
30 #include <Geom2d_Hyperbola.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_Parabola.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <Geom2dAdaptor_Curve.hxx>
35 #include <Geom2dConvert.hxx>
36 #include <Geom_BSplineCurve.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_ConicalSurface.hxx>
39 #include <Geom_CylindricalSurface.hxx>
40 #include <Geom_ElementarySurface.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_SphericalSurface.hxx>
44 #include <Geom_Surface.hxx>
45 #include <Geom_SurfaceOfRevolution.hxx>
46 #include <Geom_ToroidalSurface.hxx>
47 #include <Geom_TrimmedCurve.hxx>
48 #include <GeomToStep_MakeCurve.hxx>
49 #include <GeomToStep_MakeSurface.hxx>
50 #include <Interface_Static.hxx>
51 #include <Precision.hxx>
52 #include <ShapeAlgo.hxx>
53 #include <ShapeAlgo_AlgoContainer.hxx>
54 #include <StdFail_NotDone.hxx>
55 #include <StepGeom_Curve.hxx>
56 #include <StepGeom_DegenerateToroidalSurface.hxx>
57 #include <StepGeom_GeometricRepresentationContextAndParametricRepresentationContext.hxx>
58 #include <StepGeom_HArray1OfPcurveOrSurface.hxx>
59 #include <StepGeom_Pcurve.hxx>
60 #include <StepGeom_PcurveOrSurface.hxx>
61 #include <StepGeom_SeamCurve.hxx>
62 #include <StepGeom_Surface.hxx>
63 #include <StepGeom_SurfaceCurve.hxx>
64 #include <StepGeom_ToroidalSurface.hxx>
65 #include <StepRepr_DefinitionalRepresentation.hxx>
66 #include <StepRepr_HArray1OfRepresentationItem.hxx>
67 #include <StepShape_AdvancedFace.hxx>
68 #include <StepShape_EdgeCurve.hxx>
69 #include <StepShape_FaceBound.hxx>
70 #include <StepShape_FaceOuterBound.hxx>
71 #include <StepShape_HArray1OfFaceBound.hxx>
72 #include <StepShape_Loop.hxx>
73 #include <StepShape_TopologicalRepresentationItem.hxx>
74 #include <TCollection_HAsciiString.hxx>
75 #include <TColStd_SequenceOfTransient.hxx>
76 #include <TopExp_Explorer.hxx>
77 #include <TopoDS.hxx>
78 #include <TopoDS_Face.hxx>
79 #include <TopoDS_Iterator.hxx>
80 #include <TopoDSToStep.hxx>
81 #include <TopoDSToStep_MakeStepFace.hxx>
82 #include <TopoDSToStep_MakeStepWire.hxx>
83 #include <TopoDSToStep_Tool.hxx>
84 #include <Transfer_FinderProcess.hxx>
85 #include <TransferBRep.hxx>
86 #include <TransferBRep_ShapeMapper.hxx>
87 #include <UnitsMethods.hxx>
88
89 // Processing of non-manifold topology (ssv; 10.11.2010)
90 // ----------------------------------------------------------------------------
91 // Constructors
92 // ----------------------------------------------------------------------------
93 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace()
94 {
95   done = Standard_False;
96 }
97
98 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace
99 (const TopoDS_Face& F,
100  TopoDSToStep_Tool& T,
101  const Handle(Transfer_FinderProcess)& FP)
102 {
103   done = Standard_False;
104   Init(F, T, FP);
105 }
106
107 // ----------------------------------------------------------------------------
108 // Method  : Init
109 // Purpose :
110 // ----------------------------------------------------------------------------
111
112 void TopoDSToStep_MakeStepFace::Init(const TopoDS_Face& aFace, 
113                                      TopoDSToStep_Tool& aTool,
114                                      const Handle(Transfer_FinderProcess)& FP)
115 {
116   // --------------------------------------------------------------
117   // the face is given with its relative orientation (in the Shell)
118   // --------------------------------------------------------------
119
120   //szv#4:S4163:12Mar99 SGI warns
121   TopoDS_Shape sh = aFace.Oriented(TopAbs_FORWARD);
122   const TopoDS_Face ForwardFace = TopoDS::Face(sh);
123   aTool.SetCurrentFace(ForwardFace);
124   Handle(TransferBRep_ShapeMapper) errShape =
125     new TransferBRep_ShapeMapper(aFace);  // on ne sait jamais
126
127   // [BEGIN] Processing non-manifold topology (another approach) (ssv; 10.11.2010)
128   Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold");
129   if (isNMMode) {
130     Handle(StepShape_AdvancedFace) anAF;
131     Handle(TransferBRep_ShapeMapper) aSTEPMapper = TransferBRep::ShapeMapper(FP, aFace);
132     if ( FP->FindTypedTransient(aSTEPMapper, STANDARD_TYPE(StepShape_AdvancedFace), anAF) ) {
133       // Non-manifold topology detected
134       Handle(StepShape_AdvancedFace) aLinkingAF = new StepShape_AdvancedFace;
135       aLinkingAF->Init( anAF->Name(), 
136                         anAF->Bounds(),
137                         anAF->FaceGeometry(),
138                        !anAF->SameSense() );
139
140       myError  = TopoDSToStep_FaceDone;
141       myResult = aLinkingAF;
142       done     = Standard_True;
143       return;
144     }
145   }
146   // [END] Processing non-manifold topology (ssv; 10.11.2010)
147
148   if (aTool.IsBound(aFace)) {
149     myError  = TopoDSToStep_FaceDone;
150     done     = Standard_True;
151     myResult = aTool.Find(aFace);
152     return;
153   }
154   
155   TopoDS_Iterator  It;
156   Standard_Integer i;
157   
158   //BRepAdaptor_Surface SA = BRepAdaptor_Surface(ForwardFace);  
159
160   if (aFace.Orientation() == TopAbs_INTERNAL ||
161       aFace.Orientation() == TopAbs_EXTERNAL ) {
162     FP->AddWarning(errShape, " Face from Non Manifold Topology");
163     myError = TopoDSToStep_NonManifoldFace;
164     done    = Standard_False;
165     return;
166   }
167   
168   // ------------------    
169   // Get the Outer Wire
170   // ------------------
171   
172   const TopoDS_Wire theOuterWire = BRepTools::OuterWire(ForwardFace);
173   
174   if (theOuterWire.IsNull()) {
175 #ifdef OCCT_DEBUG
176     cout<< "Warning : Face without wire not mapped";
177 #endif
178     FP->AddWarning(errShape, " Face without wire not mapped");
179     myError = TopoDSToStep_InfiniteFace;
180     done    = Standard_False;
181     return;
182   }
183   
184   // -----------------
185   // Translate Surface
186   // -----------------
187   
188   Handle(Geom_Surface) Su = BRep_Tool::Surface(ForwardFace);
189 //  CKY  23 SEP 1996 : une FACE de Step n a pas droit a RECTANGULAR_TRIMMED...
190 //  Il faut donc d abord "demonter" la RectangularTrimmedSurface pour
191 //  passer la Surface de base
192   Handle(Geom_RectangularTrimmedSurface) aRTS =
193     Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
194   if (!aRTS.IsNull()) Su = aRTS->BasisSurface();
195
196   //Handle(Geom_Surface) Su = SA.Surface().Surface();
197   //Su = Handle(Geom_Surface)::DownCast(Su->Copy());
198   //gp_Trsf Tr1 = SA.Trsf();
199   //Su->Transform(Tr1);
200
201 // Surfaces with indirect Axes are already reversed
202 // (see TopoDSToStepAct_Actor)
203   //Standard_Boolean ReverseSurfaceOrientation = Standard_False; //szv#4:S4163:12Mar99 unused
204   aTool.SetSurfaceReversed(Standard_False);
205
206   GeomToStep_MakeSurface MkSurface(Su);
207   Handle(StepGeom_Surface) Spms =  MkSurface.Value();
208
209   //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp: 
210   // toruses with major_radius < minor are re-coded as degenerate
211   // rln 19.01.99: uncomment %30 pdn for integration into K4L
212   if(Spms->IsKind(STANDARD_TYPE(StepGeom_ToroidalSurface))) {
213     Handle(StepGeom_ToroidalSurface) trsf = Handle(StepGeom_ToroidalSurface)::DownCast(Spms);
214     Standard_Real R = trsf->MajorRadius();
215     Standard_Real r = trsf->MinorRadius();
216     if ( R < r ) { // if torus is degenerate, make revolution instead
217       Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(Su);
218       gp_Ax3 Ax3 = TS->Position();
219       gp_Pnt pos = Ax3.Location();
220       gp_Dir dir = Ax3.Direction();
221       gp_Dir X   = Ax3.XDirection();
222       
223       // create basis curve
224       Standard_Real UF, VF, UL, VL;
225       ShapeAlgo::AlgoContainer()->GetFaceUVBounds ( aFace, UF, UL, VF, VL );
226       gp_Ax2 Ax2 ( pos.XYZ() + X.XYZ() * TS->MajorRadius(), X ^ dir, X );
227       Handle(Geom_Curve) BasisCurve = new Geom_Circle ( Ax2, TS->MinorRadius() );
228       
229       // convert basis curve to bspline in order to avoid self-intersecting
230       // surface of revolution (necessary e.g. for CATIA)
231       if ( VL - VF - 2 * M_PI < -Precision::PConfusion() ) 
232         BasisCurve = ShapeAlgo::AlgoContainer()->ConvertCurveToBSpline (BasisCurve, VF, VL, Precision::Approximation(),
233                                                                         GeomAbs_C1, 100, 9);
234 //      BasisCurve = new Geom_TrimmedCurve ( BasisCurve, VF, VL );
235
236       // create surface of revolution
237       gp_Ax1 Axis = Ax3.Axis();
238       if ( ! Ax3.Direct() ) Axis.Reverse();
239       Handle(Geom_SurfaceOfRevolution) Rev = new Geom_SurfaceOfRevolution ( BasisCurve, Axis );
240       
241       // and translate it
242       GeomToStep_MakeSurface MkRev(Rev);
243       Spms = MkRev.Value();
244     }
245   }
246
247   // ----------------
248   // Translates Wires
249   // ----------------
250   
251   Handle(StepShape_Loop)                          Loop;
252   Handle(StepShape_FaceBound)                     FaceBound;
253
254   TopoDSToStep_MakeStepWire MkWire;
255   TColStd_SequenceOfTransient mySeq;
256
257   // Initialize the Wire Explorer with the forward face
258
259   TopExp_Explorer WireExp;
260   for (WireExp.Init(ForwardFace,TopAbs_WIRE);WireExp.More();WireExp.Next()) {
261
262     const TopoDS_Wire CurrentWire = TopoDS::Wire(WireExp.Current());
263     if (!CurrentWire.IsNull()) {
264
265       //szv#4:S4163:12Mar99 SGI warns
266       //TopoDS_Shape ssh = CurrentWire.Oriented(TopAbs_FORWARD);
267       //const TopoDS_Wire ForwardWire = TopoDS::Wire(ssh);
268
269       //MkWire.Init(ForwardWire, aTool, FP);
270       MkWire.Init(CurrentWire, aTool, FP);
271       if (MkWire.IsDone()) Loop = Handle(StepShape_Loop)::DownCast(MkWire.Value());
272       else {
273 #ifdef OCCT_DEBUG
274         cout << TopoDSToStep::DecodeWireError(MkWire.Error())->String() << endl;
275 #endif
276         FP->AddWarning(errShape, " a Wire not mapped");
277         continue;
278       }
279     }
280
281     //if (theOuterWire.IsEqual(CurrentWire))
282     //FaceBound = new StepShape_FaceOuterBound();
283     //else
284     FaceBound = new StepShape_FaceBound();
285
286     // ----------------------------------------------------
287     // When the geometric normal of a Surface is reversed : 
288     //    - the wire topological orientation is reversed
289     // ----------------------------------------------------
290     // CAS.CADE face orientation :
291     // when a face is reversed in a shell, the orientation of the underlying
292     // topology is implicitly reversed. This is not the case in Step.
293     // If face orientation is Reversed => the underlying (Step mapped) wire
294     // are explicitly reversed
295
296     Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
297
298     // Ajoute le 30 Juin pour TEST
299     // Il convient de reprendre a la base ce probleme d'orientation
300     // et notamment la politique d`exploration du Shape (on explore
301     // toujours les sous-shapes d'un shape de maniere FORWARD !
302     // la modif (on ajoute : si context faceted ... sinon) est a verifier
303     // aupres des autres editeurs de CFAO de la Round Table.
304
305     if (!aTool.Faceted() && aFace.Orientation() == TopAbs_REVERSED)
306       FaceBound->Init(aName, Loop,
307                       (CurrentWire.Orientation() == TopAbs_REVERSED));
308     else
309       FaceBound->Init(aName, Loop,
310                       (CurrentWire.Orientation() == TopAbs_FORWARD));
311
312     mySeq.Append(FaceBound);
313   }
314   
315   // ----------------------------------------
316   // Translate the Edge 2D Geometry (pcurves)
317   // ----------------------------------------
318   
319   if ( ! aTool.Faceted() && aTool.PCurveMode() != 0 ) {
320     
321     TopExp_Explorer Ex(ForwardFace, TopAbs_EDGE);
322
323     // ------------------------------------------------
324     // Exploration of all the Edges in the current face
325     // ------------------------------------------------
326     
327     for (;Ex.More(); Ex.Next()) {
328       TopoDS_Edge E = TopoDS::Edge(Ex.Current());
329       Standard_Real cf, cl;
330       Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, ForwardFace, cf, cl);
331
332       //CA = BRepAdaptor_Curve(E, ForwardFace);
333       //GeomAbs_CurveType typCOnS = CA.CurveOnSurface().GetCurve().GetType();
334       
335       //if (typCOnS == GeomAbs_Line && BRep_Tool::Degenerated(E) ) {
336       if ( //:abv 26Jan00, CAX-IF TRJ3: C2d->IsKind(STANDARD_TYPE(Geom2d_Line)) && 
337            BRep_Tool::Degenerated(E)) {
338         // The edge 2D Geometry degenerates in 3D
339         // The edge 2D geometry is not mapped onto any Step entity
340         // (ProStep agreement)
341         continue;
342       }
343       else { // Copy the Curve2d which might be changed
344         //C2d = CA.CurveOnSurface().GetCurve().Curve();
345         //C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
346         C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
347       }
348       
349       // for writing VERTEX_LOOP
350       if(!aTool.IsBound(E)) continue;      
351       Handle(StepGeom_Curve) Cpms = 
352         Handle(StepShape_EdgeCurve)::DownCast(aTool.Find(E))->EdgeGeometry();
353       if ( Cpms.IsNull() ) continue;
354       
355       if ( !C2d.IsNull() && aTool.IsBound(E) ) {
356         if (C2d->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)) || 
357             C2d->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
358           if(Su->IsKind(STANDARD_TYPE(Geom_SphericalSurface))  ||
359              Su->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
360              Su->IsKind(STANDARD_TYPE(Geom_ConicalSurface)) ||
361              Su->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
362             C2d = new Geom2d_TrimmedCurve(C2d, cf, cl, Standard_True);
363           }
364         }
365         
366         if ((C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ||
367             (C2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))) {
368           C2d = Geom2dConvert::CurveToBSplineCurve(C2d);
369         }       
370         
371         // if the Surface is a RectangularTrimmedSurface, 
372         // use the BasisSurface.
373 //   CKY  23 SEP 1996 : on reste en Radian car on code des Radians
374 //    sauf que ca ne marche pas bien ...
375         Handle(Geom2d_Curve) C2dMapped;
376         if (Su->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
377           Handle(Geom_RectangularTrimmedSurface) alocalRTS =
378             Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
379           C2dMapped = UnitsMethods::RadianToDegree(C2d, alocalRTS->BasisSurface());
380         }
381         else {
382           C2dMapped = UnitsMethods::RadianToDegree(C2d, Su);
383         }
384 //
385 //      C2dMapped = C2d;  // cky : en remplacement de ce qui precede
386         GeomToStep_MakeCurve MkCurve(C2dMapped);
387         
388         // --------------------
389         // Translate the Pcurve
390         // --------------------
391         
392         Handle(StepGeom_Pcurve) Pc = new StepGeom_Pcurve;
393         Handle(StepRepr_DefinitionalRepresentation) DRI = 
394           new StepRepr_DefinitionalRepresentation;
395         Handle(StepRepr_HArray1OfRepresentationItem) aItems = 
396           new StepRepr_HArray1OfRepresentationItem(1,1);
397         aItems->SetValue(1,MkCurve.Value());
398         Handle(StepGeom_GeometricRepresentationContextAndParametricRepresentationContext) aContext =
399           new StepGeom_GeometricRepresentationContextAndParametricRepresentationContext();
400         Handle(TCollection_HAsciiString) aContextIdentifier =
401           new TCollection_HAsciiString("2D SPACE");
402         Handle(TCollection_HAsciiString) aContextType = 
403           new TCollection_HAsciiString("");
404         Standard_Integer aCoordSpaceDim = 2;
405         aContext->Init(aContextIdentifier, aContextType, aCoordSpaceDim);
406
407         Handle(TCollection_HAsciiString) aName = 
408           new TCollection_HAsciiString("");
409
410         DRI->Init(aName, aItems, aContext);
411         Pc->Init(aName, Spms, DRI );
412         Handle(StepGeom_SurfaceCurve) C1pms = 
413           Handle(StepGeom_SurfaceCurve)::DownCast(Cpms);
414         Handle(StepGeom_HArray1OfPcurveOrSurface) aGeom = C1pms->AssociatedGeometry();
415         if (aGeom.IsNull()) aGeom = new StepGeom_HArray1OfPcurveOrSurface(1,2);
416         StepGeom_PcurveOrSurface PcOrSur;
417         PcOrSur.SetValue(Pc);
418         if ((aGeom->Value(1)).IsNull()) {
419           aGeom->SetValue(1, PcOrSur);
420           if (C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) {
421             aGeom->SetValue(2,PcOrSur);    // c est au moins ca
422           }
423         }
424         else  if (aGeom->Value(2).IsNull() || //) {
425                   C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) { //:a8 abv 13 Feb 98: allow seam to have two different pcurves
426           aGeom->SetValue(2, PcOrSur);
427         }
428         C1pms->SetAssociatedGeometry(aGeom);
429       }
430     }
431   }
432   
433   // ------------------
434   // Translate the Face
435   // ------------------
436   
437   Standard_Integer nbWires = mySeq.Length();
438   if ( nbWires ) {
439     Handle(StepShape_HArray1OfFaceBound) aBounds =
440       new StepShape_HArray1OfFaceBound(1,nbWires);
441     for ( i=1; i<=nbWires; i++ ) {
442       aBounds->SetValue(i, Handle(StepShape_FaceBound)::DownCast(mySeq.Value(i)));
443     }
444     Handle(StepShape_AdvancedFace) Fpms = new StepShape_AdvancedFace;
445
446     // ---------------------------------------------------------------
447     // The underlying surface has always a direct axis (see above)
448     // ---------------------------------------------------------------
449
450     Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
451
452     Fpms->Init(aName, aBounds, Spms, aFace.Orientation() == TopAbs_FORWARD);
453
454     aTool.Bind(aFace, Fpms);
455     myError  = TopoDSToStep_FaceDone;
456     myResult = Fpms;
457     done     = Standard_True;
458   }
459   else {
460
461     // ----------------------------
462     // MakeFace Face Error Handling
463     // ----------------------------
464
465     FP->AddWarning(errShape, " No Wires of this Face were mapped");
466     myError = TopoDSToStep_NoWireMapped;
467     done    = Standard_False;
468   }
469 }
470
471   
472 // ----------------------------------------------------------------------------
473 // Method  : Value
474 // Purpose :
475 // ----------------------------------------------------------------------------
476
477 const Handle(StepShape_TopologicalRepresentationItem)& TopoDSToStep_MakeStepFace::Value() const 
478 {
479   StdFail_NotDone_Raise_if(!done,"");
480   return myResult;
481 }
482
483 // ----------------------------------------------------------------------------
484 // Method  : Error
485 // Purpose :
486 // ----------------------------------------------------------------------------
487
488 TopoDSToStep_MakeFaceError TopoDSToStep_MakeStepFace::Error() const 
489 {
490   return myError;
491 }