convutil.inc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2004 by Marco van de Voort
  4. member of the Free Pascal development team.
  5. An implementation for unit convutils, which converts between
  6. units and simple combinations of them.
  7. Based on a guessed interface derived from some programs on the web. (Like
  8. Marco Cantu's EuroConv example), so things can be a bit Delphi
  9. incompatible. Also part on Delphibasics.co.uk.
  10. Quantities are mostly taken from my HP48g/gx or the unix units program
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY;without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. unit convutils;
  16. interface
  17. {$mode objfpc}
  18. {$H+}
  19. {$ifndef FPUNONE}
  20. Type TConvType = type Integer;
  21. TConvFamily = type Integer;
  22. TConvFamilyArray = array of TConvFamily;
  23. TConvTypeArray = array of TConvType;
  24. TConversionProc = function(const AValue: Double): Double;
  25. TConvUtilFloat = double;
  26. Function RegisterConversionFamily(Const S : String):TConvFamily;
  27. Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
  28. function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat;
  29. function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat;
  30. function ConvFamilyToDescription(const AFamily: TConvFamily): string;
  31. function ConvTypeToDescription(const AType: TConvType): string;
  32. procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
  33. procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
  34. Type
  35. TConvTypeInfo = Class(Tobject)
  36. private
  37. FDescription : String;
  38. FConvFamily : TConvFamily;
  39. FConvType : TConvType;
  40. public
  41. Constructor Create(Const AConvFamily : TConvFamily;const ADescription:String);
  42. function ToCommon(const AValue: Double) : Double; virtual; abstract;
  43. function FromCommon(const AValue: Double) : Double; virtual; abstract;
  44. property ConvFamily : TConvFamily read FConvFamily;
  45. property ConvType : TConvType read FConvType;
  46. property Description: String read FDescription;
  47. end;
  48. TConvTypeFactor = class(TConvTypeInfo)
  49. private
  50. FFactor: Double;
  51. protected
  52. property Factor: Double read FFactor;
  53. public
  54. constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
  55. const AFactor: Double);
  56. function ToCommon(const AValue: Double): Double; override;
  57. function FromCommon(const AValue: Double): Double; override;
  58. end;
  59. TConvTypeProcs = class(TConvTypeInfo)
  60. private
  61. FToProc: TConversionProc;
  62. FFromProc: TConversionProc;
  63. public
  64. constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
  65. const AToProc, AFromProc: TConversionProc);
  66. function ToCommon(const AValue: Double): Double; override;
  67. function FromCommon(const AValue: Double): Double; override;
  68. end;
  69. Implementation
  70. Type ResourceData = record
  71. Description : String;
  72. Value : TConvUtilFloat;
  73. Fam : TConvFamily;
  74. end;
  75. var TheUnits : array of ResourceData =nil;
  76. TheFamilies : array of string =nil;
  77. function ConvFamilyToDescription(const AFamily: TConvFamily): string;
  78. begin
  79. result:='';
  80. if AFamily<length(TheFamilies) then
  81. result:=TheFamilies[AFamily];
  82. end;
  83. procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
  84. var i : integer;
  85. begin
  86. setlength(AFamilies,length(thefamilies));
  87. for i:=0 to length(TheFamilies)-1 do
  88. AFamilies[i]:=i;
  89. end;
  90. procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
  91. var i,j,nrTypes:integer;
  92. begin
  93. nrTypes:=0;
  94. for i:=0 to length(TheUnits)-1 do
  95. if TheUnits[i].fam=AFamily Then
  96. inc(nrTypes);
  97. setlength(atypes,nrtypes);
  98. j:=0;
  99. for i:=0 to length(TheUnits)-1 do
  100. if TheUnits[i].fam=AFamily Then
  101. begin
  102. atypes[j]:=i;
  103. inc(j);
  104. end;
  105. end;
  106. function ConvTypeToDescription(const AType: TConvType): string;
  107. Begin
  108. result:='';
  109. if AType<length(TheUnits) then
  110. result:=TheUnits[AType].Description;
  111. end;
  112. Function RegisterConversionFamily(Const S:String):TConvFamily;
  113. var i,l : Longint;
  114. begin
  115. l:=Length(TheFamilies);
  116. If l=0 Then
  117. begin
  118. SetLength(TheFamilies,1);
  119. TheFamilies[0]:=S;
  120. Result:=0;
  121. end
  122. else
  123. begin
  124. i:=0;
  125. while (i<l) and (s<>TheFamilies[i]) do inc(i);
  126. if i=l Then
  127. begin
  128. SetLength(TheFamilies,l+1);
  129. TheFamilies[l]:=s;
  130. end;
  131. Result:=i;
  132. end;
  133. end;
  134. Function CheckFamily(i:TConvFamily):Boolean;
  135. begin
  136. Result:=i<Length(TheFamilies);
  137. end;
  138. const macheps=1E-9;
  139. Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
  140. var l1 : Longint;
  141. begin
  142. If NOT CheckFamily(Fam) Then exit(-1); // family not registered.
  143. if (value+1.0)<macheps then // not properly defined yet.
  144. exit(-1);
  145. l1:=length(theunits);
  146. Setlength(theunits,l1+1);
  147. theunits[l1].description:=s;
  148. theunits[l1].value:=value;
  149. theunits[l1].fam:=fam;
  150. Result:=l1;
  151. end;
  152. function SearchConvert(TheType:TConvType; var r:ResourceData):Boolean;
  153. var l1 : longint;
  154. begin
  155. l1:=length(TheUnits);
  156. if thetype>=l1 then
  157. exit(false);
  158. r:=theunits[thetype];
  159. result:=true;
  160. end;
  161. function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat;
  162. var
  163. fromrec,torec : resourcedata;
  164. begin
  165. if not SearchConvert(fromtype,fromrec) then
  166. exit(-1.0); // raise exception?
  167. if not SearchConvert(totype,torec) then
  168. exit(-1.0); // raise except?
  169. if fromrec.fam<>torec.fam then
  170. exit(-1.0);
  171. result:=Measurement*fromrec.value/torec.value;
  172. end;
  173. function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat;
  174. var
  175. fromrec1,fromrec2,torec1 ,
  176. torec2 : resourcedata;
  177. begin
  178. if not SearchConvert(fromtype1,fromrec1) then
  179. exit(-1.0); // raise exception?
  180. if not SearchConvert(totype1,torec1) then
  181. exit(-1.0); // raise except?
  182. if not SearchConvert(fromtype2,fromrec2) then
  183. exit(-1.0); // raise exception?
  184. if not SearchConvert(totype2,torec2) then
  185. exit(-1.0); // raise except?
  186. if (fromrec1.fam<>torec1.fam) or (fromrec1.fam<>torec1.fam) then
  187. exit(-1.0);
  188. result:=Measurement*(fromrec1.value/fromrec2.value)/(torec1.value/torec2.value);
  189. end;
  190. Constructor TConvTypeInfo.Create(Const AConvFamily : TConvFamily;const ADescription:String);
  191. begin
  192. FDescription:=ADescription;
  193. FConvFamily :=AConvFamily;
  194. end;
  195. constructor TConvTypeFactor.Create(const AConvFamily: TConvFamily; const ADescription: string;const AFactor: Double);
  196. begin
  197. inherited create(AConvFamily,ADescription);
  198. FFactor:=AFactor;
  199. end;
  200. function TConvTypeFactor.ToCommon(const AValue: Double): Double;
  201. begin
  202. result:=AValue * FFactor;
  203. end;
  204. function TConvTypeFactor.FromCommon(const AValue: Double): Double;
  205. begin
  206. result:=AValue / FFactor;
  207. end;
  208. constructor TConvTypeProcs.Create(const AConvFamily: TConvFamily; const ADescription: string; const AToProc, AFromProc: TConversionProc);
  209. begin
  210. inherited create(AConvFamily,ADescription);
  211. ftoproc:=AToProc;
  212. ffromproc:=AFromProc;
  213. end;
  214. function TConvTypeProcs.ToCommon(const AValue: Double): Double;
  215. begin
  216. result:=FTOProc(Avalue);
  217. end;
  218. function TConvTypeProcs.FromCommon(const AValue: Double): Double;
  219. begin
  220. result:=FFromProc(Avalue);
  221. end;
  222. finalization
  223. setlength(theunits,0);
  224. setlength(thefamilies,0);
  225. {$else}
  226. implementation
  227. {$endif}
  228. end.