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