GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
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
21static 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) {
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);
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 */
133int 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 lineid
182 * \param type feature type
183 * \param Points line geometry
184 * \param box bounding box
185 * \param offset line offset
186 *
187 * \return -1 on error
188 * \return line id
189 */
190int dig_restore_line(struct Plus_head *plus, int lineid, int type,
191 const struct line_pnts *Points,
192 const struct bound_box *box, off_t offset)
193{
195 return -1;
196 }
197
198 return add_line(plus, lineid, type, Points, box, offset);
199}
200
201/*!
202 * \brief Delete line from Plus_head structure.
203 *
204 * Doesn't update area/isle references (dig_del_area() or dig_del_isle()) must
205 * be run before the line is deleted if the line is part of such structure).
206 * Update is info about line in nodes. If this line is last in node then node is
207 * deleted.
208 *
209 * \param[in,out] plus pointer to Plus_head structure
210 * \param[in] line line id
211 * \param[in] x,y,z coordinates
212 *
213 * \return -1 on error
214 * \return 0 OK
215 *
216 */
217int dig_del_line(struct Plus_head *plus, int line, double x, double y, double z)
218{
219 int i;
220 plus_t N1 = 0, N2 = 0;
221 struct P_line *Line;
222 struct P_node *Node;
223
224 G_debug(3, "dig_del_line() line = %d", line);
225
226 Line = plus->Line[line];
227 dig_spidx_del_line(plus, line, x, y, z);
228
229 if (plus->uplist.do_uplist) {
230 dig_line_add_updated(plus, line, -Line->offset);
231 }
232
233 if (!(Line->type & GV_LINES)) {
234 /* Delete line */
235 dig_free_line(Line);
236 plus->Line[line] = NULL;
237
238 return 0;
239 }
240
241 /* Delete from nodes (and nodes) */
242 if (Line->type == GV_LINE) {
243 struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
244
245 N1 = topo->N1;
246 }
247 else if (Line->type == GV_BOUNDARY) {
248 struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
249
250 N1 = topo->N1;
251 }
252
253 Node = plus->Node[N1];
254
255 i = 0;
256 while (i < Node->n_lines && Node->lines[i] != line)
257 i++;
258
259 if (i == Node->n_lines) {
261 _("Attempt to delete not registered line %d from node %d"), line,
262 N1);
263 }
264
265 i++;
266 while (i < Node->n_lines) {
267 Node->lines[i - 1] = Node->lines[i];
268 Node->angles[i - 1] = Node->angles[i];
269 i++;
270 }
271 Node->n_lines--;
272
273 if (plus->uplist.do_uplist) {
274 dig_node_add_updated(plus, Node->n_lines > 0 ? N1 : -N1);
275 }
276 if (Node->n_lines == 0) {
277 G_debug(3, " node %d has 0 lines -> delete", N1);
278 dig_spidx_del_node(plus, N1);
279 /* free structures */
280 dig_free_node(Node);
281 plus->Node[N1] = NULL;
282 }
283
284 if (Line->type == GV_LINE) {
285 struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
286
287 N2 = topo->N2;
288 }
289 else if (Line->type == GV_BOUNDARY) {
290 struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
291
292 N2 = topo->N2;
293 }
294
295 Node = plus->Node[N2];
296 i = 0;
297 while (i < Node->n_lines && Node->lines[i] != -line)
298 i++;
299
300 if (i == Node->n_lines) {
302 _("Attempt to delete not registered line %d from node %d"), -line,
303 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 */
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 */
383int dig_line_set_area(struct Plus_head *plus, plus_t line, int side,
384 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 *
416 Box)
417 {
418 struct P_line *Line;
419
420 Line = plus->Line[line];
421
422 Line->N = Box->N;
423 Line->S = Box->S;
424 Line->E = Box->E;
425 Line->W = Box->W;
426 Line->T = Box->T;
427 Line->B = Box->B;
428
429 return (1);
430 }
431 */
432
433/*!
434 * \brief Get line bounding box saved in topo
435 *
436 * \param[in] plus pointer Plus_head structure
437 * \param[in] line line id
438 * \param[in,out] Box bounding box
439 *
440 * \return 1
441 */
442/*
443 int dig_line_get_box(struct Plus_head *plus, plus_t line, struct bound_box *
444 Box)
445 {
446 struct P_line *Line;
447
448 Line = plus->Line[line];
449
450 Box->N = Line->N;
451 Box->S = Line->S;
452 Box->E = Line->E;
453 Box->W = Line->W;
454 Box->T = Line->T;
455 Box->B = Line->B;
456
457 return (1);
458 }
459 */
#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
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_LINES
#define GV_BOUNDARY
#define GV_FACE
#define GV_RIGHT
#define GV_LEFT
Boundary side indicator left/right.
#define GV_KERNEL
void dig_free_line(struct P_line *)
Free line structure.
void dig_free_node(struct P_node *)
Free node structure.
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:717
void * dig_alloc_topo(char)
Allocate new topo struct.
struct P_line * dig_alloc_line(void)
Allocate new line structure.
int dig_spidx_del_line(struct Plus_head *, int, double, double, double)
Delete line from spatial index.
Definition spindex.c:472
int dig_alloc_lines(struct Plus_head *, int)
Reallocate array of pointers to lines.
int dig_spidx_del_node(struct Plus_head *, int)
Delete node from spatial index.
Definition spindex.c:429
void dig_line_add_updated(struct Plus_head *, int, off_t)
Add new line to updated.
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:39
#define TRUE
Definition gis.h:78
#define FALSE
Definition gis.h:82
#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:217
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
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:190
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:383
Vector geometry.
char type
Line type.
off_t offset
Offset in coor file for line.
void * topo
Topology info.
Topological feature - node.
double x
X coordinate.
plus_t n_lines
Number of attached lines (size of lines, angle)
float * angles
List of angles of connected lines.
plus_t * lines
List of connected lines.
double z
Z coordinate (used only for 3D data)
double y
Y coordinate.
Boundary topology.
plus_t left
Area number to the left, negative for isle.
plus_t N1
Start node.
plus_t N2
End node.
plus_t right
Area number to the right, negative for isle.
Centroid topology.
Line topology.
plus_t N1
Start node.
plus_t N2
End node.
Basic topology-related info.
plus_t n_klines
Current number of kernels.
plus_t alloc_lines
Number of allocated lines.
struct P_line ** Line
Array of vector geometries.
plus_t n_lines
Current number of lines.
plus_t n_plines
Current number of points.
plus_t n_blines
Current number of boundaries.
plus_t n_clines
Current number of centroids.
struct Plus_head::@10 uplist
List of updated lines/nodes.
struct P_node ** Node
Array of nodes.
plus_t n_flines
Current number of faces.
plus_t n_llines
Current number of lines.
Bounding box.
Definition dig_structs.h:62
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.