Typica is a free program for professional coffee roasters. https://typica.us
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

units.w 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. @* Unit information.
  2. \noindent As unit information is required in several places, the enumeration
  3. listing these is moved to an external class. This derives from QObject only to
  4. take advantage of the meta-object system. There are no data members, however
  5. there are some convenience methods for working with unit data.
  6. @(units.h@>=
  7. #include <QObject>
  8. #ifndef TypicaUnitsIncluded
  9. #define TypicaUnitsIncluded
  10. class Units: public QObject@/
  11. {@/
  12. @[Q_OBJECT@]@;
  13. @[Q_ENUMS(Unit)@]@;
  14. public:@/
  15. enum Unit@/
  16. {@/
  17. Unitless = 0,
  18. Fahrenheit = 10144,
  19. Celsius = 10143,
  20. Kelvin = 10325,
  21. Rankine = 10145,
  22. Pound = 15876,
  23. Kilogram = 15877,
  24. Ounce = 1,
  25. Gram = 2
  26. };@/
  27. static double convertTemperature(double value, Unit fromUnit, Unit toUnit);
  28. static double convertRelativeTemperature(double value, Unit fromUnit, Unit toUnit);
  29. static bool isTemperatureUnit(Unit unit);
  30. static double convertWeight(double value, Unit fromUnit, Unit toUnit);
  31. static bool isWeightUnit(Unit unit);@/
  32. };
  33. #endif
  34. @ Methods are implemented in a separate file.
  35. @(units.cpp@>=
  36. #include "units.h"
  37. #include <QtDebug>
  38. @ The |isTemperatureUnit()| method may seem counter-intuitive while the enum
  39. only contains represenations of temperature measurements, but there are plans
  40. to extend this later to extend hardware support to devices that do not directly
  41. measure temperature values and also to support the measurement of properties
  42. that cannot sensibly be represented as temperatures such as fuel pressure and
  43. control settings.
  44. @(units.cpp@>=
  45. bool Units::isTemperatureUnit(Unit unit)
  46. {
  47. return (unit == Fahrenheit ||
  48. unit == Celsius ||
  49. unit == Kelvin ||
  50. unit == Rankine);
  51. }
  52. @ Temperature conversions can be performed by the |Units| class and should
  53. eliminate the need to have conversion code in multiple places. This method
  54. takes the measurement value, the unit that value is in, and the unit that we
  55. would like to have the measurement converted into. It returns the value as it
  56. would be expressed after unit conversion. A value of 0 is presently returned
  57. if either or both of the units to convert are not temperature units, however
  58. that behavior may change in the future. Any code activating that branch should
  59. be considered flawed.
  60. @(units.cpp@>=
  61. double Units::convertTemperature(double value, Unit fromUnit, Unit toUnit)@/
  62. {
  63. if(!(isTemperatureUnit(fromUnit) && isTemperatureUnit(toUnit)))
  64. {
  65. return 0;
  66. }
  67. switch(fromUnit)@/
  68. {@t\1@>@/
  69. case Fahrenheit:@/
  70. switch(toUnit)@/
  71. {@t\1@>@/
  72. case Fahrenheit:@/
  73. return value;
  74. break;
  75. case Celsius:@/
  76. return (value - 32.0) * 5.0 / 9.0;
  77. break;
  78. case Kelvin:@/
  79. return (value + 459.67) * 5.0 / 9.0;
  80. break;
  81. case Rankine:@/
  82. return value + 459.67;
  83. break;
  84. default:@/
  85. qDebug() << "Warning: Non-sensical unit conversion.";
  86. break;@t\2@>@/
  87. }@/
  88. break;
  89. case Celsius:
  90. switch(toUnit)@/
  91. {@t\1@>@/
  92. case Fahrenheit:@/
  93. return value * 9.0 / 5.0 + 32.0;
  94. break;
  95. case Celsius:@/
  96. return value;
  97. break;
  98. case Kelvin:@/
  99. return value + 273.15;
  100. break;
  101. case Rankine:@/
  102. return (value + 273.15) * 9.0 / 5.0;
  103. break;
  104. default:@/
  105. qDebug() << "Warning: Non-sensical unit conversion.";
  106. break;@t\2@>@/
  107. }@/
  108. break;
  109. case Kelvin:
  110. switch(toUnit)@/
  111. {@t\1@>@/
  112. case Fahrenheit:@/
  113. return value * 5.0 / 9.0 - 459.67;
  114. break;
  115. case Celsius:@/
  116. return value - 273.15;
  117. break;
  118. case Kelvin:@/
  119. return value;
  120. break;
  121. case Rankine:@/
  122. return value * 9.0 / 5.0;
  123. break;
  124. default:@/
  125. qDebug() << "Warning: Non-sensical unit conversion.";
  126. break;@t\2@>@/
  127. }@/
  128. break;
  129. case Rankine:
  130. switch(toUnit)@/
  131. {@t\1@>@/
  132. case Fahrenheit:@/
  133. return value - 457.67;
  134. break;
  135. case Celsius:@/
  136. return (value - 491.67) * 5.0 / 9.0;
  137. break;
  138. case Kelvin:@/
  139. return value * 5.0 / 9.0;
  140. break;
  141. case Rankine:@/
  142. return value;
  143. break;
  144. default:@/
  145. qDebug() << "Warning: Non-sensical unit conversion.";
  146. break;@t\2@>@/
  147. }@/
  148. break;
  149. default:@/
  150. return 0;
  151. break;@t\2@>@/
  152. }
  153. return 0;
  154. }
  155. @ Conversions are also provided for relative temperature measurements.
  156. @(units.cpp@>=
  157. double Units::convertRelativeTemperature(double value, Unit fromUnit, Unit toUnit)
  158. {
  159. if(!(isTemperatureUnit(fromUnit) && isTemperatureUnit(toUnit)))@/
  160. {
  161. return 0;
  162. }
  163. switch(fromUnit)@/
  164. {@t\1@>@/
  165. case Fahrenheit:
  166. switch(toUnit)@/
  167. {@t\1@>@/
  168. case Fahrenheit:@/
  169. return value;
  170. break;
  171. case Celsius:@/
  172. return value * (5.0 / 9.0);
  173. break;
  174. case Kelvin:@/
  175. return value * (5.0 / 9.0);
  176. break;
  177. case Rankine:@/
  178. return value;
  179. break;
  180. default:@/
  181. return 0;
  182. break;@t\2@>@/
  183. }
  184. break;
  185. case Celsius:
  186. switch(toUnit)@/
  187. {@t\1@>@/
  188. case Fahrenheit:@/
  189. return value * (9.0 / 5.0);
  190. break;
  191. case Celsius:@/
  192. return value;
  193. break;
  194. case Kelvin:@/
  195. return value;
  196. break;
  197. case Rankine:@/
  198. return value * (9.0 / 5.0);
  199. break;
  200. default:@/
  201. return 0;
  202. break;@t\2@>@/
  203. }
  204. break;
  205. case Kelvin:
  206. switch(toUnit)@/
  207. {@t\1@>@/
  208. case Fahrenheit:@/
  209. return value * (5.0 / 9.0);
  210. break;
  211. case Celsius:@/
  212. return value;
  213. break;
  214. case Kelvin:@/
  215. return value;
  216. break;
  217. case Rankine:@/
  218. return value * (9.0 / 5.0);
  219. break;
  220. default:@/
  221. return 0;
  222. break;@t\2@>@/
  223. }
  224. break;
  225. case Rankine:
  226. switch(toUnit)@/
  227. {@t\1@>@/
  228. case Fahrenheit:@/
  229. return value;
  230. break;
  231. case Celsius:@/
  232. return value * (5.0 / 9.0);
  233. break;
  234. case Kelvin:@/
  235. return value * (5.0 / 9.0);
  236. break;
  237. case Rankine:@/
  238. return value;
  239. break;
  240. default:
  241. return 0;
  242. break;@t\2@>@/
  243. }
  244. break;
  245. default:@/
  246. return 0;
  247. break;
  248. }
  249. return 0;
  250. }
  251. @ Units of force are handled similarly to units of temperature.
  252. @(units.cpp@>=
  253. double Units::convertWeight(double value, Unit fromUnit, Unit toUnit)
  254. {
  255. if(isWeightUnit(fromUnit) && isWeightUnit(toUnit))@/
  256. {
  257. switch(fromUnit)@/
  258. {@t\1@>@/
  259. case Pound:
  260. switch(toUnit)@/
  261. {@t\1@>@/
  262. case Pound:@/
  263. return value;
  264. break;
  265. case Kilogram:@/
  266. return value / 2.2;
  267. break;
  268. case Ounce:@/
  269. return value * 16.0;
  270. break;
  271. case Gram:@/
  272. return value / 0.0022;
  273. break;
  274. default:@/
  275. return 0;
  276. break;@t\2@>@/
  277. }
  278. break;
  279. case Kilogram:
  280. switch(toUnit)@/
  281. {@t\1@>@/
  282. case Pound:@/
  283. return value * 2.2;
  284. break;
  285. case Kilogram:@/
  286. return value;
  287. break;
  288. case Ounce:@/
  289. return value * 35.2;
  290. break;
  291. case Gram:@/
  292. return value * 1000.0;
  293. break;
  294. default:@/
  295. return 0;
  296. break;@t\2@>@/
  297. }
  298. break;
  299. case Ounce:
  300. switch(toUnit)@/
  301. {@t\1@>@/
  302. case Pound:@/
  303. return value / 16.0;
  304. break;
  305. case Kilogram:@/
  306. return value / 35.2;
  307. break;
  308. case Ounce:@/
  309. return value;
  310. break;
  311. case Gram:@/
  312. return value / 0.0352;
  313. break;
  314. default:@/
  315. return 0;
  316. break;@t\2@>@/
  317. }
  318. break;
  319. case Gram:
  320. switch(toUnit)@/
  321. {@t\1@>@/
  322. case Pound:@/
  323. return value * 0.0022;
  324. break;
  325. case Kilogram:@/
  326. return value / 1000.0;
  327. break;
  328. case Ounce:@/
  329. return value * 0.0352;
  330. break;
  331. case Gram:@/
  332. return value;
  333. break;
  334. default:@/
  335. return 0;
  336. break;@t\2@>@/
  337. }
  338. break;
  339. default:@/
  340. return 0;
  341. break;@t\2@>@/
  342. }
  343. }
  344. return 0;
  345. }
  346. bool Units::isWeightUnit(Unit unit)
  347. {
  348. return (unit == Pound ||
  349. unit == Kilogram ||
  350. unit == Ounce ||
  351. unit == Gram);
  352. }
  353. @ This class is exposed to the host environment. Note the lack of constructor.
  354. We do not wish to create any instances, just have access to the |Unit|
  355. enumeration and conversion methods.
  356. Unfortunately, marking a static method |Q_INVOKABLE| will not work as per Qt
  357. bug \#18840. There seems to be no intention to correct this deficiency so
  358. instead of having something that just works, we must resort to the following
  359. hackery.
  360. @<Function prototypes for scripting@>=
  361. QScriptValue Units_convertTemperature(QScriptContext *context, QScriptEngine *engine);
  362. QScriptValue Units_convertRelativeTemperature(QScriptContext *context,
  363. QScriptEngine *engine);
  364. QScriptValue Units_isTemperatureUnit(QScriptContext *context, QScriptEngine *engine);
  365. QScriptValue Units_convertWeight(QScriptContext *context, QScriptEngine *engine);
  366. QScriptValue Units_isWeightUnit(QScriptContext *context, QScriptEngine *engine);
  367. @ These functions are added as properties for the host environment.
  368. @<Set up the scripting engine@>=
  369. value = engine->newQMetaObject(&Units::staticMetaObject);
  370. value.setProperty("convertTemperature", engine->newFunction(Units_convertTemperature));
  371. value.setProperty("convertRelativeTemperature",
  372. engine->newFunction(Units_convertRelativeTemperature));
  373. value.setProperty("isTemperatureUnit", engine->newFunction(Units_isTemperatureUnit));
  374. value.setProperty("convertWeight", engine->newFunction(Units_convertWeight));
  375. value.setProperty("isWeightUnit", engine->newFunction(Units_isWeightUnit));
  376. engine->globalObject().setProperty("Units", value);
  377. @ The implementation of these functions is trivial.
  378. @<Functions for scripting@>=
  379. QScriptValue Units_convertTemperature(QScriptContext *context, QScriptEngine *)
  380. {
  381. return QScriptValue(Units::convertTemperature(argument<double>(0, context),
  382. argument<Units::Unit>(1, context),
  383. argument<Units::Unit>(2, context)));
  384. }
  385. QScriptValue Units_convertRelativeTemperature(QScriptContext *context,
  386. QScriptEngine *)
  387. {
  388. return QScriptValue(Units::convertRelativeTemperature(
  389. argument<double>(0, context),
  390. argument<Units::Unit>(1, context),
  391. argument<Units::Unit>(2, context)));
  392. }
  393. QScriptValue Units_isTemperatureUnit(QScriptContext *context, QScriptEngine *)
  394. {
  395. return QScriptValue(Units::isTemperatureUnit(argument<Units::Unit>(0, context)));
  396. }
  397. QScriptValue Units_convertWeight(QScriptContext *context, QScriptEngine *)
  398. {
  399. return QScriptValue(Units::convertWeight(argument<double>(0, context),
  400. argument<Units::Unit>(1, context),
  401. argument<Units::Unit>(2, context)));
  402. }
  403. QScriptValue Units_isWeightUnit(QScriptContext *context, QScriptEngine *)
  404. {
  405. return QScriptValue(Units::isWeightUnit(argument<Units::Unit>(0, context)));
  406. }
  407. @ To pass unit data in some circumstances, the inner enumeration must be
  408. registered as a meta-type with script conversions.
  409. @<Class declarations@>=
  410. Q_DECLARE_METATYPE(Units::Unit)
  411. @ A pair of conversion methods is required.
  412. @<Function prototypes for scripting@>=
  413. QScriptValue Unit_toScriptValue(QScriptEngine *engine, const Units::Unit &value);
  414. void Unit_fromScriptValue(const QScriptValue &sv, Units::Unit &value);
  415. @ These are implemented thusly.
  416. @<Functions for scripting@>=
  417. QScriptValue Unit_toScriptValue(QScriptEngine *engine, const Units::Unit &value)
  418. {
  419. return engine->newVariant(QVariant(value));
  420. }
  421. void Unit_fromScriptValue(const QScriptValue &sv, Units::Unit &value)
  422. {
  423. value = sv.toVariant().value<Units::Unit>();
  424. }
  425. @ These conversion functions are registered.
  426. @<Set up the scripting engine@>=
  427. qScriptRegisterMetaType(engine, Unit_toScriptValue, Unit_fromScriptValue);