GRASS Programmer's Manual
6.4.2(2012)
|
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 }