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