GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
write_nat.c
Go to the documentation of this file.
1 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29 
30 #include <grass/gis.h>
31 #include <grass/Vect.h>
32 #include <grass/glocale.h>
33 
40 static void delete_area_cats_from_cidx(struct Map_info *Map, int area)
41 {
42  int i;
43  P_AREA *Area;
44  static struct line_cats *Cats = NULL;
45 
46  G_debug(3, "delete_area_cats_from_cidx() area = %d", area);
47 
48  Area = Map->plus.Area[area];
49  if (!Area)
50  G_fatal_error(_("%s: Area %d does not exist"),
51  "delete_area_cats_from_cidx()", area);
52 
53  if (Area->centroid == 0) /* no centroid found */
54  return;
55 
56  if (!Cats)
57  Cats = Vect_new_cats_struct();
58 
59  V2_read_line_nat(Map, NULL, Cats, Area->centroid);
60 
61  for (i = 0; i < Cats->n_cats; i++) {
62  dig_cidx_del_cat(&(Map->plus), Cats->field[i], Cats->cat[i], area,
63  GV_AREA);
64  }
65 }
66 
73 static void add_area_cats_to_cidx(struct Map_info *Map, int area)
74 {
75  int i;
76  P_AREA *Area;
77  static struct line_cats *Cats = NULL;
78 
79  G_debug(3, "add_area_cats_to_cidx() area = %d", area);
80 
81  Area = Map->plus.Area[area];
82  if (!Area)
83  G_fatal_error(_("%s: Area %d does not exist"),
84  "add_area_cats_to_cidx():", area);
85 
86  if (Area->centroid == 0) /* no centroid found */
87  return;
88 
89  if (!Cats)
90  Cats = Vect_new_cats_struct();
91 
92  V2_read_line_nat(Map, NULL, Cats, Area->centroid);
93 
94  for (i = 0; i < Cats->n_cats; i++) {
95  dig_cidx_add_cat_sorted(&(Map->plus), Cats->field[i], Cats->cat[i],
96  area, GV_AREA);
97  }
98 }
99 
131 static void add_line_to_topo(struct Map_info *Map, int line,
132  struct line_pnts *points, struct line_cats *cats)
133 {
134  int first, s, n, i;
135  int type, node, next_line, area, side, sel_area, new_area[2];
136 
137  struct Plus_head *plus;
138  P_LINE *Line, *NLine;
139  P_NODE *Node;
140  P_AREA *Area;
141 
142  BOUND_BOX box, abox;
143 
144  plus = &(Map->plus);
145  Line = plus->Line[line];
146  type = Line->type;
147 
148  if (plus->built >= GV_BUILD_AREAS) {
149  if (type == GV_BOUNDARY) {
150  /* Delete neighbour areas/isles */
151  first = 1;
152  for (s = 1; s < 3; s++) { /* for each node */
153  if (s == 1)
154  node = Line->N1; /* Node 1 */
155  else
156  node = Line->N2;
157  G_debug(3,
158  " delete neighbour areas/iseles: side = %d node = %d",
159  s, node);
160  Node = plus->Node[node];
161  n = 0;
162  for (i = 0; i < Node->n_lines; i++) {
163  NLine = plus->Line[abs(Node->lines[i])];
164  if (NLine->type == GV_BOUNDARY)
165  n++;
166  }
167 
168  G_debug(3, " number of boundaries at node = %d", n);
169  if (n > 2) { /* more than 2 boundaries at node ( >= 2 old + 1 new ) */
170  /* Line above (to the right), it is enough to check to the right, because if area/isle
171  * exists it is the same to the left */
172  if (s == 1)
173  next_line =
174  dig_angle_next_line(plus, line, GV_RIGHT,
175  GV_BOUNDARY);
176  else
177  next_line =
178  dig_angle_next_line(plus, -line, GV_RIGHT,
179  GV_BOUNDARY);
180 
181  if (next_line != 0) { /* there is a boundary to the right */
182  NLine = plus->Line[abs(next_line)];
183  if (next_line > 0) /* the boundary is connected by 1. node */
184  area = NLine->right; /* we are interested just in this side (close to our line) */
185  else if (next_line < 0) /* the boundary is connected by 2. node */
186  area = NLine->left;
187 
188  G_debug(3, " next_line = %d area = %d", next_line,
189  area);
190  if (area > 0) { /* is area */
191  Vect_get_area_box(Map, area, &box);
192  if (first) {
193  Vect_box_copy(&abox, &box);
194  first = 0;
195  }
196  else
197  Vect_box_extend(&abox, &box);
198 
199  if (plus->update_cidx) {
200  delete_area_cats_from_cidx(Map, area);
201  }
202  dig_del_area(plus, area);
203  }
204  else if (area < 0) { /* is isle */
205  dig_del_isle(plus, -area);
206  }
207  }
208  }
209  }
210  /* Build new areas/isles. Thas true that we deleted also adjacent areas/isles, but if
211  * they form new one our boundary must participate, so we need to build areas/isles
212  * just for our boundary */
213  for (s = 1; s < 3; s++) {
214  if (s == 1)
215  side = GV_LEFT;
216  else
217  side = GV_RIGHT;
218  G_debug(3, " build area/isle on side = %d", side);
219 
220  G_debug(3, "Build area for line = %d, side = %d", line, side);
221  area = Vect_build_line_area(Map, line, side);
222  G_debug(3, "Build area for line = %d, side = %d", line, side);
223  if (area > 0) { /* area */
224  Vect_get_area_box(Map, area, &box);
225  if (first) {
226  Vect_box_copy(&abox, &box);
227  first = 0;
228  }
229  else
230  Vect_box_extend(&abox, &box);
231  }
232  else if (area < 0) {
233  /* isle -> must be attached -> add to abox */
234  Vect_get_isle_box(Map, -area, &box);
235  if (first) {
236  Vect_box_copy(&abox, &box);
237  first = 0;
238  }
239  else
240  Vect_box_extend(&abox, &box);
241  }
242  new_area[s - 1] = area;
243  }
244  /* Reattach all centroids/isles in deleted areas + new area.
245  * Because isles are selected by box it covers also possible new isle created above */
246  if (!first) { /* i.e. old area/isle was deleted or new one created */
247  /* Reattache isles */
248  if (plus->built >= GV_BUILD_ATTACH_ISLES)
249  Vect_attach_isles(Map, &abox);
250 
251  /* Reattach centroids */
252  if (plus->built >= GV_BUILD_CENTROIDS)
253  Vect_attach_centroids(Map, &abox);
254  }
255  /* Add to category index */
256  if (plus->update_cidx) {
257  for (s = 1; s < 3; s++) {
258  if (new_area[s - 1] > 0) {
259  add_area_cats_to_cidx(Map, new_area[s - 1]);
260  }
261  }
262  }
263  }
264  }
265 
266  /* Attach centroid */
267  if (plus->built >= GV_BUILD_CENTROIDS) {
268  if (type == GV_CENTROID) {
269  sel_area = Vect_find_area(Map, points->x[0], points->y[0]);
270  G_debug(3, " new centroid %d is in area %d", line, sel_area);
271  if (sel_area > 0) {
272  Area = plus->Area[sel_area];
273  Line = plus->Line[line];
274  if (Area->centroid == 0) { /* first centroid */
275  G_debug(3, " first centroid -> attach to area");
276  Area->centroid = line;
277  Line->left = sel_area;
278  if (plus->update_cidx) {
279  add_area_cats_to_cidx(Map, sel_area);
280  }
281  }
282  else { /* duplicate centroid */
283  G_debug(3,
284  " duplicate centroid -> do not attach to area");
285  Line->left = -sel_area;
286  }
287  }
288  }
289  }
290 
291  /* Add cetegory index */
292  for (i = 0; i < cats->n_cats; i++) {
293  dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
294  type);
295  }
296 
297  return;
298 }
299 
300 long V1__rewrite_line_nat(struct Map_info *Map, long offset, int type,
301  struct line_pnts *points, struct line_cats *cats);
302 
314 long V1_write_line_nat(struct Map_info *Map,
315  int type, struct line_pnts *points, struct line_cats *cats)
316 {
317  long offset;
318 
319  if (dig_fseek(&(Map->dig_fp), 0L, SEEK_END) == -1) /* set to end of file */
320  return -1;
321 
322  offset = dig_ftell(&(Map->dig_fp));
323  if (offset == -1)
324  return -1;
325 
326  return V1__rewrite_line_nat(Map, offset, type, points, cats);
327 }
328 
340 long V2_write_line_nat(struct Map_info *Map,
341  int type, struct line_pnts *points, struct line_cats *cats)
342 {
343  int line;
344  long offset;
345  struct Plus_head *plus;
346  BOUND_BOX box;
347 
348  line = 0;
349 
350  G_debug(3, "V2_write_line_nat()");
351  offset = V1_write_line_nat(Map, type, points, cats);
352  if (offset < 0)
353  return -1;
354 
355  /* Update topology */
356  plus = &(Map->plus);
357  /* Add line */
358  if (plus->built >= GV_BUILD_BASE) {
359  line = dig_add_line(plus, type, points, offset);
360  G_debug(3, " line added to topo with id = %d", line);
361  dig_line_box(points, &box);
362  dig_line_set_box(plus, line, &box);
363  if (line == 1)
364  Vect_box_copy(&(plus->box), &box);
365  else
366  Vect_box_extend(&(plus->box), &box);
367  }
368 
369  add_line_to_topo(Map,
370  line, points, cats);
371 
372  G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
373  plus->n_upnodes);
374 
375  return line;
376 }
377 
397 long V1_rewrite_line_nat(struct Map_info *Map,
398  long offset,
399  int type,
400  struct line_pnts *points, struct line_cats *cats)
401 {
402  int old_type;
403  struct line_pnts *old_points;
404  struct line_cats *old_cats;
405  long new_offset;
406 
407  /* TODO: enable points and cats == NULL */
408 
409  /* First compare numbers of points and cats with tha old one */
410  old_points = Vect_new_line_struct();
411  old_cats = Vect_new_cats_struct();
412 
413  old_type = V1_read_line_nat(Map, old_points, old_cats, offset);
414  if (old_type == -1)
415  return (-1); /* error */
416 
417  if (old_type != -2 /* EOF -> write new line */
418  && points->n_points == old_points->n_points
419  && cats->n_cats == old_cats->n_cats
420  && (((type & GV_POINTS) && (old_type & GV_POINTS))
421  || ((type & GV_LINES) && (old_type & GV_LINES)))) {
422 
423  /* equal -> overwrite the old */
424  return V1__rewrite_line_nat(Map, offset, type, points, cats);
425  }
426  else {
427  /* differ -> delete the old and append new */
428  /* delete old */
429  V1_delete_line_nat(Map, offset);
430 
431  /* write new */
432  if (dig_fseek(&(Map->dig_fp), 0L, SEEK_END) == -1) /* end of file */
433  return -1;
434 
435  new_offset = dig_ftell(&(Map->dig_fp));
436  if (new_offset == -1)
437  return -1;
438 
439  return V1__rewrite_line_nat(Map, new_offset, type, points, cats);
440  }
441 }
442 
457 int V2_rewrite_line_nat(struct Map_info *Map,
458  int line,
459  int type,
460  struct line_pnts *points, struct line_cats *cats)
461 {
462  /* TODO: this is just quick shortcut because we have already V2_delete_nat()
463  * and V2_write_nat() this function first deletes old line
464  * and then writes new one. It is not very effective if number of points
465  * and cats was not changed or topology is not changed (nodes not moved,
466  * angles not changed etc.) */
467 
468  V2_delete_line_nat(Map, line);
469 
470  return (V2_write_line_nat(Map, type, points, cats));
471 }
472 
485 long V1__rewrite_line_nat(struct Map_info *Map,
486  long offset,
487  int type,
488  struct line_pnts *points, struct line_cats *cats)
489 {
490  int i, n_points;
491  char rhead, nc;
492  short field;
493  GVFILE *dig_fp;
494 
495  dig_set_cur_port(&(Map->head.port));
496  dig_fp = &(Map->dig_fp);
497 
498  if (dig_fseek(dig_fp, offset, 0) == -1)
499  return -1;
500 
501  /* first byte: 0 bit: 1 - alive, 0 - dead
502  * 1 bit: 1 - categories, 0 - no category
503  * 2-3 bit: store type
504  * 4-5 bit: reserved for store type expansion
505  * 6-7 bit: not used
506  */
507 
508  rhead = (char)dig_type_to_store(type);
509  rhead <<= 2;
510  if (cats->n_cats > 0) {
511  rhead |= 0x02;
512  }
513  rhead |= 0x01; /* written/rewritten is always alive */
514 
515  if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp)) {
516  return -1;
517  }
518 
519  if (cats->n_cats > 0) {
520  if (Map->head.Version_Minor == 1) { /* coor format 5.1 */
521  if (0 >= dig__fwrite_port_I(&(cats->n_cats), 1, dig_fp))
522  return -1;
523  }
524  else { /* coor format 5.0 */
525  nc = (char)cats->n_cats;
526  if (0 >= dig__fwrite_port_C(&nc, 1, dig_fp))
527  return -1;
528  }
529 
530  if (cats->n_cats > 0) {
531  if (Map->head.Version_Minor == 1) { /* coor format 5.1 */
532  if (0 >=
533  dig__fwrite_port_I(cats->field, cats->n_cats, dig_fp))
534  return -1;
535  }
536  else { /* coor format 5.0 */
537  for (i = 0; i < cats->n_cats; i++) {
538  field = (short)cats->field[i];
539  if (0 >= dig__fwrite_port_S(&field, 1, dig_fp))
540  return -1;
541  }
542  }
543  if (0 >= dig__fwrite_port_I(cats->cat, cats->n_cats, dig_fp))
544  return -1;
545  }
546  }
547 
548  if (type & GV_POINTS) {
549  n_points = 1;
550  }
551  else {
552  n_points = points->n_points;
553  if (0 >= dig__fwrite_port_I(&n_points, 1, dig_fp))
554  return -1;
555  }
556 
557  if (0 >= dig__fwrite_port_D(points->x, n_points, dig_fp))
558  return -1;
559  if (0 >= dig__fwrite_port_D(points->y, n_points, dig_fp))
560  return -1;
561 
562  if (Map->head.with_z) {
563  if (0 >= dig__fwrite_port_D(points->z, n_points, dig_fp))
564  return -1;
565  }
566 
567  if (0 != dig_fflush(dig_fp))
568  return -1;
569 
570  return offset;
571 }
572 
582 int V1_delete_line_nat(struct Map_info *Map, long offset)
583 {
584  char rhead;
585  GVFILE *dig_fp;
586 
587  G_debug(3, "V1_delete_line_nat(), offset = %ld", offset);
588 
589  dig_set_cur_port(&(Map->head.port));
590  dig_fp = &(Map->dig_fp);
591 
592  if (dig_fseek(dig_fp, offset, 0) == -1)
593  return -1;
594 
595  /* read old */
596  if (0 >= dig__fread_port_C(&rhead, 1, dig_fp))
597  return (-1);
598 
599  rhead &= 0xFE;
600 
601  if (dig_fseek(dig_fp, offset, 0) == -1)
602  return -1;
603 
604  if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp))
605  return -1;
606 
607  if (0 != dig_fflush(dig_fp))
608  return -1;
609 
610  return 0;
611 }
612 
622 int V2_delete_line_nat(struct Map_info *Map, int line)
623 {
624  int ret, i, side, type = 0, first = 0, next_line, area;
625  P_LINE *Line = NULL;
626  P_AREA *Area;
627  struct Plus_head *plus;
628  BOUND_BOX box, abox;
629  int adjacent[4], n_adjacent = 0;
630  static struct line_cats *Cats = NULL;
631 
632  G_debug(3, "V2_delete_line_nat(), line = %d", line);
633 
634  plus = &(Map->plus);
635 
636  if (plus->built >= GV_BUILD_BASE) {
637  Line = Map->plus.Line[line];
638 
639  if (Line == NULL)
640  G_fatal_error(_("Attempt to delete dead feature"));
641  type = Line->type;
642  }
643 
644  if (!Cats) {
645  Cats = Vect_new_cats_struct();
646  }
647 
648  /* Update category index */
649  if (plus->update_cidx) {
650  type = V2_read_line_nat(Map, NULL, Cats, line);
651 
652  for (i = 0; i < Cats->n_cats; i++) {
653  dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
654  }
655  }
656 
657  /* delete the line from coor */
658  ret = V1_delete_line_nat(Map, Line->offset);
659 
660  if (ret == -1) {
661  return ret;
662  }
663 
664  /* Update topology */
665  if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
666  /* Store adjacent boundaries at nodes (will be used to rebuild area/isle) */
667  /* Adjacent are stored: > 0 - we want right side; < 0 - we want left side */
668  n_adjacent = 0;
669 
670  next_line = dig_angle_next_line(plus, line, GV_RIGHT, GV_BOUNDARY);
671  if (next_line != 0 && abs(next_line) != line) {
672  /* N1, to the right -> we want the right side for > 0 and left for < 0 */
673  adjacent[n_adjacent] = next_line;
674  n_adjacent++;
675  }
676  next_line = dig_angle_next_line(plus, line, GV_LEFT, GV_BOUNDARY);
677  if (next_line != 0 && abs(next_line) != line) {
678  /* N1, to the left -> we want the left side for > 0 and right for < 0 */
679  adjacent[n_adjacent] = -next_line;
680  n_adjacent++;
681  }
682  next_line = dig_angle_next_line(plus, -line, GV_RIGHT, GV_BOUNDARY);
683  if (next_line != 0 && abs(next_line) != line) {
684  /* N2, to the right -> we want the right side for > 0 and left for < 0 */
685  adjacent[n_adjacent] = next_line;
686  n_adjacent++;
687  }
688  next_line = dig_angle_next_line(plus, -line, GV_LEFT, GV_BOUNDARY);
689  if (next_line != 0 && abs(next_line) != line) {
690  /* N2, to the left -> we want the left side for > 0 and right for < 0 */
691  adjacent[n_adjacent] = -next_line;
692  n_adjacent++;
693  }
694 
695  /* Delete area(s) and islands this line forms */
696  first = 1;
697  if (Line->left > 0) { /* delete area */
698  Vect_get_area_box(Map, Line->left, &box);
699  if (first) {
700  Vect_box_copy(&abox, &box);
701  first = 0;
702  }
703  else
704  Vect_box_extend(&abox, &box);
705 
706  if (plus->update_cidx) {
707  delete_area_cats_from_cidx(Map, Line->left);
708  }
709  dig_del_area(plus, Line->left);
710  }
711  else if (Line->left < 0) { /* delete isle */
712  dig_del_isle(plus, -Line->left);
713  }
714  if (Line->right > 0) { /* delete area */
715  Vect_get_area_box(Map, Line->right, &box);
716  if (first) {
717  Vect_box_copy(&abox, &box);
718  first = 0;
719  }
720  else
721  Vect_box_extend(&abox, &box);
722 
723  if (plus->update_cidx) {
724  delete_area_cats_from_cidx(Map, Line->right);
725  }
726  dig_del_area(plus, Line->right);
727  }
728  else if (Line->right < 0) { /* delete isle */
729  dig_del_isle(plus, -Line->right);
730  }
731  }
732 
733  /* Delete reference from area */
734  if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
735  if (Line->left > 0) {
736  G_debug(3, "Remove centroid %d from area %d", line, Line->left);
737  if (plus->update_cidx) {
738  delete_area_cats_from_cidx(Map, Line->left);
739  }
740  Area = Map->plus.Area[Line->left];
741  Area->centroid = 0;
742  }
743  }
744 
745  /* delete the line from topo */
746  dig_del_line(plus, line);
747 
748  /* Rebuild areas/isles and attach centroids and isles */
749  if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
750  int *new_areas, nnew_areas;
751 
752  nnew_areas = 0;
753  new_areas = (int *)G_malloc(2 * n_adjacent * sizeof(int));
754  /* Rebuild areas/isles */
755  for (i = 0; i < n_adjacent; i++) {
756  if (adjacent[i] > 0)
757  side = GV_RIGHT;
758  else
759  side = GV_LEFT;
760 
761  G_debug(3, "Build area for line = %d, side = %d", adjacent[i],
762  side);
763 
764  area = Vect_build_line_area(Map, abs(adjacent[i]), side);
765  if (area > 0) { /* area */
766  Vect_get_area_box(Map, area, &box);
767  if (first) {
768  Vect_box_copy(&abox, &box);
769  first = 0;
770  }
771  else
772  Vect_box_extend(&abox, &box);
773 
774  new_areas[nnew_areas] = area;
775  nnew_areas++;
776  }
777  else if (area < 0) {
778  /* isle -> must be attached -> add to abox */
779  Vect_get_isle_box(Map, -area, &box);
780  if (first) {
781  Vect_box_copy(&abox, &box);
782  first = 0;
783  }
784  else
785  Vect_box_extend(&abox, &box);
786  }
787  }
788  /* Reattach all centroids/isles in deleted areas + new area.
789  * Because isles are selected by box it covers also possible new isle created above */
790  if (!first) { /* i.e. old area/isle was deleted or new one created */
791  /* Reattache isles */
792  if (plus->built >= GV_BUILD_ATTACH_ISLES)
793  Vect_attach_isles(Map, &abox);
794 
795  /* Reattach centroids */
796  if (plus->built >= GV_BUILD_CENTROIDS)
797  Vect_attach_centroids(Map, &abox);
798  }
799 
800  if (plus->update_cidx) {
801  for (i = 0; i < nnew_areas; i++) {
802  add_area_cats_to_cidx(Map, new_areas[i]);
803  }
804  }
805  }
806 
807  G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
808  plus->n_upnodes);
809  return ret;
810 }
811 
821 int V1_restore_line_nat(struct Map_info *Map, long offset)
822 {
823  char rhead;
824  GVFILE *dig_fp;
825 
826  G_debug(3, "V1_restore_line_nat(), offset = %ld", offset);
827 
828  dig_set_cur_port(&(Map->head.port));
829  dig_fp = &(Map->dig_fp);
830 
831  if (dig_fseek(dig_fp, offset, 0) == -1)
832  return -1;
833 
834  /* read old */
835  if (0 >= dig__fread_port_C(&rhead, 1, dig_fp))
836  return (-1);
837 
838  /* mark as alive */
839  rhead |= 1;
840 
841  /* write new */
842  if (dig_fseek(dig_fp, offset, 0) == -1)
843  return -1;
844 
845  if (0 >= dig__fwrite_port_C(&rhead, 1, dig_fp))
846  return -1;
847 
848  if (0 != dig_fflush(dig_fp))
849  return -1;
850 
851  return 0;
852 }
853 
864 int V2_restore_line_nat(struct Map_info *Map, int line, long offset)
865 {
866  int i, ret, type;
867  P_LINE *Line;
868  struct Plus_head *plus;
869  BOUND_BOX box;
870 
871  static struct line_pnts *points = NULL;
872  static struct line_cats *cats = NULL;
873 
874  Line = NULL;
875  type = 0;
876 
877  G_debug(3, "V2_restore_line_nat(), line = %d", line);
878 
879  plus = &(Map->plus);
880 
881  if (plus->built >= GV_BUILD_BASE) {
882  Line = Map->plus.Line[line];
883 
884  if (Line != NULL)
885  G_fatal_error(_("Attempt to restore alive feature"));
886  }
887 
888  if (!points) {
889  points = Vect_new_line_struct();
890  }
891 
892  if (!cats) {
893  cats = Vect_new_cats_struct();
894  }
895 
896  /* restore the line in coor */
897  ret = V1_restore_line_nat(Map, offset);
898 
899  if (ret == -1) {
900  return ret;
901  }
902 
903  /* read feature geometry */
904  type = V1_read_line_nat(Map, points, cats, offset);
905  if (type < 0) {
906  return -1;
907  }
908 
909  /* update category index */
910  if (plus->update_cidx) {
911  for (i = 0; i < cats->n_cats; i++) {
912  dig_cidx_add_cat(plus, cats->field[i], cats->cat[i], line, type);
913  }
914  }
915 
916  /* restore the line from topo */
917  if (plus->built >= GV_BUILD_BASE) {
918  dig_restore_line(plus, line, type, points, offset);
919  G_debug(3, " line restored in topo with id = %d", line);
920  dig_line_box(points, &box);
921  dig_line_set_box(plus, line, &box);
922  Vect_box_extend(&(plus->box), &box);
923  }
924 
925  add_line_to_topo(Map,
926  line, points, cats);
927 
928  G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
929  plus->n_upnodes);
930 
931 
932  return ret;
933 }