Salome HOME
Issues #2150 and #2151: Frequently appeared "Conflicting constraints" message for...
[modules/shaper.git] / src / Model / Model_AttributeTables.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_AttributeTables.cpp
4 // Created:     14 Nov 2016
5 // Author:      Mikhail Ponikarov
6
7 #include "Model_AttributeTables.h"
8
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_Object.h>
11
12 #include <TColStd_ListIteratorOfListOfInteger.hxx>
13 #include <TDataStd_RealArray.hxx>
14 #include <TDataStd_BooleanArray.hxx>
15 #include <TDataStd_IntegerArray.hxx>
16 #include <TDataStd_ExtStringArray.hxx>
17
18 #include <TColStd_HArray1OfReal.hxx>
19 #include <TColStd_HArray1OfByte.hxx>
20 #include <TColStd_HArray1OfInteger.hxx>
21 #include <TColStd_HArray1OfExtendedString.hxx>
22
23 #include <string>
24
25 // returns the array attribute GUID for the given type
26 #define MY_ARRAY_ID(type) \
27 ((type) == ModelAPI_AttributeTables::DOUBLE ? TDataStd_RealArray::GetID(): \
28 ((type) == ModelAPI_AttributeTables::BOOLEAN ? TDataStd_BooleanArray::GetID(): \
29 ((type) == ModelAPI_AttributeTables::INTEGER? TDataStd_IntegerArray::GetID(): \
30 TDataStd_ExtStringArray::GetID())))
31
32 int Model_AttributeTables::rows()
33 {
34   return myRows;
35 }
36
37 int Model_AttributeTables::columns()
38 {
39   return myCols;
40 }
41
42 int Model_AttributeTables::tables()
43 {
44   return myTables;
45 }
46
47 void Model_AttributeTables::setSize(const int theRows, const int theColumns, const int theTables)
48 {
49   if (theRows != myRows || theColumns != myCols || theTables != myTables) {
50     owner()->data()->sendAttributeUpdated(this);
51     int aSize = myRows * myCols * myTables;
52     int aNewSize = theRows * theColumns * theTables;
53     if (aSize == 0 && aNewSize == 0) {
54       // nothing to do
55     } else if (aNewSize == 0) {
56       // remove old array
57       myLab.ForgetAttribute(MY_ARRAY_ID(myType));
58     } else {
59       // prepare new arrays
60       Handle(TColStd_HArray1OfReal) anOldDouble, aNewDouble =
61         (myType == ModelAPI_AttributeTables::DOUBLE) ?
62         new TColStd_HArray1OfReal(0, aNewSize - 1) : Handle(TColStd_HArray1OfReal)();
63       bool* anOldBool = 0; // an not work with internal arrays because of different indexing
64       Handle(TDataStd_BooleanArray) aBoolArray; // an existing array
65       Handle(TColStd_HArray1OfInteger) anOldInt, aNewInt =
66         (myType == ModelAPI_AttributeTables::INTEGER) ?
67         new TColStd_HArray1OfInteger(0, aNewSize - 1) : Handle(TColStd_HArray1OfInteger)();
68       Handle(TColStd_HArray1OfExtendedString) anOldStr, aNewStr =
69         (myType == ModelAPI_AttributeTables::STRING) ?
70         new TColStd_HArray1OfExtendedString(0, aNewSize - 1) :
71         Handle(TColStd_HArray1OfExtendedString)();
72       if (aSize != 0) { // copy the previous values into new positions, otherwise default values
73         Handle(TDF_Attribute) anArray;
74         myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
75         switch(myType) {
76         case ModelAPI_AttributeTables::DOUBLE:
77           anOldDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Array();
78           break;
79         case ModelAPI_AttributeTables::BOOLEAN: {
80           anOldBool = new bool[aSize];
81           aBoolArray = Handle(TDataStd_BooleanArray)::DownCast(anArray);
82           for(int a = 0; a < aSize; a++)
83             anOldBool[a] = aBoolArray->Value(a);
84           aBoolArray->Init(0, aNewSize - 1);
85           break;
86         }
87         case ModelAPI_AttributeTables::INTEGER:
88           anOldInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Array();
89           break;
90         case ModelAPI_AttributeTables::STRING:
91           anOldStr = Handle(TDataStd_ExtStringArray)::DownCast(anArray)->Array();
92           break;
93         }
94       } else if (myType == ModelAPI_AttributeTables::BOOLEAN) {
95         aBoolArray = TDataStd_BooleanArray::Set(myLab, 0, aNewSize - 1);
96       }
97       for(int aTable = 0; aTable < theTables; aTable++) {
98         for(int aColumn = 0; aColumn < theColumns; aColumn++) {
99           for(int aRow = 0; aRow < theRows; aRow++) {
100             int anOldIndex, anIndex = aTable * theRows * theColumns + aRow * theColumns + aColumn;
101             bool aRestore = aTable < myTables && aColumn < myCols && aRow < myRows;
102             if (aRestore)
103               anOldIndex = aTable * myRows * myCols + aRow * myCols + aColumn;
104             switch(myType) {
105             case ModelAPI_AttributeTables::DOUBLE: {
106               aNewDouble->SetValue(anIndex, aRestore ? anOldDouble->Value(anOldIndex) : 0.);
107               break;
108             }
109             case ModelAPI_AttributeTables::BOOLEAN: {
110               aBoolArray->SetValue(anIndex, aRestore ? anOldBool[anOldIndex] : Standard_False);
111               break;
112             }
113             case ModelAPI_AttributeTables::INTEGER: {
114               aNewInt->SetValue(anIndex, aRestore ? anOldInt->Value(anOldIndex) : 0);
115               break;
116             }
117             case ModelAPI_AttributeTables::STRING: {
118               aNewStr->SetValue(anIndex, aRestore ? anOldStr->Value(anOldIndex) : "");
119               break;
120             }
121             }
122           }
123         }
124       }
125       // store the new array
126       switch(myType) {
127       case ModelAPI_AttributeTables::DOUBLE:
128         TDataStd_RealArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewDouble);
129         break;
130       case ModelAPI_AttributeTables::BOOLEAN: // nothing to do: array was set in "else" of restore
131         break;
132       case ModelAPI_AttributeTables::INTEGER:
133         TDataStd_IntegerArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewInt);
134         break;
135       case ModelAPI_AttributeTables::STRING:
136         TDataStd_ExtStringArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewStr);
137         break;
138       }
139     }
140     // store the new sizes
141     myRows = theRows;
142     myCols = theColumns;
143     myTables = theTables;
144     myProp->Clear();
145     myProp->Append(int(myType)); // default
146     myProp->Append(myTables);
147     myProp->Append(myRows);
148     myProp->Append(myCols);
149     owner()->data()->sendAttributeUpdated(this);
150   }
151 }
152
153 void Model_AttributeTables::setType(ModelAPI_AttributeTables::ValueType theType)
154 {
155   if (myType != theType) {
156     // remove the old attr
157     int aSize = myRows * myCols * myTables;
158     if (aSize != 0) {
159       myLab.ForgetAttribute(MY_ARRAY_ID(myType));
160       myType = theType;
161       int aTables = myTables;
162       myTables = 0; // to let setSize know that there is no old array
163       setSize(myRows, myCols, aTables);
164     } else {
165       myType = theType;
166       owner()->data()->sendAttributeUpdated(this);
167     }
168   }
169 }
170
171 const ModelAPI_AttributeTables::ValueType& Model_AttributeTables::type() const
172 {
173   return myType;
174 }
175
176 void Model_AttributeTables::setValue(const ModelAPI_AttributeTables::Value theValue,
177   const int theRow, const int theColumn, const int theTable)
178 {
179   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
180   Handle(TDF_Attribute) anArray;
181   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
182   switch(myType) {
183   case ModelAPI_AttributeTables::DOUBLE: {
184     Handle(TDataStd_RealArray)::DownCast(anArray)->SetValue(anIndex, theValue.myDouble);
185     break;
186   }
187   case ModelAPI_AttributeTables::BOOLEAN: {
188     Handle(TDataStd_BooleanArray)::DownCast(anArray)->SetValue(anIndex, theValue.myBool);
189     break;
190   }
191   case ModelAPI_AttributeTables::INTEGER: {
192     Handle(TDataStd_IntegerArray)::DownCast(anArray)->SetValue(anIndex, theValue.myInt);
193     break;
194   }
195   case ModelAPI_AttributeTables::STRING: {
196     Handle(TDataStd_ExtStringArray)::DownCast(anArray)->SetValue(anIndex, theValue.myStr.c_str());
197     break;
198   }
199   }
200   owner()->data()->sendAttributeUpdated(this);
201 }
202
203 ModelAPI_AttributeTables::Value Model_AttributeTables::value(
204   const int theRow, const int theColumn, const int theTable)
205 {
206   ModelAPI_AttributeTables::Value aResult;
207   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
208   Handle(TDF_Attribute) anArray;
209   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
210   switch(myType) {
211   case ModelAPI_AttributeTables::DOUBLE: {
212     aResult.myDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Value(anIndex);
213     break;
214   }
215   case ModelAPI_AttributeTables::BOOLEAN: {
216     aResult.myBool = Handle(TDataStd_BooleanArray)::DownCast(anArray)->Value(anIndex) ==
217       Standard_True;
218     break;
219   }
220   case ModelAPI_AttributeTables::INTEGER: {
221     aResult.myInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Value(anIndex);
222     break;
223   }
224   case ModelAPI_AttributeTables::STRING: {
225     aResult.myStr = TCollection_AsciiString(Handle(TDataStd_ExtStringArray)::DownCast(anArray)->
226       Value(anIndex)).ToCString();
227     break;
228   }
229   }
230   return aResult;
231 }
232
233 std::string Model_AttributeTables::valueStr(
234     const int theRow, const int theColumn, const int theTable)
235 {
236   std::ostringstream aStr;
237   switch(myType) {
238   case ModelAPI_AttributeTables::DOUBLE:
239     aStr<<value(theRow, theColumn, theTable).myDouble;
240     break;
241   case ModelAPI_AttributeTables::BOOLEAN:
242     aStr<<(value(theRow, theColumn, theTable).myBool ? "True" :"False");
243     break;
244   case ModelAPI_AttributeTables::INTEGER:
245     aStr<<value(theRow, theColumn, theTable).myInt;
246     break;
247   case ModelAPI_AttributeTables::STRING:
248     aStr<<value(theRow, theColumn, theTable).myStr;
249     break;
250   }
251   return aStr.str();
252 }
253
254 //==================================================================================================
255 Model_AttributeTables::Model_AttributeTables(TDF_Label& theLabel)
256 {
257   myLab = theLabel;
258   reinit();
259 }
260
261 void Model_AttributeTables::reinit()
262 {
263   // check the attribute could be already presented in this doc (after load document)
264   myIsInitialized =
265     myLab.FindAttribute(TDataStd_IntegerList::GetID(), myProp) == Standard_True;
266   if (!myIsInitialized) {
267     myProp = TDataStd_IntegerList::Set(myLab);
268     myProp->Append(int(Model_AttributeTables::DOUBLE)); // default
269     myProp->Append(0);
270     myProp->Append(0);
271     myProp->Append(0);
272   }
273   TColStd_ListIteratorOfListOfInteger aListIter(myProp->List());
274   myType = ModelAPI_AttributeTables::ValueType(aListIter.Value());
275   aListIter.Next();
276   myTables = aListIter.Value();
277   aListIter.Next();
278   myRows = aListIter.Value();
279   aListIter.Next();
280   myCols = aListIter.Value();
281 }