/*------------------------------------------------------------------------------ Map. Implemented as interpretive read/write, to permit interactive behaviour. Input: in_filename = name of file to read from; "" or "-" means read from standard input. out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. w = array containing spherical harmonics. lmax = maximum harmonic number. lsmooth = smoothing harmonic number (0. = no smooth). esmooth = smoothing exponent (2. = gaussian). Return value: number of items written, or -1 if error occurred. */ int map(char *in_filename, char *out_filename, format *fmt, int lmax, harmonic w[/*NW*/], double lsmooth, double esmooth) { /* precision of map values written to file */ #define PRECISION 8 #define AZEL_STR_LEN 32 inputfile file = { '\0', /* input filename */ 0x0, /* input file stream */ '\0', /* line buffer */ 64, /* size of line buffer (will expand as necessary) */ 0, /* line number */ 0 /* maximum number of characters to read (0 = no limit) */ }; char input[] = "input", output[] = "output"; char *word, *next; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int ird, len, mmax, nmap, width; double rho; azel v; char *out_fn; FILE *outfile; /* open in_filename for reading */ if (!in_filename || strcmp(in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", in_filename); return(-1); } file.name = in_filename; } file.line_number = 0; /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "cannot open %s for writing\n", out_filename); return(-1); } out_fn = out_filename; } /* advise angular units */ msg("will take units of input az, el angles in %s to be ", file.name); switch (fmt->inunit) { #include "angunit.h" } msg("\n"); if (fmt->outunit != fmt->inunit) { msg("units of output az, el angles will be "); switch (fmt->outunit) { #include "angunit.h" } msg("\n"); } /* setting mmax = lmax ensures complete set of azimuthal harmonics */ mmax = lmax; /* width of map value */ width = PRECISION + 6; /* write header */ v.az = 0.; wrangle(v.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); len = strlen(az_str); if (fmt->outunit == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); } else { sprintf(az_str, "az(%c)", fmt->outunit); sprintf(el_str, "el(%c)", fmt->outunit); } fprintf(outfile, "%*s %*s %*s\n", len, az_str, len, el_str, width - 4, "wrho"); /* interpretive read/write loop */ nmap = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read <az> */ word = file.line; ird = rdangle(word, &next, fmt->inunit, &v.az); /* skip header */ if (ird != 1 && nmap == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* read <el> */ word = next; ird = rdangle(word, &next, fmt->inunit, &v.el); /* skip header */ if (ird != 1 && nmap == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* convert az and el from input units to radians */ scale_azel(&v, fmt->inunit, 'r'); /* The entire of map.c is an interface to the next line of code. Bizarre, huh? */ /* compute the value of the window function at this point */ rho = wrho(v.az, v.el, lmax, mmax, w, lsmooth, esmooth); /* convert az and el from radians to output units */ scale_azel(&v, 'r', fmt->outunit); /* write result */ wrangle(v.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(outfile, "%s %s %- #*.*lg\n", az_str, el_str, width, PRECISION, rho); fflush(outfile); /* increment counter of results */ nmap++; } if (outfile != stdout) { msg("map: %d values written to %s\n", nmap, out_fn); } return(nmap); }
/*------------------------------------------------------------------------------ Weight polygons. Input: poly = array of pointers to polygons. npoly = pointer to number of polygons. survey = name of survey, or of filename containing list of weights. Output: polys = array of pointers to polygons; Return value: number of polygons weighted, or -1 if error occurred. */ int weight(int npoly, polygon *poly[/*npoly*/], char *survey) { const int per = 0; const int nve = 2; int do_vcirc, i, imid, ipoly, iverts, ivm, nev, nev0, nomid, nv, nvm, nzero; int *ipv, *gp, *ev; long double tol; long double *angle; vec *ve, *vm; azel v; nomid = 0; nzero = 0; for (ipoly = 0; ipoly < npoly; ipoly++) { /* vertices of polygon */ do_vcirc = 0; tol = mtol; iverts = gverts(poly[ipoly], do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev); if (iverts != 0) return(-1); /* point somewhere in the middle of the polygon */ imid = vmid(poly[ipoly], tol, nv, nve, ve, ipv, ev, &nvm, &vm); if (imid == -1) return(-1); /* check found a point inside the polygon */ imid = 0; for (ivm = 0; ivm < nvm; ivm++) { if (vm[ivm][0] != 0. || vm[ivm][1] != 0. || vm[ivm][2] != 0.) { imid = 1; if (ivm > 0) for (i = 0; i < 3; i++) vm[0][i] = vm[ivm][i]; break; } } /* found a point */ if (imid == 1) { /* convert unit vector to az, el */ rp_to_azel(*vm, &v); /* scale angles from radians to degrees */ scale_azel(&v, 'r', 'd'); /* weight at that point */ poly[ipoly]->weight = weight_fn(v.az, v.el, survey); if (poly[ipoly]->weight == 0.) nzero++; /* failed to find a point */ } else { //call weight_fn to stay in right place in weight file if reading from weights from a file weight_fn(v.az, v.el, survey); if (nomid == 0) msg("weight: failed to find interior point for the following polygons:\n"); msg(" %lld", (fmt.newid == 'n')? (long long)ipoly+fmt.idstart : poly[ipoly]->id); nomid++; } } if (nomid > 0) msg("\n"); if (nomid > 0) { msg("weight: failed to find interior point for %d polygons\n", nomid); msg("FAILURE TO FIND INTERIOR POINT PROBABLY MEANS YOU HAVE A WEIRD-SHAPED POLYGON.\n"); msg("PLEASE FILL IN THE CORRECT WEIGHT BY HAND.\n"); } /* assign new polygon id numbers in place of inherited ids */ if (fmt.newid == 'n') { for (ipoly = 0; ipoly < npoly; ipoly++) { poly[ipoly]->id = (long long)ipoly+fmt.idstart; } } if (fmt.newid == 'p') { for (ipoly = 0; ipoly < npoly; ipoly++) { poly[ipoly]->id = (long long)poly[ipoly]->pixel; } } /* warn about zero weights */ if (nzero > 0) msg("weight: %d polygons have zero weight\n", nzero); return(npoly); }
/*------------------------------------------------------------------------------ Generate random az, el positions within mask defined by poly. The results are written to out_filename. Input: out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. npoly = number of polygons in poly array. npolysmax = maximum number of polygons in poly array. poly = array of pointers to polygons. mtol = initial tolerance angle for multiple intersections. Return value: number of random points generated, or -1 if error occurred. */ int ransack(char *out_filename, format *fmt, int npoly, int npolysmax, polygon *poly[/*npolysmax*/]) { /* number of extra caps to allocate to polygon, to allow for expansion */ #define DNP 4 /* length of state vector for random number generator */ #define STATELEN 256 static char state[STATELEN], stateo[STATELEN]; #define AZEL_STR_LEN 32 char output[] = "output"; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int dnp, dnwl, i, idwidth, ier, in, inull, ip, ipmin, ipoly, iprune, irandom, lassoed, np, nwl, tries, verb, width, k; long long idmin,idmax; int *dlasso=0x0, *lasso=0x0; long double area, cmmin, cmi, phi, rpoly, si, tol, w, wcum, x, y, z; long double *wpoly; vec rp, xi, yi; azel v; char *out_fn; FILE *outfile; /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "ransack: cannot open %s for writing\n", out_filename); goto error; } out_fn = out_filename; } /* advise angular units */ if (fmt->outunit != fmt->inunit) { msg("units of output az, el angles will be "); switch (fmt->outunit) { #include "angunit.h" } msg("\n"); } /* initialize random number generator used by ransack() */ initstate(seed, state, STATELEN); /* initialize random number generator used by ikrand() */ initstate(seed, stateo, STATELEN); /* prune polygons, discarding those with zero weight * area */ msg("pruning %d polygons ...\n", npoly); ier = 0; inull = 0; np = 0; for (ipoly = 0; ipoly < npoly; ipoly++) { /* zero weight polygon */ if (poly[ipoly]->weight == 0.) { inull++; free_poly(poly[ipoly]); poly[ipoly] = 0x0; } else { /* prune polygon */ iprune = prune_poly(poly[ipoly], mtol); /* error */ if (iprune == -1) { ier++; free_poly(poly[ipoly]); poly[ipoly] = 0x0; fprintf(stderr, "ransack: failed to prune polygon %d; discard it\n", ipoly); /* goto error; */ /* zero area polygon */ } else if (iprune >= 2) { inull++; free_poly(poly[ipoly]); poly[ipoly] = 0x0; } else { np++; } } } /*copy down non-null polygons*/ k=0; for(ipoly = 0; ipoly < npoly; ipoly++){ if(poly[ipoly]){ poly[k++]=poly[ipoly]; } } /*after copying non-null polygons, k should be equal to np */ if(k!=np){ fprintf(stderr, "ransack: should be left with %d non-null polygons, but actually have %d\n",np,k); } /*nullify the rest of the array, but don't free, since pointers have been copied above*/ for(ipoly=np; ipoly < npoly; ipoly++){ poly[ipoly]=0x0; } if (ier > 0) { msg("discarding %d unprunable polygons\n", ier); } if (inull > 0) { msg("discarding %d polygons with zero weight * area\n", inull); } /* number of polygons with finite weight * area */ npoly = np; /* no polygons */ if (npoly == 0) { fprintf(stderr, "ransack: no polygons to generate random points inside!\n"); goto error; } /* pre-lasso polygons if there are many random points */ if (nrandom >= npoly) { msg("lassoing %d polygons ...\n", npoly); /* lasso each polygon */ np = npoly; for (ipoly = 0; ipoly < npoly; ipoly++) { ier = lasso_poly(&poly[ipoly], npolysmax - np, &poly[np], mtol, &dnp); if (ier == -1) { fprintf(stderr, "ransack: UHOH at polygon %lld; continuing ...\n", poly[ipoly]->id); } /* lassoed polygons are an improvement over original polygon */ if (dnp > 0) { /* check whether exceeded maximum number of polygons */ if (np + dnp > npolysmax) { fprintf(stderr, "ransack: total number of polygons exceeded maximum %d\n", npolysmax); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); goto error; } /* decrement dnp by 1 */ dnp--; /* increment number of polygons */ np += dnp; /* move last polygon part into poly[ipoly] */ free_poly(poly[ipoly]); poly[ipoly] = poly[np]; poly[np] = 0x0; } } /* revised number of polygons */ npoly = np; /* flag that all polygons have been lassoed */ lassoed = 1; /* two few random points to make it worth pre-lassoing */ } else { /* flag that all polygons have not been lassoed */ lassoed = 0; } /* allocate memory for wpoly array */ nwl = npoly; wpoly = (long double *) malloc(sizeof(long double) * nwl); if (!wpoly) { fprintf(stderr, "ransack: failed to allocate memory for %d long doubles\n", nwl); goto error; } if (!lassoed) { /* allocate memory for lasso and dlasso arrays */ lasso = (int *) malloc(sizeof(int) * nwl); if (!lasso) { fprintf(stderr, "ransack: failed to allocate memory for %d ints\n", nwl); goto error; } dlasso = (int *) malloc(sizeof(int) * nwl); if (!dlasso) { fprintf(stderr, "ransack: failed to allocate memory for %d ints\n", nwl); goto error; } /* initialize dlasso array to zero */ for (ipoly = 0; ipoly < nwl; ipoly++) dlasso[ipoly] = 0; } /* largest width of polygon id number */ idmin = 0; idmax = 0; for (ipoly = 0; ipoly < npoly; ipoly++) { if (poly[ipoly]->id < idmin) idmin = poly[ipoly]->id; if (poly[ipoly]->id > idmax) idmax = poly[ipoly]->id; } idmin = ((idmin < 0)? floorl(log10l((long double)-idmin)) + 2 : 1); idmax = ((idmax > 0)? floorl(log10l((long double)idmax)) + 1 : 1); idwidth = ((idmin > idmax)? idmin : idmax); /* write header */ wrangle(0., fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); width = strlen(az_str); if (fmt->outunit == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); } else { sprintf(az_str, "az(%c)", fmt->outunit); sprintf(el_str, "el(%c)", fmt->outunit); } fprintf(outfile, "%*s\t%*s\t%*s\n", width, az_str, width, el_str, idwidth, "id"); /* accept error messages from garea */ /* unprunable polygons were already discarded, so garea should give no errors */ verb = 1; /* cumulative area times weight of polygons */ w = 0.; for (ipoly = 0; ipoly < npoly; ipoly++) { /* skip null polygons */ if (poly[ipoly]) { /* area of polygon */ tol = mtol; ier = garea(poly[ipoly], &tol, verb, &area); if (ier) goto error; /* accumulate weight times area */ w += poly[ipoly]->weight * area; } wpoly[ipoly] = w; } wcum = w; /* random points */ if (strcmp(out_fn, output) != 0) { msg("generating %d random points from seed %u in %d polygons ...\n", nrandom, seed, npoly); } for (irandom = 0; irandom < nrandom; irandom++) { /* random number in interval [0, 1) wcum */ setstate(state); rpoly = drandom() * wcum; setstate(stateo); /* which polygon to put random point in */ ipoly = search(npoly, wpoly, rpoly); /* guard against roundoff */ if (ipoly >= npoly) { fprintf(stderr, "ransack: %d should be < %d (i.e. %.15Lg < %.15Lg)\n", ipoly, npoly, rpoly, wpoly[npoly - 1]); ipoly = npoly - 1; } /* all polygons have not been lassoed */ if (!lassoed) { /* polygon has not yet been lassoed */ if (dlasso[ipoly] == 0) { /* lasso polygon */ ier = lasso_poly(&poly[ipoly], npolysmax - np, &poly[np], mtol, &dnp); if (ier == -1) { fprintf(stderr, "ransack: UHOH at polygon %lld; continuing ...\n", poly[ipoly]->id); } /* go with original polygon */ if (dnp == 0) { /* lasso, dlasso */ lasso[ipoly] = ipoly; dlasso[ipoly] = 1; /* lassoed polygons are an improvement over original */ } else { /* check whether exceeded maximum number of polygons */ if (np + dnp > npolysmax) { fprintf(stderr, "ransack: total number of polygons exceeded maximum %d\n", npolysmax); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); goto error; } /* just one lassoed polygon */ if (dnp == 1) { /* move last polygon part into poly[ipoly] */ free_poly(poly[ipoly]); poly[ipoly] = poly[np]; poly[np] = 0x0; /* lasso, dlasso */ lasso[ipoly] = ipoly; dlasso[ipoly] = 1; /* more than one lassoed polygon */ } else { /* enlarge memory for wpoly, lasso, and dlasso arrays */ if (np + dnp > nwl) { dnwl = dnp + 1024; wpoly = (long double *) realloc(wpoly, sizeof(long double) * (nwl + dnwl)); if (!wpoly) { fprintf(stderr, "ransack: failed to reallocate memory for %d long doubles\n", nwl + dnwl); goto error; } lasso = (int *) realloc(lasso, sizeof(int) * (nwl + dnwl)); if (!lasso) { fprintf(stderr, "ransack: failed to reallocate memory for %d ints\n", nwl + dnwl); goto error; } dlasso = (int *) realloc(dlasso, sizeof(int) * (nwl + dnwl)); if (!dlasso) { fprintf(stderr, "ransack: failed to reallocate memory for %d ints\n", nwl + dnwl); goto error; } /* initialize new part of lasso and dlasso arrays to inconsistent values */ for (ipoly = nwl; ipoly < nwl + dnwl; ipoly++) lasso[ipoly] = 1; for (ipoly = nwl; ipoly < nwl + dnwl; ipoly++) dlasso[ipoly] = 0; /* revised size of wpoly, lasso, and dlasso arrays */ nwl += dnwl; } /* lasso, dlasso */ lasso[ipoly] = np; dlasso[ipoly] = dnp; /* cumulative weight times area of lassoed polygons */ w = (ipoly == 0)? 0. : wpoly[ipoly-1]; for (ip = np; ip < np + dnp; ip++) { /* area of polygon */ tol = mtol; ier = garea(poly[ip], &tol, verb, &area); if (ier) goto error; /* accumulate area times weight */ w += poly[ip]->weight * area; wpoly[ip] = w; } /* increment number of polygons */ np += dnp; } } } /* polygon was partitioned into at least two */ if (dlasso[ipoly] >= 2) { /* which polygon to put random point in */ ip = search(dlasso[ipoly], &wpoly[lasso[ipoly]], rpoly); /* guard against roundoff */ if (ip >= lasso[ipoly] + dlasso[ipoly]) { fprintf(stderr, "ransack: %d should be < %d (i.e. %.15Lg < %.15Lg)\n", ip, lasso[ipoly] + dlasso[ipoly], rpoly, wpoly[lasso[ipoly] + dlasso[ipoly] - 1]); ip = lasso[ipoly] + dlasso[ipoly] - 1; } /* revised polygon number to put random point in */ ipoly = ip; } } /* smallest cap of polygon */ cmminf(poly[ipoly], &ipmin, &cmmin); /* random point within polygon */ tries = 0; do { tries++; /* random point within smallest cap */ setstate(state); phi = TWOPI * drandom(); cmi = cmmin * drandom(); setstate(stateo); /* coordinates of random point in cap frame */ si=sqrtl(cmi * (2. - cmi)); x = si * cosl(phi); y = si * sinl(phi); z = 1. - cmi; /* polygon has caps */ if (poly[ipoly]->np > 0) { if (poly[ipoly]->cm[ipmin] < 0.) z = -z; /* Cartesian axes with z-axis along cap axis */ gaxisi_(poly[ipoly]->rp[ipmin], xi, yi); /* coordinates of random point */ for (i = 0; i < 3; i++) rp[i] = x * xi[i] + y * yi[i] + z * poly[ipoly]->rp[ipmin][i]; /* whether random point is inside polygon */ in = gptin(poly[ipoly], rp); /* polygon has no caps, so is the whole sphere */ } else { rp[0] = x; rp[1] = y; rp[2] = z; in = 1; } } while (!in); /* convert unit vector to az, el */ rp_to_azel(rp, &v); v.az -= floorl(v.az / TWOPI) * TWOPI; /* convert az and el from radians to output units */ scale_azel(&v, 'r', fmt->outunit); /* write result */ wrangle(v.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(outfile, "%s\t%s\t%*lld\n", az_str, el_str, idwidth, poly[ipoly]->id); /* fprintf(outfile, "%s %s %d %d %d %Lg %Lg %Lg %Lg %d %d\n", az_str, el_str, irandom, ipoly, tries, wcum, rpoly / wcum, area, TWOPI * cmmin / area, ipmin, poly[ipoly]->np); */ } /* advise */ if (outfile != stdout) { msg("ransack: %d random positions written to %s\n", nrandom, out_fn); } return(nrandom); /* error returns */ error: return(-1); }
/*------------------------------------------------------------------------------ Angles within mask along circles centred at az el, radii th. Anglar positions az, el are read from azel_in_filename, angular radii th are read from th_in_filename, or from azel_in_filename if th_in_filename is null, and the results are written to out_filename. Implemented as interpretive read/write, to permit interactive behaviour. Input: azel_in_filename = name of file to read az, el from; "" or "-" means read from standard input. th_in_filename = name of file to read th from; null means read from azel_in_filename; "-" means read from standard input. out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. npoly = number of polygons in poly array. poly = array of pointers to polygons. Return value: number of lines written, or -1 if error occurred. */ int drangle(char *azel_in_filename, char *th_in_filename, char *out_filename, format *fmt, int npoly, polygon *poly[/*npoly*/]) { #define AZEL_STR_LEN 32 char input[] = "input", output[] = "output"; /* maximum number of angular angular radii: will expand as necessary */ static int nthmax = 0; static int ndrmax = 0; static long double *th = 0x0, *cm = 0x0, *drsum = 0x0; static long double *dr = 0x0; #ifdef TIME clock_t time; #endif char inunit, outunit; char *word, *next; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN], th_str[AZEL_STR_LEN], dr_str[AZEL_STR_LEN]; int ier, ird, ith, len, lenth, np, nt, nth; long double rp[3], s, t; azel v; char *out_fn; FILE *outfile; inunit = (fmt->inunit == 'h')? 'd' : fmt->inunit; /* read angular radii from th_in_filename */ if (th_in_filename) { /* open th_in_filename for reading */ if (strcmp(th_in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(th_in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", th_in_filename); return(-1); } file.name = th_in_filename; } file.line_number = 0; msg("will take units of input th angles in %s to be ", file.name); switch (inunit) { #include "angunit.h" } msg("\n"); /* read angular radii from th_in_filename */ nth = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read angular radius from line */ ird = rdangle(file.line, &next, inunit, &t); /* error */ if (ird < 1) { /* retry if nothing read, otherwise break */ if (nth > 0) break; /* ok */ } else if (ird == 1) { if (nth >= nthmax) { if (nthmax == 0) { nthmax = 64; } else { nthmax *= 2; } /* (re)allocate memory for th array */ th = (long double *) realloc(th, sizeof(long double) * nthmax); if (!th) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nthmax); return(-1); } } /* copy angular radius into th array */ th[nth] = t; nth++; } } if (file.file != stdin) { /* close th_in_filename */ fclose(file.file); /* advise */ msg("%d angular radii read from %s\n", nth, file.name); } if (nth == 0) return(nth); /* (re)allocate memory for th array */ th = (long double *) realloc(th, sizeof(long double) * nth); if (!th) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nth); return(-1); } /* (re)allocate memory for cm array */ cm = (long double *) realloc(cm, sizeof(long double) * nth); if (!cm) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nth); return(-1); } /* (re)allocate memory for drsum array */ drsum = (long double *) realloc(drsum, sizeof(long double) * nth); if (!drsum) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nth); return(-1); } nthmax = nth; } /* open azel_in_filename for reading */ if (!azel_in_filename || strcmp(azel_in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(azel_in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", azel_in_filename); return(-1); } file.name = azel_in_filename; } file.line_number = 0; /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "cannot open %s for writing\n", out_filename); return(-1); } out_fn = out_filename; } /* advise input angular units */ if (th_in_filename) { msg("will take units of input az, el angles in %s to be ", file.name); } else { msg("will take units of input az, el, and th angles in %s to be ", file.name); } switch (fmt->inunit) { #include "angunit.h" } if (!th_in_filename && fmt->inunit == 'h') { msg(", th in deg"); } msg("\n"); /* advise output angular unit */ outunit = (fmt->outunit == 'h')? 'd' : fmt->outunit; msg("units of output DR angles will be "); switch (outunit) { #include "angunit.h" } msg("\n"); #ifdef TIME printf("timing ... "); fflush(stdout); time = clock(); #endif /* length of az, el and th, dr strings to be written to output */ t = 0.; wrangle(t, fmt->inunit, fmt->outprecision, AZEL_STR_LEN, az_str); len = strlen(az_str); t = 0.; wrangle(t, inunit, fmt->outprecision, AZEL_STR_LEN, th_str); lenth = strlen(th_str); /* write header */ if (!summary) { if (fmt->inunit == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); sprintf(th_str, "th(d):"); } else { sprintf(az_str, "az(%c)", fmt->inunit); sprintf(el_str, "el(%c)", fmt->inunit); sprintf(th_str, "th(%c):", fmt->inunit); } if (th_in_filename) { fprintf(outfile, "%*s %*s %*s\n", len, " ", len, " ", lenth, th_str); } fprintf(outfile, "%*s %*s", len, az_str, len, el_str); if (th_in_filename) { for (ith = 0; ith < nth; ith++) { wrangle(th[ith], inunit, fmt->outprecision, AZEL_STR_LEN, th_str); fprintf(outfile, " %s", th_str); } fprintf(outfile, "\n"); } else { fprintf(outfile, " %*s\n", lenth, th_str); } } /* initialize th and drsum */ if (th_in_filename) { /* convert th from input units to radians */ for (ith = 0; ith < nth; ith++) { scale(&th[ith], inunit, 'r'); } /* initialize sum of dr to zero */ for (ith = 0; ith < nth; ith++) { drsum[ith] = 0.; } } /* interpretive read/write loop */ np = 0; nt = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read <az> */ word = file.line; ird = rdangle(word, &next, fmt->inunit, &v.az); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* read <el> */ word = next; ird = rdangle(word, &next, fmt->inunit, &v.el); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* convert az and el from input units to radians */ scale_azel(&v, fmt->inunit, 'r'); /* read th */ if (!th_in_filename) { nth = 0; while (1) { word = next; ird = rdangle(word, &next, inunit, &t); /* done */ if (ird < 1) break; /* ok */ if (nth >= nthmax) { if (nthmax == 0) { nthmax = 64; } else { nthmax *= 2; } th = (long double *) realloc(th, sizeof(long double) * nthmax); if (!th) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nthmax); return(-1); } /* (re)allocate memory for cm array */ cm = (long double *) realloc(cm, sizeof(long double) * nthmax); if (!cm) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", nthmax); return(-1); } } th[nth] = t; /* increment count of angular radii */ nth++; } /* convert th from input units to radians */ for (ith = 0; ith < nth; ith++) { scale(&th[nth], inunit, 'r'); } } /* allocate memory for dr */ if (nth > ndrmax) { ndrmax = nth; dr = (long double *) realloc(dr, sizeof(long double) * ndrmax); if (!dr) { fprintf(stderr, "drangle: failed to allocate memory for %d long doubles\n", ndrmax); return(-1); } } /* unit vector corresponding to angular position az, el */ azel_to_rp(&v, rp); /* limiting cm = 1-cosl(th) values to each polygon */ ier = cmlim_polys(npoly, poly, mtol, rp); if (ier == -1) return(-1); /* cm = 1 - cosl(th) */ for (ith = 0; ith < nth; ith++) { s = sinl(th[ith] / 2.); cm[ith] = 2. * s * s; } /* angles about rp direction at radii th */ ier = drangle_polys(npoly, poly, mtol, rp, nth, cm, dr); if (ier == -1) return(-1); /* sum of dr at radii th */ if (th_in_filename) { for (ith = 0; ith < nth; ith++) { drsum[ith] += dr[ith]; } } /* convert az and el from radians to original input units */ scale_azel(&v, 'r', fmt->inunit); /* write result */ if (!summary) { wrangle(v.az, fmt->inunit, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->inunit, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(outfile, "%s %s", az_str, el_str); for (ith = 0; ith < nth; ith++) { scale(&dr[ith], 'r', outunit); wrangle(dr[ith], outunit, fmt->outprecision, AZEL_STR_LEN, dr_str); fprintf(outfile, " %s", dr_str); } fprintf(outfile, "\n"); fflush(outfile); } /* increment counters of results */ np++; nt += nth; /* warn about a potentially huge output file */ if (np == 100 && !summary && th_in_filename && outfile != stdout) { msg("hmm, looks like %s could grow pretty large ...\n", out_fn); msg("try using the -h switch if you only want a summary in the output file\n"); } } /* write sum of dr */ if (summary) { sprintf(th_str, "th(%c)", inunit); sprintf(dr_str, "DR(%c)", outunit); fprintf(outfile, "%*s %*s\n", lenth, th_str, lenth, dr_str); for (ith = 0; ith < nth; ith++) { scale(&th[ith], 'r', inunit); wrangle(th[ith], inunit, fmt->outprecision, AZEL_STR_LEN, th_str); scale(&drsum[ith], 'r', outunit); wrangle(drsum[ith] / (long double)np, outunit, fmt->outprecision, AZEL_STR_LEN, dr_str); fprintf(outfile, "%s %s\n", th_str, dr_str); } fflush(outfile); } else if (th_in_filename) { fprintf(outfile, "%*s", 2 * len + 1, "Average:"); for (ith = 0; ith < nth; ith++) { scale(&drsum[ith], 'r', outunit); wrangle(drsum[ith] / (long double)np, outunit, fmt->outprecision, AZEL_STR_LEN, dr_str); fprintf(outfile, " %s", dr_str); } fprintf(outfile, "\n"); fflush(outfile); } /* close azel_in_filename */ if (file.file != stdin) { fclose(file.file); } #ifdef TIME time = clock() - time; printf("done in %Lg sec\n", (float)time / (float)CLOCKS_PER_SEC); #endif /* advise */ if (outfile != stdout) { fclose(outfile); if (summary) { msg("drangle: header + %d lines written to %s\n", nth, out_fn); } else { if (th_in_filename) { msg("drangle: %d x %d = ", nth, np); } else { msg("drangle: total of "); } msg("%d angles at %d positions written to %s\n", nt, np, out_fn); } } return(nt); }
/*------------------------------------------------------------------------------ Rotate az, el positions from one frame to another. The az, el positions are read from in_filename, and rotated az, el positions are written to out_filename. Implemented as interpretive read/write, to permit interactive behaviour. Input: in_filename = name of file to read from; "" or "-" means read from standard input. out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. Return value: number of lines written, or -1 if error occurred. */ int rotate(char *in_filename, char *out_filename, format *fmt) { #ifndef BUFSIZE # define BUFSIZE 64 #endif #define AZEL_STR_LEN 32 static inputfile file = { '\0', /* input filename */ 0x0, /* input file stream */ '\0', /* line buffer */ BUFSIZE, /* size of line buffer (will expand as necessary) */ 0, /* line number */ 0 /* maximum number of characters to read (0 = no limit) */ }; char input[] = "input", output[] = "output"; char *word, *next; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int ird, len, np; long double circle; azel vi, vf; char *out_fn; FILE *outfile; /* open in_filename for reading */ if (!in_filename || strcmp(in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", in_filename); return(-1); } file.name = in_filename; } file.line_number = 0; /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "cannot open %s for writing\n", out_filename); return(-1); } out_fn = out_filename; } /* advise custom transformation */ if (fmt->outframe == -1) { /* multiple transformation */ if (strchr(fopt, ':')) { msg(" -f%s is equivalent to\n", fopt); msg(" -f%.16Lg,%.16Lg,%.16Lg%c\n", places(fmt->azn, 14), places(fmt->eln, 14), places(fmt->azp, 14), fmt->trunit); /* single transformation */ } else { msg("rotate -f%.16Lg,%.16Lg,%.16Lg%c\n", fmt->azn, fmt->eln, fmt->azp, fmt->trunit); } /* advise standard transformation */ } else if (fmt->inframe != fmt->outframe) { msg("rotate from %s to %s\n", frames[fmt->inframe], frames[fmt->outframe]); msg(" -f%s,%s is equivalent to\n", frames[fmt->inframe], frames[fmt->outframe]); msg(" -f%.16Lg,%.16Lg,%.16Lg%c\n", places(fmt->azn, 14), places(fmt->eln, 14), places(fmt->azp, 14), fmt->trunit); } /* angular units */ msg("will take units of input az, el angles in %s to be ", file.name); switch (fmt->inunit) { #include "angunit.h" } msg("\n"); if (fmt->outunit != fmt->inunit) { msg("units of output az, el angles will be "); switch (fmt->outunit) { #include "angunit.h" } msg("\n"); } /* write header */ vf.az = 0.; wrangle(vf.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); len = strlen(az_str); if (fmt->outunit == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); } else { sprintf(az_str, "az(%c)", fmt->outunit); sprintf(el_str, "el(%c)", fmt->outunit); } fprintf(outfile, "%*s %*s\n", len, az_str, len, el_str); /* interpretive read/write loop */ np = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read <az> */ word = file.line; ird = rdangle(word, &next, fmt->inunit, &vi.az); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* read <el> */ word = next; ird = rdangle(word, &next, fmt->inunit, &vi.el); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* identity: treat specially to avoid loss of precision in scaling */ if (fmt->inframe == fmt->outframe) { /* output angles = input angles */ vf.az = vi.az; vf.el = vi.el; circle = 360.; scale(&circle, 'd', fmt->inunit); /* phase az */ switch (fmt->outphase) { case '+': if (vf.az < 0.) vf.az += circle; break; case '-': if (vf.az > circle / 2.) vf.az -= circle; break; } /* convert az and el from input to output units */ scale_azel(&vf, fmt->inunit, fmt->outunit); /* normal rotation */ } else { /* convert az and el from input units to degrees */ scale_azel(&vi, fmt->inunit, 'd'); /* rotate az and el */ rotate_azel(fmt, &vi, &vf); /* phase az */ switch (fmt->outphase) { case '+': if (vf.az < 0.) vf.az += 360.; break; case '-': if (vf.az > 180.) vf.az -= 360.; break; } /* convert az and el from degrees to output units */ scale_azel(&vf, 'd', fmt->outunit); } /* write result */ wrangle(vf.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(vf.el, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(outfile, "%s %s\n", az_str, el_str); fflush(outfile); /* increment counters of results */ np++; } if (outfile != stdout) { msg("rotate: %d positions written to %s\n", np, out_fn); } return(np); }
/*------------------------------------------------------------------------------ Id numbers of polygons containing az, el positions. The az, el positions are read from in_filename, and the results are written to out_filename. Implemented as interpretive read/write, to permit interactive behaviour. Input: in_filename = name of file to read from; "" or "-" means read from standard input. out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. poly = array of pointers to polygons. npoly = number of polygons in poly array. Return value: number of lines written, or -1 if error occurred. */ int poly_ids(char *in_filename, char *out_filename, format *fmt, int npoly, polygon *poly[/*npoly*/]) { #define AZEL_STR_LEN 32 char input[] = "input", output[] = "output"; char *word, *next; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int i, idwidth, ird, len, nid, nids, nid0, nid2, np; long long idmin, idmax; long long *id; long double *weight; azel v; char *out_fn; FILE *outfile; int *start; int *total; int *parent_pixels; int p, res, max_pixel, ier, sorted; ier=-1; sorted=0; while(ier!=0){ max_pixel= poly[npoly-1]->pixel; res_max=get_res(max_pixel, scheme); max_pixel=pixel_start(res_max+1,scheme); /* allocate memory for pixel info arrays start and total */ msg("res_max=%d, max_pixel=%d\n",res_max,max_pixel); start = (int *) malloc(sizeof(int) * max_pixel); if (!start) { fprintf(stderr, "polyid: failed to allocate memory for %d integers\n", max_pixel); return(-1); } total = (int *) malloc(sizeof(int) * max_pixel); if (!total) { fprintf(stderr, "polyid: failed to allocate memory for %d integers\n", max_pixel); return(-1); } parent_pixels = (int *) malloc(sizeof(int) * (res_max+1)); if (!parent_pixels) { fprintf(stderr, "polyid: failed to allocate memory for %d integers\n", res_max+1); return(-1); } /* build lists of starting indices of each pixel and total number of polygons in each pixel*/ ier=pixel_list(npoly, poly, max_pixel, start, total); if (ier == -1) { // if pixel_list returns an error, try sorting the polygons and trying again if(!sorted){ msg("sorting polygons...\n"); poly_sort(npoly,poly,'p'); sorted=1; } else{ fprintf(stderr, "poly_ids: error building pixel index lists\n"); return(-1); } } } /* open in_filename for reading */ if (!in_filename || strcmp(in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", in_filename); return(-1); } file.name = in_filename; } file.line_number = 0; /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "cannot open %s for writing\n", out_filename); return(-1); } out_fn = out_filename; } /* advise angular units */ msg("will take units of input az, el angles in %s to be ", file.name); switch (fmt->inunit) { #include "angunit.h" } msg("\n"); if (fmt->outunit != fmt->inunit) { msg("units of output az, el angles will be "); switch (fmt->outunit) { #include "angunit.h" } msg("\n"); } /* largest width of polygon id number */ idmin = 0; idmax = 0; for (i = 0; i < npoly; i++) { if (!poly[i]) continue; if (poly[i]->id < idmin) idmin = poly[i]->id; if (poly[i]->id > idmax) idmax = poly[i]->id; } idmin = ((idmin < 0)? floorl(log10l((long double)-idmin)) + 2 : 1); idmax = ((idmax > 0)? floorl(log10l((long double)idmax)) + 1 : 1); idwidth = ((idmin > idmax)? idmin : idmax); /* write header */ v.az = 0.; wrangle(v.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); len = strlen(az_str); if (fmt->outunit == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); } else { sprintf(az_str, "az(%c)", fmt->outunit); sprintf(el_str, "el(%c)", fmt->outunit); } fprintf(outfile, "%*s %*s", len, az_str, len, el_str); if (npoly > 0){ if(polyid_weight==1){ fprintf(outfile, " polygon_weights"); } else{ fprintf(outfile, " polygon_ids"); } } fprintf(outfile, "\n"); /* interpretive read/write loop */ np = 0; nid = 0; nids = 0; nid0 = 0; nid2 = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read <az> */ word = file.line; ird = rdangle(word, &next, fmt->inunit, &v.az); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* read <el> */ word = next; ird = rdangle(word, &next, fmt->inunit, &v.el); /* skip header */ if (ird != 1 && np == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* convert az and el from input units to radians */ scale_azel(&v, fmt->inunit, 'r'); //find out what pixel the az el point is in at the maximum resolution p=which_pixel(v.az, v.el, res_max, scheme); //get the list of all the possible parent pixels get_parent_pixels(p, parent_pixels, scheme); nid=0; for(res=res_max;res>=0;res--){ p=parent_pixels[res]; //if this pixel isn't in the polygon list, go to next parent pixel if(total[p]==0) continue; // id numbers of the polygons containing position az, el nid = poly_id(total[p], &poly[start[p]], v.az, v.el, &id, &weight); } /* convert az and el from radians to output units */ scale_azel(&v, 'r', fmt->outunit); /* write result */ wrangle(v.az, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunit, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(outfile, "%s %s", az_str, el_str); for (i = 0; i < nid; i++) { if(polyid_weight==1){ fprintf(outfile, " %.18Lg", weight[i]); } else{ fprintf(outfile, " %*lld", idwidth, id[i]); } } fprintf(outfile, "\n"); fflush(outfile); /* increment counters of results */ np++; nids += nid; if (nid == 0) { nid0++; } else if (nid >= 2) { nid2++; } } /* advise */ if (nid0 > 0) msg("%d points were not inside any polygon\n", nid0); if (nid2 > 0) msg("%d points were inside >= 2 polygons\n", nid2); if (outfile != stdout) { if(polyid_weight==1){ msg("polyid: %d weights at %d positions written to %s\n", nids, np, out_fn); } else { msg("polyid: %d id numbers at %d positions written to %s\n", nids, np, out_fn); } } free(start); free(total); free(parent_pixels); return(np); }
/*------------------------------------------------------------------------------ Write midpoints. Input: filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. polys = polygons to write. npolys = number of polygons. npolyw = number of polygons to write. Return value: number of polygons written, or -1 if error occurred. */ int wr_midpoint(char *filename, format *fmt, int npolys, polygon *polys[/*npolys*/], int npolyw) { const int per = 0; const int nve = 2; const int do_vcirc = 0; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int i, idmin, idmax, idwidth, ier, imid, ipoly, ivm, nev, nev0, npoly, nv, nvm, width; int *ipv, *gp, *ev; double tol; double *angle; vec *ve, *vm; azel v; FILE *file; /* open filename for writing */ if (!filename || strcmp(filename, "-") == 0) { file = stdout; } else { file = fopen(filename, "w"); if (!file) { fprintf(stderr, "wr_midpoint: cannot open %s for writing\n", filename); return(-1); } } /* largest width of polygon id number */ idmin = 0; idmax = 0; for (ipoly = 0; ipoly < npolys; ipoly++) { if (!polys[ipoly]) continue; if (polys[ipoly]->id < idmin) idmin = polys[ipoly]->id; if (polys[ipoly]->id > idmax) idmax = polys[ipoly]->id; } idmin = ((idmin < 0)? floor(log10((double)-idmin)) + 2 : 1); idmax = ((idmax > 0)? floor(log10((double)idmax)) + 1 : 1); idwidth = ((idmin > idmax)? idmin : idmax); /* write header */ wrangle(0., fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, az_str); width = strlen(az_str); if (fmt->outunitp == 'h') { sprintf(az_str, "az(hms)"); sprintf(el_str, "el(dms)"); } else { sprintf(az_str, "az(%c)", fmt->outunitp); sprintf(el_str, "el(%c)", fmt->outunitp); } fprintf(file, "midpoint of %d polygons\n", npolyw); fprintf(file, "%*s %*s %*s\n", width, az_str, width, el_str, idwidth, "id"); npoly = 0; for (ipoly = 0; ipoly < npolys; ipoly++) { /* discard null polygons */ if (!polys[ipoly]) continue; /* point somewhere in the middle of the polygon */ tol = mtol; ier = gverts(polys[ipoly], do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev); if (ier == -1) return(-1); imid = vmid(polys[ipoly], tol, nv, nve, ve, ipv, ev, &nvm, &vm); if (imid == -1) return(-1); /* check found a point inside the polygon */ imid = 0; for (ivm = 0; ivm < nvm; ivm++) { if (vm[ivm][0] != 0. || vm[ivm][1] != 0. || vm[ivm][2] != 0.) { imid = 1; if (ivm > 0) for (i = 0; i < 3; i++) vm[0][i] = vm[ivm][i]; break; } } /* found a point */ if (imid == 1) { rp_to_azel(vm[0], &v); switch (fmt->outphase) { case '+': if (v.az < 0.) v.az += TWOPI; break; case '-': if (v.az > PI) v.az -= TWOPI; break; } scale_azel(&v, 'r', fmt->outunitp); } /* write midpoint of polygon */ wrangle(v.az, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(file, "%s %s %*d\n", az_str, el_str, idwidth, polys[ipoly]->id); /* increment polygon count */ npoly++; } /* advise */ msg("%d midpoints written to %s\n", npoly, (file == stdout)? "output": filename); /* close file */ if (file != stdout) fclose(file); return(npoly); }
/*------------------------------------------------------------------------------ Write mask data in edges or vertices format. Input: filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. polys = polygons to write. npolys = number of polygons. npolyw = number of polygons to write. Return value: number of polygons written, or -1 if error occurred. */ int wr_edge(char *filename, format *fmt, int npolys, polygon *polys[/*npolys*/], int npolyw) { const int per = 0; const int nve = 2; const char *edges_fmt = "edges %d ( %d points/edge, %d edges, %.15lg weight, %s %s mid):\n"; const char *graphics_fmt = "graphics %d ( %d points, %d edges, %.15lg weight, %s %s mid):\n"; const char *vertices_fmt = "vertices %d ( %d vertices, %.15lg weight, %s %s mid):\n"; char az_str[AZEL_STR_LEN], el_str[AZEL_STR_LEN]; int do_vcirc, i, ier, imid, ipoly, iv, ive, ivm, jv, manybounds, nbadverts, nev, nev0, npoly, npt, nv, nvm; int *ipv, *gp, *ev; double azo, tol; double *angle; vec *ve, *vm; azel v; FILE *file; /* open filename for writing */ if (!filename || strcmp(filename, "-") == 0) { file = stdout; } else { file = fopen(filename, "w"); if (!file) { fprintf(stderr, "wr_edge: cannot open %s for writing\n", filename); return(-1); } } /* whether to write vertices also for circles with no intersections */ if (strcmp(fmt->out, "vertices") == 0) { do_vcirc = 0; } else { do_vcirc = 1; } /* write number of polygons */ fprintf(file, "%d polygons\n", npolyw); /* write angular unit */ fprintf(file, "unit %c\n", fmt->outunitp); manybounds = 0; npoly = 0; nbadverts = 0; for (ipoly = 0; ipoly < npolys; ipoly++) { /* discard null polygons */ if (!polys[ipoly]) continue; /* point somewhere in the middle of the polygon */ tol = mtol; ier = gverts(polys[ipoly], do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev); if (ier == -1) return(-1); imid = vmid(polys[ipoly], tol, nv, nve, ve, ipv, ev, &nvm, &vm); if (imid == -1) return(-1); /* check found a point inside the polygon */ imid = 0; for (ivm = 0; ivm < nvm; ivm++) { if (vm[ivm][0] != 0. || vm[ivm][1] != 0. || vm[ivm][2] != 0.) { imid = 1; if (ivm > 0) for (i = 0; i < 3; i++) vm[0][i] = vm[ivm][i]; break; } } /* found a point */ if (imid == 1) { rp_to_azel(vm[0], &v); switch (fmt->outphase) { case '+': if (v.az < 0.) v.az += TWOPI; break; case '-': if (v.az > PI) v.az -= TWOPI; break; } scale_azel(&v, 'r', fmt->outunitp); } /* points on edges of polygon */ tol = mtol; ier = gverts(polys[ipoly], do_vcirc, &tol, fmt->outper, fmt->outnve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev); if (ier == -1) return(-1); if (ier) { nbadverts++; continue; } /* warn about multi-boundary polygon */ if (nev > 1) { if (WARNMAX > 0 && manybounds == 0) { msg("the following polygons have > 1 boundary (not simply-connected)\n"); msg(" separate boundaries will be split over separate lines:\n"); } if (manybounds < WARNMAX) { msg(" %d", polys[ipoly]->id); } else if (manybounds == WARNMAX) { msg(" ... more\n"); } manybounds++; } /* count number of points */ npt = 0; for (iv = jv = 0; iv < nv; jv++) { for (; iv < ev[jv]; iv++) { for (ive = 0; ive < fmt->outnve; ive++) { i = iv * fmt->outnve + ive; if (ve[i][0] == 0. && ve[i][1] == 0. && ve[i][2] == 0.) break; npt++; } } } /* number of edges, weight, and midpoint of polygon */ wrangle(v.az, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, el_str); if (strcmp(fmt->out, "edges") == 0) { fprintf(file, edges_fmt, polys[ipoly]->id, fmt->outnve, nv, polys[ipoly]->weight, az_str, el_str); } else if (strcmp(fmt->out, "graphics") == 0) { fprintf(file, graphics_fmt, polys[ipoly]->id, npt, nv, polys[ipoly]->weight, az_str, el_str); } else { fprintf(file, vertices_fmt, polys[ipoly]->id, nv, polys[ipoly]->weight, az_str, el_str); } /* write points, splitting separate boundaries over separate lines */ for (iv = jv = 0; iv < nv; jv++) { for (; iv < ev[jv]; iv++) { for (ive = 0; ive < fmt->outnve; ive++) { i = iv * fmt->outnve + ive; if (ve[i][0] == 0. && ve[i][1] == 0. && ve[i][2] == 0.) break; /* convert unit vector to azel vertex */ rp_to_azel(ve[i], &v); /* set azimuth of first point */ if (iv == 0 && ive == 0) { switch (fmt->outphase) { case '+': if (v.az < 0.) v.az += TWOPI; break; case '-': if (v.az > PI) v.az -= TWOPI; break; } /* phase azimuth of each subsequent point to the previous point */ } else { v.az -= rint((v.az - azo) / TWOPI) * TWOPI; } azo = v.az; scale_azel(&v, 'r', fmt->outunitp); wrangle(v.az, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, az_str); wrangle(v.el, fmt->outunitp, fmt->outprecision, AZEL_STR_LEN, el_str); fprintf(file, " %s %s", az_str, el_str); } } fprintf(file, "\n"); } /* increment polygon count */ npoly++; } /* warn about multi-boundary polygon */ if (WARNMAX > 0 && manybounds > 0 && manybounds <= WARNMAX) msg("\n"); if (manybounds > 0) msg("%d polygons had more than one boundary (not simply-connected)\n", manybounds); /* warn about polygons producing fatal error */ if (nbadverts > 0) { msg("%d polygons producing fatal error in gvert discarded\n"); } /* advise */ msg("%d polygons written to %s\n", npoly, (file == stdout)? "output": filename); /* close file */ if (file != stdout) fclose(file); return(npoly); }
/*------------------------------------------------------------------------------ Counts of pairs in bins bounded by radii th, centred at az el. Anglar positions az, el are read from azel_in_filename, angular radii th are read from th_in_filename, or from azel_in_filename if th_in_filename is null, and the results are written to out_filename. Implemented as interpretive read/write, to permit interactive behaviour. Input: azel_in_filename = name of file to read az, el from; "" or "-" means read from standard input. th_in_filename = name of file to read th from; "" or "-" means read from standard input. out_filename = name of file to write to; "" or "-" means write to standard output. fmt = pointer to format structure. npoly = number of polygons in poly array. poly = array of pointers to polygons. Return value: number of distinct pairs counted, or -1 if error occurred. */ long ddcount(char *azel_in_filename, char *th_in_filename, char *out_filename, format *fmt, int npoly, polygon *poly[/*npoly*/]) { #define AZEL_STR_LEN 32 char input[] = "input", output[] = "output"; /* maximum number of angular angular radii: will expand as necessary */ static int nthmax = 0; /* maximum number of az-el points: will expand as necessary */ static int nazelmax = 0; static int *dd = 0x0, *id = 0x0, *iord = 0x0; static long double *cm = 0x0, *th = 0x0; static azel *v = 0x0; static vec *rp = 0x0; #ifdef TIME clock_t time; #endif char inunit; char *word, *next; char th_str[AZEL_STR_LEN]; int i, iazel, idi, ird, ith, j, jazel, manyid, nazel, nid, noid, nth; int *id_p; long np; long double az, cmm, el, s, t; char *out_fn; FILE *outfile; /* open th_in_filename for reading */ if (strcmp(th_in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(th_in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", th_in_filename); return(-1); } file.name = th_in_filename; } file.line_number = 0; inunit = (fmt->inunit == 'h')? 'd' : fmt->inunit; msg("will take units of input th angles in %s to be ", file.name); switch (inunit) { #include "angunit.h" } msg("\n"); /* read angular radii th from th_in_filename */ nth = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read angular radius from line */ ird = rdangle(file.line, &next, inunit, &t); /* error */ if (ird < 1) { /* retry if nothing read, otherwise break */ if (nth > 0) break; /* ok */ } else if (ird == 1) { if (nth >= nthmax) { if (nthmax == 0) { nthmax = 64; } else { nthmax *= 2; } /* (re)allocate memory for th array */ th = (long double *) realloc(th, sizeof(long double) * nthmax); if (!th) { fprintf(stderr, "ddcount: failed to allocate memory for %d long doubles\n", nthmax); return(-1); } } /* store th */ th[nth] = t; nth++; } } if (file.file != stdin) { /* close th_in_filename */ fclose(file.file); /* advise */ msg("%d angular radii read from %s\n", nth, file.name); } if (nth == 0) return(nth); /* open azel_in_filename for reading */ if (!azel_in_filename || strcmp(azel_in_filename, "-") == 0) { file.file = stdin; file.name = input; } else { file.file = fopen(azel_in_filename, "r"); if (!file.file) { fprintf(stderr, "cannot open %s for reading\n", azel_in_filename); return(-1); } file.name = azel_in_filename; } file.line_number = 0; /* advise input angular units */ msg("will take units of input az, el angles in %s to be ", file.name); switch (fmt->inunit) { #include "angunit.h" } msg("\n"); /* read angular positions az, el from azel_in_filename */ nazel = 0; while (1) { /* read line */ ird = rdline(&file); /* serious error */ if (ird == -1) return(-1); /* EOF */ if (ird == 0) break; /* read <az> */ word = file.line; ird = rdangle(word, &next, fmt->inunit, &az); /* skip header */ if (ird != 1 && nazel == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* read <el> */ word = next; ird = rdangle(word, &next, fmt->inunit, &el); /* skip header */ if (ird != 1 && nazel == 0) continue; /* otherwise exit on unrecognized characters */ if (ird != 1) break; /* (re)allocate memory for array of az-el points */ if (nazel >= nazelmax) { if (nazelmax == 0) { nazelmax = 64; } else { nazelmax *= 2; } v = (azel *) realloc(v, sizeof(azel) * nazelmax); if (!v) { fprintf(stderr, "ddcount: failed to allocate memory for %d az-el points\n", nazelmax); return(-1); } } /* record az-el */ v[nazel].az = az; v[nazel].el = el; /* increment number of az-el points */ nazel++; } if (file.file != stdin) { /* close azel_in_filename */ fclose(file.file); /* advise */ msg("%d angular positions az, el read from %s\n", nazel, file.name); } if (nazel == 0) return(nazel); /* open out_filename for writing */ if (!out_filename || strcmp(out_filename, "-") == 0) { outfile = stdout; out_fn = output; } else { outfile = fopen(out_filename, "w"); if (!outfile) { fprintf(stderr, "cannot open %s for writing\n", out_filename); return(-1); } out_fn = out_filename; } /* (re)allocate memory */ cm = (long double *) realloc(dd, sizeof(long double) * nth); if (!cm) { fprintf(stderr, "ddcount: failed to allocate memory for %d long doubles\n", nth); return(-1); } dd = (int *) realloc(dd, sizeof(int) * nth); if (!dd) { fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nth); return(-1); } id = (int *) realloc(id, sizeof(int) * nazel); if (!id) { fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nazel); return(-1); } rp = (vec *) realloc(rp, sizeof(vec) * nazel); if (!rp) { fprintf(stderr, "ddcount: failed to allocate memory for %d unit vectors\n", nazel); return(-1); } iord = (int *) realloc(iord, sizeof(int) * nazel); if (!iord) { fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nazel); return(-1); } /* store 1 - cosl(th) in cm array */ for (ith = 0; ith < nth; ith++) { t = th[ith]; scale(&t, inunit, 'r'); s = sinl(t / 2.); cm[ith] = 2. * s * s; } /* convert az-el angles to radians */ for (iazel = 0; iazel < nazel; iazel++) { scale_azel(&v[iazel], fmt->inunit, 'r'); } /* convert az-el points to unit vectors */ for (iazel = 0; iazel < nazel; iazel++) { azel_to_rp(&v[iazel], rp[iazel]); } /* polygon id number(s) of az-el points */ msg("figuring polygon id number(s) of each az-el point ..."); noid = 0; manyid = 0; for (iazel = 0; iazel < nazel; iazel++) { nid = poly_id(npoly, poly, v[iazel].az, v[iazel].el, &id_p); if (nid == 0) { noid++; } else if (nid > 1) { manyid++; } /* store first polygon id of point */ if (nid == 0) { id[iazel] = -1; } else { id[iazel] = id_p[0]; } } msg(" done\n"); if (noid > 0) { msg("%d az-el points lie outside the angular mask: discard them\n", noid); } if (manyid > 0) { msg("%d az-el points lie inside more than one polygon: use only first polygon\n", manyid); } /* order az-el points in increasing order of polygon id */ finibot(id, nazel, iord, nazel); /* write header */ fprintf(outfile, "th(%c):", inunit); for (ith = 0; ith < nth; ith++) { wrangle(th[ith], inunit, fmt->outprecision, AZEL_STR_LEN, th_str); fprintf(outfile, "\t%s", th_str); } fprintf(outfile, "\n"); msg("counting pairs ..."); #ifdef TIME printf(" timing ... "); fflush(stdout); time = clock(); #endif /* loop over az-el points */ idi = -1; nid = 0; np = 0; for (iazel = 0; iazel < nazel; iazel++) { i = iord[iazel]; /* skip points outside mask */ if (id[i] == -1) continue; /* new polygon */ if (id[i] != idi) { idi = id[i]; /* reset pair counts to zero */ for (ith = 0; ith < nth; ith++) dd[ith] = 0; } //printf(" %d", idi); /* az-el neighbours within same polygon */ for (jazel = iazel + 1; jazel < nazel; jazel++) { j = iord[jazel]; /* exit at new polygon */ if (id[j] != idi) break; /* 1 - cosl(th_ij) */ cmm = cmij(rp[i], rp[j]); /* ith such that cm[ith-1] <= cmm < cm[ith] */ ith = search(nth, cm, cmm); /* increment count in this bin */ if (ith < nth) dd[ith]++; /* increment total pair count */ np++; } /* write counts for this polygon */ if (iazel + 1 == nazel || id[iord[iazel + 1]] != idi) { fprintf(outfile, "%d", idi); for (ith = 0; ith < nth; ith++) { fprintf(outfile, "\t%d", dd[ith]); } fprintf(outfile, "\n"); fflush(outfile); nid++; //printf("\n"); } } #ifdef TIME time = clock() - time; printf("done in %Lg sec\n", (float)time / (float)CLOCKS_PER_SEC); #else msg("\n"); #endif /* advise */ if (outfile != stdout) { fclose(outfile); msg("%d distinct pairs in %d th-bins x %d polygons written to %s\n", np, nth, nid, out_fn); } return(np); }