GXS.FileGRD.pas 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.FileGRD;
  5. (* GRD (Grid Text Format) vector file format implementation *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. Stage.VectorGeometry,
  12. Stage.VectorTypes,
  13. GXS.VectorFileObjects,
  14. GXS.ApplicationFileIO,
  15. GXS.Graph;
  16. type
  17. (*The GRD file represents ascii grid formats in 2D/3D.
  18. This is a format for storing regular grid values as a
  19. matrices of cell centers. The format supports variations and
  20. subformats. This importer works for Sutfer, ArcInfo and GMS formats *)
  21. TgxGRDVectorFile = class(TgxVectorFile)
  22. public
  23. HeightField: TgxHeightField;
  24. Nodes: array of TSingleArray;
  25. class function Capabilities: TDataFileCapabilities; override;
  26. procedure LoadFromStream(aStream: TStream); override;
  27. private
  28. StrVal: String;
  29. StrLine: String;
  30. MaxZ: Single;
  31. function ExtractWord(N: Integer; const S: string;
  32. const WordDelims: TSysCharSet): string;
  33. function WordPosition(const N: Integer; const S: string;
  34. const WordDelims: TSysCharSet): Integer;
  35. end;
  36. //=======================================================================
  37. implementation
  38. //=======================================================================
  39. //-------------------
  40. // ------------------ TgxGRDVectorFile ------------------
  41. // ------------------
  42. const
  43. dSURFBLANKVAL = 1.70141E38; // default value in Surfer for blanking
  44. NODATA_value = -9999; //default value in GIS ArcInfo for blanking
  45. class function TgxGRDVectorFile.Capabilities: TDataFileCapabilities;
  46. begin
  47. Result := [dfcRead];
  48. end;
  49. function TgxGRDVectorFile.WordPosition(const N: Integer; const S: string;
  50. const WordDelims: TSysCharSet): Integer;
  51. var
  52. Count, I: Integer;
  53. begin
  54. Count := 0;
  55. I := 1;
  56. Result := 0;
  57. while ((I <= Length(S)) and (Count <> N)) do
  58. begin
  59. // skip over delimiters
  60. while (I <= Length(S)) and CharInSet(S[I], WordDelims) do
  61. Inc(I);
  62. // if we're not beyond end of S, we're at the start of a word
  63. if I <= Length(S) then
  64. Inc(Count);
  65. // if not finished, find the end of the current word
  66. if Count <> N then
  67. while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
  68. Inc(I)
  69. else
  70. Result := I;
  71. end;
  72. end;
  73. function TgxGRDVectorFile.ExtractWord(N: Integer; const S: string;
  74. const WordDelims: TSysCharSet): string;
  75. var
  76. I, Len: Integer;
  77. begin
  78. Len := 0;
  79. I := WordPosition(N, S, WordDelims);
  80. if (I <> 0) then
  81. // find the end of the current word
  82. while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
  83. begin
  84. // add the I'th character to result
  85. Inc(Len);
  86. SetLength(Result, Len);
  87. Result[Len] := S[I];
  88. Inc(I);
  89. end;
  90. SetLength(Result, Len);
  91. end;
  92. procedure TgxGRDVectorFile.LoadFromStream(aStream: TStream);
  93. var
  94. I, J, K: Integer;
  95. N : Integer; // N => counter to increment through file
  96. Sl, Tl: TStringList;
  97. Nx, Ny: Integer;
  98. Dx, Dy: Single;
  99. Xo, Xe, Yo, Ye, Zo, Ze: Single;
  100. NBlanks : Integer; // Number of blank nodes
  101. BlankVal, NoData : Double;
  102. { sub } function ReadLine: string;
  103. begin
  104. Result := Sl[N];
  105. Inc(N);
  106. end;
  107. begin
  108. sl := TStringList.Create;
  109. tl := TStringList.Create;
  110. try
  111. sl.LoadFromStream(aStream);
  112. if (Copy(sl[0], 1, 4) <> 'DSAA') and (Copy(sl[0], 1, 5) <> 'ncols') then
  113. begin
  114. raise Exception.Create('Not a valid grd file !');
  115. Exit;
  116. end;
  117. HeightField := TgxHeightField.Create(Owner);
  118. Zo := 3 * 10E38; // Low
  119. Ze := -3 * 10E38; // High
  120. Tl.DelimitedText := Copy(ReadLine, 1, 4);
  121. if (Tl[0] = 'DSAA') then // Surfer ASCII grid
  122. begin
  123. Tl.DelimitedText := ReadLine;
  124. Nx := StrToInt(Tl[0]);
  125. Ny := StrToInt(Tl[1]);
  126. Tl.DelimitedText := ReadLine;
  127. Xo := StrToFloat(Tl[0]);
  128. Xe := StrToFloat(Tl[1]);
  129. Tl.DelimitedText := ReadLine;
  130. Yo := StrToFloat(Tl[0]);
  131. Ye := StrToFloat(Tl[1]);
  132. Tl.DelimitedText := ReadLine;
  133. Zo := StrToFloat(Tl[0]);
  134. Ze := StrToFloat(Tl[1]);
  135. Dx := (Xe - Xo) / Nx;
  136. Dy := (Ye - Yo) / Ny;
  137. SetLength(Nodes, Ny, Nx);
  138. Nblanks := 0;
  139. BlankVal := dSURFBLANKVAL;
  140. NoData := BlankVal; // NoData value
  141. // loop over the Ny-1 Rows
  142. for I := 0 to Ny - 1 do
  143. begin
  144. J := 0;
  145. // reading lines until Nx-1 Cols entries have been obtained
  146. while J <= Nx - 1 do
  147. begin
  148. StrLine := ReadLine;
  149. K := 1;
  150. StrVal := ExtractWord(K, StrLine, [' ']);
  151. while (StrVal <> '') do
  152. begin
  153. if (J <= Nx - 1) then
  154. Nodes[I, J] := StrToFloat(StrVal);
  155. if Nodes[I, J] > MaxZ then
  156. MaxZ := Nodes[I, J];
  157. if (Nodes[I, J] >= BlankVal) then
  158. Nblanks := Nblanks + 1;
  159. Inc(J);
  160. Inc(K);
  161. StrVal := ExtractWord(K, StrLine, [' ']);
  162. end;
  163. if (J > Nx - 1) then
  164. Break;
  165. end;
  166. end
  167. end
  168. else // ArcInfo ASCII grid
  169. begin
  170. Tl.DelimitedText := Sl[0];
  171. Ny := StrToInt(Tl[1]); // ncols
  172. Tl.DelimitedText := Sl[1];
  173. Nx := StrToInt(Tl[1]); // nrows
  174. Tl.DelimitedText := Sl[2];
  175. Xo := StrToFloat(Tl[1]); // xllcorner
  176. Tl.DelimitedText := Sl[3];
  177. Yo := StrToFloat(Tl[1]); // yllcorner
  178. Tl.DelimitedText := Sl[4];
  179. Dx := StrToFloat(Tl[1]);
  180. Dy := Dx; // cellsize
  181. Tl.DelimitedText := Sl[5];
  182. NoData := StrToFloat(Tl[1]); // NoData value
  183. MaxZ := -3 * 10E38;
  184. SetLength(Nodes, Nx, Ny);
  185. for I := 0 to Nx - 1 do
  186. begin
  187. Tl.DelimitedText := Sl[I + 6];
  188. for J := 0 to Ny - 1 do
  189. begin
  190. StrVal := Tl[J];
  191. Nodes[I, J] := StrToFloat(StrVal);
  192. if Nodes[I, J] > MaxZ then
  193. MaxZ := Nodes[I, J];
  194. end;
  195. end;
  196. end;
  197. HeightField.XSamplingScale.Min := -(Nx div 2);
  198. HeightField.XSamplingScale.Max := (Nx div 2);
  199. HeightField.YSamplingScale.Min := -(Ny div 2);
  200. HeightField.YSamplingScale.Max := (Ny div 2);
  201. finally
  202. tl.Free;
  203. sl.Free;
  204. end;
  205. end;
  206. // ------------------------------------------------------------------
  207. initialization
  208. // ------------------------------------------------------------------
  209. RegisterVectorFileFormat('grd', 'ArcInfo/Surfer grids', TgxGRDVectorFile);
  210. end.