0024023: Revamp the OCCT Handle -- general
[occt.git] / src / TopoDSToStep / TopoDSToStep_WireframeBuilder.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //:S4134 abv 10.03.99: working methods moved from package TopoDSToGBWire
15 //:j1 modified by abv 22 Oct 98: CSR BUC60401
16 // - unused parts of code dropped
17 // - fixed trimming of circles and ellipses (radians used instead of degrees)
18 //szv#4 S4163
19
20 #include <TopoDSToStep_WireframeBuilder.ixx>
21 #include <TopoDSToStep_Tool.hxx>
22
23 #include <TColgp_Array1OfPnt.hxx>
24 #include <TColStd_Array1OfReal.hxx>
25 #include <TColStd_Array1OfInteger.hxx>
26 #include <TColStd_SequenceOfTransient.hxx>
27 #include <MoniTool_DataMapOfShapeTransient.hxx>
28 #include <TCollection_HAsciiString.hxx>
29 #include <TransferBRep_ShapeMapper.hxx>
30 #include <Transfer_FinderProcess.hxx>
31
32 #include <Precision.hxx>
33 #include <gp_Vec.hxx>
34
35 #include <Geom2d_Line.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom_TrimmedCurve.hxx>
38 #include <Geom_BSplineCurve.hxx>
39 #include <Geom_Line.hxx>
40 #include <Geom_Circle.hxx>
41 #include <Geom_Ellipse.hxx>
42 #include <Geom_Plane.hxx>
43
44 #include <Adaptor3d_CurveOnSurface.hxx>
45 #include <BRepAdaptor_Curve.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
48
49 #include <TopoDS.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Shell.hxx>
53 #include <TopoDS_Iterator.hxx>
54 #include <TopExp_Explorer.hxx>
55 #include <TopLoc_Location.hxx>
56
57 #include <Standard_ErrorHandler.hxx>
58 #include <Standard_NullObject.hxx>
59
60 #include <StepGeom_CartesianPoint.hxx>
61 #include <StepGeom_Line.hxx>
62 #include <StepGeom_SurfaceCurve.hxx>
63 #include <StepGeom_SeamCurve.hxx>
64 #include <StepGeom_TrimmedCurve.hxx>
65 #include <StepGeom_TrimmingSelect.hxx>
66 #include <StepGeom_HArray1OfTrimmingSelect.hxx>
67
68 #include <GeomToStep_MakeCartesianPoint.hxx>
69 #include <GeomToStep_MakeCurve.hxx>
70 #include <GeomToStep_MakeLine.hxx>
71
72 // ============================================================================
73 // Method  : TopoDSToStep_Builder::TopoDSToStep_Builder
74 // Purpose :
75 // ============================================================================
76
77 TopoDSToStep_WireframeBuilder::TopoDSToStep_WireframeBuilder()
78 {
79   done = Standard_False;
80 }
81
82 // ============================================================================
83 // Method  : TopoDSToStep_Builder::TopoDSToStep_Builder
84 // Purpose :
85 // ============================================================================
86
87  TopoDSToStep_WireframeBuilder::TopoDSToStep_WireframeBuilder(const TopoDS_Shape& aShape, TopoDSToStep_Tool& aTool, const Handle(Transfer_FinderProcess)& FP)
88 {
89   done = Standard_False;
90   Init(aShape, aTool, FP);
91 }
92
93 void TopoDSToStep_WireframeBuilder::Init(const TopoDS_Shape& aShape, TopoDSToStep_Tool& /* T */, const Handle(Transfer_FinderProcess)& /* FP */)
94 {
95   Handle(TColStd_HSequenceOfTransient) itemList =
96     new TColStd_HSequenceOfTransient();
97   MoniTool_DataMapOfShapeTransient aPmsMap;
98   done = GetTrimmedCurveFromShape(aShape, aPmsMap, itemList);
99   myResult = itemList;
100 }
101
102 // ============================================================================
103 // Method  : TopoDSToStep_Builder::Error
104 // Purpose :
105 // ============================================================================
106
107 TopoDSToStep_BuilderError TopoDSToStep_WireframeBuilder::Error() const 
108 {
109         return myError;
110 }
111
112 // ============================================================================
113 // Method  : TopoDSToStep_Builder::Value
114 // Purpose :
115 // ============================================================================
116
117 const Handle(TColStd_HSequenceOfTransient)& TopoDSToStep_WireframeBuilder::Value() const 
118 {
119   StdFail_NotDone_Raise_if(!done,"");
120   return myResult;
121 }
122
123
124 // ============================================================================
125 //:S4134: abv 10 Mar 99: the methods below moved from package TopoDSToGBWire
126
127 #define Nbpt 23
128
129 static Handle(StepGeom_TrimmedCurve) MakeTrimmedCurve (const Handle(StepGeom_Curve) &C,
130                                                        const Handle(StepGeom_CartesianPoint) P1, 
131                                                        const Handle(StepGeom_CartesianPoint) P2, 
132                                                        Standard_Real trim1,
133                                                        Standard_Real trim2,
134                                                        Standard_Boolean sense)
135 {
136   Handle(StepGeom_HArray1OfTrimmingSelect) aSTS1 =
137     new StepGeom_HArray1OfTrimmingSelect(1,2);
138   StepGeom_TrimmingSelect tSel;
139   tSel.SetValue(P1);
140   aSTS1->SetValue(1,tSel);
141   tSel.SetParameterValue(trim1);
142   aSTS1->SetValue(2,tSel);
143     
144   Handle(StepGeom_HArray1OfTrimmingSelect) aSTS2 =
145     new StepGeom_HArray1OfTrimmingSelect(1,2);
146   tSel.SetValue(P2);
147   aSTS2->SetValue(1,tSel);
148   tSel.SetParameterValue(trim2);
149   aSTS2->SetValue(2,tSel);
150     
151   Handle(TCollection_HAsciiString) empty = 
152       new TCollection_HAsciiString("");
153   Handle(StepGeom_TrimmedCurve) pmsTC = new StepGeom_TrimmedCurve;
154   pmsTC->Init(empty,C,aSTS1,aSTS2,sense,StepGeom_tpParameter);
155   return pmsTC;
156 }
157   
158 Standard_Boolean TopoDSToStep_WireframeBuilder::
159   GetTrimmedCurveFromEdge(const TopoDS_Edge& theEdge, 
160                           const TopoDS_Face& aFace, 
161                           MoniTool_DataMapOfShapeTransient& aMap, 
162                           Handle(TColStd_HSequenceOfTransient)& curveList) const
163 {
164   if (theEdge.Orientation() == TopAbs_INTERNAL  ||
165       theEdge.Orientation() == TopAbs_EXTERNAL ) {
166 #ifdef OCCT_DEBUG
167     cout <<"Warning: TopoDSToStep_WireframeBuilder::GetTrimmedCurveFromEdge: Edge is internal or external; dropped" << endl;
168 #endif
169     return Standard_False;
170   }
171   //szv#4:S4163:12Mar99 SGI warns
172   TopoDS_Shape sh = theEdge.Oriented(TopAbs_FORWARD);
173   TopoDS_Edge anEdge = TopoDS::Edge ( sh );
174
175   // resulting curve
176   Handle(StepGeom_Curve) Gpms;
177   
178   if ( aMap.IsBound(anEdge)) {
179     Gpms = Handle(StepGeom_Curve)::DownCast ( aMap.Find(anEdge) );
180     if ( Gpms.IsNull() ) return Standard_False;
181 //??    curveList->Append(Gpms);
182     return Standard_True;
183   }
184
185   BRepAdaptor_Curve CA;
186   try {
187     OCC_CATCH_SIGNALS
188     CA.Initialize (anEdge);
189   }
190   catch (Standard_NullObject) {
191     return Standard_False;
192   }
193
194   // Vertices
195   TopoDS_Vertex Vfirst, Vlast;
196   Handle(StepGeom_CartesianPoint) pmsP1, pmsP2; 
197   for (TopoDS_Iterator It(anEdge);It.More();It.Next()) {
198     // Translates the Edge Vertices
199     TopoDS_Vertex V = TopoDS::Vertex(It.Value());
200     gp_Pnt gpP = BRep_Tool::Pnt(V);
201     if ( V.Orientation() == TopAbs_FORWARD ) {
202       Vfirst = V;
203       // 1.point for trimming
204       GeomToStep_MakeCartesianPoint gtpP(gpP);
205       pmsP1 = gtpP.Value();
206     }
207     if ( V.Orientation() == TopAbs_REVERSED ) {
208       Vlast = V;
209       // 2.point for trimming
210       GeomToStep_MakeCartesianPoint gtpP(gpP);
211       pmsP2 = gtpP.Value();
212     }
213   }
214     
215   // ---------------------------------------
216   // Translate 3D representation of the Edge
217   // ---------------------------------------
218     
219     
220   // Handle(Geom_Curve) C = CA.Curve().Curve();
221
222   // UPDATE FMA 26-02-96 
223   // General remark : this full code should be deaply reworked
224   //                  Too many objects are not used !
225
226   Standard_Real First, Last;
227   Handle(Geom_Curve) C = BRep_Tool::Curve(anEdge, First, Last); 
228   if ( ! C.IsNull() ) {
229     if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
230       C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
231     GeomToStep_MakeCurve  gtpC(C);
232
233     if(!gtpC.IsDone())
234       return Standard_False;
235
236     Handle(StepGeom_Curve) pmsC = gtpC.Value();
237
238     // trim the curve
239     Standard_Real trim1 = CA.FirstParameter();
240     Standard_Real trim2 = CA.LastParameter();
241 /* //:j1 abv 22 Oct 98: radians are used in the produced STEP file (at least by default)
242    if(C->IsKind(STANDARD_TYPE(Geom_Circle)) ||
243        C->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
244       Standard_Real fact = 180. / M_PI;
245       trim1 = trim1 * fact;
246       trim2 = trim2 * fact;
247     }
248 */
249     Gpms = MakeTrimmedCurve (pmsC, pmsP1, pmsP2, trim1, trim2, Standard_True );
250 //                           (anEdge.Orientation() == TopAbs_FORWARD));
251   }
252   else {
253
254     // -------------------------
255     // a 3D Curve is constructed
256     // -------------------------
257
258     Standard_Boolean iaplan = Standard_False;
259     if ( ! aFace.IsNull() ) {
260       Standard_Real cf, cl;
261       Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(anEdge, aFace, cf, cl);
262       Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
263       if (S->IsKind(STANDARD_TYPE(Geom_Plane)) &&
264           C2d->IsKind(STANDARD_TYPE(Geom2d_Line))) iaplan = Standard_True;
265     }
266
267     // to be modified : cf and cl are the topological trimming prameter
268     // these are computed after ! (U1 and U2) -> cf and cl instead
269     if (iaplan) {
270       gp_Pnt Pnt1 = CA.Value(CA.FirstParameter()), Pnt2 = CA.Value(CA.LastParameter());
271       gp_Vec V ( Pnt1, Pnt2 );
272       Standard_Real length = V.Magnitude();
273       if ( length >= Precision::Confusion() ) {
274         Handle(Geom_Line) L = new Geom_Line(Pnt1, gp_Dir(V));
275         GeomToStep_MakeLine gtpL(L);
276         Gpms = gtpL.Value();
277         Gpms = MakeTrimmedCurve (gtpL.Value(), pmsP1, pmsP2, 0, length, Standard_True );
278 //                               (anEdge.Orientation() == TopAbs_FORWARD));
279       }
280 #ifdef OCCT_DEBUG
281       else cout << "Warning: TopoDSToStep_WireframeBuilder::GetTrimmedCurveFromEdge: Null-length curve not mapped" << endl;
282 #endif
283     }
284     else {
285       TColgp_Array1OfPnt Points(1,Nbpt);
286       TColStd_Array1OfReal Knots(1,Nbpt);
287       TColStd_Array1OfInteger Mult(1,Nbpt);
288       Standard_Real U1 = CA.FirstParameter();
289       Standard_Real U2 = CA.LastParameter();
290       for ( Standard_Integer i=1; i<=Nbpt; i++ ) {
291         Standard_Real U = U1 + (i-1)*(U2 - U1)/(Nbpt - 1);
292         gp_Pnt P = CA.Value(U);
293         Points.SetValue(i,P);
294         Knots.SetValue(i,U);
295         Mult.SetValue(i,1);
296       }
297       Points.SetValue(1, BRep_Tool::Pnt(Vfirst));
298       Points.SetValue(Nbpt, BRep_Tool::Pnt(Vlast));
299       Mult.SetValue(1,2);
300       Mult.SetValue(Nbpt,2);
301       Handle(Geom_Curve) Bs = 
302         new Geom_BSplineCurve(Points, Knots, Mult, 1);
303       GeomToStep_MakeCurve gtpC(Bs);
304       Gpms = gtpC.Value();
305     }
306   }
307   if( Gpms.IsNull() ) return Standard_False;
308
309   aMap.Bind(anEdge, Gpms);
310   curveList->Append(Gpms);
311   return Standard_True;
312 }
313
314
315 Standard_Boolean TopoDSToStep_WireframeBuilder::
316   GetTrimmedCurveFromFace(const TopoDS_Face& aFace, 
317                           MoniTool_DataMapOfShapeTransient& aMap, 
318                           Handle(TColStd_HSequenceOfTransient)& aCurveList) const
319 {
320   TopoDS_Shape curShape;
321   TopoDS_Edge  curEdge;
322   TopExp_Explorer  exp;
323   Standard_Boolean result = Standard_False; //szv#4:S4163:12Mar99 `done` hid one from this, initialisation needed
324
325   for (exp.Init(aFace,TopAbs_EDGE); exp.More(); exp.Next()){
326     curShape = exp.Current();
327     curEdge  = TopoDS::Edge(curShape);
328     if (GetTrimmedCurveFromEdge(curEdge, aFace, aMap, aCurveList)) result = Standard_True;
329   }
330   return result;
331 }
332
333 Standard_Boolean TopoDSToStep_WireframeBuilder::
334   GetTrimmedCurveFromShape(const TopoDS_Shape& aShape, 
335                            MoniTool_DataMapOfShapeTransient& aMap,  
336                            Handle(TColStd_HSequenceOfTransient)& aCurveList) const
337 {
338   TopoDS_Iterator  It;
339   Standard_Boolean result = Standard_False; //szv#4:S4163:12Mar99 `done` hid one from this, initialisation needed
340
341   //szv#4:S4163:12Mar99 optimized
342   switch (aShape.ShapeType()) {
343     case TopAbs_EDGE : {
344       const TopoDS_Edge& curEdge = TopoDS::Edge(aShape);
345       TopoDS_Face nulFace;
346       result = GetTrimmedCurveFromEdge(curEdge, nulFace, aMap, aCurveList);
347       break;
348     }
349     case TopAbs_WIRE : {
350       TopoDS_Face nulFace;
351       TopoDS_Shape curShape;
352       TopoDS_Edge  curEdge;
353       TopExp_Explorer  exp;
354
355       for (exp.Init(aShape,TopAbs_EDGE); exp.More(); exp.Next()){
356         curShape = exp.Current();
357         curEdge  = TopoDS::Edge(curShape);
358         if (GetTrimmedCurveFromEdge(curEdge, nulFace, aMap, aCurveList)) result = Standard_True;
359       }
360       break;
361     }
362     case TopAbs_FACE : {
363       const TopoDS_Face& curFace = TopoDS::Face(aShape);
364       result = GetTrimmedCurveFromFace(curFace, aMap, aCurveList);
365       break;
366     }
367     case TopAbs_SHELL : {
368       TopoDS_Shell Sh = TopoDS::Shell(aShape);    
369       It.Initialize(Sh);
370       for (;It.More();It.Next()) {
371         TopoDS_Face curFace = TopoDS::Face(It.Value());
372         if (GetTrimmedCurveFromFace(curFace, aMap, aCurveList)) result = Standard_True;
373 #ifdef OCCT_DEBUG
374         if(!result) {
375           cout << "ERROR extracting trimmedCurve from Face" << endl;
376           //BRepTools::Dump(curFace,cout);  cout<<endl;
377         }
378 #endif
379       }
380       break;
381     }
382     case TopAbs_SOLID : {
383       It.Initialize(aShape);
384       for (;It.More();It.Next()) {
385         if  (It.Value().ShapeType() == TopAbs_SHELL) {
386           if (GetTrimmedCurveFromShape(It.Value(), aMap, aCurveList)) result = Standard_True;
387         }
388       } 
389       break;
390     }
391     case TopAbs_COMPOUND : {
392       It.Initialize(aShape);
393       for (;It.More();It.Next()) {
394 /*        if  ((It.Value().ShapeType() == TopAbs_SHELL) ||
395                (It.Value().ShapeType() == TopAbs_COMPOUND)) {
396             result = GetTrimmedCurveFromShape(It.Value(), aMap, aCurveList);
397             break;
398           }
399           else if (It.Value().ShapeType() == TopAbs_FACE) {
400             result = GetTrimmedCurveFromFace(TopoDS::Face(It.Value()), aMap, aCurveList);
401             break;
402           } */
403         if (GetTrimmedCurveFromShape(It.Value(), aMap, aCurveList)) result = Standard_True;
404       }
405       break;
406     }
407     default : break;
408   }
409   return result;
410 }