/*------------------------------------------------------------------------------ Convert unit vectors to vertices structure. Input: rp = array of nv unit vectors. nv = number of unit vectors. Output: pointer to a vertices structure. */ void rps_to_vert(int nv, vec rp[/*nv*/], vertices *vert) { int iv; /* number of vertices */ vert->nv = nv; /* convert vectors to vertices */ for (iv = 0; iv < nv; iv++) { rp_to_azel(rp[iv], &vert->v[iv]); } /* phase each vertex to the previous */ for (iv = 1; iv < nv; iv++) { vert->v[iv].az -= rint((vert->v[iv].az - vert->v[iv-1].az) / TWOPI) * TWOPI; } }
/*------------------------------------------------------------------------------ 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); }
polygon *get_healpix_poly(int nside, int hpix) { int nv, nvmax, i, pix_n, pix_e, pix_s, pix_w, ev[1]; vertices *vert; polygon *pixel, *pixelbetter; long double verts_vec[12], verts_vec_n[12], verts_vec_e[12], verts_vec_s[12], verts_vec_w[12], dist_n, dist_w, dist_s, dist_e; vec center, center_n, center_e, center_s, center_w, vertices_vec[4], vertices_vec_n[4], vertices_vec_e[4], vertices_vec_s[4], vertices_vec_w[4]; azel *vertices_azel[8], vertices[8]; for(i=0;i<=7;i++) vertices_azel[i] = &(vertices[i]); if (nside == 0) { pixel=new_poly(0); pixel->weight=1; pixel->pixel=0; return(pixel); } else { healpix_verts(nside, hpix, center, verts_vec); /* north vertex */ for(i=0;i<=2;i++) (vertices_vec[0])[i] = verts_vec[i]; /* east vertex */ for(i=0;i<=2;i++) (vertices_vec[1])[i] = verts_vec[i+3]; /* south vertex */ for(i=0;i<=2;i++) (vertices_vec[2])[i] = verts_vec[i+6]; /* west vertex */ for(i=0;i<=2;i++) (vertices_vec[3])[i] = verts_vec[i+9]; rp_to_azel(vertices_vec[0], vertices_azel[0]); rp_to_azel(vertices_vec[3], vertices_azel[2]); rp_to_azel(vertices_vec[2], vertices_azel[4]); rp_to_azel(vertices_vec[1], vertices_azel[6]); pix_n = 4*hpix + 3; pix_e = 4*hpix + 1; pix_s = 4*hpix; pix_w = 4*hpix + 2; healpix_verts(nside*2, pix_n, center_n, verts_vec_n); healpix_verts(nside*2, pix_e, center_e, verts_vec_e); healpix_verts(nside*2, pix_s, center_s, verts_vec_s); healpix_verts(nside*2, pix_w, center_w, verts_vec_w); /* north vertex of each child pixel */ for(i=0;i<=2;i++){ (vertices_vec_n[0])[i] = verts_vec_n[i]; (vertices_vec_e[0])[i] = verts_vec_e[i]; (vertices_vec_s[0])[i] = verts_vec_s[i]; (vertices_vec_w[0])[i] = verts_vec_w[i]; } /* east vertex of each child pixel */ for(i=0;i<=2;i++){ (vertices_vec_n[1])[i] = verts_vec_n[i+3]; (vertices_vec_e[1])[i] = verts_vec_e[i+3]; (vertices_vec_s[1])[i] = verts_vec_s[i+3]; (vertices_vec_w[1])[i] = verts_vec_w[i+3]; } /* south vertex of each child pixel */ for(i=0;i<=2;i++){ (vertices_vec_n[2])[i] = verts_vec_n[i+6]; (vertices_vec_e[2])[i] = verts_vec_e[i+6]; (vertices_vec_s[2])[i] = verts_vec_s[i+6]; (vertices_vec_w[2])[i] = verts_vec_w[i+6]; } /* west vertex of each child pixel */ for(i=0;i<=2;i++){ (vertices_vec_n[3])[i] = verts_vec_n[i+9]; (vertices_vec_e[3])[i] = verts_vec_e[i+9]; (vertices_vec_s[3])[i] = verts_vec_s[i+9]; (vertices_vec_w[3])[i] = verts_vec_w[i+9]; } rp_to_azel(vertices_vec_n[3], vertices_azel[1]); rp_to_azel(vertices_vec_w[2], vertices_azel[3]); rp_to_azel(vertices_vec_s[1], vertices_azel[5]); rp_to_azel(vertices_vec_e[0], vertices_azel[7]); for(i=0; i<8; i++){ if(vertices[i].az < 0.) vertices[i].az = vertices[i].az + TWOPI; else {}; } for(i=0; i<8; i++){ if(vertices[i].az >= TWOPI) vertices[i].az = vertices[i].az - TWOPI; else {}; } nv=8; nvmax=8; vert=new_vert(nvmax); if(!vert){ fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for 8 vertices\n"); return(0x0); } vert->nv=nv; vert->v=&vertices[0]; pixel=new_poly(4); if(!pixel){ fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for polygon of 4 caps\n"); return(0x0); } ev[0] = 8; edge_to_poly(vert, 2, &ev[0], pixel); pixel->id = (long long)hpix; pixelbetter=new_poly(5); if(!pixelbetter){ fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for polygon of 5 caps\n"); return(0x0); } pixelbetter->np = 5; pixelbetter->npmax = 5; for(i=0; i<=3; i++) { pixelbetter->rp[i][0] = pixel->rp[i][0]; pixelbetter->rp[i][1] = pixel->rp[i][1]; pixelbetter->rp[i][2] = pixel->rp[i][2]; pixelbetter->cm[i] = pixel->cm[i]; } pixelbetter->rp[4][0] = center[0]; pixelbetter->rp[4][1] = center[1]; pixelbetter->rp[4][2] = center[2]; pixelbetter->id = (long long)hpix; dist_n = cmrpirpj(center, vertices_vec[0]); dist_w = cmrpirpj(center, vertices_vec[3]); dist_s = cmrpirpj(center, vertices_vec[2]); dist_e = cmrpirpj(center, vertices_vec[1]); if(dist_n>=dist_w && dist_n>=dist_s && dist_n>=dist_e){ pixelbetter->cm[4] = dist_n+0.000001; } else if(dist_w>=dist_n && dist_w>=dist_s && dist_w>=dist_e){ pixelbetter->cm[4] = dist_w+0.000001; } else if(dist_s>=dist_n && dist_s>=dist_w && dist_s>=dist_e){ pixelbetter->cm[4] = dist_s+0.000001; } else if(dist_e>=dist_n && dist_e>=dist_s && dist_e>=dist_w){ pixelbetter->cm[4] = dist_e+0.000001; } else{ fprintf(stderr, "error in get_healpix_poly: cannot find correct fifth cap\n"); return(0x0); } if(!pixelbetter){ fprintf(stderr, "error in get_healpix_poly: polygon is NULL.\n"); return(0x0); } return(pixelbetter); } }
/*------------------------------------------------------------------------------ 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); }
/*------------------------------------------------------------------------------ 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); }