29 static int comp_double(
const void *,
const void *);
30 static int V__within(
double,
double,
double);
35 static void destroy_links(
struct link_head *,
struct Slink *);
36 static int Vect__divide_and_conquer(
struct Slink *,
const struct line_pnts *,
59 static int first_time = 1;
60 static int isl_allocated = 0;
63 G_debug(3,
"Vect_get_point_in_area()");
71 if (n_isles > isl_allocated) {
73 IPoints, (1 + n_isles) *
sizeof(
struct line_pnts *));
74 for (i = isl_allocated; i < n_isles; i++)
76 isl_allocated = n_isles;
82 for (i = 0; i < n_isles; i++) {
95 static int comp_double(
const void *i,
const void *j)
97 if (*(
const double *)i < *(
const double *)j)
100 return (*(
const double *)i > *(
const double *)j);
103 static int V__within(
double a,
double x,
double b)
106 return (
x >= a &&
x <
b);
108 return (
x >
b &&
x <= a);
130 double a,
b, c, d,
x;
133 for (i = 1; i < Points->
n_points; i++) {
134 a = Points->
y[i - 1];
137 c = Points->
x[i - 1];
140 if (V__within(a,
y,
b)) {
144 perc = (
y - a) / (
b - a);
145 x = perc * (d - c) + c;
173 double a,
b, c, d,
y;
176 for (i = 1; i < Points->
n_points; i++) {
177 a = Points->
x[i - 1];
180 c = Points->
y[i - 1];
183 if (V__within(a,
x,
b)) {
187 perc = (
x - a) / (
b - a);
188 y = perc * (d - c) + c;
210 double cent_x, cent_y;
214 static int first_time = 1;
229 G_debug(3,
"Vect_get_point_in_poly(): divide and conquer");
232 x_max = x_min = Points->
x[0];
233 for (i = 0; i < Points->
n_points; i++) {
234 if (x_min > Points->
x[i])
235 x_min = Points->
x[i];
236 if (x_max < Points->
x[i])
237 x_max = Points->
x[i];
248 Head = (
struct Slink *)
link_new(Token);
249 tmp = (
struct Slink *)
link_new(Token);
258 ret = Vect__divide_and_conquer(Head, Points, Token,
X,
Y, 10);
260 destroy_links(Token, Head);
263 G_warning(
"Vect_get_point_in_poly(): %s",
264 _(
"Unable to find point in polygon"));
268 G_debug(3,
"Found point in %d iterations", 10 - ret);
295 static int Vect__divide_and_conquer(
struct Slink *Head,
298 double *
Y,
int levels)
300 struct Slink *A, *B, *C;
302 G_debug(3,
"Vect__divide_and_conquer(): LEVEL %d", levels);
307 C = (
struct Slink *)
link_new(Token);
311 C->x = (A->x + B->x) / 2.;
330 return Vect__divide_and_conquer(Head, Points, Token,
X,
Y, --levels);
333 static void destroy_links(
struct link_head *Token,
struct Slink *Head)
335 struct Slink *p, *tmp;
359 double *xptr1, *yptr1;
360 double *xptr2, *yptr2;
361 double cent_weight_x, cent_weight_y;
370 xptr2 = points->
x + 1;
371 yptr2 = points->
y + 1;
374 for (i = 1; i < points->
n_points; i++) {
375 len = hypot(*xptr1 - *xptr2, *yptr1 - *yptr2);
376 cent_weight_x += len * ((*xptr1 + *xptr2) / 2.);
377 cent_weight_y += len * ((*yptr1 + *yptr2) / 2.);
388 *cent_x = cent_weight_x / tot_len;
389 *cent_y = cent_weight_y / tot_len;
450 const struct line_pnts **IPoints,
int n_isles,
451 double *att_x,
double *att_y)
454 static int first_time = 1;
455 double cent_x, cent_y;
457 double max, hi_x, lo_x, hi_y, lo_y;
461 int point_in_sles = 0;
465 G_debug(3,
"Vect_get_point_in_poly_isl(): n_isles = %d", n_isles);
474 *att_x = Points->
x[0];
475 *att_y = Points->
y[0];
486 for (i = 0; i < n_isles; i++) {
492 if (!point_in_sles) {
512 for (i = 0; i < Points->
n_points; i++) {
513 if ((lo_y < cent_y) && (hi_y >= cent_y) && (lo_x < cent_x) &&
516 if (Points->
y[i] < cent_y)
518 if (Points->
y[i] >= cent_y)
521 if (Points->
x[i] < cent_x)
523 if (Points->
x[i] >= cent_x)
527 for (i = 0; i < Points->
n_points; i++) {
528 if ((Points->
y[i] < cent_y) &&
529 ((cent_y - Points->
y[i]) < (cent_y - lo_y)))
531 if ((Points->
y[i] >= cent_y) &&
532 ((Points->
y[i] - cent_y) < (hi_y - cent_y)))
535 if ((Points->
x[i] < cent_x) &&
536 ((cent_x - Points->
x[i]) < (cent_x - lo_x)))
538 if ((Points->
x[i] >= cent_x) &&
539 ((Points->
x[i] - cent_x) < (hi_x - cent_x)))
542 for (i = 0; i < n_isles; i++) {
543 for (j = 0; j < IPoints[i]->
n_points; j++) {
544 if ((IPoints[i]->
y[j] < cent_y) &&
545 ((cent_y - IPoints[i]->
y[j]) < (cent_y - lo_y)))
546 lo_y = IPoints[i]->
y[j];
547 if ((IPoints[i]->
y[j] >= cent_y) &&
548 ((IPoints[i]->
y[j] - cent_y) < (hi_y - cent_y)))
549 hi_y = IPoints[i]->
y[j];
551 if ((IPoints[i]->
x[j] < cent_x) &&
552 ((cent_x - IPoints[i]->
x[j]) < (cent_x - lo_x)))
553 lo_x = IPoints[i]->
x[j];
554 if ((IPoints[i]->
x[j] >= cent_x) &&
555 ((IPoints[i]->
x[j] - cent_x) < (hi_x - cent_x)))
556 hi_x = IPoints[i]->
x[j];
563 *att_y = (hi_y + lo_y) / 2.0;
569 for (i = 0; i < n_isles; i++) {
578 qsort(Intersects->
x, (
size_t)Intersects->
n_points,
sizeof(
double),
585 for (i = 0; i < Intersects->
n_points; i += 2) {
586 diff = Intersects->
x[i + 1] - Intersects->
x[i];
596 fa = fabs(Intersects->
x[maxpos]);
597 fb = fabs(Intersects->
x[maxpos + 1]);
599 dmax = frexp(fa, &exp);
601 dmax = frexp(fb, &exp);
603 dmax = ldexp(dmax, exp);
606 *att_x = (Intersects->
x[maxpos] + Intersects->
x[maxpos + 1]) / 2.;
610 G_debug(3,
"Vect_get_point_in_poly_isl(): trying x intersect");
615 *att_x = (hi_x + lo_x) / 2.0;
621 for (i = 0; i < n_isles; i++) {
630 qsort(Intersects->
y, (
size_t)Intersects->
n_points,
sizeof(
double),
637 for (i = 0; i < Intersects->
n_points; i += 2) {
638 diff = Intersects->
y[i + 1] - Intersects->
y[i];
646 fa = fabs(Intersects->
y[maxpos]);
647 fb = fabs(Intersects->
y[maxpos + 1]);
649 dmax = frexp(fa, &exp);
651 dmax = frexp(fb, &exp);
653 dmax = ldexp(dmax, exp);
655 *att_y = (Intersects->
y[maxpos] + Intersects->
y[maxpos + 1]) / 2.;
659 G_warning(
"Vect_get_point_in_poly_isl(): collapsed area");
672 G_warning(
"Vect_get_point_in_poly_isl(), the hard way: centroid is on "
673 "outer ring, max dist is %g",
680 for (i = 0; i < n_isles; i++) {
683 G_warning(
"Vect_get_point_in_poly_isl(), the hard way: "
684 "centroid is in isle, max dist is %g",
689 if (!point_in_sles) {
701 static int segments_x_ray(
double X,
double Y,
const struct line_pnts *Points)
703 double x1, x2, y1, y2;
708 G_debug(3,
"segments_x_ray(): x = %f y = %f n_points = %d",
X,
Y,
716 for (n = 1; n < Points->
n_points; n++) {
717 x1 = Points->
x[n - 1];
718 y1 = Points->
y[n - 1];
735 if (y1 >
Y && y2 >
Y)
739 if (y1 <
Y && y2 <
Y)
743 if (x1 <
X && x2 <
X)
747 if ((x1 ==
X && y1 ==
Y) || (x2 ==
X && y2 ==
Y))
751 if (x1 == x2 && x1 ==
X) {
752 if ((y1 <= Y && y2 >=
Y) || (y1 >=
Y && y2 <=
Y))
757 if (y1 == y2 && y1 ==
Y) {
758 if ((x1 <= X && x2 >=
X) || (x1 >=
X && x2 <=
X))
769 if ((y1 ==
Y && y2 >
Y) || (y2 ==
Y && y1 >
Y))
775 if (y1 ==
Y && y2 <
Y) {
780 if (y2 ==
Y && y1 <
Y) {
787 if ((y1 < Y && y2 >
Y) || (y1 >
Y && y2 <
Y)) {
788 if (x1 >=
X && x2 >=
X) {
796 G_debug(3,
"x_inter = %f", x_inter);
799 else if (x_inter >
X)
806 G_warning(
"segments_x_ray() %s: X = %f Y = %f x1 = %f y1 = %f x2 = %f "
808 _(
"conditions failed"),
X,
Y, x1, y1, x2, y2);
828 G_debug(3,
"Vect_point_in_poly(): x = %f y = %f n_points = %d",
X,
Y,
831 n_intersects = segments_x_ray(
X,
Y, Points);
833 if (n_intersects == -1)
838 return (n_intersects & 1);
857 static int first = 1;
858 int n_intersects, inter;
866 G_debug(3,
"Vect_point_in_area_outer_ring(): x = %f y = %f area = %d",
X,
Y,
875 Area = Plus->
Area[area];
878 if (X < box->
W ||
X > box->
E ||
Y > box->
N || Y < box->S)
882 for (i = 0; i < Area->
n_lines; i++) {
883 line = abs(Area->
lines[i]);
900 inter = segments_x_ray(
X,
Y, Points);
903 n_intersects += inter;
908 return (n_intersects & 1);
926 static int first = 1;
927 int n_intersects, inter;
935 G_debug(3,
"Vect_point_in_island(): x = %f y = %f isle = %d",
X,
Y, isle);
943 Isle = Plus->
Isle[isle];
946 if (X < box->
W ||
X > box->
E ||
Y > box->
N || Y < box->S)
950 for (i = 0; i < Isle->
n_lines; i++) {
951 line = abs(Isle->
lines[i]);
968 inter = segments_x_ray(
X,
Y, Points);
971 n_intersects += inter;
976 return (n_intersects & 1);
int Vect_get_point_in_poly_isl(const struct line_pnts *Points, const struct line_pnts **IPoints, int n_isles, double *att_x, double *att_y)
Get point inside polygon but outside the islands specifiled in IPoints.
int Vect_point_in_poly(double X, double Y, const struct line_pnts *Points)
Determines if a point (X,Y) is inside a polygon.
int Vect_get_point_in_poly(const struct line_pnts *Points, double *X, double *Y)
Get point inside polygon.
int Vect_find_poly_centroid(const struct line_pnts *points, double *cent_x, double *cent_y)
Get centroid of polygon.
int Vect__intersect_x_line_with_poly(const struct line_pnts *, double, struct line_pnts *)
int Vect__intersect_y_line_with_poly(const struct line_pnts *, double, struct line_pnts *)
int Vect_point_in_island(double X, double Y, struct Map_info *Map, int isle, struct bound_box *box)
Determines if a point (X,Y) is inside an island.
int Vect_point_in_area_outer_ring(double X, double Y, struct Map_info *Map, int area, struct bound_box *box)
Determines if a point (X,Y) is inside an area outer ring. Islands are not considered.
int Vect_get_point_in_area(struct Map_info *Map, int area, double *X, double *Y)
Get point inside area and outside all islands.
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
struct link_head * link_init(int)
void link_dispose(struct link_head *, VOID_T *)
void link_exit_on_error(int)
VOID_T * link_new(struct link_head *)
int Vect_get_isle_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points for given isle.
int Vect_get_area_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
int Vect_get_area_isle(struct Map_info *, int, int)
Returns isle id for area.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int Vect_get_area_num_isles(struct Map_info *, int)
Returns number of isles for given area.
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.
double dig_x_intersect(double, double, double, double, double)
struct Plus_head plus
Plus info (topology, version, ...)
plus_t n_lines
Number of boundary lines.
plus_t * lines
List of boundary lines.
plus_t * lines
List of boundary lines.
plus_t n_lines
Number of boundary lines.
Basic topology-related info.
struct P_area ** Area
Array of areas.
struct P_isle ** Isle
Array of isles.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
int alloc_points
Allocated space for points.
double * x
Array of X coordinates.
int n_points
Number of points.