GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
g3d/header.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <rpc/types.h>
6 #include <rpc/xdr.h>
7 #include <grass/G3d.h>
8 #include "G3d_intern.h"
9 
10 /*---------------------------------------------------------------------------*/
11 
14 void *xdr;
16 
17 /*---------------------------------------------------------------------------*/
18 
19 #define G3D_HEADER_TILEX "TileDimensionX"
20 #define G3D_HEADER_TILEY "TileDimensionY"
21 #define G3D_HEADER_TILEZ "TileDimensionZ"
22 #define G3D_HEADER_TYPE "CellType"
23 #define G3D_HEADER_COMPRESSION "useCompression"
24 #define G3D_HEADER_USERLE "useRle"
25 #define G3D_HEADER_USELZW "useLzw"
26 #define G3D_HEADER_PRECISION "Precision"
27 #define G3D_HEADER_DATA_OFFSET "nofHeaderBytes"
28 #define G3D_HEADER_USEXDR "useXdr"
29 #define G3D_HEADER_HASINDEX "hasIndex"
30 #define G3D_HEADER_UNIT "Units"
31 
32 /*---------------------------------------------------------------------------*/
33 
34 static int
35 G3d_readWriteHeader(struct Key_Value *headerKeys, int doRead, int *proj,
36  int *zone, double *north, double *south, double *east,
37  double *west, double *top, double *bottom, int *rows,
38  int *cols, int *depths, double *ew_res, double *ns_res,
39  double *tb_res, int *tileX, int *tileY, int *tileZ,
40  int *type, int *compression, int *useRle, int *useLzw,
41  int *precision, int *dataOffset, int *useXdr,
42  int *hasIndex, char **unit)
43 {
44  int returnVal;
45  int (*headerInt) (), (*headerDouble) (), (*headerValue) ();
46  int (*headerString) ();
47 
48  if (doRead) {
49  headerDouble = G3d_keyGetDouble;
50  headerInt = G3d_keyGetInt;
51  headerString = G3d_keyGetString;
52  headerValue = G3d_keyGetValue;
53  }
54  else {
55  headerDouble = G3d_keySetDouble;
56  headerInt = G3d_keySetInt;
57  headerString = G3d_keySetString;
58  headerValue = G3d_keySetValue;
59  }
60 
61  returnVal = 1;
62  returnVal &= headerInt(headerKeys, G3D_REGION_PROJ, proj);
63  returnVal &= headerInt(headerKeys, G3D_REGION_ZONE, zone);
64 
65  returnVal &= headerDouble(headerKeys, G3D_REGION_NORTH, north);
66  returnVal &= headerDouble(headerKeys, G3D_REGION_SOUTH, south);
67  returnVal &= headerDouble(headerKeys, G3D_REGION_EAST, east);
68  returnVal &= headerDouble(headerKeys, G3D_REGION_WEST, west);
69  returnVal &= headerDouble(headerKeys, G3D_REGION_TOP, top);
70  returnVal &= headerDouble(headerKeys, G3D_REGION_BOTTOM, bottom);
71 
72  returnVal &= headerInt(headerKeys, G3D_REGION_ROWS, rows);
73  returnVal &= headerInt(headerKeys, G3D_REGION_COLS, cols);
74  returnVal &= headerInt(headerKeys, G3D_REGION_DEPTHS, depths);
75 
76  returnVal &= headerDouble(headerKeys, G3D_REGION_NSRES, ns_res);
77  returnVal &= headerDouble(headerKeys, G3D_REGION_EWRES, ew_res);
78  returnVal &= headerDouble(headerKeys, G3D_REGION_TBRES, tb_res);
79 
80  returnVal &= headerInt(headerKeys, G3D_HEADER_TILEX, tileX);
81  returnVal &= headerInt(headerKeys, G3D_HEADER_TILEY, tileY);
82  returnVal &= headerInt(headerKeys, G3D_HEADER_TILEZ, tileZ);
83 
84  returnVal &= headerValue(headerKeys, G3D_HEADER_TYPE,
85  "double", "float", DCELL_TYPE, FCELL_TYPE, type);
86  returnVal &= headerValue(headerKeys, G3D_HEADER_COMPRESSION,
87  "0", "1", 0, 1, compression);
88  returnVal &= headerValue(headerKeys, G3D_HEADER_USERLE,
89  "0", "1", 0, 1, useRle);
90  returnVal &= headerValue(headerKeys, G3D_HEADER_USELZW,
91  "0", "1", 0, 1, useLzw);
92 
93  returnVal &= headerInt(headerKeys, G3D_HEADER_PRECISION, precision);
94  returnVal &= headerInt(headerKeys, G3D_HEADER_DATA_OFFSET, dataOffset);
95 
96  returnVal &= headerValue(headerKeys, G3D_HEADER_USEXDR,
97  "0", "1", 0, 1, useXdr);
98  returnVal &= headerValue(headerKeys, G3D_HEADER_HASINDEX,
99  "0", "1", 0, 1, hasIndex);
100  returnVal &= headerString(headerKeys, G3D_HEADER_UNIT, unit);
101 
102  if (returnVal)
103  return 1;
104 
105  G3d_error("G3d_readWriteHeader: error writing header");
106  return 0;
107 }
108 
109 /*---------------------------------------------------------------------------*/
110 
111 int
112 G3d_readHeader(G3D_Map * map, int *proj, int *zone, double *north,
113  double *south, double *east, double *west, double *top,
114  double *bottom, int *rows, int *cols, int *depths,
115  double *ew_res, double *ns_res, double *tb_res, int *tileX,
116  int *tileY, int *tileZ, int *type, int *compression,
117  int *useRle, int *useLzw, int *precision, int *dataOffset,
118  int *useXdr, int *hasIndex, char **unit)
119 {
120  struct Key_Value *headerKeys;
121  char path[GPATH_MAX];
122  int status;
123 
124  G3d_filename(path, G3D_HEADER_ELEMENT, map->fileName, map->mapset);
125  if (access(path, R_OK) != 0) {
126  G3d_error("G3d_readHeader: unable to find [%s]", path);
127  return 0;
128  }
129 
130  headerKeys = G_read_key_value_file(path, &status);
131  if (status != 0) {
132  G3d_error("G3d_readHeader: Unable to open %s", path);
133  return 0;
134  }
135 
136  if (!G3d_readWriteHeader(headerKeys, 1,
137  proj, zone,
138  north, south, east, west, top, bottom,
139  rows, cols, depths,
140  ew_res, ns_res, tb_res,
141  tileX, tileY, tileZ,
142  type, compression, useRle, useLzw, precision,
143  dataOffset, useXdr, hasIndex, unit)) {
144  G3d_error("G3d_readHeader: error extracting header key(s) of file %s",
145  path);
146  return 0;
147  }
148 
149  G_free_key_value(headerKeys);
150  return 1;
151 }
152 
153 /*---------------------------------------------------------------------------*/
154 
155 int
156 G3d_writeHeader(G3D_Map * map, int proj, int zone, double north, double south,
157  double east, double west, double top, double bottom, int rows,
158  int cols, int depths, double ew_res, double ns_res,
159  double tb_res, int tileX, int tileY, int tileZ, int type,
160  int compression, int useRle, int useLzw, int precision,
161  int dataOffset, int useXdr, int hasIndex, char *unit)
162 {
163  struct Key_Value *headerKeys;
164  char path[GPATH_MAX];
165  int status;
166 
167  headerKeys = G_create_key_value();
168 
169  if (!G3d_readWriteHeader(headerKeys, 0,
170  &proj, &zone,
171  &north, &south, &east, &west, &top, &bottom,
172  &rows, &cols, &depths,
173  &ew_res, &ns_res, &tb_res,
174  &tileX, &tileY, &tileZ,
175  &type, &compression, &useRle, &useLzw,
176  &precision, &dataOffset, &useXdr, &hasIndex,
177  &unit)) {
178  G3d_error("G3d_writeHeader: error adding header key(s) for file %s",
179  path);
180  return 0;
181  }
182 
183  G3d_filename(path, G3D_HEADER_ELEMENT, map->fileName, map->mapset);
184  G3d_makeMapsetMapDirectory(map->fileName);
185  G_write_key_value_file(path, headerKeys, &status);
186 
187  G_free_key_value(headerKeys);
188 
189  if (status == 0)
190  return 1;
191 
192  G3d_error("G3d_writeHeader: error writing header file %s", path);
193  return 0;
194 }
195 
196 /*---------------------------------------------------------------------------*/
197 
198 
224 int G3d_cacheSizeEncode(int cacheCode, int n)
225 {
226  if (cacheCode >= G3D_NO_CACHE)
227  return cacheCode * n;
228  if (cacheCode == G3D_USE_CACHE_DEFAULT)
229  return cacheCode;
230 
231  if (cacheCode < G3D_USE_CACHE_XYZ)
232  G3d_fatalError("G3d_cacheSizeEncode: invalid cache code");
233 
234  return n * (-10) + cacheCode;
235 }
236 
237 /*---------------------------------------------------------------------------*/
238 
239 int G3d__computeCacheSize(G3D_Map * map, int cacheCode)
240 {
241  int n, size;
242 
243  if (cacheCode >= G3D_NO_CACHE)
244  return cacheCode;
245  if (cacheCode == G3D_USE_CACHE_DEFAULT)
246  return G3D_MIN(g3d_cache_default, map->nTiles);
247 
248  n = -(cacheCode / 10);
249  n = G3D_MAX(1, n);
250  cacheCode = -((-cacheCode) % 10);
251 
252  if (cacheCode == G3D_USE_CACHE_X)
253  size = map->nx * n;
254  else if (cacheCode == G3D_USE_CACHE_Y)
255  size = map->ny * n;
256  else if (cacheCode == G3D_USE_CACHE_Z)
257  size = map->nz * n;
258  else if (cacheCode == G3D_USE_CACHE_XY)
259  size = map->nxy * n;
260  else if (cacheCode == G3D_USE_CACHE_XZ)
261  size = map->nx * map->nz * n;
262  else if (cacheCode == G3D_USE_CACHE_YZ)
263  size = map->ny * map->nz * n;
264  else if (cacheCode == G3D_USE_CACHE_XYZ)
265  size = map->nTiles;
266  else
267  G3d_fatalError("G3d__computeCacheSize: invalid cache code");
268 
269  return G3D_MIN(size, map->nTiles);
270 }
271 
272 /*---------------------------------------------------------------------------*/
273 
274 /* this function does actually more than filling the header fields of the */
275 /* G3D-Map structure. It also allocates memory for compression and xdr, */
276 /* and initializes the index and cache. This function should be taken apart. */
277 
278 int
279 G3d_fillHeader(G3D_Map * map, int operation, int compression, int useRle,
280  int useLzw, int type, int precision, int cache, int hasIndex,
281  int useXdr, int typeIntern, int nofHeaderBytes, int tileX,
282  int tileY, int tileZ, int proj, int zone, double north,
283  double south, double east, double west, double top,
284  double bottom, int rows, int cols, int depths, double ew_res,
285  double ns_res, double tb_res, char *unit)
286 {
287  if (!G3D_VALID_OPERATION(operation))
288  G3d_fatalError("G3d_fillHeader: operation not valid\n");
289 
290  map->operation = operation;
291 
292  map->unit = G_store(unit);
293 
294  map->region.proj = proj;
295  map->region.zone = zone;
296 
297  map->region.north = north;
298  map->region.south = south;
299  map->region.east = east;
300  map->region.west = west;
301  map->region.top = top;
302  map->region.bottom = bottom;
303 
304  map->region.rows = rows;
305  map->region.cols = cols;
306  map->region.depths = depths;
307 
308  map->region.ew_res = ew_res;
309  map->region.ns_res = ns_res;
310  map->region.tb_res = tb_res;
311 
312  G3d_adjustRegion(&(map->region));
313 
314  map->tileX = tileX;
315  map->tileY = tileY;
316  map->tileZ = tileZ;
317  map->tileXY = map->tileX * map->tileY;
318  map->tileSize = map->tileXY * map->tileZ;
319 
320  map->nx = (map->region.cols - 1) / tileX + 1;
321  map->ny = (map->region.rows - 1) / tileY + 1;
322  map->nz = (map->region.depths - 1) / tileZ + 1;
323  map->nxy = map->nx * map->ny;
324  map->nTiles = map->nxy * map->nz;
325 
326  if ((map->region.cols) % map->tileX != 0)
327  map->clipX = map->nx - 1;
328  else
329  map->clipX = -1;
330  if ((map->region.rows) % map->tileY != 0)
331  map->clipY = map->ny - 1;
332  else
333  map->clipY = -1;
334  if ((map->region.depths) % map->tileZ != 0)
335  map->clipZ = map->nz - 1;
336  else
337  map->clipZ = -1;
338 
339  if ((type != FCELL_TYPE) && (type != DCELL_TYPE))
340  G3d_fatalError("G3d_fillHeader: invalid type");
341  map->type = type;
342 
343  if ((typeIntern != FCELL_TYPE) && (typeIntern != DCELL_TYPE))
344  G3d_fatalError("G3d_fillHeader: invalid type");
345  map->typeIntern = typeIntern;
346 
347  if (!G3D_VALID_XDR_OPTION(useXdr))
348  G3d_fatalError("G3d_fillHeader: invalid xdr option");
349  map->useXdr = useXdr;
350 
351  map->offset = nofHeaderBytes;
352 
353  if ((map->fileEndPtr = lseek(map->data_fd, (long)0, SEEK_END)) == -1) {
354  G3d_error("G3d_fillHeader: can't position file");
355  return 0;
356  }
357 
358  map->useCache = (cache != G3D_NO_CACHE);
359 
360  map->numLengthIntern = G3d_length(map->typeIntern);
361  map->numLengthExtern = G3d_externLength(map->type);
362 
363  map->compression = compression;
364  map->useRle = useRle;
365  map->useLzw = useLzw;
366  map->precision = precision;
367 
368 #define RLE_STATUS_BYTES 2
369 
370  if (map->compression != G3D_NO_COMPRESSION) {
371  if (tmpCompress == NULL) {
372  tmpCompressLength = map->tileSize *
373  G3D_MAX(map->numLengthIntern, map->numLengthExtern) +
376  if (tmpCompress == NULL) {
377  G3d_error("G3d_fillHeader: error in G3d_malloc");
378  return 0;
379  }
380  }
381  else if (map->tileSize *
382  G3D_MAX(map->numLengthIntern, map->numLengthExtern)
384  tmpCompressLength = map->tileSize *
385  G3D_MAX(map->numLengthIntern, map->numLengthExtern) +
388  if (tmpCompress == NULL) {
389  G3d_error("G3d_fillHeader: error in G3d_realloc");
390  return 0;
391  }
392  }
393  }
394 
395 #define XDR_MISUSE_BYTES 10
396 
397  if (!G3d_initFpXdr(map, XDR_MISUSE_BYTES)) {
398  G3d_error("G3d_fillHeader: error in G3d_initFpXdr");
399  return 0;
400  }
401 
402  if ((!map->useCache) ||
403  ((cache == G3D_USE_CACHE_DEFAULT) && (g3d_cache_default == 0))) {
404  map->useCache = 0;
405  map->cache = NULL;
406  /* allocate one tile buffer */
407  map->data = G3d_malloc(map->tileSize * map->numLengthIntern);
408  if (map->data == NULL) {
409  G3d_error("G3d_fillHeader: error in G3d_malloc");
410  return 0;
411  }
412  map->currentIndex = -1;
413  }
414  else {
415  if (!G3d_initCache(map,
416  G3D_MAX(1,
417  G3D_MIN(G3d__computeCacheSize(map, cache),
418  g3d_cache_max /
419  map->tileSize /
420  map->numLengthIntern)))) {
421  G3d_error("G3d_fillHeader: error in G3d_initCache");
422  return 0;
423  }
424  }
425 
426  if (!G3d_initIndex(map, hasIndex)) {
427  G3d_error("G3d_fillHeader: error in G3d_initIndex");
428  return 0;
429  }
430 
431  return 1;
432 }