GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
plus_area.c
Go to the documentation of this file.
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
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  */
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  */
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  */
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  */
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
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  */
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  */
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  */
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 }
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:951
Bounding box.
Definition: dig_structs.h:65
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int plus_t
plus_t size
Definition: dig_structs.h:41
if(!(yy_init))
Definition: sqlp.yy.c:775
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1537
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:174
int dig_del_isle(struct Plus_head *plus, int isle)
Delete island from Plus_head structure.
Definition: plus_area.c:757
int dig_spidx_del_isle(struct Plus_head *, int)
Delete isle from spatial index.
Definition: spindex.c:561
struct P_isle * dig_alloc_isle()
Allocate new isle structure.
Definition: struct_alloc.c:301
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
struct P_area * dig_alloc_area()
Allocate new area structure.
Definition: struct_alloc.c:266
Isle (topology) info.
Definition: dig_structs.h:1646
plus_t right
Area number to the right, negative for isle.
Definition: dig_structs.h:1526
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:891
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:883
int dig_del_area(struct Plus_head *plus, int area)
Delete area from Plus_head structure.
Definition: plus_area.c:357
plus_t n_lines
Number of attached lines (size of lines, angle)
Definition: dig_structs.h:1472
plus_t left
Area number to the left, negative for isle.
Definition: dig_structs.h:1522
int dig_out_of_memory(void)
For now just print message and return error code.
Definition: struct_alloc.c:492
struct P_isle ** Isle
Array of isles.
Definition: dig_structs.h:895
plus_t * lines
List of connected lines.
Definition: dig_structs.h:1479
plus_t * isles
1st generation interior islands
Definition: dig_structs.h:1640
plus_t n_isles
Current number of isles.
Definition: dig_structs.h:955
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1628
#define NULL
Definition: ccmath.h:32
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1651
plus_t N1
Start node.
Definition: dig_structs.h:1514
plus_t N2
End node.
Definition: dig_structs.h:1503
plus_t alloc_areas
Number of allocated areas.
Definition: dig_structs.h:992
#define GV_LINE
Definition: dig_defines.h:183
plus_t N1
Start node.
Definition: dig_structs.h:1499
int dig_spidx_add_area(struct Plus_head *, int, const struct bound_box *)
Add new area to spatial index.
Definition: spindex.c:353
char type
Line type.
Definition: dig_structs.h:1586
int dig_area_add_isle(struct Plus_head *plus, int area, int isle)
Add isle to area if does not exist yet.
Definition: plus_area.c:258
int dig_build_area_with_line(struct Plus_head *plus, plus_t first_line, int side, plus_t **lines)
Build topo for area from lines.
Definition: plus_area.c:51
Centroid topology.
Definition: dig_structs.h:1532
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1621
float dig_node_line_angle(struct Plus_head *, int, int)
Return line angle.
Definition: plus_node.c:198
Basic topology-related info.
Definition: dig_structs.h:784
int dig_alloc_areas(struct Plus_head *, int)
Reallocate array of pointers to areas.
Definition: struct_alloc.c:218
void * dig__falloc(int, int)
Definition: allocation.c:118
Line topology.
Definition: dig_structs.h:1494
void * topo
Topology info.
Definition: dig_structs.h:1599
void * dig__frealloc(void *, int, int, int)
Definition: allocation.c:133
float * angles
List of angles of connected lines.
Definition: dig_structs.h:1488
Boundary topology.
Definition: dig_structs.h:1509
int dig_add_isle(struct Plus_head *plus, int n_lines, plus_t *lines, struct bound_box *box)
Allocate space for new island and create boundary info from array.
Definition: plus_area.c:682
void dig_free_area(struct P_area *)
Free area structure.
Definition: struct_alloc.c:284
#define GV_BOUNDARY
Definition: dig_defines.h:184
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1662
int dig_angle_next_line(struct Plus_head *plus, plus_t current_line, int side, int type, float *angle)
Find line number of next angle to follow a line.
Definition: plus_area.c:466
Topological feature - node.
Definition: dig_structs.h:1448
int dig_spidx_add_isle(struct Plus_head *, int, const struct bound_box *)
Add new island to spatial index.
Definition: spindex.c:388
plus_t n_isles
Number of islands inside.
Definition: dig_structs.h:1632
plus_t alloc_isles
Allocated space for isles.
Definition: dig_structs.h:1636
int dig_area_alloc_isle(struct P_area *, int)
Allocate space in P_area for add new isles.
Definition: struct_alloc.c:445
Area (topology) info.
Definition: dig_structs.h:1605
int dig_area_alloc_line(struct P_area *, int)
allocate space in P_area for add new lines
Definition: struct_alloc.c:419
void G_warning(const char *,...) __attribute__((format(printf
int dig_node_angle_check(struct Plus_head *plus, plus_t line, int type)
Check if angles of adjacent lines differ.
Definition: plus_area.c:607
int dig_spidx_del_area(struct Plus_head *, int)
Delete area from spatial index.
Definition: spindex.c:508
#define GV_RIGHT
Definition: dig_defines.h:175
void dig_free_isle(struct P_isle *)
Free isle structure.
Definition: struct_alloc.c:319
#define _(str)
Definition: glocale.h:10
const char * G_getenv_nofatal(const char *)
Get environment variable.
Definition: env.c:383
int dig_alloc_isles(struct Plus_head *, int)
Reallocate array of pointers to isles.
Definition: struct_alloc.c:243
int dig_isle_alloc_line(struct P_isle *, int)
Allocate space in P_isle for add new lines.
Definition: struct_alloc.c:471
#define GV_LINES
Definition: dig_defines.h:192
plus_t N2
End node.
Definition: dig_structs.h:1518
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1610
plus_t area
Area it exists w/in, if any.
Definition: dig_structs.h:1669
int dig_add_area(struct Plus_head *plus, int n_lines, plus_t *lines, struct bound_box *box)
Allocate space for new area and create boundary info from array.
Definition: plus_area.c:184
int G_debug(int, const char *,...) __attribute__((format(printf
plus_t alloc_isles
Number of allocated isles.
Definition: dig_structs.h:998
int dig_area_del_isle(struct Plus_head *plus, int area, int isle)
Delete isle from area.
Definition: plus_area.c:307