1 
2 /**
3  * \file plus_area.c
4  *
5  * \brief Vector library - update topo for areas (lower level functions)
6  *
7  * Lower level functions for reading/writing/manipulating vectors.
8  *
9  * This program is free software under the GNU General Public License
10  * (>=v2). Read the file COPYING that comes with GRASS for details.
11  *
12  * \author CERL (probably Dave Gerdes), Radim Blazek
13  *
14  * \date 2001-2006
15  */
16 
17 #include <stdlib.h>
18 #include <grass/vector.h>
19 #include <grass/glocale.h>
20 
21 static int debug_level = -1;
22 
23 /*!
24  * \brief Build topo for area from lines
25  *
26  * Area is built in clockwise order.
27  * Take a given line and start off to the RIGHT/LEFT and try to complete
28  * an area.
29  *
30  * Possible Scenarios:
31  *  - I.    path runs into first line.                              : AREA!
32  *  - II.   path runs into a dead end (no other area lines at node) : no area
33  *  - III.  path runs into a previous line that is not 1st line or to 1st line but not to start node : no area
34  *
35  * After we find an area then we call point_in_area() to see if the
36  * specified point is w/in the area
37  *
38  * Old returns  -1:  error   0:  no area    (1:  point in area)
39  *              -2: island  !!
40  *
41  * \param[in] plus pointer to Plus_head structure
42  * \param[in] first_line line id of first line
43  * \param[in] side side of line to build area on (GV_LEFT | GV_RIGHT)
44  * \param[in] lines pointer to array of lines
45  *
46  * \return  -1 on error
47  * \return   0 no area
48  * \return   number of lines
49  */
50 int
dig_build_area_with_line(struct Plus_head * plus,plus_t first_line,int side,plus_t ** lines)51 dig_build_area_with_line(struct Plus_head *plus, plus_t first_line, int side,
52 			 plus_t ** lines)
53 {
54     register int i;
55     int prev_line, next_line;
56     static plus_t *array;
57     char *p;
58     static int array_size;	/* 0 on startup */
59     int n_lines;
60     struct P_line *Line;
61     struct P_topo_b *topo;
62     int node;
63 
64     if (debug_level == -1) {
65 	const char *dstr = G_getenv_nofatal("DEBUG");
66 
67 	if (dstr != NULL)
68 	    debug_level = atoi(dstr);
69 	else
70 	    debug_level = 0;
71     }
72 
73     G_debug(3, "dig_build_area_with_line(): first_line = %d, side = %d",
74 	    first_line, side);
75 
76     /* First check if line is not degenerated (degenerated lines have angle -9)
77      *  Following degenerated lines are skip by dig_angle_next_line() */
78     Line = plus->Line[first_line];
79     if (Line->type != GV_BOUNDARY)
80 	return -1;
81 
82     topo = (struct P_topo_b *)Line->topo;
83     node = topo->N1;		/* to check one is enough, because if degenerated N1 == N2 */
84     if (dig_node_line_angle(plus, node, first_line) == -9.) {
85 	G_debug(3, "First line degenerated");
86 	return (0);
87     }
88 
89     if (array_size == 0) {	/* first time */
90 	array_size = 1000;
91 	array = (plus_t *) dig__falloc(array_size, sizeof(plus_t));
92 	if (array == NULL)
93 	    return (dig_out_of_memory());
94     }
95 
96     if (side == GV_LEFT) {
97 	first_line = -first_line;	/* start at node1, reverse direction */
98     }
99     array[0] = first_line;
100     prev_line = -first_line;	/* start at node2 for direct and node1 for
101 				   reverse direction */
102     /* angle of first line */
103     n_lines = 1;
104     while (1) {
105 	next_line =
106 	    dig_angle_next_line(plus, prev_line, GV_RIGHT, GV_BOUNDARY, NULL);
107 	G_debug(3, "next_line = %d", next_line);
108 
109 	if (next_line == 0) {
110 	    G_debug(3, "Cannot build area, no next line for line %d",
111 	            prev_line);
112 	    return (-1);	/* Not found */
113 	}
114 
115 	/* Check if adjacent lines do not have the same angle */
116 	if (!dig_node_angle_check(plus, next_line, GV_BOUNDARY)) {
117 	    G_debug(3,
118 		    "Cannot build area, a neighbour of the line %d has the same angle at the node",
119 		    next_line);
120 	    return 0;
121 	}
122 
123 	/*  I. Area closed. This also handles the problem w/ 1 single area line */
124 	if (first_line == next_line) {
125 	    /* GOT ONE!  fill area struct  and return */
126 	    G_debug(3, "Got one! :");
127 
128 	    /* avoid loop when not debugging */
129 	    if (debug_level > 2) {
130 		for (i = 0; i < n_lines; i++) {
131 		    G_debug(3, " area line (%d) = %d", i, array[i]);
132 		}
133 	    }
134 
135 	    *lines = array;
136 	    return (n_lines);
137 	}
138 
139 	/* II. Note this is a dead end */
140 	/* ( if prev_line != -first_line so it goes after the previous test) ? */
141 	if (prev_line == next_line) {
142 	    G_debug(3, "Dead_end:");
143 	    return (0);		/* dead end */
144 	}
145 
146 	/* III. Unclosed ?, I would say started from free end */
147 	for (i = 0; i < n_lines; i++)
148 	    if (abs(next_line) == abs(array[i])) {
149 		G_debug(3, "Unclosed area:");
150 		return (0);	/* ran into a different area */
151 	    }
152 
153 	/* otherwise keep going */
154 	if (n_lines >= array_size) {
155 	    p = dig__frealloc(array, array_size + 100, sizeof(plus_t),
156 			      array_size);
157 	    if (p == NULL)
158 		return (dig_out_of_memory());
159 	    array = (plus_t *) p;
160 	    array_size += 100;
161 	}
162 	array[n_lines++] = next_line;
163 	prev_line = -next_line;
164     }
165 
166     return 0;
167 }
168 
169 /*!
170  * \brief Allocate space for new area and create boundary info from array.
171  *
172  * Then for each line in area, update line (right,left) info.
173  *
174  * Neither islands nor centroids are filled.
175  *
176  * \param[in] plus pointer to Plus_head structure
177  * \param[in] n_lines number of lines
178  * \param[in] lines array of lines, negative for reverse direction
179  * \param[in] box bounding box
180  *
181  * \return number of new area
182  * \return -1 on error
183  */
dig_add_area(struct Plus_head * plus,int n_lines,plus_t * lines,struct bound_box * box)184 int dig_add_area(struct Plus_head *plus, int n_lines, plus_t * lines,
185 		 struct bound_box *box)
186 {
187     register int i;
188     register int area, line;
189     struct P_area *Area;
190     struct P_line *Line;
191     struct P_topo_b *topo;
192 
193     G_debug(3, "dig_add_area():");
194     /* First look if we have space in array of pointers to areas
195      *  and reallocate if necessary */
196     if (plus->n_areas >= plus->alloc_areas) {	/* array is full */
197 	if (dig_alloc_areas(plus, 1000) == -1)
198 	    return -1;
199     }
200 
201     /* allocate area structure */
202     area = plus->n_areas + 1;
203     G_debug(3, "    new area = %d", area);
204     Area = dig_alloc_area();
205     if (Area == NULL)
206 	return -1;
207 
208     if (dig_area_alloc_line(Area, n_lines) == -1)
209 	return -1;
210 
211     for (i = 0; i < n_lines; i++) {
212 	line = lines[i];
213 	Area->lines[i] = line;
214 	Line = plus->Line[abs(line)];
215 	topo = (struct P_topo_b *)Line->topo;
216 	if (line < 0) {		/* reverse direction -> area on left */
217 	    if (topo->left != 0) {
218 		G_warning(_("Line %d already has area/isle %d to left"), line,
219 			  topo->left);
220 		return -1;
221 	    }
222 
223 	    G_debug(3, "  Line %d left set to %d.", line, area);
224 	    topo->left = area;
225 	}
226 	else {
227 	    if (topo->right != 0) {
228 		G_warning(_("Line %d already has area/isle %d to right"),
229 			  line, topo->right);
230 		return -1;
231 	    }
232 
233 	    G_debug(3, "  Line %d right set to %d.", line, area);
234 	    topo->right = area;
235 	}
236     }
237     Area->n_lines = n_lines;
238     Area->centroid = 0;
239 
240     plus->Area[area] = Area;
241 
242     dig_spidx_add_area(plus, area, box);
243 
244     plus->n_areas++;
245 
246     return (area);
247 }
248 
249 /*!
250  * \brief Add isle to area if does not exist yet.
251  *
252  * \param[in] plus pointer to Plus_head structure
253  * \param[in] area area id
254  * \param[in] isle isle id
255  *
256  * \return 0
257  */
dig_area_add_isle(struct Plus_head * plus,int area,int isle)258 int dig_area_add_isle(struct Plus_head *plus, int area, int isle)
259 {
260     int i;
261     struct P_area *Area;
262 
263     G_debug(3, "dig_area_add_isle(): area = %d isle = %d", area, isle);
264 
265     if (debug_level == -1) {
266 	const char *dstr = G_getenv_nofatal("DEBUG");
267 
268 	if (dstr != NULL)
269 	    debug_level = atoi(dstr);
270 	else
271 	    debug_level = 0;
272     }
273 
274     Area = plus->Area[area];
275     if (Area == NULL)
276 	G_fatal_error("Attempt to add isle to dead area");
277 
278     if (debug_level > 0) {
279 	for (i = 0; i < Area->n_isles; i++) {
280 	    if (Area->isles[i] == isle) {
281 		/* Already exists: bug in vector libs */
282 		G_warning(_("Isle already registered in area"));
283 		return 0;
284 	    }
285 	}
286     }
287 
288     if (Area->alloc_isles <= Area->n_isles)	/* array is full */
289 	dig_area_alloc_isle(Area, 1);
290 
291     Area->isles[Area->n_isles] = isle;
292     Area->n_isles++;
293     G_debug(3, "  -> n_isles = %d", Area->n_isles);
294 
295     return 0;
296 }
297 
298 /*!
299  * \brief Delete isle from area.
300  *
301  * \param[in] plus pointer to Plus_head structure
302  * \param[in] area area id
303  * \param[in] isle isle id
304  *
305  * \return 0
306  */
dig_area_del_isle(struct Plus_head * plus,int area,int isle)307 int dig_area_del_isle(struct Plus_head *plus, int area, int isle)
308 {
309     int i;
310     struct P_area *Area;
311 
312     G_debug(3, "dig_area_del_isle(): area = %d isle = %d", area, isle);
313 
314     Area = plus->Area[area];
315     if (Area == NULL)
316 	G_fatal_error(_("Attempt to delete isle from dead area"));
317 
318     /* find index of the isle */
319     i = 0;
320     while (i < Area->n_isles && Area->isles[i] != isle)
321 	i++;
322 
323     if (i == Area->n_isles) {
324 	G_fatal_error(_("Attempt to delete not registered isle %d from area %d"),
325 		      isle, area);
326     }
327 
328     i++;
329     while (i < Area->n_isles) {
330 	Area->isles[i - 1] = Area->isles[i];
331 	i++;
332     }
333 
334     Area->n_isles--;
335 
336     return 0;
337 }
338 
339 /*!
340  * \brief Delete area from Plus_head structure
341  *
342  *  This function deletes area from the topo structure and resets references
343  *  to this area in boundaries, isles (within), and the centroid (if any) to 0.
344  *  Possible new area is not created by this function, so that
345  *  old boundaries participating in this area are left without area information
346  *  even if form new area.
347  *  Not enabled now: If area is inside other area, area info for islands within
348  *                   deleted area is reset to that area outside.
349  *  (currently area info of isles is set to 0)
350  *
351  * \param[in] plus pointer to Plus_head structure
352  * \param[in] area area id
353  *
354  * \return 0 on error
355  * \return 1 on success
356  */
dig_del_area(struct Plus_head * plus,int area)357 int dig_del_area(struct Plus_head *plus, int area)
358 {
359     int i, line;
360 
361     struct P_area *Area;
362     struct P_line *Line;
363     struct P_isle *Isle;
364     struct P_topo_b *btopo;
365     struct P_topo_c *ctopo;
366 
367     G_debug(3, "dig_del_area() area =  %d", area);
368     Area = plus->Area[area];
369 
370     if (Area == NULL) {
371 	G_warning(_("Attempt to delete dead area"));
372 	return 0;
373     }
374 
375     dig_spidx_del_area(plus, area);
376 
377     /* Set area for all lines to 0 */
378     /* isle = 0; */
379     for (i = 0; i < Area->n_lines; i++) {
380 	line = Area->lines[i];	/* >0 = clockwise -> right, <0 = counterclockwise ->left */
381 	Line = plus->Line[abs(line)];
382 	btopo = (struct P_topo_b *)Line->topo;
383 	if (line > 0) {
384 	    G_debug(3, "  Set line %d right side to 0", line);
385 	    btopo->right = 0;
386 	}
387 	else {
388 	    G_debug(3, "  Set line %d left side to 0", line);
389 	    btopo->left = 0;
390 	}
391 
392 	/* Find the isle this area is part of (used late below) */
393 	/*
394 	   if ( line > 0 ) {
395 	   if ( Line->left < 0 ) isle = Line->left;
396 	   } else {
397 	   if ( Line->right < 0 ) isle = Line->right;
398 	   }
399 	 */
400     }
401 
402     /* Unset area information of centroid */
403     /* TODO: duplicate centroids have also area information ->
404      *        1) do not save such info
405      *        2) find all by box and reset info */
406     line = Area->centroid;
407     if (line > 0) {
408 	Line = plus->Line[line];
409 	if (!Line) {
410 	    G_warning(_("Dead centroid %d registered for area (bug in the vector library)"),
411 		      line);
412 	}
413 	else {
414 	    ctopo = (struct P_topo_c *)Line->topo;
415 	    ctopo->area = 0;
416 	}
417     }
418 
419     /* Find the area this area is within */
420     /*
421        area_out = 0;
422        if ( isle > 0 ) {
423        Isle =  plus->Isle[abs(isle)];
424        area_out = Isle->area;
425        }
426      */
427 
428     /* Reset information about area outside for isles within this area */
429     G_debug(3, "  n_isles = %d", Area->n_isles);
430     for (i = 0; i < Area->n_isles; i++) {
431 	Isle = plus->Isle[Area->isles[i]];
432 	if (Isle == NULL) {
433 	    G_fatal_error(_("Attempt to delete area %d info from dead isle %d"),
434 			  area, Area->isles[i]);
435 	}
436 	else {
437 	    /* Isle->area = area_out; */
438 	    Isle->area = 0;
439 	}
440     }
441 
442     /* free structures */
443     dig_free_area(Area);
444     plus->Area[area] = NULL;
445     return 1;
446 }
447 
448 
449 /*!
450  * \brief Find line number of next angle to follow a line
451  *
452  * Assume that lines are sorted in increasing angle order and angles
453  * of points and degenerated lines are set to -9 (ignored).
454  *
455  * \param[in] plus pointer to Plus_head structure
456  * \param[in] current_line current line id, negative if request for end node
457  * \param[in] side side GV_RIGHT or GV_LEFT
458  * \param[in] type line type (GV_LINE, GV_BOUNDARY or both)
459  * \param[in] angle
460  *
461  * \return line number of next angle to follow a line (negative if connected by end node)
462  *               (number of current line may be returned if dangle - this is used in build)
463  * \return 0 on error or not found
464  */
465 int
dig_angle_next_line(struct Plus_head * plus,plus_t current_line,int side,int type,float * angle)466 dig_angle_next_line(struct Plus_head *plus, plus_t current_line, int side,
467 		    int type, float *angle)
468 {
469     int next;
470     int line;
471     plus_t node;
472     struct P_node *Node;
473     struct P_line *Line;
474 
475     if (debug_level == -1) {
476 	const char *dstr = G_getenv_nofatal("DEBUG");
477 
478 	if (dstr != NULL)
479 	    debug_level = atoi(dstr);
480 	else
481 	    debug_level = 0;
482     }
483 
484     G_debug(3, "dig__angle_next_line: line = %d, side = %d, type = %d",
485 	    current_line, side, type);
486 
487     Line = plus->Line[abs(current_line)];
488 
489     if (!(Line->type & GV_LINES)) {
490 	if (angle)
491 	    *angle = -9.;
492 	return 0;
493     }
494 
495     node = 0;
496     if (current_line > 0) {
497 	if (Line->type == GV_LINE) {
498 	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
499 	    node = topo->N1;
500 	}
501 	else if (Line->type == GV_BOUNDARY) {
502 	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
503 	    node = topo->N1;
504 	}
505     }
506     else {
507 	if (Line->type == GV_LINE) {
508 	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
509 	    node = topo->N2;
510 	}
511 	else if (Line->type == GV_BOUNDARY) {
512 	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
513 	    node = topo->N2;
514 	}
515     }
516 
517     G_debug(3, " node = %d", node);
518 
519     Node = plus->Node[node];
520     G_debug(3, "  n_lines = %d", Node->n_lines);
521     /* avoid loop when not debugging */
522     if (debug_level > 2) {
523 	int i;
524 
525 	for (i = 0; i < Node->n_lines; i++) {
526 	    G_debug(3, "  i = %d line = %d angle = %f", i, Node->lines[i],
527 		    Node->angles[i]);
528 	}
529     }
530 
531     /* first find index for that line */
532     next = Node->n_lines - 1;
533     while (next >= 0 && Node->lines[next] != current_line) {
534 	next--;
535     }
536 
537     if (next == -1) {
538 	/* internal error, should not happen */
539 	G_fatal_error("dig_angle_next_line(): line %d not found at its own node %d",
540 	              current_line, node);
541 	if (angle)
542 	    *angle = -9.;
543 	return 0;		/* not found */
544     }
545 
546     G_debug(3, "  current position = %d", next);
547     while (1) {
548 	if (side == GV_RIGHT) {	/* go up (greater angle) */
549 	    if (next == Node->n_lines - 1)
550 		next = 0;
551 	    else
552 		next++;
553 	}
554 	else {			/* go down (smaller angle) */
555 	    if (next == 0)
556 		next = Node->n_lines - 1;
557 	    else
558 		next--;
559 	}
560 	G_debug(3, "  next = %d line = %d angle = %f", next,
561 		Node->lines[next], Node->angles[next]);
562 
563 	if (Node->angles[next] == -9.) {	/* skip points and degenerated */
564 	    G_debug(3, "  point/degenerated -> skip");
565 	    if (Node->lines[next] == current_line)
566 		break;		/* Yes, that may happen if input line is degenerated and isolated and this breaks loop */
567 	    else
568 		continue;
569 	}
570 
571 	line = Node->lines[next];
572 	Line = plus->Line[abs(line)];
573 
574 	if (Line->type & type) {	/* line found */
575 	    G_debug(3, "  this one");
576 	    if (angle)
577 		*angle = Node->angles[next];
578 	    return line;
579 	}
580 
581 	/* input line reached, this must be last, because current_line may be correct return value (dangle) */
582 	if (line == current_line)
583 	    break;
584     }
585     G_debug(3, "  No next line for line %d at node %d",
586             current_line, (int)node);
587     if (angle)
588 	*angle = -9.;
589 
590     return 0;
591 }
592 
593 /*!
594  * \brief Check if angles of adjacent lines differ.
595  *
596  * Negative line number for end point. Assume that lines are sorted
597  * in increasing angle order and angles of points and degenerated
598  * lines are set to 9 (ignored).
599  *
600  * \param[in] plus pointer to Plus_head structure
601  * \param[in] line current line id, negative if request for node 2
602  * \param[in] type line type (GV_LINE, GV_BOUNDARY or both)
603  *
604  * \return 1 angles differ
605  * \return 0 angle of a line up or down is identical
606  */
dig_node_angle_check(struct Plus_head * plus,plus_t line,int type)607 int dig_node_angle_check(struct Plus_head *plus, plus_t line, int type)
608 {
609     int next, prev;
610     float angle1, angle2;
611     plus_t node = 0;
612     struct P_line *Line;
613 
614     G_debug(3, "dig_node_angle_check: line = %d, type = %d", line, type);
615 
616     Line = plus->Line[abs(line)];
617     if (!(Line->type & GV_LINES))
618 	return 0;
619 
620     if (line > 0) {
621 	if (Line->type == GV_LINE) {
622 	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
623 	    node = topo->N1;
624 	}
625 	else if (Line->type == GV_BOUNDARY) {
626 	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
627 	    node = topo->N1;
628 	}
629     }
630     else {
631 	if (Line->type == GV_LINE) {
632 	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
633 	    node = topo->N2;
634 	}
635 	else if (Line->type == GV_BOUNDARY) {
636 	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
637 	    node = topo->N2;
638 	}
639     }
640 
641     angle1 = dig_node_line_angle(plus, node, line);
642 
643     /* Next */
644     next = dig_angle_next_line(plus, line, GV_RIGHT, type, &angle2);
645     /* angle2 = dig_node_line_angle(plus, node, next); */
646     if (angle1 == angle2) {
647 	G_debug(3,
648 		"  The line to the right has the same angle: node = %d, line = %d",
649 		node, next);
650 	return 0;
651     }
652 
653     /* Previous */
654     prev = dig_angle_next_line(plus, line, GV_LEFT, type, &angle2);
655     /* angle2 = dig_node_line_angle(plus, node, prev); */
656     if (angle1 == angle2) {
657 	G_debug(3,
658 		"  The line to the left has the same angle: node = %d, line = %d",
659 		node, next);
660 	return 0;
661     }
662 
663     return 1;			/* OK */
664 }
665 
666 /*!
667  * \brief Allocate space for new island and create boundary info from array.
668  *
669  * The order of input lines is expected to be counter clockwise.
670  * Then for each line in isle, update line (right,left) info.
671  *
672  * Area number the island is within is not filled.
673  *
674  * \param[in] plus pointer to Plus_head structure
675  * \param[in] n_lines number of lines
676  * \param[in] lines array of lines, negative for reverse direction
677  * \param[in] box bounding box
678  *
679  * \return number of new isle
680  * \return -1 on error
681  */
dig_add_isle(struct Plus_head * plus,int n_lines,plus_t * lines,struct bound_box * box)682 int dig_add_isle(struct Plus_head *plus, int n_lines, plus_t * lines,
683 		 struct bound_box *box)
684 {
685     register int i;
686     register int isle, line;
687     struct P_isle *Isle;
688     struct P_line *Line;
689     struct P_topo_b *topo;
690 
691     G_debug(3, "dig_add_isle():");
692     /* First look if we have space in array of pointers to isles
693      *  and reallocate if necessary */
694     if (plus->n_isles >= plus->alloc_isles) {	/* array is full */
695 	if (dig_alloc_isles(plus, 1000) == -1)
696 	    return -1;
697     }
698 
699     /* allocate isle structure */
700     isle = plus->n_isles + 1;
701     Isle = dig_alloc_isle();
702     if (Isle == NULL)
703 	return -1;
704 
705     if ((dig_isle_alloc_line(Isle, n_lines)) == -1)
706 	return -1;
707 
708     Isle->area = 0;
709 
710     for (i = 0; i < n_lines; i++) {
711 	line = lines[i];
712 	G_debug(3, " i = %d line = %d", i, line);
713 	Isle->lines[i] = line;
714 	Line = plus->Line[abs(line)];
715 	topo = (struct P_topo_b *)Line->topo;
716 	if (line < 0) {		/* revers direction -> isle on left */
717 	    if (topo->left != 0) {
718 		G_warning(_("Line %d already has area/isle %d to left"), line,
719 			  topo->left);
720 		return -1;
721 	    }
722 	    topo->left = -isle;
723 	}
724 	else {
725 	    if (topo->right != 0) {
726 		G_warning(_("Line %d already has area/isle %d to right"), line,
727 			  topo->right);
728 		return -1;
729 	    }
730 
731 	    topo->right = -isle;
732 	}
733     }
734 
735     Isle->n_lines = n_lines;
736 
737     plus->Isle[isle] = Isle;
738 
739     dig_spidx_add_isle(plus, isle, box);
740 
741     plus->n_isles++;
742 
743     return (isle);
744 }
745 
746 
747 /*!
748  * \brief Delete island from Plus_head structure
749  *
750  * Reset references to it in lines and area outside.
751  *
752  * \param[in] plus pointer to Plus_head structure
753  * \param[in] isle isle id
754  *
755  * \return 1
756  */
dig_del_isle(struct Plus_head * plus,int isle)757 int dig_del_isle(struct Plus_head *plus, int isle)
758 {
759     int i, line;
760     struct P_line *Line;
761     struct P_isle *Isle;
762     struct P_topo_b *topo;
763 
764     G_debug(3, "dig_del_isle() isle =  %d", isle);
765     Isle = plus->Isle[isle];
766 
767     dig_spidx_del_isle(plus, isle);
768 
769     /* Set area for all lines to 0 */
770     for (i = 0; i < Isle->n_lines; i++) {
771 	line = Isle->lines[i];	/* >0 = clockwise -> right, <0 = counterclockwise ->left */
772 	Line = plus->Line[abs(line)];
773 	topo = (struct P_topo_b *)Line->topo;
774 	if (line > 0)
775 	    topo->right = 0;
776 	else
777 	    topo->left = 0;
778     }
779 
780     /* Delete reference from area it is within */
781     G_debug(3, "  area outside isle = %d", Isle->area);
782     if (Isle->area > 0) {
783 	if (plus->Area[Isle->area] == NULL) {
784 	    G_fatal_error(_("Attempt to delete isle %d info from dead area %d"),
785 			  isle, Isle->area);
786 	}
787 	else {
788 	    dig_area_del_isle(plus, Isle->area, isle);
789 	}
790     }
791 
792     /* free structures */
793     dig_free_isle(Isle);
794     plus->Isle[isle] = NULL;
795 
796     return 1;
797 }
798