GRASS Programmer's Manual
6.4.2(2012)
|
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 }