/* NB: MAKE SURE YOU EDIT THE TEMPLATE FILE!!!! */ #ifndef FILTER_PTYPE #include #endif #ifndef UNUSED #ifdef __GNUC__ # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define UNUSED(x) UNUSED_ ## x #endif #endif /* panda and pie incorrectly used astronomical angles. fixed 4/2004 */ #define USE_ASTRO_ANGLE 0 /* we might want to avoid (x86) extended precision problems */ #define USE_FPU_DOUBLE 0 #if USE_FPU_DOUBLE #include static fpu_control_t _cw; #define FPU_DOUBLE {fpu_control_t _cw2; _FPU_GETCW(_cw); _cw2 = _cw & ~_FPU_EXTENDED; _cw2 |= _FPU_DOUBLE; _FPU_SETCW(_cw2);} #define FPU_RESTORE {_FPU_SETCW(_cw);} #else #define FPU_DOUBLE #define FPU_RESTORE #endif /* add to FilterOpen to cause this module to be loaded for dynamic linking */ static int imregno=0; void initimregions(void) { imregno++; return; } static void markx(GFilt g, int UNUSED(sno), int flag, int type, int x, int y) { /* don't mark exclude regions */ if( type == TOK_EREG ) return; /* for include, we might extend the x limits */ if( flag ){ if( x <= g->x0s[y] ) g->x0s[y] = max(x,g->x0); if( x >= g->x1s[y] ) g->x1s[y] = min(x,g->x1); } /* for exclude, we have to look at the full line */ else{ g->x0s[y] = g->x0; g->x1s[y] = g->x1; } } static void marky(GFilt g, int sno, int flag, int type) { int i; /* don't mark exclude regions */ if( type == TOK_EREG ) return; /* mark include shape */ if( flag ){ for(i=max(g->y0,g->shapes[sno].ystart); i<=min(g->y1,g->shapes[sno].ystop); i++) g->ybuf[i] = 1; } /* mark exclude shape */ else{ for(i=g->y0; i<=g->shapes[sno].ystart-1; i++) g->ybuf[i] = 1; for(i=g->shapes[sno].ystop+1; i<=g->y1; i++) g->ybuf[i] = 1; } } static int imagemaskcmp(const void *s1, const void *s2) { FilterMask f1 = (FilterMask)s1; FilterMask f2 = (FilterMask)s2; if( f1->y < f2->y ){ return -1; } else if( f1->y > f2->y ){ return 1; } else{ if( f1->xstart < f2->xstart ){ return -1; } else{ return 1; } } } /* ***************************** shape support ***************************** */ static void quadeq(double a, double b, double c, double *x1, double *x2, int *nr, int *nc) { double dis, q; if( feq(a,0.0) ){ *nc = 0; if( feq(b,0.0) ){ *nr = 0; *x1 = 0.0; } else{ *nr = 1; *x1 = -c / b; } *x2 = *x1; } else{ dis = b*b - 4.0 * a * c; if( dis > 0.0 ){ *nr = 2; *nc = 0; dis = sqrt(dis); if( b < 0.0 ) dis = -dis; q = -0.5 * (b + dis); *x1 = q/a; *x2 = c/q; if(*x1 > *x2){ q = *x1; *x1 = *x2; *x2 = q; } } else if( feq(dis,0.0) ){ *nr = 1; *nc = 0; *x1 = - 0.5 * b / a; *x2 = *x1; } else{ *nr = 0; *nc = 2; *x1 = - 0.5 * b / a; *x2 = 0.5 * sqrt(-dis) / a; } } } static void rgs_mark(GFilt g, Scan *scanlist, int sno, int flag, int type, int xval, int yval ) { Scan scanmark, mark; /* since yval is used as an index, make sure its within limits */ if(yval < g->y0) yval = g->y0; if(yval > g->y1) yval = g->y1; mark = (Scan)calloc(1, sizeof(ScanRec)); mark->x = xval; /* sanity check */ if( !scanlist ) return; /* starts are installed at back of list for given x */ if( !scanlist[yval] || ((scanlist[yval])->x > xval) ){ mark->next = scanlist[yval]; scanlist[yval] = mark; } else { scanmark = scanlist[yval]; while( scanmark->next && ((scanmark->next)->x < xval) ) scanmark = scanmark->next; mark->next = scanmark->next; scanmark->next = mark; } markx(g, sno, flag, type, xval, yval); } static void rgs_segment(GFilt g, Scan *scanlist, int width, int height, int sno, int flag, int type, double x1, double y1, double x2, double y2) { int ystart, ystop, yval, xval; double invslope, xoffset; ystart = PIXINCL(y1); if( ystart < 1 ) ystart = 1; /* note: PIXINCL(stop) is 1st pixel not counted */ ystop = PIXINCL(y2) - 1; if( ystop > height ) ystop = height; /* ignore segment if there is no positive slope in integer coords */ if( (ystart > ystop) || (ystop < 1) ) return; /* use inverse slope (run/rise) to get x given y with a multiply */ invslope = (x1 - x2) / (y1 - y2); xoffset = x1 + ((ystart - y1) * invslope); for(yval=ystart; yval<=ystop; yval++){ xval = PIXINCL(xoffset); /* clip line to edges of image area (actually bend line) */ if(xval < 1) xval = 1; if(xval > width) xval = width + 1; rgs_mark(g, scanlist, sno, flag, type, xval, yval); xoffset = xoffset + invslope; } } static void _polygoni(GFilt g, int qt, int UNUSED(rno), int sno, int flag, int type, double *vx, double *vy, int count) { int i, j; double xlo, xhi; double ylo, yhi; #ifdef ALREADY_DONE /* divide by block factor to get real endpoints */ for(i=0; ixmin)/g->block + 1.0; vy[i] = (vy[i] - g->ymin)/g->block + 1.0; } #endif /* find the limits */ xlo = vx[0]; xhi = xlo; ylo = vy[0]; yhi = ylo; for(i=0; i xhi) xhi = vx[i]; if(vx[i] < xlo) xlo = vx[i]; if(vy[i] > yhi) yhi = vy[i]; if(vy[i] < ylo) ylo = vy[i]; } if( qt && (sno > 1) ){ g->shapes[sno].ystart = g->shapes[sno-1].ystart; g->shapes[sno].ystop = g->shapes[sno-1].ystop; } else{ g->shapes[sno].ystart = max(g->y0,PIXINCL(ylo)); g->shapes[sno].ystop = min(g->y1,PIXINCL(yhi) - 1); } g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); marky(g, sno, flag, type); /* mark all horizontal segment crossings */ /* start with segment between last and first point */ j = count-1; for(i=0; i vy[j]){ rgs_segment(g, g->shapes[sno].scanlist, g->x1, g->y1, sno, flag, type, vx[j], vy[j], vx[i], vy[i]); } else{ rgs_segment(g, g->shapes[sno].scanlist, g->x1, g->y1, sno, flag, type, vx[i], vy[i], vx[j], vy[j]); } j = i; } } static int corner_vertex(int index, int width, int height, double *x, double *y) { switch (index) { case 1: *x = 0.0; *y = height + 1; break; case 2: *x = 0.0; *y = 0.0; break; case 3: *x = width + 1; *y = 0.0; break; case 4: *x = width + 1; *y = height + 1; default: break; } index = index + 1; if(index > 4) index = 1; return(index); } static int pie_intercept(int width, int height, double xcen, double ycen, double angle, double *xcept, double *ycept) { double angl, slope; /* l: angle and slope of ray */ angl = angle; /* put angles in normal range */ while (angl < 0.0) angl = angl + 360.0; while (angl >= 360.0) angl = angl - 360.0; /* check for a horizontal angle */ #if USE_ASTRO_ANGLE if(fabs(angl - 90.0) < SMALL_NUMBER) { #else if(fabs(angl - 180.0) < SMALL_NUMBER) { #endif *xcept = 0.0; *ycept = ycen; return(2); } #if USE_ASTRO_ANGLE if(fabs(angl - 270.0) < SMALL_NUMBER) { #else if(fabs(angl - 0.0) < SMALL_NUMBER) { #endif *xcept = width + 1; *ycept = ycen; return(4); } #if USE_ASTRO_ANGLE /* convert to a Cartesian angle */ angl = angl + 90.0; #endif if(angl >= 360.0) angl = angl - 360.0; if(angl < 180.0) { *ycept = height + 1; /* rule out vertical line */ if(fabs(angl - 90.0) < SMALL_NUMBER) { *xcept = xcen; return(1); } } else { *ycept = 0.0; /* rule out vertical line */ if(fabs(angl - 270.0) < SMALL_NUMBER) { *xcept = xcen; return(3); } } /* convert to radians */ angl = (angl / 180.0) * M_PI; /* calculate slope */ slope = tan(angl); /* calculate intercept with designated y edge */ *xcept = xcen + ((*ycept - ycen) / slope); if(*xcept < 0) { *ycept = (ycen - (xcen * slope)); *xcept = 0.0; return(2); } else if(*xcept > (width + 1)) { *ycept = (ycen + ((width + 1 - xcen) * slope)); *xcept = width + 1; return(4); } else { if(*ycept < height) return(3); else return(1); } } void _impiei(GFilt g, int qt, int rno, int sno, int flag, int type, double UNUSED(x), double UNUSED(y), double xcen, double ycen, double angle1, double angle2) { int width, height; /* l: image mask width and height */ double sweep; /* l: sweep between cut angles */ double vx[7], vy[7]; /* l: arrays of vertices for polygon */ int count; /* l: number of polygon vertices */ int intrcpt1, intrcpt2; /* l: side intercepted by each cut */ double x2, y2; /* l: coordinates of second intercept */ /* NB: do not use x and y variables, they have bogus values */ /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; /* temps */ width = g->x1; height = g->y1; /* start listing vertices of polygon */ vx[0] = xcen; vy[0] = ycen; sweep = angle2 - angle1; /* if sweep is too small to be noticed, don't bother */ if(fabs(sweep) < SMALL_NUMBER) return; if (sweep < 0.0) sweep = sweep + 360.0; intrcpt1 = pie_intercept(width, height, xcen, ycen, angle1, &(vx[1]), &(vy[1])); intrcpt2 = pie_intercept(width, height, xcen, ycen, angle2, &x2, &y2); count = 2; /* if angles intercept same side and slice is between them, no corners */ /* else, mark corners until reaching side with second angle intercept */ if((intrcpt1 != intrcpt2) || (sweep > 180.0)){ do{ intrcpt1 = corner_vertex(intrcpt1, width, height, &(vx[count]), &(vy[count])); count = count + 1; }while(intrcpt1 != intrcpt2); } vx[count] = x2; vy[count] = y2; count++; _polygoni(g, qt, rno, sno, flag, type, vx, vy, count); } /* ***************************** shapes ********************************** */ void imannulusi(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double iradius, double oradius) { int yy; double dval; double xoff, yoff; Scan *scanlist; /* NB: do not use x and y variables, they have bogus values */ if( iradius == 0 ){ imcirclei(g, rno, sno, flag, type, x, y, xcen, ycen, oradius); return; } /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; iradius /= (double)g->block; oradius /= (double)g->block; /* set y limits */ if( PIXSTART(ycen - oradius) < PIXSTOP(ycen + oradius) ){ g->shapes[sno].ystart = max(g->y0,PIXSTART(ycen - oradius)); g->shapes[sno].ystop = min(g->y1,PIXSTOP(ycen + oradius)); } else{ g->shapes[sno].ystart = min(g->y1,PIXSTOP(ycen + oradius)); g->shapes[sno].ystop = max(g->y0,PIXSTART(ycen - oradius)); } g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); scanlist = g->shapes[sno].scanlist; marky(g, sno, flag, type); /* calculate start/stop values for each y line */ for(yy=g->shapes[sno].ystart; yy<=g->shapes[sno].ystop; yy++){ yoff = PIXCEN(yy) - ycen; if( (dval=(oradius * oradius) - (yoff * yoff)) > 0.0 ){ xoff = sqrt(dval); if( PIXSTART(xcen - xoff) <= PIXSTOP(xcen + xoff) ){ rgs_mark(g, scanlist, sno, flag, type, PIXSTART(xcen - xoff), yy); rgs_mark(g, scanlist, sno, flag, type, PIXSTOP(xcen + xoff), yy); } if( (dval=(iradius * iradius) - (yoff * yoff)) > 0.0 ){ xoff = sqrt(dval); if( PIXSTART(xcen - xoff) <= PIXSTOP(xcen + xoff) ){ rgs_mark(g, scanlist, sno, flag, type, PIXSTART(xcen - xoff), yy); rgs_mark(g, scanlist, sno, flag, type, PIXSTOP(xcen + xoff), yy); } } } } } int imannulus(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double iradius, double oradius) { Scan scan; if( iradius == 0 ){ return(imcircle(g, rno, sno, flag, type, x, y, xcen, ycen, oradius)); } if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } scan = g->shapes[sno].scanlist[(int)y]; if( (scan && ((y >= g->shapes[sno].ystart) && (y <= g->shapes[sno].ystop)) && (scan->next->next ? (((x >= scan->x) && (x <= scan->next->next->next->x)) && !((x >= scan->next->x) && (x <= scan->next->next->x))) : ((x >= scan->x) && (x <= scan->next->x)))) ==flag ){ if( rno && flag ) g->rid = rno; return 1; } else return 0; } void imboxi(GFilt g, int rno, int sno, int flag, int type, double UNUSED(x), double UNUSED(y), double xcen, double ycen, double xwidth, double yheight, double angle) { double angl; /* l: Cartesian angle in radians */ double half_width, half_height;/* l: radii (1/2 width and height) */ double cosangl, sinangl; /* l: sine, cosine of the Cartesian angle */ double hw_cos, hw_sin; /* l: products of half_width with sin, cos */ double hh_cos, hh_sin; /* l: products of half_height with sin, cos */ double cornerx[4], cornery[4]; /* l: arrays of x and y coords of 4 corners */ /* NB: do not use x and y variables, they have bogus values */ if( (xwidth == 0) && (yheight==0) ){ return; } /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; xwidth /= (double)g->block; yheight /= (double)g->block; #if USE_ASTRO_ANGLE /* convert to a Cartesian angle; save angle for use in multi or slices */ angl = angle + 90.0; #else angl = angle; #endif while (angl >= 360.0) angl = angl - 360.0; /* convert to radians */ angl = (angl / 180.0) * M_PI; sinangl = sin (angl); cosangl = cos (angl); #if USE_ASTRO_ANGLE /* since we rotate by 90.0 degrees to get from astro angle to cartesian, */ /* we also need to switch the width and height. we do this secretly so */ /* that the display will turn out right, by doing it in the half terms */ half_width = yheight / 2.0; half_height = xwidth / 2.0; #else half_width = xwidth / 2.0; half_height = yheight / 2.0; #endif hw_cos = half_width * cosangl; hw_sin = half_width * sinangl; hh_cos = half_height * cosangl; hh_sin = half_height * sinangl; #if USE_ASTRO_ANGLE cornerx[0] = xcen - hw_cos - hh_sin; cornery[0] = ycen - hw_sin + hh_cos; cornerx[1] = xcen + hw_cos - hh_sin; cornery[1] = ycen + hw_sin + hh_cos; cornerx[2] = xcen + hw_cos + hh_sin; cornery[2] = ycen + hw_sin - hh_cos; cornerx[3] = xcen - hw_cos + hh_sin; cornery[3] = ycen - hw_sin - hh_cos; #else cornerx[0] = xcen - hw_cos + hh_sin; cornery[0] = ycen - hh_cos - hw_sin; cornerx[1] = xcen - hw_cos - hh_sin; cornery[1] = ycen + hh_cos - hw_sin; cornerx[2] = xcen + hw_cos - hh_sin; cornery[2] = ycen + hh_cos + hw_sin; cornerx[3] = xcen + hw_cos + hh_sin; cornery[3] = ycen - hh_cos + hw_sin; #endif _polygoni(g, 0, rno, sno, flag, type, cornerx, cornery, 4); } int imbox(GFilt g, int rno, int sno, int flag, int type, double x, double y, double UNUSED(xcen), double UNUSED(ycen), double xwidth, double yheight, double UNUSED(angle)) { if( (xwidth == 0) && (yheight==0) ){ return(!flag); } return impolygon(g, rno, sno, flag, type, x, y); } void imcirclei(GFilt g, int UNUSED(rno), int sno, int flag, int type, double UNUSED(x), double UNUSED(y), double xcen, double ycen, double radius) { int yy; double dval; double xoff, yoff; Scan *scanlist; /* NB: do not use x and y variables, they have bogus values */ if( radius == 0 ){ return; } /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; radius /= (double)g->block; /* set y limits */ if( PIXSTART(ycen - radius) < PIXSTOP(ycen + radius) ){ g->shapes[sno].ystart = max(g->y0,PIXSTART(ycen - radius)); g->shapes[sno].ystop = min(g->y1,PIXSTOP(ycen + radius)); } else{ g->shapes[sno].ystart = min(g->y1,PIXSTOP(ycen + radius)); g->shapes[sno].ystop = max(g->y0,PIXSTART(ycen - radius)); } g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); scanlist = g->shapes[sno].scanlist; marky(g, sno, flag, type); /* calculate start/stop values for each y line */ for(yy=g->shapes[sno].ystart; yy<=g->shapes[sno].ystop; yy++){ yoff = PIXCEN(yy) - ycen; if( (dval=(radius * radius) - (yoff * yoff))>=0.0 ){ xoff = sqrt(dval); if( PIXSTART(xcen - xoff) <= PIXSTOP(xcen + xoff) ){ rgs_mark(g, scanlist, sno, flag, type, PIXSTART(xcen - xoff), yy); rgs_mark(g, scanlist, sno, flag, type, PIXSTOP(xcen + xoff), yy); } } } } int imcircle(GFilt g, int rno, int sno, int flag, int UNUSED(type), double x, double y, double UNUSED(xcen), double UNUSED(ycen), double radius) { Scan scan; if( radius == 0 ){ return(!flag); } if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } scan = g->shapes[sno].scanlist[(int)y]; if( (scan && ((y>=g->shapes[sno].ystart) && (y<=g->shapes[sno].ystop)) && ((x >= scan->x) && (x <= (scan->next)->x))) == flag ){ if( rno && flag ) g->rid = rno; return 1; } else{ return 0; } } void imellipsei(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double xrad, double yrad, double angle) { int yy; int nr, nc; double yhi; double yoff; double xboff, xfoff; double angl; double sinangl, cosangl; double cossq, sinsq, xradsq, yradsq; double a, b_partial, c_partial; double b, c; Scan *scanlist; /* NB: do not use x and y variables, they have bogus values */ if( xrad == yrad ){ imcirclei(g, rno, sno, flag, type, x, y, xcen, ycen, xrad); return; } /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; xrad /= (double)g->block; yrad /= (double)g->block; /* set worst case limits (xrad axis parallel to vertical axis) */ #if USE_ASTRO_ANGLE /* convert to a Cartesian angle; save "angle" for use by other routines */ angl = angle + 90.0; #else angl = angle; #endif while( angl >= 360.0 ) angl = angl - 360.0; /* convert to radians */ angl = (angl / 180.0) * M_PI; sinangl = sin(angl); cosangl = cos(angl); /* calculate approximate y limits */ /* choose lesser of containing rotbox and circle */ FPU_DOUBLE #if USE_ASTRO_ANGLE yhi = fabs(sinangl * yrad) + fabs(cosangl * xrad); #else yhi = fabs(sinangl * xrad) + fabs(cosangl * yrad); #endif yhi = min(yhi, max(yrad, xrad)); /* set y limits */ if( PIXSTART(ycen - yhi) < PIXSTOP(ycen + yhi) ){ g->shapes[sno].ystart = max(g->y0,PIXSTART(ycen - yhi)); g->shapes[sno].ystop = min(g->y1,PIXSTOP(ycen + yhi)); } else{ g->shapes[sno].ystart = min(g->y1,PIXSTOP(ycen + yhi)); g->shapes[sno].ystop = max(g->y0,PIXSTART(ycen - yhi)); } FPU_RESTORE g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); scanlist = g->shapes[sno].scanlist; marky(g, sno, flag, type); /* prepare partials for quadratic equation solutions to coordinates */ cossq = cosangl * cosangl; sinsq = sinangl * sinangl; #if USE_ASTRO_ANGLE /* because we rotate by 90.0 degrees to get from astro angle to */ /* cartesian, we also need to switch the x and y axes. we do this */ /* secretly so that the display will turn out right, by doing it in */ /* the sq terms */ xradsq = yrad * yrad; yradsq = xrad * xrad; #else xradsq = xrad * xrad; yradsq = yrad * yrad; #endif /* fill in as much of a,b,c as we can */ a = (cossq / xradsq) + (sinsq / yradsq); b_partial = (2.0 * sinangl) * ((cosangl / xradsq) - (cosangl / yradsq)); c_partial = (sinsq / xradsq) + (cossq / yradsq); /* calculate start/stop values for each y line */ for(yy=g->shapes[sno].ystart; yy<=g->shapes[sno].ystop; yy++){ yoff = yy - ycen; b = b_partial * yoff; c = (c_partial * yoff * yoff) - 1.0; /* solve quadratic */ quadeq (a, b, c, &xboff, &xfoff, &nr, &nc); /* if real roots */ if( nr != 0 ) { /* translate x coordinates */ rgs_mark(g, scanlist, sno, flag, type, PIXSTART(xcen + xboff), yy); rgs_mark(g, scanlist, sno, flag, type, PIXSTOP(xcen + xfoff), yy); } } } int imellipse(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double xrad, double yrad, double UNUSED(angle)) { Scan scan; if( xrad == yrad ){ return(imcircle(g, rno, sno, flag, type, x, y, xcen, ycen, xrad)); } if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } scan = g->shapes[sno].scanlist[(int)y]; FPU_DOUBLE if( (scan && ((y>=g->shapes[sno].ystart) && (y<=g->shapes[sno].ystop)) && ((x >= scan->x) && (x <= (scan->next)->x))) == flag ){ if( rno && flag ) g->rid = rno; FPU_RESTORE return 1; } else{ FPU_RESTORE return 0; } } void imfieldi(GFilt g, int UNUSED(rno), int sno, int flag, int type, double UNUSED(x), double UNUSED(y)) { int yy; Scan *scanlist; /* NB: do not use x and y variables, they have bogus values */ g->shapes[sno].ystart = g->y0; g->shapes[sno].ystop = g->y1; g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); scanlist = g->shapes[sno].scanlist; marky(g, sno, flag, type); /* calculate start/stop values for each y line */ for(yy=g->shapes[sno].ystart; yy<=g->shapes[sno].ystop; yy++){ rgs_mark(g, scanlist, sno, flag, type, g->x0, yy); rgs_mark(g, scanlist, sno, flag, type, g->x1, yy); } } int imfield(GFilt g, int rno, int UNUSED(sno), int flag, int UNUSED(type), double UNUSED(x), double UNUSED(y)) { if( flag ){ if( rno && flag ) g->rid = rno; return 1; } else{ return 0; } } void imlinei(GFilt g, int UNUSED(rno), int sno, int flag, int type, double UNUSED(x), double UNUSED(y), double x1, double y1, double x2, double y2) { double vx[2]; double vy[2]; int xval, yval; double invslope, xoffset; /* NB: do not use x and y variables, they have bogus values */ /* divide by block factor to get "real" parameters */ x1 = (x1 - g->xmin)/g->block + 1.0; y1 = (y1 - g->ymin)/g->block + 1.0; x2 = (x2 - g->xmin)/g->block + 1.0; y2 = (y2 - g->ymin)/g->block + 1.0; /* order by increasing y */ if( y1 < y2 ){ vx[0] = x1; vy[0] = y1; vx[1] = x2; vy[1] = y2; } else{ vx[0] = x2; vy[0] = y2; vx[1] = x1; vy[1] = y1; } /* set y limits */ g->shapes[sno].ystart = PIXNUM(vy[0]); g->shapes[sno].ystop = PIXNUM(vy[1]); g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); marky(g, sno, flag, type); if( feq(vy[0],vy[1]) ){ rgs_mark(g, g->shapes[sno].scanlist, sno, flag, type, (int)min(vx[0],vx[1]), (int)vy[0]); rgs_mark(g, g->shapes[sno].scanlist, sno, flag, type, (int)max(vx[0],vx[1]), (int)vy[0]); } else{ /* mark all horizontal segment crossings */ invslope = (vx[0] - vx[1]) / (vy[0] - vy[1]); xoffset = vx[0]; for(yval=vy[0]; yval<=vy[1]; yval++){ xval = xoffset; rgs_mark(g, g->shapes[sno].scanlist, sno, flag, type, xval, yval); xoffset = xoffset + invslope; } } } int imline(GFilt g, int rno, int sno, int flag, int UNUSED(type), double x, double y, double UNUSED(x1), double UNUSED(y1), double UNUSED(x2), double UNUSED(y2)) { Scan scan; if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } scan = g->shapes[sno].scanlist[(int)y]; if( (scan && ((x==(int)scan->x) || (scan->next&&((x>=(int)scan->x)&&(x<=(int)scan->next->x)))))==flag ) { if( rno && flag ) g->rid = rno; return 1; } else return 0; } void impiei(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double angle1, double angle2) { _impiei(g, 0, rno, sno, flag, type, x, y, xcen, ycen, angle1, angle2); } int impie(GFilt g, int rno, int sno, int flag, int type, double x, double y, double UNUSED(xcen), double UNUSED(ycen), double UNUSED(angle1), double UNUSED(angle2)) { return impolygon(g, rno, sno, flag, type, x, y); } void imqtpiei(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double angle1, double angle2) { _impiei(g, 1, rno, sno, flag, type, x, y, xcen, ycen, angle1, angle2); } int imqtpie(GFilt g, int rno, int sno, int flag, int type, double x, double y, double UNUSED(xcen), double UNUSED(ycen), double UNUSED(angle1), double UNUSED(angle2)) { return impolygon(g, rno, sno, flag, type, x, y); } void impointi(GFilt g, int UNUSED(rno), int sno, int flag, int type, double UNUSED(x), double UNUSED(y), double xcen, double ycen) { /* NB: do not use x and y variables, they have bogus values */ /* divide by block factor to get "real" parameters */ xcen = (xcen - g->xmin)/g->block + 1.0; ycen = (ycen - g->ymin)/g->block + 1.0; /* set y limits */ g->shapes[sno].ystart = PIXNUM(ycen); g->shapes[sno].ystop = PIXNUM(ycen); g->shapes[sno].scanlist = (Scan *)calloc(g->y1+1, sizeof(Scan)); marky(g, sno, flag, type); rgs_mark(g, g->shapes[sno].scanlist, sno, flag, type, PIXNUM(xcen), PIXNUM(ycen)); } int impoint(GFilt g, int rno, int sno, int flag, int UNUSED(type), double x, double y, double UNUSED(xcen), double UNUSED(ycen)) { Scan scan; if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } scan = g->shapes[sno].scanlist[(int)y]; if( (scan && (y == (int)g->shapes[sno].ystart) && (x == (int)scan->x))==flag ) { if( rno && flag ) g->rid = rno; return 1; } else return 0; } #ifdef __STDC__ void impolygoni(GFilt g, int rno, int sno, int flag, int type, double UNUSED(x), double y, ...) { double *vx=NULL, *vy=NULL; int count, maxcount; va_list args; va_start(args, y); #else void impolygoni(va_alist) va_dcl { GFilt g; int rno, sno, flag, type; double x, y; double *vx=NULL, *vy=NULL; int count, maxcount; va_list args; va_start(args); g = va_arg(args, GFilt); rno = va_arg(args, int); sno = va_arg(args, int); flag = va_arg(args, int); type = va_arg(args, int); x = va_arg(args, double); y = va_arg(args, double); #endif /* NB: do not use x and y variables, they have bogus values */ /* allocate space for x,y arguments */ maxcount = MASKINC; vx = (double *)calloc(maxcount, sizeof(double)); vy = (double *)calloc(maxcount, sizeof(double)); /* look for x,y arguments */ count = 0; while( 1 ){ if( (count + 1) >= maxcount ){ maxcount += MASKINC; vx = (double *)realloc(vx, maxcount*sizeof(double)); vy = (double *)realloc(vy, maxcount*sizeof(double)); } vx[count] = va_arg(args, double); vy[count] = va_arg(args, double); if( feq(vx[count],PSTOP) && feq(vy[count],PSTOP) ) break; vx[count] = (vx[count] - g->xmin)/g->block + 1.0; vy[count] = (vy[count] - g->ymin)/g->block + 1.0; count ++; } va_end(args); /* realloc to actual size */ vx = (double *)realloc(vx, count*sizeof(double)); vy = (double *)realloc(vy, count*sizeof(double)); /* call the common routine */ _polygoni(g, 0, rno, sno, flag, type, vx, vy, count); if( vx ) free(vx); if( vy ) free(vy); } #ifdef __STDC__ int impolygon(GFilt g, int rno, int sno, int flag, int UNUSED(type), double x, double y, ...) { int crossings; Scan scan; va_list args; va_start(args, y); #else int impolygon(va_alist) va_dcl { GFilt g; int rno, sno, flag, type; double x, y; int crossings; Scan scan; va_list args; va_start(args); g = va_arg(args, GFilt); rno = va_arg(args, int); sno = va_arg(args, int); flag = va_arg(args, int); type = va_arg(args, int); x = va_arg(args, double); y = va_arg(args, double); #endif va_end(args); if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } if( flag ){ if(y < g->shapes[sno].ystart ) return 0; if(y > g->shapes[sno].ystop ) return 0; } /* no initialization of x for this row, just jump right in */ if( (y>=g->shapes[sno].ystart)&&(y<=g->shapes[sno].ystop) ){ crossings = 0; for(scan=g->shapes[sno].scanlist[(int)y]; scan; scan=scan->next){ if( x >= scan->x ) crossings++; else break; } if( (crossings%2) == flag ){ if( rno && flag ) g->rid = rno; return 1; } else{ return 0; } } else{ return !flag; } } void imnannulusi(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double lo, double hi, int n) { int i; int xsno; double dinc; /* NB: do not use x and y variables, they have bogus values */ /* get limits */ dinc = (hi - lo)/n; xsno = (g->nshapes+1)+((sno-1)*XSNO); /* init all shapes */ imannulusi(g, 0, xsno, flag, type, x, y, xcen, ycen, lo, hi); for(i=0; inshapes+1)+((sno-1)*XSNO); /* init all shapes */ imboxi(g, 0, xsno, flag, type, x, y, xcen, ycen, hix, hiy, ang); imboxi(g, 0, xsno+1, flag, type, x, y, xcen, ycen, lox, loy, ang); for(i=0; inshapes+1)+((sno-1)*XSNO); /* init all shapes */ imellipsei(g, 0, xsno, flag, type, x, y, xcen, ycen, hix, hiy, ang); imellipsei(g, 0, xsno+1, flag, type, x, y, xcen, ycen, lox, loy, ang); for(i=0; i hi ) lo -= 360.0; dinc = (hi - lo)/n; xsno = (g->nshapes+1)+((sno-1)*XSNO); /* init all shapes */ impiei(g, 0, xsno, flag, type, x, y, xcen, ycen, lo, hi); for(i=0; i anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; rinc = (radhi - radlo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); /* init pies and annuli */ imannulusi(g, 0, xsno, flag, type, x, y, xcen, ycen, radlo, radhi); imqtpiei(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi); for(a=0; a anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; xinc = (xhi - xlo)/radn; yinc = (yhi - ylo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); /* init pies and ellipses */ imboxi(g, 0, xsno, flag, type, x, y, xcen, ycen, xhi, yhi, ang); imqtpiei(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi); imboxi(g, 0, xsno+2, flag, type, x, y, xcen, ycen, xlo, ylo, ang); for(a=0; a anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; xinc = (xhi - xlo)/radn; yinc = (yhi - ylo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); /* init pies and ellipses */ imellipsei(g, 0, xsno, flag, type, x, y, xcen, ycen, xhi, yhi, ang); imqtpiei(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi); imellipsei(g, 0, xsno+2, flag, type, x, y, xcen, ycen, xlo, ylo, ang); for(a=0; anshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imannulus(g, 0, xsno, flag, type, x, y, xcen, ycen, lo, hi) ){ return(0); } /* look through all of them to find the right one */ for(i=0; inshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imbox(g, 0, xsno, flag, type, x, y, xcen, ycen, hix, hiy, ang) ){ return(0); } /* if its in the inner region we lose */ if( imbox(g, 0, xsno+1, flag, type, x, y, xcen, ycen, lox, loy, ang) ){ return(0); } /* look through all of them to find the right one */ for(i=0; inshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imellipse(g, 0, xsno, flag, type, x, y, xcen, ycen, hix, hiy, ang) ){ return(0); } /* if its in the inner region we lose */ if( imellipse(g, 0, xsno+1, flag, type, x, y, xcen, ycen, lox, loy, ang) ){ return(0); } /* look through all of them to find the right one */ for(i=0; i hi ) lo -= 360.0; dinc = (hi - lo)/n; xsno = (g->nshapes+1)+((sno-1)*XSNO); if( flag ){ /* check limits */ if( !impie(g, 0, xsno, flag, type, x, y, xcen, ycen, lo, hi) ){ return(0); } /* look through all of them to find the right one */ for(i=0; i anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; rinc = (radhi - radlo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imannulus(g, 0, xsno, flag, type, x, y, xcen, ycen, radlo, radhi) || !impie(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi) ){ return(0); } /* look through all of them to find the right one */ for(a=1; a<=ahi; a++){ for(r=1; r<=rhi; r++){ if( imannulus(g, rno+n, sno+(2*n), flag, type, x, y, xcen, ycen, radlo+((r-1)*rinc), radlo+(r*rinc)) && impie(g, rno+n, sno+(2*n+1), flag, type, x, y, xcen, ycen, anglo+((a-1)*ainc), anglo+(a*ainc)) ){ return(1); } n++; } } return(0); } else{ /* if its not somewhere inside the entire region we win ... */ if( !imannulus(g, 0, xsno, 1, type, x, y, xcen, ycen, radlo, radhi) ) return(1); else if( !impie(g, 0, xsno+1, 1, type, x, y, xcen, ycen, anglo, anghi) ){ return(1); } else{ return(0); } } } int imbpanda(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, double anglo, double anghi, double angn, double xlo, double ylo, double xhi, double yhi, double radn, double ang) { int a, r; int ahi, rhi; int xsno; int n=0; double ainc, xinc, yinc; /* get limits */ anglo += ang; anghi += ang; while( anglo > anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; xinc = (xhi - xlo)/radn; yinc = (yhi - ylo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imbox(g, 0, xsno, flag, type, x, y, xcen, ycen, xhi, yhi, ang) ){ return(0); } /* but if its in the inner region we lose */ else if( imbox(g, 0, xsno+2, flag, type, x, y, xcen, ycen, xlo, ylo, ang) ){ return(0); } /* its in the box .. must also be in the pie */ else if( !impie(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi)){ return(0); } /* look through all of them to find the right one */ for(a=0; a anghi ) anglo -= 360.0; ainc = (anghi - anglo)/angn; ahi = (int)angn; xinc = (xhi - xlo)/radn; yinc = (yhi - ylo)/radn; rhi = (int)radn; xsno = (g->nshapes+1)+((sno-1)*XSNO); if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imellipse(g, 0, xsno, flag, type, x, y, xcen, ycen, xhi, yhi, ang) ){ return(0); } /* but if its in the inner region we lose */ else if( imellipse(g, 0, xsno+2, flag, type, x, y, xcen, ycen, xlo, ylo, ang) ){ return(0); } /* its in the ellipse .. must also be in the pie */ else if( !impie(g, 0, xsno+1, flag, type, x, y, xcen, ycen, anglo, anghi)){ return(0); } /* look through all of them to find the right one */ for(a=0; anshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; /* this should be impossible ... */ if( n == 2 ){ imannulusi(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1]); return; } imannulusi(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[0], xv[n-1]); for(i=0; i<(n-1); i++){ imannulusi(g, rno+i, sno+i, flag, type, x, y, xcen, ycen, xv[i], xv[i+1]); } } #ifdef __STDC__ void imvboxi(GFilt g, int rno, int sno, int flag, int type, double x, double y, double xcen, double ycen, ...) { int i, j, n; int maxpts; int xsno; double ang; double *xv; va_list args; va_start(args, ycen); #else int imvboxi(va_alist) va_dcl { GFilt g; int rno, sno, flag, type; double x, y; double xcen, ycen; double ang; double *xv; int i, j, n; int maxpts; int xsno; va_list args; va_start(args); g = va_arg(args, GFilt); rno = va_arg(args, int); sno = va_arg(args, int); flag = va_arg(args, int); type = va_arg(args, int); x = va_arg(args, double); y = va_arg(args, double); xcen = va_arg(args, double); ycen = va_arg(args, double); #endif xsno = (g->nshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; ang = xv[--n]; /* this should be impossible ... */ if( n == 2 ){ imboxi(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang); return; } imboxi(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[n-2], xv[n-1], ang); imboxi(g, 0, xsno+1, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang); for(i=2, j=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; ang = xv[--n]; /* this should be impossible ... */ if( n == 2 ){ imellipsei(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang); return; } imellipsei(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[n-2], xv[n-1], ang); imellipsei(g, 0, xsno+1, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang); for(i=2, j=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; /* this should be impossible ... */ if( n == 2 ){ impiei(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1]); return; } impiei(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[0], xv[n-1]); for(i=0; i<(n-1); i++){ impiei(g, rno+i, sno+i, flag, type, x, y, xcen, ycen, xv[i], xv[i+1]); } } #ifdef __STDC__ void imvpointi(GFilt g, int rno, int sno, int flag, int type, double x, double y, ...) { int i, j, n; int maxpts; int xsno; double *xv; va_list args; va_start(args, y); #else int imvpointi(va_alist) va_dcl { GFilt g; int rno, sno, flag, type; double x, y; double *xv; int i, j, n; int maxpts; int xsno; va_list args; va_start(args); g = va_arg(args, GFilt); rno = va_arg(args, int); sno = va_arg(args, int); flag = va_arg(args, int); type = va_arg(args, int); x = va_arg(args, double); y = va_arg(args, double); #endif xsno = (g->nshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; for(i=0, j=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; /* this should be impossible ... */ if( n == 2 ){ return(imannulus(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1])); } if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imannulus(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[0], xv[n-1]) ){ return(0); } /* look through all of them to find the right one */ for(i=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; ang = xv[--n]; /* this should be impossible ... */ if( n == 2 ){ return(imbox(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang)); } if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imbox(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[n-2], xv[n-1], ang) ){ return(0); } /* if its in the inner region we lose */ if( imbox(g, 0, xsno+1, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang) ){ return(0); } /* look through all of them to find the right one */ for(i=2, j=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; ang = xv[--n]; /* this should be impossible ... */ if( n == 2 ){ return(imellipse(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang)); } if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !imellipse(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[n-2], xv[n-1], ang) ){ return(0); } /* if its in the inner region we lose */ if( imellipse(g, 0, xsno+1, flag, type, x, y, xcen, ycen, xv[0], xv[1], ang) ){ return(0); } /* look through all of them to find the right one */ for(i=2, j=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; /* this should be impossible ... */ if( n == 2 ){ return(impie(g, rno, sno, flag, type, x, y, xcen, ycen, xv[0], xv[1])); } if( flag ){ /* if its not somewhere inside the entire region we lose ... */ if( !impie(g, 0, xsno, flag, type, x, y, xcen, ycen, xv[0], xv[n-1]) ){ return(0); } /* look through all of them to find the right one */ for(i=0; inshapes+1)+((sno-1)*XSNO); if( !g->shapes[xsno].xv ){ maxpts = MASKINC; g->shapes[xsno].xv = (double *)calloc(maxpts, sizeof(double)); g->shapes[xsno].nv = 0; while( 1 ){ if( g->shapes[xsno].nv >= maxpts ){ maxpts += MASKINC; g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, maxpts*sizeof(double)); } g->shapes[xsno].xv[g->shapes[xsno].nv] = va_arg(args, double); if( feq(g->shapes[xsno].xv[g->shapes[xsno].nv],PSTOP) && feq(g->shapes[xsno].xv[g->shapes[xsno].nv-1],PSTOP) ){ g->shapes[xsno].nv--; break; } g->shapes[xsno].nv++; } va_end(args); g->shapes[xsno].xv = (double *)realloc(g->shapes[xsno].xv, g->shapes[xsno].nv*sizeof(double)); } n = g->shapes[xsno].nv; xv = g->shapes[xsno].xv; /* look through all of them to find the right one */ for(i=0, j=0; ixmax - g->xmin + 1)/g->block)/(double)g->maskdim) + 0.5); if( mblock < 1 ){ g->masks = NULL; g->nmask = 0; } /* copy all masks and translate x,y positions as needed */ fsize = g->nmask * sizeof(FilterMaskRec) * mblock; xmasks = (FilterMask)calloc(1, fsize); for(got=0, i=0; inmask; i++){ xmasks[got].region = g->masks[i].region; xmasks[got].y = (g->masks[i].y - 1.0) * mblock + 1.0; xmasks[got].xstart = (g->masks[i].xstart - 1.0) * mblock + 1.0; xmasks[got].xstop = (g->masks[i].xstop - 1.0) * mblock + 1.0; /* replicate the segment up to the block factor */ for(j=1; jmasks ) free(g->masks); */ /* set up new mask records */ g->masks = xmasks; g->nmask = got; /* now mark each y line that has a y mask value */ for(i=0; iybuf[g->masks[i].y] ) g->ybuf[g->masks[i].y] = i+1; } } int imimagemask(GFilt g, int UNUSED(rno), int UNUSED(sno), int UNUSED(flag), int UNUSED(type), double x, double y) { int i; int ix, iy; if( g->nmask == 0 ) return(0); if( g->evsect ){ if( g->usebinsiz ){ x = (int)((x - g->tlminx)/g->binsizx + 1.0); y = (int)((y - g->tlminy)/g->binsizy + 1.0); } else{ x = (int)((x - g->tlminx) + 1.0); y = (int)((y - g->tlminy) + 1.0); } x = (int)((x - g->xmin)/g->block + 1.0); y = (int)((y - g->ymin)/g->block + 1.0); if(y < g->y0) return 0; if(y > g->y1) return 0; if(x < g->x0) return 0; if(x > g->x1) return 0; } ix = (int)x; iy = (int)y; /* look for mask segment containing ix, iy */ i = g->ybuf[iy]; /* ybuf contains offset+1 of first mask record containing iy */ if( i != 0 ){ i--; for(; inmask; i++){ if( g->masks[i].y > iy ){ return(0); } if( (ix >= g->masks[i].xstart) && (ix <= g->masks[i].xstop) ){ g->rid = g->masks[i].region; return(1); } } } return(0); }