1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
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. *
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. *
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 ***************************************************************************/
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();
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();
56 int arcToHgt(const QString filename
, char* voids
)
58 qDebug() << "Reading" << filename
;
60 // first open arcinfo file
62 if (!af
.open(QIODevice::ReadOnly
))
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
];
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
);
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
)
119 qDebug() << " Writing to" << filename
;
124 // overwrite directly with new values
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
);
133 for (int col
= 0; col
< ncols
; ++col
)
135 int x
= (int)floor(0.5 + xllcorner
/cellsize
- lonMin
/cellsize
+ col
);
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)
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
));
164 QDataStream
stream(&srtm
[index
]);
165 stream
.setByteOrder(QDataStream::BigEndian
);
166 srtm
[index
].seek(FILEPOS(lonMod
, latMod
));
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
));
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));
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));
207 int main(int argc
, char** argv
)
209 qDebug() << "Welcome to arcToHgt";
211 // Convert the file in each argument to HGT, overwriting any existing data
213 for (int i
= 1; i
< argc
; ++i
)
215 if (0 == strcmp(argv
[i
], "--voids"))
217 // next argument is voids directory
221 qDebug() << "Using voids from " << voids
;
226 error
|= arcToHgt(argv
[i
], voids
);