GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
plus_line.c
Go to the documentation of this file.
1 /**
2  * \file plus_line.c
3  *
4  * \brief Vector library - update topo for lines (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-2008
14  */
15 
16 #include <sys/types.h>
17 #include <stdlib.h>
18 #include <grass/vector.h>
19 #include <grass/glocale.h>
20 
21 static int add_line(struct Plus_head *plus, int lineid, int type,
22  const struct line_pnts *Points, const struct bound_box *box,
23  off_t offset)
24 {
25  int node, lp, node_new;
26  struct P_line *line;
27 
28  plus->Line[lineid] = dig_alloc_line();
29  line = plus->Line[lineid];
30 
31  line->type = type;
32  line->offset = offset;
33 
34  dig_spidx_add_line(plus, lineid, box);
35  if (plus->uplist.do_uplist) {
36  dig_line_add_updated(plus, lineid, offset);
37  }
38 
39  if (type & GV_POINT) {
40  line->topo = NULL;
41  return (lineid);
42  }
43 
44  line->topo = dig_alloc_topo(type);
45 
46  if (type & GV_CENTROID) {
47  struct P_topo_c *topo = (struct P_topo_c *)line->topo;
48 
49  topo->area = 0;
50  return (lineid);
51  }
52 
53  /* Add nodes for lines */
54  G_debug(3, "Register node: type = %d, %f,%f", type, Points->x[0],
55  Points->y[0]);
56 
57  /* Start node */
58  node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
59  G_debug(3, "node = %d", node);
60  if (node == 0) {
61  node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
62  G_debug(3, "Add new node: %d", node);
63  node_new = TRUE;
64  }
65  else {
66  G_debug(3, "Old node found: %d", node);
67  node_new = FALSE;
68  }
69 
70  if (type == GV_LINE) {
71  struct P_topo_l *topo = (struct P_topo_l *)line->topo;
72 
73  topo->N1 = node;
74  topo->N2 = 0;
75  }
76  else if (type == GV_BOUNDARY) {
77  struct P_topo_b *topo = (struct P_topo_b *)line->topo;
78 
79  topo->N1 = node;
80  topo->N2 = 0;
81  topo->left = 0;
82  topo->right = 0;
83  }
84 
85  dig_node_add_line(plus, node, lineid, Points, type);
86  if (plus->uplist.do_uplist)
87  dig_node_add_updated(plus, node_new ? -node : node);
88 
89  /* End node */
90  lp = Points->n_points - 1;
91  G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
92  node = dig_find_node(plus, Points->x[lp], Points->y[lp], Points->z[lp]);
93  G_debug(3, "node = %d", node);
94  if (node == 0) {
95  node = dig_add_node(plus, Points->x[lp], Points->y[lp], Points->z[lp]);
96  G_debug(3, "Add new node: %d", node);
97  node_new = TRUE;
98  }
99  else {
100  G_debug(3, "Old node found: %d", node);
101  node_new = FALSE;
102  }
103  if (type == GV_LINE) {
104  struct P_topo_l *topo = (struct P_topo_l *)line->topo;
105 
106  topo->N2 = node;
107  }
108  else if (type == GV_BOUNDARY) {
109  struct P_topo_b *topo = (struct P_topo_b *)line->topo;
110 
111  topo->N2 = node;
112  }
113 
114  dig_node_add_line(plus, node, -lineid, Points, type);
115  if (plus->uplist.do_uplist)
116  dig_node_add_updated(plus, node_new ? -node : node);
117 
118  return (lineid);
119 }
120 
121 /*!
122  * \brief Add new line to Plus_head structure.
123  *
124  * \param[in,out] plus pointer to Plus_head structure
125  * \param type feature type
126  * \param Points line geometry
127  * \param box bounding box
128  * \param offset line offset
129  *
130  * \return -1 on error
131  * \return line id
132  */
133 int dig_add_line(struct Plus_head *plus, int type,
134  const struct line_pnts *Points, const struct bound_box *box,
135  off_t offset)
136 {
137  int ret;
138 
139  /* First look if we have space in array of pointers to lines
140  * and reallocate if necessary */
141  if (plus->n_lines >= plus->alloc_lines) { /* array is full */
142  if (dig_alloc_lines(plus, 1000) == -1)
143  return -1;
144  }
145 
146  ret = add_line(plus, plus->n_lines + 1, type, Points, box, offset);
147 
148  if (ret == -1)
149  return ret;
150 
151  plus->n_lines++;
152 
153  switch (type) {
154  case GV_POINT:
155  plus->n_plines++;
156  break;
157  case GV_LINE:
158  plus->n_llines++;
159  break;
160  case GV_BOUNDARY:
161  plus->n_blines++;
162  break;
163  case GV_CENTROID:
164  plus->n_clines++;
165  break;
166  case GV_FACE:
167  plus->n_flines++;
168  break;
169  case GV_KERNEL:
170  plus->n_klines++;
171  break;
172  }
173 
174  return ret;
175 }
176 
177 /*!
178  * \brief Restore line in Plus_head structure.
179  *
180  * \param[in,out] plus pointer to Plus_head structure
181  * \param type feature type
182  * \param Points line geometry
183  * \param box bounding box
184  * \param offset line offset
185  *
186  * \return -1 on error
187  * \return line id
188  */
189 int dig_restore_line(struct Plus_head *plus, int lineid, int type,
190  const struct line_pnts *Points,
191  const struct bound_box *box, off_t offset)
192 {
193  if (lineid < 1 || lineid > plus->n_lines) {
194  return -1;
195  }
196 
197  return add_line(plus, lineid, type, Points, box, offset);
198 }
199 
200 /*!
201  * \brief Delete line from Plus_head structure.
202  *
203  * Doesn't update area/isle references (dig_del_area() or dig_del_isle()) must
204  * be run before the line is deleted if the line is part of such structure).
205  * Update is info about line in nodes. If this line is last in node then node is
206  * deleted.
207  *
208  * \param[in,out] plus pointer to Plus_head structure
209  * \param[in] line line id
210  * \param[in] x,y,z coordinates
211  *
212  * \return -1 on error
213  * \return 0 OK
214  *
215  */
216 int dig_del_line(struct Plus_head *plus, int line, double x, double y, double z)
217 {
218  int i;
219  plus_t N1 = 0, N2 = 0;
220  struct P_line *Line;
221  struct P_node *Node;
222 
223  G_debug(3, "dig_del_line() line = %d", line);
224 
225  Line = plus->Line[line];
226  dig_spidx_del_line(plus, line, x, y, z);
227 
228  if (plus->uplist.do_uplist) {
229  dig_line_add_updated(plus, line, -Line->offset);
230  }
231 
232  if (!(Line->type & GV_LINES)) {
233  /* Delete line */
234  dig_free_line(Line);
235  plus->Line[line] = NULL;
236 
237  return 0;
238  }
239 
240  /* Delete from nodes (and nodes) */
241  if (Line->type == GV_LINE) {
242  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
243 
244  N1 = topo->N1;
245  }
246  else if (Line->type == GV_BOUNDARY) {
247  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
248 
249  N1 = topo->N1;
250  }
251 
252  Node = plus->Node[N1];
253 
254  i = 0;
255  while (i < Node->n_lines && Node->lines[i] != line)
256  i++;
257 
258  if (i == Node->n_lines) {
260  _("Attempt to delete not registered line %d from node %d"), line,
261  N1);
262  }
263 
264  i++;
265  while (i < Node->n_lines) {
266  Node->lines[i - 1] = Node->lines[i];
267  Node->angles[i - 1] = Node->angles[i];
268  i++;
269  }
270  Node->n_lines--;
271 
272  if (plus->uplist.do_uplist) {
273  dig_node_add_updated(plus, Node->n_lines > 0 ? N1 : -N1);
274  }
275  if (Node->n_lines == 0) {
276  G_debug(3, " node %d has 0 lines -> delete", N1);
277  dig_spidx_del_node(plus, N1);
278  /* free structures */
279  dig_free_node(Node);
280  plus->Node[N1] = NULL;
281  }
282 
283  if (Line->type == GV_LINE) {
284  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
285 
286  N2 = topo->N2;
287  }
288  else if (Line->type == GV_BOUNDARY) {
289  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
290 
291  N2 = topo->N2;
292  }
293 
294  Node = plus->Node[N2];
295  i = 0;
296  while (i < Node->n_lines && Node->lines[i] != -line)
297  i++;
298 
299  if (i == Node->n_lines) {
301  _("Attempt to delete not registered line %d from node %d"), -line,
302  N2);
303  }
304 
305  i++;
306  while (i < Node->n_lines) {
307  Node->lines[i - 1] = Node->lines[i];
308  Node->angles[i - 1] = Node->angles[i];
309  i++;
310  }
311  Node->n_lines--;
312 
313  if (plus->uplist.do_uplist) {
314  dig_node_add_updated(plus, Node->n_lines > 0 ? N2 : -N2);
315  }
316  if (Node->n_lines == 0) {
317  G_debug(3, " node %d has 0 lines -> delete", N2);
318  dig_spidx_del_node(plus, N2);
319  /* free structures */
320  dig_free_node(Node);
321  plus->Node[N2] = NULL;
322  }
323 
324  /* Delete line */
325  dig_free_line(Line);
326  plus->Line[line] = NULL;
327 
328  return 0;
329 }
330 
331 /*!
332  * \brief Get area number on line side.
333  *
334  * \param[in] plus pointer Plus_head structure
335  * \param[in] line line id
336  * \param[in] side side id (GV_LEFT || GV_RIGHT)
337  *
338  * \return area number
339  * \return 0 no area
340  * \return -1 on error
341  */
342 plus_t dig_line_get_area(struct Plus_head *plus, plus_t line, int side)
343 {
344  struct P_line *Line;
345  struct P_topo_b *topo;
346 
347  Line = plus->Line[line];
348  if (!Line) /* dead */
349  return -1;
350 
351  if (Line->type != GV_BOUNDARY)
352  return -1;
353 
354  topo = (struct P_topo_b *)Line->topo;
355  if (side == GV_LEFT) {
356  G_debug(3,
357  "dig_line_get_area(): line = %d, side = %d (left), area = %d",
358  line, side, topo->left);
359  return (topo->left);
360  }
361  if (side == GV_RIGHT) {
362  G_debug(3,
363  "dig_line_get_area(): line = %d, side = %d (right), area = %d",
364  line, side, topo->right);
365 
366  return (topo->right);
367  }
368 
369  return (-1);
370 }
371 
372 /*!
373  * \brief Set area number on line side
374  *
375  * \param[in] plus pointer Plus_head structure
376  * \param[in] line line id
377  * \param[in] side side id (GV_LEFT || GV_RIGHT)
378  * \param[in] area area id
379  *
380  * \return 1
381  */
382 int dig_line_set_area(struct Plus_head *plus, plus_t line, int side,
383  plus_t area)
384 {
385  struct P_line *Line;
386  struct P_topo_b *topo;
387 
388  Line = plus->Line[line];
389  if (Line->type != GV_BOUNDARY)
390  return (0);
391 
392  topo = (struct P_topo_b *)Line->topo;
393 
394  if (side == GV_LEFT) {
395  topo->left = area;
396  }
397  else if (side == GV_RIGHT) {
398  topo->right = area;
399  }
400 
401  return (1);
402 }
403 
404 /*!
405  * \brief Set line bounding box
406  *
407  * \param[in] plus pointer Plus_head structure
408  * \param[in] line line id
409  * \param[in] Box bounding box
410  *
411  * \return 1
412  */
413 /*
414  int dig_line_set_box(struct Plus_head *plus, plus_t line, struct bound_box *
415  Box)
416  {
417  struct P_line *Line;
418 
419  Line = plus->Line[line];
420 
421  Line->N = Box->N;
422  Line->S = Box->S;
423  Line->E = Box->E;
424  Line->W = Box->W;
425  Line->T = Box->T;
426  Line->B = Box->B;
427 
428  return (1);
429  }
430  */
431 
432 /*!
433  * \brief Get line bounding box saved in topo
434  *
435  * \param[in] plus pointer Plus_head structure
436  * \param[in] line line id
437  * \param[in,out] Box bounding box
438  *
439  * \return 1
440  */
441 /*
442  int dig_line_get_box(struct Plus_head *plus, plus_t line, struct bound_box *
443  Box)
444  {
445  struct P_line *Line;
446 
447  Line = plus->Line[line];
448 
449  Box->N = Line->N;
450  Box->S = Line->S;
451  Box->E = Line->E;
452  Box->W = Line->W;
453  Box->T = Line->T;
454  Box->B = Line->B;
455 
456  return (1);
457  }
458  */
#define NULL
Definition: ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_CENTROID
Definition: dig_defines.h:186
#define GV_LINE
Definition: dig_defines.h:184
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:183
#define GV_LINES
Definition: dig_defines.h:193
#define GV_BOUNDARY
Definition: dig_defines.h:185
#define GV_FACE
Definition: dig_defines.h:187
#define GV_RIGHT
Definition: dig_defines.h:176
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:175
#define GV_KERNEL
Definition: dig_defines.h:188
void dig_free_line(struct P_line *)
Free line structure.
Definition: struct_alloc.c:177
void dig_free_node(struct P_node *)
Free node structure.
Definition: struct_alloc.c:48
void dig_node_add_updated(struct Plus_head *, int)
Add node to updated.
int dig_node_add_line(struct Plus_head *, int, int, const struct line_pnts *, int)
Add line info to node.
Definition: plus_node.c:44
int dig_find_node(struct Plus_head *, double, double, double)
Find one node by coordinates.
Definition: spindex.c:718
void * dig_alloc_topo(char)
Allocate new topo struct.
Definition: struct_alloc.c:145
int dig_spidx_del_line(struct Plus_head *, int, double, double, double)
Delete line from spatial index.
Definition: spindex.c:473
int dig_alloc_lines(struct Plus_head *, int)
Reallocate array of pointers to lines.
Definition: struct_alloc.c:193
int dig_spidx_del_node(struct Plus_head *, int)
Delete node from spatial index.
Definition: spindex.c:430
void dig_line_add_updated(struct Plus_head *, int, off_t)
Add new line to updated.
struct P_line * dig_alloc_line(void)
Allocate new line structure.
Definition: struct_alloc.c:127
int dig_add_node(struct Plus_head *, double, double, double)
Add new node to plus structure.
Definition: plus_node.c:101
int dig_spidx_add_line(struct Plus_head *, int, const struct bound_box *)
Add new line to spatial index.
Definition: spindex.c:326
int plus_t
plus_t size
Definition: dig_structs.h:41
#define TRUE
Definition: gis.h:79
#define FALSE
Definition: gis.h:83
#define _(str)
Definition: glocale.h:10
int dig_add_line(struct Plus_head *plus, int type, const struct line_pnts *Points, const struct bound_box *box, off_t offset)
Add new line to Plus_head structure.
Definition: plus_line.c:133
int dig_del_line(struct Plus_head *plus, int line, double x, double y, double z)
Delete line from Plus_head structure.
Definition: plus_line.c:216
plus_t dig_line_get_area(struct Plus_head *plus, plus_t line, int side)
Get area number on line side.
Definition: plus_line.c:342
int dig_restore_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points, const struct bound_box *box, off_t offset)
Restore line in Plus_head structure.
Definition: plus_line.c:189
int dig_line_set_area(struct Plus_head *plus, plus_t line, int side, plus_t area)
Set area number on line side.
Definition: plus_line.c:382
return(psObject)
if(!(yy_init))
Definition: sqlp.yy.c:775
Vector geometry.
Definition: dig_structs.h:1553
char type
Line type.
Definition: dig_structs.h:1564
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1571
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
double z
Z coordinate (used only for 3D data)
Definition: dig_structs.h:1445
double y
Y coordinate.
Definition: dig_structs.h:1441
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
int do_uplist
Indicates if the list of updated features is maintained.
Definition: dig_structs.h:1161
plus_t n_klines
Current number of kernels.
Definition: dig_structs.h:906
plus_t alloc_lines
Number of allocated lines.
Definition: dig_structs.h:970
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:871
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:931
plus_t n_plines
Current number of points.
Definition: dig_structs.h:886
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:894
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:898
struct Plus_head::@10 uplist
List of updated lines/nodes.
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:867
plus_t n_flines
Current number of faces.
Definition: dig_structs.h:902
plus_t n_llines
Current number of lines.
Definition: dig_structs.h:890
Bounding box.
Definition: dig_structs.h:64
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
double * y
Array of Y coordinates.
Definition: dig_structs.h:1659
double * x
Array of X coordinates.
Definition: dig_structs.h:1655
int n_points
Number of points.
Definition: dig_structs.h:1667
double * z
Array of Z coordinates.
Definition: dig_structs.h:1663
#define x