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