1 /* rawdem.c -- library of routines for processing raw dem files (30 arcsec)
3 * Written by Curtis Olson, started February 1998.
5 * Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * (Log is kept at end of this file)
26 #include <math.h> /* rint() */
28 #include <stdlib.h> /* atoi() atof() */
29 #include <string.h> /* swab() */
31 #include <sys/types.h> /* open() */
34 #include <unistd.h> /* close() */
39 /* Read the DEM header to determine various key parameters for this
41 void rawReadDemHdr( fgRAWDEM *raw, char *hdr_file ) {
43 char line[256], key[256], value[256];
47 if ( (hdr = fopen(hdr_file, "r")) == NULL ) {
48 printf("Error opening DEM header file: %s\n", hdr_file);
52 /* process each line */
53 while ( (fgets(line, 256, hdr) != NULL) ) {
54 /* printf("%s", line); */
59 while ( (line[i] != ' ') && (i < len) ) {
65 /* skip middle space */
66 while ( (line[i] == ' ') && (i < len) ) {
72 while ( (line[i] != '\n') && (i < len) ) {
73 value[i-offset] = line[i];
76 value[i-offset] = '\0';
77 /* printf("key='%s' value='%s'\n", key, value); */
79 if ( strcmp(key, "NROWS") == 0 ) {
80 raw->nrows = atoi(value);
81 } else if ( strcmp(key, "NCOLS") == 0 ) {
82 raw->ncols = atoi(value);
83 } else if ( strcmp(key, "ULXMAP") == 0 ) {
85 raw->ulxmap = (int)rint(tmp * 3600.0); /* convert to arcsec */
86 } else if ( strcmp(key, "ULYMAP") == 0 ) {
88 raw->ulymap = (int)rint(tmp * 3600.0); /* convert to arcsec */
89 } else if ( strcmp(key, "XDIM") == 0 ) {
91 raw->xdim = (int)rint(tmp * 3600.0); /* convert to arcsec */
92 } else if ( strcmp(key, "YDIM") == 0 ) {
94 raw->ydim = (int)rint(tmp * 3600.0); /* convert to arcsec */
100 raw->rootx = raw->ulxmap - (raw->xdim / 2);
101 raw->rooty = raw->ulymap + (raw->ydim / 2);
103 printf("%d %d %d %d %d %d %d %d\n", raw->nrows, raw->ncols,
104 raw->ulxmap, raw->ulymap, raw->rootx, raw->rooty, raw->xdim,
109 /* Open a raw DEM file. */
110 void rawOpenDemFile( fgRAWDEM *raw, char *raw_dem_file ) {
111 printf("Opening Raw DEM file: %s\n", raw_dem_file);
112 if ( (raw->fd = open(raw_dem_file ,O_RDONLY)) == -1 ) {
113 printf("Error opening Raw DEM file: %s\n", raw_dem_file);
119 /* Close a raw DEM file. */
120 void rawCloseDemFile( fgRAWDEM *raw ) {
125 /* Advance file pointer position to correct latitude (row) */
126 void rawAdvancePosition( fgRAWDEM *raw, int arcsec ) {
129 offset = 2 * raw->ncols * ( arcsec / raw->ydim );
131 if ( (result = lseek(raw->fd, offset, SEEK_SET)) == -1 ) {
132 printf("Error lseek filed trying to offset by %ld\n", offset);
136 printf("Successful seek ahead of %ld bytes\n", result);
140 /* Read the next row of data */
141 void rawReadNextRow( fgRAWDEM *raw, int index ) {
142 char buf[MAX_COLS_X_2];
145 if ( raw->ncols > MAX_ROWS ) {
146 printf("Error, buf needs to be bigger in rawReadNextRow()\n");
150 /* printf("Attempting to read %d bytes\n", 2 * raw->ncols); */
151 result = read(raw->fd, buf, 2 * raw->ncols);
152 /* printf("Read %d bytes\n", result); */
154 /* reverse byte order */
155 /* it would be nice to test in advance some how if we need to do
157 /* swab(frombuf, tobuf, 2 * raw->ncols); */
159 for ( i = 0; i < raw->ncols; i++ ) {
160 /* printf("hi = %d lo = %d\n", buf[2*i], buf[2*i + 1]); */
161 raw->strip[index][i] = ( (buf[2*i] + 1) << 8 ) + buf[2*i + 1];
166 /* Convert from pixel centered values to pixel corner values. This is
167 accomplished by taking the average of the closes center nodes. In
168 the following diagram "x" marks the data point location:
177 void rawConvertCenter2Edge( fgRAWDEM *raw ) {
180 /* derive corner nodes */
181 raw->edge[0][0] = raw->center[0][0];
182 raw->edge[120][0] = raw->center[119][0];
183 raw->edge[120][120] = raw->center[119][119];
184 raw->edge[0][120] = raw->center[0][119];
186 /* derive edge nodes */
187 for ( i = 1; i < 120; i++ ) {
188 raw->edge[i][0] = (raw->center[i-1][0] + raw->center[i][0]) / 2.0;
189 raw->edge[i][120] = (raw->center[i-1][119] + raw->center[i][119]) / 2.0;
190 raw->edge[0][i] = (raw->center[0][i-1] + raw->center[0][i]) / 2.0;
191 raw->edge[120][i] = (raw->center[119][i-1] + raw->center[119][i]) / 2.0;
194 /* derive internal nodes */
195 for ( j = 1; j < 120; j++ ) {
196 for ( i = 1; i < 120; i++ ) {
197 raw->edge[i][j] = ( raw->center[i-1][j-1] +
198 raw->center[i] [j-1] +
200 raw->center[i-1][j] ) / 4;
206 /* Dump out the ascii format DEM file */
207 void rawDumpAsciiDEM( fgRAWDEM *raw ) {
209 /* Generate output file name */
212 /* Dump the "A" record */
214 /* get the name field (144 characters) */
215 for ( i = 0; i < 144; i++ ) {
220 /* clean off the whitespace at the end */
221 for ( i = strlen(name)-2; i > 0; i-- ) {
222 if ( !isspace(name[i]) ) {
228 printf(" Quad name field: %s\n", name);
230 /* get quadrangle id (now part of previous section */
231 /* next_token(fd, dem_quadrangle); */
232 /* printf(" Quadrangle = %s\n", dem_quadrangle); */
234 /* DEM level code, 3 reflects processing by DMA */
236 printf(" DEM level code = %d\n", inum);
238 /* Pattern code, 1 indicates a regular elevation pattern */
240 printf(" Pattern code = %d\n", inum);
242 /* Planimetric reference system code, 0 indicates geographic
243 * coordinate system. */
245 printf(" Planimetric reference code = %d\n", inum);
249 printf(" Zone code = %d\n", inum);
251 /* Map projection parameters (ignored) */
252 for ( i = 0; i < 15; i++ ) {
253 dnum = next_double(fd);
254 /* printf("%d: %f\n",i,dnum); */
257 /* Units code, 3 represents arc-seconds as the unit of measure for
258 * ground planimetric coordinates throughout the file. */
261 printf(" Unknown (X,Y) units code = %d!\n", inum);
265 /* Units code; 2 represents meters as the unit of measure for
266 * elevation coordinates throughout the file. */
269 printf(" Unknown (Z) units code = %d!\n", inum);
273 /* Number (n) of sides in the polygon which defines the coverage of
274 * the DEM file (usually equal to 4). */
277 printf(" Unknown polygon dimension = %d!\n", inum);
281 /* Ground coordinates of bounding box in arc-seconds */
282 dem_x1 = m->originx = next_exp(fd);
283 dem_y1 = m->originy = next_exp(fd);
284 printf(" Origin = (%.2f,%.2f)\n", m->originx, m->originy);
286 dem_x2 = next_exp(fd);
287 dem_y2 = next_exp(fd);
289 dem_x3 = next_exp(fd);
290 dem_y3 = next_exp(fd);
292 dem_x4 = next_exp(fd);
293 dem_y4 = next_exp(fd);
295 /* Minimum/maximum elevations in meters */
296 dem_z1 = next_exp(fd);
297 dem_z2 = next_exp(fd);
298 printf(" Elevation range %.4f %.4f\n", dem_z1, dem_z2);
300 /* Counterclockwise angle from the primary axis of ground
301 * planimetric referenced to the primary axis of the DEM local
302 * reference system. */
303 next_token(fd, token);
305 /* Accuracy code; 0 indicates that a record of accuracy does not
306 * exist and that no record type C will follow. */
307 /* DEM spacial resolution. Usually (3,3,1) (3,6,1) or (3,9,1)
308 * depending on latitude */
309 /* I will eventually have to do something with this for data at
310 * higher latitudes */
311 next_token(fd, token);
312 printf(" accuracy & spacial resolution string = %s\n", token);
314 printf(" length = %d\n", i);
316 ptr = token + i - 12;
317 printf(" last field = %s = %.2f\n", ptr, atof(ptr));
321 m->col_step = atof(ptr);
322 printf(" last field = %s = %.2f\n", ptr, m->row_step);
326 m->row_step = atof(ptr);
327 printf(" last field = %s = %.2f\n", ptr, m->col_step);
330 /* accuracy code = atod(token) */
332 printf(" Accuracy code = %d\n", inum);
334 printf(" column step = %.2f row step = %.2f\n",
335 m->col_step, m->row_step);
336 /* dimension of arrays to follow (1)*/
337 next_token(fd, token);
339 /* number of profiles */
340 dem_num_profiles = m->cols = m->rows = next_int(fd);
341 printf(" Expecting %d profiles\n", dem_num_profiles);
346 /* Read a horizontal strip of (1 vertical degree) from the raw DEM
347 * file specified by the upper latitude of the stripe specified in
349 void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
351 int i, j, index, row, col;
352 int min = 0, max = 0;
353 int span, num_degrees, tile_width;
356 /* convert to arcsec */
357 lat = lat_degrees * 3600;
359 printf("Max Latitude = %d arcsec\n", lat);
361 /* validity check ... */
362 if ( (lat > raw->rooty) ||
363 (lat < (raw->rooty - raw->nrows * raw->ydim + 1)) ) {
364 printf("Latitude out of range for this DEM file\n");
368 printf ("Reading strip starting at %d (top and working down)\n", lat);
370 /* advance to the correct latitude */
371 rawAdvancePosition(raw, (raw->rooty - lat));
373 /* printf("short = %d\n", sizeof(short)); */
375 yrange = 3600 / raw->ydim;
377 for ( i = 0; i < yrange; i++ ) {
378 index = yrange - i - 1;
379 /* printf("About to read into row %d\n", index); */
380 rawReadNextRow(raw, index);
382 for ( j = 0; j < raw->ncols; j++ ) {
383 if ( raw->strip[index][j] == -9999 ) {
384 /* map ocean to 0 for now */
385 raw->strip[index][j] = 0;
388 if ( raw->strip[index][j] < min) {
389 min = raw->strip[index][j];
392 if ( raw->strip[index][j] > max) {
393 max = raw->strip[index][j];
397 printf("min = %d max = %d\n", min, max);
399 /* extract individual tiles from the strip */
400 span = raw->ncols * raw->xdim;
401 num_degrees = span / 3600;
402 tile_width = raw->ncols / num_degrees;
403 printf("span = %d num_degrees = %d width = %d\n",
404 span, num_degrees, tile_width);
406 for ( i = 0; i < num_degrees; i++ ) {
407 xstart = i * tile_width;
410 for ( row = 0; row < yrange; row++ ) {
411 for ( col = xstart; col < xend; col++ ) {
412 /* Copy from strip to pixel centered tile. Yep,
413 * row/col are reversed here. raw->strip is backwards
414 * for convenience. I am converting to [x,y] now. */
415 raw->center[col-xstart][row] = raw->strip[row][col];
419 /* Convert from pixel centered to pixel edge values */
420 rawConvertCenter2Edge(raw);
422 /* Dump out the ascii format DEM file */
423 rawDumpAsciiDEM(raw);
429 /* Revision 1.2 1998/03/03 02:04:01 curt
430 /* Starting DEM Ascii format output routine.
432 * Revision 1.1 1998/03/02 23:31:01 curt