~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/raster3d/header.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <sys/types.h>
 
4
#include <unistd.h>
 
5
#include <grass/raster3d.h>
 
6
#include <grass/glocale.h>
 
7
#include "raster3d_intern.h"
 
8
 
 
9
/*---------------------------------------------------------------------------*/
 
10
 
 
11
void *tmpCompress;
 
12
int tmpCompressLength;
 
13
void *xdr;
 
14
int xdrLength;
 
15
 
 
16
/*---------------------------------------------------------------------------*/
 
17
 
 
18
#define RASTER3D_HEADER_TILEX "TileDimensionX"
 
19
#define RASTER3D_HEADER_TILEY "TileDimensionY"
 
20
#define RASTER3D_HEADER_TILEZ "TileDimensionZ"
 
21
#define RASTER3D_HEADER_TYPE "CellType"
 
22
#define RASTER3D_HEADER_COMPRESSION "useCompression"
 
23
#define RASTER3D_HEADER_USERLE "useRle"
 
24
#define RASTER3D_HEADER_USELZW "useLzw"
 
25
#define RASTER3D_HEADER_PRECISION "Precision"
 
26
#define RASTER3D_HEADER_DATA_OFFSET "nofHeaderBytes"
 
27
#define RASTER3D_HEADER_USEXDR "useXdr"
 
28
#define RASTER3D_HEADER_HASINDEX "hasIndex"
 
29
#define RASTER3D_HEADER_UNIT "Units"
 
30
#define RASTER3D_HEADER_VERTICAL_UNIT "VerticalUnits"
 
31
#define RASTER3D_HEADER_VERSION "Version"
 
32
 
 
33
/*---------------------------------------------------------------------------*/
 
34
 
 
35
static int
 
36
Rast3d_readWriteHeader(struct Key_Value *headerKeys, int doRead, int *proj,
 
37
                    int *zone, double *north, double *south, double *east,
 
38
                    double *west, double *top, double *bottom, int *rows,
 
39
                    int *cols, int *depths, double *ew_res, double *ns_res,
 
40
                    double *tb_res, int *tileX, int *tileY, int *tileZ,
 
41
                    int *type, int *compression, int *useRle, int *useLzw,
 
42
                    int *precision, int *dataOffset, int *useXdr,
 
43
                    int *hasIndex, char **unit, int *vertical_unit, int *version)
 
44
{
 
45
    int returnVal;
 
46
    int (*headerInt) (), (*headerDouble) (), (*headerValue) ();
 
47
    int (*headerString) ();
 
48
 
 
49
    if (doRead) {
 
50
        headerDouble = Rast3d_key_get_double;
 
51
        headerInt = Rast3d_key_get_int;
 
52
        headerString = Rast3d_key_get_string;
 
53
        headerValue = Rast3d_key_get_value;
 
54
    }
 
55
    else {
 
56
        headerDouble = Rast3d_key_set_double;
 
57
        headerInt = Rast3d_key_set_int;
 
58
        headerString = Rast3d_key_set_string;
 
59
        headerValue = Rast3d_key_set_value;
 
60
    }
 
61
 
 
62
    returnVal = 1;
 
63
    returnVal &= headerInt(headerKeys, RASTER3D_REGION_PROJ, proj);
 
64
    returnVal &= headerInt(headerKeys, RASTER3D_REGION_ZONE, zone);
 
65
 
 
66
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_NORTH, north);
 
67
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_SOUTH, south);
 
68
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_EAST, east);
 
69
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_WEST, west);
 
70
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_TOP, top);
 
71
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_BOTTOM, bottom);
 
72
 
 
73
    returnVal &= headerInt(headerKeys, RASTER3D_REGION_ROWS, rows);
 
74
    returnVal &= headerInt(headerKeys, RASTER3D_REGION_COLS, cols);
 
75
    returnVal &= headerInt(headerKeys, RASTER3D_REGION_DEPTHS, depths);
 
76
 
 
77
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_NSRES, ns_res);
 
78
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_EWRES, ew_res);
 
79
    returnVal &= headerDouble(headerKeys, RASTER3D_REGION_TBRES, tb_res);
 
80
 
 
81
    returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEX, tileX);
 
82
    returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEY, tileY);
 
83
    returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEZ, tileZ);
 
84
 
 
85
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_TYPE,
 
86
                             "double", "float", DCELL_TYPE, FCELL_TYPE, type);
 
87
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_COMPRESSION,
 
88
                             "0", "1", 0, 1, compression);
 
89
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_USERLE,
 
90
                             "0", "1", 0, 1, useRle);
 
91
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_USELZW,
 
92
                             "0", "1", 0, 1, useLzw);
 
93
 
 
94
    returnVal &= headerInt(headerKeys, RASTER3D_HEADER_PRECISION, precision);
 
95
    returnVal &= headerInt(headerKeys, RASTER3D_HEADER_DATA_OFFSET, dataOffset);
 
96
 
 
97
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_USEXDR,
 
98
                             "0", "1", 0, 1, useXdr);
 
99
    returnVal &= headerValue(headerKeys, RASTER3D_HEADER_HASINDEX,
 
100
                             "0", "1", 0, 1, hasIndex);
 
101
    returnVal &= headerString(headerKeys, RASTER3D_HEADER_UNIT, unit);
 
102
    /* New format and API changes */
 
103
    if(!headerInt(headerKeys, RASTER3D_HEADER_VERTICAL_UNIT, vertical_unit))
 
104
        G_warning("You are using an old raster3d data format, the vertical unit is undefined. "
 
105
                  "Please use r3.support to define the vertical unit to avoid this warning.");
 
106
    /* New format and API changes */
 
107
    if(!headerInt(headerKeys, RASTER3D_HEADER_VERSION, version)) {
 
108
        G_warning("You are using an old raster3d data format, the version is undefined.");
 
109
        *version = 1;
 
110
    }
 
111
 
 
112
    if (returnVal)
 
113
        return 1;
 
114
 
 
115
    Rast3d_error("Rast3d_readWriteHeader: error reading/writing header");
 
116
    return 0;
 
117
}
 
118
 
 
119
/*---------------------------------------------------------------------------*/
 
120
 
 
121
int
 
122
Rast3d_read_header(RASTER3D_Map * map, int *proj, int *zone, double *north,
 
123
               double *south, double *east, double *west, double *top,
 
124
               double *bottom, int *rows, int *cols, int *depths,
 
125
               double *ew_res, double *ns_res, double *tb_res, int *tileX,
 
126
               int *tileY, int *tileZ, int *type, int *compression,
 
127
               int *useRle, int *useLzw, int *precision, int *dataOffset,
 
128
               int *useXdr, int *hasIndex, char **unit, int *vertical_unit,
 
129
               int *version)
 
130
{
 
131
    struct Key_Value *headerKeys;
 
132
    char path[GPATH_MAX];
 
133
 
 
134
    Rast3d_filename(path, RASTER3D_HEADER_ELEMENT, map->fileName, map->mapset);
 
135
    if (access(path, R_OK) != 0) {
 
136
        Rast3d_error("Rast3d_read_header: unable to find [%s]", path);
 
137
        return 0;
 
138
    }
 
139
 
 
140
    headerKeys = G_read_key_value_file(path);
 
141
 
 
142
    if (!Rast3d_readWriteHeader(headerKeys, 1,
 
143
                             proj, zone,
 
144
                             north, south, east, west, top, bottom,
 
145
                             rows, cols, depths,
 
146
                             ew_res, ns_res, tb_res,
 
147
                             tileX, tileY, tileZ,
 
148
                             type, compression, useRle, useLzw, precision,
 
149
                             dataOffset, useXdr, hasIndex, unit, vertical_unit, version)) {
 
150
        Rast3d_error("Rast3d_read_header: error extracting header key(s) of file %s",
 
151
                  path);
 
152
        return 0;
 
153
    }
 
154
 
 
155
    G_free_key_value(headerKeys);
 
156
    return 1;
 
157
}
 
158
 
 
159
/*---------------------------------------------------------------------------*/
 
160
 
 
161
int
 
162
Rast3d_write_header(RASTER3D_Map * map, int proj, int zone, double north, double south,
 
163
                double east, double west, double top, double bottom, int rows,
 
164
                int cols, int depths, double ew_res, double ns_res,
 
165
                double tb_res, int tileX, int tileY, int tileZ, int type,
 
166
                int compression, int useRle, int useLzw, int precision,
 
167
                int dataOffset, int useXdr, int hasIndex, char *unit, int vertical_unit,
 
168
                int version)
 
169
{
 
170
    struct Key_Value *headerKeys;
 
171
    char path[GPATH_MAX];
 
172
 
 
173
    headerKeys = G_create_key_value();
 
174
 
 
175
    if (!Rast3d_readWriteHeader(headerKeys, 0,
 
176
                             &proj, &zone,
 
177
                             &north, &south, &east, &west, &top, &bottom,
 
178
                             &rows, &cols, &depths,
 
179
                             &ew_res, &ns_res, &tb_res,
 
180
                             &tileX, &tileY, &tileZ,
 
181
                             &type, &compression, &useRle, &useLzw,
 
182
                             &precision, &dataOffset, &useXdr, &hasIndex,
 
183
                             &unit, &vertical_unit, &version)) {
 
184
        Rast3d_error("Rast3d_write_header: error adding header key(s) for file %s",
 
185
                  path);
 
186
        return 0;
 
187
    }
 
188
 
 
189
    Rast3d_filename(path, RASTER3D_HEADER_ELEMENT, map->fileName, map->mapset);
 
190
    Rast3d_make_mapset_map_directory(map->fileName);
 
191
    G_write_key_value_file(path, headerKeys);
 
192
 
 
193
    G_free_key_value(headerKeys);
 
194
 
 
195
    return 1;
 
196
}
 
197
/*---------------------------------------------------------------------------*/
 
198
 
 
199
int
 
200
Rast3d_rewrite_header(RASTER3D_Map * map)
 
201
{
 
202
    if (!Rast3d_write_header(map,
 
203
                         map->region.proj, map->region.zone,
 
204
                         map->region.north, map->region.south,
 
205
                         map->region.east, map->region.west,
 
206
                         map->region.top, map->region.bottom,
 
207
                         map->region.rows, map->region.cols,
 
208
                         map->region.depths,
 
209
                         map->region.ew_res, map->region.ns_res,
 
210
                         map->region.tb_res,
 
211
                         map->tileX, map->tileY, map->tileZ,
 
212
                         map->type,
 
213
                         map->compression, map->useRle, map->useLzw,
 
214
                         map->precision, map->offset, map->useXdr,
 
215
                         map->hasIndex, map->unit, map->vertical_unit,
 
216
                         map->version)) {
 
217
        G_warning(_("Unable to write header for 3D raster map <%s>"), map->fileName);
 
218
        return 0;
 
219
    }
 
220
    return 1;
 
221
}
 
222
 
 
223
/*---------------------------------------------------------------------------*/
 
224
 
 
225
 
 
226
/*!
 
227
 * \brief 
 
228
 *
 
229
 *  Returns a number
 
230
 * which encodes multiplicity <em>n</em> of <em>cacheCode</em>. This value can be used
 
231
 * to specify the size of the cache.
 
232
 * If <em>cacheCode</em> is the size (in tiles) of the cache the function returns
 
233
 * <em>cacheCode * n</em>.
 
234
 * If <em>cacheCode</em> is RASTER3D_USE_CACHE_DEFAULT the function returns
 
235
 * RASTER3D_USE_CACHE_DEFAULT.
 
236
 * If <em>cacheCode</em> is RASTER3D_USE_CACHE_??? the function returns a value
 
237
 * encoding RASTER3D_USE_CACHE_??? and <em>n</em>. Here RASTER3D_USE_CACHE_??? is one
 
238
 * of RASTER3D_USE_CACHE_X, RASTER3D_USE_CACHE_Y, RASTER3D_USE_CACHE_Z,
 
239
 * RASTER3D_USE_CACHE_XY, RASTER3D_USE_CACHE_XZ, RASTER3D_USE_CACHE_YZ, or
 
240
 * RASTER3D_USE_CACHE_XYZ, where e.g.  RASTER3D_USE_CACHE_X specifies that the cache
 
241
 * should store as many tiles as there exist in one row along the x-axis of the
 
242
 * tile cube, and RASTER3D_USE_CACHE_XY specifies that the cache should store as
 
243
 * many tiles as there exist in one slice of the tile cube with constant Z
 
244
 * coordinate.
 
245
 *
 
246
 *  \param cacheCode
 
247
 *  \param n
 
248
 *  \return int
 
249
 */
 
250
 
 
251
int Rast3d_cache_size_encode(int cacheCode, int n)
 
252
{
 
253
    if (cacheCode >= RASTER3D_NO_CACHE)
 
254
        return cacheCode * n;
 
255
    if (cacheCode == RASTER3D_USE_CACHE_DEFAULT)
 
256
        return cacheCode;
 
257
 
 
258
    if (cacheCode < RASTER3D_USE_CACHE_XYZ)
 
259
        Rast3d_fatal_error("Rast3d_cache_size_encode: invalid cache code");
 
260
 
 
261
    return n * (-10) + cacheCode;
 
262
}
 
263
 
 
264
/*---------------------------------------------------------------------------*/
 
265
 
 
266
int Rast3d__compute_cache_size(RASTER3D_Map * map, int cacheCode)
 
267
{
 
268
    int n, size;
 
269
 
 
270
    if (cacheCode >= RASTER3D_NO_CACHE)
 
271
        return cacheCode;
 
272
    if (cacheCode == RASTER3D_USE_CACHE_DEFAULT)
 
273
        return RASTER3D_MIN(g3d_cache_default, map->nTiles);
 
274
 
 
275
    n = -(cacheCode / 10);
 
276
    n = RASTER3D_MAX(1, n);
 
277
    cacheCode = -((-cacheCode) % 10);
 
278
 
 
279
    if (cacheCode == RASTER3D_USE_CACHE_X)
 
280
        size = map->nx * n;
 
281
    else if (cacheCode == RASTER3D_USE_CACHE_Y)
 
282
        size = map->ny * n;
 
283
    else if (cacheCode == RASTER3D_USE_CACHE_Z)
 
284
        size = map->nz * n;
 
285
    else if (cacheCode == RASTER3D_USE_CACHE_XY)
 
286
        size = map->nxy * n;
 
287
    else if (cacheCode == RASTER3D_USE_CACHE_XZ)
 
288
        size = map->nx * map->nz * n;
 
289
    else if (cacheCode == RASTER3D_USE_CACHE_YZ)
 
290
        size = map->ny * map->nz * n;
 
291
    else if (cacheCode == RASTER3D_USE_CACHE_XYZ)
 
292
        size = map->nTiles;
 
293
    else
 
294
        Rast3d_fatal_error("Rast3d__compute_cache_size: invalid cache code");
 
295
 
 
296
    return RASTER3D_MIN(size, map->nTiles);
 
297
}
 
298
 
 
299
/*---------------------------------------------------------------------------*/
 
300
 
 
301
/* this function does actually more than filling the header fields of the */
 
302
/* RASTER3D-Map structure. It also allocates memory for compression and xdr, */
 
303
/* and initializes the index and cache. This function should be taken apart. */
 
304
 
 
305
int
 
306
Rast3d_fill_header(RASTER3D_Map * map, int operation, int compression, int useRle,
 
307
               int useLzw, int type, int precision, int cache, int hasIndex,
 
308
               int useXdr, int typeIntern, int nofHeaderBytes, int tileX,
 
309
               int tileY, int tileZ, int proj, int zone, double north,
 
310
               double south, double east, double west, double top,
 
311
               double bottom, int rows, int cols, int depths, double ew_res,
 
312
               double ns_res, double tb_res, char *unit, int vertical_unit,
 
313
               int version)
 
314
{
 
315
    if (!RASTER3D_VALID_OPERATION(operation))
 
316
        Rast3d_fatal_error("Rast3d_fill_header: operation not valid\n");
 
317
 
 
318
    map->version = version;
 
319
 
 
320
    map->operation = operation;
 
321
 
 
322
    map->unit = G_store(unit);
 
323
    map->vertical_unit = vertical_unit;
 
324
 
 
325
    map->region.proj = proj;
 
326
    map->region.zone = zone;
 
327
 
 
328
    map->region.north = north;
 
329
    map->region.south = south;
 
330
    map->region.east = east;
 
331
    map->region.west = west;
 
332
    map->region.top = top;
 
333
    map->region.bottom = bottom;
 
334
 
 
335
    map->region.rows = rows;
 
336
    map->region.cols = cols;
 
337
    map->region.depths = depths;
 
338
 
 
339
    map->region.ew_res = ew_res;
 
340
    map->region.ns_res = ns_res;
 
341
    map->region.tb_res = tb_res;
 
342
 
 
343
    Rast3d_adjust_region(&(map->region));
 
344
 
 
345
    map->tileX = tileX;
 
346
    map->tileY = tileY;
 
347
    map->tileZ = tileZ;
 
348
    map->tileXY = map->tileX * map->tileY;
 
349
    map->tileSize = map->tileXY * map->tileZ;
 
350
 
 
351
    map->nx = (map->region.cols - 1) / tileX + 1;
 
352
    map->ny = (map->region.rows - 1) / tileY + 1;
 
353
    map->nz = (map->region.depths - 1) / tileZ + 1;
 
354
    map->nxy = map->nx * map->ny;
 
355
    map->nTiles = map->nxy * map->nz;
 
356
 
 
357
    if ((map->region.cols) % map->tileX != 0)
 
358
        map->clipX = map->nx - 1;
 
359
    else
 
360
        map->clipX = -1;
 
361
    if ((map->region.rows) % map->tileY != 0)
 
362
        map->clipY = map->ny - 1;
 
363
    else
 
364
        map->clipY = -1;
 
365
    if ((map->region.depths) % map->tileZ != 0)
 
366
        map->clipZ = map->nz - 1;
 
367
    else
 
368
        map->clipZ = -1;
 
369
 
 
370
    if ((type != FCELL_TYPE) && (type != DCELL_TYPE))
 
371
        Rast3d_fatal_error("Rast3d_fill_header: invalid type");
 
372
    map->type = type;
 
373
 
 
374
    if ((typeIntern != FCELL_TYPE) && (typeIntern != DCELL_TYPE))
 
375
        Rast3d_fatal_error("Rast3d_fill_header: invalid type");
 
376
    map->typeIntern = typeIntern;
 
377
 
 
378
    if (!RASTER3D_VALID_XDR_OPTION(useXdr))
 
379
        Rast3d_fatal_error("Rast3d_fill_header: invalid xdr option");
 
380
    map->useXdr = useXdr;       /* Only kept for backward compatibility */
 
381
 
 
382
    map->offset = nofHeaderBytes;
 
383
 
 
384
    if ((map->fileEndPtr = lseek(map->data_fd, (long)0, SEEK_END)) == -1) {
 
385
        Rast3d_error("Rast3d_fill_header: can't position file");
 
386
        return 0;
 
387
    }
 
388
 
 
389
    map->useCache = (cache != RASTER3D_NO_CACHE);
 
390
 
 
391
    map->numLengthIntern = Rast3d_length(map->typeIntern);
 
392
    map->numLengthExtern = Rast3d_extern_length(map->type);
 
393
 
 
394
    map->compression = compression;
 
395
    map->useRle = useRle;       /* Only kept for backward compatibility */
 
396
    map->useLzw = useLzw;       /* Only kept for backward compatibility */
 
397
    map->precision = precision;
 
398
 
 
399
#define RLE_STATUS_BYTES 2
 
400
 
 
401
    if (map->compression != RASTER3D_NO_COMPRESSION) {
 
402
        if (tmpCompress == NULL) {
 
403
            tmpCompressLength = map->tileSize *
 
404
                RASTER3D_MAX(map->numLengthIntern, map->numLengthExtern) +
 
405
                RLE_STATUS_BYTES;
 
406
            tmpCompress = Rast3d_malloc(tmpCompressLength);
 
407
            if (tmpCompress == NULL) {
 
408
                Rast3d_error("Rast3d_fill_header: error in Rast3d_malloc");
 
409
                return 0;
 
410
            }
 
411
        }
 
412
        else if (map->tileSize *
 
413
                 RASTER3D_MAX(map->numLengthIntern, map->numLengthExtern)
 
414
                 + RLE_STATUS_BYTES > tmpCompressLength) {
 
415
            tmpCompressLength = map->tileSize *
 
416
                RASTER3D_MAX(map->numLengthIntern, map->numLengthExtern) +
 
417
                RLE_STATUS_BYTES;
 
418
            tmpCompress = Rast3d_realloc(tmpCompress, tmpCompressLength);
 
419
            if (tmpCompress == NULL) {
 
420
                Rast3d_error("Rast3d_fill_header: error in Rast3d_realloc");
 
421
                return 0;
 
422
            }
 
423
        }
 
424
    }
 
425
 
 
426
#define XDR_MISUSE_BYTES 10
 
427
 
 
428
    if (!Rast3d_init_fp_xdr(map, XDR_MISUSE_BYTES)) {
 
429
        Rast3d_error("Rast3d_fill_header: error in Rast3d_init_fp_xdr");
 
430
        return 0;
 
431
    }
 
432
 
 
433
    if ((!map->useCache) ||
 
434
        ((cache == RASTER3D_USE_CACHE_DEFAULT) && (g3d_cache_default == 0))) {
 
435
        map->useCache = 0;
 
436
        map->cache = NULL;
 
437
        /* allocate one tile buffer */
 
438
        map->data = Rast3d_malloc(map->tileSize * map->numLengthIntern);
 
439
        if (map->data == NULL) {
 
440
            Rast3d_error("Rast3d_fill_header: error in Rast3d_malloc");
 
441
            return 0;
 
442
        }
 
443
        map->currentIndex = -1;
 
444
    }
 
445
    else {
 
446
        if (!Rast3d_init_cache(map,
 
447
                           RASTER3D_MAX(1,
 
448
                                   RASTER3D_MIN(Rast3d__compute_cache_size(map, cache),
 
449
                                           g3d_cache_max /
 
450
                                           map->tileSize /
 
451
                                           map->numLengthIntern)))) {
 
452
            Rast3d_error("Rast3d_fill_header: error in Rast3d_init_cache");
 
453
            return 0;
 
454
        }
 
455
    }
 
456
 
 
457
    if (!Rast3d_init_index(map, hasIndex)) {
 
458
        Rast3d_error("Rast3d_fill_header: error in Rast3d_init_index");
 
459
        return 0;
 
460
    }
 
461
 
 
462
    return 1;
 
463
}