map.c

Go to the documentation of this file.
00001 /*
00002 ****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Radim Blazek
00007 *
00008 * PURPOSE:      Higher 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 <stdio.h>
00019 #include <dirent.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include "glocale.h"
00025 #include "gis.h"
00026 #include "Vect.h"
00027 #include "dbmi.h"
00028 
00035 int 
00036 Vect_copy_map_lines ( struct Map_info *In, struct Map_info *Out )
00037 {
00038     int    i, type, nlines, ret;
00039     struct line_pnts *Points;
00040     struct line_cats *Cats;
00041 
00042     Points = Vect_new_line_struct ();
00043     Cats = Vect_new_cats_struct ();
00044    
00045     if ( Vect_level ( In ) < 1 )
00046         G_fatal_error ("Vect_copy_map_lines(): input vector is not open");
00047     
00048     ret = 0;
00049     /* Note: sometimes is important to copy on level 2 (pseudotopo centroids) 
00050      *       and sometimes on level 1 if build take too long time */
00051     if ( Vect_level ( In ) >= 2 ) { 
00052         nlines = Vect_get_num_lines ( In );
00053         for ( i = 1; i <= nlines; i++ ) {
00054             type =  Vect_read_line (In, Points, Cats, i);
00055             if ( type == -1 ) {
00056                 G_warning ("Cannot read vector file\n" );
00057                 ret = 1;
00058                 break;
00059             } 
00060             if ( type == 0 ) continue; /* dead line */
00061 
00062             Vect_write_line ( Out, type, Points, Cats );
00063         }
00064     } else {  /* Level 1 */
00065         Vect_rewind ( In );
00066         while ( 1 ) {
00067             type =  Vect_read_next_line (In, Points, Cats);
00068             if ( type == -1 ) {
00069                 G_warning ("Cannot read vector file\n" );
00070                 ret = 1;
00071                 break;
00072             } else if ( type == -2 ) { /* EOF */ 
00073                 break;
00074             } else if ( type == 0 ) { /* dead line */
00075                 continue;
00076             }
00077             Vect_write_line ( Out, type, Points, Cats );
00078         }
00079     }
00080     Vect_destroy_line_struct (Points);
00081     Vect_destroy_cats_struct (Cats);
00082 
00083     return ret;
00084 }
00085 
00095 int 
00096 Vect_copy ( char *in, char *mapset, char *out, FILE *msgout )
00097 {
00098     int i, n, ret, type;
00099     struct Map_info In, Out;
00100     struct field_info *Fi, *Fin;
00101     char   old_path[1000], new_path[1000], cmd[2000]; 
00102     struct stat info;
00103     dbDriver *driver;
00104 
00105     G_debug (3, "Copy vector '%s' in '%s' to '%s'", in, mapset, out );
00106 
00107     /* Delete old vector if it exists */
00108     if ( G_find_vector2(out, G_mapset()) ) {
00109         G_warning (_("The vector '%s' already exists and will be overwritten."), out);
00110         ret = Vect_delete ( out );
00111         if ( ret != 0 ) {
00112             G_warning ( "Cannot copy vector" );
00113             return -1;
00114         }
00115     }
00116 
00117     /* Copy the directory */
00118     G__make_mapset_element ( GRASS_VECT_DIRECTORY );
00119     G__file_name (old_path, GRASS_VECT_DIRECTORY, in, mapset );
00120     G__file_name (new_path, GRASS_VECT_DIRECTORY, out, G_mapset() );
00121     sprintf ( cmd, "cp -r '%s' '%s'", old_path, new_path );
00122     G_debug (2, "system: %s", cmd );
00123     ret = system ( cmd );
00124 
00125     if  (ret != 0 ) {
00126         G_warning ( "Cannot copy vector" );
00127         return -1;
00128     }
00129 
00130     /* remove dbln */
00131     sprintf (old_path, "%s/%s", GRASS_VECT_DIRECTORY, out);
00132     G__file_name ( new_path, old_path, GRASS_VECT_DBLN_ELEMENT, G_mapset ());
00133 
00134     if (stat (new_path, &info) == 0)      /* file exists? */
00135         unlink (new_path);
00136 
00137     /* Open input */
00138     Vect_set_open_level (1);
00139     Vect_open_old_head (&In, in, mapset);
00140 
00141     if ( In.format != GV_FORMAT_NATIVE ) { /* Done */
00142         Vect_close ( &In );
00143         return 0;
00144     }
00145     
00146     /* Open output */
00147     Vect_open_update_head ( &Out, out, G_mapset() );
00148 
00149     /* Copy tables */
00150     n = Vect_get_num_dblinks ( &In );
00151     type = GV_1TABLE;
00152     if ( n > 1 ) type = GV_MTABLE;
00153     for ( i = 0; i < n; i++ ) {
00154         Fi = Vect_get_dblink ( &In, i );
00155         if ( Fi == NULL ) {
00156             G_warning ( "Cannot get db link info" );
00157             Vect_close ( &In );
00158             Vect_close ( &Out );
00159             return -1;
00160         }
00161         Fin = Vect_default_field_info ( &Out, Fi->number, Fi->name, type );
00162         G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00163                       Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00164         Vect_map_add_dblink ( &Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00165         
00166         ret = db_copy_table ( Fi->driver, Fi->database, Fi->table, 
00167                     Fin->driver, Vect_subst_var(Fin->database,&Out), Fin->table );
00168         if ( ret == DB_FAILED ) {
00169             G_warning ( "Cannot copy table" );
00170             Vect_close ( &In );
00171             Vect_close ( &Out );
00172             return -1;
00173         }
00174 
00175         driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,&Out) );
00176         if ( driver == NULL ) {
00177             G_warning ( "Cannot open database -> create index" );
00178         } else {
00179             if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
00180                 G_warning ( "Cannot create index" );
00181 
00182             db_close_database_shutdown_driver ( driver );
00183         }
00184     }
00185     
00186     Vect_close ( &In );
00187     Vect_close ( &Out );
00188 
00189     return 0;
00190 }
00191 
00202 int 
00203 Vect_rename ( char *in, char *out, FILE *msgout )
00204 {
00205     int i, n, ret, type;
00206     struct Map_info Map;
00207     struct field_info *Fin, *Fout;
00208     int *fields;
00209     dbDriver *driver;
00210 
00211     G_debug (2, "Rename vector '%s' to '%s'", in, out );
00212 
00213     /* Delete old vector if it exists */
00214     if ( G_find_vector2(out, G_mapset()) ) {
00215         G_warning (_("The vector '%s' already exists and will be overwritten."), out);
00216         Vect_delete ( out );
00217     }
00218 
00219     /* Move the directory */
00220     ret = G_rename ( GRASS_VECT_DIRECTORY, in, out );
00221 
00222     if ( ret == 0 ) {
00223         G_warning (_("Input vector '%s' not found"), in );
00224         return -1;
00225     } else if ( ret == -1 ) {
00226         G_warning (_("Cannot copy vector '%s' to '%s'"), in, out );
00227         return -1;
00228     }
00229 
00230     /* Rename all tables if the format is native */
00231     Vect_set_open_level (1);
00232     Vect_open_update_head ( &Map, out, G_mapset() );
00233 
00234     if ( Map.format != GV_FORMAT_NATIVE ) { /* Done */
00235         Vect_close ( &Map );
00236         return 0;
00237     }
00238 
00239     /* Copy tables */
00240     n = Vect_get_num_dblinks ( &Map );
00241     type = GV_1TABLE;
00242     if ( n > 1 ) type = GV_MTABLE;
00243 
00244     /* Make the list of fields */
00245     fields = (int *) G_malloc ( n * sizeof(int) );
00246 
00247     for ( i = 0; i < n; i++ ) {
00248         Fin = Vect_get_dblink ( &Map, i );
00249 
00250         fields[i] = Fin->number;
00251     }
00252     
00253     for ( i = 0; i < n; i++ ) {
00254         G_debug (3, "field[%d] = %d", i, fields[i] );
00255         
00256         Fin = Vect_get_field ( &Map, fields[i] );
00257         if ( Fin == NULL ) {
00258             G_warning ( "Cannot get db link info" );
00259             Vect_close ( &Map );
00260             return -1;
00261         }
00262 
00263         Fout = Vect_default_field_info ( &Map, Fin->number, Fin->name, type );
00264         G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00265                       Fin->driver, Fin->database, Fin->table, Fout->driver, Fout->database, Fout->table );
00266 
00267         /* TODO: db_rename_table instead of db_copy_table */
00268         ret = db_copy_table ( Fin->driver, Fin->database, Fin->table, 
00269                     Fout->driver, Vect_subst_var(Fout->database,&Map), Fout->table );
00270 
00271         if ( ret == DB_FAILED ) {
00272             G_warning ( "Cannot copy table" );
00273             Vect_close ( &Map );
00274             return -1;
00275         }
00276 
00277         /* Change the link */
00278         Vect_map_del_dblink ( &Map, Fin->number );
00279         
00280         Vect_map_add_dblink ( &Map, Fout->number, Fout->name, Fout->table, Fin->key, 
00281                                     Fout->database, Fout->driver);
00282 
00283         /* Delete old table */
00284         ret = db_delete_table ( Fin->driver, Fin->database, Fin->table );
00285         if ( ret == DB_FAILED ) {
00286             G_warning ( "Cannot delete table" );
00287             Vect_close ( &Map );
00288             return -1;
00289         }
00290 
00291         driver = db_start_driver_open_database ( Fout->driver, Vect_subst_var(Fout->database, &Map) );
00292         if ( driver == NULL ) {
00293             G_warning ( "Cannot open database -> create index" );
00294         } else {
00295             if ( db_create_index2(driver, Fout->table, Fin->key ) != DB_OK )
00296                 G_warning ( "Cannot create index" );
00297 
00298             db_close_database_shutdown_driver ( driver );
00299         }
00300     }
00301     
00302     Vect_close ( &Map );
00303     free ( fields );
00304 
00305     return 0;
00306 }
00307 
00314 int 
00315 Vect_delete ( char *map )
00316 {
00317     int i, n, ret;
00318     struct Map_info Map;
00319     struct field_info *Fi;
00320     char   buf[5000];
00321     DIR    *dir;
00322     struct dirent *ent; 
00323 
00324     G_debug (3, "Delete vector '%s'", map );
00325 
00326     G_chop ( map );
00327 
00328     if ( map == NULL || strlen ( map ) == 0 ) {
00329         G_warning ( "Wrong map name '%s'", map );
00330         return -1;
00331     }
00332 
00333     /* Open input */
00334     Vect_set_open_level (1); /* Topo not needed */
00335     ret = Vect_open_old_head (&Map, map, G_mapset());
00336     if ( ret < 1 ) {
00337         G_warning ( "Cannot open vector %s", map );
00338         return -1;
00339     }
00340 
00341     /* Delete all tables, NOT external (OGR) */
00342     if ( Map.format == GV_FORMAT_NATIVE ) {
00343 
00344         n = Vect_get_num_dblinks ( &Map );
00345         for ( i = 0; i < n; i++ ) {
00346             Fi = Vect_get_dblink ( &Map, i );
00347             if ( Fi == NULL ) {
00348                 G_warning ( "Cannot get db link info" );
00349                 Vect_close ( &Map );
00350                 return -1;
00351             }
00352             G_debug (3, "Delete drv:db:table '%s:%s:%s'", Fi->driver, Fi->database, Fi->table);
00353             
00354             ret = db_table_exists ( Fi->driver, Fi->database, Fi->table );
00355             if ( ret == -1 ) {
00356                 G_warning ( "Cannot get info if table '%s' linked to vector exists.", Fi->table );
00357                 Vect_close ( &Map );
00358                 return -1;
00359             }
00360             
00361             if ( ret == 1 ) {
00362                 ret = db_delete_table ( Fi->driver, Fi->database, Fi->table );
00363                 if ( ret == DB_FAILED ) {
00364                     G_warning ( "Cannot delete table" );
00365                     Vect_close ( &Map );
00366                     return -1;
00367                 }
00368             } else {
00369                 G_warning ( "Table '%s' linked to vector did not exist.", Fi->table );
00370             }
00371         }
00372     }
00373         
00374     Vect_close ( &Map );
00375 
00376     /* Delete all files from vector/name directory */
00377     sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
00378     G_debug (3, "opendir '%s'", buf ); 
00379     dir = opendir( buf );
00380     if (dir == NULL) {
00381         G_warning ( "Cannot open directory '%s'", buf );
00382         return -1;
00383     }
00384 
00385     while ( (ent = readdir (dir)) ) {
00386         G_debug (3, "file = '%s'", ent->d_name );
00387         if ( (strcmp (ent->d_name, ".") == 0) || (strcmp (ent->d_name, "..") == 0) ) continue;
00388         sprintf ( buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map, ent->d_name );
00389         G_debug (3, "delete file '%s'", buf );
00390         ret = unlink ( buf );
00391         if ( ret == -1 ) { 
00392             G_warning ( "Cannot delete file '%s'", buf );
00393             closedir (dir);
00394             return -1;
00395         }
00396     }
00397     closedir (dir);
00398 
00399     /* NFS can create . files for those deleted -> second time */
00400     sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
00401     G_debug (3, "opendir '%s'", buf ); 
00402     dir = opendir( buf );
00403     if (dir == NULL) {
00404         G_warning ( "Cannot open directory '%s'", buf );
00405         return -1;
00406     }
00407     while ( (ent = readdir (dir)) ) {
00408         G_debug (3, "file = '%s'", ent->d_name );
00409         if ( (strcmp (ent->d_name, ".") == 0) || (strcmp (ent->d_name, "..") == 0) ) continue;
00410         sprintf ( buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map, ent->d_name );
00411         G_debug (3, "delete file '%s'", buf );
00412         ret = unlink ( buf );
00413         if ( ret == -1 ) { 
00414             G_warning ( "Cannot delete file '%s'", buf );
00415             closedir (dir);
00416             return -1;
00417         }
00418     }
00419     closedir (dir);
00420 
00421     sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
00422     G_debug (3, "delete directory '%s'", buf );
00423     ret = rmdir ( buf );
00424     if ( ret == -1 ) { 
00425         G_warning ( "Cannot delete directory '%s'", buf );
00426         return -1;
00427     }
00428 
00429     return 0;
00430 }
00431 
00438 int 
00439 Vect_copy_tables ( struct Map_info *In, struct Map_info *Out, int field )
00440 {
00441     int i, n, ret, type;
00442     struct field_info *Fi, *Fin;
00443     dbDriver *driver;
00444 
00445     G_debug (2, "Vect_copy_tables()");
00446 
00447     n = Vect_get_num_dblinks ( In );
00448     type = GV_1TABLE;
00449     if ( n > 1 ) type = GV_MTABLE;
00450 
00451     for ( i = 0; i < n; i++ ) {
00452         Fi = Vect_get_dblink ( In, i );
00453         if ( Fi == NULL ) {
00454             G_warning ( "Cannot get db link info" );
00455             return -1;
00456         }
00457         if ( field > 0 && Fi->number != field ) continue;
00458 
00459         Fin = Vect_default_field_info ( Out, Fi->number, Fi->name, type );
00460         G_debug (2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00461                       Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00462         
00463         ret = Vect_map_add_dblink ( Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00464         if ( ret == -1 ) {
00465             G_warning ( "Cannot add database link" );
00466             return -1;
00467         }
00468         
00469         ret = db_copy_table ( Fi->driver, Fi->database, Fi->table, 
00470                     Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table );
00471         if ( ret == DB_FAILED ) {
00472             G_warning ( "Cannot copy table" );
00473             return -1;
00474         }
00475 
00476         driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,Out) );
00477         if ( driver == NULL ) {
00478             G_warning ( "Cannot open database -> create index" );
00479         } else {
00480             if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
00481                 G_warning ( "Cannot create index" );
00482 
00483             db_close_database_shutdown_driver ( driver );
00484         }
00485     }
00486 
00487     return 0;
00488 }
00489 
00502 int 
00503 Vect_copy_table ( struct Map_info *In, struct Map_info *Out, int field_in, 
00504                    int field_out,  char *field_name, int type )
00505 {
00506     return Vect_copy_table_by_cats ( In, Out, field_in, field_out, field_name, type, NULL, 0); 
00507 }
00508 
00523 int 
00524 Vect_copy_table_by_cats ( struct Map_info *In, struct Map_info *Out, int field_in, 
00525                    int field_out,  char *field_name, int type, int *cats, int ncats )
00526 {
00527     int    ret;
00528     struct field_info *Fi, *Fin;
00529     char   *name, *key;
00530 
00531     G_debug (2, "Vect_copy_table(): field_in = %d field_out = %d", field_in, field_out);
00532 
00533     Fi = Vect_get_field ( In, field_in );
00534     if ( Fi == NULL ) {
00535         G_warning ( "Cannot get db link info" );
00536         return -1;
00537     }
00538 
00539     if ( field_name != NULL ) name = field_name;
00540     else name = Fi->name;
00541     
00542     Fin = Vect_default_field_info ( Out, field_out, name, type );
00543     G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00544                   Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00545     
00546     ret = Vect_map_add_dblink ( Out, Fin->number, Fin->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00547     if ( ret == -1 ) {
00548         G_warning ( "Cannot add database link" );
00549         return -1;
00550     }
00551     
00552     if ( cats ) 
00553         key = Fi->key;
00554     else 
00555         key = NULL;
00556     
00557     ret = db_copy_table_by_ints ( Fi->driver, Fi->database, Fi->table, 
00558                 Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table, key, cats, ncats );
00559     if ( ret == DB_FAILED ) {
00560         G_warning ( "Cannot copy table" );
00561         return -1;
00562     }
00563 
00564     return 0;
00565 }
00566 
00572 void
00573 Vect_set_release_support ( struct Map_info * Map )
00574 {
00575     Map->plus.release_support = 1;
00576 }
00577 
00585 void
00586 Vect_set_category_index_update ( struct Map_info * Map )
00587 {
00588     Map->plus.update_cidx = 1;
00589 }
00590 

Generated on Sat Jul 22 22:05:57 2006 for GRASS by  doxygen 1.4.7