76static int cmp_cross(
const void *
pa,
const void *pb);
79static double dist2(
double x1,
double y1,
double x2,
double y2);
81static int debug_level = -1;
84static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh);
86static int cross_seg(
int id,
const struct RTree_Rect *rect,
void *
arg);
87static 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))
114 double *x1,
double *y1,
double *z1,
double *x2,
115 double *y2,
double *z2,
int with_z)
124 G_debug(4,
"Vect_segment_intersection()");
130 G_warning(
_(
"3D not supported by Vect_segment_intersection()"));
185 G_debug(2,
" -> identical segments");
240 G_debug(2,
"Vect_segment_intersection(): d = %f, d1 = %f, d2 = %f", d,
d1,
270 G_debug(2,
" -> not parallel/collinear: d1 = %f, d2 = %f",
d1,
d2);
276 " -> fp error, but intersection at end points %f, %f",
282 G_debug(2,
" -> no intersection");
293 " -> fp error, but intersection at end points %f, %f",
299 G_debug(2,
" -> no intersection");
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");
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");
362 G_debug(2,
" -> a contains b");
374 G_debug(2,
" -> b contains a");
386 G_debug(2,
" -> partial overlap");
412 "Vect_segment_intersection() ERROR (collinear vertical segments)"));
425 G_debug(2,
" -> collinear non vertical");
430 G_debug(2,
" -> no intersection");
435 G_debug(2,
" -> overlap/connected end points");
439 G_debug(2,
" -> connected by end points");
447 G_debug(2,
" -> connected by end points");
457 G_debug(2,
" -> a contains b");
469 G_debug(2,
" -> b contains a");
481 G_debug(2,
" -> partial overlap");
507 "Vect_segment_intersection() ERROR (collinear non vertical segments)"));
528static int a_cross = 0;
530static CROSS *cross =
NULL;
531static int *use_cross =
NULL;
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",
549 cross[n_cross].segment[0] =
asegment;
551 cross[n_cross].segment[1] =
bsegment;
553 cross[n_cross].x =
x;
554 cross[n_cross].y = y;
558static 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])
575static double dist2(
double x1,
double y1,
double x2,
double y2)
581 return (dx * dx + dy * dy);
586static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh)
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);
680 if (debug_level == -1) {
791 for (i = 0; i <
BPoints->n_points - 1; i++) {
834 for (i = 0; i <
APoints->n_points - 1; i++) {
876 G_debug(2,
"n_cross = %d", n_cross);
886 for (i = 0; i < n_cross; i++) {
889 seg = cross[i].segment[0];
895 cross[i].distance[0] =
curdist;
898 dist = dist2(cross[i].
x, cross[i].y,
APoints->x[seg + 1],
907 seg = cross[i].segment[1];
908 dist = dist2(cross[i].
x, cross[i].y,
BPoints->x[seg],
BPoints->y[seg]);
909 cross[i].distance[1] = dist;
917 dist = dist2(cross[i].
x, cross[i].y,
BPoints->x[seg + 1],
929 seg = cross[i].segment[0];
930 cross[i].distance[0] =
932 seg = cross[i].segment[1];
933 cross[i].distance[1] =
939 for (
l = 1;
l < 3;
l++) {
940 for (i = 0; i < n_cross; i++)
947 G_debug(2,
"Clean and create array for line A");
955 G_debug(2,
"Clean and create array for line B");
964 qsort((
void *)cross,
sizeof(
char) * n_cross,
sizeof(CROSS), cmp_cross);
968 if (debug_level > 2) {
969 for (i = 0; i < n_cross; i++) {
972 " cross = %d seg1/dist1 = %d/%f seg2/dist2 = %d/%f x = %f "
974 i, cross[i].segment[current],
975 sqrt(cross[i].distance[current]), cross[i].segment[second],
976 sqrt(cross[i].distance[second]), cross[i].
x, cross[i].y);
981 for (i = 0; i < n_cross; i++) {
982 if (use_cross[i] == 1) {
986 if ((cross[i].segment[current] == 0 &&
988 cross[i].y ==
Points1->y[0]) ||
989 (cross[i].segment[current] ==
j - 1 &&
993 G_debug(3,
"cross %d deleted (first/last point)", i);
1010 for (i = 0; i < n_cross; i++) {
1011 if (use_cross[i] == 0)
1013 G_debug(3,
" is %d between colinear?", i);
1015 seg1 = cross[i].segment[current];
1016 seg2 = cross[i].segment[second];
1028 G_debug(3,
" -> is not vertex on 1. line");
1045 G_debug(3,
" -> is not vertex on 2. line");
1066 G_debug(3,
" -> previous/next are not identical");
1072 G_debug(3,
" -> collinear -> remove");
1093 for (i = 0; i < n_cross; i++) {
1094 if (use_cross[i] == 0)
1100 seg = cross[i].segment[current];
1102 G_debug(3,
" duplicate ?: cross = %d seg = %d dist = %f", i,
1103 cross[i].segment[current], cross[i].distance[current]);
1104 if ((cross[i].segment[current] == cross[last].segment[current] &&
1105 cross[i].distance[current] == cross[last].distance[current]) ||
1106 (cross[i].segment[current] ==
1107 cross[last].segment[current] + 1 &&
1108 cross[i].distance[current] == 0 &&
1109 cross[i].
x == cross[last].
x && cross[i].y == cross[last].y)) {
1110 G_debug(3,
" cross %d identical to last -> removed", i);
1121 G_debug(3,
" alive crosses:");
1122 for (i = 0; i < n_cross; i++) {
1123 if (use_cross[i] == 1) {
1132 use_cross[n_cross] = 1;
1134 cross[n_cross].x = Points->
x[
j];
1135 cross[n_cross].y = Points->
y[
j];
1136 cross[n_cross].segment[current] = Points->
n_points - 2;
1144 for (i = 0; i <= n_cross; i++) {
1145 seg = cross[i].segment[current];
1146 G_debug(2,
"%d seg = %d dist = %f", i, seg,
1147 cross[i].distance[current]);
1148 if (use_cross[i] == 0) {
1149 G_debug(3,
" removed -> next");
1165 G_debug(2,
" -> skip (identical to last break)");
1170 G_debug(2,
" append first of seg: %f %f", Points->
x[
j],
1195 sqrt(cross[i].distance[current]) +
1197 (
sqrt(dist) -
sqrt(cross[i].distance[current]))) /
1203 G_debug(2,
" append cross / last point: %f %f", cross[i].
x,
1208 G_debug(2,
" line is degenerate -> skipped");
1231static struct line_pnts *APnts, *BPnts, *IPnts;
1233static int cross_found;
1234static int report_all;
1239 double x1, y1, z1, x2, y2, z2;
1248 APnts->x[i], APnts->y[i], APnts->z[i], APnts->x[i + 1], APnts->y[i + 1],
1249 APnts->z[i + 1], BPnts->x[
j], BPnts->y[
j], BPnts->z[
j], BPnts->x[
j + 1],
1250 BPnts->y[
j + 1], BPnts->z[
j + 1], &x1, &y1, &z1, &x2, &y2, &z2, 0);
1258 G_warning(
_(
"Error while adding point to array. Out of memory"));
1264 G_warning(
_(
"Error while adding point to array. Out of memory"));
1266 G_warning(
_(
"Error while adding point to array. Out of memory"));
1311 _(
"Error while adding point to array. Out of memory"));
1320 G_warning(
_(
"Error while adding point to array. Out of "
1342 _(
"Error while adding point to array. Out of memory"));
1359 _(
"Error while adding point to array. Out of memory"));
1376 for (i = 0; i <
BPoints->n_points - 1; i++) {
1412 for (i = 0; i <
APoints->n_points - 1; i++) {
1442 if (!report_all && cross_found) {
const char * G_getenv_nofatal(const char *)
Get environment variable.
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
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.
void Vect_reset_line(struct line_pnts *)
Reset line.
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
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)
Intersect 2 lines.
void RTreeSetOverflow(struct RTree *t, char overflow)
Enable/disable R*-tree forced reinsertion (overflow)
struct RTree * RTreeCreateTree(int fd, off_t rootpos, int ndims)
Create new empty R*-Tree.
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.