74static int cmp_cross(
const void *
pa,
const void *pb);
77static double dist2(
double x1,
double y1,
double x2,
double y2);
79static int debug_level = -1;
82static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh);
84static int cross_seg(
int id,
const struct RTree_Rect *rect,
void *
arg);
85static int find_cross(
int id,
const struct RTree_Rect *rect,
void *
arg);
89#define D ((ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2))
90#define D1 ((bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2))
91#define D2 ((ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1))
112 double *x1,
double *y1,
double *z1,
double *x2,
113 double *y2,
double *z2,
int with_z)
122 G_debug(4,
"Vect_segment_intersection()");
128 G_warning(
_(
"3D not supported by Vect_segment_intersection()"));
183 G_debug(2,
" -> identical segments");
238 G_debug(2,
"Vect_segment_intersection(): d = %f, d1 = %f, d2 = %f", d,
d1,
268 G_debug(2,
" -> not parallel/collinear: d1 = %f, d2 = %f",
d1,
d2);
274 " -> fp error, but intersection at end points %f, %f",
280 G_debug(2,
" -> no intersection");
291 " -> fp error, but intersection at end points %f, %f",
297 G_debug(2,
" -> no intersection");
310 G_debug(2,
" -> intersection %f, %f", *x1, *y1);
315 G_debug(3,
" -> parallel/collinear");
320 G_debug(2,
"Segments are apparently parallel, but connected at end "
321 "points -> collinear");
332 G_debug(2,
" -> collinear vertical");
334 G_debug(2,
" -> no intersection");
340 G_debug(2,
" -> connected by end points");
348 G_debug(2,
" -> connected by end points");
357 G_debug(3,
" -> vertical overlap");
360 G_debug(2,
" -> a contains b");
372 G_debug(2,
" -> b contains a");
384 G_debug(2,
" -> partial overlap");
410 "Vect_segment_intersection() ERROR (collinear vertical segments)"));
423 G_debug(2,
" -> collinear non vertical");
428 G_debug(2,
" -> no intersection");
433 G_debug(2,
" -> overlap/connected end points");
437 G_debug(2,
" -> connected by end points");
445 G_debug(2,
" -> connected by end points");
455 G_debug(2,
" -> a contains b");
467 G_debug(2,
" -> b contains a");
479 G_debug(2,
" -> partial overlap");
505 "Vect_segment_intersection() ERROR (collinear non vertical segments)"));
526static int a_cross = 0;
528static CROSS *cross =
NULL;
529static int *use_cross =
NULL;
534 if (n_cross == a_cross) {
537 (CROSS *)
G_realloc((
void *)cross, (a_cross + 101) *
sizeof(CROSS));
539 (
int *)
G_realloc((
void *)use_cross, (a_cross + 101) *
sizeof(
int));
545 " add new cross: aseg/dist = %d/%f bseg/dist = %d/%f, x = %f y = %f",
547 cross[n_cross].segment[0] =
asegment;
549 cross[n_cross].segment[1] =
bsegment;
551 cross[n_cross].x =
x;
552 cross[n_cross].y = y;
556static int cmp_cross(
const void *
pa,
const void *pb)
558 CROSS *
p1 = (CROSS *)
pa;
559 CROSS *p2 = (CROSS *)pb;
561 if (
p1->segment[current] < p2->segment[current])
563 if (
p1->segment[current] > p2->segment[current])
566 if (
p1->distance[current] < p2->distance[current])
568 if (
p1->distance[current] > p2->distance[current])
573static double dist2(
double x1,
double y1,
double x2,
double y2)
579 return (dx * dx + dy * dy);
584static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh)
604 double x1, y1, z1, x2, y2, z2;
613 APnts->x[i], APnts->y[i], APnts->z[i], APnts->x[i + 1], APnts->y[i + 1],
614 APnts->z[i + 1], BPnts->x[
j], BPnts->y[
j], BPnts->z[
j], BPnts->x[
j + 1],
615 BPnts->y[
j + 1], BPnts->z[
j + 1], &x1, &y1, &z1, &x2, &y2, &z2, 0);
619 G_debug(2,
" -> %d x %d: intersection type = %d", i,
j,
ret);
621 G_debug(3,
" in %f, %f ", x1, y1);
622 add_cross(i, 0.0,
j, 0.0, x1, y1);
624 else if (
ret == 2 ||
ret == 3 ||
ret == 4 ||
ret == 5) {
629 G_debug(3,
" in %f, %f; %f, %f", x1, y1, x2, y2);
630 add_cross(i, 0.0,
j, 0.0, x1, y1);
631 add_cross(i, 0.0,
j, 0.0, x2, y2);
678 if (debug_level == -1) {
789 for (i = 0; i <
BPoints->n_points - 1; i++) {
832 for (i = 0; i <
APoints->n_points - 1; i++) {
874 G_debug(2,
"n_cross = %d", n_cross);
884 for (i = 0; i < n_cross; i++) {
887 seg = cross[i].segment[0];
893 cross[i].distance[0] =
curdist;
896 dist = dist2(cross[i].
x, cross[i].y,
APoints->x[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;
915 dist = dist2(cross[i].
x, cross[i].y,
BPoints->x[seg + 1],
927 seg = cross[i].segment[0];
928 cross[i].distance[0] =
930 seg = cross[i].segment[1];
931 cross[i].distance[1] =
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 &&
986 cross[i].y ==
Points1->y[0]) ||
987 (cross[i].segment[current] ==
j - 1 &&
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];
1026 G_debug(3,
" -> is not vertex on 1. line");
1043 G_debug(3,
" -> is not vertex on 2. line");
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) {
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;
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");
1163 G_debug(2,
" -> skip (identical to last break)");
1168 G_debug(2,
" append first of seg: %f %f", Points->
x[
j],
1193 sqrt(cross[i].distance[current]) +
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");
1229static struct line_pnts *APnts, *BPnts, *IPnts;
1231static int cross_found;
1232static int report_all;
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"));
1309 _(
"Error while adding point to array. Out of memory"));
1318 G_warning(
_(
"Error while adding point to array. Out of "
1340 _(
"Error while adding point to array. Out of memory"));
1357 _(
"Error while adding point to array. Out of memory"));
1374 for (i = 0; i <
BPoints->n_points - 1; i++) {
1410 for (i = 0; i <
APoints->n_points - 1; i++) {
1440 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 G_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.