0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / DDocStd / DDocStd_ShapeSchemaCommands.cxx
1 // Created on: 2017-03-28
2 // Created by: Sergey NIKONOV
3 // Copyright (c) 2000-2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <DDocStd.hxx>
17 #include <DBRep.hxx>
18 #include <FSD_File.hxx>
19 #include <FSD_CmpFile.hxx>
20 #include <FSD_BinaryFile.hxx>
21 #include <BRep_Builder.hxx>
22 #include <NCollection_Handle.hxx>
23 #include <TCollection_AsciiString.hxx>
24 #include <TopTools_SequenceOfShape.hxx>
25 #include <Storage_BaseDriver.hxx>
26 #include <StdStorage.hxx>
27 #include <StdStorage_Data.hxx>
28 #include <StdStorage_HeaderData.hxx>
29 #include <StdStorage_RootData.hxx>
30 #include <StdStorage_TypeData.hxx>
31 #include <ShapePersistent_TopoDS.hxx>
32
33 //==========================================================
34 // ErrorMessage
35 //==========================================================
36
37 static void DDocStd_StorageErrorMessage (Draw_Interpretor& theDI, const Storage_Error theStatus)
38 {
39   switch (theStatus) {
40   case Storage_VSOk:
41     break;
42   case Storage_VSOpenError:
43     theDI << "Storage error: failed to open the stream";
44     break;
45   case Storage_VSModeError:
46     theDI << "Storage error: the stream is opened with a wrong mode for operation ";
47     break;
48   case Storage_VSCloseError:
49     theDI << "Storage error: failed to closing the stream";
50     break;
51   case Storage_VSAlreadyOpen:
52     theDI << "Storage error: stream is already opened";
53     break;
54   case Storage_VSNotOpen:
55     theDI << "Storage error: stream not opened";
56     break;
57   case Storage_VSSectionNotFound:
58     theDI << "Storage error: the section is not found";
59     break;
60   case Storage_VSWriteError:
61     theDI << "Storage error: error during writing";
62     break;
63   case Storage_VSFormatError:
64     theDI << "Storage error: wrong format error occured while reading";
65     break;
66   case Storage_VSUnknownType:
67     theDI << "Storage error: try to read an unknown type";
68     break;
69   case Storage_VSTypeMismatch:
70     theDI << "Storage error: try to read a wrong primitive type (read a char while expecting a real)";
71     break;
72   case Storage_VSInternalError:
73     theDI << "Storage error: internal error";
74     break;
75   case Storage_VSExtCharParityError:
76     theDI << "Storage error: parity error";
77     break;
78   default:
79     theDI << "Storage error: unknown error code";
80     break;
81   }
82 }
83
84 //=======================================================================
85 //function : DDocStd_ShapeSchema_Write 
86 //=======================================================================
87
88 static Standard_Integer DDocStd_fsdwrite(Draw_Interpretor& theDI,
89                                          Standard_Integer theArgNb,
90                                          const char** theArgs)
91 {
92   if (theArgNb < 3)
93   {
94     theDI << "Usage : fsdwrite shapes filename [gen | cmp | bin]\n";
95     theDI << "        Arguments:\n";
96     theDI << "        shapes   : list os shape names\n";
97     theDI << "        filename : output file name\n";
98     theDI << "        Storage driver:\n";
99     theDI << "          gen : FSD_File driver (default)\n";
100     theDI << "          cmp : FSD_CmpFile driver\n";
101     theDI << "          bin : FSD_BinaryFile driver\n";
102     return 1;
103   }
104
105   Handle(Storage_BaseDriver) aFileDriver(new FSD_File);
106
107   Standard_Boolean hasStorageDriver = Standard_False;
108   Standard_Integer iArgN = theArgNb - 1;
109
110   if (strncmp(theArgs[iArgN], "gen", 3) == 0)
111   {
112     aFileDriver = new FSD_File;
113     hasStorageDriver = Standard_True;
114   }
115   else if (strncmp(theArgs[iArgN], "cmp", 3) == 0)
116   {
117     aFileDriver = new FSD_CmpFile;
118     hasStorageDriver = Standard_True;
119   }
120   else if (strncmp(theArgs[iArgN], "bin", 3) == 0)
121   {
122     aFileDriver = new FSD_BinaryFile;
123     hasStorageDriver = Standard_True;
124   }
125
126   if (hasStorageDriver) --iArgN;
127
128   Storage_Error aStatus = aFileDriver->Open(theArgs[iArgN], Storage_VSWrite);
129   if (aStatus != Storage_VSOk) {
130     theDI << "Error: cannot  open file '" << "' for writing (" << aStatus << ")\n";
131     DDocStd_StorageErrorMessage (theDI, aStatus);
132     return 0;
133   }
134
135   TopTools_SequenceOfShape aShapes;
136   NCollection_DataMap<TCollection_AsciiString, Standard_Integer> aShapeNames;
137   for (Standard_Integer i = 1; i < iArgN; ++i)
138   {
139     TopoDS_Shape aShape = DBRep::Get(theArgs[i]);
140     if (aShape.IsNull())
141     {
142       theDI << "Error : null shape " << theArgs[i] << "\n";
143       return 1;
144     }
145     aShapes.Append(aShape);
146     if (aShapeNames.IsBound(theArgs[i]))
147       aShapeNames.ChangeFind(theArgs[i]) += 1;
148     else
149       aShapeNames.Bind(theArgs[i], 1);
150   }
151
152   Handle(StdStorage_Data) aData = new StdStorage_Data;
153
154   aData->HeaderData()->SetApplicationName(TCollection_ExtendedString("DDocStd_ShapeSchema_Write"));
155
156   StdObjMgt_TransientPersistentMap aMap;
157   for (Standard_Integer i = 1; i <= aShapes.Length(); ++i)
158   {
159     TopoDS_Shape aShape = aShapes.Value(i);
160
161     Handle(ShapePersistent_TopoDS::HShape) aPShape =
162       ShapePersistent_TopoDS::Translate(aShape, aMap, ShapePersistent_WithTriangle);
163     if (aPShape.IsNull())
164     {
165       theDI << "Error : couldn't translate shape " << theArgs[i] << "\n";
166       return 1;
167     }
168     
169     TCollection_AsciiString aName = theArgs[i];
170     if (aShapeNames.IsBound(aName))
171     {
172       Standard_Integer n = aShapeNames.Find(theArgs[i]);
173       if (n > 1)
174       {
175         aName += "_";
176         aName += n;
177       }
178     }
179
180     Handle(StdStorage_Root) aRoot = new StdStorage_Root(aName, aPShape);
181     aData->RootData()->AddRoot(aRoot);
182   }
183
184   Storage_Error anError = StdStorage::Write(aFileDriver, aData);
185   aFileDriver->Close();
186   DDocStd_StorageErrorMessage(theDI, anError);
187
188   return 0;
189 }
190
191 //=======================================================================
192 //function : DDocStd_ShapeSchema_Read 
193 //=======================================================================
194
195 static Standard_Integer DDocStd_fsdread(Draw_Interpretor& theDI, 
196                                         Standard_Integer theArgNb, 
197                                         const char** theArgs)
198 {
199   if (theArgNb < 3)
200   {
201     theDI << "Usage : fsdread filename shape\n";
202     theDI << "        Arguments:\n";
203     theDI << "        filename : input file name\n";
204     theDI << "        shape    : name of an output shape, or \n";
205     theDI << "                   reserved name = 'restore_with_names';\n";
206     theDI << "                   by default root shapes will be put into \n";
207     theDI << "                   a compound in case of multiple roots in the file;\n";
208     theDI << "                   if name = restore_with_names, the shapes will be put to\n";
209     theDI << "                   separate variables according kept names.\n";
210     return 1;
211   }
212   Standard_Boolean rflag(Standard_False);
213   if (strcmp(theArgs[2],"restore_with_names") == 0) 
214     rflag = Standard_True;
215   Handle(StdStorage_Data) aData;
216   Storage_Error anError = StdStorage::Read(TCollection_AsciiString(theArgs[1]), aData);
217   if (anError != Storage_VSOk)
218   {
219     DDocStd_StorageErrorMessage(theDI, anError);
220     return 0;
221   }
222
223   TopTools_SequenceOfShape aShapes;
224
225   Handle(StdStorage_TypeData) aTypeData = aData->TypeData();
226   Handle(StdStorage_RootData) aRootData = aData->RootData();
227   Handle(StdStorage_HSequenceOfRoots) aRoots = aRootData->Roots();
228   if (!aRoots.IsNull())
229   {
230     for (StdStorage_HSequenceOfRoots::Iterator anIt(*aRoots); anIt.More(); anIt.Next())
231     {
232       Handle(StdStorage_Root)& aRoot = anIt.ChangeValue();
233       Handle(StdObjMgt_Persistent) aPObject = aRoot->Object();
234       if (!aPObject.IsNull())
235       {
236         Handle(ShapePersistent_TopoDS::HShape) aHShape = Handle(ShapePersistent_TopoDS::HShape)::DownCast(aPObject);
237         if (aHShape) // shapes are expected
238         {
239           TopoDS_Shape aShape = aHShape->Import();
240           if(rflag) {
241             if(!aRoot->Name().IsEmpty())
242               DBRep::Set(aRoot->Name().ToCString(), aShape);
243             else {
244               TCollection_AsciiString aNam("name_");
245               aNam += aRoot->Reference();
246               DBRep::Set(aNam.ToCString(), aShape);
247             }
248 #ifdef DEBUG_FSDREAD
249             Standard_Integer indx = aRoot->Reference();
250             theDI << "Ref indx = " <<indx << " Name = " << aRoot->Name().ToCString() << "\n";
251 #endif
252           } else
253             aShapes.Append(aShape);
254         }
255       }
256     }
257   }
258
259   theDI << "Info : " << aTypeData->NumberOfTypes() << " type(s)\n";
260   theDI << "       " << aRoots->Length() << " root(s)\n";
261
262   if (!rflag) {
263     if (aShapes.Length() > 1)
264     {
265       theDI << "       " << aShapes.Length() << " shape(s) translated\n";
266       BRep_Builder aB;
267       TopoDS_Compound aC;
268       aB.MakeCompound(aC);
269       for (Standard_Integer i = 1; i <= aShapes.Length(); ++i)
270         aB.Add(aC, aShapes.Value(i));
271       DBRep::Set(theArgs[2], aC);
272     }
273     else
274       DBRep::Set(theArgs[2], aShapes.First());
275   }
276   return 0;
277 }
278
279 //=======================================================================
280 //function : ShapeSchemaCommands
281 //purpose  : registers shape schema related commands in Draw interpreter
282 //=======================================================================
283
284 void DDocStd::ShapeSchemaCommands(Draw_Interpretor& theCommands)
285 {
286   static Standard_Boolean done = Standard_False;
287   if (done) return;
288   done = Standard_True;
289
290   const char* g = "Shape persistence commands";
291
292   theCommands.Add("fsdwrite",
293     "fsdrite shape filename [driver]",
294     __FILE__, DDocStd_fsdwrite, g);
295
296   theCommands.Add("fsdread",
297     "fsdread filename shape [name | or key 'restore_with_names']",
298     __FILE__, DDocStd_fsdread, g);
299
300 }