76 static int cmp_cross(
const void *pa,
const void *pb);
77 static void add_cross(
int asegment,
double adistance,
int bsegment,
78 double bdistance,
double x,
double y);
79 static double dist2(
double x1,
double y1,
double x2,
double y2);
81 static int debug_level = -1;
84 static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh);
86 static int cross_seg(
int id,
const struct RTree_Rect *rect,
void *arg);
87 static int find_cross(
int id,
const struct RTree_Rect *rect,
void *arg);
91 #define D ((ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2))
92 #define D1 ((bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2))
93 #define D2 ((ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1))
112 double ay2,
double az2,
double bx1,
double by1,
113 double bz1,
double bx2,
double by2,
double bz2,
114 double *x1,
double *y1,
double *z1,
double *x2,
115 double *y2,
double *z2,
int with_z)
117 static int first_3d = 1;
118 double d, d1, d2, r1, dtol,
t;
124 G_debug(4,
"Vect_segment_intersection()");
125 G_debug(4,
" %.15g , %.15g - %.15g , %.15g", ax1, ay1, ax2, ay2);
126 G_debug(4,
" %.15g , %.15g - %.15g , %.15g", bx1, by1, bx2, by2);
129 if (with_z && first_3d) {
130 G_warning(
_(
"3D not supported by Vect_segment_intersection()"));
146 else if (bx2 == bx1) {
166 else if (ax2 == ax1) {
184 if (ax1 == bx1 && ay1 == by1 && ax2 == bx2 && ay2 == by2) {
185 G_debug(2,
" -> identical segments");
200 else if (bx1 == ax1) {
203 else if (bx2 == ax2) {
206 else if (by1 == ay1) {
240 G_debug(2,
"Vect_segment_intersection(): d = %f, d1 = %f, d2 = %f", d, d1,
244 if (ax1 == bx1 && ay1 == by1) {
249 if (ax1 == bx2 && ay1 == by2) {
254 if (ax2 == bx1 && ay2 == by1) {
259 if (ax2 == bx2 && ay2 == by2) {
268 if (fabs(d) > dtol) {
270 G_debug(2,
" -> not parallel/collinear: d1 = %f, d2 = %f", d1, d2);
272 if (d1 < 0 || d1 > d || d2 < 0 || d2 > d) {
276 " -> fp error, but intersection at end points %f, %f",
282 G_debug(2,
" -> no intersection");
289 if (d1 < d || d1 > 0 || d2 < d || d2 > 0) {
293 " -> fp error, but intersection at end points %f, %f",
299 G_debug(2,
" -> no intersection");
308 *x1 = ax1 + r1 * (ax2 - ax1);
309 *y1 = ay1 + r1 * (ay2 - ay1);
312 G_debug(2,
" -> intersection %f, %f", *x1, *y1);
317 G_debug(3,
" -> parallel/collinear");
322 G_debug(2,
"Segments are apparently parallel, but connected at end "
323 "points -> collinear");
334 G_debug(2,
" -> collinear vertical");
335 if (ay1 > by2 || ay2 < by1) {
336 G_debug(2,
" -> no intersection");
342 G_debug(2,
" -> connected by end points");
350 G_debug(2,
" -> connected by end points");
359 G_debug(3,
" -> vertical overlap");
361 if (ay1 <= by1 && ay2 >= by2) {
362 G_debug(2,
" -> a contains b");
373 if (ay1 >= by1 && ay2 <= by2) {
374 G_debug(2,
" -> b contains a");
386 G_debug(2,
" -> partial overlap");
387 if (by1 > ay1 && by1 < ay2) {
398 if (by2 > ay1 && by2 < ay2) {
412 "Vect_segment_intersection() ERROR (collinear vertical segments)"));
425 G_debug(2,
" -> collinear non vertical");
428 if ((bx1 > ax2) || (bx2 < ax1)) {
430 G_debug(2,
" -> no intersection");
435 G_debug(2,
" -> overlap/connected end points");
438 if (ax1 == bx2 && ay1 == by2) {
439 G_debug(2,
" -> connected by end points");
446 if (ax2 == bx1 && ay2 == by1) {
447 G_debug(2,
" -> connected by end points");
456 if (ax1 <= bx1 && ax2 >= bx2) {
457 G_debug(2,
" -> a contains b");
468 if (ax1 >= bx1 && ax2 <= bx2) {
469 G_debug(2,
" -> b contains a");
481 G_debug(2,
" -> partial overlap");
482 if (bx1 > ax1 && bx1 < ax2) {
493 if (bx2 > ax1 && bx2 < ax2) {
507 "Vect_segment_intersection() ERROR (collinear non vertical segments)"));
528 static int a_cross = 0;
530 static CROSS *cross =
NULL;
531 static int *use_cross =
NULL;
533 static void add_cross(
int asegment,
double adistance,
int bsegment,
534 double bdistance,
double x,
double y)
536 if (n_cross == a_cross) {
539 (CROSS *)
G_realloc((
void *)cross, (a_cross + 101) *
sizeof(CROSS));
541 (
int *)
G_realloc((
void *)use_cross, (a_cross + 101) *
sizeof(
int));
547 " add new cross: aseg/dist = %d/%f bseg/dist = %d/%f, x = %f y = %f",
548 asegment, adistance, bsegment, bdistance,
x, y);
549 cross[n_cross].segment[0] = asegment;
550 cross[n_cross].distance[0] = adistance;
551 cross[n_cross].segment[1] = bsegment;
552 cross[n_cross].distance[1] = bdistance;
553 cross[n_cross].x =
x;
554 cross[n_cross].y = y;
558 static int cmp_cross(
const void *pa,
const void *pb)
560 CROSS *p1 = (CROSS *)pa;
561 CROSS *p2 = (CROSS *)pb;
563 if (p1->segment[current] < p2->segment[current])
565 if (p1->segment[current] > p2->segment[current])
568 if (p1->distance[current] < p2->distance[current])
570 if (p1->distance[current] > p2->distance[current])
575 static double dist2(
double x1,
double y1,
double x2,
double y2)
581 return (dx * dx + dy * dy);
586 static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh)
592 if ((dx * dx + dy * dy) <= thresh * thresh)
604 static int cross_seg(
int id,
const struct RTree_Rect *rect
UNUSED,
void *arg)
606 double x1, y1, z1, x2, y2, z2;
615 APnts->
x[i], APnts->
y[i], APnts->
z[i], APnts->
x[i + 1], APnts->
y[i + 1],
616 APnts->
z[i + 1], BPnts->
x[j], BPnts->
y[j], BPnts->
z[j], BPnts->
x[j + 1],
617 BPnts->
y[j + 1], BPnts->
z[j + 1], &x1, &y1, &z1, &x2, &y2, &z2, 0);
621 G_debug(2,
" -> %d x %d: intersection type = %d", i, j, ret);
623 G_debug(3,
" in %f, %f ", x1, y1);
624 add_cross(i, 0.0, j, 0.0, x1, y1);
626 else if (ret == 2 || ret == 3 || ret == 4 || ret == 5) {
631 G_debug(3,
" in %f, %f; %f, %f", x1, y1, x2, y2);
632 add_cross(i, 0.0, j, 0.0, x1, y1);
633 add_cross(i, 0.0, j, 0.0, x2, y2);
663 struct line_pnts ***BLines,
int *nalines,
664 int *nblines,
int with_z
UNUSED)
666 int i, j, k,
l, last_seg, seg, last;
668 double dist, curdist, last_x, last_y, last_z;
669 double x,
y, rethresh;
671 struct RTree *MyRTree;
673 int seg1, seg2, vert1, vert2;
675 static int rect_init = 0;
678 if (debug_level == -1) {
682 debug_level = atoi(dstr);
766 if (abbox.
N > ABox->
N)
768 if (abbox.
S < ABox->
S)
770 if (abbox.
E > ABox->
E)
772 if (abbox.
W < ABox->
W)
774 if (abbox.
T > ABox->
T)
776 if (abbox.
B < ABox->
B)
789 for (i = 0; i < BPoints->
n_points - 1; i++) {
790 if (BPoints->
x[i] <= BPoints->
x[i + 1]) {
799 if (BPoints->
y[i] <= BPoints->
y[i + 1]) {
808 if (BPoints->
z[i] <= BPoints->
z[i + 1]) {
832 for (i = 0; i < APoints->
n_points - 1; i++) {
833 if (APoints->
x[i] <= APoints->
x[i + 1]) {
842 if (APoints->
y[i] <= APoints->
y[i + 1]) {
850 if (APoints->
z[i] <= APoints->
z[i + 1]) {
874 G_debug(2,
"n_cross = %d", n_cross);
884 for (i = 0; i < n_cross; i++) {
887 seg = cross[i].segment[0];
889 dist2(cross[i].
x, cross[i].y, APoints->
x[seg], APoints->
y[seg]);
893 cross[i].distance[0] = curdist;
896 dist = dist2(cross[i].
x, cross[i].y, APoints->
x[seg + 1],
897 APoints->
y[seg + 1]);
898 if (dist < curdist) {
900 x = APoints->
x[seg + 1];
901 y = APoints->
y[seg + 1];
905 seg = cross[i].segment[1];
906 dist = dist2(cross[i].
x, cross[i].y, BPoints->
x[seg], BPoints->
y[seg]);
907 cross[i].distance[1] = dist;
909 if (dist < curdist) {
915 dist = dist2(cross[i].
x, cross[i].y, BPoints->
x[seg + 1],
916 BPoints->
y[seg + 1]);
917 if (dist < curdist) {
919 x = BPoints->
x[seg + 1];
920 y = BPoints->
y[seg + 1];
922 if (curdist < rethresh * rethresh) {
927 seg = cross[i].segment[0];
928 cross[i].distance[0] =
929 dist2(APoints->
x[seg], APoints->
y[seg], cross[i].x, cross[i].y);
930 seg = cross[i].segment[1];
931 cross[i].distance[1] =
932 dist2(BPoints->
x[seg], BPoints->
y[seg], cross[i].x, cross[i].y);
937 for (
l = 1;
l < 3;
l++) {
938 for (i = 0; i < n_cross; i++)
945 G_debug(2,
"Clean and create array for line A");
953 G_debug(2,
"Clean and create array for line B");
962 qsort((
void *)cross,
sizeof(
char) * n_cross,
sizeof(CROSS), cmp_cross);
966 if (debug_level > 2) {
967 for (i = 0; i < n_cross; i++) {
970 " cross = %d seg1/dist1 = %d/%f seg2/dist2 = %d/%f x = %f "
972 i, cross[i].segment[current],
973 sqrt(cross[i].distance[current]), cross[i].segment[second],
974 sqrt(cross[i].distance[second]), cross[i].
x, cross[i].y);
979 for (i = 0; i < n_cross; i++) {
980 if (use_cross[i] == 1) {
984 if ((cross[i].segment[current] == 0 &&
985 cross[i].
x == Points1->
x[0] &&
986 cross[i].y == Points1->
y[0]) ||
987 (cross[i].segment[current] == j - 1 &&
988 cross[i].x == Points1->
x[j] &&
989 cross[i].y == Points1->
y[j])) {
991 G_debug(3,
"cross %d deleted (first/last point)", i);
1008 for (i = 0; i < n_cross; i++) {
1009 if (use_cross[i] == 0)
1011 G_debug(3,
" is %d between colinear?", i);
1013 seg1 = cross[i].segment[current];
1014 seg2 = cross[i].segment[second];
1017 if (cross[i].
x == Points1->
x[seg1] &&
1018 cross[i].y == Points1->
y[seg1]) {
1021 else if (cross[i].
x == Points1->
x[seg1 + 1] &&
1022 cross[i].y == Points1->
y[seg1 + 1]) {
1026 G_debug(3,
" -> is not vertex on 1. line");
1034 if (cross[i].
x == Points2->
x[seg2] &&
1035 cross[i].y == Points2->
y[seg2]) {
1038 else if (cross[i].
x == Points2->
x[seg2 + 1] &&
1039 cross[i].y == Points2->
y[seg2 + 1]) {
1043 G_debug(3,
" -> is not vertex on 2. line");
1046 G_debug(3,
" seg1/vert1 = %d/%d seg2/ver2 = %d/%d", seg1, vert1,
1050 if (vert2 == 0 || vert2 == Points2->
n_points - 1) {
1051 G_debug(3,
" -> vertex 2 (%d) is first/last", vert2);
1056 if (!((Points1->
x[vert1 - 1] == Points2->
x[vert2 - 1] &&
1057 Points1->
y[vert1 - 1] == Points2->
y[vert2 - 1] &&
1058 Points1->
x[vert1 + 1] == Points2->
x[vert2 + 1] &&
1059 Points1->
y[vert1 + 1] == Points2->
y[vert2 + 1]) ||
1060 (Points1->
x[vert1 - 1] == Points2->
x[vert2 + 1] &&
1061 Points1->
y[vert1 - 1] == Points2->
y[vert2 + 1] &&
1062 Points1->
x[vert1 + 1] == Points2->
x[vert2 - 1] &&
1063 Points1->
y[vert1 + 1] == Points2->
y[vert2 - 1]))) {
1064 G_debug(3,
" -> previous/next are not identical");
1070 G_debug(3,
" -> collinear -> remove");
1091 for (i = 0; i < n_cross; i++) {
1092 if (use_cross[i] == 0)
1098 seg = cross[i].segment[current];
1100 G_debug(3,
" duplicate ?: cross = %d seg = %d dist = %f", i,
1101 cross[i].segment[current], cross[i].distance[current]);
1102 if ((cross[i].segment[current] == cross[last].segment[current] &&
1103 cross[i].distance[current] == cross[last].distance[current]) ||
1104 (cross[i].segment[current] ==
1105 cross[last].segment[current] + 1 &&
1106 cross[i].distance[current] == 0 &&
1107 cross[i].
x == cross[last].
x && cross[i].y == cross[last].y)) {
1108 G_debug(3,
" cross %d identical to last -> removed", i);
1119 G_debug(3,
" alive crosses:");
1120 for (i = 0; i < n_cross; i++) {
1121 if (use_cross[i] == 1) {
1128 if (n_alive_cross > 0) {
1130 use_cross[n_cross] = 1;
1132 cross[n_cross].x = Points->
x[j];
1133 cross[n_cross].y = Points->
y[j];
1134 cross[n_cross].segment[current] = Points->
n_points - 2;
1137 last_x = Points->
x[0];
1138 last_y = Points->
y[0];
1139 last_z = Points->
z[0];
1142 for (i = 0; i <= n_cross; i++) {
1143 seg = cross[i].segment[current];
1144 G_debug(2,
"%d seg = %d dist = %f", i, seg,
1145 cross[i].distance[current]);
1146 if (use_cross[i] == 0) {
1147 G_debug(3,
" removed -> next");
1155 G_debug(2,
" append last vert: %f %f", last_x, last_y);
1158 for (j = last_seg + 1; j <= seg; j++) {
1159 G_debug(2,
" segment j = %d", j);
1161 if ((j == last_seg + 1) && Points->
x[j] == last_x &&
1162 Points->
y[j] == last_y) {
1163 G_debug(2,
" -> skip (identical to last break)");
1168 G_debug(2,
" append first of seg: %f %f", Points->
x[j],
1173 last_x = cross[i].x;
1174 last_y = cross[i].y;
1177 if (Points->
z[last_seg] == Points->
z[last_seg + 1]) {
1178 last_z = Points->
z[last_seg + 1];
1180 else if (last_x == Points->
x[last_seg] &&
1181 last_y == Points->
y[last_seg]) {
1182 last_z = Points->
z[last_seg];
1184 else if (last_x == Points->
x[last_seg + 1] &&
1185 last_y == Points->
y[last_seg + 1]) {
1186 last_z = Points->
z[last_seg + 1];
1189 dist = dist2(Points->
x[last_seg], Points->
x[last_seg + 1],
1190 Points->
y[last_seg], Points->
y[last_seg + 1]);
1192 (Points->
z[last_seg] *
1193 sqrt(cross[i].distance[current]) +
1194 Points->
z[last_seg + 1] *
1195 (sqrt(dist) - sqrt(cross[i].distance[current]))) /
1201 G_debug(2,
" append cross / last point: %f %f", cross[i].
x,
1206 G_debug(2,
" line is degenerate -> skipped");
1229 static struct line_pnts *APnts, *BPnts, *IPnts;
1231 static int cross_found;
1232 static int report_all;
1235 static int find_cross(
int id,
const struct RTree_Rect *rect
UNUSED,
void *arg)
1237 double x1, y1, z1, x2, y2, z2;
1246 APnts->
x[i], APnts->
y[i], APnts->
z[i], APnts->
x[i + 1], APnts->
y[i + 1],
1247 APnts->
z[i + 1], BPnts->
x[j], BPnts->
y[j], BPnts->
z[j], BPnts->
x[j + 1],
1248 BPnts->
y[j + 1], BPnts->
z[j + 1], &x1, &y1, &z1, &x2, &y2, &z2, 0);
1256 G_warning(
_(
"Error while adding point to array. Out of memory"));
1262 G_warning(
_(
"Error while adding point to array. Out of memory"));
1264 G_warning(
_(
"Error while adding point to array. Out of memory"));
1280 double dist, rethresh;
1281 struct RTree *MyRTree;
1283 static int rect_init = 0;
1290 rethresh = 0.000001;
1303 if (APoints->
x[0] == BPoints->
x[0] && APoints->
y[0] == BPoints->
y[0]) {
1307 &APoints->
y[0],
NULL, 1))
1309 _(
"Error while adding point to array. Out of memory"));
1313 if (APoints->
z[0] == BPoints->
z[0]) {
1318 G_warning(
_(
"Error while adding point to array. Out of "
1335 if (dist <= rethresh) {
1340 _(
"Error while adding point to array. Out of memory"));
1352 if (dist <= rethresh) {
1357 _(
"Error while adding point to array. Out of memory"));
1374 for (i = 0; i < BPoints->
n_points - 1; i++) {
1375 if (BPoints->
x[i] <= BPoints->
x[i + 1]) {
1384 if (BPoints->
y[i] <= BPoints->
y[i + 1]) {
1393 if (BPoints->
z[i] <= BPoints->
z[i + 1]) {
1410 for (i = 0; i < APoints->
n_points - 1; i++) {
1411 if (APoints->
x[i] <= APoints->
x[i + 1]) {
1420 if (APoints->
y[i] <= APoints->
y[i + 1]) {
1428 if (APoints->
z[i] <= APoints->
z[i + 1]) {
1440 if (!report_all && cross_found) {
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_getenv_nofatal(const char *)
Get environment variable.
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
int Vect_copy_xyz_to_pnts(struct line_pnts *, const double *, const double *, const double *, int)
Copy points from array to line_pnts structure.
int Vect_line_distance(const struct line_pnts *, double, double, double, int, double *, double *, double *, double *, double *, double *)
Calculate distance of point to line.
int Vect_box_overlap(const struct bound_box *, const struct bound_box *)
Tests for overlap of two boxes.
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
void Vect_reset_line(struct line_pnts *)
Reset line.
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
int dig_line_degenerate(const struct line_pnts *)
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
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.
int line_check_intersection(struct line_pnts *APoints, struct line_pnts *BPoints, int with_z)
int Vect_line_check_intersection(struct line_pnts *APoints, struct line_pnts *BPoints, int with_z)
Check if 2 lines intersect.
int Vect_segment_intersection(double ax1, double ay1, double az1, double ax2, double ay2, double az2, double bx1, double by1, double bz1, double bx2, double by2, double bz2, double *x1, double *y1, double *z1, double *x2, double *y2, double *z2, int with_z)
Check for intersect of 2 line segments.
int Vect_line_get_intersections(struct line_pnts *APoints, struct line_pnts *BPoints, struct line_pnts *IPoints, int with_z)
Get 2 lines intersection points.
int Vect_line_intersection(struct line_pnts *APoints, struct line_pnts *BPoints, struct bound_box *ABox, struct bound_box *BBox, struct line_pnts ***ALines, struct line_pnts ***BLines, int *nalines, int *nblines, int with_z UNUSED)
Intersect 2 lines.
void RTreeSetOverflow(struct RTree *t, char overflow)
Enable/disable R*-tree forced reinsertion (overflow)
int RTreeInsertRect(struct RTree_Rect *r, int tid, struct RTree *t)
Insert an item into a R*-Tree.
void RTreeDestroyTree(struct RTree *t)
Destroy an R*-Tree.
int RTreeSearch(struct RTree *t, struct RTree_Rect *r, SearchHitCallback *shcb, void *cbarg)
Search an R*-Tree.
struct RTree * RTreeCreateTree(int fd, off_t rootpos, int ndims)
Create new empty R*-Tree.