convutil.inc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. Type TConvType = type Integer;
  20. TConvFamily = type Integer;
  21. TConvFamilyArray = array of TConvFamily;
  22. TConvTypeArray = array of TConvType;
  23. TConversionProc = function(const AValue: Double): Double;
  24. Type TConvUtilFloat = double;
  25. Function RegisterConversionFamily(Const S : String):TConvFamily;
  26. Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
  27. function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat;
  28. function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat;
  29. function ConvFamilyToDescription(const AFamily: TConvFamily): string;
  30. function ConvTypeToDescription(const AType: TConvType): string;
  31. procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
  32. procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
  33. Type
  34. TConvTypeInfo = Class(Tobject)
  35. private
  36. FDescription : String;
  37. FConvFamily : TConvFamily;
  38. FConvType : TConvType;
  39. public
  40. Constructor Create(Const AConvFamily : TConvFamily;const ADescription:String);
  41. function ToCommon(const AValue: Double) : Double; virtual; abstract;
  42. function FromCommon(const AValue: Double) : Double; virtual; abstract;
  43. property ConvFamily : TConvFamily read FConvFamily;
  44. property ConvType : TConvType read FConvType;
  45. property Description: String read FDescription;
  46. end;
  47. TConvTypeFactor = class(TConvTypeInfo)
  48. private
  49. FFactor: Double;
  50. protected
  51. property Factor: Double read FFactor;
  52. public
  53. constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
  54. const AFactor: Double);
  55. function ToCommon(const AValue: Double): Double; override;
  56. function FromCommon(const AValue: Double): Double; override;
  57. end;
  58. TConvTypeProcs = class(TConvTypeInfo)
  59. private
  60. FToProc: TConversionProc;
  61. FFromProc: TConversionProc;
  62. public
  63. constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
  64. const AToProc, AFromProc: TConversionProc);
  65. function ToCommon(const AValue: Double): Double; override;
  66. function FromCommon(const AValue: Double): Double; override;
  67. end;
  68. Implementation
  69. Type ResourceData = record
  70. Description : String;
  71. Value : TConvUtilFloat;
  72. Fam : TConvFamily;
  73. end;
  74. var TheUnits : array of ResourceData =nil;
  75. TheFamilies : array of string =nil;
  76. function ConvFamilyToDescription(const AFamily: TConvFamily): string;
  77. begin
  78. result:='';
  79. if AFamily<length(TheFamilies) then
  80. result:=TheFamilies[AFamily];
  81. end;
  82. procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
  83. var i : integer;
  84. begin
  85. setlength(AFamilies,length(thefamilies));
  86. for i:=0 to length(TheFamilies)-1 do
  87. AFamilies[i]:=i;
  88. end;
  89. procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
  90. var i,j,nrTypes:integer;
  91. begin
  92. nrTypes:=0;
  93. for i:=0 to length(TheUnits)-1 do
  94. if TheUnits[i].fam=AFamily Then
  95. inc(nrTypes);
  96. setlength(atypes,nrtypes);
  97. j:=0;
  98. for i:=0 to length(TheUnits)-1 do
  99. if TheUnits[i].fam=AFamily Then
  100. begin
  101. atypes[j]:=i;
  102. inc(j);
  103. end;
  104. end;
  105. function ConvTypeToDescription(const AType: TConvType): string;
  106. Begin
  107. result:='';
  108. if AType<length(TheUnits) then
  109. result:=TheUnits[AType].Description;
  110. end;
  111. Function RegisterConversionFamily(Const S:String):TConvFamily;
  112. var i,l : Longint;
  113. begin
  114. l:=Length(TheFamilies);
  115. If l=0 Then
  116. begin
  117. SetLength(TheFamilies,1);
  118. TheFamilies[0]:=S;
  119. Result:=0;
  120. end
  121. else
  122. begin
  123. i:=0;
  124. while (i<l) and (s<>TheFamilies[i]) do inc(i);
  125. if i=l Then
  126. begin
  127. SetLength(TheFamilies,l+1);
  128. TheFamilies[l]:=s;
  129. end;
  130. Result:=i;
  131. end;
  132. end;
  133. Function CheckFamily(i:TConvFamily):Boolean;
  134. begin
  135. Result:=i<Length(TheFamilies);
  136. end;
  137. const macheps=1E-9;
  138. Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
  139. var l1 : Longint;
  140. begin
  141. If NOT CheckFamily(Fam) Then exit(-1); // family not registered.
  142. if (value+1.0)<macheps then // not properly defined yet.
  143. exit(-1);
  144. l1:=length(theunits);
  145. Setlength(theunits,l1+1);
  146. theunits[l1].description:=s;
  147. theunits[l1].value:=value;
  148. theunits[l1].fam:=fam;
  149. Result:=l1;
  150. end;
  151. function SearchConvert(TheType:TConvType; var r:ResourceData):Boolean;
  152. var l1 : longint;
  153. begin
  154. l1:=length(TheUnits);
  155. if thetype>=l1 then
  156. exit(false);
  157. r:=theunits[thetype];
  158. result:=true;
  159. end;
  160. function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat;
  161. var
  162. fromrec,torec : resourcedata;
  163. begin
  164. if not SearchConvert(fromtype,fromrec) then
  165. exit(-1.0); // raise exception?
  166. if not SearchConvert(totype,torec) then
  167. exit(-1.0); // raise except?
  168. if fromrec.fam<>torec.fam then
  169. exit(-1.0);
  170. result:=Measurement*fromrec.value/torec.value;
  171. end;
  172. function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat;
  173. var
  174. fromrec1,fromrec2,torec1 ,
  175. torec2 : resourcedata;
  176. begin
  177. if not SearchConvert(fromtype1,fromrec1) then
  178. exit(-1.0); // raise exception?
  179. if not SearchConvert(totype1,torec1) then
  180. exit(-1.0); // raise except?
  181. if not SearchConvert(fromtype2,fromrec2) then
  182. exit(-1.0); // raise exception?
  183. if not SearchConvert(totype2,torec2) then
  184. exit(-1.0); // raise except?
  185. if (fromrec1.fam<>torec1.fam) or (fromrec1.fam<>torec1.fam) then
  186. exit(-1.0);
  187. result:=Measurement*(fromrec1.value/fromrec2.value)/(torec1.value/torec2.value);
  188. end;
  189. Constructor TConvTypeInfo.Create(Const AConvFamily : TConvFamily;const ADescription:String);
  190. begin
  191. FDescription:=ADescription;
  192. FConvFamily :=AConvFamily;
  193. end;
  194. constructor TConvTypeFactor.Create(const AConvFamily: TConvFamily; const ADescription: string;const AFactor: Double);
  195. begin
  196. inherited create(AConvFamily,ADescription);
  197. FFactor:=AFactor;
  198. end;
  199. function TConvTypeFactor.ToCommon(const AValue: Double): Double;
  200. begin
  201. result:=AValue * FFactor;
  202. end;
  203. function TConvTypeFactor.FromCommon(const AValue: Double): Double;
  204. begin
  205. result:=AValue / FFactor;
  206. end;
  207. constructor TConvTypeProcs.Create(const AConvFamily: TConvFamily; const ADescription: string; const AToProc, AFromProc: TConversionProc);
  208. begin
  209. inherited create(AConvFamily,ADescription);
  210. ftoproc:=AToProc;
  211. ffromproc:=AFromProc;
  212. end;
  213. function TConvTypeProcs.ToCommon(const AValue: Double): Double;
  214. begin
  215. result:=FTOProc(Avalue);
  216. end;
  217. function TConvTypeProcs.FromCommon(const AValue: Double): Double;
  218. begin
  219. result:=FFromProc(Avalue);
  220. end;
  221. finalization
  222. setlength(theunits,0);
  223. setlength(thefamilies,0);
  224. end.