Snapshotting and loading
[tecorrec.git] / arctohgt / arcToHgt.cpp
blob1321b68c8d1103088df87b4610958f3af071cb95
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, char* voids)
58 qDebug() << "Reading" << filename;
60 // first open arcinfo file
61 QFile af(filename);
62 if (!af.open(QIODevice::ReadOnly))
64 return 1;
67 // and read the header info
68 int ncols = readInt(af);
69 int nrows = readInt(af);
70 double xllcorner = readDouble(af);
71 double yllcorner = readDouble(af);
72 double cellsize = readDouble(af);
73 int nodata_value = readInt(af);
75 // find corresponding HGT tiles
76 int lonMin = (int)floor(xllcorner);
77 int lonMax = (int)floor(xllcorner + cellsize*(ncols-1));
78 int latMin = (int)floor(yllcorner);
79 int latMax = (int)floor(yllcorner + cellsize*(nrows-1));
80 int tilesX = 1+lonMax-lonMin;
81 int tilesY = 1+latMax-latMin;
82 QFile* srtm = new QFile[tilesX*tilesY];
83 QFile* voidfs = 0;
84 if (0 != voids)
86 voidfs = new QFile[tilesX*tilesY];
88 for (int lon = lonMin; lon <= lonMax; ++lon)
90 for (int lat = latMin; lat <= latMax; ++lat)
92 QString filename = QString("%3%4%5%6.hgt")
93 .arg(lat >= 0 ? 'N' : 'S')
94 .arg(abs(lat), 2, 10, QLatin1Char('0'))
95 .arg(lon >= 0 ? 'E' : 'W')
96 .arg(abs(lon), 3, 10, QLatin1Char('0'));
97 int index = tilesX*(lat-latMin) + lon-lonMin;
98 srtm[index].setFileName(filename);
99 srtm[index].open(QIODevice::ReadWrite);
100 if (0 != voids)
102 voidfs[index].setFileName(QString("%1/%2").arg(voids).arg(filename));
103 voidfs[index].open(QIODevice::ReadOnly);
105 // if it doesn't exist, initialize with void
106 if (srtm[index].atEnd())
108 qDebug() << " Creating" << filename;
109 QDataStream stream(&srtm[index]);
110 stream.setByteOrder(QDataStream::BigEndian);
111 uint16_t sample = 0x8000;
112 for (int i = 0; i < 1201*1201; ++i)
114 stream << sample;
117 else
119 qDebug() << " Writing to" << filename;
124 // overwrite directly with new values
126 QTextStream in(&af);
127 // go through the rows
128 for (int row = nrows-1; row >= 0; --row)
130 int y = (int)floor(0.5 + yllcorner/cellsize - latMin/cellsize + row);
131 int latDiv = y/1200;
132 int latMod = y%1200;
133 for (int col = 0; col < ncols; ++col)
135 int x = (int)floor(0.5 + xllcorner/cellsize - lonMin/cellsize + col);
136 int lonDiv = x/1200;
137 int lonMod = x%1200;
139 int value;
140 in >> value;
141 uint16_t sample = value;
143 bool inX = (lonDiv >= 0 && lonDiv < tilesX);
144 bool inY = (latDiv >= 0 && latDiv < tilesY);
145 bool inXm1 = (lonDiv > 0 && lonDiv <= tilesX);
146 bool inYm1 = (latDiv > 0 && latDiv <= tilesY);
147 #define FILEPOS(X,Y) (((1201-(Y))*1201 + (X))*2)
148 if (inX && inY)
150 int index = latDiv*tilesX + lonDiv;
151 // if void flag is set, adjust sample
152 if (0 != voidfs && voidfs[index].isOpen())
154 QDataStream stream(&voidfs[index]);
155 stream.setByteOrder(QDataStream::BigEndian);
156 voidfs[index].seek(FILEPOS(lonMod, latMod));
157 uint16_t mask;
158 stream >> mask;
159 if (mask & 0x8000)
161 sample |= 0x8000;
164 QDataStream stream(&srtm[index]);
165 stream.setByteOrder(QDataStream::BigEndian);
166 srtm[index].seek(FILEPOS(lonMod, latMod));
167 stream << sample;
169 bool edgeX = (lonMod == 0);
170 bool edgeY = (latMod == 0);
171 if (edgeX && inXm1 && inY)
173 int index = latDiv*tilesX + lonDiv-1;
174 QDataStream stream(&srtm[index]);
175 stream.setByteOrder(QDataStream::BigEndian);
176 srtm[index].seek(FILEPOS(1200, latMod));
177 stream << sample;
179 if (edgeY && inX && inYm1)
181 int index = (latDiv-1)*tilesX + lonDiv;
182 QDataStream stream(&srtm[index]);
183 stream.setByteOrder(QDataStream::BigEndian);
184 srtm[index].seek(FILEPOS(lonMod, 1200));
185 stream << sample;
187 if (edgeX && edgeY && inXm1 && inYm1)
189 int index = (latDiv-1)*tilesX + lonDiv-1;
190 QDataStream stream(&srtm[index]);
191 stream.setByteOrder(QDataStream::BigEndian);
192 srtm[index].seek(FILEPOS(1200, 1200));
193 stream << sample;
198 delete [] srtm;
199 if (0 != voidfs)
201 delete [] voidfs;
204 return 0;
207 int main(int argc, char** argv)
209 qDebug() << "Welcome to arcToHgt";
210 int error = 0;
211 // Convert the file in each argument to HGT, overwriting any existing data
212 char * voids = 0;
213 for (int i = 1; i < argc; ++i)
215 if (0 == strcmp(argv[i], "--voids"))
217 // next argument is voids directory
218 if (++i < argc)
220 voids = argv[i];
221 qDebug() << "Using voids from " << voids;
224 else
226 error |= arcToHgt(argv[i], voids);
229 return error;