/*------------------------------------------------------------------------------ Lasso polygon, keeping the lassoed parts only if the sum of the areas of lassos is sufficiently less than the area of the tightest cap of the original polygon. Output: *np = number of lassoed parts; = 0 to retain original polygon. Return value: same as partition_poly: -1 if error occurred; 0 ok; 1 if *poly was only partially partioned. */ int lasso_poly(polygon **poly, int npolys, polygon *polys[/*npolys*/], long double mtol, int *np) { /* part_poly should lasso all one-boundary polygons */ #define ALL_ONEBOUNDARY 2 /* how part_poly should tighten lasso */ #define ADJUST_LASSO 2 /* part_poly should not force polygon to be split even if no part can be lassoed */ #define FORCE_SPLIT 0 /* partition_poly should never overwrite original polygons */ #define OVERWRITE_ORIGINAL 0 int ier, ip, ipmin; long double cmmin, cmmino, cmmint; /* area/(2 pi) of smallest cap of polygon */ cmminf(*poly, &ipmin, &cmmino); /* lasso polygon */ ier = partition_poly(poly, npolys, polys, mtol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, np); /* polygon was successfully lassoed */ if (ier == 0) { if (*np > 0) { /* not enough polygons */ if (*np > npolys) return(0); /* area/(2 pi) of combined smallest caps of lassoed polygon */ cmmint = 0.; for (ip = 0; ip < *np; ip++) { cmminf(polys[ip], &ipmin, &cmmin); cmmint += cmmin; } /* lassoed polygons are a genuine improvement */ if ((*np == 1 && cmmint < cmmino) || cmmint <= .9 * cmmino) { /* lassoed polygons are too large to bother with */ } else { *np = 0; } } } else { *np = 0; } return(ier); }
/*------------------------------------------------------------------------------ Pixelize: split polygons against a pre-defined pixel map such that each polygon is in only one pixel Input: npoly = number of polygons. poly = array of pointers to polygons. npolys = maximum number of output polygons. Output: polys = array of pointers to polygons. Return value: number of disjoint connected polygons, or -1 if error occurred. */ int pixelize(int npoly, polygon *poly[/*npoly*/], int npolys, polygon *polys[/*npolys*/]) { /* part_poly should lasso one-boundary polygons only if they have too many caps */ #define ALL_ONEBOUNDARY 1 /* how part_poly should tighten lasso */ #define ADJUST_LASSO 1 /* part_poly should force polygon to be split even if no part can be lassoed */ #define FORCE_SPLIT 1 /* partition_poly should overwrite all original polygons */ #define OVERWRITE_ORIGINAL 2 #define WARNMAX 8 char *snapped_polys = 0x0; int isnap,j, nadj; int dn, dnp, failed, i, ier, inull, ip, iprune, m, n, np; msg("pruning input polygons\n"); /* start by pruning all input polygons */ np = 0; inull = 0; for (i = 0; i < npoly; i++) { iprune = prune_poly(poly[i], mtol); /* error */ if (iprune == -1) { fprintf(stderr, "pixelize: initial prune failed at polygon %lld\n", poly[i]->id); return(-1); } /* zero area polygon */ if (iprune >= 2) { if (WARNMAX > 0 && inull == 0) msg("warning from pixelize: the following polygons have zero area & are being discarded:\n"); if (inull < WARNMAX) { msg(" %lld", (fmt.newid == 'o')? poly[i]->id : (long long)i+fmt.idstart); } else if (inull == WARNMAX) { msg(" ... more\n"); } inull++; } else { np++; } } if (WARNMAX > 0 && inull > 0 && inull <= WARNMAX) msg("\n"); if (inull > 0) { msg("pixelize: %d polygons with zero area are being discarded.\n", inull); } /* number of polygons */ msg("pixelizing %d polygons ...\n", np); /* set all input polygons to be in pixel 0 (whole sky)*/ inull=0; for (i = 0; i < npoly; i++) { if(poly[i]->pixel!=0){ poly[i]->pixel = 0; if(WARNMAX>0 && inull ==0) msg("warning from pixelize: following polygons are being re-set to be in pixel 0:\n"); if (inull < WARNMAX) { msg(" %lld", (fmt.newid == 'o')? poly[i]->id : (long long)i+fmt.idstart); } else if (inull == WARNMAX) { msg(" ... more\n"); } inull++; } } if (WARNMAX > 0 && inull > 0 && inull <= WARNMAX) msg("\n"); if (inull > 0) { msg("pixelize: %d polygons have been re-set to be in pixel 0.\n", inull); } /* nullify all output polygons */ for (i = 0; i < npolys; i++) { polys[i] = 0x0; } msg("pixelize stage 1 (fragment each polygon so it is in only one pixel):\n"); /*call recursive pixel_loop to split polygons into pixels*/ n=pixel_loop(0,npoly,poly,npolys,polys); if(n==-1) return(-1); dnp=n-np; np=n; msg("added %d polygons to make %d\n", dnp, np); /* partition disconnected polygons into connected parts */ msg("pixelize stage 2 (partition disconnected polygons into connected parts):\n"); m = n; dnp = 0; ip = 0; failed = 0; for (i = 0; i < m; i++) { /* skip null polygons */ if (!polys[i] || (polys[i]->np > 0 && polys[i]->cm[0] == 0.)) continue; /* partition disconnected polygons */ ier = partition_poly(&polys[i], npolys - n, &polys[n], mtol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, &dn); /* error */ if (ier == -1) { fprintf(stderr, "pixelize: UHOH at polygon %lld; continuing ...\n", (fmt.newid == 'o')? polys[i]->id : (long long)ip+fmt.idstart); continue; /* return(-1); */ /* failed to partition polygon into desired number of parts */ } else if (ier == 1) { fprintf(stderr, "pixelize: failed to partition polygon %lld fully; partitioned it into %d parts\n", (fmt.newid == 'o')? polys[i]->id : (long long)ip+fmt.idstart, dn + 1); failed++; } /* increment index of next subset of fragments */ n += dn; /* increment polygon count */ np += dn; dnp += dn; /* check whether exceeded maximum number of polygons */ if (n > npolys) { fprintf(stderr, "pixelize: total number of polygons exceeded maximum %d\n", npoly + npolys); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); return(-1); } ip++; } msg("added %d polygons to make %d\n", dnp, np); if (failed > 0) { msg("pixelize: failed to split %d polygons into desired number of connected parts\n", failed); msg(".............................................................................\n"); msg("Failure to split polygon probably means:\n"); msg("either (1) you forgot to run snap on all your input polygon files;\n"); msg(" or (2) the polygon is too small for the numerics to cope with;\n"); msg(" or (3) you have a weird-shaped polygon.\n"); msg("You may ignore this warning message if the weights of polygons in the input\n"); msg("polygon file(s) are already correct, and you do not want to reweight them.\n"); msg("Similarly, you may ignore this warning message if you do want to reweight the\n"); msg("polygons, but the weights of the different parts of each unsplit polygon are\n"); msg("the same. If you want to reweight the different parts of an unsplit polygon\n"); msg("with different weights, then you will need to split that polygon by hand.\n"); msg("Whatever the case, the output file of pixelized polygons constitutes\n"); msg("a valid mask with each polygon in only one pixel, and is safe to use.\n"); msg(".............................................................................\n"); } /* // prune msg("pruning ... \n"); j = 0; inull = 0; for (i = 0; i < n; i++) { iprune = prune_poly(polys[i], mtol); if (iprune == -1) { fprintf(stderr, "pixelize: failed to prune polygon %lld; continuing ...\n", (fmt.newid == 'o')? polys[i]->id : (long long)j+fmt.idstart); return(-1); } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("pixelize: %d pixelized polygons have zero area, and are being discarded\n", inull); n = j; //allocate snapped_polys array snapped_polys = (char *) malloc(sizeof(char) * n); if (!snapped_polys) { fprintf(stderr, "pixelize: failed to allocate memory for %d characters\n", n); return(-1); } //snap edges of each polygon selfsnap = 1; nadj = snap_polys(&fmt, n, polys, selfsnap, axtol, btol, thtol, ytol, mtol, WARNMAX, snapped_polys); if(nadj==-1){ msg("pixelize: error snapping pixelized polygons\n"); return(-1); } //number of polygons whose edges were snapped isnap = 0; for (i = 0; i < n; i++) if (snapped_polys[i]) isnap++; if (isnap > 0) msg("pixelize: edges of %d pixelized polygons were snapped\n", isnap); //prune snapped polygons j = 0; inull = 0; for (i = 0; i < n; i++) { if (snapped_polys[i]) { iprune = prune_poly(polys[i], mtol); if (iprune == -1) { fprintf(stderr, "pixelize: failed to prune polygon %lld; continuing ...\n", (fmt.newid == 'o')? polys[i]->id : (long long)j+fmt.idstart); // return(-1); } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("pixelize: %d snapped polygons have zero area, and are being discarded\n", inull); n = j; //free snapped_polys array free(snapped_polys); */ if(n!=-1){ /* sort polygons by pixel number */ poly_sort(n, polys, 'p'); } /* assign new polygon id numbers in place of inherited ids */ if (fmt.newid == 'n') { for (i = 0; i < n; i++) { polys[i]->id = (long long)i+fmt.idstart; } } if (fmt.newid == 'p') { for (i = 0; i < n; i++) { polys[i]->id = (long long)polys[i]->pixel; } } return(n); }
/*------------------------------------------------------------------------------ Balkanize overlapping polygons into many disjoint connected polygons. Input: npoly = number of polygons. poly = array of pointers to polygons. npolys = maximum number of output polygons. mtol = tolerance angle for multiple intersections. fmt = pointer to format structure. axtol, btol, thtol, ytol = tolerance angles (see documentation). Output: polys = array of pointers to polygons. Return value: number of disjoint connected polygons, or -1 if error occurred. */ int balkanize(int npoly, polygon *poly[/*npoly*/], int npolys, polygon *polys[/*npolys*/], long double mtol, format *fmt, long double axtol, long double btol, long double thtol, long double ytol) { /* part_poly should lasso one-boundary polygons only if they have too many caps */ #define ALL_ONEBOUNDARY 1 /* how part_poly should tighten lasso */ #define ADJUST_LASSO 1 /* part_poly should force polygon to be split even if no part can be lassoed */ #define FORCE_SPLIT 1 /* partition_poly should overwrite all original polygons */ #define OVERWRITE_ORIGINAL 2 #define WARNMAX 8 char *snapped_polys = 0x0; int discard, dm, dn, dnp, failed, i, ier, inull, isnap, ip, iprune, j, k, m, n, nadj, np, selfsnap; int *start; int *total; int begin, end, p, max_pixel; long double tol; poly_sort(npoly, poly, 'p'); /* allocate memory for pixel info arrays start and total */ max_pixel=poly[npoly-1]->pixel+1; start = (int *) malloc(sizeof(int) * max_pixel); if (!start) { fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel); return(-1); } total = (int *) malloc(sizeof(int) * max_pixel); if (!total) { fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel); 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) { fprintf(stderr, "balkanize: error building pixel index lists\n"); return(-1); } /* start by pruning all input polygons */ np = 0; inull = 0; for (i = 0; i < npoly; i++) { tol = mtol; iprune = prune_poly(poly[i], tol); /* error */ if (iprune == -1) { fprintf(stderr, "balkanize: initial prune failed at polygon %d\n", poly[i]->id); return(-1); } /* zero area polygon */ if (iprune >= 2) { if (WARNMAX > 0 && inull == 0) msg("warning from balkanize: following polygons have zero area & are being discarded:\n"); if (inull < WARNMAX) { msg(" %lld", (fmt->newid == 'o')? poly[i]->id : (long long)i); } else if (inull == WARNMAX) { msg(" ... more\n"); } inull++; } else { np++; } } if (WARNMAX > 0 && inull > 0 && inull <= WARNMAX) msg("\n"); if (inull > 0) { msg("balkanize: %d polygons with zero area are being discarded;\n", inull); } /* number of polygons */ msg("balkanizing %d polygons ...\n", np); /* nullify all output polygons */ for (i = 0; i < npolys; i++) { polys[i] = 0x0; } /* m = starting index of current set of fragments of i'th polygon dm = number of current set of fragments of i'th polygon n = starting index of new subset of fragments of i'th polygon dn = number of new subset of fragments of i'th polygon */ msg("balkanize stage 1 (fragment into non-overlapping polygons):\n"); n = 0; dnp = 0; ip = 0; /* go through each pixel and fragment each polygon against the other polygons in its pixel */ for(p=0;p<max_pixel;p++){ begin=start[p]; end=start[p]+total[p]; /* too many polygons */ if (n >= npolys) break; /* fragment each polygon in turn */ for (i = begin; i < end; i++) { /* skip null polygons */ if (poly[i]->np > 0 && poly[i]->cm[0] == 0.) continue; /* update indices */ m = n; dm = 1; n = m + dm; /* make sure output polygon has enough room */ ier = room_poly(&polys[m], poly[i]->np, DNP, 0); if (ier == -1) { fprintf(stderr, "balkanize: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP); return(-1); } /* copy polygon i into output polygon */ copy_poly(poly[i], polys[m]); /* fragment successively against other polygons */ for (j = begin; j < end; j++) { /* skip self, or null polygons */ if (j == i || (poly[j]->np > 0 && poly[j]->cm[0] == 0.)) continue; /* keep only one copy of the intersection of i & j */ /* intersection inherits weight of polygon being fragmented, so keeping later polygon ensures intersection inherits weight of later polygon */ if (i < j) { discard = 1; } else { discard = 0; } /* fragment each part of i'th polygon */ for (k = m; k < m + dm; k++) { /* skip null polygons */ if (!polys[k] || (polys[k]->np > 0 && polys[k]->cm[0] == 0.)) continue; /* fragment */ tol = mtol; dn = fragment_poly(&polys[k], poly[j], discard, npolys - n, &polys[n], tol, bmethod); /* error */ if (dn == -1) { fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip); continue; /* return(-1); */ } /* increment index of next subset of fragments */ n += dn; /* increment polygon count */ np += dn; dnp += dn; if (!polys[k]) { np--; dnp--; } /* check whether exceeded maximum number of polygons */ //printf("(1) n = %d\n", n); if (n > npolys) { fprintf(stderr, "(1) balkanize: total number of polygons (= %d) exceeded maximum %d\n", npoly + n, npoly + npolys); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); fprintf(stderr, "currently, dn = %d, np = %d, dnp = %d, poly[%d]->id = %lld, poly[%d]->pixel = %d\n", dn, np, dnp, i, poly[i]->id, i, poly[i]->pixel); n = npolys; #ifdef CARRY_ON_REGARDLESS break; #else return(-1); #endif } } /* copy down non-null polygons */ dm = 0; for (k = m; k < n; k++) { if (polys[k]) { polys[m + dm] = polys[k]; dm++; } } /* nullify but don't free, because freeing polys[k] will free polys[m + dm] */ for (k = m + dm; k < n; k++) { polys[k] = 0x0; } n = m + dm; if (dm == 0) break; } /* too many polygons */ if (n >= npolys) break; ip++; } } free(start); free(total); msg("added %d polygons to make %d\n", dnp, np); // partition disconnected polygons into connected parts msg("balkanize stage 2 (partition disconnected polygons into connected parts):\n"); m = n; dnp = 0; ip = 0; failed = 0; for (i = 0; i < m; i++) { // skip null polygons if (!polys[i] || (polys[i]->np > 0 && polys[i]->cm[0] == 0.)) continue; // partition disconnected polygons tol = mtol; ier = partition_poly(&polys[i], npolys - n, &polys[n], tol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, &dn); // error if (ier == -1) { fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip); continue; // return(-1); // failed to partition polygon into desired number of parts } else if (ier == 1) { fprintf(stderr, "balkanize: failed to partition polygon %lld fully; partitioned it into %d parts\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip, dn + 1); failed++; } // increment index of next subset of fragments n += dn; // increment polygon count np += dn; dnp += dn; // check whether exceeded maximum number of polygons //printf("(2) n = %d\n", n); if (n > npolys) { fprintf(stderr, "(2) balkanize: total number of polygons (= %d) exceeded maximum %d\n", n + npoly, npoly + npolys); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); n = npolys; #ifdef CARRY_ON_REGARDLESS break; #else return(-1); #endif } ip++; } msg("added %d polygons to make %d\n", dnp, np); if (failed > 0) { msg("balkanize: failed to split %d polygons into desired number of connected parts\n", failed); msg(".............................................................................\n"); msg("Failure to split polygon probably means:\n"); msg("either (1) you forgot to run snap on all your input polygon files;\n"); msg(" or (2) the polygon is too small for the numerics to cope with;\n"); msg(" or (3) you have a weird-shaped polygon.\n"); msg("You may ignore this warning message if the weights of polygons in the input\n"); msg("polygon file(s) are already correct, and you do not want to reweight them.\n"); msg("Similarly, you may ignore this warning message if you do want to reweight the\n"); msg("polygons, but the weights of the different parts of each unsplit polygon are\n"); msg("the same. If you want to reweight the different parts of an unsplit polygon\n"); msg("with different weights, then you will need to split that polygon by hand.\n"); msg("Whatever the case, the output file of balkanized polygons constitutes\n"); msg("a valid mask of non-overlapping polygons, which is safe to use.\n"); msg(".............................................................................\n"); } /* prune */ j = 0; inull = 0; for (i = 0; i < n; i++) { tol = mtol; iprune = prune_poly(polys[i], tol); if (iprune == -1) { fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j); /* return(-1); */ } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("balkanize: %d balkanized polygons have zero area, and are being discarded\n", inull); n = j; /* // allocate snapped_polys array snapped_polys = (char *) malloc(sizeof(char) * n); if (!snapped_polys) { fprintf(stderr, "balkanize: failed to allocate memory for %d characters\n", n); return(-1); } //snap edges of each polygon selfsnap = 1; nadj = snap_polys(fmt, n, polys, selfsnap, axtol, btol, thtol, ytol, mtol, WARNMAX, snapped_polys); if(nadj==-1){ msg("balkanize: error snapping balkanized polygons\n"); return(-1); } // number of polygons whose edges were snapped isnap = 0; for (i = 0; i < n; i++) if (snapped_polys[i]) isnap++; if (isnap > 0) msg("balkanize: edges of %d balkanized polygons were snapped\n", isnap); // prune snapped polygons j = 0; inull = 0; for (i = 0; i < n; i++) { if (snapped_polys[i]) { iprune = prune_poly(polys[i], mtol); if (iprune == -1) { fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j); // return(-1); } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("balkanize: %d snapped polygons have zero area, and are being discarded\n", inull); n = j; // free snapped_polys array free(snapped_polys); */ if(n!=-1){ /* sort polygons by pixel number */ poly_sort(n, polys,'p'); msg("balkanize: balkans contain %d polygons\n", n); } /* assign new polygon id numbers in place of inherited ids */ if (fmt->newid == 'n') { for (i = 0; i < n; i++) { polys[i]->id = (long long)i; } } if (fmt->newid == 'p') { for (i = 0; i < n; i++) { polys[i]->id = (long long)polys[i]->pixel; } } return(n); }
int grow_poly(polygon **poly, int npolys, polygon *polys[/*npolys*/], long double grow_angle, long double mtol, int *np){ int i, ip, jp, iret, ier, dn; long double s, cmi, cm_new,theta, theta_new, tol; polygon *poly1= 0x0; /* part_poly should lasso all one-boundary polygons */ #define ALL_ONEBOUNDARY 2 /* how part_poly should tighten lasso */ #define ADJUST_LASSO 2 /* part_poly should force polygon to be split even if no part can be lassoed */ #define FORCE_SPLIT 1 /* partition_poly should overwrite all original polygons */ #define OVERWRITE_ORIGINAL 2 if((*poly)->pixel!=0){ fprintf(stderr, "Error: input polygon is pixelized. The grow function can only be applied to non-pixelized polygons."); return(-1); } *np=0; // partition disconnected polygons tol = mtol; ier = partition_poly(poly, npolys, polys, tol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, &dn); // error if (ier == -1) { fprintf(stderr, "grow: UHOH at polygon %lld; continuing ...\n",polys[i]->id); // return(-1); // failed to partition polygon into desired number of parts } else if (ier == 1) { fprintf(stderr, "grow: failed to partition polygon %lld fully; partitioned it into %d parts\n", (*poly)->id, dn + 1); } *np+=dn; // check whether exceeded maximum number of polygons //printf("(2) n = %d\n", n); if (*np > npolys) { fprintf(stderr, "grow: total number of polygons exceeded maximum\n"); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); return(-1); } for(i=-1; i<*np; i++){ if(i=-1) poly1=(*poly); else poly1=polys[i]; for (ip = 0; ip < poly1->np; ip++) { cmi=poly1->cm[ip]; //convert cm into an angle s = sqrtl(fabsl(cmi) / 2.); if (s > 1.) s = 1.; theta = 2. * asinl(s); theta=(cmi >= 0.)? theta : -theta; theta_new=theta+grow_angle; // if growing angle has caused cap to encompass whole sphere, set cm_new=2 to make it superfluous if(theta>=0 && theta_new>=PI) cm_new=2.; else if(theta<0 && theta_new>=0) cm_new=2.; // if growing angle (with a negative value for grow_angle) has shrunk cap to less than nothing, make polygon null else if(theta>=0 && theta_new<0) cm_new=0.; else if(theta<0 && theta_new<=-PI) cm_new=0.; // otherwise convert normally else{ /* 1 - cosl(radius) = 2 sin^2(radius/2) */ s = sinl(theta_new / 2.); cm_new = s * s * 2.; cm_new = (theta_new >= 0.)? cm_new : -cm_new; } poly1->cm[ip]=cm_new; } tol=mtol; iret=prune_poly(poly1,tol); } return(iret); }