GRASS Programmer's Manual  6.4.2(2012)
g3d/header.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <sys/types.h>
00004 #include <unistd.h>
00005 #include <rpc/types.h>
00006 #include <rpc/xdr.h>
00007 #include <grass/G3d.h>
00008 #include "G3d_intern.h"
00009 
00010 /*---------------------------------------------------------------------------*/
00011 
00012 void *tmpCompress;
00013 int tmpCompressLength;
00014 void *xdr;
00015 int xdrLength;
00016 
00017 /*---------------------------------------------------------------------------*/
00018 
00019 #define G3D_HEADER_TILEX "TileDimensionX"
00020 #define G3D_HEADER_TILEY "TileDimensionY"
00021 #define G3D_HEADER_TILEZ "TileDimensionZ"
00022 #define G3D_HEADER_TYPE "CellType"
00023 #define G3D_HEADER_COMPRESSION "useCompression"
00024 #define G3D_HEADER_USERLE "useRle"
00025 #define G3D_HEADER_USELZW "useLzw"
00026 #define G3D_HEADER_PRECISION "Precision"
00027 #define G3D_HEADER_DATA_OFFSET "nofHeaderBytes"
00028 #define G3D_HEADER_USEXDR "useXdr"
00029 #define G3D_HEADER_HASINDEX "hasIndex"
00030 #define G3D_HEADER_UNIT "Units"
00031 
00032 /*---------------------------------------------------------------------------*/
00033 
00034 static int
00035 G3d_readWriteHeader(struct Key_Value *headerKeys, int doRead, int *proj,
00036                     int *zone, double *north, double *south, double *east,
00037                     double *west, double *top, double *bottom, int *rows,
00038                     int *cols, int *depths, double *ew_res, double *ns_res,
00039                     double *tb_res, int *tileX, int *tileY, int *tileZ,
00040                     int *type, int *compression, int *useRle, int *useLzw,
00041                     int *precision, int *dataOffset, int *useXdr,
00042                     int *hasIndex, char **unit)
00043 {
00044     int returnVal;
00045     int (*headerInt) (), (*headerDouble) (), (*headerValue) ();
00046     int (*headerString) ();
00047 
00048     if (doRead) {
00049         headerDouble = G3d_keyGetDouble;
00050         headerInt = G3d_keyGetInt;
00051         headerString = G3d_keyGetString;
00052         headerValue = G3d_keyGetValue;
00053     }
00054     else {
00055         headerDouble = G3d_keySetDouble;
00056         headerInt = G3d_keySetInt;
00057         headerString = G3d_keySetString;
00058         headerValue = G3d_keySetValue;
00059     }
00060 
00061     returnVal = 1;
00062     returnVal &= headerInt(headerKeys, G3D_REGION_PROJ, proj);
00063     returnVal &= headerInt(headerKeys, G3D_REGION_ZONE, zone);
00064 
00065     returnVal &= headerDouble(headerKeys, G3D_REGION_NORTH, north);
00066     returnVal &= headerDouble(headerKeys, G3D_REGION_SOUTH, south);
00067     returnVal &= headerDouble(headerKeys, G3D_REGION_EAST, east);
00068     returnVal &= headerDouble(headerKeys, G3D_REGION_WEST, west);
00069     returnVal &= headerDouble(headerKeys, G3D_REGION_TOP, top);
00070     returnVal &= headerDouble(headerKeys, G3D_REGION_BOTTOM, bottom);
00071 
00072     returnVal &= headerInt(headerKeys, G3D_REGION_ROWS, rows);
00073     returnVal &= headerInt(headerKeys, G3D_REGION_COLS, cols);
00074     returnVal &= headerInt(headerKeys, G3D_REGION_DEPTHS, depths);
00075 
00076     returnVal &= headerDouble(headerKeys, G3D_REGION_NSRES, ns_res);
00077     returnVal &= headerDouble(headerKeys, G3D_REGION_EWRES, ew_res);
00078     returnVal &= headerDouble(headerKeys, G3D_REGION_TBRES, tb_res);
00079 
00080     returnVal &= headerInt(headerKeys, G3D_HEADER_TILEX, tileX);
00081     returnVal &= headerInt(headerKeys, G3D_HEADER_TILEY, tileY);
00082     returnVal &= headerInt(headerKeys, G3D_HEADER_TILEZ, tileZ);
00083 
00084     returnVal &= headerValue(headerKeys, G3D_HEADER_TYPE,
00085                              "double", "float", DCELL_TYPE, FCELL_TYPE, type);
00086     returnVal &= headerValue(headerKeys, G3D_HEADER_COMPRESSION,
00087                              "0", "1", 0, 1, compression);
00088     returnVal &= headerValue(headerKeys, G3D_HEADER_USERLE,
00089                              "0", "1", 0, 1, useRle);
00090     returnVal &= headerValue(headerKeys, G3D_HEADER_USELZW,
00091                              "0", "1", 0, 1, useLzw);
00092 
00093     returnVal &= headerInt(headerKeys, G3D_HEADER_PRECISION, precision);
00094     returnVal &= headerInt(headerKeys, G3D_HEADER_DATA_OFFSET, dataOffset);
00095 
00096     returnVal &= headerValue(headerKeys, G3D_HEADER_USEXDR,
00097                              "0", "1", 0, 1, useXdr);
00098     returnVal &= headerValue(headerKeys, G3D_HEADER_HASINDEX,
00099                              "0", "1", 0, 1, hasIndex);
00100     returnVal &= headerString(headerKeys, G3D_HEADER_UNIT, unit);
00101 
00102     if (returnVal)
00103         return 1;
00104 
00105     G3d_error("G3d_readWriteHeader: error writing header");
00106     return 0;
00107 }
00108 
00109 /*---------------------------------------------------------------------------*/
00110 
00111 int
00112 G3d_readHeader(G3D_Map * map, int *proj, int *zone, double *north,
00113                double *south, double *east, double *west, double *top,
00114                double *bottom, int *rows, int *cols, int *depths,
00115                double *ew_res, double *ns_res, double *tb_res, int *tileX,
00116                int *tileY, int *tileZ, int *type, int *compression,
00117                int *useRle, int *useLzw, int *precision, int *dataOffset,
00118                int *useXdr, int *hasIndex, char **unit)
00119 {
00120     struct Key_Value *headerKeys;
00121     char path[GPATH_MAX];
00122     int status;
00123 
00124     G3d_filename(path, G3D_HEADER_ELEMENT, map->fileName, map->mapset);
00125     if (access(path, R_OK) != 0) {
00126         G3d_error("G3d_readHeader: unable to find [%s]", path);
00127         return 0;
00128     }
00129 
00130     headerKeys = G_read_key_value_file(path, &status);
00131     if (status != 0) {
00132         G3d_error("G3d_readHeader: Unable to open %s", path);
00133         return 0;
00134     }
00135 
00136     if (!G3d_readWriteHeader(headerKeys, 1,
00137                              proj, zone,
00138                              north, south, east, west, top, bottom,
00139                              rows, cols, depths,
00140                              ew_res, ns_res, tb_res,
00141                              tileX, tileY, tileZ,
00142                              type, compression, useRle, useLzw, precision,
00143                              dataOffset, useXdr, hasIndex, unit)) {
00144         G3d_error("G3d_readHeader: error extracting header key(s) of file %s",
00145                   path);
00146         return 0;
00147     }
00148 
00149     G_free_key_value(headerKeys);
00150     return 1;
00151 }
00152 
00153 /*---------------------------------------------------------------------------*/
00154 
00155 int
00156 G3d_writeHeader(G3D_Map * map, int proj, int zone, double north, double south,
00157                 double east, double west, double top, double bottom, int rows,
00158                 int cols, int depths, double ew_res, double ns_res,
00159                 double tb_res, int tileX, int tileY, int tileZ, int type,
00160                 int compression, int useRle, int useLzw, int precision,
00161                 int dataOffset, int useXdr, int hasIndex, char *unit)
00162 {
00163     struct Key_Value *headerKeys;
00164     char path[GPATH_MAX];
00165     int status;
00166 
00167     headerKeys = G_create_key_value();
00168 
00169     if (!G3d_readWriteHeader(headerKeys, 0,
00170                              &proj, &zone,
00171                              &north, &south, &east, &west, &top, &bottom,
00172                              &rows, &cols, &depths,
00173                              &ew_res, &ns_res, &tb_res,
00174                              &tileX, &tileY, &tileZ,
00175                              &type, &compression, &useRle, &useLzw,
00176                              &precision, &dataOffset, &useXdr, &hasIndex,
00177                              &unit)) {
00178         G3d_error("G3d_writeHeader: error adding header key(s) for file %s",
00179                   path);
00180         return 0;
00181     }
00182 
00183     G3d_filename(path, G3D_HEADER_ELEMENT, map->fileName, map->mapset);
00184     G3d_makeMapsetMapDirectory(map->fileName);
00185     G_write_key_value_file(path, headerKeys, &status);
00186 
00187     G_free_key_value(headerKeys);
00188 
00189     if (status == 0)
00190         return 1;
00191 
00192     G3d_error("G3d_writeHeader: error writing header file %s", path);
00193     return 0;
00194 }
00195 
00196 /*---------------------------------------------------------------------------*/
00197 
00198 
00224 int G3d_cacheSizeEncode(int cacheCode, int n)
00225 {
00226     if (cacheCode >= G3D_NO_CACHE)
00227         return cacheCode * n;
00228     if (cacheCode == G3D_USE_CACHE_DEFAULT)
00229         return cacheCode;
00230 
00231     if (cacheCode < G3D_USE_CACHE_XYZ)
00232         G3d_fatalError("G3d_cacheSizeEncode: invalid cache code");
00233 
00234     return n * (-10) + cacheCode;
00235 }
00236 
00237 /*---------------------------------------------------------------------------*/
00238 
00239 int G3d__computeCacheSize(G3D_Map * map, int cacheCode)
00240 {
00241     int n, size;
00242 
00243     if (cacheCode >= G3D_NO_CACHE)
00244         return cacheCode;
00245     if (cacheCode == G3D_USE_CACHE_DEFAULT)
00246         return G3D_MIN(g3d_cache_default, map->nTiles);
00247 
00248     n = -(cacheCode / 10);
00249     n = G3D_MAX(1, n);
00250     cacheCode = -((-cacheCode) % 10);
00251 
00252     if (cacheCode == G3D_USE_CACHE_X)
00253         size = map->nx * n;
00254     else if (cacheCode == G3D_USE_CACHE_Y)
00255         size = map->ny * n;
00256     else if (cacheCode == G3D_USE_CACHE_Z)
00257         size = map->nz * n;
00258     else if (cacheCode == G3D_USE_CACHE_XY)
00259         size = map->nxy * n;
00260     else if (cacheCode == G3D_USE_CACHE_XZ)
00261         size = map->nx * map->nz * n;
00262     else if (cacheCode == G3D_USE_CACHE_YZ)
00263         size = map->ny * map->nz * n;
00264     else if (cacheCode == G3D_USE_CACHE_XYZ)
00265         size = map->nTiles;
00266     else
00267         G3d_fatalError("G3d__computeCacheSize: invalid cache code");
00268 
00269     return G3D_MIN(size, map->nTiles);
00270 }
00271 
00272 /*---------------------------------------------------------------------------*/
00273 
00274 /* this function does actually more than filling the header fields of the */
00275 /* G3D-Map structure. It also allocates memory for compression and xdr, */
00276 /* and initializes the index and cache. This function should be taken apart. */
00277 
00278 int
00279 G3d_fillHeader(G3D_Map * map, int operation, int compression, int useRle,
00280                int useLzw, int type, int precision, int cache, int hasIndex,
00281                int useXdr, int typeIntern, int nofHeaderBytes, int tileX,
00282                int tileY, int tileZ, int proj, int zone, double north,
00283                double south, double east, double west, double top,
00284                double bottom, int rows, int cols, int depths, double ew_res,
00285                double ns_res, double tb_res, char *unit)
00286 {
00287     if (!G3D_VALID_OPERATION(operation))
00288         G3d_fatalError("G3d_fillHeader: operation not valid\n");
00289 
00290     map->operation = operation;
00291 
00292     map->unit = G_store(unit);
00293 
00294     map->region.proj = proj;
00295     map->region.zone = zone;
00296 
00297     map->region.north = north;
00298     map->region.south = south;
00299     map->region.east = east;
00300     map->region.west = west;
00301     map->region.top = top;
00302     map->region.bottom = bottom;
00303 
00304     map->region.rows = rows;
00305     map->region.cols = cols;
00306     map->region.depths = depths;
00307 
00308     map->region.ew_res = ew_res;
00309     map->region.ns_res = ns_res;
00310     map->region.tb_res = tb_res;
00311 
00312     G3d_adjustRegion(&(map->region));
00313 
00314     map->tileX = tileX;
00315     map->tileY = tileY;
00316     map->tileZ = tileZ;
00317     map->tileXY = map->tileX * map->tileY;
00318     map->tileSize = map->tileXY * map->tileZ;
00319 
00320     map->nx = (map->region.cols - 1) / tileX + 1;
00321     map->ny = (map->region.rows - 1) / tileY + 1;
00322     map->nz = (map->region.depths - 1) / tileZ + 1;
00323     map->nxy = map->nx * map->ny;
00324     map->nTiles = map->nxy * map->nz;
00325 
00326     if ((map->region.cols) % map->tileX != 0)
00327         map->clipX = map->nx - 1;
00328     else
00329         map->clipX = -1;
00330     if ((map->region.rows) % map->tileY != 0)
00331         map->clipY = map->ny - 1;
00332     else
00333         map->clipY = -1;
00334     if ((map->region.depths) % map->tileZ != 0)
00335         map->clipZ = map->nz - 1;
00336     else
00337         map->clipZ = -1;
00338 
00339     if ((type != FCELL_TYPE) && (type != DCELL_TYPE))
00340         G3d_fatalError("G3d_fillHeader: invalid type");
00341     map->type = type;
00342 
00343     if ((typeIntern != FCELL_TYPE) && (typeIntern != DCELL_TYPE))
00344         G3d_fatalError("G3d_fillHeader: invalid type");
00345     map->typeIntern = typeIntern;
00346 
00347     if (!G3D_VALID_XDR_OPTION(useXdr))
00348         G3d_fatalError("G3d_fillHeader: invalid xdr option");
00349     map->useXdr = useXdr;
00350 
00351     map->offset = nofHeaderBytes;
00352 
00353     if ((map->fileEndPtr = lseek(map->data_fd, (long)0, SEEK_END)) == -1) {
00354         G3d_error("G3d_fillHeader: can't position file");
00355         return 0;
00356     }
00357 
00358     map->useCache = (cache != G3D_NO_CACHE);
00359 
00360     map->numLengthIntern = G3d_length(map->typeIntern);
00361     map->numLengthExtern = G3d_externLength(map->type);
00362 
00363     map->compression = compression;
00364     map->useRle = useRle;
00365     map->useLzw = useLzw;
00366     map->precision = precision;
00367 
00368 #define RLE_STATUS_BYTES 2
00369 
00370     if (map->compression != G3D_NO_COMPRESSION) {
00371         if (tmpCompress == NULL) {
00372             tmpCompressLength = map->tileSize *
00373                 G3D_MAX(map->numLengthIntern, map->numLengthExtern) +
00374                 RLE_STATUS_BYTES;
00375             tmpCompress = G3d_malloc(tmpCompressLength);
00376             if (tmpCompress == NULL) {
00377                 G3d_error("G3d_fillHeader: error in G3d_malloc");
00378                 return 0;
00379             }
00380         }
00381         else if (map->tileSize *
00382                  G3D_MAX(map->numLengthIntern, map->numLengthExtern)
00383                  + RLE_STATUS_BYTES > tmpCompressLength) {
00384             tmpCompressLength = map->tileSize *
00385                 G3D_MAX(map->numLengthIntern, map->numLengthExtern) +
00386                 RLE_STATUS_BYTES;
00387             tmpCompress = G3d_realloc(tmpCompress, tmpCompressLength);
00388             if (tmpCompress == NULL) {
00389                 G3d_error("G3d_fillHeader: error in G3d_realloc");
00390                 return 0;
00391             }
00392         }
00393     }
00394 
00395 #define XDR_MISUSE_BYTES 10
00396 
00397     if (!G3d_initFpXdr(map, XDR_MISUSE_BYTES)) {
00398         G3d_error("G3d_fillHeader: error in G3d_initFpXdr");
00399         return 0;
00400     }
00401 
00402     if ((!map->useCache) ||
00403         ((cache == G3D_USE_CACHE_DEFAULT) && (g3d_cache_default == 0))) {
00404         map->useCache = 0;
00405         map->cache = NULL;
00406         /* allocate one tile buffer */
00407         map->data = G3d_malloc(map->tileSize * map->numLengthIntern);
00408         if (map->data == NULL) {
00409             G3d_error("G3d_fillHeader: error in G3d_malloc");
00410             return 0;
00411         }
00412         map->currentIndex = -1;
00413     }
00414     else {
00415         if (!G3d_initCache(map,
00416                            G3D_MAX(1,
00417                                    G3D_MIN(G3d__computeCacheSize(map, cache),
00418                                            g3d_cache_max /
00419                                            map->tileSize /
00420                                            map->numLengthIntern)))) {
00421             G3d_error("G3d_fillHeader: error in G3d_initCache");
00422             return 0;
00423         }
00424     }
00425 
00426     if (!G3d_initIndex(map, hasIndex)) {
00427         G3d_error("G3d_fillHeader: error in G3d_initIndex");
00428         return 0;
00429     }
00430 
00431     return 1;
00432 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines