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);
87 double *
bdistance,
double *xc,
double *yc);
88static int cross_seg(
int i,
int j,
int b);
89static int find_cross(
int i,
int j,
int b);
103static int a_cross = 0;
105static CROSS *cross =
NULL;
106static int *use_cross =
NULL;
110static double d_ulp(
double a,
double b)
135 if (n_cross == a_cross) {
138 (CROSS *)
G_realloc((
void *)cross, (a_cross + 101) *
sizeof(CROSS));
140 (
int *)
G_realloc((
void *)use_cross, (a_cross + 101) *
sizeof(
int));
146 " add new cross: aseg/dist = %d/%f bseg/dist = %d/%f, x = %f y = %f",
148 cross[n_cross].segment[0] =
asegment;
150 cross[n_cross].segment[1] =
bsegment;
152 cross[n_cross].x =
x;
153 cross[n_cross].y = y;
157static int cmp_cross(
const void *
pa,
const void *pb)
159 CROSS *
p1 = (CROSS *)
pa;
160 CROSS *p2 = (CROSS *)pb;
162 if (
p1->segment[current] < p2->segment[current])
164 if (
p1->segment[current] > p2->segment[current])
167 if (
p1->distance[current] < p2->distance[current])
169 if (
p1->distance[current] > p2->distance[current])
174static double dist2(
double x1,
double y1,
double x2,
double y2)
180 return (dx * dx + dy * dy);
185static int ident(
double x1,
double y1,
double x2,
double y2,
double thresh)
200static struct line_pnts *APnts, *BPnts, *ABPnts[2], *IPnts;
205 double *
bdistance,
double *xc,
double *yc)
213 curdist = dist2(*xc, *yc, APnts->x[seg], APnts->y[seg]);
220 dist = dist2(*xc, *yc, APnts->x[seg + 1], APnts->y[seg + 1]);
223 x = APnts->x[seg + 1];
224 y = APnts->y[seg + 1];
229 dist = dist2(*xc, *yc, BPnts->x[seg], BPnts->y[seg]);
238 dist = dist2(*xc, *yc, BPnts->x[seg + 1], BPnts->y[seg + 1]);
241 x = BPnts->x[seg + 1];
242 y = BPnts->y[seg + 1];
259 *
adistance = dist2(*xc, *yc, APnts->x[seg], APnts->y[seg]);
261 *
bdistance = dist2(*xc, *yc, BPnts->x[seg], BPnts->y[seg]);
270static int cross_seg(
int i,
int j,
int b)
272 double x1, y1, z1, x2, y2, z2;
278 y1max = APnts->y[i + 1];
279 if (APnts->y[i] > APnts->y[i + 1]) {
280 y1min = APnts->y[i + 1];
286 if (BPnts->y[
j] > BPnts->y[
j + 1]) {
296 APnts->x[i], APnts->y[i], APnts->z[i], APnts->x[i + 1],
297 APnts->y[i + 1], APnts->z[i + 1], BPnts->x[
j], BPnts->y[
j],
298 BPnts->z[
j], BPnts->x[
j + 1], BPnts->y[
j + 1], BPnts->z[
j + 1], &x1,
299 &y1, &z1, &x2, &y2, &z2, 0);
303 BPnts->x[
j], BPnts->y[
j], BPnts->z[
j], BPnts->x[
j + 1],
304 BPnts->y[
j + 1], BPnts->z[
j + 1], APnts->x[i], APnts->y[i],
305 APnts->z[i], APnts->x[i + 1], APnts->y[i + 1], APnts->z[i + 1], &x1,
306 &y1, &z1, &x2, &y2, &z2, 0);
311 G_debug(2,
" -> %d x %d: intersection type = %d", i,
j,
ret);
313 G_debug(3,
" in %f, %f ", x1, y1);
320 else if (
ret == 2 ||
ret == 3 ||
ret == 4 ||
ret == 5) {
325 G_debug(3,
" in %f, %f; %f, %f", x1, y1, x2, y2);
344#define GET_PARENT(p, c) ((p) = (int)(((c) - 2) / 3 + 1))
345#define GET_CHILD(c, p) ((c) = (int)(((p) * 3) - 1))
362static int cmp_q_x(
struct qitem *a,
struct qitem *
b)
364 double x1, y1, z1, x2, y2, z2;
366 x1 = ABPnts[a->l]->x[a->p];
367 y1 = ABPnts[a->l]->y[a->p];
368 z1 = ABPnts[a->l]->z[a->p];
370 x2 = ABPnts[
b->l]->x[
b->p];
371 y2 = ABPnts[
b->l]->y[
b->p];
372 z2 = ABPnts[
b->l]->z[
b->p];
402static int sift_up(
struct boq *q,
int start)
404 register int parent, child;
415 if (cmp_q_x(&a,
b)) {
417 q->i[child] = q->i[parent];
433static int boq_add(
struct boq *q,
struct qitem *i)
435 if (q->count + 2 >= q->alloc) {
436 q->alloc = q->count + 100;
437 q->i =
G_realloc(q->i, q->alloc *
sizeof(
struct qitem));
439 q->i[q->count + 1] = *i;
440 sift_up(q, q->count + 1);
448static int boq_drop(
struct boq *q,
struct qitem *
qi)
450 register int child,
childr, parent;
469 while (
GET_CHILD(child, parent) <= q->count) {
481 q->i[parent] = q->i[child];
487 q->i[parent] = q->i[q->count];
502static int cmp_t_y(
const void *
aa,
const void *
bb)
504 double x1, y1, z1, x2, y2, z2;
505 struct qitem *a = (
struct qitem *)
aa;
506 struct qitem *
b = (
struct qitem *)
bb;
508 x1 = ABPnts[a->l]->x[a->p];
509 y1 = ABPnts[a->l]->y[a->p];
510 z1 = ABPnts[a->l]->z[a->p];
512 x2 = ABPnts[
b->l]->x[
b->p];
513 y2 = ABPnts[
b->l]->y[
b->p];
514 z2 = ABPnts[
b->l]->z[
b->p];
544 double x1, y1, z1, x2, y2, z2;
552 for (i = 0; i <
Pnts->n_points - 1; i++) {
561 if (x1 == x2 && y1 == y2 && (!with_z || z1 == z2))
588 box.W -= d_ulp(box.W, box.W);
589 box.S -= d_ulp(box.S, box.S);
590 box.B -= d_ulp(box.B, box.B);
591 box.E += d_ulp(box.E, box.E);
592 box.N += d_ulp(box.N, box.N);
593 box.T += d_ulp(box.T, box.T);
694 if (debug_level == -1) {
817 if (APnts->n_points < 2 || BPnts->n_points < 2) {
818 G_fatal_error(
"Intersection with points is not yet supported");
824 bo_queue.alloc = 2 * (APnts->n_points + BPnts->n_points);
892 G_debug(2,
"n_cross = %d", n_cross);
902 for (
l = 1;
l <
nl;
l++) {
903 for (i = 0; i < n_cross; i++)
910 G_debug(2,
"Clean and create array for line A");
918 G_debug(2,
"Clean and create array for line B");
927 qsort((
void *)cross,
sizeof(
char) * n_cross,
sizeof(CROSS), cmp_cross);
931 if (debug_level > 2) {
932 for (i = 0; i < n_cross; i++) {
935 " cross = %d seg1/dist1 = %d/%f seg2/dist2 = %d/%f x = %f "
937 i, cross[i].segment[current],
938 sqrt(cross[i].distance[current]), cross[i].segment[second],
939 sqrt(cross[i].distance[second]), cross[i].
x, cross[i].y);
944 for (i = 0; i < n_cross; i++) {
945 if (use_cross[i] == 1) {
949 if ((cross[i].segment[current] == 0 &&
951 cross[i].y ==
Points1->y[0]) ||
952 (cross[i].segment[current] ==
j - 1 &&
956 G_debug(3,
"cross %d deleted (first/last point)", i);
973 for (i = 0; i < n_cross; i++) {
974 if (use_cross[i] == 0)
976 G_debug(3,
" is %d between colinear?", i);
978 seg1 = cross[i].segment[current];
979 seg2 = cross[i].segment[second];
991 G_debug(3,
" -> is not vertex on 1. line");
1008 G_debug(3,
" -> is not vertex on 2. line");
1029 G_debug(3,
" -> previous/next are not identical");
1035 G_debug(3,
" -> collinear -> remove");
1056 for (i = 0; i < n_cross; i++) {
1057 if (use_cross[i] == 0)
1063 seg = cross[i].segment[current];
1065 G_debug(3,
" duplicate ?: cross = %d seg = %d dist = %f", i,
1066 cross[i].segment[current], cross[i].distance[current]);
1067 if ((cross[i].segment[current] == cross[last].segment[current] &&
1068 cross[i].distance[current] == cross[last].distance[current]) ||
1069 (cross[i].segment[current] ==
1070 cross[last].segment[current] + 1 &&
1071 cross[i].distance[current] == 0 &&
1072 cross[i].
x == cross[last].
x && cross[i].y == cross[last].y)) {
1073 G_debug(3,
" cross %d identical to last -> removed", i);
1084 G_debug(3,
" alive crosses:");
1085 for (i = 0; i < n_cross; i++) {
1086 if (use_cross[i] == 1) {
1095 use_cross[n_cross] = 1;
1097 cross[n_cross].x = Points->
x[
j];
1098 cross[n_cross].y = Points->
y[
j];
1099 cross[n_cross].segment[current] = Points->
n_points - 2;
1107 for (i = 0; i <= n_cross; i++) {
1108 seg = cross[i].segment[current];
1109 G_debug(2,
"%d seg = %d dist = %f", i, seg,
1110 cross[i].distance[current]);
1111 if (use_cross[i] == 0) {
1112 G_debug(3,
" removed -> next");
1128 G_debug(2,
" -> skip (identical to last break)");
1133 G_debug(2,
" append first of seg: %f %f", Points->
x[
j],
1158 sqrt(cross[i].distance[current]) +
1161 sqrt(cross[i].distance[current]))) /
1168 G_debug(2,
" append cross / last point: %f %f", cross[i].
x,
1173 G_debug(2,
" line is degenerate -> skipped");
1197static int find_cross(
int i,
int j,
int b)
1199 double x1, y1, z1, x2, y2, z2;
1203 y1min = APnts->y[i];
1204 y1max = APnts->y[i + 1];
1205 if (APnts->y[i] > APnts->y[i + 1]) {
1206 y1min = APnts->y[i + 1];
1207 y1max = APnts->y[i];
1212 if (BPnts->y[
j] > BPnts->y[
j + 1]) {
1222 APnts->x[i], APnts->y[i], APnts->z[i], APnts->x[i + 1],
1223 APnts->y[i + 1], APnts->z[i + 1], BPnts->x[
j], BPnts->y[
j],
1224 BPnts->z[
j], BPnts->x[
j + 1], BPnts->y[
j + 1], BPnts->z[
j + 1], &x1,
1225 &y1, &z1, &x2, &y2, &z2, 0);
1229 BPnts->x[
j], BPnts->y[
j], BPnts->z[
j], BPnts->x[
j + 1],
1230 BPnts->y[
j + 1], BPnts->z[
j + 1], APnts->x[i], APnts->y[i],
1231 APnts->z[i], APnts->x[i + 1], APnts->y[i + 1], APnts->z[i + 1], &x1,
1232 &y1, &z1, &x2, &y2, &z2, 0);
1245 G_warning(
_(
"Error while adding point to array. Out of memory"));
1251 G_warning(
_(
"Error while adding point to array. Out of memory"));
1253 G_warning(
_(
"Error while adding point to array. Out of memory"));
1292 _(
"Error while adding point to array. Out of memory"));
1300 G_warning(
_(
"Error while adding point to array. Out of "
1321 _(
"Error while adding point to array. Out of memory"));
1337 _(
"Error while adding point to array. Out of memory"));
1385 bo_queue.alloc = 2 * (APnts->n_points + BPnts->n_points);
1407 xa2 = APnts->x[APnts->n_points - 1];
1408 ya2 = APnts->y[APnts->n_points - 1];
1411 xb2 = BPnts->x[BPnts->n_points - 1];
1412 yb2 = BPnts->y[BPnts->n_points - 1];
1429 else if (intersect != 1) {
1431 xi = IPnts->x[IPnts->n_points - 1];
1432 yi = IPnts->y[IPnts->n_points - 1];
1448 if (intersect == 1) {
1467 else if (intersect != 1) {
1469 xi = IPnts->x[IPnts->n_points - 1];
1470 yi = IPnts->y[IPnts->n_points - 1];
1486 if (intersect == 1) {
1513 if (!
all && intersect == 1) {
const char * G_getenv_nofatal(const char *)
Get environment variable.
void G_free(void *)
Free allocated memory.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int rbtree_insert(struct RB_TREE *, void *)
int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *)
struct RB_TREE * rbtree_create(rb_compare_fn *, size_t)
int rbtree_remove(struct RB_TREE *, const void *)
void * rbtree_traverse(struct RB_TRAV *)
void rbtree_destroy(struct RB_TREE *)
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
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.
int Vect_segment_intersection(double, double, double, double, double, double, double, double, double, double, double, double, double *, double *, double *, double *, double *, double *, int)
Check for intersect of 2 line segments.
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.
#define PORT_DOUBLE_MAX
Limits for portable types.
int dig_line_degenerate(const struct line_pnts *)
int dig_line_box(const struct line_pnts *, struct bound_box *)
int Vect_line_check_intersection2(struct line_pnts *APoints, struct line_pnts *BPoints, int with_z)
Check if 2 lines intersect.
int line_check_intersection2(struct line_pnts *APoints, struct line_pnts *BPoints, int with_z, int all)
int Vect_line_get_intersections2(struct line_pnts *APoints, struct line_pnts *BPoints, struct line_pnts *IPoints, int with_z)
Get 2 lines intersection points.
int Vect_line_intersection2(struct line_pnts *APoints, struct line_pnts *BPoints, struct bound_box *pABox, struct bound_box *pBBox, struct line_pnts ***ALines, struct line_pnts ***BLines, int *nalines, int *nblines, int with_z)
Intersect 2 lines.
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.