5
#include <grass/raster3d.h>
6
#include <grass/glocale.h>
7
#include "raster3d_intern.h"
9
/*---------------------------------------------------------------------------*/
12
int tmpCompressLength;
16
/*---------------------------------------------------------------------------*/
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"
33
/*---------------------------------------------------------------------------*/
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)
46
int (*headerInt) (), (*headerDouble) (), (*headerValue) ();
47
int (*headerString) ();
50
headerDouble = Rast3d_key_get_double;
51
headerInt = Rast3d_key_get_int;
52
headerString = Rast3d_key_get_string;
53
headerValue = Rast3d_key_get_value;
56
headerDouble = Rast3d_key_set_double;
57
headerInt = Rast3d_key_set_int;
58
headerString = Rast3d_key_set_string;
59
headerValue = Rast3d_key_set_value;
63
returnVal &= headerInt(headerKeys, RASTER3D_REGION_PROJ, proj);
64
returnVal &= headerInt(headerKeys, RASTER3D_REGION_ZONE, zone);
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);
73
returnVal &= headerInt(headerKeys, RASTER3D_REGION_ROWS, rows);
74
returnVal &= headerInt(headerKeys, RASTER3D_REGION_COLS, cols);
75
returnVal &= headerInt(headerKeys, RASTER3D_REGION_DEPTHS, depths);
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);
81
returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEX, tileX);
82
returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEY, tileY);
83
returnVal &= headerInt(headerKeys, RASTER3D_HEADER_TILEZ, tileZ);
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);
94
returnVal &= headerInt(headerKeys, RASTER3D_HEADER_PRECISION, precision);
95
returnVal &= headerInt(headerKeys, RASTER3D_HEADER_DATA_OFFSET, dataOffset);
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.");
115
Rast3d_error("Rast3d_readWriteHeader: error reading/writing header");
119
/*---------------------------------------------------------------------------*/
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,
131
struct Key_Value *headerKeys;
132
char path[GPATH_MAX];
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);
140
headerKeys = G_read_key_value_file(path);
142
if (!Rast3d_readWriteHeader(headerKeys, 1,
144
north, south, east, west, top, bottom,
146
ew_res, ns_res, tb_res,
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",
155
G_free_key_value(headerKeys);
159
/*---------------------------------------------------------------------------*/
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,
170
struct Key_Value *headerKeys;
171
char path[GPATH_MAX];
173
headerKeys = G_create_key_value();
175
if (!Rast3d_readWriteHeader(headerKeys, 0,
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",
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);
193
G_free_key_value(headerKeys);
197
/*---------------------------------------------------------------------------*/
200
Rast3d_rewrite_header(RASTER3D_Map * map)
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,
209
map->region.ew_res, map->region.ns_res,
211
map->tileX, map->tileY, map->tileZ,
213
map->compression, map->useRle, map->useLzw,
214
map->precision, map->offset, map->useXdr,
215
map->hasIndex, map->unit, map->vertical_unit,
217
G_warning(_("Unable to write header for 3D raster map <%s>"), map->fileName);
223
/*---------------------------------------------------------------------------*/
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
251
int Rast3d_cache_size_encode(int cacheCode, int n)
253
if (cacheCode >= RASTER3D_NO_CACHE)
254
return cacheCode * n;
255
if (cacheCode == RASTER3D_USE_CACHE_DEFAULT)
258
if (cacheCode < RASTER3D_USE_CACHE_XYZ)
259
Rast3d_fatal_error("Rast3d_cache_size_encode: invalid cache code");
261
return n * (-10) + cacheCode;
264
/*---------------------------------------------------------------------------*/
266
int Rast3d__compute_cache_size(RASTER3D_Map * map, int cacheCode)
270
if (cacheCode >= RASTER3D_NO_CACHE)
272
if (cacheCode == RASTER3D_USE_CACHE_DEFAULT)
273
return RASTER3D_MIN(g3d_cache_default, map->nTiles);
275
n = -(cacheCode / 10);
276
n = RASTER3D_MAX(1, n);
277
cacheCode = -((-cacheCode) % 10);
279
if (cacheCode == RASTER3D_USE_CACHE_X)
281
else if (cacheCode == RASTER3D_USE_CACHE_Y)
283
else if (cacheCode == RASTER3D_USE_CACHE_Z)
285
else if (cacheCode == RASTER3D_USE_CACHE_XY)
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)
294
Rast3d_fatal_error("Rast3d__compute_cache_size: invalid cache code");
296
return RASTER3D_MIN(size, map->nTiles);
299
/*---------------------------------------------------------------------------*/
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. */
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,
315
if (!RASTER3D_VALID_OPERATION(operation))
316
Rast3d_fatal_error("Rast3d_fill_header: operation not valid\n");
318
map->version = version;
320
map->operation = operation;
322
map->unit = G_store(unit);
323
map->vertical_unit = vertical_unit;
325
map->region.proj = proj;
326
map->region.zone = zone;
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;
335
map->region.rows = rows;
336
map->region.cols = cols;
337
map->region.depths = depths;
339
map->region.ew_res = ew_res;
340
map->region.ns_res = ns_res;
341
map->region.tb_res = tb_res;
343
Rast3d_adjust_region(&(map->region));
348
map->tileXY = map->tileX * map->tileY;
349
map->tileSize = map->tileXY * map->tileZ;
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;
357
if ((map->region.cols) % map->tileX != 0)
358
map->clipX = map->nx - 1;
361
if ((map->region.rows) % map->tileY != 0)
362
map->clipY = map->ny - 1;
365
if ((map->region.depths) % map->tileZ != 0)
366
map->clipZ = map->nz - 1;
370
if ((type != FCELL_TYPE) && (type != DCELL_TYPE))
371
Rast3d_fatal_error("Rast3d_fill_header: invalid type");
374
if ((typeIntern != FCELL_TYPE) && (typeIntern != DCELL_TYPE))
375
Rast3d_fatal_error("Rast3d_fill_header: invalid type");
376
map->typeIntern = typeIntern;
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 */
382
map->offset = nofHeaderBytes;
384
if ((map->fileEndPtr = lseek(map->data_fd, (long)0, SEEK_END)) == -1) {
385
Rast3d_error("Rast3d_fill_header: can't position file");
389
map->useCache = (cache != RASTER3D_NO_CACHE);
391
map->numLengthIntern = Rast3d_length(map->typeIntern);
392
map->numLengthExtern = Rast3d_extern_length(map->type);
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;
399
#define RLE_STATUS_BYTES 2
401
if (map->compression != RASTER3D_NO_COMPRESSION) {
402
if (tmpCompress == NULL) {
403
tmpCompressLength = map->tileSize *
404
RASTER3D_MAX(map->numLengthIntern, map->numLengthExtern) +
406
tmpCompress = Rast3d_malloc(tmpCompressLength);
407
if (tmpCompress == NULL) {
408
Rast3d_error("Rast3d_fill_header: error in Rast3d_malloc");
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) +
418
tmpCompress = Rast3d_realloc(tmpCompress, tmpCompressLength);
419
if (tmpCompress == NULL) {
420
Rast3d_error("Rast3d_fill_header: error in Rast3d_realloc");
426
#define XDR_MISUSE_BYTES 10
428
if (!Rast3d_init_fp_xdr(map, XDR_MISUSE_BYTES)) {
429
Rast3d_error("Rast3d_fill_header: error in Rast3d_init_fp_xdr");
433
if ((!map->useCache) ||
434
((cache == RASTER3D_USE_CACHE_DEFAULT) && (g3d_cache_default == 0))) {
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");
443
map->currentIndex = -1;
446
if (!Rast3d_init_cache(map,
448
RASTER3D_MIN(Rast3d__compute_cache_size(map, cache),
451
map->numLengthIntern)))) {
452
Rast3d_error("Rast3d_fill_header: error in Rast3d_init_cache");
457
if (!Rast3d_init_index(map, hasIndex)) {
458
Rast3d_error("Rast3d_fill_header: error in Rast3d_init_index");