23 #include <grass/Vect.h>
24 #include <grass/gis.h>
25 #include <grass/linkm.h>
26 #include <grass/glocale.h>
36 static int comp_double(
double *,
double *);
37 static int V__within(
double,
double,
double);
39 static void destroy_links(
struct link_head *,
struct Slink *);
40 static int Vect__divide_and_conquer(
struct Slink *,
struct line_pnts *,
41 struct link_head *,
double *,
double *,
63 static struct line_pnts *Points;
64 static struct line_pnts **IPoints;
65 static int first_time = 1;
66 static int isl_allocated = 0;
69 G_debug(3,
"Vect_get_point_in_area()");
77 if (n_isles > isl_allocated) {
78 IPoints = (
struct line_pnts **)
79 G_realloc(IPoints, (1 + n_isles) *
sizeof(
struct line_pnts *));
80 for (i = isl_allocated; i < n_isles; i++)
82 isl_allocated = n_isles;
88 for (i = 0; i < n_isles; i++) {
89 IPoints[i]->alloc_points = 0;
100 static int comp_double(
double *i,
double *j)
111 static int V__within(
double a,
double x,
double b)
121 return (x >= a && x <= b);
142 double y,
struct line_pnts *Inter)
145 double a,
b, c, d, x;
148 for (i = 1; i < Points->n_points; i++) {
149 a = Points->y[i - 1];
152 c = Points->x[i - 1];
155 if (V__within(a, y, b)) {
159 perc = (y - a) / (b - a);
160 x = perc * (d - c) + c;
182 double cent_x, cent_y;
184 static struct link_head *Token;
186 static int first_time = 1;
202 x_max = x_min = Points->x[0];
203 for (i = 0; i < Points->n_points; i++) {
204 if (x_min > Points->x[i])
205 x_min = Points->x[i];
206 if (x_max < Points->x[i])
207 x_max = Points->x[i];
229 ret = Vect__divide_and_conquer(Head, Points, Token, X, Y, 10);
231 destroy_links(Token, Head);
234 G_warning(
"Vect_get_point_in_poly(): %s",
235 _(
"Unable to find point in polygon"));
239 G_debug(3,
"Found point in %d iterations", 10 - ret);
267 Vect__divide_and_conquer(
struct Slink *Head,
268 struct line_pnts *Points,
269 struct link_head *Token,
270 double *
X,
double *
Y,
int levels)
274 G_debug(3,
"Vect__divide_and_conquer(): LEVEL %d", levels);
283 C->
x = (A->
x + B->
x) / 2.;
303 return Vect__divide_and_conquer(Head, Points, Token, X, Y, --levels);
306 static void destroy_links(
struct link_head *Token,
struct Slink *Head)
308 struct Slink *p, *tmp;
331 double *cent_x,
double *cent_y)
334 double *xptr1, *yptr1;
335 double *xptr2, *yptr2;
336 double cent_weight_x, cent_weight_y;
345 xptr2 = points->x + 1;
346 yptr2 = points->y + 1;
348 for (i = 1; i < points->n_points; i++) {
349 len = hypot(*xptr1 - *xptr2, *yptr1 - *yptr2);
350 cent_weight_x += len * ((*xptr1 + *xptr2) / 2.);
351 cent_weight_y += len * ((*yptr1 + *yptr2) / 2.);
362 *cent_x = cent_weight_x / tot_len;
363 *cent_y = cent_weight_y / tot_len;
425 struct line_pnts **IPoints,
int n_isles,
426 double *att_x,
double *att_y)
428 static struct line_pnts *Intersects;
429 static int first_time = 1;
430 double cent_x, cent_y;
432 double max, hi_y, lo_y;
434 int point_in_sles = 0;
437 G_debug(3,
"Vect_get_point_in_poly_isl(): n_isles = %d", n_isles);
444 if (Points->n_points < 3) {
445 if (Points->n_points > 0) {
446 *att_x = Points->x[0];
447 *att_y = Points->y[0];
459 for (i = 0; i < n_isles; i++) {
465 if (!point_in_sles) {
480 for (i = 0; i < Points->n_points; i++) {
481 if ((lo_y < cent_y) && (hi_y >= cent_y))
483 if (Points->y[i] < cent_y)
485 if (Points->y[i] >= cent_y)
489 for (i = 0; i < Points->n_points; i++) {
490 if ((Points->y[i] < cent_y) &&
491 ((cent_y - Points->y[i]) < (cent_y - lo_y)))
493 if ((Points->y[i] >= cent_y) &&
494 ((Points->y[i] - cent_y) < (hi_y - cent_y)))
497 for (i = 0; i < n_isles; i++)
498 for (j = 0; j < IPoints[i]->n_points; j++) {
499 if ((IPoints[i]->
y[j] < cent_y) &&
500 ((cent_y - IPoints[i]->
y[j]) < (cent_y - lo_y)))
501 lo_y = IPoints[i]->y[j];
503 if ((IPoints[i]->
y[j] >= cent_y) &&
504 ((IPoints[i]->
y[j] - cent_y) < (hi_y - cent_y)))
505 hi_y = IPoints[i]->y[j];
511 *att_y = (hi_y + lo_y) / 2.0;
513 Intersects->n_points = 0;
517 for (i = 0; i < n_isles; i++) {
523 if (Intersects->n_points < 2)
526 qsort(Intersects->x, (
size_t) Intersects->n_points,
sizeof(
double),
527 (
void *)comp_double);
533 for (i = 0; i < Intersects->n_points; i += 2) {
534 diff = Intersects->x[i + 1] - Intersects->x[i];
544 *att_x = (Intersects->x[maxpos] + Intersects->x[maxpos + 1]) / 2.;
554 static int segments_x_ray(
double X,
double Y,
struct line_pnts *Points)
556 double x1, x2, y1, y2;
561 G_debug(3,
"segments_x_ray(): x = %f y = %f n_points = %d", X, Y,
568 for (n = 0; n < Points->n_points - 1; n++) {
571 x2 = Points->x[n + 1];
572 y2 = Points->y[n + 1];
574 G_debug(3,
"X = %f Y = %f x1 = %f y1 = %f x2 = %f y2 = %f", X, Y, x1,
581 if (x1 < X && x2 < X)
585 if ((x1 == X && y1 == Y) || (x2 == X && y2 == Y))
589 if ((x1 == x2 && x1 == X) &&
590 ((y1 <= Y && y2 >= Y) || (y1 >= Y && y2 <= Y)))
594 if ((y1 == y2 && y1 == Y) &&
595 ((x1 <= X && x2 >= X) || (x1 >= X && x2 <= X)))
599 if (y1 == Y && y2 == Y)
603 if (y1 > Y && y2 > Y)
607 if (y1 < Y && y2 < Y)
611 if ((y1 == Y && y2 > Y) || (y2 == Y && y1 > Y))
617 if (y1 == Y && y2 < Y) {
622 if (y2 == Y && y1 < Y) {
629 if ((y1 < Y && y2 > Y) || (y1 > Y && y2 < Y)) {
630 if (x1 >= X && x2 >= X) {
637 G_debug(3,
"x_inter = %f", x_inter);
640 else if (x_inter > X)
648 (
"segments_x_ray() %s: X = %f Y = %f x1 = %f y1 = %f x2 = %f y2 = %f",
649 _(
"conditions failed"), X, Y, x1, y1, x2, y2);
669 G_debug(3,
"Vect_point_in_poly(): x = %f y = %f n_points = %d", X, Y,
672 n_intersects = segments_x_ray(X, Y, Points);
674 if (n_intersects == -1)
677 if (n_intersects % 2)
698 static int first = 1;
699 int n_intersects, inter;
701 static struct line_pnts *Points;
702 struct Plus_head *Plus;
706 G_debug(3,
"Vect_point_in_area_outer_ring(): x = %f y = %f area = %d", X,
715 Area = Plus->Area[area];
718 if (X < Area->W || X > Area->E || Y > Area->N || Y < Area->S)
722 for (i = 0; i < Area->n_lines; i++) {
723 line = abs(Area->lines[i]);
724 G_debug(3,
" line[%d] = %d", i, line);
726 Line = Plus->Line[line];
729 if ((Line->N < Y) || (Line->S > Y) || (Line->E < X))
734 inter = segments_x_ray(X, Y, Points);
735 G_debug(3,
" inter = %d", inter);
739 n_intersects += inter;
740 G_debug(3,
" n_intersects = %d", n_intersects);
743 if (n_intersects % 2)
762 static int first = 1;
763 int n_intersects, inter;
765 static struct line_pnts *Points;
766 struct Plus_head *Plus;
770 G_debug(3,
"Vect_point_in_island(): x = %f y = %f isle = %d", X, Y, isle);
778 Isle = Plus->Isle[isle];
780 if (X < Isle->W || X > Isle->E || Y > Isle->N || Y < Isle->S)
784 for (i = 0; i < Isle->n_lines; i++) {
785 line = abs(Isle->lines[i]);
787 Line = Plus->Line[line];
790 if ((Line->N < Y) || (Line->S > Y) || (Line->E < X))
795 inter = segments_x_ray(X, Y, Points);
798 n_intersects += inter;
801 if (n_intersects % 2)
double dig_x_intersect(double beg_x, double end_x, double beg_y, double end_y, double Y)
int Vect_get_isle_points(struct Map_info *Map, int isle, struct line_pnts *BPoints)
Returns the polygon array of points in BPoints.
struct link_head * link_init(int size)
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
struct link_head * link_new(struct link_head *Head)
int Vect_point_in_island(double X, double Y, struct Map_info *Map, int isle)
Determines if a point (X,Y) is inside an island.
int Vect__intersect_line_with_poly()
int Vect_get_area_num_isles(struct Map_info *Map, int area)
Returns number of isles for area.
int Vect_get_area_isle(struct Map_info *Map, int area, int isle)
Returns isle for area.
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
int Vect_get_area_points(struct Map_info *Map, int area, struct line_pnts *BPoints)
Returns the polygon array of points in BPoints.
int Vect_point_in_area_outer_ring(double X, double Y, struct Map_info *Map, int area)
Determines if a point (X,Y) is inside an area outer ring. Islands are not considered.
int Vect_get_point_in_poly_isl(struct line_pnts *Points, 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_find_poly_centroid(struct line_pnts *points, double *cent_x, double *cent_y)
Get centroid of polygon.
void link_exit_on_error(int flag)
void link_dispose(struct link_head *Head, VOID_T *ptr)
int Vect_point_in_poly(double X, double Y, struct line_pnts *Points)
Determines if a point (X,Y) is inside a polygon.
int Vect_get_point_in_area(struct Map_info *Map, int area, double *X, double *Y)
Get point inside area and outside all islands.
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.
int Vect_get_point_in_poly(struct line_pnts *Points, double *X, double *Y)
Get point inside polygon.