GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-25961a86c2
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  dig_free_area(Area);
213  return -1;
214  }
215 
216  for (i = 0; i < n_lines; i++) {
217  line = lines[i];
218  Area->lines[i] = line;
219  Line = plus->Line[abs(line)];
220  topo = (struct P_topo_b *)Line->topo;
221  if (line < 0) { /* reverse direction -> area on left */
222  if (topo->left != 0) {
223  G_warning(_("Line %d already has area/isle %d to left"), line,
224  topo->left);
225  dig_free_area(Area);
226  return -1;
227  }
228 
229  G_debug(3, " Line %d left set to %d.", line, area);
230  topo->left = area;
231  }
232  else {
233  if (topo->right != 0) {
234  G_warning(_("Line %d already has area/isle %d to right"), line,
235  topo->right);
236  dig_free_area(Area);
237  return -1;
238  }
239 
240  G_debug(3, " Line %d right set to %d.", line, area);
241  topo->right = area;
242  }
243  }
244  Area->n_lines = n_lines;
245  Area->centroid = 0;
246 
247  plus->Area[area] = Area;
248 
249  dig_spidx_add_area(plus, area, box);
250 
251  plus->n_areas++;
252 
253  return (area);
254 }
255 
256 /*!
257  * \brief Add isle to area if does not exist yet.
258  *
259  * \param[in] plus pointer to Plus_head structure
260  * \param[in] area area id
261  * \param[in] isle isle id
262  *
263  * \return 0
264  */
265 int dig_area_add_isle(struct Plus_head *plus, int area, int isle)
266 {
267  int i;
268  struct P_area *Area;
269 
270  G_debug(3, "dig_area_add_isle(): area = %d isle = %d", area, isle);
271 
272  if (debug_level == -1) {
273  const char *dstr = G_getenv_nofatal("DEBUG");
274 
275  if (dstr != NULL)
276  debug_level = atoi(dstr);
277  else
278  debug_level = 0;
279  }
280 
281  Area = plus->Area[area];
282  if (Area == NULL)
283  G_fatal_error("Attempt to add isle to dead area");
284 
285  if (debug_level > 0) {
286  for (i = 0; i < Area->n_isles; i++) {
287  if (Area->isles[i] == isle) {
288  /* Already exists: bug in vector libs */
289  G_warning(_("Isle already registered in area"));
290  return 0;
291  }
292  }
293  }
294 
295  if (Area->alloc_isles <= Area->n_isles) /* array is full */
296  dig_area_alloc_isle(Area, 1);
297 
298  Area->isles[Area->n_isles] = isle;
299  Area->n_isles++;
300  G_debug(3, " -> n_isles = %d", Area->n_isles);
301 
302  return 0;
303 }
304 
305 /*!
306  * \brief Delete isle from area.
307  *
308  * \param[in] plus pointer to Plus_head structure
309  * \param[in] area area id
310  * \param[in] isle isle id
311  *
312  * \return 0
313  */
314 int dig_area_del_isle(struct Plus_head *plus, int area, int isle)
315 {
316  int i;
317  struct P_area *Area;
318 
319  G_debug(3, "dig_area_del_isle(): area = %d isle = %d", area, isle);
320 
321  Area = plus->Area[area];
322  if (Area == NULL)
323  G_fatal_error(_("Attempt to delete isle from dead area"));
324 
325  /* find index of the isle */
326  i = 0;
327  while (i < Area->n_isles && Area->isles[i] != isle)
328  i++;
329 
330  if (i == Area->n_isles) {
332  _("Attempt to delete not registered isle %d from area %d"), isle,
333  area);
334  }
335 
336  i++;
337  while (i < Area->n_isles) {
338  Area->isles[i - 1] = Area->isles[i];
339  i++;
340  }
341 
342  Area->n_isles--;
343 
344  return 0;
345 }
346 
347 /*!
348  * \brief Delete area from Plus_head structure
349  *
350  * This function deletes area from the topo structure and resets references
351  * to this area in boundaries, isles (within), and the centroid (if any) to 0.
352  * Possible new area is not created by this function, so that
353  * old boundaries participating in this area are left without area information
354  * even if form new area.
355  * Not enabled now: If area is inside other area, area info for islands within
356  * deleted area is reset to that area outside.
357  * (currently area info of isles is set to 0)
358  *
359  * \param[in] plus pointer to Plus_head structure
360  * \param[in] area area id
361  *
362  * \return 0 on error
363  * \return 1 on success
364  */
365 int dig_del_area(struct Plus_head *plus, int area)
366 {
367  int i, line;
368 
369  struct P_area *Area;
370  struct P_line *Line;
371  struct P_isle *Isle;
372  struct P_topo_b *btopo;
373  struct P_topo_c *ctopo;
374 
375  G_debug(3, "dig_del_area() area = %d", area);
376  Area = plus->Area[area];
377 
378  if (Area == NULL) {
379  G_warning(_("Attempt to delete dead area"));
380  return 0;
381  }
382 
383  dig_spidx_del_area(plus, area);
384 
385  /* Set area for all lines to 0 */
386  /* isle = 0; */
387  for (i = 0; i < Area->n_lines; i++) {
388  line = Area->lines[i]; /* >0 = clockwise -> right, <0 = counterclockwise
389  ->left */
390  Line = plus->Line[abs(line)];
391  btopo = (struct P_topo_b *)Line->topo;
392  if (line > 0) {
393  G_debug(3, " Set line %d right side to 0", line);
394  btopo->right = 0;
395  }
396  else {
397  G_debug(3, " Set line %d left side to 0", line);
398  btopo->left = 0;
399  }
400 
401  /* Find the isle this area is part of (used late below) */
402  /*
403  if ( line > 0 ) {
404  if ( Line->left < 0 ) isle = Line->left;
405  } else {
406  if ( Line->right < 0 ) isle = Line->right;
407  }
408  */
409  }
410 
411  /* Unset area information of centroid */
412  /* TODO: duplicate centroids have also area information ->
413  * 1) do not save such info
414  * 2) find all by box and reset info */
415  line = Area->centroid;
416  if (line > 0) {
417  Line = plus->Line[line];
418  if (!Line) {
419  G_warning(_("Dead centroid %d registered for area (bug in the "
420  "vector library)"),
421  line);
422  }
423  else {
424  ctopo = (struct P_topo_c *)Line->topo;
425  ctopo->area = 0;
426  }
427  }
428 
429  /* Find the area this area is within */
430  /*
431  area_out = 0;
432  if ( isle > 0 ) {
433  Isle = plus->Isle[abs(isle)];
434  area_out = Isle->area;
435  }
436  */
437 
438  /* Reset information about area outside for isles within this area */
439  G_debug(3, " n_isles = %d", Area->n_isles);
440  for (i = 0; i < Area->n_isles; i++) {
441  Isle = plus->Isle[Area->isles[i]];
442  if (Isle == NULL) {
443  G_fatal_error(_("Attempt to delete area %d info from dead isle %d"),
444  area, Area->isles[i]);
445  }
446  else {
447  /* Isle->area = area_out; */
448  Isle->area = 0;
449  }
450  }
451 
452  /* free structures */
453  dig_free_area(Area);
454  plus->Area[area] = NULL;
455  return 1;
456 }
457 
458 /*!
459  * \brief Find line number of next angle to follow a line
460  *
461  * Assume that lines are sorted in increasing angle order and angles
462  * of points and degenerated lines are set to -9 (ignored).
463  *
464  * \param[in] plus pointer to Plus_head structure
465  * \param[in] current_line current line id, negative if request for end node
466  * \param[in] side side GV_RIGHT or GV_LEFT
467  * \param[in] type line type (GV_LINE, GV_BOUNDARY or both)
468  * \param[out] angle
469  *
470  * \return line number of next angle to follow a line (negative if connected by
471  * end node) (number of current line may be returned if dangle - this is used in
472  * build) \return 0 on error or not found
473  */
474 int dig_angle_next_line(struct Plus_head *plus, plus_t current_line, int side,
475  int type, float *angle)
476 {
477  int next;
478  int line;
479  plus_t node;
480  struct P_node *Node;
481  struct P_line *Line;
482 
483  if (debug_level == -1) {
484  const char *dstr = G_getenv_nofatal("DEBUG");
485 
486  if (dstr != NULL)
487  debug_level = atoi(dstr);
488  else
489  debug_level = 0;
490  }
491 
492  G_debug(3, "dig__angle_next_line: line = %d, side = %d, type = %d",
493  current_line, side, type);
494 
495  Line = plus->Line[abs(current_line)];
496 
497  if (!(Line->type & GV_LINES)) {
498  if (angle)
499  *angle = -9.;
500  return 0;
501  }
502 
503  node = 0;
504  if (current_line > 0) {
505  if (Line->type == GV_LINE) {
506  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
507 
508  node = topo->N1;
509  }
510  else if (Line->type == GV_BOUNDARY) {
511  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
512 
513  node = topo->N1;
514  }
515  }
516  else {
517  if (Line->type == GV_LINE) {
518  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
519 
520  node = topo->N2;
521  }
522  else if (Line->type == GV_BOUNDARY) {
523  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
524 
525  node = topo->N2;
526  }
527  }
528 
529  G_debug(3, " node = %d", node);
530 
531  Node = plus->Node[node];
532  G_debug(3, " n_lines = %d", Node->n_lines);
533  /* avoid loop when not debugging */
534  if (debug_level > 2) {
535  int i;
536 
537  for (i = 0; i < Node->n_lines; i++) {
538  G_debug(3, " i = %d line = %d angle = %f", i, Node->lines[i],
539  Node->angles[i]);
540  }
541  }
542 
543  /* first find index for that line */
544  next = Node->n_lines - 1;
545  while (next >= 0 && Node->lines[next] != current_line) {
546  next--;
547  }
548 
549  if (next == -1) {
550  /* internal error, should not happen */
552  "dig_angle_next_line(): line %d not found at its own node %d",
553  current_line, node);
554  if (angle)
555  *angle = -9.;
556  return 0; /* not found */
557  }
558 
559  G_debug(3, " current position = %d", next);
560  while (1) {
561  if (side == GV_RIGHT) { /* go up (greater angle) */
562  if (next == Node->n_lines - 1)
563  next = 0;
564  else
565  next++;
566  }
567  else { /* go down (smaller angle) */
568  if (next == 0)
569  next = Node->n_lines - 1;
570  else
571  next--;
572  }
573  G_debug(3, " next = %d line = %d angle = %f", next, Node->lines[next],
574  Node->angles[next]);
575 
576  if (Node->angles[next] == -9.) { /* skip points and degenerated */
577  G_debug(3, " point/degenerated -> skip");
578  if (Node->lines[next] == current_line)
579  break; /* Yes, that may happen if input line is degenerated and
580  isolated and this breaks loop */
581  else
582  continue;
583  }
584 
585  line = Node->lines[next];
586  Line = plus->Line[abs(line)];
587 
588  if (Line->type & type) { /* line found */
589  G_debug(3, " this one");
590  if (angle)
591  *angle = Node->angles[next];
592  return line;
593  }
594 
595  /* input line reached, this must be last, because current_line may be
596  * correct return value (dangle) */
597  if (line == current_line)
598  break;
599  }
600  G_debug(3, " No next line for line %d at node %d", current_line,
601  (int)node);
602  if (angle)
603  *angle = -9.;
604 
605  return 0;
606 }
607 
608 /*!
609  * \brief Check if angles of adjacent lines differ.
610  *
611  * Negative line number for end point. Assume that lines are sorted
612  * in increasing angle order and angles of points and degenerated
613  * lines are set to 9 (ignored).
614  *
615  * \param[in] plus pointer to Plus_head structure
616  * \param[in] line current line id, negative if request for node 2
617  * \param[in] type line type (GV_LINE, GV_BOUNDARY or both)
618  *
619  * \return 1 angles differ
620  * \return 0 angle of a line up or down is identical
621  */
622 int dig_node_angle_check(struct Plus_head *plus, plus_t line, int type)
623 {
624  int next, prev;
625  float angle1, angle2;
626  plus_t node = 0;
627  struct P_line *Line;
628 
629  G_debug(3, "dig_node_angle_check: line = %d, type = %d", line, type);
630 
631  Line = plus->Line[abs(line)];
632  if (!(Line->type & GV_LINES))
633  return 0;
634 
635  if (line > 0) {
636  if (Line->type == GV_LINE) {
637  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
638 
639  node = topo->N1;
640  }
641  else if (Line->type == GV_BOUNDARY) {
642  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
643 
644  node = topo->N1;
645  }
646  }
647  else {
648  if (Line->type == GV_LINE) {
649  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
650 
651  node = topo->N2;
652  }
653  else if (Line->type == GV_BOUNDARY) {
654  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
655 
656  node = topo->N2;
657  }
658  }
659 
660  angle1 = dig_node_line_angle(plus, node, line);
661 
662  /* Next */
663  next = dig_angle_next_line(plus, line, GV_RIGHT, type, &angle2);
664  /* angle2 = dig_node_line_angle(plus, node, next); */
665  if (angle1 == angle2) {
666  G_debug(
667  3,
668  " The line to the right has the same angle: node = %d, line = %d",
669  node, next);
670  return 0;
671  }
672 
673  /* Previous */
674  prev = dig_angle_next_line(plus, line, GV_LEFT, type, &angle2);
675  /* angle2 = dig_node_line_angle(plus, node, prev); */
676  if (angle1 == angle2) {
677  G_debug(
678  3,
679  " The line to the left has the same angle: node = %d, line = %d",
680  node, prev);
681  return 0;
682  }
683 
684  return 1; /* OK */
685 }
686 
687 /*!
688  * \brief Allocate space for new island and create boundary info from array.
689  *
690  * The order of input lines is expected to be counter clockwise.
691  * Then for each line in isle, update line (right,left) info.
692  *
693  * Area number the island is within is not filled.
694  *
695  * \param[in] plus pointer to Plus_head structure
696  * \param[in] n_lines number of lines
697  * \param[in] lines array of lines, negative for reverse direction
698  * \param[in] box bounding box
699  *
700  * \return number of new isle
701  * \return -1 on error
702  */
703 int dig_add_isle(struct Plus_head *plus, int n_lines, plus_t *lines,
704  struct bound_box *box)
705 {
706  register int i;
707  register int isle, line;
708  struct P_isle *Isle;
709  struct P_line *Line;
710  struct P_topo_b *topo;
711 
712  G_debug(3, "dig_add_isle():");
713  /* First look if we have space in array of pointers to isles
714  * and reallocate if necessary */
715  if (plus->n_isles >= plus->alloc_isles) { /* array is full */
716  if (dig_alloc_isles(plus, 1000) == -1)
717  return -1;
718  }
719 
720  /* allocate isle structure */
721  isle = plus->n_isles + 1;
722  Isle = dig_alloc_isle();
723  if (Isle == NULL)
724  return -1;
725 
726  if ((dig_isle_alloc_line(Isle, n_lines)) == -1) {
727  dig_free_isle(Isle);
728  return -1;
729  }
730 
731  Isle->area = 0;
732 
733  for (i = 0; i < n_lines; i++) {
734  line = lines[i];
735  G_debug(3, " i = %d line = %d", i, line);
736  Isle->lines[i] = line;
737  Line = plus->Line[abs(line)];
738  topo = (struct P_topo_b *)Line->topo;
739  if (line < 0) { /* revers direction -> isle on left */
740  if (topo->left != 0) {
741  G_warning(_("Line %d already has area/isle %d to left"), line,
742  topo->left);
743  dig_free_isle(Isle);
744  return -1;
745  }
746  topo->left = -isle;
747  }
748  else {
749  if (topo->right != 0) {
750  G_warning(_("Line %d already has area/isle %d to right"), line,
751  topo->right);
752  dig_free_isle(Isle);
753  return -1;
754  }
755 
756  topo->right = -isle;
757  }
758  }
759 
760  Isle->n_lines = n_lines;
761 
762  plus->Isle[isle] = Isle;
763 
764  dig_spidx_add_isle(plus, isle, box);
765 
766  plus->n_isles++;
767 
768  return (isle);
769 }
770 
771 /*!
772  * \brief Delete island from Plus_head structure
773  *
774  * Reset references to it in lines and area outside.
775  *
776  * \param[in] plus pointer to Plus_head structure
777  * \param[in] isle isle id
778  *
779  * \return 1
780  */
781 int dig_del_isle(struct Plus_head *plus, int isle)
782 {
783  int i, line;
784  struct P_line *Line;
785  struct P_isle *Isle;
786  struct P_topo_b *topo;
787 
788  G_debug(3, "dig_del_isle() isle = %d", isle);
789  Isle = plus->Isle[isle];
790 
791  dig_spidx_del_isle(plus, isle);
792 
793  /* Set area for all lines to 0 */
794  for (i = 0; i < Isle->n_lines; i++) {
795  line = Isle->lines[i]; /* >0 = clockwise -> right, <0 = counterclockwise
796  ->left */
797  Line = plus->Line[abs(line)];
798  topo = (struct P_topo_b *)Line->topo;
799  if (line > 0)
800  topo->right = 0;
801  else
802  topo->left = 0;
803  }
804 
805  /* Delete reference from area it is within */
806  G_debug(3, " area outside isle = %d", Isle->area);
807  if (Isle->area > 0) {
808  if (plus->Area[Isle->area] == NULL) {
809  G_fatal_error(_("Attempt to delete isle %d info from dead area %d"),
810  isle, Isle->area);
811  }
812  else {
813  dig_area_del_isle(plus, Isle->area, isle);
814  }
815  }
816 
817  /* free structures */
818  dig_free_isle(Isle);
819  plus->Isle[isle] = NULL;
820 
821  return 1;
822 }
#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:395
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:515
int dig_spidx_add_area(struct Plus_head *, int, const struct bound_box *)
Add new area to spatial index.
Definition: spindex.c:360
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:568
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:474
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:265
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:622
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:703
int dig_area_del_isle(struct Plus_head *plus, int area, int isle)
Delete isle from area.
Definition: plus_area.c:314
int dig_del_area(struct Plus_head *plus, int area)
Delete area from Plus_head structure.
Definition: plus_area.c:365
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:781
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