GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
plus_node.c
Go to the documentation of this file.
1 
2 /**
3  * \file plus_node.c
4  *
5  * \brief Vector library - update topo for nodes (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 <math.h>
19 #include <grass/vector.h>
20 #include <grass/glocale.h>
21 
22 static double dist_squared(double, double, double, double);
23 
24 /*!
25  * \brief Add line info to node
26  *
27  * Line will be negative if END node
28  *
29  * 'node' must of course already exist space will be alloced to add 'line' to array
30  *
31  * Lines are sorted in increasing angle order and
32  * degenerated lines are set to -9 (ignored).
33  *
34  * \param[in] plus pointer to Plus_head structure
35  * \param[in] nodeid node id
36  * \param[in] lineid line id
37  * \param[in] points line geometry
38  * \param[in] type line type
39  *
40  * \return -1 on error
41  * \return 0 line not added (degenerate)
42  * \return new number of lines in node
43  */
44 int
45 dig_node_add_line(struct Plus_head *plus, int nodeid, int lineid,
46  const struct line_pnts *points, int type)
47 {
48  register int i;
49  float angle;
50  int ret;
51  struct P_node *node;
52 
53  G_debug(3, "dig_node_add_line(): node = %d line = %d", nodeid, lineid);
54 
55  node = plus->Node[nodeid];
56 
57  /* reallocate memory */
58  ret = dig_node_alloc_line(node, 1);
59  if (ret == -1)
60  return -1;
61 
62  angle = -9.;
63  if (type & GV_LINES) {
64  if (lineid < 0)
65  angle = dig_calc_end_angle(points, 0);
66  else
67  angle = dig_calc_begin_angle(points, 0);
68  }
69  G_debug(3, " angle = %f", angle);
70 
71  i = node->n_lines;
72  while (i > 0) {
73  if (angle >= node->angles[i - 1])
74  break;
75  node->angles[i] = node->angles[i - 1];
76  node->lines[i] = node->lines[i - 1];
77 
78  i--;
79  }
80  node->angles[i] = angle;
81  node->lines[i] = lineid;
82 
83  node->n_lines++;
84 
85  G_debug(3,
86  "dig_node_add_line(): line %d added position %d n_lines: %d angle %f",
87  lineid, i, node->n_lines, angle);
88 
89  return ((int)node->n_lines);
90 }
91 
92 
93 /*!
94  * \brief Add new node to plus structure
95  *
96  * \param[in] plus pointer to Plus_head structure
97  * \param[in] x,y,z coordinates
98  *
99  * \return -1 on error
100  * \return number of node
101  */
102 int dig_add_node(struct Plus_head *plus, double x, double y, double z)
103 {
104  int nnum;
105  struct P_node *node;
106 
107  /* First look if we have space in array of pointers to nodes
108  * and reallocate if necessary */
109  G_debug(3, "dig_add_node(): n_nodes = %d, alloc_nodes = %d",
110  plus->n_nodes, plus->alloc_nodes);
111  if (plus->n_nodes >= plus->alloc_nodes) { /* array is full */
112  if (dig_alloc_nodes(plus, 1000) == -1)
113  return -1;
114  }
115 
116  /* allocate node structure */
117  nnum = plus->n_nodes + 1;
118 
119  plus->Node[nnum] = dig_alloc_node();
120 
121  node = plus->Node[nnum];
122  node->x = x;
123  node->y = y;
124  node->z = z;
125 
126  dig_spidx_add_node(plus, nnum, x, y, z);
127 
128  plus->n_nodes++;
129 
130  G_debug(3, "new node = %d, n_nodes = %d, alloc_nodes = %d", nnum,
131  plus->n_nodes, plus->alloc_nodes);
132 
133  return (nnum);
134 }
135 
136 /*!
137  * \brief Return actual index into node arrays of the first set of matching coordinates
138  *
139  * \param[in] plus pointer to Plus_head structure
140  * \param[in] x,y coordinates
141  * \param[in] thresh threshold value
142  *
143  * \return node index
144  * \return -1 if no node found
145  */
146 int dig_which_node(struct Plus_head *plus, double x, double y, double thresh)
147 {
148  register int i;
149  register int first_time;
150  register int have_match;
151  int winner;
152  double least_dist, dist;
153  struct P_node *node;
154 
155  first_time = 1;
156  have_match = 0;
157  winner = 0;
158  least_dist = 0.0;
159  for (i = 1; i <= plus->n_nodes; i++) {
160  if (plus->Node[i] == NULL)
161  continue;
162 
163  node = plus->Node[i];
164  if ((fabs(node->x - x) <= thresh) && (fabs(node->y - y) <= thresh)) {
165  dist = dist_squared(x, y, node->x, node->y);
166  if (first_time) {
167  least_dist = dist;
168  first_time = 0;
169  winner = i;
170  have_match = 1;
171  }
172  if (dist < least_dist) {
173  least_dist = dist;
174  winner = i;
175  }
176  }
177  }
178 
179  if (!have_match)
180  return (-1);
181 
182  return (winner);
183 } /* which_node () */
184 
185 /*!
186  * \brief Return line angle
187  *
188  * Lines is specified by line id in topology, NOT by order number.
189  * Negative id if looking for line end point.
190  *
191  * \param[in] plus pointer to Plus_head structure
192  * \param[in] nodeid node id
193  * \param[in] lineid line id
194  *
195  * \return line angle <-PI,PI>
196  * \return 0 not reached
197  */
198 float dig_node_line_angle(struct Plus_head *plus, int nodeid, int lineid)
199 {
200  int i, nlines;
201  struct P_node *node;
202 
203  G_debug(3, "dig_node_line_angle: node = %d line = %d", nodeid, lineid);
204 
205  node = plus->Node[nodeid];
206  nlines = node->n_lines;
207 
208  for (i = 0; i < nlines; i++) {
209  if (node->lines[i] == lineid)
210  return (node->angles[i]);
211  }
212 
213  G_fatal_error(_("Attempt to read line angle for the line which is not connected to the node: "
214  "node %d, line %d"), nodeid, lineid);
215 
216  return 0.0; /* not reached */
217 }
218 
219 static double dist_squared(double x1, double y1, double x2, double y2)
220 {
221  double dx, dy;
222 
223  dx = x1 - x2;
224  dy = y1 - y2;
225  return (dx * dx + dy * dy);
226 }
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
plus_t alloc_nodes
Number of allocated nodes.
Definition: dig_structs.h:974
float dig_node_line_angle(struct Plus_head *plus, int nodeid, int lineid)
Return line angle.
Definition: plus_node.c:198
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:883
double x
X coordinate.
Definition: dig_structs.h:1453
float dig_calc_end_angle(const struct line_pnts *, double)
Definition: angle.c:82
plus_t n_lines
Number of attached lines (size of lines, angle)
Definition: dig_structs.h:1472
plus_t * lines
List of connected lines.
Definition: dig_structs.h:1479
#define NULL
Definition: ccmath.h:32
#define x
int dig_add_node(struct Plus_head *plus, double x, double y, double z)
Add new node to plus structure.
Definition: plus_node.c:102
double z
Z coordinate (used only for 3D data)
Definition: dig_structs.h:1461
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
float dig_calc_begin_angle(const struct line_pnts *, double)
Definition: angle.c:31
Basic topology-related info.
Definition: dig_structs.h:784
float * angles
List of angles of connected lines.
Definition: dig_structs.h:1488
int dig_node_alloc_line(struct P_node *, int)
Allocate space in P_node struct.
Definition: struct_alloc.c:69
struct P_node * dig_alloc_node()
Allocate new node structure.
Definition: struct_alloc.c:30
Topological feature - node.
Definition: dig_structs.h:1448
int dig_spidx_add_node(struct Plus_head *, int, double, double, double)
Add new node to spatial index.
Definition: spindex.c:284
double y
Y coordinate.
Definition: dig_structs.h:1457
int dig_which_node(struct Plus_head *plus, double x, double y, double thresh)
Return actual index into node arrays of the first set of matching coordinates.
Definition: plus_node.c:146
#define _(str)
Definition: glocale.h:10
int dig_node_add_line(struct Plus_head *plus, int nodeid, int lineid, const struct line_pnts *points, int type)
Add line info to node.
Definition: plus_node.c:45
#define GV_LINES
Definition: dig_defines.h:192
int G_debug(int, const char *,...) __attribute__((format(printf
int dig_alloc_nodes(struct Plus_head *, int)
Reallocate array of pointers to nodes.
Definition: struct_alloc.c:105
plus_t n_nodes
Current number of topological features derived from vector geometries.
Definition: dig_structs.h:939