Simple program to read arcinfo ascii files and convert into hgt elevation data (for...
[tecorrec.git] / arctohgt / arcToHgt.cpp
blobbec96e8514284ba70c286ee7a9fcaa4881870bfc
1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * Tecorrec is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * Tecorrec is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with Tecorrec. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 #include <QString>
21 #include <QByteArray>
22 #include <QFile>
23 #include <QRegExp>
24 #include <QtDebug>
26 #include <cmath>
28 double readDouble(QFile& file)
30 QByteArray line = file.readLine();
31 static QRegExp intLine("^\\s*\\w+\\s+([-+]?\\d+(\\.\\d+)?)\\s*$");
32 if (intLine.exactMatch(line))
34 return intLine.cap(1).toDouble();
36 else
38 return -1;
42 int readInt(QFile& file)
44 QByteArray line = file.readLine();
45 static QRegExp intLine("^\\s*\\w+\\s+([-+]?\\d+)\\s*$");
46 if (intLine.exactMatch(line))
48 return intLine.cap(1).toInt();
50 else
52 return -1;
56 int arcToHgt(const QString filename)
58 qDebug() << "Reading" << filename;
60 // first open arcinfo file
61 QFile af(filename);
62 af.open(QIODevice::ReadOnly);
64 // and read the header info
65 int ncols = readInt(af);
66 int nrows = readInt(af);
67 double xllcorner = readDouble(af);
68 double yllcorner = readDouble(af);
69 double cellsize = readDouble(af);
70 int nodata_value = readInt(af);
72 // find corresponding HGT tiles
73 int lonMin = (int)floor(xllcorner);
74 int lonMax = (int)floor(xllcorner + cellsize*(ncols-1));
75 int latMin = (int)floor(yllcorner);
76 int latMax = (int)floor(yllcorner + cellsize*(nrows-1));
77 int tilesX = 1+lonMax-lonMin;
78 int tilesY = 1+latMax-latMin;
79 QFile* srtm = new QFile[tilesX*tilesY];
80 for (int lon = lonMin; lon <= lonMax; ++lon)
82 for (int lat = latMin; lat <= latMax; ++lat)
84 QString filename = QString("%3%4%5%6.hgt")
85 .arg(lat >= 0 ? 'N' : 'S')
86 .arg(abs(lat), 2, 10, QLatin1Char('0'))
87 .arg(lon >= 0 ? 'E' : 'W')
88 .arg(abs(lon), 3, 10, QLatin1Char('0'));
89 int index = tilesX*(lat-latMin) + lon-lonMin;
90 srtm[index].setFileName(filename);
91 srtm[index].open(QIODevice::WriteOnly);
92 // if it doesn't exist, initialize with void
93 if (srtm[index].atEnd())
95 QDataStream stream(&srtm[index]);
96 stream.setByteOrder(QDataStream::BigEndian);
97 uint16_t sample = 0x8000;
98 for (int i = 0; i < 1201*1201; ++i)
100 stream << sample;
106 // overwrite directly with new values
108 QTextStream in(&af);
109 // go through the rows
110 for (int row = 0; row < nrows; ++row)
112 int y = (int)floor(0.5 + yllcorner/cellsize - latMin/cellsize + nrows-1-row);
113 int latDiv = y/1200;
114 int latMod = y%1200;
115 for (int col = 0; col < ncols; ++col)
117 int x = (int)floor(0.5 + xllcorner/cellsize - lonMin/cellsize + col);
118 int lonDiv = x/1200;
119 int lonMod = x%1200;
121 int value;
122 in >> value;
123 uint16_t sample = value;
125 bool inX = (lonDiv >= 0 && lonDiv < tilesX);
126 bool inY = (latDiv >= 0 && latDiv < tilesY);
127 bool inXm1 = (lonDiv > 0 && lonDiv <= tilesX);
128 bool inYm1 = (latDiv > 0 && latDiv <= tilesY);
129 #define FILEPOS(X,Y) (((1201-(Y))*1201 + (X))*2)
130 if (inX && inY)
132 int index = latDiv*tilesX + lonDiv;
133 QDataStream stream(&srtm[index]);
134 stream.setByteOrder(QDataStream::BigEndian);
135 srtm[index].seek(FILEPOS(lonMod, latMod));
136 stream << sample;
138 bool edgeX = (lonMod == 0);
139 bool edgeY = (latMod == 0);
140 if (edgeX && inXm1 && inY)
142 int index = latDiv*tilesX + lonDiv-1;
143 QDataStream stream(&srtm[index]);
144 stream.setByteOrder(QDataStream::BigEndian);
145 srtm[index].seek(FILEPOS(1200, latMod));
146 stream << sample;
148 if (edgeY && inX && inYm1)
150 int index = (latDiv-1)*tilesX + lonDiv;
151 QDataStream stream(&srtm[index]);
152 stream.setByteOrder(QDataStream::BigEndian);
153 srtm[index].seek(FILEPOS(lonMod, 1200));
154 stream << sample;
156 if (edgeX && edgeY && inXm1 && inYm1)
158 int index = (latDiv-1)*tilesX + lonDiv-1;
159 QDataStream stream(&srtm[index]);
160 stream.setByteOrder(QDataStream::BigEndian);
161 srtm[index].seek(FILEPOS(1200, 1200));
162 stream << sample;
167 delete [] srtm;
170 int main(int argc, char** argv)
172 qDebug() << "Welcome to arcToHgt";
173 int error = 0;
174 // Convert the file in each argument to HGT, overwriting any existing data
175 for (int i = 1; i < argc; ++i)
177 error |= arcToHgt(argv[i]);
179 return error;