ba11d5f9c847719fc9117e143353c8aee7eef00d
[occt.git] / src / Units / Units_UnitsSystem.cxx
1 // Created on: 1993-10-22
2 // Created by: Gilles DEBARBOUILLE
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #define PRO8619 //GG_160697
18 //              Convertir correctement les unites translatees
19
20 #include <Units_UnitsSystem.ixx>
21 #include <Units.hxx>
22 #include <Units_UnitsDictionary.hxx>
23 #include <Units_QuantitiesSequence.hxx>
24 #include <Units_Explorer.hxx>
25 #include <Units_Quantity.hxx>
26 #include <Units_UnitsSequence.hxx>
27 #include <Units_UnitSentence.hxx>
28 #include <Units_Unit.hxx>
29 #include <Units_ShiftedUnit.hxx>
30 #include <Units_Token.hxx>
31 #include <Units_ShiftedToken.hxx>
32 #include <Resource_Manager.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <TColStd_HSequenceOfHAsciiString.hxx>
35 #include <Units_Operators.hxx>
36
37
38 //=======================================================================
39 //function : Units_UnitsSystem
40 //purpose  : 
41 //=======================================================================
42
43 Units_UnitsSystem::Units_UnitsSystem()
44 {
45   thequantitiessequence = new Units_QuantitiesSequence();
46   theactiveunitssequence = new TColStd_HSequenceOfInteger;
47 }
48
49
50 //=======================================================================
51 //function : Units_UnitsSystem
52 //purpose  : 
53 //=======================================================================
54
55 Units_UnitsSystem::Units_UnitsSystem(const Standard_CString aName,
56                                      const Standard_Boolean Verbose)
57 {
58   Handle(Resource_Manager) themanager = new Resource_Manager(aName,Verbose);
59
60   thequantitiessequence = new Units_QuantitiesSequence();
61   theactiveunitssequence = new TColStd_HSequenceOfInteger;
62 }
63
64
65 //=======================================================================
66 //function : QuantitiesSequence
67 //purpose  : 
68 //=======================================================================
69
70 Handle(Units_QuantitiesSequence) Units_UnitsSystem::QuantitiesSequence() const
71 {
72   return thequantitiessequence;
73 }
74
75
76 //=======================================================================
77 //function : ActiveUnitsSequence
78 //purpose  : 
79 //=======================================================================
80
81 Handle(TColStd_HSequenceOfInteger) Units_UnitsSystem::ActiveUnitsSequence() const
82 {
83   return theactiveunitssequence;
84 }
85
86
87 //=======================================================================
88 //function : Specify
89 //purpose  : 
90 //=======================================================================
91
92 void Units_UnitsSystem::Specify(const Standard_CString aquantity,const Standard_CString aunit)
93 {
94   Standard_Integer index;
95   Handle(Units_Unit) unit;
96   Handle(Units_UnitsSequence) unitssequence;
97   Handle(Units_Quantity) quantity;
98   Handle(Units_Quantity) thequantity;
99   Handle(Units_QuantitiesSequence) quantitiessequence;
100   TCollection_AsciiString quantityname;
101
102   Units_UnitSentence unitsentence(aunit);
103   if(!unitsentence.IsDone()) {
104     cout<<"Units_UnitsSystem::Specify : incorrect unit"<<endl;
105     return;
106   }
107   Handle(Units_Token) token = unitsentence.Evaluate();
108
109 #ifdef PRO8619
110   if( token->IsKind(STANDARD_TYPE(Units_ShiftedToken)) ) {
111     Handle(Units_ShiftedToken) stoken =
112         Handle(Units_ShiftedToken)::DownCast(token) ;
113     Handle(Units_ShiftedUnit) sunit;
114     unit = sunit = new Units_ShiftedUnit(aunit,aunit);
115     sunit->Value(stoken->Value());
116     sunit->Move(stoken->Move());
117   } else
118 #endif
119   {
120     unit = new Units_Unit(aunit,aunit);
121     unit->Value(token->Value());
122   }
123
124   for(index=1;index<=thequantitiessequence->Length();index++) {
125     quantity = thequantitiessequence->Value(index);
126     if(quantity == aquantity) {   
127       unit->Quantity(quantity);
128       quantity->Sequence()->Append(unit);
129       return;
130     }
131   }
132
133   quantity = Units::Quantity(aquantity);
134   
135 //  Units_NoSuchType_Raise_if(quantity.IsNull(),aquantity);
136   if( quantity.IsNull() ) {
137     cout<<"Warning: in Units_UnitsSystem : Units_NoSuchType '" << aquantity << "'" << endl;
138     return;
139   }
140   
141   unitssequence = new Units_UnitsSequence();
142   quantityname = quantity->Name();
143   thequantity = new Units_Quantity(quantityname.ToCString(),quantity->Dimensions(),unitssequence);
144   unit->Quantity(thequantity);
145   thequantitiessequence->Append(thequantity);
146   theactiveunitssequence->Append(0);
147   thequantity->Sequence()->Append(unit);
148 }
149
150
151 //=======================================================================
152 //function : Remove
153 //purpose  : 
154 //=======================================================================
155
156 void Units_UnitsSystem::Remove(const Standard_CString aquantity,
157                                const Standard_CString aunit)
158 {
159   Standard_Integer index1,index2;
160   Handle(Units_Unit) unit;
161   Handle(Units_UnitsSequence) unitssequence;
162   Handle(Units_Quantity) quantity;
163
164   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
165
166     quantity = thequantitiessequence->Value(index1);
167     if(quantity == aquantity) {
168
169       unitssequence = quantity->Sequence();
170       for(index2=1;index2<=unitssequence->Length();index2++) {
171
172         unit = unitssequence->Value(index2);
173         if(unit == aunit) {
174           unitssequence->Remove(index2);
175             
176           if(unitssequence->Length() == 0) {
177             thequantitiessequence->Remove(index1);
178             theactiveunitssequence->Remove(index1);
179           }
180           else {
181             if(theactiveunitssequence->Value(index1) == index2)
182               theactiveunitssequence->SetValue(index1,0);
183             else if(theactiveunitssequence->Value(index1) > index2)
184               theactiveunitssequence->SetValue(index1,theactiveunitssequence->Value(index1)-1);
185             return;
186           }
187         }
188       }
189       
190       Units_NoSuchUnit::Raise(aunit);
191       
192     }
193   }
194   
195   Units_NoSuchType::Raise(aquantity);
196 }
197
198
199 //=======================================================================
200 //function : Activate
201 //purpose  : 
202 //=======================================================================
203
204 void Units_UnitsSystem::Activate(const Standard_CString aquantity,
205                                  const Standard_CString aunit)
206 {
207   Standard_Integer index1,index2;
208   Handle(Units_Unit) unit;
209   Handle(Units_UnitsSequence) unitssequence;
210   Handle(Units_Quantity) quantity;
211
212   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
213     quantity = thequantitiessequence->Value(index1);
214     if(quantity == aquantity)   {
215       unitssequence = quantity->Sequence();
216       for(index2=1;index2<=thequantitiessequence->Length();index2++) {
217         unit = unitssequence->Value(index2);
218         if(unit == aunit) {
219           theactiveunitssequence->SetValue(index1,index2);
220           return;
221         }
222       }
223       Units_NoSuchUnit::Raise(aunit);
224     }
225   }
226
227   Units_NoSuchType::Raise(aquantity);
228 }
229
230
231 //=======================================================================
232 //function : Activates
233 //purpose  : 
234 //=======================================================================
235
236 void Units_UnitsSystem::Activates()
237 {
238   Standard_Integer index;
239   Handle(Units_UnitsSequence) unitssequence;
240   Handle(Units_Quantity) quantity;
241
242   for(index=1;index<=thequantitiessequence->Length();index++) {
243     quantity = thequantitiessequence->Value(index);
244     unitssequence = quantity->Sequence();
245     if( unitssequence->Length() > 0 ) {
246       theactiveunitssequence->SetValue(index,1);
247     }
248   }
249 }
250
251
252 //=======================================================================
253 //function : ActiveUnit
254 //purpose  : 
255 //=======================================================================
256
257 TCollection_AsciiString Units_UnitsSystem::ActiveUnit(const Standard_CString aquantity) const
258 {
259   Standard_Integer index1,index2;
260   Handle(Units_Unit) unit;
261   Handle(Units_UnitsSequence) unitssequence;
262   Handle(Units_Quantity) quantity;
263
264   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
265     quantity = thequantitiessequence->Value(index1);
266     if(quantity == aquantity) {
267       unitssequence = quantity->Sequence();
268       index2 = theactiveunitssequence->Value(index1);
269       if(index2)
270         return unitssequence->Value(index2)->SymbolsSequence()->Value(1)->String();
271       else {
272 #ifdef OCCT_DEBUG
273         cout<<" Pas d'unite active pour "<<aquantity<<endl;
274 #endif
275         return TCollection_AsciiString() ;
276       }
277     }
278   }
279
280   Units_NoSuchType::Raise(aquantity);
281   return TCollection_AsciiString() ;
282 }
283
284
285 //=======================================================================
286 //function : ConvertValueToUserSystem
287 //purpose  : 
288 //=======================================================================
289
290 Standard_Real Units_UnitsSystem::ConvertValueToUserSystem
291   (const Standard_CString aquantity,
292    const Standard_Real avalue,
293    const Standard_CString aunit) const
294 {
295   Units_UnitSentence unitsentence(aunit);
296   if(!unitsentence.IsDone()) {
297     cout<<"Units_UnitsSystem::ConvertValueToUserSystem : incorrect unit => return 0"<<endl;
298     return 0.;
299   }
300   return ConvertSIValueToUserSystem(aquantity,avalue*(unitsentence.Evaluate())->Value());
301 }
302
303
304 //=======================================================================
305 //function : ConvertSIValueToUserSystem
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Real Units_UnitsSystem::ConvertSIValueToUserSystem
310   (const Standard_CString aquantity,const Standard_Real avalue) const
311 {
312   Standard_Integer index,activeunit;
313   Handle(Units_UnitsSequence) unitssequence;
314   Handle(Units_Quantity) quantity;
315   Handle(Units_QuantitiesSequence) quantitiessequence;
316   Handle(Units_Unit) unit;
317   Handle(Units_ShiftedUnit) sunit;
318   Standard_Real uvalue,umove;
319
320   for(index=1;index<=thequantitiessequence->Length();index++) {
321     quantity = thequantitiessequence->Value(index);
322     if(quantity == aquantity) {
323       activeunit = theactiveunitssequence->Value(index);
324       if(activeunit) {
325         unitssequence = quantity->Sequence();
326         unit = unitssequence->Value(activeunit);
327 #ifdef PRO8619
328         if( unit->IsKind(STANDARD_TYPE(Units_ShiftedUnit)) ) {
329           sunit = Handle(Units_ShiftedUnit)::DownCast(unit) ;
330           uvalue = sunit->Value();
331           umove = sunit->Move();
332           return avalue/uvalue - umove;
333         }
334         else
335 #endif
336         {
337           uvalue = unit->Value();
338           return avalue/uvalue;
339         }
340       }
341       else {
342         return avalue;
343       }
344     }
345   }
346
347   quantity = Units::Quantity(aquantity);
348   
349   Units_NoSuchType_Raise_if(quantity.IsNull(),aquantity);
350
351   return avalue;
352 }
353
354
355 //=======================================================================
356 //function : ConvertUserSystemValueToSI
357 //purpose  : 
358 //=======================================================================
359
360 Standard_Real Units_UnitsSystem::ConvertUserSystemValueToSI
361   (const Standard_CString aquantity,const Standard_Real avalue) const
362 {
363   Standard_Integer index,activeunit;
364   Handle(Units_UnitsSequence) unitssequence;
365   Handle(Units_Quantity) quantity;
366   Handle(Units_QuantitiesSequence) quantitiessequence;
367   Handle(Units_Unit) unit;
368   Handle(Units_ShiftedUnit) sunit;
369   Standard_Real uvalue,umove;
370
371   for(index=1;index<=thequantitiessequence->Length();index++) {
372     quantity = thequantitiessequence->Value(index);
373     if(quantity == aquantity) {
374       activeunit = theactiveunitssequence->Value(index);
375       if(activeunit) {
376         unitssequence = quantity->Sequence();
377         unit = unitssequence->Value(activeunit);
378 #ifdef PRO8619
379         if( unit->IsKind(STANDARD_TYPE(Units_ShiftedUnit)) ) {
380           sunit = Handle(Units_ShiftedUnit)::DownCast(unit) ;
381           uvalue = sunit->Value();
382           umove = sunit->Move();
383           return avalue*(uvalue + umove);
384         } else
385 #endif
386         {
387           uvalue = unit->Value();
388           return avalue*uvalue;
389         }
390       }
391       else {
392         return avalue;
393       }
394     }
395   }
396
397   quantity = Units::Quantity(aquantity);
398   
399   Units_NoSuchType_Raise_if(quantity.IsNull(),aquantity);
400
401   return avalue;
402 }
403
404
405 //=======================================================================
406 //function : Dump
407 //purpose  : 
408 //=======================================================================
409
410 void Units_UnitsSystem::Dump() const
411 {
412   Handle(Standard_Transient) transient = This();
413   Handle(Units_UnitsSystem) unitssystem = *(Handle(Units_UnitsSystem)*)&transient;
414   Units_Explorer explorer(unitssystem);
415   cout<<" UNITSSYSTEM : "<<endl;
416   for(; explorer.MoreQuantity(); explorer.NextQuantity()) {
417     cout<<explorer.Quantity()<<endl;
418     for(; explorer.MoreUnit(); explorer.NextUnit())
419       cout<<"  "<<explorer.Unit()<<endl;
420   }
421 }
422
423
424 //=======================================================================
425 //function : IsEmpty
426 //purpose  : 
427 //=======================================================================
428
429 Standard_Boolean Units_UnitsSystem::IsEmpty() const
430 {
431   return (thequantitiessequence->Length() > 0) ? Standard_False : Standard_True;
432 }