GRASS 8 Programmer's Manual 8.6.0dev(2026)-c83afef6d3
Loading...
Searching...
No Matches
line.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/line.c
3
4 \brief Vector library - vector feature geometry
5
6 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Original author CERL, probably Dave Gerdes or Mike Higgins.
10 \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
11 \author Some updates for GRASS 7 by Martin Landa <landa.martin gmail.com>
12 */
13
14#include <stdlib.h>
15#include <math.h>
16#include <grass/vector.h>
17#include <grass/glocale.h>
18
19/*!
20 \brief Creates and initializes a struct line_pnts (internal use only)
21
22 Use Vect_new_line_struct() instead.
23
24 \return pointer to allocated line_pnts structure
25 \return NULL on error
26 */
28
29/*!
30 \brief Creates and initializes a line_pnts structure
31
32 This structure is used for reading and writing vector lines and
33 polygons. The library routines handle all memory allocation. If 3
34 lines in memory are needed at the same time, then simply 3 line_pnts
35 structures have to be used.
36
37 To free allocated memory call Vect_destroy_line_struct().
38
39 Calls G_fatal_error() on error.
40
41 \return pointer to line_pnts
42 */
44{
45 struct line_pnts *p;
46
47 if (NULL == (p = Vect__new_line_struct()))
48 G_fatal_error("Vect_new_line_struct(): %s", _("Out of memory"));
49
50 return p;
51}
52
54{
55 struct line_pnts *p;
56
57 p = (struct line_pnts *)malloc(sizeof(struct line_pnts));
58
59 /* alloc_points MUST be initialized to zero */
60 if (p)
61 p->alloc_points = p->n_points = 0;
62
63 if (p)
64 p->x = p->y = p->z = NULL;
65
66 return p;
67}
68
69/*!
70 \brief Frees all memory associated with a line_pnts structure,
71 including the structure itself
72
73 \param p pointer to line_pnts structure
74 */
76{
77 if (p) { /* probably a moot test */
78 if (p->alloc_points) {
79 G_free((char *)p->x);
80 G_free((char *)p->y);
81 G_free((char *)p->z);
82 }
83 G_free((char *)p);
84 }
85}
86
87/*!
88 \brief Copy points from array to line_pnts structure
89
90 \param Points pointer to line_ptns structure
91 \param x,y,z array of coordinates
92 \param n number of points to be copied
93
94 \return 0 on success
95 \return -1 on out of memory
96 */
97int Vect_copy_xyz_to_pnts(struct line_pnts *Points, const double *x,
98 const double *y, const double *z, int n)
99{
100 int i;
101
102 if (0 > dig_alloc_points(Points, n))
103 return -1;
104
105 for (i = 0; i < n; i++) {
106 Points->x[i] = x[i];
107 Points->y[i] = y[i];
108 if (z != NULL)
109 Points->z[i] = z[i];
110 else
111 Points->z[i] = 0;
112 Points->n_points = n;
113 }
114
115 return 0;
116}
117
118/*!
119 \brief Reset line
120
121 Make sure line structure is clean to be re-used, i.e. it has no
122 points associated with it Points must have previously been created
123 with Vect_new_line_struct().
124
125 \param Points pointer to line_pnts structure to be reset
126 */
127void Vect_reset_line(struct line_pnts *Points)
128{
129 Points->n_points = 0;
130}
131
132/*!
133 \brief Appends one point to the end of a line.
134
135 If you are re-using a line struct, be sure to clear out old data
136 first by calling Vect_reset_line().
137
138 Calls G_fatal_error() when out of memory.
139
140 \param Points pointer to line_pnts structure
141 \param x,y,z point coordinates to be added
142
143 \return number of points
144 \return -1 on error (out of memory)
145 */
146int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
147{
148 register int n;
149
150 if (0 > dig_alloc_points(Points, Points->n_points + 1)) {
151 G_fatal_error(_("Out of memory"));
152 return -1;
153 }
154
155 n = Points->n_points;
156 Points->x[n] = x;
157 Points->y[n] = y;
158 Points->z[n] = z;
159
160 return ++(Points->n_points);
161}
162
163/*!
164 \brief Insert new point at index position and move all old points
165 at that position and above up
166
167 \param Points pointer to line_pnts structure
168 \param index (from 0 to Points->n_points-1)
169 \param x,y,z point coordinates
170
171 \return number of points
172 \return -1 on error (allocation)
173 */
174int Vect_line_insert_point(struct line_pnts *Points, int index, double x,
175 double y, double z)
176{
177 int n;
178
179 if (index < 0 || index > Points->n_points - 1)
180 G_fatal_error("Vect_line_insert_point(): %s",
181 _("Index out of range in"));
182
183 if (0 > dig_alloc_points(Points, Points->n_points + 1))
184 return -1;
185
186 /* move up */
187 for (n = Points->n_points; n > index; n--) {
188 Points->x[n] = Points->x[n - 1];
189 Points->y[n] = Points->y[n - 1];
190 Points->z[n] = Points->z[n - 1];
191 }
192
193 Points->x[index] = x;
194 Points->y[index] = y;
195 Points->z[index] = z;
196
197 return ++(Points->n_points);
198}
199
200/*!
201 \brief Delete point at given index and move all points above down
202
203 \param Points pointer to line_pnts structure
204 \param index point (from 0 to Points->n_points-1)
205
206 \return number of points
207 */
208int Vect_line_delete_point(struct line_pnts *Points, int index)
209{
210 int n;
211
212 if (index < 0 || index > Points->n_points - 1)
213 G_fatal_error("Vect_line_insert_point(): %s",
214 _("Index out of range in"));
215
216 if (Points->n_points == 0)
217 return 0;
218
219 /* move down */
220 for (n = index; n < Points->n_points - 1; n++) {
221 Points->x[n] = Points->x[n + 1];
222 Points->y[n] = Points->y[n + 1];
223 Points->z[n] = Points->z[n + 1];
224 }
225
226 return --(Points->n_points);
227}
228
229/*!
230 \brief Get line point of given index
231
232 Calls G_fatal_error() when index is not range in.
233
234 \param Points pointer to line_pnts structure
235 \param index point index (from 0 to Points->n_points-1)
236 \param x pointer to x coordinate or NULL
237 \param y pointer to y coordinate or NULL
238 \param z pointer to z coordinate or NULL
239
240 \return number of points
241 */
242int Vect_line_get_point(const struct line_pnts *Points, int index, double *x,
243 double *y, double *z)
244{
245 if (index < 0 || index > Points->n_points - 1)
246 G_fatal_error("Vect_line_get_point(): %s", _("Index out of range in"));
247
248 if (x)
249 *x = Points->x[index];
250 if (y)
251 *y = Points->y[index];
252 if (z)
253 *z = Points->z[index];
254
255 return Points->n_points;
256}
257
258/*!
259 \brief Get number of line points
260
261 \param Points pointer to line_pnts structure
262
263 \return number of points
264 */
265int Vect_get_num_line_points(const struct line_pnts *Points)
266{
267 return Points->n_points;
268}
269
270/*!
271 \brief Remove duplicate points, i.e. zero length segments
272
273 \param Points pointer to line_pnts structure
274
275 \return number of points
276 */
277int Vect_line_prune(struct line_pnts *Points)
278{
279 int i, j;
280
281 if (Points->n_points > 0) {
282 j = 1;
283 for (i = 1; i < Points->n_points; i++) {
284 if (Points->x[i] != Points->x[j - 1] ||
285 Points->y[i] != Points->y[j - 1] ||
286 Points->z[i] != Points->z[j - 1]) {
287 Points->x[j] = Points->x[i];
288 Points->y[j] = Points->y[i];
289 Points->z[j] = Points->z[i];
290 j++;
291 }
292 }
293 Points->n_points = j;
294 }
295
296 return (Points->n_points);
297}
298
299/*!
300 \brief Remove points in threshold
301
302 \param Points pointer to line_pnts structure
303 \param threshold threshold value
304
305 \return number of points in result
306 */
307int Vect_line_prune_thresh(struct line_pnts *Points, double threshold)
308{
309 int ret;
310
311 ret = dig_prune(Points, threshold);
312
314 Points->n_points = ret;
315
316 return (Points->n_points);
317}
318
319/*!
320 \brief Appends points to the end of a line.
321
322 Note, this will append to whatever is in line_pnts structure. If you
323 are re-using a line struct, be sure to clear out old data first by
324 calling Vect_reset_line().
325
326 \param Points pointer to line_pnts structure
327 \param APoints points to be included
328 \param direction direction (GV_FORWARD, GV_BACKWARD)
329
330 \return new number of points
331 \return -1 on out of memory
332 */
333int Vect_append_points(struct line_pnts *Points,
334 const struct line_pnts *APoints, int direction)
335{
336 int i, n, on, an;
337
338 on = Points->n_points;
339 an = APoints->n_points;
340 n = on + an;
341
342 /* Should be OK, dig_alloc_points calls realloc */
343 if (0 > dig_alloc_points(Points, n))
344 return (-1);
345
346 if (direction == GV_FORWARD) {
347 for (i = 0; i < an; i++) {
348 Points->x[on + i] = APoints->x[i];
349 Points->y[on + i] = APoints->y[i];
350 Points->z[on + i] = APoints->z[i];
351 }
352 }
353 else {
354 for (i = 0; i < an; i++) {
355 Points->x[on + i] = APoints->x[an - i - 1];
356 Points->y[on + i] = APoints->y[an - i - 1];
357 Points->z[on + i] = APoints->z[an - i - 1];
358 }
359 }
360
361 Points->n_points = n;
362 return n;
363}
364
365/*!
366 \brief Copy points from line structure to array
367
368 x/y/z arrays MUST be at least as large as Points->n_points
369
370 Also note that n is a pointer to int.
371
372 \param Points pointer to line_pnts structure
373 \param x,y,z coordinates arrays
374 \param n number of points
375
376 \return number of points copied
377 */
378int Vect_copy_pnts_to_xyz(const struct line_pnts *Points, double *x, double *y,
379 double *z, int *n)
380{
381 int i;
382
383 for (i = 0; i < *n; i++) {
384 x[i] = Points->x[i];
385 y[i] = Points->y[i];
386 if (z != NULL)
387 z[i] = Points->z[i];
388 *n = Points->n_points;
389 }
390
391 return (Points->n_points);
392}
393
394/*!
395 \brief Find point on line in the specified distance.
396
397 From the beginning, measured along line.
398
399 If the distance is greater than line length or negative, error is returned.
400
401 \param Points pointer to line_pnts structure
402 \param distance distance value
403 \param x,y,z pointers to point coordinates or NULL
404 \param angle pointer to angle of line in that point (radians, counter
405 clockwise from x axis) or NULL \param slope pointer to slope angle in radians
406 (positive up)
407
408 \return number of segment the point is on (first is 1),
409 \return 0 error when point is outside the line
410 */
411int Vect_point_on_line(const struct line_pnts *Points, double distance,
412 double *x, double *y, double *z, double *angle,
413 double *slope)
414{
415 int j, np, seg = 0;
416 double dist = 0, length;
417 double xp = 0, yp = 0, zp = 0, dx = 0, dy = 0, dz = 0, dxy = 0, dxyz, k,
418 rest;
419
420 G_debug(3, "Vect_point_on_line(): distance = %f", distance);
421 if ((distance < 0) || (Points->n_points < 2))
422 return 0;
423
424 /* Check if first or last */
425 length = Vect_line_length(Points);
426 G_debug(3, " length = %f", length);
427 if (distance < 0 || distance > length) {
428 G_debug(3, " -> outside line");
429 return 0;
430 }
431
432 np = Points->n_points;
433 if (distance == 0) {
434 G_debug(3, " -> first point");
435 xp = Points->x[0];
436 yp = Points->y[0];
437 zp = Points->z[0];
438 dx = Points->x[1] - Points->x[0];
439 dy = Points->y[1] - Points->y[0];
440 dz = Points->z[1] - Points->z[0];
441 dxy = hypot(dx, dy);
442 seg = 1;
443 }
444 else if (distance == length) {
445 G_debug(3, " -> last point");
446 xp = Points->x[np - 1];
447 yp = Points->y[np - 1];
448 zp = Points->z[np - 1];
449 dx = Points->x[np - 1] - Points->x[np - 2];
450 dy = Points->y[np - 1] - Points->y[np - 2];
451 dz = Points->z[np - 1] - Points->z[np - 2];
452 dxy = hypot(dx, dy);
453 seg = np - 1;
454 }
455 else {
456 for (j = 0; j < Points->n_points - 1; j++) {
457 /* dxyz = G_distance(Points->x[j], Points->y[j],
458 Points->x[j+1], Points->y[j+1]); */
459 dx = Points->x[j + 1] - Points->x[j];
460 dy = Points->y[j + 1] - Points->y[j];
461 dz = Points->z[j + 1] - Points->z[j];
462 dxy = hypot(dx, dy);
463 dxyz = hypot(dxy, dz);
464
465 dist += dxyz;
466 if (dist >= distance) { /* point is on the current line part */
467 rest = distance - dist +
468 dxyz; /* from first point of segment to point */
469 k = rest / dxyz;
470
471 xp = Points->x[j] + k * dx;
472 yp = Points->y[j] + k * dy;
473 zp = Points->z[j] + k * dz;
474 seg = j + 1;
475 break;
476 }
477 }
478 }
479
480 if (x != NULL)
481 *x = xp;
482 if (y != NULL)
483 *y = yp;
484 if (z != NULL)
485 *z = zp;
486
487 /* calculate angle */
488 if (angle != NULL)
489 *angle = atan2(dy, dx);
490
491 /* calculate slope */
492 if (slope != NULL)
493 *slope = atan2(dz, dxy);
494
495 return seg;
496}
497
498/*!
499 \brief Create line segment.
500
501 Creates segment of InPoints from start to end measured along the
502 line and write it to OutPoints.
503
504 If the distance is greater than line length or negative, error is
505 returned.
506
507 \param InPoints input line
508 \param start segment number
509 \param end segment number
510 \param OutPoints output line
511
512 \return 1 success
513 \return 0 error when start > length or end < 0 or start < 0 or end > length
514 */
515int Vect_line_segment(const struct line_pnts *InPoints, double start,
516 double end, struct line_pnts *OutPoints)
517{
518 int i, seg1, seg2;
519 double length, tmp;
520 double x1, y1, z1, x2, y2, z2;
521
522 G_debug(3, "Vect_line_segment(): start = %f, end = %f, n_points = %d",
523 start, end, InPoints->n_points);
524
526
527 if (start > end) {
528 tmp = start;
529 start = end;
530 end = tmp;
531 }
532
533 /* Check start/end */
534 if (end < 0)
535 return 0;
536 length = Vect_line_length(InPoints);
537 if (start > length)
538 return 0;
539
540 /* Find coordinates and segments of start/end */
541 seg1 = Vect_point_on_line(InPoints, start, &x1, &y1, &z1, NULL, NULL);
542 seg2 = Vect_point_on_line(InPoints, end, &x2, &y2, &z2, NULL, NULL);
543
544 G_debug(3, " -> seg1 = %d seg2 = %d", seg1, seg2);
545
546 if (seg1 == 0 || seg2 == 0) {
547 G_warning(_("Segment outside line, no segment created"));
548 return 0;
549 }
550
551 Vect_append_point(OutPoints, x1, y1, z1);
552
553 for (i = seg1; i < seg2; i++) {
555 InPoints->z[i]);
556 };
557
558 Vect_append_point(OutPoints, x2, y2, z2);
560
561 return 1;
562}
563
564/*!
565 \brief Calculate line length, 3D-length in case of 3D vector line
566
567 For Lat-Long use Vect_line_geodesic_length() instead.
568
569 \param Points pointer to line_pnts structure geometry
570
571 \return line length
572 */
573double Vect_line_length(const struct line_pnts *Points)
574{
575 int j;
576 double dx, dy, dz, len = 0;
577
578 if (Points->n_points < 2)
579 return 0;
580
581 for (j = 0; j < Points->n_points - 1; j++) {
582 dx = Points->x[j + 1] - Points->x[j];
583 dy = Points->y[j + 1] - Points->y[j];
584 dz = Points->z[j + 1] - Points->z[j];
585 len += hypot(hypot(dx, dy), dz);
586 }
587
588 return len;
589}
590
591/*!
592 \brief Calculate line length.
593
594 If projection is LL, the length is measured along the geodesic.
595
596 \param Points pointer to line_pnts structure geometry
597
598 \return line length
599 */
600double Vect_line_geodesic_length(const struct line_pnts *Points)
601{
602 int j, dc;
603 double dx, dy, dz, dxy, len = 0;
604
606
607 if (Points->n_points < 2)
608 return 0;
609
610 for (j = 0; j < Points->n_points - 1; j++) {
611 if (dc == 2)
612 dxy = G_geodesic_distance(Points->x[j], Points->y[j],
613 Points->x[j + 1], Points->y[j + 1]);
614 else {
615 dx = Points->x[j + 1] - Points->x[j];
616 dy = Points->y[j + 1] - Points->y[j];
617 dxy = hypot(dx, dy);
618 }
619
620 dz = Points->z[j + 1] - Points->z[j];
621 len += hypot(dxy, dz);
622 }
623
624 return len;
625}
626
627/*!
628 \brief Calculate distance of point to line.
629
630 Sets (if not null):
631 - px, py - point on line,
632 - dist - distance to line,
633 - spdist - distance to point on line from segment beginning,
634 - lpdist - distance to point on line from line beginning along line
635
636 \param points pointer to line_pnts structure
637 \param ux,uy,uz point coordinates
638 \param with_z flag if to use z coordinate (3D calculation)
639 \param[out] px,py,pz point on line
640 \param[out] dist distance to line
641 \param[out] spdist distance to point on line from segment beginning
642 \param[out] lpdist distance to point on line from line beginning along line
643
644 \return nearest segment (first is 1)
645 */
646int Vect_line_distance(const struct line_pnts *points, double ux, double uy,
647 double uz, int with_z, double *px, double *py,
648 double *pz, double *dist, double *spdist, double *lpdist)
649{
650 int i;
651 double distance;
652 double new_dist;
653 double tpx, tpy, tpz, tdist, tspdist, tlpdist = 0;
654 double dx, dy, dz;
655 int n_points;
656 int segment;
657
658 n_points = points->n_points;
659
660 if (n_points == 1) {
662 ux, uy, uz, points->x[0], points->y[0], points->z[0], points->x[0],
663 points->y[0], points->z[0], with_z, NULL, NULL, NULL, NULL, NULL);
664 tpx = points->x[0];
665 tpy = points->y[0];
666 tpz = points->z[0];
667 tdist = sqrt(distance);
668 tspdist = 0;
669 tlpdist = 0;
670 segment = 0;
671 }
672 else {
673
675 ux, uy, uz, points->x[0], points->y[0], points->z[0], points->x[1],
676 points->y[1], points->z[1], with_z, NULL, NULL, NULL, NULL, NULL);
677 segment = 1;
678
679 for (i = 1; i < n_points - 1; i++) {
681 ux, uy, uz, points->x[i], points->y[i], points->z[i],
682 points->x[i + 1], points->y[i + 1], points->z[i + 1], with_z,
683 NULL, NULL, NULL, NULL, NULL);
684 if (new_dist < distance) {
685 distance = new_dist;
686 segment = i + 1;
687 }
688 }
689
690 /* we have segment and now we can recalculate other values (speed) */
692 ux, uy, uz, points->x[segment - 1], points->y[segment - 1],
693 points->z[segment - 1], points->x[segment], points->y[segment],
694 points->z[segment], with_z, &tpx, &tpy, &tpz, &tspdist, NULL);
695
696 /* calculate distance from beginning of line */
697 if (lpdist) {
698 tlpdist = 0;
699 for (i = 0; i < segment - 1; i++) {
700 dx = points->x[i + 1] - points->x[i];
701 dy = points->y[i + 1] - points->y[i];
702 if (with_z)
703 dz = points->z[i + 1] - points->z[i];
704 else
705 dz = 0;
706
707 tlpdist += hypot(hypot(dx, dy), dz);
708 }
709 tlpdist += tspdist;
710 }
711 tdist = sqrt(distance);
712 }
713
714 if (px)
715 *px = tpx;
716 if (py)
717 *py = tpy;
718 if (pz && with_z)
719 *pz = tpz;
720 if (dist)
721 *dist = tdist;
722 if (spdist)
723 *spdist = tspdist;
724 if (lpdist)
725 *lpdist = tlpdist;
726
727 return (segment);
728}
729
730/*!
731 \brief Calculate geodesic distance of point to line in meters.
732
733 Sets (if not null):
734 - px, py - point on line,
735 - dist - distance to line,
736 - spdist - distance to point on line from segment beginning,
737 - lpdist - distance to point on line from line beginning along line
738
739 \param points pointer to line_pnts structure
740 \param ux,uy,uz point coordinates
741 \param with_z flag if to use z coordinate (3D calculation)
742 \param[out] px,py,pz point on line
743 \param[out] dist distance to line
744 \param[out] spdist distance to point on line from segment beginning
745 \param[out] lpdist distance to point on line from line beginning along line
746
747 \return nearest segment (first is 1)
748 */
749int Vect_line_geodesic_distance(const struct line_pnts *points, double ux,
750 double uy, double uz, int with_z, double *px,
751 double *py, double *pz, double *dist,
752 double *spdist, double *lpdist)
753{
754 int i;
755 double distance;
756 double new_dist;
757 double tpx, tpy, tpz, ttpx, ttpy, ttpz;
758 double tdist, tspdist, tlpdist = 0, tlpdistseg;
759 double dz;
760 int n_points;
761 int segment;
762
764
765 n_points = points->n_points;
766
767 if (n_points == 1) {
768 distance = G_distance(ux, uy, points->x[0], points->y[0]);
769 if (with_z)
770 distance = hypot(distance, uz - points->z[0]);
771
772 tpx = points->x[0];
773 tpy = points->y[0];
774 tpz = points->z[0];
775 tdist = distance;
776 tspdist = 0;
777 tlpdist = 0;
778 segment = 0;
779 }
780 else {
782 ux, uy, uz, points->x[0], points->y[0], points->z[0], points->x[1],
783 points->y[1], points->z[1], with_z, &tpx, &tpy, &tpz, NULL, NULL);
784
785 distance = G_distance(ux, uy, tpx, tpy);
786 if (with_z)
787 distance = hypot(distance, uz - tpz);
788
789 segment = 1;
790
791 for (i = 1; i < n_points - 1; i++) {
793 ux, uy, uz, points->x[i], points->y[i], points->z[i],
794 points->x[i + 1], points->y[i + 1], points->z[i + 1], with_z,
795 &ttpx, &ttpy, &ttpz, NULL, NULL);
796
798 if (with_z)
800
801 if (new_dist < distance) {
802 distance = new_dist;
803 segment = i + 1;
804 tpx = ttpx;
805 tpy = ttpy;
806 tpz = ttpz;
807 }
808 }
809
810 /* calculate distance from beginning of segment */
811 tspdist = G_distance(points->x[segment - 1], points->y[segment - 1],
812 tpx, tpy);
813 if (with_z) {
814 dz = points->z[segment - 1] - tpz;
815 tspdist += hypot(tspdist, dz);
816 }
817
818 /* calculate distance from beginning of line */
819 if (lpdist) {
820 tlpdist = 0;
821 for (i = 0; i < segment - 1; i++) {
822 tlpdistseg = G_distance(points->x[i], points->y[i],
823 points->x[i + 1], points->y[i + 1]);
824
825 if (with_z) {
826 dz = points->z[i + 1] - points->z[i];
828 }
829
831 }
832 tlpdist += tspdist;
833 }
834 tdist = distance;
835 }
836
837 if (px)
838 *px = tpx;
839 if (py)
840 *py = tpy;
841 if (pz && with_z)
842 *pz = tpz;
843 if (dist)
844 *dist = tdist;
845 if (spdist)
846 *spdist = tspdist;
847 if (lpdist)
848 *lpdist = tlpdist;
849
850 return (segment);
851}
852
853/*!
854 \brief Calculate distance of 2 points
855
856 Simply uses Pythagoras.
857
858 \param x1,y1,z1 first point
859 \param x2,y2,z2 second point
860 \param with_z use z coordinate
861
862 \return distance
863 */
864double Vect_points_distance(double x1, double y1, double z1, /* point 1 */
865 double x2, double y2, double z2, /* point 2 */
866 int with_z)
867{
868 double dx, dy, dz;
869
870 dx = x2 - x1;
871 dy = y2 - y1;
872 dz = z2 - z1;
873
874 if (with_z)
875 return hypot(hypot(dx, dy), dz);
876 else
877 return hypot(dx, dy);
878}
879
880/*!
881 \brief Get bounding box of line
882
883 \param Points pointer to line_pnts structure
884 \param[out] Box bounding box
885 */
886void Vect_line_box(const struct line_pnts *Points, struct bound_box *Box)
887{
888 dig_line_box(Points, Box);
889}
890
891/*!
892 \brief Reverse the order of vertices
893
894 \param Points pointer to line_pnts structure to be changed
895 */
896void Vect_line_reverse(struct line_pnts *Points)
897{
898 int i, j, np;
899 double x, y, z;
900
901 np = (int)Points->n_points / 2;
902
903 for (i = 0; i < np; i++) {
904 j = Points->n_points - i - 1;
905 x = Points->x[i];
906 y = Points->y[i];
907 z = Points->z[i];
908 Points->x[i] = Points->x[j];
909 Points->y[i] = Points->y[j];
910 Points->z[i] = Points->z[j];
911 Points->x[j] = x;
912 Points->y[j] = y;
913 Points->z[j] = z;
914 }
915}
916
917/*!
918 \brief Fetches FIRST category number for given vector line and field
919
920 \param Map pointer to Map_info structure
921 \param line line id
922 \param field layer number
923
924 \return -1 no category
925 \return category number (>=0)
926 */
927int Vect_get_line_cat(struct Map_info *Map, int line, int field)
928{
929
930 static struct line_cats *cats = NULL;
931 int cat, ltype;
932
933 if (cats == NULL)
934 cats = Vect_new_cats_struct();
935
936 ltype = Vect_read_line(Map, NULL, cats, line);
937 Vect_cat_get(cats, field, &cat);
938 G_debug(3, "Vect_get_line_cat: display line %d, ltype %d, cat %d", line,
939 ltype, cat);
940
941 return cat;
942}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
double G_geodesic_distance(double, double, double, double)
Calculates geodesic distance.
Definition geodist.c:195
double G_distance(double, double, double, double)
Returns distance in meters.
int G_debug(int, const char *,...) __attribute__((format(printf
int int G_begin_distance_calculations(void)
Begin distance calculations.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
#define GV_FORWARD
Line direction indicator forward/backward.
double dig_distance2_point_to_line(double, double, double, double, double, double, double, double, double, int, double *, double *, double *, double *, int *)
int dig_alloc_points(struct line_pnts *, int)
allocate room for 'num' X and Y arrays in struct line_pnts
int dig_prune(struct line_pnts *, double)
Definition prune.c:71
int dig_line_box(const struct line_pnts *, struct bound_box *)
#define _(str)
Definition glocale.h:10
float Box[8][3]
Vertices for box.
Definition gsd_objs.c:1451
int Vect_line_prune_thresh(struct line_pnts *Points, double threshold)
Remove points in threshold.
Definition line.c:307
int Vect_line_insert_point(struct line_pnts *Points, int index, double x, double y, double z)
Insert new point at index position and move all old points at that position and above up.
Definition line.c:174
int Vect_line_geodesic_distance(const struct line_pnts *points, double ux, double uy, double uz, int with_z, double *px, double *py, double *pz, double *dist, double *spdist, double *lpdist)
Calculate geodesic distance of point to line in meters.
Definition line.c:749
int Vect_line_segment(const struct line_pnts *InPoints, double start, double end, struct line_pnts *OutPoints)
Create line segment.
Definition line.c:515
double Vect_line_geodesic_length(const struct line_pnts *Points)
Calculate line length.
Definition line.c:600
int Vect_line_distance(const struct line_pnts *points, double ux, double uy, double uz, int with_z, double *px, double *py, double *pz, double *dist, double *spdist, double *lpdist)
Calculate distance of point to line.
Definition line.c:646
int Vect_copy_xyz_to_pnts(struct line_pnts *Points, const double *x, const double *y, const double *z, int n)
Copy points from array to line_pnts structure.
Definition line.c:97
void Vect_reset_line(struct line_pnts *Points)
Reset line.
Definition line.c:127
int Vect_line_delete_point(struct line_pnts *Points, int index)
Delete point at given index and move all points above down.
Definition line.c:208
int Vect_line_get_point(const struct line_pnts *Points, int index, double *x, double *y, double *z)
Get line point of given index.
Definition line.c:242
int Vect_get_num_line_points(const struct line_pnts *Points)
Get number of line points.
Definition line.c:265
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
Definition line.c:146
int Vect_point_on_line(const struct line_pnts *Points, double distance, double *x, double *y, double *z, double *angle, double *slope)
Find point on line in the specified distance.
Definition line.c:411
void Vect_destroy_line_struct(struct line_pnts *p)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:75
void Vect_line_box(const struct line_pnts *Points, struct bound_box *Box)
Get bounding box of line.
Definition line.c:886
void Vect_line_reverse(struct line_pnts *Points)
Reverse the order of vertices.
Definition line.c:896
int Vect_append_points(struct line_pnts *Points, const struct line_pnts *APoints, int direction)
Appends points to the end of a line.
Definition line.c:333
struct line_pnts * Vect__new_line_struct(void)
Creates and initializes a struct line_pnts (internal use only)
Definition line.c:53
double Vect_points_distance(double x1, double y1, double z1, double x2, double y2, double z2, int with_z)
Calculate distance of 2 points.
Definition line.c:864
double Vect_line_length(const struct line_pnts *Points)
Calculate line length, 3D-length in case of 3D vector line.
Definition line.c:573
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
int Vect_copy_pnts_to_xyz(const struct line_pnts *Points, double *x, double *y, double *z, int *n)
Copy points from line structure to array.
Definition line.c:378
int Vect_line_prune(struct line_pnts *Points)
Remove duplicate points, i.e. zero length segments.
Definition line.c:277
int Vect_get_line_cat(struct Map_info *Map, int line, int field)
Fetches FIRST category number for given vector line and field.
Definition line.c:927
void * malloc(unsigned)
Vector map info.
Bounding box.
Definition dig_structs.h:62
Feature category info.
int * field
Array of layers (fields)
int * cat
Array of categories.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
int alloc_points
Allocated space for points.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.