GRASS Programmer's Manual
6.4.1(2011)
|
00001 /* 00002 **************************************************************************** 00003 * 00004 * MODULE: Vector library 00005 * 00006 * AUTHOR(S): Radim Blazek. 00007 * 00008 * PURPOSE: Lower level functions for reading/writing/manipulating vectors. 00009 * 00010 * COPYRIGHT: (C) 2001 by the GRASS Development Team 00011 * 00012 * This program is free software under the GNU General Public 00013 * License (>=v2). Read the file COPYING that comes with GRASS 00014 * for details. 00015 * 00016 *****************************************************************************/ 00017 #include <stdlib.h> 00018 #include <string.h> 00019 #include <grass/gis.h> 00020 #include <grass/Vect.h> 00021 00022 00023 int dig_Wr_spindx_head(GVFILE * fp, struct Plus_head *ptr) 00024 { 00025 unsigned char buf[5]; 00026 long length = 42; 00027 00028 dig_rewind(fp); 00029 dig_set_cur_port(&(ptr->spidx_port)); 00030 00031 /* bytes 1 - 5 */ 00032 buf[0] = GV_SIDX_VER_MAJOR; 00033 buf[1] = GV_SIDX_VER_MINOR; 00034 buf[2] = GV_SIDX_EARLIEST_MAJOR; 00035 buf[3] = GV_SIDX_EARLIEST_MINOR; 00036 buf[4] = ptr->spidx_port.byte_order; 00037 if (0 >= dig__fwrite_port_C(buf, 5, fp)) 00038 return (-1); 00039 00040 /* bytes 6 - 9 : header size */ 00041 if (0 >= dig__fwrite_port_L(&length, 1, fp)) 00042 return (0); 00043 00044 /* byte 10 : dimension 2D or 3D */ 00045 buf[0] = ptr->spidx_with_z; 00046 if (0 >= dig__fwrite_port_C(buf, 1, fp)) 00047 return (-1); 00048 00049 /* bytes 11 - 38 : Offsets */ 00050 if (0 >= dig__fwrite_port_L(&(ptr->Node_spidx_offset), 1, fp)) 00051 return (-1); 00052 if (0 >= dig__fwrite_port_L(&(ptr->Edge_spidx_offset), 1, fp)) 00053 return (-1); 00054 if (0 >= dig__fwrite_port_L(&(ptr->Line_spidx_offset), 1, fp)) 00055 return (-1); 00056 if (0 >= dig__fwrite_port_L(&(ptr->Area_spidx_offset), 1, fp)) 00057 return (-1); 00058 if (0 >= dig__fwrite_port_L(&(ptr->Isle_spidx_offset), 1, fp)) 00059 return (-1); 00060 if (0 >= dig__fwrite_port_L(&(ptr->Volume_spidx_offset), 1, fp)) 00061 return (-1); 00062 if (0 >= dig__fwrite_port_L(&(ptr->Hole_spidx_offset), 1, fp)) 00063 return (-1); 00064 00065 G_debug(3, "spidx offset node = %ld line = %ld, area = %ld isle = %ld", 00066 ptr->Node_spidx_offset, ptr->Line_spidx_offset, 00067 ptr->Area_spidx_offset, ptr->Isle_spidx_offset); 00068 00069 /* bytes 39 - 42 : Offsets */ 00070 if (0 >= dig__fwrite_port_L(&(ptr->coor_size), 1, fp)) 00071 return (-1); 00072 00073 G_debug(2, "spidx body offset %ld", dig_ftell(fp)); 00074 00075 return (0); 00076 } 00077 00078 00079 int dig_Rd_spindx_head(GVFILE * fp, struct Plus_head *ptr) 00080 { 00081 unsigned char buf[5]; 00082 int byte_order; 00083 long coor_size; 00084 00085 dig_rewind(fp); 00086 00087 /* bytes 1 - 5 */ 00088 if (0 >= dig__fread_port_C(buf, 5, fp)) 00089 return (-1); 00090 ptr->spidx_Version_Major = buf[0]; 00091 ptr->spidx_Version_Minor = buf[1]; 00092 ptr->spidx_Back_Major = buf[2]; 00093 ptr->spidx_Back_Minor = buf[3]; 00094 byte_order = buf[4]; 00095 00096 G_debug(2, 00097 "Sidx header: file version %d.%d , supported from GRASS version %d.%d", 00098 ptr->spidx_Version_Major, ptr->spidx_Version_Minor, 00099 ptr->spidx_Back_Major, ptr->spidx_Back_Minor); 00100 00101 G_debug(2, " byte order %d", byte_order); 00102 00103 /* check version numbers */ 00104 if (ptr->spidx_Version_Major > GV_SIDX_VER_MAJOR || 00105 ptr->spidx_Version_Minor > GV_SIDX_VER_MINOR) { 00106 /* The file was created by GRASS library with higher version than this one */ 00107 00108 if (ptr->spidx_Back_Major > GV_SIDX_VER_MAJOR || 00109 ptr->spidx_Back_Minor > GV_SIDX_VER_MINOR) { 00110 /* This version of GRASS lib is lower than the oldest which can read this format */ 00111 G_fatal_error 00112 ("Spatial index format version %d.%d is not supported by this release." 00113 " Try to rebuild topology or upgrade GRASS.", 00114 ptr->spidx_Version_Major, ptr->spidx_Version_Minor); 00115 return (-1); 00116 } 00117 00118 G_warning 00119 ("Your GRASS version does not fully support spatial index format %d.%d of the vector." 00120 " Consider to rebuild topology or upgrade GRASS.", 00121 ptr->spidx_Version_Major, ptr->spidx_Version_Minor); 00122 } 00123 00124 dig_init_portable(&(ptr->spidx_port), byte_order); 00125 dig_set_cur_port(&(ptr->spidx_port)); 00126 00127 /* bytes 6 - 9 : header size */ 00128 if (0 >= dig__fread_port_L(&(ptr->spidx_head_size), 1, fp)) 00129 return (-1); 00130 G_debug(2, " header size %ld", ptr->spidx_head_size); 00131 00132 /* byte 10 : dimension 2D or 3D */ 00133 if (0 >= dig__fread_port_C(buf, 1, fp)) 00134 return (-1); 00135 ptr->spidx_with_z = buf[0]; 00136 G_debug(2, " with_z %d", ptr->spidx_with_z); 00137 00138 /* bytes 11 - 38 : Offsets */ 00139 if (0 >= dig__fread_port_L(&(ptr->Node_spidx_offset), 1, fp)) 00140 return (-1); 00141 if (0 >= dig__fread_port_L(&(ptr->Edge_spidx_offset), 1, fp)) 00142 return (-1); 00143 if (0 >= dig__fread_port_L(&(ptr->Line_spidx_offset), 1, fp)) 00144 return (-1); 00145 if (0 >= dig__fread_port_L(&(ptr->Area_spidx_offset), 1, fp)) 00146 return (-1); 00147 if (0 >= dig__fread_port_L(&(ptr->Isle_spidx_offset), 1, fp)) 00148 return (-1); 00149 if (0 >= dig__fread_port_L(&(ptr->Volume_spidx_offset), 1, fp)) 00150 return (-1); 00151 if (0 >= dig__fread_port_L(&(ptr->Hole_spidx_offset), 1, fp)) 00152 return (-1); 00153 00154 /* bytes 39 - 42 : Offsets */ 00155 if (0 >= dig__fread_port_L(&coor_size, 1, fp)) 00156 return (-1); 00157 G_debug(2, " coor size %ld", coor_size); 00158 00159 dig_fseek(fp, ptr->spidx_head_size, SEEK_SET); 00160 00161 return (0); 00162 } 00163 00164 int rtree_dump_node(FILE * fp, struct Node *n, int with_z); 00165 00166 /* Dump RTree branch to file */ 00167 int rtree_dump_branch(FILE * fp, struct Branch *b, int with_z, int level) 00168 { 00169 struct Rect *r; 00170 00171 r = &(b->rect); 00172 00173 if (level == 0) 00174 fprintf(fp, " id = %d ", (int)b->child); 00175 00176 fprintf(fp, " %f %f %f %f %f %f\n", r->boundary[0], r->boundary[1], 00177 r->boundary[2], r->boundary[3], r->boundary[4], r->boundary[5]); 00178 00179 if (level > 0) { 00180 rtree_dump_node(fp, b->child, with_z); 00181 } 00182 return 0; 00183 } 00184 00185 /* Dump RTree node to file */ 00186 int rtree_dump_node(FILE * fp, struct Node *n, int with_z) 00187 { 00188 int i, nn; 00189 00190 fprintf(fp, "Node level=%d count=%d\n", n->level, n->count); 00191 00192 if (n->level > 0) 00193 nn = NODECARD; 00194 else 00195 nn = LEAFCARD; 00196 00197 for (i = 0; i < nn; i++) { 00198 if (n->branch[i].child) { 00199 fprintf(fp, " Branch %d", i); 00200 rtree_dump_branch(fp, &n->branch[i], with_z, n->level); 00201 } 00202 } 00203 00204 return 0; 00205 } 00206 00207 int rtree_write_node(GVFILE * fp, struct Node *n, int with_z); 00208 00209 /* Write RTree branch to file */ 00210 int rtree_write_branch(GVFILE * fp, struct Branch *b, int with_z, int level) 00211 { 00212 struct Rect *r; 00213 int i; 00214 00215 r = &(b->rect); 00216 00217 /* rectangle */ 00218 if (with_z) { 00219 if (0 >= dig__fwrite_port_D(&(r->boundary[0]), 6, fp)) 00220 return (-1); 00221 } 00222 else { 00223 if (0 >= dig__fwrite_port_D(&(r->boundary[0]), 2, fp)) 00224 return (-1); 00225 if (0 >= dig__fwrite_port_D(&(r->boundary[3]), 2, fp)) 00226 return (-1); 00227 } 00228 if (level == 0) { /* write data (element id) */ 00229 i = (int)b->child; 00230 if (0 >= dig__fwrite_port_I(&i, 1, fp)) 00231 return (-1); 00232 } 00233 else { 00234 rtree_write_node(fp, b->child, with_z); 00235 } 00236 return 0; 00237 } 00238 00239 /* Write RTree node to file */ 00240 int rtree_write_node(GVFILE * fp, struct Node *n, int with_z) 00241 { 00242 int i, nn; 00243 00244 /* level ( 0 = leaf, data ) */ 00245 if (0 >= dig__fwrite_port_I(&(n->level), 1, fp)) 00246 return (-1); 00247 00248 /* count */ 00249 if (0 >= dig__fwrite_port_I(&(n->count), 1, fp)) 00250 return (-1); 00251 00252 if (n->level > 0) 00253 nn = NODECARD; 00254 else 00255 nn = LEAFCARD; 00256 for (i = 0; i < nn; i++) { 00257 if (n->branch[i].child) { 00258 rtree_write_branch(fp, &n->branch[i], with_z, n->level); 00259 } 00260 } 00261 00262 return 0; 00263 } 00264 00265 int rtree_read_node(GVFILE * fp, struct Node *n, int with_z); 00266 00267 /* Read RTree branch from file */ 00268 int rtree_read_branch(GVFILE * fp, struct Branch *b, int with_z, int level) 00269 { 00270 struct Rect *r; 00271 int i; 00272 00273 G_debug(3, "rtree_read_branch()"); 00274 00275 r = &(b->rect); 00276 00277 /* rectangle */ 00278 if (with_z) { 00279 if (0 >= dig__fread_port_D(&(r->boundary[0]), 6, fp)) 00280 return (-1); 00281 } 00282 else { 00283 if (0 >= dig__fread_port_D(&(r->boundary[0]), 2, fp)) 00284 return (-1); 00285 if (0 >= dig__fread_port_D(&(r->boundary[3]), 2, fp)) 00286 return (-1); 00287 r->boundary[2] = 0; 00288 r->boundary[5] = 0; 00289 } 00290 00291 if (level == 0) { /* read data (element id) */ 00292 if (0 >= dig__fread_port_I(&i, 1, fp)) 00293 return (-1); 00294 b->child = (struct Node *)i; 00295 } 00296 else { 00297 /* create new node */ 00298 b->child = RTreeNewNode(); 00299 rtree_read_node(fp, b->child, with_z); 00300 } 00301 return 0; 00302 } 00303 00304 /* Read RTree node to file */ 00305 int rtree_read_node(GVFILE * fp, struct Node *n, int with_z) 00306 { 00307 int level, count, i; 00308 00309 G_debug(3, "rtree_read_node()"); 00310 00311 /* level ( 0 = leaf, data ) */ 00312 if (0 >= dig__fread_port_I(&level, 1, fp)) 00313 return (-1); 00314 n->level = level; 00315 00316 /* count */ 00317 if (0 >= dig__fread_port_I(&count, 1, fp)) 00318 return (-1); 00319 n->count = count; 00320 00321 for (i = 0; i < count; i++) { 00322 if (0 > rtree_read_branch(fp, &n->branch[i], with_z, level)) 00323 return (-1); 00324 } 00325 00326 return 0; 00327 } 00328 00329 /* Write spatial index */ 00330 int dig_write_spidx(GVFILE * fp, struct Plus_head *Plus) 00331 { 00332 dig_set_cur_port(&(Plus->spidx_port)); 00333 dig_rewind(fp); 00334 00335 dig_Wr_spindx_head(fp, Plus); 00336 00337 Plus->Node_spidx_offset = dig_ftell(fp); 00338 rtree_write_node(fp, Plus->Node_spidx, Plus->with_z); 00339 00340 Plus->Line_spidx_offset = dig_ftell(fp); 00341 rtree_write_node(fp, Plus->Line_spidx, Plus->with_z); 00342 00343 Plus->Area_spidx_offset = dig_ftell(fp); 00344 rtree_write_node(fp, Plus->Area_spidx, Plus->with_z); 00345 00346 Plus->Isle_spidx_offset = dig_ftell(fp); 00347 rtree_write_node(fp, Plus->Isle_spidx, Plus->with_z); 00348 00349 dig_rewind(fp); 00350 dig_Wr_spindx_head(fp, Plus); /* rewrite with offsets */ 00351 00352 return 0; 00353 } 00354 00355 /* Read spatial index file */ 00356 int dig_read_spidx(GVFILE * fp, struct Plus_head *Plus) 00357 { 00358 G_debug(1, "dig_read_spindx()"); 00359 00360 /* TODO: free old tree */ 00361 dig_spidx_init(Plus); 00362 00363 dig_rewind(fp); 00364 dig_Rd_spindx_head(fp, Plus); 00365 dig_set_cur_port(&(Plus->spidx_port)); 00366 00367 dig_fseek(fp, Plus->Node_spidx_offset, 0); 00368 rtree_read_node(fp, Plus->Node_spidx, Plus->with_z); 00369 00370 dig_fseek(fp, Plus->Line_spidx_offset, 0); 00371 rtree_read_node(fp, Plus->Line_spidx, Plus->with_z); 00372 00373 dig_fseek(fp, Plus->Area_spidx_offset, 0); 00374 rtree_read_node(fp, Plus->Area_spidx, Plus->with_z); 00375 00376 dig_fseek(fp, Plus->Isle_spidx_offset, 0); 00377 rtree_read_node(fp, Plus->Isle_spidx, Plus->with_z); 00378 00379 return 0; 00380 } 00381 00382 /* Dump spatial index */ 00383 int dig_dump_spidx(FILE * fp, struct Plus_head *Plus) 00384 { 00385 00386 fprintf(fp, "Nodes\n"); 00387 rtree_dump_node(fp, Plus->Node_spidx, Plus->with_z); 00388 00389 fprintf(fp, "Lines\n"); 00390 rtree_dump_node(fp, Plus->Line_spidx, Plus->with_z); 00391 00392 fprintf(fp, "Areas\n"); 00393 rtree_dump_node(fp, Plus->Area_spidx, Plus->with_z); 00394 00395 fprintf(fp, "Isles\n"); 00396 rtree_dump_node(fp, Plus->Isle_spidx, Plus->with_z); 00397 00398 return 0; 00399 }