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