Reputation: 23
I have been searching high and low for a Delphi function or any info that can parse a space delimited TStringList(Loaded from *.asc file) to a dynamic 2D array of integer.
What I have is an ASCII grid file with elevations in a grid format. Firstly I read the file into a TStringlist, where I extract the header data to variables, then delete the header data from the TStringlist. What I'm left with is a TStringlist with only elevation data in a grid of 3601 x 3601, with each value separated by a space. With this Stringlist still in memory, I'd like to fill a 2D array of integer with the elevation data, then free the TStringList.
From my searches I stumbled upon a piece of code here that kind of worked, but not completely.
What I have is:
var sourceData, tmpGrid, tmpRow : TStringList;
val : String;
Pos, i, j, k, l : Integer;
nCols, nRows, noData : Integer;
xllCorner, yllCorner, cellSize : Extended;
Dem : array of array of Integer;
begin
val := '';
sourceData := TStringList.Create;
tmpGrid := TStringList.Create;
tmpRow := TStringList.Create;
tmpRow.StrictDelimiter := True;
tmpRow.Delimiter := ' ';
sourceData.LoadFromFile('D:\ZA_DEM_DATA\Bulk_Order_466486\ARCASCII\s30_e026_1arc_v3.asc');
nCols := StrToInt(StripNonConforming(sourceData.Strings[0], ['0'..'9', '+', '-', '.']));
nRows := StrToInt(StripNonConforming(sourceData.Strings[1], ['0'..'9', '+', '-', '.']));
xllCorner := StrToFloat(StripNonConforming(sourceData.Strings[2], ['0'..'9', '+', '-', '.']));
yllCorner := StrToFloat(StripNonConforming(sourceData.Strings[3], ['0'..'9', '+', '-', '.']));
cellSize := StrToFloat(StripNonConforming(sourceData.Strings[4], ['0'..'9', '+', '-', '.']));
noData := StrToInt(StripNonConforming(sourceData.Strings[5], ['0'..'9', '+', '-', '.']));
Edit1.Text := IntToStr(nCols);
Edit2.Text := IntToStr(nRows);
Edit3.Text := FloatToStr(xllCorner);
Edit4.Text := FloatToStr(yllCorner);
Edit5.Text := FloatToStr(cellSize);
Edit6.Text := IntToStr(noData);
for I := 0 to 5 do
begin
sourceData.Delete(0);
end;
//This is where I start parsing my TStrinList
tmpGrid.DelimitedText := sourceData.Text;
SetLength(Dem, nCols, nRows);
Edit7.Text := IntToStr(sourceData.Count);
try
for i := 0 to sourceData.Count -1 do
for j := 0 to sourceData.Count -1 do
begin
Dem[i][j] := StrToInt(tmpGrid.Strings[i]);
end;
finally
sourceData.Free;
end;
StringGrid1.ColCount := nCols;
StringGrid1.RowCount := nRows;
//This is mainly to visualise the data while testing the code
for i := 0 to nCols -1 do
for j := 0 to nRows -1 do
begin
StringGrid1.Cells[i, j] := IntToStr(dem[i, j]);
end;
end;
The result I get is the first "row" of data as displayed in the original file, but copied to all rows of the array. For example:
Original Data:
1. 1245 1268 1232 1258 2. 1354 1321 1578 1689 3. 1461 1423 1475 1427 4. 1598 1541 1562 1550
What I get is:
1. 1245 1268 1232 1258 2. 1245 1268 1232 1258 3. 1245 1268 1232 1258 4. 1245 1268 1232 1258
Any and all help will be greatly appreciated.
Upvotes: 0
Views: 1640
Reputation: 21045
This seems to be the cause of the wrong results
for i := 0 to sourceData.Count -1 do
for j := 0 to sourceData.Count -1 do
begin
Dem[i][j] := StrToInt(tmpGrid.Strings[i]);
end;
You have moved the actual data from SourceData to tmpGrid, which is not needed. Instead, assign one line at a time from SourceData to tmpRow, then read the values one at a time from tmpRow, and assign to the value array:
for i := 0 to SourceData.Count-1 do
begin
tmpRow.DelimitedText := SourceData[i];
for j := 0 to tmpRow.Count-1 do
Dem[i,j] := StrToInt(tmpRow[j]);
end;
Upvotes: 2
Reputation: 19106
Just after this code line
//This is where I start parsing my TStrinList
tmpGrid.DelimitedText := sourceData.Text;
your sourceData
contains 4 lines of text
1245 1268 1232 1258 1354 1321 1578 1689 1461 1423 1475 1427 1598 1541 1562 1550
and tmpGrid
contains 16 lines of text
1245 1268 1232 1258 1354 1321 1578 1689 1461 1423 1475 1427 1598 1541 1562 1550
But you only access the tmpGrid lines from 0 to 3 for each row
for i := 0 to sourceData.Count -1 do
for j := 0 to sourceData.Count -1 do
begin
Dem[i][j] := StrToInt(tmpGrid.Strings[i]);
end;
You should change your code to use the values from nCols
and nRows
and then calculate the line inside tmpGrid
for i := 0 to nCols -1 do
for j := 0 to nRows -1 do
begin
Dem[i][j] := StrToInt(tmpGrid.Strings[i + j*nCols]);
end;
i = 0 // first column j = 1 // second row i + j * nCols => 0 + 4 => fifth line of tmpGrid (zero indexed)
Upvotes: 2