Пример #1
0
Файл: area.c Проект: caomw/grass
/*!
   \brief Check if point is in area

   \param x,y point coordinates
   \param Map pointer to Map_info structure
   \param area area id
   \param box area bounding box

   \return 1 if point is in area
   \return 0 if not 
 */
int Vect_point_in_area(double x, double y, const struct Map_info *Map,
                       int area, struct bound_box *box)
{
    int i, isle;
    const struct Plus_head *Plus;
    struct P_area *Area;
    struct bound_box ibox;
    int poly;

    Plus = &(Map->plus);
    Area = Plus->Area[area];
    if (Area == NULL)
	return 0;

    poly = Vect_point_in_area_outer_ring(x, y, Map, area, box);
    if (poly == 0)
	return 0;		/* includes area boundary (poly == 2), OK? */

    /* check if in islands */
    for (i = 0; i < Area->n_isles; i++) {
	isle = Area->isles[i];
	Vect_get_isle_box(Map, isle, &ibox);
	poly = Vect_point_in_island(x, y, Map, isle, &ibox);
	if (poly >= 1)
	    return 0;		/* excludes island boundary (poly == 2), OK? */
    }

    return 1;
}
Пример #2
0
/* shortest distance between line and area
 * return 1 inside area 
 * return 2 inside isle of area 
 * return 3 outside area */
int line2area(const struct Map_info *To,
	      struct line_pnts *Points, int type,
	      int area, const struct bound_box *abox,
	      double *fx, double *fy, double *fz,
	      double *falong, double *fangle,
	      double *tx, double *ty, double *tz,
	      double *talong, double *tangle,
	      double *dist,
	      int with_z)
{
    int i, j;
    double tmp_dist;
    int isle, nisles;
    int all_inside_outer, all_outside_outer, all_outside_inner;
    static struct line_pnts *aPoints = NULL;
    static struct line_pnts **iPoints = NULL;
    static struct bound_box *ibox = NULL;
    static int isle_alloc = 0;

    if (!aPoints)
	aPoints = Vect_new_line_struct();

    *dist = PORT_DOUBLE_MAX;

    /* fangle and tangle are angles in radians, counter clockwise from x axis
     * initialize to invalid angle */
    *fangle = *tangle = -9.;
    *falong = *talong = 0.;

    *fx = Points->x[0];
    *fy = Points->y[0];
    *fz = Points->z[0];

    *tx = Points->x[0];
    *ty = Points->y[0];
    *tz = Points->z[0];

    Vect_get_area_points(To, area, aPoints);
    nisles = Vect_get_area_num_isles(To, area);
    
    if (nisles > isle_alloc) {
	iPoints = G_realloc(iPoints, nisles * sizeof(struct line_pnts *));
	ibox = G_realloc(ibox, nisles * sizeof(struct bound_box));
	for (i = isle_alloc; i < nisles; i++)
	    iPoints[i] = Vect_new_line_struct();
	isle_alloc = nisles;
    }
    for (i = 0; i < nisles; i++) {
	isle = Vect_get_area_isle(To, area, i);
	Vect_get_isle_points(To, isle, iPoints[i]);
	Vect_get_isle_box(To, isle, &ibox[i]);
    }

    /* inside area ? */
    all_inside_outer = all_outside_outer = 1;
    all_outside_inner = 1;

    int in_box;
    for (i = 0; i < Points->n_points; i++) {
        if (with_z)
            in_box = Vect_point_in_box(Points->x[i], Points->y[i],
                                       Points->z[i], abox);
        else
            in_box = Vect_point_in_box_2d(Points->x[i], Points->y[i], abox);
        if (in_box) {

	    int poly;
	    
	    poly = Vect_point_in_poly(Points->x[i], Points->y[i], aPoints);
	    
	    if (poly > 0) {
		/* inside outer ring */
		all_outside_outer = 0;
	    }
	    else {
		/* outside outer ring */
		all_inside_outer = 0;
	    }
	    
	    /* exactly on boundary */
	    if (poly == 2) {
		line2line(Points, type, aPoints, GV_BOUNDARY,
		          fx, fy, fz, falong, fangle,
		          tx, ty, tz, talong, tangle,
			  dist, with_z);

		*talong = 0;
		*tangle = -9;
		
		return 1;
	    }
	    /* inside outer ring */
	    else if (poly == 1) {
		int inside_isle = 0;

		for (j = 0; j < nisles; j++) {
                    if (with_z)
                        in_box = Vect_point_in_box(Points->x[i], Points->y[i],
                                                   Points->z[i], &ibox[j]);
                    else
                        in_box = Vect_point_in_box_2d(Points->x[i],
                                                      Points->y[i], &ibox[j]);
                    if (in_box) {

			poly = Vect_point_in_poly(Points->x[i], Points->y[i], iPoints[j]);
			
			/* inside or exactly on boundary */
			if (poly > 0) {
			    double tmp_fx, tmp_fy, tmp_fz, tmp_fangle, tmp_falong;
			    double tmp_tx, tmp_ty, tmp_tz, tmp_tangle, tmp_talong;

			    /* pass all points of the line, 
			     * this will catch an intersection */
			    line2line(Points, type, iPoints[j], GV_BOUNDARY,
				      &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
				      &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
				      &tmp_dist, with_z);

			    if (*dist > tmp_dist) {
				*dist = tmp_dist;

				*fx = tmp_fx;
				*fy = tmp_fy;
				*fz = tmp_fz;
				*falong = tmp_falong;
				*fangle = tmp_fangle;

				*tx = tmp_tx;
				*ty = tmp_ty;
				*tz = tmp_tz;
				*talong = 0;
				*tangle = tmp_tangle;
			    }

			    if (poly == 1) /* excludes isle boundary */
				inside_isle = 1;
			    
			}
		    }
		    if (*dist == 0)
			break;
		}
		/* inside area (inside outer ring, outside inner rings
		 * or exactly on one of the inner rings) */
		if (!inside_isle) {
		    *fx = Points->x[i];
		    *fy = Points->y[i];
		    *fz = Points->z[i];

		    *tx = Points->x[i];
		    *ty = Points->y[i];
		    *tz = Points->z[i];

		    *fangle = *tangle = -9.;
		    *falong = *talong = 0.;
		    
		    *dist = 0;

		    return 1;
		}
		else {
		    /* inside one of the islands */
		    all_outside_inner = 0;
		    if (*dist == 0) {
			/* the line intersected with the isle boundary
			 * -> line is partially inside the area */

			*fangle = *tangle = -9.;
			*falong = *talong = 0.;

			return 1;
		    }
		    /* else continue with next point */
		}
	    } /* end inside outer ring */
	}
	else {
	    /* point not in box of outer ring */
	    all_inside_outer = 0;
	}
	/* exactly on boundary */
	if (*dist == 0)
	    return 1;
    }
    
    /* if all points are inside the outer ring and inside inner rings,
     * there could still be an intersection with one of the inner rings */
     if (all_inside_outer) {
	 if (all_outside_inner) {
	     /* at least one point is really inside the area!
	      * that should have been detected above */
	     G_fatal_error(_("At least one point is really inside the area!"));
	 }
	 /* else all points are inside one of the area isles 
	  * and we already have the minimum distance */
	  return 2;
     }

    /* if at least one point was found to be inside the outer ring, 
     * but no point really inside the area,
     * and at least one point outside,
     * then there must be an intersection of the line with both 
     * the outer ring and one of the isle boundaries */

    /* if all line points are outside of the area,
     * intersection is still possible */

    line2line(Points, type, aPoints, GV_BOUNDARY,
	      fx, fy, fz, falong, fangle,
	      tx, ty, tz, talong, tangle,
	      dist, with_z);

    *talong = 0;

    if (*dist == 0)
	return 1;

    return 3;
}