0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / BinMNaming / BinMNaming_NamingDriver.cxx
1 // Created on: 2004-05-13
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 <BinMDF_ADriver.hxx>
18 #include <BinMNaming.hxx>
19 #include <BinMNaming_NamingDriver.hxx>
20 #include <BinObjMgt_Persistent.hxx>
21 #include <BinObjMgt_RRelocationTable.hxx>
22 #include <BinObjMgt_SRelocationTable.hxx>
23 #include <Message_Messenger.hxx>
24 #include <Standard_Type.hxx>
25 #include <TCollection_AsciiString.hxx>
26 #include <TCollection_ExtendedString.hxx>
27 #include <TColStd_Array1OfInteger.hxx>
28 #include <TDF_Attribute.hxx>
29 #include <TDF_Tool.hxx>
30 #include <TNaming_Iterator.hxx>
31 #include <TNaming_ListIteratorOfListOfNamedShape.hxx>
32 #include <TNaming_NamedShape.hxx>
33 #include <TNaming_NameType.hxx>
34 #include <TNaming_Naming.hxx>
35 #include <TopAbs_ShapeEnum.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(BinMNaming_NamingDriver,BinMDF_ADriver)
38
39 #define  NULL_ENTRY "0:0"
40 #define  OBSOLETE_NUM (int)sizeof(Standard_Integer)
41
42 //=======================================================================
43 // 'Z' - is reserved for: forfidden to use
44 //=======================================================================
45 static Standard_Character NameTypeToChar(const TNaming_NameType theNameType)
46 {
47   switch(theNameType) {
48     case TNaming_UNKNOWN      : return 'N';
49     case TNaming_IDENTITY     : return 'I';
50     case TNaming_MODIFUNTIL   : return 'M';
51     case TNaming_GENERATION   : return 'G';
52     case TNaming_INTERSECTION : return 'S';
53     case TNaming_UNION        : return 'U';
54     case TNaming_SUBSTRACTION : return 'B';
55     case TNaming_CONSTSHAPE   : return 'C';
56     case TNaming_FILTERBYNEIGHBOURGS : return 'F';
57     case TNaming_ORIENTATION  : return 'O'; 
58     case TNaming_WIREIN       : return 'W';
59     case TNaming_SHELLIN      : return 'H';
60   default:
61     throw Standard_DomainError("TNaming_NameType:: Name Type Unknown");
62   }
63 }
64
65 //=======================================================================
66 static TNaming_NameType CharTypeToName(const Standard_Character theCharType)
67 {
68   switch(theCharType) {
69     case 'N'  : return TNaming_UNKNOWN;
70     case 'I'  : return TNaming_IDENTITY;
71     case 'M'  : return TNaming_MODIFUNTIL;
72     case 'G'  : return TNaming_GENERATION;
73     case 'S'  : return TNaming_INTERSECTION;
74     case 'U'  : return TNaming_UNION;
75     case 'B'  : return TNaming_SUBSTRACTION;
76     case 'C'  : return TNaming_CONSTSHAPE;
77     case 'F'  : return TNaming_FILTERBYNEIGHBOURGS;
78     case 'O'  : return TNaming_ORIENTATION;
79     case 'W'  : return TNaming_WIREIN;
80     case 'H'  : return TNaming_SHELLIN;
81   default:
82     throw Standard_DomainError("TNaming_NameType:: Name Type Unknown");
83   }
84 }
85
86 //=======================================================================
87 static Standard_Character ShapeTypeToChar(const TopAbs_ShapeEnum theShapeType)
88 {
89   switch (theShapeType)
90     {
91     case TopAbs_COMPOUND  : return 'C';
92     case TopAbs_COMPSOLID : return 'O';
93     case TopAbs_SOLID     : return 'S';
94     case TopAbs_SHELL     : return 'H';
95     case TopAbs_FACE      : return 'F';
96     case TopAbs_WIRE      : return 'W';
97     case TopAbs_EDGE      : return 'E';
98     case TopAbs_VERTEX    : return 'V';
99     case TopAbs_SHAPE     : return 'A';
100     }
101   return 'A'; // To avoid compilation error message.
102 }
103 //=======================================================================
104 static TopAbs_ShapeEnum CharToShapeType(const Standard_Character theCharType)
105 {
106   switch (theCharType)
107     {
108     case 'C' : return TopAbs_COMPOUND;
109     case 'O' : return TopAbs_COMPSOLID;
110     case 'S' : return TopAbs_SOLID;
111     case 'H' : return TopAbs_SHELL;
112     case 'F' : return TopAbs_FACE;
113     case 'W' : return TopAbs_WIRE;
114     case 'E' : return TopAbs_EDGE;
115     case 'V' : return TopAbs_VERTEX;
116     case 'A' : return TopAbs_SHAPE;
117     }
118   return TopAbs_SHAPE; // To avoid compilation error message.
119 }
120 //=======================================================================
121 //function : BinMNaming_NamingDriver
122 //purpose  : Constructor
123 //=======================================================================
124
125 BinMNaming_NamingDriver::BinMNaming_NamingDriver
126                         (const Handle(Message_Messenger)& theMsgDriver)
127      : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_Naming)->Name())
128 {
129 }
130
131 //=======================================================================
132 //function : NewEmpty
133 //purpose  : 
134 //=======================================================================
135
136 Handle(TDF_Attribute) BinMNaming_NamingDriver::NewEmpty() const
137 {
138   return new TNaming_Naming();
139 }
140
141 //=======================================================================
142 //function : Paste
143 //purpose  : persistent -> transient (retrieve)
144 //=======================================================================
145
146 Standard_Boolean BinMNaming_NamingDriver::Paste
147                                 (const BinObjMgt_Persistent&  theSource,
148                                  const Handle(TDF_Attribute)& theTarget,
149                                  BinObjMgt_RRelocationTable&  theRelocTable) const
150 {
151   Handle(TNaming_Naming) anAtt = Handle(TNaming_Naming)::DownCast(theTarget);
152   if(anAtt.IsNull()) return Standard_False;
153
154   TNaming_Name& aName = anAtt->ChangeName();
155   TCollection_ExtendedString aMsg;
156 //1. NameType
157   Standard_Character aValue;
158   Standard_Boolean ok = theSource >> aValue;
159   Standard_Boolean aNewF = Standard_False;
160   if (ok) {
161     if(aValue == 'Z') {      // new format
162       aNewF = Standard_True;
163       ok = theSource >> aValue; //skip the sign & get NameType
164       if(!ok) return ok;
165     }
166
167     aName.Type(CharTypeToName(aValue));
168
169 //2. ShapeType    
170     ok = theSource >> aValue;
171     if (ok) {
172       aName.ShapeType(CharToShapeType(aValue));
173       
174 //3. Args
175       Standard_Integer aNbArgs=0;
176       Standard_Integer anIndx;
177       Handle(TNaming_NamedShape) aNS;
178       ok = theSource >> aNbArgs;
179       if (ok) {
180         if(aNbArgs > 0) {
181           Standard_Integer i;
182           // read array
183           for(i=1; i<=aNbArgs;i++) {
184             if(!aNewF && i > OBSOLETE_NUM) break;//interrupt reading as old format can have only 4 items
185             ok = theSource >> anIndx;
186             if (!ok)
187               break;
188             else {
189               if (theRelocTable.IsBound(anIndx))
190                 aNS = Handle(TNaming_NamedShape)::DownCast(theRelocTable.Find(anIndx));
191               else {
192                 aNS = new TNaming_NamedShape;
193                 theRelocTable.Bind(anIndx, aNS);
194               }
195               aName.Append(aNS);
196             }
197           }
198           //patch to release the rest of items  
199           if(!aNewF && aNbArgs < OBSOLETE_NUM) {    
200             for(i = aNbArgs+1;i <= OBSOLETE_NUM;i++)
201               theSource >> anIndx;
202           }
203         }
204 //4. StopNS
205         ok = theSource >> anIndx;
206         if(ok) {
207           if(anIndx > 0) {
208             if (theRelocTable.IsBound(anIndx))
209               aNS = Handle(TNaming_NamedShape)::DownCast(theRelocTable.Find(anIndx));
210             else
211             {
212               aNS = new TNaming_NamedShape;
213               theRelocTable.Bind(anIndx, aNS);
214             }
215             aName.StopNamedShape(aNS);  
216           }
217
218 //5. Index
219           ok = theSource >> anIndx;
220           if(ok) 
221             aName.Index(anIndx);
222           else {
223             aMsg = TCollection_ExtendedString("BinMNaming_NamingDriver: "
224                                               "Cannot retrieve Index of Name");
225             myMessageDriver->Send (aMsg, Message_Warning); 
226           }
227         } else {
228           aMsg = TCollection_ExtendedString("BinMNaming_NamingDriver: "
229                                             "Cannot retrieve reference on "
230                                             "StopNamedShape");
231           myMessageDriver->Send (aMsg, Message_Warning); 
232         }
233       } else {
234         aMsg = TCollection_ExtendedString("BinMNaming_NamingDriver: "
235                                           "Cannot retrieve reference on "
236                                           "Arguments of Name");
237         myMessageDriver->Send (aMsg, Message_Warning);
238           }
239
240     if(theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() > 3) {
241         TCollection_AsciiString entry;
242         ok = theSource >> entry;
243         if(ok) {
244 #ifdef OCCT_DEBUG
245           std::cout << "NamingDriver:: Retrieved Context Label = " << entry << " Ok = " << theSource.IsOK()  <<std::endl;
246 #endif
247          
248 //6. context label
249           if(!entry.IsEmpty() && !entry.IsEqual(TCollection_AsciiString(NULL_ENTRY))) 
250             {
251               TDF_Label tLab; // Null label.
252               TDF_Tool::Label(anAtt->Label().Data(),entry, tLab, Standard_True);
253               if (!tLab.IsNull()) 
254                 aName.ContextLabel(tLab);
255             }
256         }
257     if(theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() > 4 && 
258        theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() < 7) {
259           // Orientation processing - converting from old format
260       Handle(TNaming_NamedShape) aNShape;
261       if(anAtt->Label().FindAttribute(TNaming_NamedShape::GetID(), aNShape)) {
262             //const TDF_Label& aLab = aNS->Label();
263         TNaming_Iterator itL (aNShape);
264         for (; itL.More(); itL.Next()) {
265           const TopoDS_Shape& S = itL.NewShape();
266           if (S.IsNull()) continue;
267           if(aNShape->Evolution() == TNaming_SELECTED) {
268             if (itL.More() && itL.NewShape().ShapeType() != TopAbs_VERTEX &&
269                   !itL.OldShape().IsNull() && itL.OldShape().ShapeType() == TopAbs_VERTEX ) {//OR-N
270               TopAbs_Orientation OrientationToApply = itL.OldShape().Orientation();
271               aName.Orientation(OrientationToApply);
272                         }
273                   }
274                 }
275           }
276         }
277     if(theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() > 6) {
278       ok = theSource >> anIndx;
279       TopAbs_Orientation OrientationToApply(TopAbs_FORWARD);
280       if(ok) {
281         OrientationToApply = (TopAbs_Orientation)anIndx;
282                 aName.Orientation(OrientationToApply);
283 #ifdef OCCT_DEBUG
284             std::cout << "NamingDriver:: Retrieved Orientation = " << OrientationToApply << " Ok = " << theSource.IsOK()  <<std::endl;
285 #endif
286           } else {
287           aMsg = TCollection_ExtendedString("BinMNaming_NamingDriver: "
288                                             "Cannot retrieve Name Orientation ");
289           myMessageDriver->Send (aMsg, Message_Warning);
290           }
291         }
292         }
293 #ifdef OCCT_DEBUG
294               std::cout << "Current Document Format Version = " << theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() <<std::endl;      
295 #endif
296         }
297   }
298   return ok;
299 }
300
301 //=======================================================================
302 //function : Paste
303 //purpose  : transient -> persistent (store)
304 //=======================================================================
305
306 void BinMNaming_NamingDriver::Paste (const Handle(TDF_Attribute)&  theSource,
307                                        BinObjMgt_Persistent&       theTarget,
308                                        BinObjMgt_SRelocationTable& theRelocTable) const
309 {
310   Handle(TNaming_Naming) anAtt = Handle(TNaming_Naming)::DownCast(theSource);
311   const TNaming_Name& aName = anAtt->GetName();
312
313 //0. add the sign of new format (to fix misprint with Array size)
314   theTarget.PutCharacter('Z');
315
316 //1. << NameType to Char
317   theTarget << NameTypeToChar(aName.Type());
318
319 //2. << ShapeType to Char
320   theTarget << ShapeTypeToChar(aName.ShapeType());
321
322 //3. Keep Args
323   Standard_Integer anIndx;
324   Standard_Integer aNbArgs = aName.Arguments().Extent();
325   theTarget << aNbArgs; // keep Number
326   if (aNbArgs > 0) {
327     Standard_Integer i=0;
328     TColStd_Array1OfInteger anArray(1, aNbArgs);
329     //fill array
330     for (TNaming_ListIteratorOfListOfNamedShape it (aName.Arguments()); it.More(); it.Next()) {
331       Handle(TNaming_NamedShape) anArg = it.Value();
332       anIndx = 0; i++;
333       if (!anArg.IsNull()) {
334         anIndx = theRelocTable.FindIndex(anArg);
335         if (anIndx == 0)
336           anIndx = theRelocTable.Add(anArg);
337       }
338       anArray.SetValue(i, anIndx);
339     }
340     
341     theTarget.PutIntArray ((BinObjMgt_PInteger) &anArray.Value(1), aNbArgs); // keep Array
342   }
343
344 //4. keep StopNS
345   Handle(TNaming_NamedShape) aStopNS = aName.StopNamedShape();
346   if (!aStopNS.IsNull()) {
347     anIndx = theRelocTable.FindIndex(aStopNS);
348     if (anIndx == 0)
349       anIndx = theRelocTable.Add(aStopNS);
350   } else 
351     anIndx = 0;
352   theTarget << anIndx;
353
354 //5. keep Index
355   theTarget << aName.Index();
356
357 //6. keep context label
358   TCollection_AsciiString entry(NULL_ENTRY);
359   if(!aName.ContextLabel().IsNull())
360     TDF_Tool::Entry(aName.ContextLabel(), entry);
361   theTarget << entry;
362
363 //7. keep Orientation
364   theTarget << (Standard_Integer)aName.Orientation();
365
366 }