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)
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)
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
00151 first = 1;
00152 for (s = 1; s < 3; s++) {
00153 if (s == 1)
00154 node = Line->N1;
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) {
00170
00171
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) {
00182 NLine = plus->Line[abs(next_line)];
00183 if (next_line > 0)
00184 area = NLine->right;
00185 else if (next_line < 0)
00186 area = NLine->left;
00187
00188 G_debug(3, " next_line = %d area = %d", next_line,
00189 area);
00190 if (area > 0) {
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) {
00205 dig_del_isle(plus, -area);
00206 }
00207 }
00208 }
00209 }
00210
00211
00212
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) {
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
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
00245
00246 if (!first) {
00247
00248 if (plus->built >= GV_BUILD_ATTACH_ISLES)
00249 Vect_attach_isles(Map, &abox);
00250
00251
00252 if (plus->built >= GV_BUILD_CENTROIDS)
00253 Vect_attach_centroids(Map, &abox);
00254 }
00255
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
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) {
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 {
00283 G_debug(3,
00284 " duplicate centroid -> do not attach to area");
00285 Line->left = -sel_area;
00286 }
00287 }
00288 }
00289 }
00290
00291
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)
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
00356 plus = &(Map->plus);
00357
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
00408
00409
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);
00416
00417 if (old_type != -2
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
00424 return V1__rewrite_line_nat(Map, offset, type, points, cats);
00425 }
00426 else {
00427
00428
00429 V1_delete_line_nat(Map, offset);
00430
00431
00432 if (dig_fseek(&(Map->dig_fp), 0L, SEEK_END) == -1)
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
00463
00464
00465
00466
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
00502
00503
00504
00505
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;
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) {
00521 if (0 >= dig__fwrite_port_I(&(cats->n_cats), 1, dig_fp))
00522 return -1;
00523 }
00524 else {
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) {
00532 if (0 >=
00533 dig__fwrite_port_I(cats->field, cats->n_cats, dig_fp))
00534 return -1;
00535 }
00536 else {
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
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
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
00658 ret = V1_delete_line_nat(Map, Line->offset);
00659
00660 if (ret == -1) {
00661 return ret;
00662 }
00663
00664
00665 if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
00666
00667
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
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
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
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
00691 adjacent[n_adjacent] = -next_line;
00692 n_adjacent++;
00693 }
00694
00695
00696 first = 1;
00697 if (Line->left > 0) {
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) {
00712 dig_del_isle(plus, -Line->left);
00713 }
00714 if (Line->right > 0) {
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) {
00729 dig_del_isle(plus, -Line->right);
00730 }
00731 }
00732
00733
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
00746 dig_del_line(plus, line);
00747
00748
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
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) {
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
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
00789
00790 if (!first) {
00791
00792 if (plus->built >= GV_BUILD_ATTACH_ISLES)
00793 Vect_attach_isles(Map, &abox);
00794
00795
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
00835 if (0 >= dig__fread_port_C(&rhead, 1, dig_fp))
00836 return (-1);
00837
00838
00839 rhead |= 1;
00840
00841
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
00897 ret = V1_restore_line_nat(Map, offset);
00898
00899 if (ret == -1) {
00900 return ret;
00901 }
00902
00903
00904 type = V1_read_line_nat(Map, points, cats, offset);
00905 if (type < 0) {
00906 return -1;
00907 }
00908
00909
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
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 }