/*------------------------------------------------------------------------------ Determine whether the first vertex in vert is closer to the nearest vertex or to the nearest antivertex of poly. Return value: 0 or 1 as first vertex of vert is closer to the nearest vertex or antivertex of poly; -1 if error. */ int antivert(vertices *vert, polygon *poly) { const int do_vcirc = 0, nve = 1, per = 0; int anti, ier, iv, nev, nev0, nv; int *ipv, *gp, *ev; double cm, cmmax, cmmin, tol; double *angle; vec rp; vec *ve; /* vert has no vertices */ if (vert->nv == 0) return(0); /* vertices of polygon */ tol = mtol; ier = gverts(poly, do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev); /* error */ if (ier) return(-1); /* poly has less than 3 vertices */ if (nv < 3) return(0); /* convert first vertex to unit vector */ azel_to_rp(&vert->v[0], rp); cmmin = 2.; cmmax = 0.; for (iv = 0; iv < nv; iv++) { cm = cmij(rp, ve[iv]); if (cm < cmmin) cmmin = cm; if (cm > cmmax) cmmax = cm; } anti = ((cmmin + cmmax <= 2.)? 0 : 1); return(anti); }
/*------------------------------------------------------------------------------ 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); }
/*------------------------------------------------------------------------------ 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); }