Пример #1
0
/*------------------------------------------------------------------------------
  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);
}
Пример #2
0
/*------------------------------------------------------------------------------
  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);
}
Пример #3
0
/*------------------------------------------------------------------------------
  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);
}
Пример #4
0
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);
}