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