58 #include <grass/Vect.h>
59 #include <grass/gis.h>
61 #define LENGTH(DX, DY) ( sqrt( (DX*DX)+(DY*DY) ) )
63 #define D_MULT 0.99999999
66 static void vect(
double x1,
double y1,
double x2,
double y2,
double *x,
90 static int find_cross(
struct line_pnts *Points,
int s1,
int s2,
int s3,
91 int s4,
int *s5,
int *s6)
93 int i, j, jstart, np, ret;
97 "find_cross(): npoints = %d, s1 = %d, s2 = %d, s3 = %d, s4 = %d",
98 Points->n_points, s1, s2, s3, s4);
102 np = Points->n_points;
104 for (i = s1; i <= s2; i++) {
105 jstart = i + 1 < s3 ? s3 : i + 1;
106 for (j = jstart; j <= s4; j++) {
112 x[j], y[j], x[j + 1], y[j + 1]);
114 if (ret == 1 && ((i - j) > 1 || (i - j) < -1)) {
117 G_debug(5,
" intersection: s5 = %d, s6 = %d", *s5, *s6);
123 G_debug(5,
" overlap: s5 = %d, s6 = %d", *s5, *s6);
128 G_debug(5,
"find_cross() -> no intersection");
140 static int find_cross_reverse(
struct line_pnts *Points,
int s1,
int s2,
int s3,
141 int s4,
int *s5,
int *s6)
143 int i, j, jend, np, ret;
147 "find_cross_reverse(): npoints = %d, s1 = %d, s2 = %d, s3 = %d, s4 = %d",
148 Points->n_points, s1, s2, s3, s4);
152 np = Points->n_points;
154 for (i = s1; i <= s2; i++) {
155 jend = i + 1 < s3 ? s3 : i + 1;
156 for (j = s4 - 1; j >= jend; j--) {
162 x[j], y[j], x[j + 1], y[j + 1]);
164 if (ret == 1 && ((i - j) > 1 || (i - j) < -1)) {
167 G_debug(5,
" intersection: s5 = %d, s6 = %d", *s5, *s6);
173 G_debug(5,
" overlap: s5 = %d, s6 = %d", *s5, *s6);
178 G_debug(5,
"find_cross_reverse() -> no intersection");
190 static int find_cross_from_start(
struct line_pnts *Points,
int s1,
int *s2,
191 double *ix,
double *iy)
193 int i, np, ret, found = 0;
194 double *x, *
y, min_dist, new_dist, new_x, new_y, dx, dy;
196 G_debug(5,
"find_cross_from_start(): npoints = %d, s1 = %d",
197 Points->n_points, s1);
201 np = Points->n_points;
203 min_dist = PORT_DOUBLE_MAX;
205 for (i = np - 2; i > s1; i--) {
208 x[i], y[i], x[i + 1], y[i + 1]);
212 y[i], x[i + 1], y[i + 1], &new_x, &new_y);
213 if ((new_x != x[s1] || new_y != y[s1]) &&
214 (new_x != x[s1 + 1] || new_y != y[s1 + 1])) {
218 new_dist =
LENGTH(dx, dy);
219 if (min_dist > new_dist) {
229 G_debug(5,
"find_cross_from_start(): intersection %s",
230 found ?
"found" :
"not found");
242 static int find_cross_from_end(
struct line_pnts *Points,
int s1,
int *s2,
243 double *ix,
double *iy)
245 int i, np, ret, found = 0;
246 double *x, *
y, min_dist, new_dist, new_x, new_y, dx, dy;
248 G_debug(5,
"find_cross_from_end(): npoints = %d, s1 = %d",
249 Points->n_points, s1);
253 np = Points->n_points;
255 min_dist = PORT_DOUBLE_MAX;
257 for (i = 0; i < s1; i++) {
260 x[i], y[i], x[i + 1], y[i + 1]);
264 y[i], x[i + 1], y[i + 1], &new_x, &new_y);
265 if ((new_x != x[s1] || new_y != y[s1]) &&
266 (new_x != x[s1 + 1] || new_y != y[s1 + 1])) {
268 dx = x[s1 + 1] - new_x;
269 dy = y[s1 + 1] - new_y;
270 new_dist =
LENGTH(dx, dy);
271 if (min_dist > new_dist) {
281 G_debug(5,
"find_cross_from_end(): intersection %s",
282 found ?
"found" :
"not found");
290 static int point_in_buf(
struct line_pnts *Points,
double px,
double py,
296 np = Points->n_points;
298 for (i = 0; i < np - 1; i++) {
300 Points->x[i], Points->y[i], 0,
301 Points->x[i + 1], Points->y[i + 1],
327 static void clean_parallel(
struct line_pnts *Points,
328 struct line_pnts *origPoints,
329 double d,
double tol,
int rm_end,
int close_loop)
331 int i, j, np, npn, sa, sb, ret, side;
333 int first = 0, current, last, lcount;
334 double *x, *
y, px, py, ix, iy;
335 static struct line_pnts *sPoints =
NULL;
336 double d2 = d * d *
D_MULT;
338 G_debug(4,
"clean_parallel(): npoints = %d, d = %f, rm_end = %d",
339 Points->n_points, d, rm_end);
344 np = Points->n_points;
358 for (i = Points->n_points - 1; i >= 1; i--) {
362 px = (x[i] + x[i - 1]) / 2;
363 py = (y[i] + y[i - 1]) / 2;
370 if (point_in_buf(origPoints, x[i], y[i], d2)) {
375 if (find_cross_from_end(Points, current, &sa, &ix, &iy) != 0) {
380 if ((ix == x[sa] && iy == y[sa]) ||
381 (ix == x[sa + 1] && iy == y[sa + 1])) {
385 Points->y[Points->n_points - 1], 0);
387 for (k = Points->n_points - 2; k > current + 1; k--) {
388 Points->x[k] = Points->x[k - 1];
389 Points->y[k] = Points->y[k - 1];
391 Points->x[current + 1] = ix;
392 Points->y[current + 1] = iy;
397 Points->y[Points->n_points - 1], 0);
399 Points->y[Points->n_points - 1], 0);
401 for (k = Points->n_points - 2; k > current + 2; k--) {
402 Points->x[k] = Points->x[k - 2];
403 Points->y[k] = Points->y[k - 2];
405 Points->x[current + 2] = ix;
406 Points->y[current + 2] = iy;
407 for (k = current + 1; k > sa + 1; k--) {
408 Points->x[k] = Points->x[k - 1];
409 Points->y[k] = Points->y[k - 1];
411 Points->x[sa + 1] = ix;
412 Points->y[sa + 1] = iy;
418 else if (point_in_buf(origPoints, px, py, d2)) {
432 Points->n_points -= j;
437 for (i = 0; i < Points->n_points - 1; i++) {
440 px = (x[i] + x[i + 1]) / 2;
441 py = (y[i] + y[i + 1]) / 2;
442 if (point_in_buf(origPoints, x[i], y[i], d2)) {
447 if (find_cross_from_start(Points, current, &sa, &ix, &iy) != 0) {
452 if ((ix == x[sa] && iy == y[sa]) ||
453 (ix == x[sa + 1] && iy == y[sa + 1])) {
457 Points->y[Points->n_points - 1], 0);
459 for (k = Points->n_points - 2; k > current + 1; k--) {
460 Points->x[k] = Points->x[k - 1];
461 Points->y[k] = Points->y[k - 1];
463 Points->x[current + 1] = ix;
464 Points->y[current + 1] = iy;
469 Points->y[Points->n_points - 1], 0);
471 Points->y[Points->n_points - 1], 0);
473 for (k = Points->n_points - 2; k > sa + 2; k--) {
474 Points->x[k] = Points->x[k - 2];
475 Points->y[k] = Points->y[k - 2];
477 Points->x[sa + 2] = ix;
478 Points->y[sa + 2] = iy;
479 for (k = sa + 1; k > current + 1; k--) {
480 Points->x[k] = Points->x[k - 1];
481 Points->y[k] = Points->y[k - 1];
483 Points->x[current + 1] = ix;
484 Points->y[current + 1] = iy;
489 else if (point_in_buf(origPoints, px, py, d2)) {
506 for (i = j; i < Points->n_points; i++) {
511 Points->n_points = npn;
517 np = Points->n_points;
518 if (np > 3 && (x[0] != x[np - 1] || y[0] != y[np - 1])) {
523 x[j], y[j], x[j + 1], y[j + 1]);
532 y[j], x[j + 1], y[j + 1], &ix, &iy);
547 np = Points->n_points;
550 side = (
int)(d / fabs(d));
553 while (np > 3 && first < np - 2) {
556 G_debug(5,
"current: %d", current);
557 last = Points->n_points - 2;
561 (Points, current, last - 1, current + 1, last, &sa, &sb) != 0) {
569 G_debug(5,
" current = %d, last = %d, lcount = %d", current,
586 if ((sb - sa) == 1) {
597 y[sb], x[sb + 1], y[sb + 1], &ix, &iy);
599 if (ix == x[0] && iy == y[0] && ix == x[np - 1] && iy == y[np - 1])
603 for (i = sa + 1; i < sb + 1; i++) {
612 in_buffer = area_size * side < 0;
613 if (!in_buffer && area_size) {
616 in_buffer = point_in_buf(origPoints, px, py, d2) != 0;
622 if (ix != x[sa] && iy != y[sa]) {
627 if (ix != x[sb + 1] && iy != y[sb + 1]) {
646 for (i = j; i < Points->n_points; i++) {
651 Points->n_points = np = npn;
657 if (origPoints->x[0] == origPoints->x[origPoints->n_points - 1] &&
658 origPoints->y[0] == origPoints->y[origPoints->n_points - 1] &&
660 double tx, ty, vx, vy, ux, uy, wx, wy, a, aw, av;
665 atol = 2 * acos(1 - tol / fabs(d));
667 side = (
int)(d / fabs(d));
669 xorg = origPoints->x;
670 yorg = origPoints->y;
672 np = origPoints->n_points;
675 vect(xorg[np - 2], yorg[np - 2], xorg[np - 1], yorg[np - 1], &tx, &ty);
679 vect(xorg[0], yorg[0], xorg[1], yorg[1], &ux, &uy);
684 a = (aw - av) * side;
689 G_debug(5,
"search intersection");
692 if (find_cross_reverse(Points, 0, Points->n_points - 2, 1, Points->n_points - 1, &sa,
694 G_debug(5,
"found intersection");
696 y[sb], x[sb + 1], y[sb + 1], &ix, &iy);
701 for (i = sa + 1; i <= sb; i++) {
706 Points->n_points = npn;
711 if (a <= PI && a > atol) {
716 na = (
int)(a / atol);
717 atol2 = a / (na + 1) * side;
718 for (j = 0; j < na; j++) {
720 nx = xorg[0] + fabs(d) * cos(av);
721 ny = yorg[0] + fabs(d) * sin(av);
741 static void parallel_line(
struct line_pnts *Points,
double d,
double tol,
742 struct line_pnts *nPoints)
744 int i, j, np, na, side;
745 double *x, *
y, nx, ny, tx, ty, vx, vy, ux, uy, wx, wy;
746 double atol, atol2, a, av, aw;
752 np = Points->n_points;
769 side = (
int)(d / fabs(d));
770 atol = 2 * acos(1 - tol / fabs(d));
772 for (i = 0; i < np - 1; i++) {
773 vect(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
786 vect(x[i + 1], y[i + 1], x[i + 2], y[i + 2], &ux, &uy);
791 a = (aw - av) * side;
796 if (a <= PI && a > atol) {
797 na = (
int)(a / atol);
798 atol2 = a / (na + 1) * side;
799 for (j = 0; j < na; j++) {
801 nx = x[i + 1] + fabs(d) * cos(av);
802 ny = y[i + 1] + fabs(d) * sin(av);
824 double tolerance,
int rm_end,
struct line_pnts *OutPoints)
827 "Vect_line_parallel(): npoints = %d, distance = %f, tolerance = %f",
828 InPoints->n_points, distance, tolerance);
830 parallel_line(InPoints, distance, tolerance, OutPoints);
831 G_debug(4,
"%d outpoints", OutPoints->n_points);
833 clean_parallel(OutPoints, InPoints, distance, tolerance, rm_end, 1);
834 G_debug(4,
"%d outpoints after cleaning", OutPoints->n_points);
852 double tolerance,
struct line_pnts *OutPoints)
856 static struct line_pnts *Points =
NULL;
857 static struct line_pnts *PPoints =
NULL;
858 double d2 = distance * distance *
D_MULT;
860 distance = fabs(distance);
862 dangle = 2 * acos(1 - tolerance / fabs(distance));
876 npoints = Points->n_points;
880 else if (npoints == 1) {
883 for (angle = 0; angle < 2 *
PI; angle += dangle) {
884 x = Points->x[0] + distance * cos(angle);
885 y = Points->y[0] + distance * sin(angle);
892 for (side = 0; side < 2; side++) {
893 double angle, sangle;
894 double lx1, ly1, lx2, ly2;
895 double x,
y, nx, ny, sx, sy, ex, ey;
902 parallel_line(InPoints, distance, tolerance, PPoints);
903 G_debug(4,
"%d outpoints", PPoints->n_points);
910 parallel_line(InPoints, -distance, tolerance, PPoints);
911 G_debug(4,
"%d outpoints", PPoints->n_points);
919 lx1 = Points->x[npoints - 2];
920 ly1 = Points->y[npoints - 2];
921 lx2 = Points->x[npoints - 1];
922 ly2 = Points->y[npoints - 1];
932 vect(lx1, ly1, lx2, ly2, &nx, &ny);
935 sangle = atan2(-nx, ny);
936 sx = lx2 + ny * distance;
937 sy = ly2 - nx * distance;
940 ex = lx2 - ny * distance;
941 ey = ly2 + nx * distance;
946 for (angle = dangle; angle <
PI; angle += dangle) {
947 x = lx2 + distance * cos(sangle + angle);
948 y = ly2 + distance * sin(sangle + angle);
958 if (OutPoints->x[0] == OutPoints->x[OutPoints->n_points - 1] &&
959 OutPoints->y[0] == OutPoints->y[OutPoints->n_points - 1])
960 OutPoints->n_points--;
962 clean_parallel(OutPoints, InPoints, distance, tolerance, 2, 0);
965 if (OutPoints->x[0] != OutPoints->x[OutPoints->n_points - 1] ||
966 OutPoints->y[0] != OutPoints->y[OutPoints->n_points - 1]) {
968 if (point_in_buf(InPoints, OutPoints->x[0], OutPoints->y[0], d2)) {
969 OutPoints->x[0] = OutPoints->x[OutPoints->n_points - 1];
970 OutPoints->y[0] = OutPoints->y[OutPoints->n_points - 1];
972 else if (point_in_buf(InPoints, OutPoints->x[OutPoints->n_points - 1],
973 OutPoints->y[OutPoints->n_points - 1], d2)) {
974 OutPoints->x[OutPoints->n_points - 1] = OutPoints->x[0];
975 OutPoints->y[OutPoints->n_points - 1] = OutPoints->y[0];
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
int dig_find_intersection(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2, double *x, double *y)
int Vect_append_points(struct line_pnts *Points, struct line_pnts *APoints, int direction)
Appends points to the end of a line.
int Vect_reset_line(struct line_pnts *Points)
Reset line.
double dig_distance2_point_to_line(double x, double y, double z, double x1, double y1, double z1, double x2, double y2, double z2, int with_z, double *px, double *py, double *pz, double *pdist, int *status)
void Vect_line_buffer(struct line_pnts *InPoints, double distance, double tolerance, struct line_pnts *OutPoints)
Create buffer around the line line.
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
int Vect_copy_xyz_to_pnts(struct line_pnts *Points, double *x, double *y, double *z, int n)
Copy points from array to line structure.
int Vect_find_poly_centroid(struct line_pnts *points, double *cent_x, double *cent_y)
Get centroid of polygon.
int dig_test_for_intersection(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2)
int Vect_line_prune(struct line_pnts *Points)
Remove duplicate points, i.e. zero length segments.
int G_debug(int level, const char *msg,...)
Print debugging message.
int dig_find_area_poly(struct line_pnts *Points, double *totalarea)
void Vect_line_parallel(struct line_pnts *InPoints, double distance, double tolerance, int rm_end, struct line_pnts *OutPoints)
Create parrallel line.