0028427: Data Exchange - Update Reference Manual for STEP format
[occt.git] / src / StepToTopoDS / StepToTopoDS_TranslateFace.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 // pdn 30.11.98: fixes improved
18 // pdn 20.12.98: to keep pcurves
19 // pdn 28.12.98: PRO10366 shifting pcurve between two singularities
20 //:p4 abv, pdn 23.02.99: PRO9234 #15720: call BRepTools::Update() for faces
21 //:q7 abv 23.03.99: bm4_al_eye.stp #53710: remove pseudo-seams
22 //    rln 31.03.99 S4135: prohibit fixing intersection of non-adjacent edges (temporarily)
23 //#4  szv          S4163: optimization
24 //%19 pdn 17.04.99 using ShapeFix_Wire::FixEdgeCurves instead of ShapeFix_PCurves
25 //    smh 31.01.01 Bad data in file : case of vertex loop on plane face
26 // sln 01.10.2001 BUC61003. StepToTopoDS_TranslateFace::Init function is corrected (verifying  Handle(...).IsNull() is added)
27
28 #include <BRep_Builder.hxx>
29 #include <BRep_TEdge.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRep_TVertex.hxx>
32 #include <BRepBuilderAPI_MakeFace.hxx>
33 #include <BRepTools.hxx>
34 #include <Geom2d_Curve.hxx>
35 #include <Geom_BoundedSurface.hxx>
36 #include <Geom_BSplineSurface.hxx>
37 #include <Geom_Plane.hxx>
38 #include <Geom_SphericalSurface.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom_ToroidalSurface.hxx>
41 #include <GeomAbs_Shape.hxx>
42 #include <GeomAdaptor_HSurface.hxx>
43 #include <GeomAdaptor_Surface.hxx>
44 #include <Precision.hxx>
45 #include <ShapeAlgo.hxx>
46 #include <ShapeAlgo_AlgoContainer.hxx>
47 #include <StdFail_NotDone.hxx>
48 #include <StepGeom_BSplineSurface.hxx>
49 #include <StepGeom_BSplineSurfaceForm.hxx>
50 #include <StepGeom_OffsetSurface.hxx>
51 #include <StepGeom_Surface.hxx>
52 #include <StepShape_Edge.hxx>
53 #include <StepShape_EdgeCurve.hxx>
54 #include <StepShape_EdgeLoop.hxx>
55 #include <StepShape_FaceBound.hxx>
56 #include <StepShape_FaceOuterBound.hxx>
57 #include <StepShape_FaceSurface.hxx>
58 #include <StepShape_OrientedEdge.hxx>
59 #include <StepShape_PolyLoop.hxx>
60 #include <StepShape_VertexLoop.hxx>
61 #include <StepToGeom.hxx>
62 #include <StepToTopoDS.hxx>
63 #include <StepToTopoDS_NMTool.hxx>
64 #include <StepToTopoDS_Tool.hxx>
65 #include <StepToTopoDS_TranslateEdgeLoop.hxx>
66 #include <StepToTopoDS_TranslateFace.hxx>
67 #include <StepToTopoDS_TranslatePolyLoop.hxx>
68 #include <StepToTopoDS_TranslateVertexLoop.hxx>
69 #include <TCollection_HAsciiString.hxx>
70 #include <TopExp.hxx>
71 #include <TopExp_Explorer.hxx>
72 #include <TopoDS.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
75 #include <TopoDS_Iterator.hxx>
76 #include <TopoDS_Shape.hxx>
77 #include <TopoDS_Vertex.hxx>
78 #include <TopoDS_Wire.hxx>
79 #include <Transfer_TransientProcess.hxx>
80 #include <StepGeom_RectangularTrimmedSurface.hxx>
81 #include <StepGeom_ToroidalSurface.hxx>
82
83 //#3 rln 16/02/98
84 //#include <GeomAdaptor_Curve.hxx>
85 //#include <GeomAdaptor_CurveOnSurface.hxx>
86 //#3 rln 16/02/98
87 //rln 28/01/98
88 //rln 28/01/98
89 //  Provisoire, pour VertexLoop
90 //:d4
91 // To proceed with I-DEAS-like STP (ssv; 15.11.2010)
92 //#define DEBUG
93 // ============================================================================
94 // Method  : StepToTopoDS_TranslateFace::StepToTopoDS_TranslateFace
95 // Purpose : Empty Constructor
96 // ============================================================================
97 StepToTopoDS_TranslateFace::StepToTopoDS_TranslateFace()
98 {
99   done = Standard_False;
100 }
101
102 // ============================================================================
103 // Method  : StepToTopoDS_TranslateFace::StepToTopoDS_TranslateFace
104 // Purpose : Constructor with a FaceSurface and a Tool
105 // ============================================================================
106
107 StepToTopoDS_TranslateFace::StepToTopoDS_TranslateFace
108 (const Handle(StepShape_FaceSurface)& FS, StepToTopoDS_Tool& T, StepToTopoDS_NMTool& NMTool)
109 {
110   Init(FS, T, NMTool);
111 }
112
113 // ============================================================================
114 // Method  : Init
115 // Purpose : Init with a FaceSurface and a Tool
116 // ============================================================================
117
118 static inline Standard_Boolean isReversed(const Handle(StepGeom_Surface)& theStepSurf)
119 {
120   Handle(StepGeom_ToroidalSurface) aStepTorSur;
121   if(theStepSurf->IsKind(STANDARD_TYPE(StepGeom_RectangularTrimmedSurface)))
122     return isReversed(Handle(StepGeom_RectangularTrimmedSurface)::DownCast(theStepSurf)->BasisSurface());
123   
124   else
125     aStepTorSur = Handle(StepGeom_ToroidalSurface)::DownCast(theStepSurf);
126   
127   return (!aStepTorSur.IsNull() && aStepTorSur->MajorRadius() < 0 ? Standard_True : Standard_False);
128 }
129
130 // ============================================================================
131 // Method  : Init
132 // Purpose : Init with a FaceSurface and a Tool
133 // ============================================================================
134
135 void StepToTopoDS_TranslateFace::Init
136 (const Handle(StepShape_FaceSurface)& FS, StepToTopoDS_Tool& aTool, StepToTopoDS_NMTool& NMTool)
137 {
138   done = Standard_True;
139   if (aTool.IsBound(FS)) {
140     myResult = TopoDS::Face(aTool.Find(FS));
141     myError  = StepToTopoDS_TranslateFaceDone;
142     done     = Standard_True;
143     return;
144   }
145   
146   Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
147   
148   // ----------------------------------------------
149   // Map the Face Geometry and create a TopoDS_Face
150   // ----------------------------------------------
151   
152   Handle(StepGeom_Surface) StepSurf = FS->FaceGeometry();
153
154    // sln 01.10.2001 BUC61003. If corresponding entity was read with error StepSurface may be NULL. In this case we exit from function
155   if ( StepSurf.IsNull() ) {
156     TP->AddFail(StepSurf," Surface has not been created");
157     myError = StepToTopoDS_TranslateFaceOther;
158     done = Standard_False;
159     return;
160   }
161
162   // [BEGIN] Added to process non-manifold topology (ssv; 14.11.2010)
163   if ( NMTool.IsActive() && NMTool.IsBound(StepSurf) ) {
164     TopoDS_Shape existingShape = NMTool.Find(StepSurf);
165     // Reverse shape's orientation for the next shell
166     existingShape.Reverse();
167     myResult = existingShape;
168     myError  = StepToTopoDS_TranslateFaceDone;
169     done = Standard_True;
170     return;
171   }
172   // [END] Added to process non-manifold topology (ssv; 14.11.2010)
173
174   if (StepSurf->IsKind(STANDARD_TYPE(StepGeom_OffsetSurface))) //:d4 abv 12 Mar 98
175     TP->AddWarning(StepSurf," Type OffsetSurface is out of scope of AP 214");
176   Handle(Geom_Surface) GeomSurf = StepToGeom::MakeSurface (StepSurf);
177   if (GeomSurf.IsNull())
178   {
179     TP->AddFail(StepSurf," Surface has not been created");
180     myError = StepToTopoDS_TranslateFaceOther;
181     done = Standard_False;
182     return;
183   }
184   // pdn to force bsplsurf to be periodic
185   Handle(StepGeom_BSplineSurface) sgbss = Handle(StepGeom_BSplineSurface)::DownCast(StepSurf);
186   if (!sgbss.IsNull()) {
187     Handle(Geom_Surface) periodicSurf = ShapeAlgo::AlgoContainer()->ConvertToPeriodic(GeomSurf);
188     if (!periodicSurf.IsNull()) {
189       TP->AddWarning(StepSurf, "Surface forced to be periodic");
190       GeomSurf = periodicSurf;
191     }
192   }
193     
194   Standard_Boolean sameSenseFace = FS->SameSense();
195
196   //fix for bug 0026376 Solid Works wrote face based on toroidal surface having negative major radius
197   //seems that such case is interpreted  by "Solid Works" and "ProE" as face having reversed orientation.
198   Standard_Boolean sameSense = (isReversed(StepSurf) ? !sameSenseFace : sameSenseFace);
199   
200   // -- Statistics --
201   aTool.AddContinuity (GeomSurf);
202   
203   TopoDS_Face   F;
204   BRep_Builder B;
205   B.MakeFace ( F, GeomSurf, Precision::Confusion() );
206   
207   // ----------------------------------
208   // Iterate on each FaceBounds (Wires)
209   // ----------------------------------
210   
211   Handle(StepShape_FaceBound) FaceBound;
212   Handle(StepShape_Loop)      Loop;
213   
214   StepToTopoDS_TranslateVertexLoop myTranVL;
215   StepToTopoDS_TranslatePolyLoop   myTranPL;
216   StepToTopoDS_TranslateEdgeLoop   myTranEdgeLoop;
217   
218   Standard_Integer NbBnd = FS->NbBounds();
219
220   // --  Critere de couture simple (CKY, JAN97)
221   // surface periodique (typiquement un cylindre)
222   // 2 face bounds, chacun avec un edge loop d une seule edge
223   //  cette edge est fermee, c-a-d vtx-deb = vtx-fin (pour les deux edges)
224   // est-ce suffisant (verifier que ce sont deux outer-bounds ... ?? comment ?)
225   // Alors on peut dire : face a deux bords dont la couture manque
226   // La couture est entre les deux vertex
227
228   for (Standard_Integer i = 1; i <= NbBnd; i ++) {
229
230 #ifdef OCCT_DEBUG
231     cout << "    Processing Wire : " << i << endl;
232 #endif    
233     FaceBound = FS->BoundsValue(i);
234     Loop      = FaceBound->Bound();
235     
236     // ------------------------
237     // The Loop is a VertexLoop
238     // ------------------------
239     
240     if (Loop->IsKind(STANDARD_TYPE(StepShape_VertexLoop))) {
241 //:S4136      STF.Closed() = Standard_False;
242 //  PROBLEME si SPHERE ou TORE
243 //  Il faudra faire un wire complet, a condition que le point porte sur la face
244 //  En attendant, on ne fait rien
245       Handle(StepShape_VertexLoop) VL = Handle(StepShape_VertexLoop)::DownCast(Loop);
246
247       // abv 10.07.00 pr1sy.stp: vertex_loop can be wrong; so just make natural bounds
248       if (GeomSurf->IsKind (STANDARD_TYPE(Geom_SphericalSurface)) ||
249           GeomSurf->IsKind (STANDARD_TYPE(Geom_BSplineSurface)) )
250       {
251         if (NbBnd ==1 || FaceBound->IsKind(STANDARD_TYPE(StepShape_FaceOuterBound))) {
252           BRepBuilderAPI_MakeFace mf (GeomSurf, Precision());
253           for (TopoDS_Iterator it(mf); it.More(); it.Next()) 
254             B.Add (F, it.Value());
255           continue;
256         }
257       }
258       
259       if (GeomSurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
260         continue;
261       }
262       if (GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane))) {
263         TP->AddWarning(VL, "VertexLoop on plane is ignored");
264         continue; //smh : BUC60809
265       }
266       myTranVL.SetPrecision(Precision());//gka
267       myTranVL.SetMaxTol(MaxTol());
268       myTranVL.Init(VL, aTool, NMTool);
269       if (myTranVL.IsDone()) {
270         B.Add(F, myTranVL.Value());
271       }
272       else {
273         TP->AddWarning(VL, " a VertexLoop not mapped to TopoDS");
274       }
275     }
276     
277     // ----------------------
278     // The Loop is a PolyLoop
279     // ----------------------
280     
281     else if (Loop->IsKind(STANDARD_TYPE(StepShape_PolyLoop))) {
282 //:S4136      STF.Closed() = Standard_False;
283       Handle(StepShape_PolyLoop) PL = Handle(StepShape_PolyLoop)::DownCast(Loop);
284       F.Orientation ( FS->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED);
285       myTranPL.SetPrecision(Precision()); //gka
286       myTranPL.SetMaxTol(MaxTol());
287       myTranPL.Init(PL, aTool, GeomSurf, F);
288       if (myTranPL.IsDone()) {
289         TopoDS_Wire W = TopoDS::Wire(myTranPL.Value());
290         W.Orientation(FaceBound->Orientation() ? TopAbs_FORWARD : TopAbs_REVERSED);
291         B.Add(F, W);
292       }
293       else {
294         TP->AddWarning(PL, " a PolyLoop not mapped to TopoDS");
295       }
296     }
297     
298     // -----------------------
299     // The Loop is an EdgeLoop
300     // -----------------------
301     
302     else if (Loop->IsKind(STANDARD_TYPE(StepShape_EdgeLoop))) {
303       //:S4136      if (STF.Closed()) {
304       //:S4136  Handle(StepShape_EdgeLoop) EL = 
305       //:S4136    Handle(StepShape_EdgeLoop)::DownCast(FaceBound->Bound());
306       //:S4136  if (EL->NbEdgeList() != 1) STF.Closed() = Standard_False;
307       //:S4136      }
308
309       TopoDS_Wire   W;
310       myTranEdgeLoop.SetPrecision(Precision());  //gka
311       myTranEdgeLoop.SetMaxTol(MaxTol());
312       myTranEdgeLoop.Init(FaceBound, F, GeomSurf, StepSurf, sameSense, aTool, NMTool);
313
314       if (myTranEdgeLoop.IsDone()) {
315         W = TopoDS::Wire(myTranEdgeLoop.Value());
316
317         // STEP Face_Surface orientation :
318         // if the topological orientation is opposite to the geometric
319         // orientation of the surface => the underlying topological 
320         // orientation are not implicitly reversed
321         // this is the case in CAS.CADE => If the face_surface is reversed,
322         // the wire orientation has to be explictly reversed
323         if (FaceBound->Orientation()) {
324           // *DTH*        if (sameSense || GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane)))
325           W.Orientation(sameSense ? TopAbs_FORWARD : TopAbs_REVERSED);
326         }
327         else {
328           // *DTH*        if (sameSense || GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane)))
329           W.Orientation(sameSense ? TopAbs_REVERSED : TopAbs_FORWARD);
330         }
331         // -----------------------------
332         // The Wire is added to the Face      
333         // -----------------------------
334
335         B.Add(F, W);
336       }
337       else {
338         // Il y a eu un probleme dans le mapping : On perd la Face
339         // (facon de parler ...) Pas de moyen aujourd hui de recuperer
340         // au moins toutes les geometries (Points, Courbes 3D, Surface)
341         TP->AddFail(Loop, " EdgeLoop not mapped to TopoDS");
342
343         // CKY JAN-97 : un Wire manque, eh bien on continue quand meme !!
344         //  sauf si OuterBound : la c est quand meme pas bien normal ...
345         if (FaceBound->IsKind(STANDARD_TYPE(StepShape_FaceOuterBound))) {
346           TP->AddWarning(FS, "No Outer Bound : Face not done");
347         }
348         continue;
349       }
350     }    
351     else { 
352       // Type not yet implemented or non sens
353       TP->AddFail(Loop," Type of loop not yet implemented");
354 #ifdef OCCT_DEBUG
355       cout << Loop->DynamicType() << endl;
356 #endif
357       continue;
358     }
359   }
360
361   F.Orientation ( FS->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED);
362   aTool.Bind(FS,F);
363
364   // Register face in NM tool (ssv; 14.11.2010)
365   if ( NMTool.IsActive() )
366     NMTool.Bind(StepSurf, F);
367
368   myResult = F;
369   myError  = StepToTopoDS_TranslateFaceDone;
370   done     = Standard_True;
371 }
372
373
374 // ============================================================================
375 // Method  : Value 
376 // Purpose : Return the mapped Shape
377 // ============================================================================
378
379 const TopoDS_Shape& StepToTopoDS_TranslateFace::Value() const 
380 {
381   StdFail_NotDone_Raise_if(!done,"");
382   return myResult;
383 }
384
385 // ============================================================================
386 // Method  : Error
387 // Purpose : Return the TranslateFace error
388 // ============================================================================
389
390 StepToTopoDS_TranslateFaceError StepToTopoDS_TranslateFace::Error() const
391 {
392   return myError;
393 }