00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00072
00073
00074
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 )
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
00094
00095
00096
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
00117 plus = &(Map->plus);
00118
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
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 if ( plus->built >= GV_BUILD_AREAS ) {
00154 if ( type == GV_BOUNDARY ) {
00155 Line = plus->Line[line];
00156
00157 first = 1;
00158 for ( s = 1; s < 3; s++ ) {
00159 if ( s == 1 ) node = Line->N1;
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) {
00172
00173
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 ) {
00180 NLine = plus->Line[abs(next_line)];
00181 if ( next_line > 0 )
00182 area = NLine->right;
00183 else if ( next_line < 0 )
00184 area = NLine->left;
00185
00186 G_debug ( 3, " next_line = %d area = %d", next_line, area);
00187 if ( area > 0 ) {
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 ) {
00197 dig_del_isle ( plus, -area );
00198 }
00199 }
00200 }
00201 }
00202
00203
00204
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 ) {
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
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
00226
00227 if ( !first ) {
00228
00229 if ( plus->built >= GV_BUILD_ATTACH_ISLES )
00230 Vect_attach_isles ( Map, &abox );
00231
00232
00233 if ( plus->built >= GV_BUILD_CENTROIDS )
00234 Vect_attach_centroids ( Map, &abox );
00235 }
00236
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
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 ) {
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 {
00263 G_debug ( 3, " duplicate centroid -> do not attach to area");
00264 Line->left = -sel_area;
00265 }
00266 }
00267 }
00268 }
00269
00270
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
00280
00281
00282
00283
00284
00285
00286
00287
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
00302
00303
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);
00309
00310 if ( old_type != -2
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
00317 return V1__rewrite_line_nat (Map, offset, type, points, cats);
00318 } else {
00319
00320
00321 V1_delete_line_nat ( Map, offset);
00322
00323
00324 if ( dig_fseek ( &(Map->dig_fp), 0L, SEEK_END) == -1 )
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
00336
00337
00338
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
00348
00349
00350
00351
00352
00353 V2_delete_line_nat ( Map, line );
00354
00355 return ( V2_write_line_nat ( Map, type, points, cats) );
00356 }
00357
00358
00359
00360
00361
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
00383
00384
00385
00386
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;
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 ) {
00402 if (0 >= dig__fwrite_port_I ( &(cats->n_cats), 1, dig_fp))
00403 return -1;
00404 } else {
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 ) {
00412 if (0 >= dig__fwrite_port_I (cats->field, cats->n_cats, dig_fp))
00413 return -1;
00414 } else {
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
00451
00452
00453
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
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
00490
00491
00492
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
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
00530 ret = V1_delete_line_nat (Map, Line->offset);
00531
00532 if ( ret == -1 ) { return ret; }
00533
00534
00535 if ( plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY ) {
00536
00537
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
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
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
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
00561 adjacent[n_adjacent] = -next_line;
00562 n_adjacent++;
00563 }
00564
00565
00566 first = 1;
00567 if ( Line->left > 0 ) {
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 ) {
00577 dig_del_isle ( plus, -Line->left );
00578 }
00579 if ( Line->right > 0 ) {
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 ) {
00589 dig_del_isle ( plus, -Line->right );
00590 }
00591 }
00592
00593
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
00606 dig_del_line ( plus, line );
00607
00608
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
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 ) {
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
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
00637
00638 if ( !first ) {
00639
00640 if ( plus->built >= GV_BUILD_ATTACH_ISLES )
00641 Vect_attach_isles ( Map, &abox );
00642
00643
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