spindex_rw.c

Go to the documentation of this file.
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 }
Generated on Tue Apr 6 13:28:10 2010 for GRASS Programmer's Manual by  doxygen 1.6.3