0025689: IGESCAFControl_Writer crash in constructor.
[occt.git] / src / IGESControl / IGESControl_Writer.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 //cky 16.01.99 Remove couts.
15 //rln 28.12.98 CCI60005
16
17 #include <Standard_Stream.hxx>
18
19 #include <IGESControl_Writer.ixx>
20 #include <IGESControl_Controller.hxx>
21 #include <IGESSelect_WorkLibrary.hxx>
22 #include <BRepToIGES_BREntity.hxx>
23 #include <BRepToIGESBRep_Entity.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <GeomToIGES_GeomCurve.hxx>
27 #include <GeomToIGES_GeomSurface.hxx>
28 #include <IGESData_IGESWriter.hxx>
29 #include <XSControl_TransferWriter.hxx>
30
31 #include <Interface_Macros.hxx>
32 #include <Interface_Static.hxx>
33 #include <ShapeAnalysis_ShapeTolerance.hxx>
34
35 #include <gp_XYZ.hxx>
36 #include <Bnd_Box.hxx>
37 #include <BRepBndLib.hxx>
38 #include <GeomAdaptor_Curve.hxx>
39 #include <GeomAdaptor_Surface.hxx>
40 #include <BndLib_Add3dCurve.hxx>
41 #include <BndLib_AddSurface.hxx>
42 #include <XSAlgo.hxx>
43 #include <XSAlgo_AlgoContainer.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <Message_ProgressIndicator.hxx>
46 #include <errno.h>
47 #include <OSD_OpenFile.hxx>
48
49 IGESControl_Writer::IGESControl_Writer ()
50     :  theTP (new Transfer_FinderProcess(10000)) ,
51        thest (Standard_False)
52 {
53 //  faudrait aussi (?) prendre les parametres par defaut ... ?
54   IGESControl_Controller::Init();
55   thedit.Init(IGESSelect_WorkLibrary::DefineProtocol());
56   thedit.SetUnitName(Interface_Static::CVal ("write.iges.unit"));
57   thedit.ApplyUnit(); 
58   thecr = Interface_Static::IVal ("write.iges.brep.mode");
59   themod = thedit.Model();
60 }
61
62 IGESControl_Writer::IGESControl_Writer
63   (const Standard_CString unit, const Standard_Integer modecr)
64     :  theTP (new Transfer_FinderProcess(10000)) ,
65        thecr (modecr) , thest (Standard_False)
66 {
67 //  faudrait aussi (?) prendre les parametres par defaut ... ?
68   IGESControl_Controller::Init();
69   thedit.Init(IGESSelect_WorkLibrary::DefineProtocol());
70   thedit.SetUnitName(unit);
71   thedit.ApplyUnit();
72   themod = thedit.Model();
73 }
74
75 IGESControl_Writer::IGESControl_Writer
76   (const Handle(IGESData_IGESModel)& model, const Standard_Integer modecr)
77     :  theTP (new Transfer_FinderProcess(10000)) ,
78        themod (model) , 
79        thedit (model,IGESSelect_WorkLibrary::DefineProtocol()) ,
80        thecr (modecr) , thest (Standard_False)     {  }
81
82 Handle(IGESData_IGESModel) IGESControl_Writer::Model () const
83 {
84   return themod;
85 }
86
87 Handle(Transfer_FinderProcess) IGESControl_Writer::TransferProcess () const
88 {
89   return theTP;
90 }
91
92 void IGESControl_Writer::SetTransferProcess
93   (const Handle(Transfer_FinderProcess)& TP)
94 {
95   theTP = TP;
96 }
97
98 Standard_Boolean IGESControl_Writer::AddShape (const TopoDS_Shape& theShape)
99 {
100   if (theShape.IsNull()) return Standard_False;
101   
102   // for progress indication
103   Handle(Message_ProgressIndicator) progress = theTP->GetProgress();
104   if ( ! progress.IsNull() ) { 
105     Standard_Integer nbfaces=0;
106     for( TopExp_Explorer exp(theShape,TopAbs_FACE); exp.More(); exp.Next() )
107       nbfaces++;
108     progress->SetScale ( "Faces", 0, nbfaces, 1 );
109   }
110   
111   XSAlgo::AlgoContainer()->PrepareForTransfer();
112   
113   //  modified by NIZHNY-EAP Tue Aug 29 11:16:54 2000 ___BEGIN___
114   Handle(Standard_Transient) info;
115   Standard_Real Tol = Interface_Static::RVal("write.precision.val");
116   Standard_Real maxTol = Interface_Static::RVal("read.maxprecision.val");
117   TopoDS_Shape Shape = XSAlgo::AlgoContainer()->ProcessShape( theShape, Tol, maxTol, 
118                                                               "write.iges.resource.name", 
119                                                               "write.iges.sequence", info,
120                                                               progress );
121   //  modified by NIZHNY-EAP Tue Aug 29 11:17:01 2000 ___END___
122   Handle(IGESData_IGESEntity) ent; 
123   BRepToIGES_BREntity   B0;  B0.SetTransferProcess(theTP); B0.SetModel(themod);
124   BRepToIGESBRep_Entity B1;  B1.SetTransferProcess(theTP); B1.SetModel(themod);
125   if (thecr) ent = B1.TransferShape(Shape);
126   else       ent = B0.TransferShape(Shape);
127
128   if(ent.IsNull())
129     return Standard_False;
130 //  modified by NIZHNY-EAP Tue Aug 29 11:37:18 2000 ___BEGIN___
131   XSAlgo::AlgoContainer()->MergeTransferInfo(theTP, info);
132 //  modified by NIZHNY-EAP Tue Aug 29 11:37:25 2000 ___END___
133   
134   //22.10.98 gka BUC60080
135
136   Standard_Integer oldnb = themod->NbEntities();
137   Standard_Boolean aent = AddEntity (ent);
138   Standard_Integer newnb = themod->NbEntities();
139
140   Standard_Real oldtol = themod->GlobalSection().Resolution(), newtol;
141   
142   Standard_Integer tolmod = Interface_Static::IVal("write.precision.mode");
143   if (tolmod == 2)
144     newtol = Interface_Static::RVal("write.precision.val");
145   else {
146     ShapeAnalysis_ShapeTolerance stu; 
147     Standard_Real Tolv = stu.Tolerance (Shape, tolmod, TopAbs_VERTEX);
148     Standard_Real Tole = stu.Tolerance (Shape, tolmod, TopAbs_EDGE); 
149
150     if (tolmod == 0 ) {   //Average
151       Standard_Real Tol1 = (Tolv + Tole) / 2;
152       newtol = (oldtol * oldnb + Tol1 * (newnb - oldnb)) / newnb;
153     }
154     else if (tolmod < 0) {//Least
155       newtol = Min (Tolv, Tole);
156       if (oldnb > 0) newtol = Min (oldtol, newtol);
157     }
158     else {                //Greatest
159       newtol = Max (Tolv, Tole);
160       if (oldnb > 0) newtol = Max (oldtol, newtol);
161     }
162   }
163   
164   IGESData_GlobalSection gs = themod->GlobalSection();
165   gs.SetResolution (newtol / gs.UnitValue());//rln 28.12.98 CCI60005
166
167   //#34 22.10.98 rln BUC60081
168   Bnd_Box box;
169   BRepBndLib::Add (Shape, box);
170   if (!(box.IsVoid() || box.IsOpenXmax() || box.IsOpenYmax() || box.IsOpenZmax() || box.IsOpenXmin() || box.IsOpenYmin() || box.IsOpenZmin())){
171     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
172     box.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
173     gs.MaxMaxCoords (gp_XYZ (aXmax / gs.UnitValue(),
174                              aYmax / gs.UnitValue(),
175                              aZmax / gs.UnitValue()));
176     gs.MaxMaxCoords (gp_XYZ (aXmin / gs.UnitValue(),
177                              aYmin / gs.UnitValue(),
178                              aZmin / gs.UnitValue()));
179   }
180
181   themod->SetGlobalSection(gs);
182
183   return aent;
184 }
185
186 Standard_Boolean IGESControl_Writer::AddGeom (const Handle(Standard_Transient)& geom)
187 {
188   if (geom.IsNull() || !geom->IsKind (STANDARD_TYPE (Geom_Geometry)))
189     return Standard_False;
190   DeclareAndCast(Geom_Curve,Curve,geom);
191   DeclareAndCast(Geom_Surface,Surf,geom);
192   Handle(IGESData_IGESEntity) ent; 
193
194 //  On reconnait : Curve et Surface de Geom
195 //   quid de Point; Geom2d ?
196
197 //  GeomToIGES_GeomPoint GP;
198   GeomToIGES_GeomCurve GC;    GC.SetModel(themod);
199   GeomToIGES_GeomSurface GS;  GS.SetModel(themod);
200
201   //#34 22.10.98 rln BUC60081
202   IGESData_GlobalSection gs = themod->GlobalSection();
203   Bnd_Box box;
204
205   if (!Curve.IsNull()) {
206     ent = GC.TransferCurve(Curve,Curve->FirstParameter(),Curve->LastParameter());
207     BndLib_Add3dCurve::Add (GeomAdaptor_Curve (Curve), 0, box); }
208   else if (!Surf.IsNull()) {
209     Standard_Real U1,U2,V1,V2;
210     Surf->Bounds(U1,U2,V1,V2);
211     ent = GS.TransferSurface(Surf,U1,U2,V1,V2);
212     BndLib_AddSurface::Add (GeomAdaptor_Surface (Surf), 0, box);
213   }
214
215   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
216   box.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
217   gs.MaxMaxCoords (gp_XYZ (aXmax / gs.UnitValue(),
218                            aYmax / gs.UnitValue(),
219                            aZmax / gs.UnitValue()));
220   gs.MaxMaxCoords (gp_XYZ (aXmin / gs.UnitValue(),
221                            aYmin / gs.UnitValue(),
222                            aZmin / gs.UnitValue()));
223   themod->SetGlobalSection(gs);
224   return AddEntity (ent);
225 }
226
227 Standard_Boolean IGESControl_Writer::AddEntity (const Handle(IGESData_IGESEntity)& ent)
228 {
229   if (ent.IsNull()) return Standard_False;
230   themod->AddWithRefs(ent,IGESSelect_WorkLibrary::DefineProtocol());
231   thest = Standard_False;
232   return Standard_True;
233 }
234
235 void IGESControl_Writer::ComputeModel ()
236 {
237   if (thest) return;
238   thedit.ComputeStatus();
239   thedit.AutoCorrectModel();
240   thest = Standard_True;
241 }
242
243 Standard_Boolean IGESControl_Writer::Write
244   (Standard_OStream& S, const Standard_Boolean fnes)
245 {
246   if (!S) return Standard_False;
247   ComputeModel();
248   Standard_Integer nbEnt = themod->NbEntities();
249 #ifdef OCCT_DEBUG
250   cout<<" IGES Write : "<<nbEnt<<" ent.s"<< flush;
251 #endif
252   if(!nbEnt)
253     return Standard_False;
254   IGESData_IGESWriter IW (themod);
255 //  ne pas oublier le mode fnes ... a transmettre a IW
256   IW.SendModel (IGESSelect_WorkLibrary::DefineProtocol());
257 #ifdef OCCT_DEBUG
258   cout<<" ...  ecriture  ..."<<flush;
259 #endif
260   if (fnes) IW.WriteMode() = 10;
261   Standard_Boolean status = IW.Print(S);
262 #ifdef OCCT_DEBUG
263   cout<<" ...  fichier ecrit  ..."<<endl;
264 #endif
265   return status;
266 }
267
268 Standard_Boolean IGESControl_Writer::Write
269   (const Standard_CString file, const Standard_Boolean fnes)
270 {
271   ofstream fout;
272   OSD_OpenStream(fout,file,ios::out);
273   if (!fout) return Standard_False;
274 #ifdef OCCT_DEBUG
275   cout<<" Ecriture fichier ("<< (fnes ? "fnes" : "IGES") <<"): "<<file<<endl;
276 #endif
277   Standard_Boolean res = Write (fout,fnes);
278
279   errno = 0;
280   fout.close();
281   res = fout.good() && res && !errno;
282
283   return res;
284 }
285
286 void IGESControl_Writer::PrintStatsTransfer
287   (const Standard_Integer what, const Standard_Integer mode) const
288 {
289   XSControl_TransferWriter::PrintStatsProcess (theTP,what,mode);
290 }