write_nat.c

Go to the documentation of this file.
00001 /*
00002 ****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Original author CERL, probably Dave Gerdes or Mike Higgins.
00007 *               Update to GRASS 5.7 Radim Blazek and David D. Gray.
00008 *
00009 * PURPOSE:      Higher level functions for reading/writing/manipulating vectors.
00010 *
00011 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00012 *
00013 *               This program is free software under the GNU General Public
00014 *               License (>=v2). Read the file COPYING that comes with GRASS
00015 *               for details.
00016 *
00017 *****************************************************************************/
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <math.h>
00021 #include <grass/gis.h>
00022 #include <grass/Vect.h>
00023 
00024 void delete_area_cats_from_cidx ( struct Map_info *Map, int area ) 
00025 {
00026     int i;
00027     P_AREA *Area;
00028     static struct line_cats *Cats = NULL;
00029     
00030     G_debug ( 3, "delete_area_cats_from_cidx() area = %d", area );
00031 
00032     Area =  Map->plus.Area[area];
00033     if ( !Area ) G_fatal_error ("BUG (delete_area_cats_from_cidx): Area %d does not exist", area );
00034 
00035     if ( Area->centroid == 0 ) return;
00036 
00037     if ( !Cats ) Cats = Vect_new_cats_struct ();
00038 
00039     V2_read_line_nat ( Map, NULL, Cats, Area->centroid );
00040 
00041     for ( i = 0 ; i < Cats->n_cats; i++ ) {
00042         dig_cidx_del_cat ( &(Map->plus), Cats->field[i], Cats->cat[i], area, GV_AREA );
00043     }
00044 }
00045 
00046 void add_area_cats_to_cidx ( struct Map_info *Map, int area ) 
00047 {
00048     int i;
00049     P_AREA *Area;
00050     static struct line_cats *Cats = NULL;
00051     
00052     G_debug ( 3, "add_area_cats_to_cidx() area = %d", area );
00053 
00054     Area =  Map->plus.Area[area];
00055     if ( !Area ) G_fatal_error ("BUG (add_area_cats_to_cidx): Area %d does not exist", area );
00056 
00057     if ( Area->centroid == 0 ) return;
00058 
00059     if ( !Cats ) Cats = Vect_new_cats_struct ();
00060 
00061     V2_read_line_nat ( Map, NULL, Cats, Area->centroid );
00062 
00063     for ( i = 0 ; i < Cats->n_cats; i++ ) {
00064         dig_cidx_add_cat_sorted ( &(Map->plus), Cats->field[i], Cats->cat[i], area, GV_AREA );
00065     }
00066 }
00067 
00068 long V1__rewrite_line_nat ( struct Map_info *Map, long   offset, int    type,
00069                        struct line_pnts *points, struct line_cats *cats);
00070 
00071 /* Writes line to 'coor' file.
00072 *  
00073 *  Returns: offset into file
00074 *           -1 on error */
00075 long 
00076 V1_write_line_nat (  struct Map_info *Map,
00077                      int    type,
00078                      struct line_pnts *points,
00079                      struct line_cats *cats)
00080 {
00081   long offset;
00082 
00083   if ( dig_fseek ( &(Map->dig_fp), 0L, SEEK_END) == -1 ) /* set to  end of file */
00084       return -1;
00085   
00086   offset = dig_ftell ( &(Map->dig_fp) );
00087   if ( offset == -1 )
00088       return -1;
00089   
00090   return V1__rewrite_line_nat (Map, offset, type, points, cats);
00091 }
00092 
00093 /* Writes line to 'coor' file.
00094 *  
00095 *  Returns: number of new line
00096 *           -1 on error */
00097 long 
00098 V2_write_line_nat (  struct Map_info *Map,
00099                      int    type,
00100                      struct line_pnts *points,
00101                      struct line_cats *cats)
00102 {
00103     int    i, s, n, line=0, next_line, area=0, node, side, first, sel_area;
00104     int    new_area[2];
00105     long   offset;
00106     struct Plus_head *plus;
00107     BOUND_BOX box, abox;
00108     P_LINE *Line, *NLine;  
00109     P_AREA *Area;  
00110     P_NODE *Node;  
00111 
00112     G_debug ( 3, "V2_write_line_nat()" );
00113     offset = V1_write_line_nat ( Map, type, points, cats);
00114     if ( offset < 0 ) return -1;
00115 
00116     /* Update topology */
00117     plus = &(Map->plus);
00118     /* Add line */
00119     if (  plus->built >= GV_BUILD_BASE ) {
00120         line = dig_add_line ( plus, type, points, offset );
00121         G_debug ( 3, "  line added to topo with id = %d", line );
00122         dig_line_box ( points, &box );
00123         dig_line_set_box (plus, line, &box);
00124         if ( line == 1 )
00125             Vect_box_copy (&(plus->box), &box);
00126         else
00127             Vect_box_extend (&(plus->box), &box);
00128     }
00129 
00130     /* Update areas. Areas are modified if: 
00131     *  1) first or/and last point are existing nodes ->
00132     *     - drop areas/islands whose boundaries are neighbour to this boundary at these nodes
00133     *     - try build areas and islands for this boundary and neighbour boundaries going through these nodes
00134     *       Question: may be by adding line created new area/isle which doesn't go through nodes of this line
00135     *            old         new line 
00136     *        +----+----+                    +----+----+                 +----+----+ 
00137     *        | A1 | A2 |  +      /      ->  | A1 |   /|   or +   \   -> | A1 | A2 |\
00138     *        |    |    |                    |    |    |                 |    |    |
00139     *        +----+----+                    +----+----+                 +----+----+
00140     *          I1   I1                        I1   I1                      
00141     *        
00142     *     - reattache all centroids/isles inside new area(s)
00143     *     - attach new isle to area outside
00144     *  2) line is closed ring (node at the end is new, so it is not case above)
00145     *     - build new area/isle
00146     *     - check if it is island or contains island(s)
00147     *     - reattache all centroids/isles inside new area(s)
00148     *     - attach new isle to area outside
00149     *
00150     *  Note that 1) and 2) is done by the same code.
00151     */
00152     
00153     if (  plus->built >= GV_BUILD_AREAS ) {
00154         if ( type == GV_BOUNDARY ) {
00155             Line = plus->Line[line]; 
00156             /* Delete neighbour areas/isles */
00157             first = 1;
00158             for ( s = 1; s < 3; s++ ) { /* for each node */
00159                 if ( s == 1 ) node = Line->N1; /* Node 1 */
00160                 else node = Line->N2;
00161                 G_debug ( 3, "  delete neighbour areas/iseles: side = %d node = %d", s, node );
00162                 Node = plus->Node[node];
00163                 n = 0;
00164                 for (i = 0; i < Node->n_lines; i++) {
00165                     NLine = plus->Line[abs(Node->lines[i])];
00166                     if ( NLine->type == GV_BOUNDARY ) 
00167                         n++;
00168                 }
00169                 
00170                 G_debug ( 3, "  number of boundaries at node = %d", n );
00171                 if ( n > 2) { /* more than 2 boundaries at node ( >= 2 old + 1 new ) */
00172                     /* Line above (to the right), it is enough to check to the right, because if area/isle
00173                     *  exists it is the same to the left */
00174                     if ( s == 1 )
00175                         next_line = dig_angle_next_line (plus, line, GV_RIGHT, GV_BOUNDARY ); 
00176                     else
00177                         next_line = dig_angle_next_line (plus, -line, GV_RIGHT, GV_BOUNDARY ); 
00178 
00179                     if ( next_line != 0 ) { /* there is a boundary to the right */
00180                         NLine = plus->Line[abs(next_line)]; 
00181                         if ( next_line > 0 )      /* the boundary is connected by 1. node */
00182                             area = NLine->right;  /* we are interested just in this side (close to our line) */
00183                         else if ( next_line < 0 ) /* the boundary is connected by 2. node */
00184                             area = NLine->left;   
00185                         
00186                         G_debug ( 3, "  next_line = %d area = %d", next_line, area);
00187                         if ( area > 0 ) {         /* is area */
00188                             Vect_get_area_box ( Map, area, &box); 
00189                             if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00190                             else  Vect_box_extend ( &abox, &box);
00191 
00192                             if ( plus->update_cidx ) {
00193                                 delete_area_cats_from_cidx ( Map, area );
00194                             }
00195                             dig_del_area ( plus, area );
00196                         } else if ( area < 0 ) {  /* is isle */
00197                             dig_del_isle ( plus, -area ); 
00198                         }
00199                     }
00200                 }
00201             }
00202             /* Build new areas/isles. Thas true that we deleted also adjacent areas/isles, but if
00203             *  they form new one our boundary must participate, so we need to build areas/isles
00204             *  just for our boundary */
00205             for (s = 1; s < 3; s++) {
00206                 if ( s == 1 ) side = GV_LEFT;
00207                 else side = GV_RIGHT;
00208                 G_debug ( 3, "  build area/isle on side = %d", side );
00209                 
00210                 G_debug ( 3, "Build area for line = %d, side = %d", line, side );
00211                 area = Vect_build_line_area ( Map, line, side );
00212                 G_debug ( 3, "Build area for line = %d, side = %d", line, side );
00213                 if ( area > 0 ) { /* area */
00214                     Vect_get_area_box ( Map, area, &box); 
00215                     if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00216                     else  Vect_box_extend ( &abox, &box);
00217                 } else if ( area < 0 ) { 
00218                     /* isle -> must be attached -> add to abox */   
00219                     Vect_get_isle_box ( Map, -area, &box); 
00220                     if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00221                     else  Vect_box_extend ( &abox, &box);
00222                 }
00223                 new_area[s-1] = area; 
00224             }
00225             /* Reattach all centroids/isles in deleted areas + new area.
00226             *  Because isles are selected by box it covers also possible new isle created above */
00227             if ( !first ) { /* i.e. old area/isle was deleted or new one created */
00228                 /* Reattache isles */
00229                 if (  plus->built >= GV_BUILD_ATTACH_ISLES )
00230                     Vect_attach_isles ( Map, &abox );
00231                 
00232                 /* Reattach centroids */
00233                 if (  plus->built >= GV_BUILD_CENTROIDS )
00234                     Vect_attach_centroids ( Map, &abox );
00235             }
00236             /* Add to category index */
00237             if ( plus->update_cidx ) {
00238                 for (s = 1; s < 3; s++) {
00239                     if ( new_area[s-1] > 0 ) {
00240                         add_area_cats_to_cidx ( Map, new_area[s-1] );
00241                     }
00242                 }
00243             }
00244         }
00245     }
00246     
00247     /* Attach centroid */
00248     if (  plus->built >= GV_BUILD_CENTROIDS ) {
00249         if ( type == GV_CENTROID ) {
00250             sel_area = Vect_find_area ( Map, points->x[0], points->y[0] );
00251             G_debug ( 3, "  new centroid %d is in area %d", line, sel_area);
00252             if ( sel_area > 0 ) {
00253                 Area = plus->Area[sel_area];
00254                 Line = plus->Line[line];
00255                 if ( Area->centroid == 0 ) { /* first centroid */
00256                     G_debug ( 3, "  first centroid -> attach to area");
00257                     Area->centroid = line;
00258                     Line->left = sel_area;
00259                     if ( plus->update_cidx ) {
00260                         add_area_cats_to_cidx ( Map, sel_area );
00261                     }
00262                 } else {  /* duplicate centroid */
00263                     G_debug ( 3, "  duplicate centroid -> do not attach to area");
00264                     Line->left = -sel_area;
00265                 }
00266             }
00267         }
00268     }
00269     
00270     /* Add cetegory index */  
00271     for ( i = 0 ; i < cats->n_cats; i++ ) {
00272         dig_cidx_add_cat_sorted ( plus, cats->field[i], cats->cat[i], line, type );
00273     }
00274 
00275     G_debug ( 3, "updated lines : %d , updated nodes : %d", plus->n_uplines, plus->n_upnodes );
00276     return line;
00277 }
00278 
00279 /* Rewrites line at the given offset.
00280 *  If the number of points or cats differs from
00281 *  the original one or the type is changed:
00282 *  GV_POINTS -> GV_LINES or GV_LINES -> GV_POINTS,
00283 *  the old one is deleted and the
00284 *  new is appended to the end of the file.
00285 *
00286 *  Returns: line offset
00287 *           -1 on error
00288 */
00289 long 
00290 V1_rewrite_line_nat (  struct Map_info *Map,
00291                        long   offset,
00292                        int    type,
00293                        struct line_pnts *points,
00294                        struct line_cats *cats)
00295 {
00296   int    old_type;
00297   struct line_pnts *old_points;
00298   struct line_cats *old_cats; 
00299   long   new_offset;
00300  
00301   /* TODO: enable points and cats == NULL  */
00302   
00303   /* First compare numbers of points and cats with tha old one */
00304   old_points = Vect_new_line_struct ();
00305   old_cats = Vect_new_cats_struct ();
00306 
00307   old_type = V1_read_line_nat ( Map, old_points, old_cats, offset );
00308   if ( old_type == -1 ) return (-1); /* error */
00309 
00310   if ( old_type != -2 /* EOF -> write new line */
00311        && points->n_points == old_points->n_points 
00312        && cats->n_cats == old_cats->n_cats
00313        && (   ( (type & GV_POINTS) && (old_type & GV_POINTS) )   
00314            || ( (type & GV_LINES ) && (old_type & GV_LINES ) ) ) ) {
00315 
00316       /* equal -> overwrite the old */
00317       return V1__rewrite_line_nat (Map, offset, type, points, cats);
00318   } else {
00319       /* differ -> delete the old and append new */
00320       /* delete old */
00321       V1_delete_line_nat ( Map, offset);
00322       
00323       /* write new */
00324       if ( dig_fseek ( &(Map->dig_fp), 0L, SEEK_END) == -1 )    /*  end of file */
00325           return -1;
00326       
00327       new_offset = dig_ftell ( &(Map->dig_fp) );
00328       if ( new_offset == -1 )
00329           return -1;
00330 
00331       return V1__rewrite_line_nat (Map, new_offset, type, points, cats);
00332   }
00333 }
00334 
00335 /* Rewrites line of given number.
00336 * 
00337 *  Returns: number of new line
00338 *           -1 on error
00339 */
00340 int
00341 V2_rewrite_line_nat (  struct Map_info *Map,
00342                        int    line,
00343                        int    type,
00344                        struct line_pnts *points,
00345                        struct line_cats *cats)
00346 {
00347     /* TODO: this is just quick shortcut because we have already V2_delete_nat()
00348     *        and V2_write_nat() this function first deletes old line
00349     *        and then writes new one. It is not very effective if number of points
00350     *        and cats was not changed or topology is not changed (nodes not moved,
00351     *        angles not changed etc.) */
00352 
00353     V2_delete_line_nat ( Map, line );
00354   
00355     return ( V2_write_line_nat ( Map, type, points, cats) );
00356 }
00357 
00358 /* Rewrites line at the given offset.
00359 *
00360 *  Returns: line offset
00361 *           -1 on error
00362 */
00363 long 
00364 V1__rewrite_line_nat (
00365                        struct Map_info *Map,
00366                        long   offset,
00367                        int    type,
00368                        struct line_pnts *points,
00369                        struct line_cats *cats)
00370 {
00371   int  i, n_points;
00372   char rhead, nc;
00373   short field;
00374   GVFILE *dig_fp;
00375   
00376   dig_set_cur_port (&(Map->head.port));
00377   dig_fp = &(Map->dig_fp);
00378   
00379   if ( dig_fseek ( dig_fp, offset, 0) == -1 )
00380       return -1;
00381 
00382   /* first byte:   0 bit: 1 - alive, 0 - dead
00383   *                1 bit: 1 - categories, 0 - no category
00384   *              2-3 bit: store type
00385   *              4-5 bit: reserved for store type expansion
00386   *              6-7 bit: not used  
00387   */
00388   
00389   rhead = (char) dig_type_to_store ( type );
00390   rhead <<= 2;
00391   if (cats->n_cats > 0) {
00392       rhead |=  0x02;
00393   }
00394   rhead |= 0x01; /* written/rewritten is always alive */
00395   
00396   if (0 >= dig__fwrite_port_C (&rhead, 1, dig_fp)) {
00397     return -1;
00398   }
00399 
00400   if (cats->n_cats > 0) {
00401       if ( Map->head.Version_Minor == 1 ) { /* coor format 5.1 */
00402           if (0 >= dig__fwrite_port_I ( &(cats->n_cats), 1, dig_fp))
00403             return -1;
00404       } else { /* coor format 5.0 */
00405           nc = (char) cats->n_cats;
00406           if (0 >= dig__fwrite_port_C (&nc, 1, dig_fp))
00407             return -1;
00408       }
00409 
00410       if (cats->n_cats > 0) {
00411           if ( Map->head.Version_Minor == 1 ) { /* coor format 5.1 */
00412               if (0 >= dig__fwrite_port_I (cats->field, cats->n_cats, dig_fp))
00413                 return -1;
00414           } else { /* coor format 5.0 */
00415               for (i = 0; i < cats->n_cats; i++) { 
00416                   field = (short) cats->field[i];
00417                   if (0 >= dig__fwrite_port_S (&field, 1, dig_fp))
00418                     return -1;
00419               }
00420           }
00421           if (0 >= dig__fwrite_port_I (cats->cat, cats->n_cats, dig_fp))
00422             return -1;
00423       } 
00424   }
00425   
00426   if ( type & GV_POINTS ) {
00427       n_points = 1;       
00428   } else {
00429       n_points = points->n_points;
00430       if (0 >= dig__fwrite_port_I (&n_points, 1, dig_fp) )
00431           return -1;
00432   }
00433 
00434   if (0 >= dig__fwrite_port_D (points->x, n_points, dig_fp))
00435     return -1;
00436   if (0 >= dig__fwrite_port_D (points->y, n_points, dig_fp))
00437     return -1;
00438 
00439   if ( Map->head.with_z ) {
00440       if (0 >= dig__fwrite_port_D (points->z, n_points, dig_fp))
00441           return -1;
00442   }
00443   
00444   if ( 0 != dig_fflush (dig_fp) )
00445       return -1;
00446 
00447   return offset;
00448 }
00449 
00450 /* Deletes line at the given offset.
00451 *
00452 *  Returns:  0 ok
00453 *           -1 on error
00454 */
00455 int 
00456 V1_delete_line_nat (
00457                        struct Map_info *Map,
00458                        long   offset )
00459 {
00460   char rhead;
00461   GVFILE *dig_fp;
00462   
00463   G_debug ( 3, "V1_delete_line_nat(), offset = %ld", offset );
00464   
00465   dig_set_cur_port (&(Map->head.port));
00466   dig_fp = &(Map->dig_fp);
00467   
00468   if ( dig_fseek ( dig_fp, offset, 0) == -1 )
00469       return -1;
00470 
00471   /* read old */
00472   if (0 >= dig__fread_port_C (&rhead, 1, dig_fp))
00473       return (-1);
00474   
00475   rhead &= 0xFE; 
00476   
00477   if ( dig_fseek (dig_fp, offset, 0) == -1 )
00478       return -1;
00479 
00480   if (0 >= dig__fwrite_port_C (&rhead, 1, dig_fp))
00481       return -1;
00482 
00483   if ( 0 != dig_fflush (dig_fp) )
00484       return -1;
00485 
00486   return 0;
00487 }
00488 
00489 /* Deletes line of given number.
00490 *
00491 *  Returns:  0 ok
00492 *           -1 on error
00493 */
00494 int 
00495 V2_delete_line_nat ( struct Map_info *Map, int  line )
00496 {
00497   int ret, i, side, type=0, first=0, next_line, area;
00498   P_LINE *Line = NULL;
00499   P_AREA *Area;  
00500   struct Plus_head *plus;
00501   BOUND_BOX box, abox;
00502   int adjacent[4], n_adjacent=0;
00503   static struct line_cats *Cats = NULL;
00504   
00505   G_debug ( 3, "V2_delete_line_nat(), line = %d", line );
00506   
00507   plus = &(Map->plus);
00508   
00509   if (  plus->built >= GV_BUILD_BASE ) {
00510       Line = Map->plus.Line[line]; 
00511 
00512       if ( Line == NULL ) G_fatal_error ("Attempt to delete dead line");
00513       type = Line->type;
00514   }
00515 
00516   if ( !Cats ) {
00517       Cats = Vect_new_cats_struct ();
00518   }
00519 
00520   /* Update category index */
00521   if ( plus->update_cidx ) {
00522       type = V2_read_line_nat ( Map, NULL, Cats, line );
00523 
00524       for ( i = 0 ; i < Cats->n_cats; i++ ) {
00525           dig_cidx_del_cat ( plus, Cats->field[i], Cats->cat[i], line, type );
00526       }
00527   }
00528   
00529   /* delete the line from coor */
00530   ret = V1_delete_line_nat (Map, Line->offset); 
00531   
00532   if ( ret == -1 ) { return ret; }
00533 
00534   /* Update topology */
00535   if (  plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY ) {
00536       /* Store adjacent boundaries at nodes (will be used to rebuild area/isle) */
00537       /* Adjacent are stored: > 0 - we want right side; < 0 - we want left side */
00538       n_adjacent = 0;
00539       
00540       next_line = dig_angle_next_line (plus, line, GV_RIGHT, GV_BOUNDARY ); 
00541       if ( next_line != 0 && abs(next_line) != line ) { 
00542           /* N1, to the right -> we want the right side for > 0  and left for < 0*/
00543           adjacent[n_adjacent] =  next_line;
00544           n_adjacent++;
00545       }
00546       next_line = dig_angle_next_line (plus, line, GV_LEFT, GV_BOUNDARY ); 
00547       if ( next_line != 0 && abs(next_line) != line ) { 
00548           /* N1, to the left -> we want the left side for > 0  and right for < 0*/
00549           adjacent[n_adjacent] =  -next_line;
00550           n_adjacent++;
00551       }
00552       next_line = dig_angle_next_line (plus, -line, GV_RIGHT, GV_BOUNDARY ); 
00553       if ( next_line != 0 && abs(next_line) != line ) { 
00554           /* N2, to the right -> we want the right side for > 0  and left for < 0*/
00555           adjacent[n_adjacent] =  next_line;
00556           n_adjacent++;
00557       }
00558       next_line = dig_angle_next_line (plus, -line, GV_LEFT, GV_BOUNDARY ); 
00559       if ( next_line != 0 && abs(next_line) != line ) { 
00560           /* N2, to the left -> we want the left side for > 0  and right for < 0*/
00561           adjacent[n_adjacent] =  -next_line;
00562           n_adjacent++;
00563       }
00564 
00565       /* Delete area(s) and islands this line forms */
00566       first = 1;
00567       if ( Line->left > 0 ) { /* delete area */
00568           Vect_get_area_box ( Map, Line->left, &box); 
00569           if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00570           else  Vect_box_extend ( &abox, &box);
00571           
00572           if ( plus->update_cidx ) {
00573               delete_area_cats_from_cidx ( Map, Line->left );
00574           }
00575           dig_del_area ( plus, Line->left );
00576       } else if ( Line->left < 0 )  {  /* delete isle */
00577           dig_del_isle ( plus, -Line->left );
00578       }
00579       if ( Line->right > 0 ) { /* delete area */
00580           Vect_get_area_box ( Map, Line->right, &box); 
00581           if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00582           else  Vect_box_extend ( &abox, &box);
00583 
00584           if ( plus->update_cidx ) {
00585               delete_area_cats_from_cidx ( Map, Line->right );
00586           }
00587           dig_del_area ( plus, Line->right );
00588       } else if ( Line->right < 0 )  {  /* delete isle */
00589           dig_del_isle ( plus, -Line->right );
00590       }
00591   }
00592 
00593   /* Delete reference from area */
00594   if (  plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID ) {
00595       if ( Line->left > 0 ) {
00596           G_debug ( 3, "Remove centroid %d from area %d", line, Line->left );
00597           if ( plus->update_cidx ) {
00598               delete_area_cats_from_cidx ( Map, Line->left );
00599           }
00600           Area = Map->plus.Area[Line->left];
00601           Area->centroid = 0;
00602       }  
00603   }
00604   
00605   /* delete the line from topo */
00606   dig_del_line ( plus, line );
00607 
00608   /* Rebuild areas/isles and attach centroids and isles */
00609   if ( plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY ) {
00610       int *new_areas, nnew_areas;
00611 
00612       nnew_areas = 0;
00613       new_areas = (int *) G_malloc ( 2 * n_adjacent * sizeof(int) );
00614       /* Rebuild areas/isles */
00615       for (i = 0; i < n_adjacent; i++) {
00616           if ( adjacent[i] > 0 ) side = GV_RIGHT;
00617           else side = GV_LEFT;
00618         
00619           G_debug ( 3, "Build area for line = %d, side = %d", adjacent[i], side );
00620           
00621           area = Vect_build_line_area ( Map, abs(adjacent[i]), side );
00622           if ( area > 0 ) { /* area */
00623               Vect_get_area_box ( Map, area, &box); 
00624               if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00625               else  Vect_box_extend ( &abox, &box);
00626                     
00627               new_areas[nnew_areas] = area;
00628               nnew_areas++;
00629           } else if ( area < 0 ) { 
00630               /* isle -> must be attached -> add to abox */   
00631               Vect_get_isle_box ( Map, -area, &box); 
00632               if ( first ) { Vect_box_copy ( &abox, &box); first = 0; } 
00633               else  Vect_box_extend ( &abox, &box);
00634           }
00635       }
00636       /* Reattach all centroids/isles in deleted areas + new area.
00637       *  Because isles are selected by box it covers also possible new isle created above */
00638       if ( !first ) { /* i.e. old area/isle was deleted or new one created */
00639           /* Reattache isles */
00640           if (  plus->built >= GV_BUILD_ATTACH_ISLES )
00641               Vect_attach_isles ( Map, &abox );
00642             
00643           /* Reattach centroids */
00644           if (  plus->built >= GV_BUILD_CENTROIDS )
00645               Vect_attach_centroids ( Map, &abox );
00646       }
00647       
00648       if ( plus->update_cidx ) {
00649           for (i = 0; i < nnew_areas; i++ ) {
00650             add_area_cats_to_cidx ( Map, new_areas[i] );
00651           }
00652       }
00653   }
00654 
00655   G_debug ( 3, "updated lines : %d , updated nodes : %d", plus->n_uplines, plus->n_upnodes );
00656   return ret;
00657 }
00658 

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5