0031918: Application Framework - New binary format for fast reading part of OCAF...
[occt.git] / src / BinMNaming / BinMNaming_NamedShapeDriver.cxx
1 // Created on: 2004-04-08
2 // Created by: Sergey ZARITCHNY
3 // Copyright (c) 2004-2014 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
17 #include <BinMNaming_NamedShapeDriver.hxx>
18 #include <BinObjMgt_Persistent.hxx>
19 #include <BinTools_LocationSet.hxx>
20 #include <BinTools_ShapeSet.hxx>
21 #include <BinTools_ShapeWriter.hxx>
22 #include <BinTools_ShapeReader.hxx>
23 #include <Message_Messenger.hxx>
24 #include <Standard_DomainError.hxx>
25 #include <Standard_Type.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <TDF_Attribute.hxx>
28 #include <TDF_Label.hxx>
29 #include <TDocStd_FormatVersion.hxx>
30 #include <TNaming_Builder.hxx>
31 #include <TNaming_Evolution.hxx>
32 #include <TNaming_Iterator.hxx>
33 #include <TNaming_NamedShape.hxx>
34 #include <TopAbs_Orientation.hxx>
35 #include <TopoDS_Shape.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(BinMNaming_NamedShapeDriver,BinMDF_ADriver)
38
39 #define SHAPESET "SHAPE_SECTION"
40 //=======================================================================
41 static Standard_Character EvolutionToChar (const TNaming_Evolution theEvol)
42 {
43   switch(theEvol) {
44     case TNaming_PRIMITIVE    : return 'P';
45     case TNaming_GENERATED    : return 'G';
46     case TNaming_MODIFY       : return 'M';
47     case TNaming_DELETE       : return 'D';
48     case TNaming_SELECTED     : return 'S';
49     case TNaming_REPLACE      : return 'M'; // for compatibility case TNaming_REPLACE      : return 'R';
50   default:
51     throw Standard_DomainError("TNaming_Evolution:: Evolution Unknown");
52   }
53 }
54
55 //=======================================================================
56 static TNaming_Evolution EvolutionToEnum (const Standard_Character theEvol)
57 {
58   switch(theEvol) {
59     case 'P': return TNaming_PRIMITIVE;
60     case 'G': return TNaming_GENERATED;
61     case 'M': return TNaming_MODIFY;
62     case 'D': return TNaming_DELETE;
63     case 'S': return TNaming_SELECTED;
64     case 'R': return TNaming_MODIFY; //for compatibility //TNaming_REPLACE;
65   default:
66     throw Standard_DomainError("TNaming_Evolution:: Evolution Unknown");
67   }
68 }
69 //=======================================================================
70 static Standard_Character OrientationToChar (const TopAbs_Orientation theOrient)
71 {
72   switch(theOrient) {
73     case TopAbs_FORWARD    : return 'F';
74     case TopAbs_REVERSED   : return 'R';
75     case TopAbs_INTERNAL   : return 'I';
76     case TopAbs_EXTERNAL   : return 'E';
77   default:
78     throw Standard_DomainError("TopAbs_Orientation:: Orientation Unknown");
79   }
80 }
81 //=======================================================================
82 static TopAbs_Orientation CharToOrientation (const Standard_Character  theCharOrient)
83 {
84   switch(theCharOrient) {
85     case 'F':  return TopAbs_FORWARD;
86     case 'R':  return TopAbs_REVERSED;
87     case 'I':  return TopAbs_INTERNAL;
88     case 'E':  return TopAbs_EXTERNAL;
89   default:
90     throw Standard_DomainError("TopAbs_Orientation:: Orientation Unknown");
91   }
92 }
93
94 //=======================================================================
95 static void TranslateTo (const TopoDS_Shape&            theShape,
96                          BinObjMgt_Persistent&          theResult,
97                          BinTools_ShapeSet*             theShapeSet)
98 {
99   // Check for empty shape
100   if (theShape.IsNull()) {
101     theResult.PutInteger (-1);
102     theResult.PutInteger (-1);
103     theResult.PutInteger (-1);
104     return;
105   }
106   // Add to shape set both TShape and Location contained in <theShape>
107   const Standard_Integer aTShapeID = theShapeSet->Add (theShape);
108   const Standard_Integer aLocID =
109     theShapeSet->Locations().Index (theShape.Location());
110
111   // Fill theResult with shape parameters: TShape ID, Location, Orientation
112   theResult << aTShapeID;
113   theResult << aLocID;
114   theResult << OrientationToChar (theShape.Orientation());
115 }
116 //=======================================================================
117 static int TranslateFrom  (const BinObjMgt_Persistent&  theSource,
118                          TopoDS_Shape&                  theResult,
119                          BinTools_ShapeSet*            theShapeSet)
120 {
121   Standard_Integer aShapeID, aLocID;
122   Standard_Character aCharOrient;
123   Standard_Boolean Ok = theSource >> aShapeID; //TShapeID;
124   if(!Ok) return 1;
125   // Read TShape and Orientation
126   if (aShapeID <= 0 || aShapeID > theShapeSet->NbShapes())
127     return 1;
128   Ok = theSource >> aLocID;
129   if(!Ok) return 1;
130   Ok = theSource >> aCharOrient;
131   if(!Ok) return 1;
132   TopAbs_Orientation anOrient = CharToOrientation (aCharOrient);
133
134   theResult.TShape      (theShapeSet->Shape (aShapeID).TShape());//TShape
135   theResult.Location    (theShapeSet->Locations().Location (aLocID)); //Location
136   theResult.Orientation (anOrient);//Orientation
137   return 0;
138 }
139
140 //=======================================================================
141 //function : BinMNaming_NamedShapeDriver
142 //purpose  : Constructor
143 //=======================================================================
144
145 BinMNaming_NamedShapeDriver::BinMNaming_NamedShapeDriver
146                         (const Handle(Message_Messenger)& theMsgDriver)
147      : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()),
148        myShapeSet (NULL),
149        myWithTriangles (Standard_False),
150        myWithNormals  (Standard_False),
151        myIsQuickPart (Standard_False)
152 {
153 }
154
155 //=======================================================================
156 //function : NewEmpty
157 //purpose  : 
158 //=======================================================================
159
160 Handle(TDF_Attribute) BinMNaming_NamedShapeDriver::NewEmpty() const
161 {
162   return new TNaming_NamedShape();
163 }
164
165 //=======================================================================
166 //function : Paste
167 //purpose  : persistent => transient (retrieve)
168 //=======================================================================
169
170 Standard_Boolean BinMNaming_NamedShapeDriver::Paste
171                                 (const BinObjMgt_Persistent&  theSource,
172                                  const Handle(TDF_Attribute)& theTarget,
173                                  BinObjMgt_RRelocationTable&  ) const
174 {
175   Handle(TNaming_NamedShape) aTAtt= Handle(TNaming_NamedShape)::DownCast (theTarget);
176   Standard_Integer aNbShapes;
177   theSource >> aNbShapes;
178   TDF_Label aLabel = theTarget->Label ();
179   TNaming_Builder aBuilder (aLabel);
180   Standard_Integer aVer;
181   Standard_Boolean ok = theSource >> aVer;
182   if(!ok) return Standard_False;
183   aTAtt->SetVersion(aVer); //Version
184   Standard_Character aCharEvol;
185   ok = theSource >> aCharEvol;
186   if(!ok) return Standard_False;
187   TNaming_Evolution anEvol  = EvolutionToEnum (aCharEvol); //Evolution
188   aTAtt->SetVersion (anEvol);
189
190   BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_True);
191   Standard_IStream* aDirectStream = NULL;
192   if (myIsQuickPart) // enables direct reading of shapes from the stream
193     aDirectStream = const_cast<BinObjMgt_Persistent*>(&theSource)->GetIStream();
194
195   NCollection_List<TopoDS_Shape> anOldShapes, aNewShapes;
196   for (Standard_Integer i = 1; i <= aNbShapes; i++)
197   {
198     TopoDS_Shape anOldShape, aNewShape;
199
200     if (anEvol != TNaming_PRIMITIVE)
201     {
202       if (myIsQuickPart)
203         aShapeSet->Read (*aDirectStream, anOldShape);
204       else
205         if (TranslateFrom (theSource, anOldShape, static_cast<BinTools_ShapeSet*>(aShapeSet))) return Standard_False;
206     }
207
208     if (anEvol != TNaming_DELETE)
209     {
210       if (myIsQuickPart)
211         aShapeSet->Read (*aDirectStream, aNewShape);
212       else
213         if (TranslateFrom (theSource, aNewShape, static_cast<BinTools_ShapeSet*>(aShapeSet))) return Standard_False;
214     }
215
216     // Here we add shapes in reverse order because TNaming_Builder also adds them in reverse order.
217     anOldShapes.Prepend (anOldShape);
218     aNewShapes.Prepend (aNewShape);
219   }
220
221   for (NCollection_List<TopoDS_Shape>::Iterator anOldIt (anOldShapes), aNewIt (aNewShapes);
222       anOldIt.More() && aNewIt.More();
223       anOldIt.Next(), aNewIt.Next())
224   {
225     switch (anEvol)
226     {
227       case TNaming_PRIMITIVE:
228         aBuilder.Generated (aNewIt.Value ());
229         break;
230       case TNaming_GENERATED:
231         aBuilder.Generated (anOldIt.Value(), aNewIt.Value());
232         break;
233       case TNaming_MODIFY:
234         aBuilder.Modify (anOldIt.Value(), aNewIt.Value());
235         break;
236       case TNaming_DELETE:
237         aBuilder.Delete (anOldIt.Value());
238         break;
239       case TNaming_SELECTED:
240         aBuilder.Select (aNewIt.Value(), anOldIt.Value());
241         break;
242       case TNaming_REPLACE:
243         aBuilder.Modify (anOldIt.Value(), aNewIt.Value()); // for compatibility aBuilder.Replace(anOldShape, aNewShape);
244         break;
245       default:
246           throw Standard_DomainError("TNaming_Evolution:: Evolution Unknown");
247     }
248   }
249   return Standard_True;
250 }
251
252 //=======================================================================
253 //function : Paste
254 //purpose  : transient => persistent (store)
255 //=======================================================================
256
257 void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
258                                          BinObjMgt_Persistent&        theTarget,
259                                          BinObjMgt_SRelocationTable&  ) const
260 {
261   Handle(TNaming_NamedShape) aSAtt= Handle(TNaming_NamedShape)::DownCast(theSource);
262
263   //--------------------------------------------------------------
264   Standard_Integer NbShapes = 0;
265   for (TNaming_Iterator SItr (aSAtt); SItr.More (); SItr.Next ()) NbShapes++;
266   //--------------------------------------------------------------
267
268   BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_False);
269   TNaming_Evolution anEvol = aSAtt->Evolution();
270   
271   theTarget << NbShapes;
272   theTarget << aSAtt->Version();
273   theTarget << EvolutionToChar (anEvol);
274
275
276   Standard_OStream* aDirectStream = NULL;
277   if (myIsQuickPart) // enables direct writing of shapes to the stream
278     aDirectStream = theTarget.GetOStream();
279
280   Standard_Integer i = 1;  
281   for (TNaming_Iterator SIterator(aSAtt); SIterator.More(); SIterator.Next()) {
282     const TopoDS_Shape& anOldShape = SIterator.OldShape();
283     const TopoDS_Shape& aNewShape = SIterator.NewShape();
284     
285     if (anEvol != TNaming_PRIMITIVE)
286     {
287       if (myIsQuickPart)
288         aShapeSet->Write (anOldShape, *aDirectStream);
289       else
290         TranslateTo (anOldShape, theTarget, static_cast<BinTools_ShapeSet*>(aShapeSet));
291     }
292
293     if (anEvol != TNaming_DELETE)
294     {
295       if (myIsQuickPart)
296         aShapeSet->Write (aNewShape, *aDirectStream);
297       else
298         TranslateTo (aNewShape, theTarget, static_cast<BinTools_ShapeSet*>(aShapeSet));
299     }
300     
301     i++;
302   }
303
304 }
305
306
307 //=======================================================================
308 //function : WriteShapeSection
309 //purpose  : 
310 //=======================================================================
311
312 void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS,
313                                                      const Standard_Integer theDocVer,
314                                                      const Message_ProgressRange& theRange)
315 {
316   myIsQuickPart = Standard_False;
317   theOS << SHAPESET;
318   if (theDocVer >= TDocStd_FormatVersion_VERSION_11)
319   {
320     ShapeSet (Standard_False)->SetFormatNb (BinTools_FormatVersion_VERSION_4);
321   }
322   else
323   {
324     ShapeSet (Standard_False)->SetFormatNb (BinTools_FormatVersion_VERSION_1);
325   }
326   ShapeSet (Standard_False)->Write (theOS, theRange);
327   ShapeSet (Standard_False)->Clear();
328 }
329
330 //=======================================================================
331 //function : Clear
332 //purpose  : 
333 //=======================================================================
334
335 void BinMNaming_NamedShapeDriver::Clear()
336 {
337   if (myShapeSet)
338   {
339     myShapeSet->Clear();
340     delete myShapeSet;
341     myShapeSet = NULL;
342   }
343 }
344
345 //=======================================================================
346 //function : ReadShapeSection
347 //purpose  : 
348 //=======================================================================
349
350 void BinMNaming_NamedShapeDriver::ReadShapeSection (Standard_IStream& theIS,
351                                                     const Message_ProgressRange& theRange)
352 {
353   myIsQuickPart = Standard_False;
354   // check section title string; note that some versions of OCCT (up to 6.3.1) 
355   // might avoid writing shape section if it is empty
356   std::streamoff aPos = theIS.tellg();
357   TCollection_AsciiString aSectionTitle;
358   theIS >> aSectionTitle;
359   if(aSectionTitle.Length() > 0 && aSectionTitle == SHAPESET) {
360     BinTools_ShapeSetBase* aShapeSet = ShapeSet (Standard_True);
361     aShapeSet->Clear();
362     aShapeSet->Read (theIS, theRange);
363   }
364   else
365     theIS.seekg (aPos); // no shape section is present, try to return to initial point
366 }
367
368 //=======================================================================
369 //function : ShapeSet
370 //purpose  : 
371 //=======================================================================
372
373 BinTools_ShapeSetBase* BinMNaming_NamedShapeDriver::ShapeSet (const Standard_Boolean theReading)
374 {
375   if (!myShapeSet)
376   {
377     if (myIsQuickPart)
378     {
379       if (theReading)
380         myShapeSet = new BinTools_ShapeReader();
381       else
382         myShapeSet = new BinTools_ShapeWriter();
383     }
384     else
385       myShapeSet = new BinTools_ShapeSet();
386     myShapeSet->SetWithTriangles(myWithTriangles);
387     myShapeSet->SetWithNormals(myWithNormals);
388   }
389   return myShapeSet;
390 }
391
392 //=======================================================================
393 //function : GetShapesLocations
394 //purpose  : 
395 //=======================================================================
396 BinTools_LocationSet& BinMNaming_NamedShapeDriver::GetShapesLocations() const
397 {
398   BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_False);
399   return static_cast<BinTools_ShapeSet*>(aShapeSet)->ChangeLocations();
400 }