SEXP point_in_polygon(SEXP px, SEXP py, SEXP polx, SEXP poly) { int i; PLOT_POINT p; POLYGON pol; SEXP ret; S_EVALUATOR pol.lines = LENGTH(polx); /* check later that first == last */ pol.p = (PLOT_POINT *) Calloc(pol.lines, PLOT_POINT); /* Calloc does error handling */ for (i = 0; i < LENGTH(polx); i++) { pol.p[i].x = NUMERIC_POINTER(polx)[i]; pol.p[i].y = NUMERIC_POINTER(poly)[i]; } pol.close = (pol.p[0].x == pol.p[pol.lines - 1].x && pol.p[0].y == pol.p[pol.lines - 1].y); setup_poly_minmax(&pol); PROTECT(ret = NEW_INTEGER(LENGTH(px))); for (i = 0; i < LENGTH(px); i++) { p.x = NUMERIC_POINTER(px)[i]; p.y = NUMERIC_POINTER(py)[i]; if ((p.x > pol.mbr.min.x) & (p.x <= pol.mbr.max.y) & (p.y > pol.mbr.min.y) & (p.y <= pol.mbr.max.y)) { INTEGER_POINTER(ret)[i] = InPoly(p, &pol); } else { INTEGER_POINTER(ret)[i] = 0; } } Free(pol.p); UNPROTECT(1); return(ret); }
SEXP R_point_in_polygon_sp(const SEXP px, const SEXP py, const SEXP polx, const SEXP poly) { int i, pc=0; PLOT_POINT p; POLYGON pol; SEXP ret, px1, py1, polx1, poly1; if (MAYBE_REFERENCED(px)) { PROTECT(px1 = duplicate(px)); pc++; } else px1 = px; if (MAYBE_REFERENCED(py)) { PROTECT(py1 = duplicate(py)); pc++; } else py1 = py; if (MAYBE_REFERENCED(polx)) { PROTECT(polx1 = duplicate(polx)); pc++; } else polx1 = polx; if (MAYBE_REFERENCED(poly)) { PROTECT(poly1 = duplicate(poly)); pc++; } else poly1 = poly; pol.lines = LENGTH(polx); /* check later that first == last */ pol.p = (PLOT_POINT *) R_alloc((size_t) pol.lines, sizeof(PLOT_POINT)); /* transient; will be freed by R; freed by R on user interrupt */ for (i = 0; i < LENGTH(polx); i++) { pol.p[i].x = NUMERIC_POINTER(polx)[i]; pol.p[i].y = NUMERIC_POINTER(poly)[i]; } pol.close = (pol.p[0].x == pol.p[pol.lines - 1].x && pol.p[0].y == pol.p[pol.lines - 1].y); setup_poly_minmax(&pol); PROTECT(ret = NEW_INTEGER(LENGTH(px))); pc++; for (i = 0; i < LENGTH(px); i++) { p.x = NUMERIC_POINTER(px)[i]; p.y = NUMERIC_POINTER(py)[i]; /* For each query point q, InPoly returns one of four char's: i : q is strictly interior to P o : q is strictly exterior to P v : q is a vertex of P e : q lies on the relative interior of an edge of P */ switch (InPoly(p, &pol)) { case 'i': INTEGER_POINTER(ret)[i] = 1; break; case 'o': INTEGER_POINTER(ret)[i] = 0; break; case 'v': INTEGER_POINTER(ret)[i] = 3; break; case 'e': INTEGER_POINTER(ret)[i] = 2; break; default: INTEGER_POINTER(ret)[i] = -1; break; } } UNPROTECT(pc); return(ret); }
SEXP point_in_polygon2(SEXP px, SEXP py, SEXP polx, SEXP poly, SEXP id, SEXP holes) { int i, j; PLOT_POINT p; POLYGON pol; SEXP ret, polxx, polyy; int isHole, nHoles, lastPart; int *hole, *tmp; PROTECT(px); PROTECT(py); PROTECT(id = coerceVector(id, INTSXP)); PROTECT(holes = coerceVector(holes, INTSXP)); PROTECT(polx = coerceVector(polx, VECSXP)); PROTECT(poly = coerceVector(poly, VECSXP)); PROTECT(ret = NEW_INTEGER(LENGTH(px))); tmp = (int *) malloc(LENGTH(px)*sizeof(double)); hole = (int *) malloc(LENGTH(px)*sizeof(int)); for (i = 0; i < LENGTH(ret); i++) { INTEGER_POINTER(ret)[i] = R_NaInt; hole[i] = 0; tmp[i] = R_NaInt; } lastPart = 0; nHoles = 0; int oldid = INTEGER_POINTER(id)[0]; int n = LENGTH(polx); for (i = 0; i < n; i++) { if (i == (n-1) ) { lastPart = 1; } else if ((INTEGER_POINTER(id)[i+1]) != oldid) { lastPart = 1; oldid = INTEGER_POINTER(id)[i+1]; } if (INTEGER_POINTER(holes)[i]) { isHole = 1; nHoles++; } else { isHole = 0; } polxx = VECTOR_ELT(polx, i); polyy = VECTOR_ELT(poly, i); pol.lines = LENGTH(polxx); /* check later that first == last */ pol.p = (PLOT_POINT *) Calloc(pol.lines, PLOT_POINT); /* Calloc does error handling */ for (j = 0; j < LENGTH(polxx); j++) { pol.p[j].x = NUMERIC_POINTER(polxx)[j]; pol.p[j].y = NUMERIC_POINTER(polyy)[j]; } pol.close = (pol.p[0].x == pol.p[pol.lines - 1].x && pol.p[0].y == pol.p[pol.lines - 1].y); // call error if pol.close = FALSE ? setup_poly_minmax(&pol); if (isHole) { for (j = 0; j < LENGTH(px); j++) { p.x = NUMERIC_POINTER(px)[j]; p.y = NUMERIC_POINTER(py)[j]; if ((p.x > pol.mbr.min.x) & (p.x <= pol.mbr.max.x) & (p.y > pol.mbr.min.y) & (p.y <= pol.mbr.max.y)) { if (InPoly(p, &pol)) { hole[j] = 1; } } } } else { for (j = 0; j < LENGTH(px); j++) { p.x = NUMERIC_POINTER(px)[j]; p.y = NUMERIC_POINTER(py)[j]; if ((p.x > pol.mbr.min.x) & (p.x <= pol.mbr.max.x) & (p.y > pol.mbr.min.y) & (p.y <= pol.mbr.max.y)) { if (InPoly(p, &pol)) { tmp[j] = INTEGER_POINTER(id)[i]; } } } } Free(pol.p); if (lastPart) { lastPart = 0; if (nHoles > 0) { nHoles = 0; for (j = 0; j < LENGTH(px); j++) { if ((tmp[j] != NA_INTEGER ) & (! hole[j])) { // Rprintf ("%s \n", "a"); INTEGER_POINTER(ret)[j] = tmp[j]; } tmp[j] = R_NaInt; hole[j] = 0; } } else { for (j = 0; j < LENGTH(px); j++) { if (NA_INTEGER != tmp[j]) { INTEGER_POINTER(ret)[j] = tmp[j]; tmp[i] = R_NaInt; } } } } } UNPROTECT(7); return(ret); }