write_nat.c

Go to the documentation of this file.
00001 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <math.h>
00029 
00030 #include <grass/gis.h>
00031 #include <grass/Vect.h>
00032 #include <grass/glocale.h>
00033 
00040 static void delete_area_cats_from_cidx(struct Map_info *Map, int area)
00041 {
00042     int i;
00043     P_AREA *Area;
00044     static struct line_cats *Cats = NULL;
00045 
00046     G_debug(3, "delete_area_cats_from_cidx() area = %d", area);
00047 
00048     Area = Map->plus.Area[area];
00049     if (!Area)
00050         G_fatal_error(_("%s: Area %d does not exist"),
00051                       "delete_area_cats_from_cidx()", area);
00052     
00053     if (Area->centroid == 0) /* no centroid found */
00054         return;
00055 
00056     if (!Cats)
00057         Cats = Vect_new_cats_struct();
00058 
00059     V2_read_line_nat(Map, NULL, Cats, Area->centroid);
00060 
00061     for (i = 0; i < Cats->n_cats; i++) {
00062         dig_cidx_del_cat(&(Map->plus), Cats->field[i], Cats->cat[i], area,
00063                          GV_AREA);
00064     }
00065 }
00066 
00073 static void add_area_cats_to_cidx(struct Map_info *Map, int area)
00074 {
00075     int i;
00076     P_AREA *Area;
00077     static struct line_cats *Cats = NULL;
00078 
00079     G_debug(3, "add_area_cats_to_cidx() area = %d", area);
00080 
00081     Area = Map->plus.Area[area];
00082     if (!Area)
00083         G_fatal_error(_("%s: Area %d does not exist"),
00084                       "add_area_cats_to_cidx():", area);
00085 
00086     if (Area->centroid == 0) /* no centroid found */
00087         return;
00088 
00089     if (!Cats)
00090         Cats = Vect_new_cats_struct();
00091 
00092     V2_read_line_nat(Map, NULL, Cats, Area->centroid);
00093 
00094     for (i = 0; i < Cats->n_cats; i++) {
00095         dig_cidx_add_cat_sorted(&(Map->plus), Cats->field[i], Cats->cat[i],
00096                                 area, GV_AREA);
00097     }
00098 }
00099 
00131 static void add_line_to_topo(struct Map_info *Map, int line,
00132                              struct line_pnts *points, struct line_cats *cats)
00133 {
00134     int first, s, n, i;
00135     int type, node, next_line, area, side, sel_area, new_area[2];
00136 
00137     struct Plus_head *plus;
00138     P_LINE *Line, *NLine;
00139     P_NODE *Node;
00140     P_AREA *Area;
00141     
00142     BOUND_BOX box, abox;
00143     
00144     plus = &(Map->plus);
00145     Line = plus->Line[line];
00146     type = Line->type;
00147 
00148     if (plus->built >= GV_BUILD_AREAS) {
00149         if (type == GV_BOUNDARY) {
00150             /* Delete neighbour areas/isles */
00151             first = 1;
00152             for (s = 1; s < 3; s++) {   /* for each node */
00153                 if (s == 1)
00154                     node = Line->N1;    /* Node 1 */
00155                 else
00156                     node = Line->N2;
00157                 G_debug(3,
00158                         "  delete neighbour areas/iseles: side = %d node = %d",
00159                         s, node);
00160                 Node = plus->Node[node];
00161                 n = 0;
00162                 for (i = 0; i < Node->n_lines; i++) {
00163                     NLine = plus->Line[abs(Node->lines[i])];
00164                     if (NLine->type == GV_BOUNDARY)
00165                         n++;
00166                 }
00167 
00168                 G_debug(3, "  number of boundaries at node = %d", n);
00169                 if (n > 2) {    /* more than 2 boundaries at node ( >= 2 old + 1 new ) */
00170                     /* Line above (to the right), it is enough to check to the right, because if area/isle
00171                      *  exists it is the same to the left */
00172                     if (s == 1)
00173                         next_line =
00174                             dig_angle_next_line(plus, line, GV_RIGHT,
00175                                                 GV_BOUNDARY);
00176                     else
00177                         next_line =
00178                             dig_angle_next_line(plus, -line, GV_RIGHT,
00179                                                 GV_BOUNDARY);
00180 
00181                     if (next_line != 0) {       /* there is a boundary to the right */
00182                         NLine = plus->Line[abs(next_line)];
00183                         if (next_line > 0)      /* the boundary is connected by 1. node */
00184                             area = NLine->right;        /* we are interested just in this side (close to our line) */
00185                         else if (next_line < 0) /* the boundary is connected by 2. node */
00186                             area = NLine->left;
00187 
00188                         G_debug(3, "  next_line = %d area = %d", next_line,
00189                                 area);
00190                         if (area > 0) { /* is area */
00191                             Vect_get_area_box(Map, area, &box);
00192                             if (first) {
00193                                 Vect_box_copy(&abox, &box);
00194                                 first = 0;
00195                             }
00196                             else
00197                                 Vect_box_extend(&abox, &box);
00198 
00199                             if (plus->update_cidx) {
00200                                 delete_area_cats_from_cidx(Map, area);
00201                             }
00202                             dig_del_area(plus, area);
00203                         }
00204                         else if (area < 0) {    /* is isle */
00205                             dig_del_isle(plus, -area);
00206                         }
00207                     }
00208                 }
00209             }
00210             /* Build new areas/isles. Thas true that we deleted also adjacent areas/isles, but if
00211              *  they form new one our boundary must participate, so we need to build areas/isles
00212              *  just for our boundary */
00213             for (s = 1; s < 3; s++) {
00214                 if (s == 1)
00215                     side = GV_LEFT;
00216                 else
00217                     side = GV_RIGHT;
00218                 G_debug(3, "  build area/isle on side = %d", side);
00219 
00220                 G_debug(3, "Build area for line = %d, side = %d", line, side);
00221                 area = Vect_build_line_area(Map, line, side);
00222                 G_debug(3, "Build area for line = %d, side = %d", line, side);
00223                 if (area > 0) { /* area */
00224                     Vect_get_area_box(Map, area, &box);
00225                     if (first) {
00226                         Vect_box_copy(&abox, &box);
00227                         first = 0;
00228                     }
00229                     else
00230                         Vect_box_extend(&abox, &box);
00231                 }
00232                 else if (area < 0) {
00233                     /* isle -> must be attached -> add to abox */
00234                     Vect_get_isle_box(Map, -area, &box);
00235                     if (first) {
00236                         Vect_box_copy(&abox, &box);
00237                         first = 0;
00238                     }
00239                     else
00240                         Vect_box_extend(&abox, &box);
00241                 }
00242                 new_area[s - 1] = area;
00243             }
00244             /* Reattach all centroids/isles in deleted areas + new area.
00245              *  Because isles are selected by box it covers also possible new isle created above */
00246             if (!first) {       /* i.e. old area/isle was deleted or new one created */
00247                 /* Reattache isles */
00248                 if (plus->built >= GV_BUILD_ATTACH_ISLES)
00249                     Vect_attach_isles(Map, &abox);
00250 
00251                 /* Reattach centroids */
00252                 if (plus->built >= GV_BUILD_CENTROIDS)
00253                     Vect_attach_centroids(Map, &abox);
00254             }
00255             /* Add to category index */
00256             if (plus->update_cidx) {
00257                 for (s = 1; s < 3; s++) {
00258                     if (new_area[s - 1] > 0) {
00259                         add_area_cats_to_cidx(Map, new_area[s - 1]);
00260                     }
00261                 }
00262             }
00263         }
00264     }
00265 
00266     /* Attach centroid */
00267     if (plus->built >= GV_BUILD_CENTROIDS) {
00268         if (type == GV_CENTROID) {
00269             sel_area = Vect_find_area(Map, points->x[0], points->y[0]);
00270             G_debug(3, "  new centroid %d is in area %d", line, sel_area);
00271             if (sel_area > 0) {
00272                 Area = plus->Area[sel_area];
00273                 Line = plus->Line[line];
00274                 if (Area->centroid == 0) {      /* first centroid */
00275                     G_debug(3, "  first centroid -> attach to area");
00276                     Area->centroid = line;
00277                     Line->left = sel_area;
00278                     if (plus->update_cidx) {
00279                         add_area_cats_to_cidx(Map, sel_area);
00280                     }
00281                 }
00282                 else {          /* duplicate centroid */
00283                     G_debug(3,
00284                             "  duplicate centroid -> do not attach to area");
00285                     Line->left = -sel_area;
00286                 }
00287             }
00288         }
00289     }
00290 
00291     /* Add cetegory index */
00292     for (i = 0; i < cats->n_cats; i++) {
00293         dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
00294                                 type);
00295     }
00296 
00297     return;
00298 }
00299 
00300 long V1__rewrite_line_nat(struct Map_info *Map, long offset, int type,
00301                           struct line_pnts *points, struct line_cats *cats);
00302 
00314 long V1_write_line_nat(struct Map_info *Map,
00315                        int type, struct line_pnts *points, struct line_cats *cats)
00316 {
00317     long offset;
00318 
00319     if (dig_fseek(&(Map->dig_fp), 0L, SEEK_END) == -1)  /* set to  end of file */
00320         return -1;
00321 
00322     offset = dig_ftell(&(Map->dig_fp));
00323     if (offset == -1)
00324         return -1;
00325 
00326     return V1__rewrite_line_nat(Map, offset, type, points, cats);
00327 }
00328 
00340 long V2_write_line_nat(struct Map_info *Map,
00341                        int type, struct line_pnts *points, struct line_cats *cats)
00342 {
00343     int line;
00344     long offset;
00345     struct Plus_head *plus;
00346     BOUND_BOX box;
00347 
00348     line = 0;
00349     
00350     G_debug(3, "V2_write_line_nat()");
00351     offset = V1_write_line_nat(Map, type, points, cats);
00352     if (offset < 0)
00353         return -1;
00354 
00355     /* Update topology */
00356     plus = &(Map->plus);
00357     /* Add line */
00358     if (plus->built >= GV_BUILD_BASE) {
00359         line = dig_add_line(plus, type, points, offset);
00360         G_debug(3, "  line added to topo with id = %d", line);
00361         dig_line_box(points, &box);
00362         dig_line_set_box(plus, line, &box);
00363         if (line == 1)
00364             Vect_box_copy(&(plus->box), &box);
00365         else
00366             Vect_box_extend(&(plus->box), &box);
00367     }
00368 
00369     add_line_to_topo(Map,
00370                      line, points, cats);
00371 
00372     G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
00373             plus->n_upnodes);
00374     
00375     return line;
00376 }
00377 
00397 long V1_rewrite_line_nat(struct Map_info *Map,
00398                          long offset,
00399                          int type,
00400                          struct line_pnts *points, struct line_cats *cats)
00401 {
00402     int old_type;
00403     struct line_pnts *old_points;
00404     struct line_cats *old_cats;
00405     long new_offset;
00406     
00407     /* TODO: enable points and cats == NULL  */
00408 
00409     /* First compare numbers of points and cats with tha old one */
00410     old_points = Vect_new_line_struct();
00411     old_cats = Vect_new_cats_struct();
00412 
00413     old_type = V1_read_line_nat(Map, old_points, old_cats, offset);
00414     if (old_type == -1)
00415         return (-1);            /* error */
00416 
00417     if (old_type != -2          /* EOF -> write new line */
00418         && points->n_points == old_points->n_points
00419         && cats->n_cats == old_cats->n_cats
00420         && (((type & GV_POINTS) && (old_type & GV_POINTS))
00421             || ((type & GV_LINES) && (old_type & GV_LINES)))) {
00422 
00423         /* equal -> overwrite the old */
00424         return V1__rewrite_line_nat(Map, offset, type, points, cats);
00425     }
00426     else {
00427         /* differ -> delete the old and append new */
00428         /* delete old */
00429         V1_delete_line_nat(Map, offset);
00430 
00431         /* write new */
00432         if (dig_fseek(&(Map->dig_fp), 0L, SEEK_END) == -1)      /*  end of file */
00433             return -1;
00434 
00435         new_offset = dig_ftell(&(Map->dig_fp));
00436         if (new_offset == -1)
00437             return -1;
00438 
00439         return V1__rewrite_line_nat(Map, new_offset, type, points, cats);
00440     }
00441 }
00442 
00457 int V2_rewrite_line_nat(struct Map_info *Map,
00458                         int line,
00459                         int type,
00460                         struct line_pnts *points, struct line_cats *cats)
00461 {
00462     /* TODO: this is just quick shortcut because we have already V2_delete_nat()
00463      *        and V2_write_nat() this function first deletes old line
00464      *        and then writes new one. It is not very effective if number of points
00465      *        and cats was not changed or topology is not changed (nodes not moved,
00466      *        angles not changed etc.) */
00467 
00468     V2_delete_line_nat(Map, line);
00469 
00470     return (V2_write_line_nat(Map, type, points, cats));
00471 }
00472 
00485 long V1__rewrite_line_nat(struct Map_info *Map,
00486                           long offset,
00487                           int type,
00488                           struct line_pnts *points, struct line_cats *cats)
00489 {
00490     int i, n_points;
00491     char rhead, nc;
00492     short field;
00493     GVFILE *dig_fp;
00494 
00495     dig_set_cur_port(&(Map->head.port));
00496     dig_fp = &(Map->dig_fp);
00497 
00498     if (dig_fseek(dig_fp, offset, 0) == -1)
00499         return -1;
00500 
00501     /* first byte:   0 bit: 1 - alive, 0 - dead
00502      *                1 bit: 1 - categories, 0 - no category
00503      *              2-3 bit: store type
00504      *              4-5 bit: reserved for store type expansion
00505      *              6-7 bit: not used  
00506      */
00507 
00508     rhead = (char)dig_type_to_store(type);
00509     rhead <<= 2;
00510     if (cats->n_cats > 0) {
00511         rhead |= 0x02;
00512     }
00513     rhead |= 0x01;              /* written/rewritten is always alive */
00514 
00515     if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp)) {
00516         return -1;
00517     }
00518 
00519     if (cats->n_cats > 0) {
00520         if (Map->head.Version_Minor == 1) {     /* coor format 5.1 */
00521             if (0 >= dig__fwrite_port_I(&(cats->n_cats), 1, dig_fp))
00522                 return -1;
00523         }
00524         else {                  /* coor format 5.0 */
00525             nc = (char)cats->n_cats;
00526             if (0 >= dig__fwrite_port_C(&nc, 1, dig_fp))
00527                 return -1;
00528         }
00529 
00530         if (cats->n_cats > 0) {
00531             if (Map->head.Version_Minor == 1) { /* coor format 5.1 */
00532                 if (0 >=
00533                     dig__fwrite_port_I(cats->field, cats->n_cats, dig_fp))
00534                     return -1;
00535             }
00536             else {              /* coor format 5.0 */
00537                 for (i = 0; i < cats->n_cats; i++) {
00538                     field = (short)cats->field[i];
00539                     if (0 >= dig__fwrite_port_S(&field, 1, dig_fp))
00540                         return -1;
00541                 }
00542             }
00543             if (0 >= dig__fwrite_port_I(cats->cat, cats->n_cats, dig_fp))
00544                 return -1;
00545         }
00546     }
00547 
00548     if (type & GV_POINTS) {
00549         n_points = 1;
00550     }
00551     else {
00552         n_points = points->n_points;
00553         if (0 >= dig__fwrite_port_I(&n_points, 1, dig_fp))
00554             return -1;
00555     }
00556 
00557     if (0 >= dig__fwrite_port_D(points->x, n_points, dig_fp))
00558         return -1;
00559     if (0 >= dig__fwrite_port_D(points->y, n_points, dig_fp))
00560         return -1;
00561 
00562     if (Map->head.with_z) {
00563         if (0 >= dig__fwrite_port_D(points->z, n_points, dig_fp))
00564             return -1;
00565     }
00566 
00567     if (0 != dig_fflush(dig_fp))
00568         return -1;
00569 
00570     return offset;
00571 }
00572 
00582 int V1_delete_line_nat(struct Map_info *Map, long offset)
00583 {
00584     char rhead;
00585     GVFILE *dig_fp;
00586 
00587     G_debug(3, "V1_delete_line_nat(), offset = %ld", offset);
00588 
00589     dig_set_cur_port(&(Map->head.port));
00590     dig_fp = &(Map->dig_fp);
00591 
00592     if (dig_fseek(dig_fp, offset, 0) == -1)
00593         return -1;
00594 
00595     /* read old */
00596     if (0 >= dig__fread_port_C(&rhead, 1, dig_fp))
00597         return (-1);
00598 
00599     rhead &= 0xFE;
00600 
00601     if (dig_fseek(dig_fp, offset, 0) == -1)
00602         return -1;
00603 
00604     if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp))
00605         return -1;
00606 
00607     if (0 != dig_fflush(dig_fp))
00608         return -1;
00609 
00610     return 0;
00611 }
00612 
00622 int V2_delete_line_nat(struct Map_info *Map, int line)
00623 {
00624     int ret, i, side, type = 0, first = 0, next_line, area;
00625     P_LINE *Line = NULL;
00626     P_AREA *Area;
00627     struct Plus_head *plus;
00628     BOUND_BOX box, abox;
00629     int adjacent[4], n_adjacent = 0;
00630     static struct line_cats *Cats = NULL;
00631 
00632     G_debug(3, "V2_delete_line_nat(), line = %d", line);
00633 
00634     plus = &(Map->plus);
00635 
00636     if (plus->built >= GV_BUILD_BASE) {
00637         Line = Map->plus.Line[line];
00638 
00639         if (Line == NULL)
00640             G_fatal_error(_("Attempt to delete dead feature"));
00641         type = Line->type;
00642     }
00643 
00644     if (!Cats) {
00645         Cats = Vect_new_cats_struct();
00646     }
00647 
00648     /* Update category index */
00649     if (plus->update_cidx) {
00650         type = V2_read_line_nat(Map, NULL, Cats, line);
00651 
00652         for (i = 0; i < Cats->n_cats; i++) {
00653             dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
00654         }
00655     }
00656 
00657     /* delete the line from coor */
00658     ret = V1_delete_line_nat(Map, Line->offset);
00659 
00660     if (ret == -1) {
00661         return ret;
00662     }
00663 
00664     /* Update topology */
00665     if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
00666         /* Store adjacent boundaries at nodes (will be used to rebuild area/isle) */
00667         /* Adjacent are stored: > 0 - we want right side; < 0 - we want left side */
00668         n_adjacent = 0;
00669 
00670         next_line = dig_angle_next_line(plus, line, GV_RIGHT, GV_BOUNDARY);
00671         if (next_line != 0 && abs(next_line) != line) {
00672             /* N1, to the right -> we want the right side for > 0  and left for < 0 */
00673             adjacent[n_adjacent] = next_line;
00674             n_adjacent++;
00675         }
00676         next_line = dig_angle_next_line(plus, line, GV_LEFT, GV_BOUNDARY);
00677         if (next_line != 0 && abs(next_line) != line) {
00678             /* N1, to the left -> we want the left side for > 0  and right for < 0 */
00679             adjacent[n_adjacent] = -next_line;
00680             n_adjacent++;
00681         }
00682         next_line = dig_angle_next_line(plus, -line, GV_RIGHT, GV_BOUNDARY);
00683         if (next_line != 0 && abs(next_line) != line) {
00684             /* N2, to the right -> we want the right side for > 0  and left for < 0 */
00685             adjacent[n_adjacent] = next_line;
00686             n_adjacent++;
00687         }
00688         next_line = dig_angle_next_line(plus, -line, GV_LEFT, GV_BOUNDARY);
00689         if (next_line != 0 && abs(next_line) != line) {
00690             /* N2, to the left -> we want the left side for > 0  and right for < 0 */
00691             adjacent[n_adjacent] = -next_line;
00692             n_adjacent++;
00693         }
00694 
00695         /* Delete area(s) and islands this line forms */
00696         first = 1;
00697         if (Line->left > 0) {   /* delete area */
00698             Vect_get_area_box(Map, Line->left, &box);
00699             if (first) {
00700                 Vect_box_copy(&abox, &box);
00701                 first = 0;
00702             }
00703             else
00704                 Vect_box_extend(&abox, &box);
00705 
00706             if (plus->update_cidx) {
00707                 delete_area_cats_from_cidx(Map, Line->left);
00708             }
00709             dig_del_area(plus, Line->left);
00710         }
00711         else if (Line->left < 0) {      /* delete isle */
00712             dig_del_isle(plus, -Line->left);
00713         }
00714         if (Line->right > 0) {  /* delete area */
00715             Vect_get_area_box(Map, Line->right, &box);
00716             if (first) {
00717                 Vect_box_copy(&abox, &box);
00718                 first = 0;
00719             }
00720             else
00721                 Vect_box_extend(&abox, &box);
00722 
00723             if (plus->update_cidx) {
00724                 delete_area_cats_from_cidx(Map, Line->right);
00725             }
00726             dig_del_area(plus, Line->right);
00727         }
00728         else if (Line->right < 0) {     /* delete isle */
00729             dig_del_isle(plus, -Line->right);
00730         }
00731     }
00732 
00733     /* Delete reference from area */
00734     if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
00735         if (Line->left > 0) {
00736             G_debug(3, "Remove centroid %d from area %d", line, Line->left);
00737             if (plus->update_cidx) {
00738                 delete_area_cats_from_cidx(Map, Line->left);
00739             }
00740             Area = Map->plus.Area[Line->left];
00741             Area->centroid = 0;
00742         }
00743     }
00744 
00745     /* delete the line from topo */
00746     dig_del_line(plus, line);
00747 
00748     /* Rebuild areas/isles and attach centroids and isles */
00749     if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
00750         int *new_areas, nnew_areas;
00751 
00752         nnew_areas = 0;
00753         new_areas = (int *)G_malloc(2 * n_adjacent * sizeof(int));
00754         /* Rebuild areas/isles */
00755         for (i = 0; i < n_adjacent; i++) {
00756             if (adjacent[i] > 0)
00757                 side = GV_RIGHT;
00758             else
00759                 side = GV_LEFT;
00760 
00761             G_debug(3, "Build area for line = %d, side = %d", adjacent[i],
00762                     side);
00763 
00764             area = Vect_build_line_area(Map, abs(adjacent[i]), side);
00765             if (area > 0) {     /* area */
00766                 Vect_get_area_box(Map, area, &box);
00767                 if (first) {
00768                     Vect_box_copy(&abox, &box);
00769                     first = 0;
00770                 }
00771                 else
00772                     Vect_box_extend(&abox, &box);
00773 
00774                 new_areas[nnew_areas] = area;
00775                 nnew_areas++;
00776             }
00777             else if (area < 0) {
00778                 /* isle -> must be attached -> add to abox */
00779                 Vect_get_isle_box(Map, -area, &box);
00780                 if (first) {
00781                     Vect_box_copy(&abox, &box);
00782                     first = 0;
00783                 }
00784                 else
00785                     Vect_box_extend(&abox, &box);
00786             }
00787         }
00788         /* Reattach all centroids/isles in deleted areas + new area.
00789          *  Because isles are selected by box it covers also possible new isle created above */
00790         if (!first) {           /* i.e. old area/isle was deleted or new one created */
00791             /* Reattache isles */
00792             if (plus->built >= GV_BUILD_ATTACH_ISLES)
00793                 Vect_attach_isles(Map, &abox);
00794 
00795             /* Reattach centroids */
00796             if (plus->built >= GV_BUILD_CENTROIDS)
00797                 Vect_attach_centroids(Map, &abox);
00798         }
00799 
00800         if (plus->update_cidx) {
00801             for (i = 0; i < nnew_areas; i++) {
00802                 add_area_cats_to_cidx(Map, new_areas[i]);
00803             }
00804         }
00805     }
00806 
00807     G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
00808             plus->n_upnodes);
00809     return ret;
00810 }
00811 
00821 int V1_restore_line_nat(struct Map_info *Map, long offset)
00822 {
00823     char rhead;
00824     GVFILE *dig_fp;
00825     
00826     G_debug(3, "V1_restore_line_nat(), offset = %ld", offset);
00827     
00828     dig_set_cur_port(&(Map->head.port));
00829     dig_fp = &(Map->dig_fp);
00830     
00831     if (dig_fseek(dig_fp, offset, 0) == -1)
00832         return -1;
00833     
00834     /* read old */
00835     if (0 >= dig__fread_port_C(&rhead, 1, dig_fp))
00836         return (-1);
00837 
00838     /* mark as alive */
00839     rhead |= 1;
00840     
00841     /* write new */
00842     if (dig_fseek(dig_fp, offset, 0) == -1)
00843         return -1;
00844 
00845     if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp))
00846         return -1;
00847     
00848     if (0 != dig_fflush(dig_fp))
00849         return -1;
00850     
00851     return 0;
00852 }
00853 
00864 int V2_restore_line_nat(struct Map_info *Map, int line, long offset)
00865 {
00866     int i, ret, type;
00867     P_LINE *Line;
00868     struct Plus_head *plus;
00869     BOUND_BOX box;
00870     
00871     static struct line_pnts *points = NULL;
00872     static struct line_cats *cats = NULL;
00873     
00874     Line = NULL;
00875     type = 0;
00876     
00877     G_debug(3, "V2_restore_line_nat(), line = %d", line);
00878 
00879     plus = &(Map->plus);
00880 
00881     if (plus->built >= GV_BUILD_BASE) {
00882         Line = Map->plus.Line[line];
00883 
00884         if (Line != NULL)
00885             G_fatal_error(_("Attempt to restore alive feature"));
00886     }
00887 
00888     if (!points) {
00889         points = Vect_new_line_struct();
00890     }
00891 
00892     if (!cats) {
00893         cats = Vect_new_cats_struct();
00894     }
00895 
00896     /* restore the line in coor */
00897     ret = V1_restore_line_nat(Map, offset);
00898 
00899     if (ret == -1) {
00900         return ret;
00901     }
00902     
00903     /* read feature geometry */
00904     type = V1_read_line_nat(Map, points, cats, offset);
00905     if (type < 0) {
00906         return -1;
00907     }
00908 
00909     /* update category index */
00910     if (plus->update_cidx) {
00911         for (i = 0; i < cats->n_cats; i++) {
00912             dig_cidx_add_cat(plus, cats->field[i], cats->cat[i], line, type);
00913         }
00914     }
00915     
00916     /* restore the line from topo */               
00917     if (plus->built >= GV_BUILD_BASE) {
00918         dig_restore_line(plus, line, type, points, offset);
00919         G_debug(3, "  line restored in topo with id = %d", line);
00920         dig_line_box(points, &box);
00921         dig_line_set_box(plus, line, &box);
00922         Vect_box_extend(&(plus->box), &box);
00923     }
00924     
00925     add_line_to_topo(Map,
00926                      line, points, cats);
00927 
00928     G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
00929             plus->n_upnodes);
00930     
00931 
00932     return ret;
00933 }

Generated on Thu Jul 16 13:21:18 2009 for GRASS Programmer's Manual by  doxygen 1.5.6