GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
plus_line.c
Go to the documentation of this file.
1 
2 /**
3  * \file plus_line.c
4  *
5  * \brief Vector library - update topo for lines (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-2008
15  */
16 
17 #include <sys/types.h>
18 #include <stdlib.h>
19 #include <grass/vector.h>
20 #include <grass/glocale.h>
21 
22 static int add_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points,
23  const struct bound_box *box, 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],
93  Points->z[lp]);
94  G_debug(3, "node = %d", node);
95  if (node == 0) {
96  node = dig_add_node(plus, Points->x[lp], Points->y[lp],
97  Points->z[lp]);
98  G_debug(3, "Add new node: %d", node);
99  node_new = TRUE;
100  }
101  else {
102  G_debug(3, "Old node found: %d", node);
103  node_new = FALSE;
104  }
105  if (type == GV_LINE) {
106  struct P_topo_l *topo = (struct P_topo_l *)line->topo;
107 
108  topo->N2 = node;
109  }
110  else if (type == GV_BOUNDARY) {
111  struct P_topo_b *topo = (struct P_topo_b *)line->topo;
112 
113  topo->N2 = node;
114  }
115 
116  dig_node_add_line(plus, node, -lineid, Points, type);
117  if (plus->uplist.do_uplist)
118  dig_node_add_updated(plus, node_new ? -node : node);
119 
120  return (lineid);
121 }
122 
123 /*!
124  * \brief Add new line to Plus_head structure.
125  *
126  * \param[in,out] plus pointer to Plus_head structure
127  * \param type feature type
128  * \param Points line geometry
129  * \param box bounding box
130  * \param offset line offset
131  *
132  * \return -1 on error
133  * \return line id
134  */
135 int
136 dig_add_line(struct Plus_head *plus, int type, const struct line_pnts *Points,
137  const struct bound_box *box, off_t offset)
138 {
139  int ret;
140 
141  /* First look if we have space in array of pointers to lines
142  * and reallocate if necessary */
143  if (plus->n_lines >= plus->alloc_lines) { /* array is full */
144  if (dig_alloc_lines(plus, 1000) == -1)
145  return -1;
146  }
147 
148  ret = add_line(plus, plus->n_lines + 1, type, Points, box, offset);
149 
150  if (ret == -1)
151  return ret;
152 
153  plus->n_lines++;
154 
155  switch (type) {
156  case GV_POINT:
157  plus->n_plines++;
158  break;
159  case GV_LINE:
160  plus->n_llines++;
161  break;
162  case GV_BOUNDARY:
163  plus->n_blines++;
164  break;
165  case GV_CENTROID:
166  plus->n_clines++;
167  break;
168  case GV_FACE:
169  plus->n_flines++;
170  break;
171  case GV_KERNEL:
172  plus->n_klines++;
173  break;
174  }
175 
176  return ret;
177 }
178 
179 /*!
180  * \brief Restore line in Plus_head structure.
181  *
182  * \param[in,out] plus pointer to Plus_head structure
183  * \param type feature type
184  * \param Points line geometry
185  * \param box bounding box
186  * \param offset line offset
187  *
188  * \return -1 on error
189  * \return line id
190  */
191 int
192 dig_restore_line(struct Plus_head *plus, int lineid,
193  int type, const struct line_pnts *Points,
194  const struct bound_box *box, off_t offset)
195 {
196  if (lineid < 1 || lineid > plus->n_lines) {
197  return -1;
198  }
199 
200  return add_line(plus, lineid, type, Points, box, offset);
201 }
202 
203 /*!
204  * \brief Delete line from Plus_head structure.
205  *
206  * Doesn't update area/isle references (dig_del_area() or dig_del_isle()) must be
207  * run before the line is deleted if the line is part of such
208  * structure). Update is info about line in nodes. If this line is
209  * last in node then node is deleted.
210  *
211  * \param[in,out] plus pointer to Plus_head structure
212  * \param[in] line line id
213  * \param[in] x,y,z coordinates
214  *
215  * \return -1 on error
216  * \return 0 OK
217  *
218  */
219 int dig_del_line(struct Plus_head *plus, int line, double x, double y, double z)
220 {
221  int i;
222  plus_t N1 = 0, N2 = 0;
223  struct P_line *Line;
224  struct P_node *Node;
225 
226  G_debug(3, "dig_del_line() line = %d", line);
227 
228  Line = plus->Line[line];
229  dig_spidx_del_line(plus, line, x, y, z);
230 
231  if (plus->uplist.do_uplist) {
232  dig_line_add_updated(plus, line, -Line->offset);
233  }
234 
235  if (!(Line->type & GV_LINES)) {
236  /* Delete line */
237  dig_free_line(Line);
238  plus->Line[line] = NULL;
239 
240  return 0;
241  }
242 
243  /* Delete from nodes (and nodes) */
244  if (Line->type == GV_LINE) {
245  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
246 
247  N1 = topo->N1;
248  }
249  else if (Line->type == GV_BOUNDARY) {
250  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
251 
252  N1 = topo->N1;
253  }
254 
255  Node = plus->Node[N1];
256 
257  i = 0;
258  while (i < Node->n_lines && Node->lines[i] != line)
259  i++;
260 
261  if (i == Node->n_lines) {
262  G_fatal_error(_("Attempt to delete not registered line %d from node %d"),
263  line, N1);
264  }
265 
266  i++;
267  while (i < Node->n_lines) {
268  Node->lines[i - 1] = Node->lines[i];
269  Node->angles[i - 1] = Node->angles[i];
270  i++;
271  }
272  Node->n_lines--;
273 
274  if (plus->uplist.do_uplist) {
275  dig_node_add_updated(plus, Node->n_lines > 0 ? N1 : -N1);
276  }
277  if (Node->n_lines == 0) {
278  G_debug(3, " node %d has 0 lines -> delete", N1);
279  dig_spidx_del_node(plus, N1);
280  /* free structures */
281  dig_free_node(Node);
282  plus->Node[N1] = NULL;
283  }
284 
285  if (Line->type == GV_LINE) {
286  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
287 
288  N2 = topo->N2;
289  }
290  else if (Line->type == GV_BOUNDARY) {
291  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
292 
293  N2 = topo->N2;
294  }
295 
296  Node = plus->Node[N2];
297  i = 0;
298  while (i < Node->n_lines && Node->lines[i] != -line)
299  i++;
300 
301  if (i == Node->n_lines) {
302  G_fatal_error(_("Attempt to delete not registered line %d from node %d"),
303  -line, N2);
304  }
305 
306  i++;
307  while (i < Node->n_lines) {
308  Node->lines[i - 1] = Node->lines[i];
309  Node->angles[i - 1] = Node->angles[i];
310  i++;
311  }
312  Node->n_lines--;
313 
314  if (plus->uplist.do_uplist) {
315  dig_node_add_updated(plus, Node->n_lines > 0 ? N2 : -N2);
316  }
317  if (Node->n_lines == 0) {
318  G_debug(3, " node %d has 0 lines -> delete", N2);
319  dig_spidx_del_node(plus, N2);
320  /* free structures */
321  dig_free_node(Node);
322  plus->Node[N2] = NULL;
323  }
324 
325  /* Delete line */
326  dig_free_line(Line);
327  plus->Line[line] = NULL;
328 
329  return 0;
330 }
331 
332 /*!
333  * \brief Get area number on line side.
334  *
335  * \param[in] plus pointer Plus_head structure
336  * \param[in] line line id
337  * \param[in] side side id (GV_LEFT || GV_RIGHT)
338  *
339  * \return area number
340  * \return 0 no area
341  * \return -1 on error
342  */
343 plus_t dig_line_get_area(struct Plus_head * plus, plus_t line, int side)
344 {
345  struct P_line *Line;
346  struct P_topo_b *topo;
347 
348  Line = plus->Line[line];
349  if (!Line) /* dead */
350  return -1;
351 
352  if (Line->type != GV_BOUNDARY)
353  return -1;
354 
355  topo = (struct P_topo_b *)Line->topo;
356  if (side == GV_LEFT) {
357  G_debug(3,
358  "dig_line_get_area(): line = %d, side = %d (left), area = %d",
359  line, side, topo->left);
360  return (topo->left);
361  }
362  if (side == GV_RIGHT) {
363  G_debug(3,
364  "dig_line_get_area(): line = %d, side = %d (right), area = %d",
365  line, side, topo->right);
366 
367  return (topo->right);
368  }
369 
370  return (-1);
371 }
372 
373 /*!
374  * \brief Set area number on line side
375  *
376  * \param[in] plus pointer Plus_head structure
377  * \param[in] line line id
378  * \param[in] side side id (GV_LEFT || GV_RIGHT)
379  * \param[in] area area id
380  *
381  * \return 1
382  */
383 int
384 dig_line_set_area(struct Plus_head *plus, plus_t line, int side, plus_t area)
385 {
386  struct P_line *Line;
387  struct P_topo_b *topo;
388 
389  Line = plus->Line[line];
390  if (Line->type != GV_BOUNDARY)
391  return (0);
392 
393  topo = (struct P_topo_b *)Line->topo;
394 
395  if (side == GV_LEFT) {
396  topo->left = area;
397  }
398  else if (side == GV_RIGHT) {
399  topo->right = area;
400  }
401 
402  return (1);
403 }
404 
405 /*!
406  * \brief Set line bounding box
407  *
408  * \param[in] plus pointer Plus_head structure
409  * \param[in] line line id
410  * \param[in] Box bounding box
411  *
412  * \return 1
413  */
414 /*
415 int dig_line_set_box(struct Plus_head *plus, plus_t line, struct bound_box * 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 * Box)
443 {
444  struct P_line *Line;
445 
446  Line = plus->Line[line];
447 
448  Box->N = Line->N;
449  Box->S = Line->S;
450  Box->E = Line->E;
451  Box->W = Line->W;
452  Box->T = Line->T;
453  Box->B = Line->B;
454 
455  return (1);
456 }
457 */
#define TRUE
Definition: gis.h:59
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
return(const char *)
Definition: dbfopen.c:1621
plus_t n_klines
Current number of kernels.
Definition: dig_structs.h:922
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1593
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int dig_spidx_del_line(struct Plus_head *, int, double, double, double)
Delete line from spatial index.
Definition: spindex.c:466
plus_t n_plines
Current number of points.
Definition: dig_structs.h:902
plus_t right
Area number to the right, negative for isle.
Definition: dig_structs.h:1526
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:883
void * dig_alloc_topo(char)
Allocate new topo struct.
Definition: struct_alloc.c:145
int n_points
Number of points.
Definition: dig_structs.h:1692
#define GV_CENTROID
Definition: dig_defines.h:185
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
plus_t * lines
List of connected lines.
Definition: dig_structs.h:1479
int do_uplist
Indicates if the list of updated features is maintained.
Definition: dig_structs.h:1177
#define NULL
Definition: ccmath.h:32
#define x
plus_t N1
Start node.
Definition: dig_structs.h:1514
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:182
plus_t N2
End node.
Definition: dig_structs.h:1503
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
#define GV_LINE
Definition: dig_defines.h:183
plus_t N1
Start node.
Definition: dig_structs.h:1499
int dig_alloc_lines(struct Plus_head *, int)
Reallocate array of pointers to lines.
Definition: struct_alloc.c:193
double * x
Array of X coordinates.
Definition: dig_structs.h:1680
char type
Line type.
Definition: dig_structs.h:1586
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
Centroid topology.
Definition: dig_structs.h:1532
#define GV_FACE
Definition: dig_defines.h:186
Basic topology-related info.
Definition: dig_structs.h:784
int dig_node_add_line(struct Plus_head *, int, int, const struct line_pnts *, int)
Add line info to node.
Definition: plus_node.c:45
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:384
void dig_node_add_updated(struct Plus_head *, int)
Add node to updated.
plus_t alloc_lines
Number of allocated lines.
Definition: dig_structs.h:986
Line topology.
Definition: dig_structs.h:1494
#define FALSE
Definition: gis.h:63
void * topo
Topology info.
Definition: dig_structs.h:1599
int dig_spidx_del_node(struct Plus_head *, int)
Delete node from spatial index.
Definition: spindex.c:423
float * angles
List of angles of connected lines.
Definition: dig_structs.h:1488
Boundary topology.
Definition: dig_structs.h:1509
struct P_line * dig_alloc_line()
Allocate new line structure.
Definition: struct_alloc.c:127
#define GV_BOUNDARY
Definition: dig_defines.h:184
Topological feature - node.
Definition: dig_structs.h:1448
void dig_line_add_updated(struct Plus_head *, int, off_t)
Add new line to updated.
plus_t n_flines
Current number of faces.
Definition: dig_structs.h:918
void dig_free_node(struct P_node *)
Free node structure.
Definition: struct_alloc.c:48
double * y
Array of Y coordinates.
Definition: dig_structs.h:1684
plus_t n_llines
Current number of lines.
Definition: dig_structs.h:906
int dig_add_node(struct Plus_head *, double, double, double)
Add new node to plus structure.
Definition: plus_node.c:102
#define GV_RIGHT
Definition: dig_defines.h:175
double * z
Array of Z coordinates.
Definition: dig_structs.h:1688
#define _(str)
Definition: glocale.h:10
int dig_find_node(struct Plus_head *, double, double, double)
Find one node by coordinates.
Definition: spindex.c:710
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:914
void dig_free_line(struct P_line *)
Free line structure.
Definition: struct_alloc.c:177
int dig_spidx_add_line(struct Plus_head *, int, const struct bound_box *)
Add new line to spatial index.
Definition: spindex.c:319
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:136
#define GV_LINES
Definition: dig_defines.h:192
struct Plus_head::@10 uplist
List of updated lines/nodes.
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:219
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:910
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:343
plus_t N2
End node.
Definition: dig_structs.h:1518
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_KERNEL
Definition: dig_defines.h:187
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:192