summaryrefslogtreecommitdiffstats
path: root/funtools/filter/imregions_c.tmpl
diff options
context:
space:
mode:
Diffstat (limited to 'funtools/filter/imregions_c.tmpl')
-rw-r--r--funtools/filter/imregions_c.tmpl2585
1 files changed, 2585 insertions, 0 deletions
diff --git a/funtools/filter/imregions_c.tmpl b/funtools/filter/imregions_c.tmpl
new file mode 100644
index 0000000..639fefc
--- /dev/null
+++ b/funtools/filter/imregions_c.tmpl
@@ -0,0 +1,2585 @@
+/*
+ NB: MAKE SURE YOU EDIT THE TEMPLATE FILE!!!!
+*/
+
+#ifndef FILTER_PTYPE
+#include <regions.h>
+#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 _FPUDBL_
+#if USE_FPU_DOUBLE
+#include <fpu_control.h>
+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; i<count; i++){
+ vx[i] = (vx[i] - g->xmin)/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<count; i++){
+ if(vx[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<count; i++){
+ /* make segments always run from lower y to higher y */
+ if(vy[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; i<n; i++){
+ imannulusi(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lo+(i*dinc), lo+((i+1)*dinc));
+ }
+}
+
+void imnboxi(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y,
+ double xcen, double ycen,
+ double lox, double loy, double hix, double hiy, int n,
+ double ang)
+{
+ int i;
+ int xsno;
+ double dincx;
+ double dincy;
+
+ /* NB: do not use x and y variables, they have bogus values */
+
+ /* get limits */
+ dincx = (hix - lox)/n;
+ dincy = (hiy - loy)/n;
+ xsno = (g->nshapes+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; i<n; i++){
+ imboxi(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lox+((i+1)*dincx), loy+((i+1)*dincy), ang);
+ }
+}
+
+void imnellipsei(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y,
+ double xcen, double ycen,
+ double lox, double loy, double hix, double hiy, int n,
+ double ang)
+{
+ int i;
+ int xsno;
+ double dincx;
+ double dincy;
+
+ /* NB: do not use x and y variables, they have bogus values */
+
+ /* get limits */
+ dincx = (hix - lox)/n;
+ dincy = (hiy - loy)/n;
+ xsno = (g->nshapes+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<n; i++){
+ imellipsei(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lox+((i+1)*dincx), loy+((i+1)*dincy), ang);
+ }
+}
+
+void imnpiei(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 */
+ while( lo > 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<n; i++){
+ impiei(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lo+(i*dinc), lo+((i+1)*dinc));
+ }
+}
+
+void impandai(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 radlo, double radhi, double radn)
+{
+ int a, r;
+ int ahi, rhi;
+ int xsno;
+ int n=0;
+ double ainc, rinc;
+
+ /* NB: do not use x and y variables, they have bogus values */
+
+ /* get limits */
+ while( anglo > 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<ahi; a++){
+ for(r=0; r<rhi; r++){
+ imannulusi(g, rno+n, sno+(2*n), flag, type, x, y,
+ xcen, ycen, radlo+(r*rinc), radlo+((r+1)*rinc));
+ imqtpiei(g, rno+n, sno+(2*n+1), flag, type, x, y,
+ xcen, ycen, anglo+(a*ainc), anglo+((a+1)*ainc));
+ n++;
+ }
+ }
+}
+
+void imbpandai(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;
+
+ /* NB: do not use x and y variables, they have bogus values */
+
+ /* 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);
+ /* 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<ahi; a++){
+ for(r=1; r<=rhi; r++){
+ imboxi(g, rno+n, sno+(2*n), flag, type, x, y,
+ xcen, ycen, xlo+(r*xinc), ylo+(r*yinc), ang);
+ imqtpiei(g, rno+n, sno+(2*n+1), flag, type, x, y,
+ xcen, ycen, anglo+(a*ainc), anglo+((a+1)*ainc));
+ n++;
+ }
+ }
+}
+
+void imepandai(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;
+
+ /* NB: do not use x and y variables, they have bogus values */
+
+ /* 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);
+ /* 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; a<ahi; a++){
+ for(r=1; r<=rhi; r++){
+ imellipsei(g, rno+n, sno+(2*n), flag, type, x, y,
+ xcen, ycen, xlo+(r*xinc), ylo+(r*yinc), ang);
+ imqtpiei(g, rno+n, sno+(2*n+1), flag, type, x, y,
+ xcen, ycen, anglo+(a*ainc), anglo+((a+1)*ainc));
+ n++;
+ }
+ }
+}
+
+/* accelerator regions -- lower and upper limits are given for n regions */
+
+int imnannulus(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;
+
+ /* get limits */
+ dinc = (hi - lo)/(double)n;
+ 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, lo, hi) ){
+ return(0);
+ }
+ /* look through all of them to find the right one */
+ for(i=0; i<n; i++){
+ if( imannulus(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lo+(i*dinc), lo+((i+1)*dinc)) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imannulus(g, 0, xsno, 1, type, x, y, xcen, ycen, lo, hi) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+int imnbox(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen,
+ double lox, double loy, double hix, double hiy, int n,
+ double ang)
+{
+ int i;
+ int xsno;
+ double dincx;
+ double dincy;
+
+ /* get limits */
+ dincx = (hix - lox)/n;
+ dincy = (hiy - loy)/n;
+ 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, 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; i<n; i++){
+ if( imbox(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lox+((i+1)*dincx), loy+((i+1)*dincy), ang) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imbox(g, 0, xsno, 1, type, x, y, xcen, ycen, hix, hiy, ang) ){
+ return(1);
+ }
+ /* if its in the inner region we win */
+ if( imbox(g, 0, xsno+1, 1, type, x, y, xcen, ycen, lox, loy, ang) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+int imnellipse(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen,
+ double lox, double loy, double hix, double hiy, int n,
+ double ang)
+{
+ int i;
+ int xsno;
+ double dincx;
+ double dincy;
+
+ /* get limits */
+ dincx = (hix - lox)/n;
+ dincy = (hiy - loy)/n;
+ 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, 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<n; i++){
+ if( imellipse(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lox+((i+1)*dincx), loy+((i+1)*dincy), ang) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imellipse(g, 0, xsno, 1, type, x, y, xcen, ycen, hix, hiy, ang) ){
+ return(1);
+ }
+ /* if its in the inner region we win */
+ if( imellipse(g, 0, xsno+1, 1, type, x, y, xcen, ycen, lox, loy, ang) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+int imnpie(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;
+
+ /* get limits */
+ while( lo > 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<n; i++){
+ if( impie(g, rno+i, sno+i, flag, type, x, y,
+ xcen, ycen, lo+(i*dinc), lo+((i+1)*dinc)) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !impie(g, 0, xsno, 1, type, x, y, xcen, ycen, lo, hi) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+int impanda(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 radlo, double radhi, double radn)
+{
+
+ int a, r;
+ int ahi, rhi;
+ int xsno;
+ int n=0;
+ double ainc, rinc;
+
+ /* get limits */
+ while( anglo > 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<ahi; a++){
+ for(r=1; r<=rhi; r++){
+ if( imbox(g, rno+n, sno+(2*n), flag, type, x, y,
+ xcen, ycen, xlo+(r*xinc), ylo+(r*yinc), ang) &&
+ imqtpie(g, rno+n, sno+(2*n+1), flag, type, x, y,
+ xcen, ycen, anglo+(a*ainc), anglo+((a+1)*ainc)) ){
+ return(1);
+ }
+ n++;
+ }
+ }
+ return(0);
+ }
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imbox(g, 0, xsno, 1, type, x, y, xcen, ycen, xhi, yhi, ang) )
+ return(1);
+ /* if its in the inner region we win */
+ else if( !imbox(g, 0, xsno+2, 1, type, x, y, xcen, ycen, xlo, ylo,
+ ang) )
+ return(1);
+ /* if its not in the pie, we win */
+ else if( !impie(g, 0, xsno+1, 1, type, x, y, xcen, ycen, anglo, anghi) ){
+ return(1);
+ }
+ else{
+ return(0);
+ }
+ }
+}
+
+int imepanda(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( !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; a<ahi; a++){
+ for(r=1; r<=rhi; r++){
+ if( imellipse(g, rno+n, sno+(2*n), flag, type, x, y,
+ xcen, ycen, xlo+(r*xinc), ylo+(r*yinc), ang) &&
+ imqtpie(g, rno+n, sno+(2*n+1), flag, type, x, y,
+ xcen, ycen, anglo+(a*ainc), anglo+((a+1)*ainc)) ){
+ return(1);
+ }
+ n++;
+ }
+ }
+ return(0);
+ }
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imellipse(g, 0, xsno, 1, type, x, y, xcen, ycen, xhi, yhi, ang) )
+ return(1);
+ /* if its in the inner region we win */
+ else if( !imellipse(g, 0, xsno+2, 1, type, x, y, xcen, ycen, xlo, ylo,
+ ang) )
+ return(1);
+ /* if its not in the pie, we win */
+ else if( !impie(g, 0, xsno+1, 1, type, x, y, xcen, ycen, anglo, anghi) ){
+ return(1);
+ }
+ else{
+ return(0);
+ }
+ }
+}
+
+#ifdef __STDC__
+void
+imvannulusi(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen, ...)
+{
+ int i, n;
+ int maxpts;
+ int xsno;
+ double *xv;
+ va_list args;
+ va_start(args, ycen);
+#else
+int imvannulusi(va_alist) va_dcl
+{
+ GFilt g;
+ int rno, sno, flag, type;
+ double x, y;
+ double xcen, ycen;
+ double ang;
+ double *xv;
+ int i, 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;
+ /* 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; i<n; i+=2, j++){
+ imboxi(g, rno+j, sno+j, flag, type, x, y, xcen, ycen, xv[i], xv[i+1], ang);
+ }
+}
+
+#ifdef __STDC__
+void
+imvellipsei(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 imvellipsei(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 ){
+ 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; i<n; i+=2, j++){
+ imellipsei(g, rno+j, sno+j, flag, type, x, y, xcen, ycen,
+ xv[i], xv[i+1], ang);
+ }
+}
+
+#ifdef __STDC__
+void
+imvpiei(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen, ...)
+{
+ int i, n;
+ int maxpts;
+ int xsno;
+ double *xv;
+ va_list args;
+ va_start(args, ycen);
+#else
+int imvpiei(va_alist) va_dcl
+{
+ GFilt g;
+ int rno, sno, flag, type;
+ double x, y;
+ double xcen, ycen;
+ double ang;
+ double *xv;
+ int i, 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;
+ /* 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; i<n; i+=2, j++){
+ impointi(g, rno+j, sno+j, flag, type, x, y, xv[i], xv[i+1]);
+ }
+}
+
+/* varargs regions -- a series of lower and upper limits is specified */
+
+#ifdef __STDC__
+int
+imvannulus(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen, ...)
+{
+ int i, n;
+ int maxpts;
+ int xsno;
+ double *xv;
+ va_list args;
+ va_start(args, ycen);
+#else
+int imvannulus(va_alist) va_dcl
+{
+ GFilt g;
+ int rno, sno, flag, type;
+ double x, y;
+ double xcen, ycen;
+ double *xv;
+ int i, 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;
+ /* 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; i<n; i++){
+ if( imannulus(g, rno+i, sno+i, flag, type, x, y, xcen, ycen,
+ xv[i], xv[i+1]) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imannulus(g, 0, xsno, 1, type, x, y, xcen, ycen, xv[0], xv[n-1]) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+#ifdef __STDC__
+int
+imvbox(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 imvbox(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 ){
+ 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; i<n; i+=2, j++){
+ if( imbox(g, rno+j, sno+j, flag, type, x, y, xcen, ycen,
+ xv[i], xv[i+1], ang) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we win ... */
+ if( !imbox(g, 0, xsno, 1, type, x, y, xcen, ycen, xv[n-2], xv[n-1], ang) ){
+ return(1);
+ }
+ /* if its in the inner region we win */
+ else if( imbox(g, 0, xsno+1, 1, type, x, y, xcen, ycen, xv[0], xv[1], ang) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+#ifdef __STDC__
+int
+imvellipse(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 imvellipse(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 ){
+ 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; i<n; i+=2, j++){
+ if( imellipse(g, rno+j, sno+j, flag, type, x, y, xcen, ycen,
+ xv[i], xv[i+1], ang) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we lose ... */
+ if( !imellipse(g, 0, xsno, 1, type, x, y, xcen, ycen, xv[n-2], xv[n-1],
+ ang) ){
+ return(1);
+ }
+ /* if its in the inner region we win */
+ if( imellipse(g, 0, xsno+1, 1, type, x, y, xcen, ycen, xv[0], xv[1], ang) ){
+ return(1);
+ }
+ return(0);
+ }
+}
+
+#ifdef __STDC__
+int
+imvpie(GFilt g, int rno, int sno, int flag, int type,
+ double x, double y, double xcen, double ycen, ...)
+{
+ int i, n;
+ int maxpts;
+ int xsno;
+ double *xv;
+ va_list args;
+ va_start(args, ycen);
+#else
+int imvpie(va_alist) va_dcl
+{
+ GFilt g;
+ int rno, sno, flag, type;
+ double x, y;
+ double xcen, ycen;
+ double *xv;
+ int i, 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;
+ /* 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; i<n; i++){
+ if( impie(g, rno+i, sno+i, flag, type, x, y, xcen, ycen, xv[i], xv[i+1]) ){
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /* for excludes, we have to check that we are not in any of them */
+ else{
+ /* if its not somewhere inside the entire region we lose ... */
+ if( !impie(g, 0, xsno, 1, type, x, y, xcen, ycen, xv[0], xv[n-1]) ){
+ return(1);
+ }
+ return(1);
+ }
+}
+
+#ifdef __STDC__
+int
+imvpoint(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 imvpoint(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;
+ /* look through all of them to find the right one */
+ for(i=0, j=0; i<n; i+=2, j++){
+ if( impoint(g, rno+j, sno+j, flag, type, x, y, xv[i], xv[i+1]) ){
+ return(1);
+ }
+ }
+ return(0);
+}
+
+void imimagemaski(GFilt g, int UNUSED(rno), int UNUSED(sno),
+ int UNUSED(flag), int UNUSED(type),
+ double UNUSED(x), double UNUSED(y))
+{
+ int i, j;
+ int got;
+ int fsize;
+ int mblock;
+ FilterMask xmasks;
+
+ /* NB: do not use x and y variables, they have bogus values */
+ /* scale mask x, y values to match the incoming image section */
+ mblock = (int)(((double)((g->xmax - 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; i<g->nmask; 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; j<mblock; j++){
+ xmasks[got+j].region = xmasks[got].region;
+ xmasks[got+j].y = xmasks[got].y+j;
+ xmasks[got+j].xstart = xmasks[got].xstart;
+ xmasks[got+j].xstop = xmasks[got].xstop;
+ }
+ got += mblock;
+ }
+ /* sort by y and x */
+ qsort(xmasks, got, sizeof(FilterMaskRec), imagemaskcmp);
+ /* we don't free previous masks, just overwrite, because they were not
+ allocated in the first place */
+ /* if( g->masks ) 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; i<got; i++){
+ if( !g->ybuf[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(; i<g->nmask; 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);
+}
+