Ejemplo n.º 1
0
void draw_models()
{
	glm::vec2 midScreen( 0.5f*proto->getWindowWidth(), 0.5f*proto->getWindowHeight() );
	glm::vec2 mouse_coords( (float)proto->getMouseX(), (float)proto->getMouseY() );

	poly shape1 = makeBox( midScreen, 60, 80 );
	//poly shape1 = makePoly( midScreen, 50.f, 7 );
	poly shape2 = makePoly( mouse_coords, 25.f, 6 );
	
	vertexList numIsects = poly_poly(shape1, shape2);

	if ( numIsects.size() > 0 ) {
		proto->setColor(1.f, 0.f, 0.f); // no seperating axis

		for (auto it=numIsects.begin(); it!=numIsects.end(); ++it){
			auto v = *it;
			proto->drawCircle( v.x, v.y, 3 );
		}

	} else {
		proto->setColor( 0.f, 1.f, 0.f ); 
	}

	glm::vec2 mouseCoord( (float)proto->getMouseX(), (float)proto->getMouseY() );
	if ( containsv(shape1, mouseCoord) ) {
		proto->drawCircle( mouseCoord.x, mouseCoord.y, -3 );
	}

	shape1.draw( glm::vec2(0.f) );
	shape2.draw( glm::vec2(0.f) );
}
Ejemplo n.º 2
0
/*------------------------------------------------------------------------------
  Intersect polygons of poly1 with any polygon(s) of poly2 having the
  same id number.

  This subroutine implements the -n option of poly2poly.
*/
int intersect_poly(int npoly1, polygon *poly1[/*npoly1*/], int npoly2, polygon *poly2[/*npoly2*/], long double mtol)
{
    int ier, inull, iprune, i, j, k, np;

    /* intersect each poly1 with any poly2 having same id number */
    for (i = 0; i < npoly1; i++) {
	for (j = 0; j < npoly2; j++) {
	    if (poly1[i]->id == poly2[j]->id && poly1[i]->pixel == poly2[j]->pixel ) {
		/* make sure poly1 contains enough space for intersection */
		np = poly1[i]->np + poly2[j]->np;
		ier = room_poly(&poly1[i], np, 0, 1);
		if (ier == -1) goto out_of_memory;

		/* intersection of poly1 and poly2 */
		poly_poly(poly1[i], poly2[j], poly1[i]);
	    }
	}
    }

    /* free poly2 polygons */
    for (j = 0; j < npoly2; j++) {
        free_poly(poly2[j]);
	poly2[j] = 0x0;
    }

    /* prune poly1 polygons */
    j = 0;
    inull = 0;
    for (i = 0; i < npoly1; i++) {
          iprune = prune_poly(poly1[i], mtol);
        if (iprune == -1) {
	  fprintf(stderr, "intersect_poly: failed to prune polygon %lld; continuing ...\n", (fmt.newid == 'o')? poly1[i]->id : (long long)j+fmt.idstart);
	}
	if (iprune >= 2) {
	    free_poly(poly1[i]);
	    poly1[i] = 0x0;
	    inull++;
	} else {
	    j++;
	}
   }

   /*copy down non-null polygons*/
    k=0;
    for(i = 0; i < npoly1; i++){
      if(poly1[i]){
	poly1[k++]=poly1[i];
      }
    }
    /*after copying non-null polygons, k should be equal to j */
    if(k!=j){
      fprintf(stderr, "intersect_poly: should be left with %d non-null polygons, but actually have %d\n",j,k);
    }

    /*nullify the rest of the array, but don't free, since pointers have been copied above*/
    for(i=j; i < npoly1; i++){
      poly1[i]=0x0;
    }

    if (inull > 0) msg("%d intersected polygons have zero area, and are being discarded\n", inull);
    npoly1 = j;

    return(npoly1);

    /* ---------------- error returns ---------------- */
    out_of_memory:
    fprintf(stderr, "intersect_poly: failed to allocate memory for polygon of %d caps\n", np);
    return(-1);
}
Ejemplo n.º 3
0
int pixel_loop(int pix, int n, polygon *input[/*n*/], int out_max, polygon *output[/*out_max*/]){
  int *child_pix,children;
  int i,j,k,m,out,nout;
  int ier, iprune, np;
  polygon *pixel;
  polygon **poly;
 
  //allocate memory for work array of polygon pointers
  poly=(polygon **) malloc(sizeof(polygon *) * n);
  if(!poly){
    fprintf(stderr, "pixel_loop: failed to allocate memory for %d polygon pointers\n",n);
    return(-1);
  }
  
  // allocate memory for child_pix array
  if(pix==0 && scheme=='d'){
    child_pix=(int *) malloc(sizeof(int) * 117);
    children=117;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for 117 integers\n");
      return(-1);
    }
  }
  else{
    child_pix=(int *) malloc(sizeof(int) * 4);
    children=4;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for %d integers\n", 4);
      return(-1);
    }
  }

  get_child_pixels(pix, child_pix, scheme);
  out=0;
  
  for(i=0;i<children;i++){    
    /*get the current child pixel*/
    pixel=get_pixel(child_pix[i], scheme);
 
    if(!pixel){
      fprintf(stderr, "error in pixel_loop: could not get pixel %d\n", child_pix[i]); 
      return(-1);
    }
    
    /*loop through input polygons to find the ones that overlap with current child pixel*/
    for(j=0;j<n;j++){
      /* skip null polygons */
      if (input[j]->np > 0 && input[j]->cm[0] == 0.){
	poly[j] = 0x0;
	continue;
      }

      np=input[j]->np+pixel->np;
      poly[j]=new_poly(np);
      if(!poly[j]){
	fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", np);
	return(-1);
      }
      /*set poly[j] to the intersection of input[j] and current child pixel*/
      poly_poly(input[j],pixel,poly[j]);
      poly[j]->pixel=pixel->pixel;
    
      iprune = prune_poly(poly[j], mtol);
      if (iprune == -1) {
	fprintf(stderr, "pixelize: failed to prune polygon for pixel %d; continuing ...\n", poly[j]->pixel);
	//return(-1);
      }
      /*if polygon is null, get rid of it*/
      if (iprune >= 2) {
	free_poly(poly[j]);
	poly[j] = 0x0;
      }       
    }
    
    /*copy down non-null polygons*/
    k=0;
    for(j=0;j<n;j++){
      if(poly[j]){
	poly[k++]=poly[j];
      }
    }
    m=k;
    /*nullify the rest of the array, but don't free, since pointers have been copied above*/
    for(j=m;j<n;j++){
      poly[j]=0x0;
    }
    
    /*if we're below the max resolution, recursively call pixel_loop on the current child pixel */ 
    if(m>polys_per_pixel && get_res(child_pix[i],scheme)<res_max){
      //printf("calling pixel loop for pixel %d with %d polygons\n",child_pix[i],m);
      nout=pixel_loop(child_pix[i],m,poly,out_max-out,&output[out]);
      if(nout==-1) return(-1);
      out+=nout;
    }
    else{
      for(k=0;k<m;k++){
	/* check whether exceeded maximum number of polygons */
	if (out >= out_max) {
	  fprintf(stderr, "pixel_loop: total number of polygons exceeded maximum %d\n", NPOLYSMAX);
	  fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n");
	  return(-1);
	}
	/*make sure output polygon has enough room */
	ier = room_poly(&output[out], poly[k]->np, DNP, 0);
	if (ier == -1) {
	  fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP);
	  return(-1);
	}

	/*copy polygon to output array*/
	copy_poly(poly[k],output[out]);
	out++;    
      }
    }
    /*free up memory for next child pixel*/
    
    free_poly(pixel);
    for(j=0;j<n;j++){
      free_poly(poly[j]);
    }
  }
  free(child_pix);
  free(poly);
  return out;
}
Ejemplo n.º 4
0
/*------------------------------------------------------------------------------
  If poly1 overlaps poly2, split poly1 into two parts.

  If poly3 is null on input, then the appropriate return value is returned,
  but poly1 is not actually split.

   Input: *poly1, poly2 are 2 polygons.
	  mtol = initial angular tolerance within which to merge multiple intersections.
  Output: If **poly3 is not null on input, then:
	      *poly1 and *poly3 are 2 split polygons of poly1, if poly1 is split,
		    with *poly1 the part outside poly2,
		    and *poly3 the part intersecting poly2;
	      *poly1 and *poly3 remain untouched if poly1 is not split.
	  If **poly3 is null on input, then *poly1 remains untouched.
  Return value: -1 = error occurred;
		0 = poly1 and poly2 have zero intersection;
		1 = poly2 fully encloses poly1;
		2 = poly2 splits poly1 into two.
*/
int split_poly(polygon **poly1, polygon *poly2, polygon **poly3, double mtol, char bmethod)

{
    static polygon *poly = 0x0, *poly4 = 0x0;

    int ier, ip, iprune, np, np1, verb;
    double area, area_tot, cm, tol;

    /* poly2 is whole sphere, therefore contains poly1 */
    if (poly2->np == 0){
      /* set weight according to balkanization scheme: */
      if(bmethod=='l'){
	//do nothing - this is the default behavior
      }
      else if(bmethod=='a'){
	(*poly1)->weight=(*poly1)->weight + poly2->weight;
      }
      else if(bmethod=='n'){
	(*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
      }
      else if(bmethod=='x'){
	(*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
      }
      else{
	fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
	return(-1);
      }
      return(1);
    }
    
    /* make sure poly contains enough space for intersection */
    np = (*poly1)->np + poly2->np;
    ier = room_poly(&poly, np, DNP, 0);
    if (ier == -1) goto out_of_memory;

    /* intersection of poly1 and poly2 */
    poly_poly(*poly1, poly2, poly);

    /* suppress coincident boundaries, to make garea happy */
    iprune = trim_poly(poly);

    /* intersection of poly1 and poly2 is null polygon */
    if (iprune >= 2) return(0);

    /* area of intersection */
    tol = mtol;
    verb = 1;
    ier = garea(poly, &tol, verb, &area_tot);
    if (ier) goto error;

    /* poly1 and poly2 have zero intersection */
    if (area_tot == 0.) return(0);

    /* number of caps of poly1 */
    np1 = (*poly1)->np; 

    /* find boundary of poly2 which intersects poly1 */
    verb = 0;

    for (ip = 0; ip < poly2->np; ip++) {

	cm = poly->cm[np1 + ip];
	poly->cm[np1 + ip] = 2.;		/* suppress boundary to be tested */
	tol = mtol;
	ier = garea(poly, &tol, verb, &area);	/* area of intersection sans boundary */
	poly->cm[np1 + ip] = cm;		/* restore tested boundary */

	if (area > area_tot) {			/* boundary intersects poly1 */
	  /* poly2 splits poly1, but do not actually split */
	  if (!poly3) return(2);

	  /* number of caps of poly1 with extra boundary */
	  np = np1 + 1;
	  
	  /* make sure poly3 contains enough space */
	  ier = room_poly(poly3, np, DNP, 0);
	  
	  if (ier == -1) goto out_of_memory;	  
	  
	  /* poly3 is intersection of poly1 and ip'th cap of poly2 */
	  poly_polyn(*poly1, poly2, ip, 1, *poly3);
	  
	  /* prune poly3 */
	  iprune = prune_poly(*poly3, mtol);
	  if (iprune == -1) goto error;
	  /* poly3 may be null because of roundoff: skip to next cap */
	  if (iprune >= 2) continue;
	  
	  /* make sure poly4 contains enough space */
	  ier = room_poly(&poly4, np, DNP, 1);
	  if (ier == -1) goto out_of_memory;
	  
	  /* poly4 is intersection of poly1 and complement of ip'th cap of poly2 */
	  poly_polyn(*poly1, poly2, ip, -1, poly4);
	  
	  /* prune poly4 */
	  iprune = prune_poly(poly4, mtol);
	  if (iprune == -1) goto error;
	  /* poly4 may be null because of roundoff: skip to next cap */
	  if (iprune >= 2) continue;
	  
	  /* make sure poly1 contains enough space */
	  np = poly4->np;
	  ier = room_poly(poly1, np, DNP, 0);
	  if (ier == -1) goto out_of_memory;
	  
	  /* copy poly4 into poly1 */
	  copy_poly(poly4, *poly1);
	  
	  /* poly1 successfully split into poly1 and poly3 */
	  /* set weight according to balkanization scheme: */
	  if(bmethod=='l'){
	    //do nothing - this is the default behavior
	  }
	  else if(bmethod=='a'){
	    (*poly3)->weight=(*poly1)->weight + poly2->weight;
	  }
	  else if(bmethod=='n'){
	    (*poly3)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
	  }
	  else if(bmethod=='x'){
	    (*poly3)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
	  }
	  else{
	    fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
	    return(-1);
	  }

	  return(2);

	} else if (area < area_tot) {
	    /* area should be >= area_tot because suppressing a boundary of poly should always increase its area;
	       but this can happen because of roundoff */
	    //fprintf(stderr, "split_poly: area %.16g of polygon with boundary %d suppressed should be >= area %.16g of polygon\n", area, ip, area_tot);
	}
    }
    
    /* poly2 contains poly1 */
    /* set weight according to balkanization scheme: */
    if(bmethod=='l'){
      //do nothing - this is the default behavior
    }
    else if(bmethod=='a'){
      (*poly1)->weight=(*poly1)->weight + poly2->weight;
    }
    else if(bmethod=='n'){
      (*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
    }
    else if(bmethod=='x'){
      (*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
    }
    else{
      fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
      return(-1);
    }
    return(1);

    /* ---------------- error returns ---------------- */
    error:
    return(-1);

    out_of_memory:
    fprintf(stderr, "split_poly: failed to allocate memory for polygon of %d caps\n", np + DNP);
    return(-1);
}
Ejemplo n.º 5
0
/*------------------------------------------------------------------------------
  Partition a polygon by lassoing its connected boundaries with circles.

  Normally the input polygon poly would be a group polygon,
  all of whose connected boundaries belong to a single group.
  If the boundaries of the input polygon belong to more than one group,
  then the polygon is not simply-connected, and each non-simply-connected part
  of the polygon will contain two or more boundaries.
  The algorithm will attempt to lasso all these boundaries, even though
  lassoing boundaries of a non-simply-connected part of the polygon
  cannot partition the polygon.

  The routine attempts to lasso all the connected boundaries of a polygon,
  unless the polygon has only a single connected boundary.
  If the polygon has a single connected boundary, then
  the all_oneboundary option controls whether or not this boundary is lassoed.

  An attempted lasso is discarded if it lies fully inside or fully outside
  all the caps of the polygon.  It would be incorrect to retain a lasso
  that lies fully inside the polygon, and it would be superfluous to retain
  a lasso that fully encloses the polygon.
  In the normal case where the input polygon is a group polygon,
  a lasso can lie fully inside or outside the caps of the group polygon
  if the group polygon has a single connected boundary.

  If the input polygon has two or more connected boundaries none of which
  can be lassoed, then the force_split option controls whether the
  routine gives up, or else forcibly splits the input polygon into two parts,
  each of which will require further splitting.

   Input: poly is a polygon.
	  npolys = maximum number of polygons available in polys array.
	  mtol = initial angular tolerance within which to merge multiple intersections.
	  all_oneboundary = 2 to lasso all one-boundary polygons,
			    1 to lasso only those one-boundary polygons
			      with more caps than vertices,
			    0 never to lasso one-boundary polygons;
			    in all cases, all multi-boundary polygons are lassoed.
	  adjust_lasso = how to tighten lasso:
		       = 0 as tight as possible,
			 1 for balkanize,
			 2 for ransack.
	  force_split = 1 to force a polygon to be split
			  even if no boundary can be lassoed;
			0 otherwise.
  Output: polys[i], i = 0 to npoly-1, are the connected parts of poly;
              if return value = 0, then:
		  if *npoly = *npoly_try = 0, then:
		      input poly already consists of a single connected part
		      that needs no partitioning;
		  if *npoly = *npoly_try > 0, then:
		      poly was fully partitioned into its parts;
		  if *npoly < *npoly_try then:
		      poly was partially partitioned,
		      and poly[npoly - 1] contains the parts of poly
		      that were not partitioned successfully;
	      if return value = 1,
		    which can occur only if force_split = 1, then:
		    poly contains at least 2 connected boundaries,
		    none of which could be lassoed successfully,
		    and instead poly was split forcibly into two,
		    with the two parts in polys[0] and polys[1].
	  *npoly = number of polygons in polys;
		   if *npoly > npolys, then there was not enough space.
	  *npoly_try = attempted number of polygons.
  Return value: -1 if error occurred;
		 0 for a normal return;
		 1 if poly was split forcibly when no boundary could be lassoed;
		   can only occur if force_split = 1.
*/
int part_poly(polygon *poly, int npolys, polygon *polys[/*npolys*/], long double mtol, int all_oneboundary, int adjust_lasso, int force_split, int *npoly, int *npoly_try)
{
    /* number of extra caps to allocate to polygon, to allow for expansion */
#define DNP		4
    static polygon *extracap = 0x0;
    const int do_vcirc = 1;
    const int per = 0;
    const int nve = 2;
    const int itmax = 30;
    int dnp, found, i, ier, iev, ip, it, iv, ivm, ivmax_that, ivmax_this, ivmin_that, ivmin_this, nev, nev0, np, nret, nv, nvm;
    int *ipv, *gp, *ev;
    long double *angle;
    vec *ve, *vm;
    long double *cmvmin, *cmvmax, *cmpmin, *cmpmax;
    vec *vmax, *vmin;
    long double cmbest, cme, cmforce, dth, dthbest, dthforce, dthm, dthp, s, th, thm, tol;
    long double cmpmax_all, cmpmin_all, cmvmax_that, cmvmax_this, cmvmin_that, cmvmin_this, thmax_that, thmax_this, thmin_that, thmin_this;
    vec v, vmbest, vmforce;

    /* initialize return value to normal */
    nret = 0;

    /* initialize number of polygon parts in polys to zero */
    *npoly = 0;

    /* initialize attempted number of polygon parts to zero */
    *npoly_try = 0;

    /* vertices and centres of edges of polygon */
    tol = mtol;
    ier = gverts(poly, do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev);
    if (ier) return(-1);

    /* no boundaries */
    if (nev == 0) return(nret);

    /* polygon has just 1 connected boundary */
    if (nev == 1) {
        if (all_oneboundary == 0) {
            return(nret);
        } else if (all_oneboundary == 1) {
            /* polygon has not too many caps */
            if (poly->np <= nv + 1) return(nret);
        }
    }

    /* barycentres of connected boundaries of polygon */
    ier = vmidc(poly, nv, nve, ve, ipv, ev, &nvm, &vm);
    if (ier == -1) return(-1);

    /* number of polygons to try to split into */
    *npoly_try = nvm;

    /* initialize lasso to be used to force split */
    if (force_split) dthforce = -4.;

    /* attempt to partition polygon around each barycentre vm[ivm] */
    for (ivm = 0; ivm < nvm; ivm++) {

        /* initialize best lasso so far */
        if (force_split) dthbest = -4.;

        /* repeat until find isolating lasso */
        it = 0;
        do {

            /* points on each edge nearest to and farthest from vm[ivm] */
            ier = gvlims(poly, do_vcirc, &tol, vm[ivm], &nv, &vmin, &vmax, &cmvmin, &cmvmax, &cmpmin, &cmpmax, &ipv, &gp, &nev, &nev0, &ev);
            if (ier == -1) return(-1);
            if (ier) break;

            /* distances that exclude/enclose all circles */
            cmpmin_all = 2.;
            cmpmax_all = 0.;
            for (ip = 0; ip < poly->np; ip++) {
                if (cmpmin[ip] <= cmpmin_all) {
                    cmpmin_all = cmpmin[ip];
                }
                if (cmpmax[ip] >= cmpmax_all) {
                    cmpmax_all = cmpmax[ip];
                }
            }

            /* distances that exclude/enclose this connected boundary */
            ivmax_this = -1;
            ivmin_this = -1;
            cmvmin_this = 2.;
            cmvmax_this = 0.;
            for (iv = (ivm == 0)? 0 : ev[ivm - 1]; iv < ev[ivm]; iv++) {
                if (cmvmin[iv] <= cmvmin_this) {
                    ivmin_this = iv;
                    cmvmin_this = cmvmin[iv];
                }
                if (cmvmax[iv] >= cmvmax_this) {
                    ivmax_this = iv;
                    cmvmax_this = cmvmax[iv];
                }
            }

            /* distances that exclude/enclose other connected boundaries */
            ivmin_that = -1;
            ivmax_that = -1;
            cmvmin_that = 2.;
            cmvmax_that = 0.;
            for (iev = 0; iev < nev; iev++) {
                if (iev == ivm) continue;
                for (iv = (iev == 0)? 0 : ev[iev - 1]; iv < ev[iev]; iv++) {
                    if (cmvmin[iv] <= cmvmin_that) {
                        ivmin_that = iv;
                        cmvmin_that = cmvmin[iv];
                    }
                    if (cmvmax[iv] >= cmvmax_that) {
                        ivmax_that = iv;
                        cmvmax_that = cmvmax[iv];
                    }
                }
            }

            /* angles corresponding to cmmin_this, cmvmax_this, cmvmin_that, and cmvmax_that */
            thmin_this = 2. * asinl(sqrtl(cmvmin_this / 2.));
            thmax_this = 2. * asinl(sqrtl(cmvmax_this / 2.));
            thmin_that = 2. * asinl(sqrtl(cmvmin_that / 2.));
            thmax_that = 2. * asinl(sqrtl(cmvmax_that / 2.));

            dthp = thmin_that - thmax_this;
            dthm = thmin_this - thmax_that;

            dth = (dthp >= dthm)? dthp : dthm;

            /* found lasso that isolates this connected boundary of polygon */
            if (dth >= - tol) {

                /* if (it >= 10) printf("%21.15Lg %21.15Lg %21.15Lg %4d %2d%21.15Lg %21.15Lg %21.15Lg %21.15Lg %21.15Lg %21.15Lg\n", vm[ivm][0], vm[ivm][1], vm[ivm][2], ivm, it, thmin_this, thmax_this, thmin_that, thmax_that, dthp, dthm); */

                /* thmin_that >= thmax_this - tol */
                if (dthp >= dthm) {
                    /* isolating lasso */
                    th = (thmax_this + thmin_that) / 2.;
                    switch (adjust_lasso) {
                    /* as tight as possible */
                    case 0:
                        thm = thmax_this;
                        break;
                    /* for balkanize: tiny angles give garea problems */
                    case 1:
                        thm = thmax_this + .001;
                        break;
                    /* for ransack: want tight lasso */
                    case 2:
                        thm = thmax_this * 1.05;
                        break;
                    }
                    /* tighten lasso */
                    if (th > thm) th = thm;
                    if (th < PI) {
                        s = sinl(th / 2.);
                        cme = 2. * s * s;
                    } else {
                        cme = 2.;
                    }

                    /* discard lasso that completely encloses all circles */
                    if (cme >= cmpmax_all) {
                        /* printf("%21.15Lg %21.15Lg %21.15Lg %21.15Lg\n", vm[ivm][0], vm[ivm][1], vm[ivm][2], cme); */
                        /* decrement number of polygons to try for */
                        (*npoly_try)--;
                        /* break out of search loop */
                        break;
                    }

                    /* thmin_this >= thmax_that - tol */
                } else {
                    /* isolating lasso */
                    th = (thmax_that + thmin_this) / 2.;
                    switch (adjust_lasso) {
                    /* as tight as possible */
                    case 0:
                        thm = thmin_this;
                        break;
                    /* for balkanize: tiny angles give garea problems */
                    case 1:
                        thm = thmin_this - .001;
                        break;
                    /* for ransack: want tight lasso */
                    case 2:
                        thm = thmin_this / 1.05;
                        break;
                    }
                    /* tighten lasso */
                    if (th < thm) th = thm;
                    if (th > 0.) {
                        s = sinl(th / 2.);
                        cme = 2. * s * s;
                    } else {
                        cme = 0.;
                    }

                    /* discard lasso that completely encloses all circles */
                    if (cme <= cmpmin_all) {
                        /* printf("%21.15Lg %21.15Lg %21.15Lg %21.15Lg\n", vm[ivm][0], vm[ivm][1], vm[ivm][2], cme); */
                        /* decrement number of polygons to try for */
                        (*npoly_try)--;
                        /* break out of search loop */
                        break;
                    }

                    cme = - cme;

                }

                /* not enough polygons for a new one */
                if (*npoly >= npolys) {
                    (*npoly)++;
                    return(0);
                }

                /* put isolating lasso into new polygon */
                np = 1;
                dnp = DNP;
                ier = room_poly(&extracap, np, dnp, 0);
                if (ier == -1) goto out_of_memory;
                for (i = 0; i < 3; i++) {
                    extracap->rp[0][i] = vm[ivm][i];
                }

                extracap->cm[0] = cme;
                extracap->np = 1;

                /* make sure new polygon contains enough space */
                np = poly->np + 1;
                dnp = 0;
                ier = room_poly(&polys[*npoly], np, dnp, 0);
                if (ier == -1) goto out_of_memory;

                /* combination of poly with new circle */
                poly_poly(poly, extracap, polys[*npoly]);

                /* increment number of polygons */
                (*npoly)++;

                /* flag found isolating boundary */
                found = 1;

                /* failed to find isolating lasso */
            } else {

                dthp = thmin_that - thmin_this;
                dthm = thmax_this - thmax_that;

                if (dthp >= dthm) {
                    /* paranoid check that ivmax_this and ivmin_that were initialized */
                    if (ivmax_this == -1 || ivmin_that == -1) {
                        /* error should never happen */
                        fprintf(stderr, "partition_poly: ivmax_this = %d ivmin_that = %d should be in interval [0, %d]\n", ivmax_this, ivmin_that, nv);
                        return(-1);
                    }

                    /* record the best lasso so far */
                    if (force_split) {
                        if (dthp > dthbest) {
                            dthbest = dthp;
                            /* circle that does not enclose connected boundary,
                               but does exclude other connected boundaries */
                            th = (thmin_this + thmin_that) / 2.;
                            thm = thmin_that * .999;
                            if (th < thm) th = thm;
                            s = sinl(th / 2.);
                            cmbest = 2. * s * s;
                            for (i = 0; i < 3; i++) {
                                vmbest[i] = vm[ivm][i];
                            }
                        }
                    }

                    /* vector to this from that */
                    for (i = 0; i < 3; i++) {
                        v[i] = vmax[ivmax_this][i] - vmin[ivmin_that][i];
                    }
                    s = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
                    /* translate centre point along vector */
                    /* the 0.02 puts centre just beyond equal distance */
                    for (i = 0; i < 3; i++) {
                        v[i] = vm[ivm][i] + ((cmvmax_this - cmvmin_that) / s + 0.02 * (it + 1)) * v[i];
                    }
                    s = sqrtl(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
                    for (i = 0; i < 3; i++) {
                        vm[ivm][i] = v[i] / s;
                    }

                } else {
                    /* paranoid check that ivmin_this and ivmax_that were initialized */
                    if (ivmin_this == -1 || ivmax_that == -1) {
                        /* error should never happen */
                        fprintf(stderr, "partition_poly: ivmin_this = %d ivmax_that = %d should be in interval [0, %d]\n", ivmin_this, ivmax_that, nv);
                        return(-1);
                    }

                    /* record the best lasso so far */
                    if (force_split) {
                        if (dthm > dthbest) {
                            dthbest = dthm;
                            /* circle that does not enclose connected boundary,
                               but does exclude other connected boundaries */
                            th = PI - (thmax_this + thmax_that) / 2.;
                            thm = (PI - thmax_that) * .999;
                            if (th < thm) th = thm;
                            s = cosl(th / 2.);
                            cmbest = - 2. * s * s;
                            for (i = 0; i < 3; i++) {
                                vmbest[i] = vm[ivm][i];
                            }
                        }
                    }

                    /* vector to that from this */
                    for (i = 0; i < 3; i++) {
                        v[i] = vmax[ivmax_that][i] - vmin[ivmin_this][i];
                    }
                    s = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
                    /* translate centre point along vector */
                    /* the 0.02 puts centre just beyond equal distance */
                    for (i = 0; i < 3; i++) {
                        v[i] = vm[ivm][i] + ((cmvmax_that - cmvmin_this) / s + 0.02 * (it + 1)) * v[i];
                    }
                    s = sqrtl(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
                    for (i = 0; i < 3; i++) {
                        vm[ivm][i] = v[i] / s;
                    }

                }

                /* flag failed to find isolating boundary */
                found = 0;

            }

        } while (!found && it++ < itmax);

        /* record the best lasso so far */
        if (force_split && !found) {
            if (dthbest > dthforce) {
                dthforce = dthbest;
                cmforce = cmbest;
                for (i = 0; i < 3; i++) {
                    vmforce[i] = vmbest[i];
                }
            }
        }

    }

    /* no polygons were lassoed */
    if (*npoly == 0) {

        /* go with original polygon */
        if (*npoly_try <= 1) {
            *npoly_try = 0;
            return(nret);
        }

        /* split polygon along best circle so far, even though it is not a lasso */
        if (force_split) {
            /* not enough polygons for a new one */
            if (*npoly >= npolys) {
                (*npoly)++;
                return(0);
            }

            /* put circle into new polygon */
            np = 1;
            dnp = DNP;
            ier = room_poly(&extracap, np, dnp, 0);
            if (ier == -1) goto out_of_memory;
            for (i = 0; i < 3; i++) {
                extracap->rp[0][i] = vmforce[i];
            }
            extracap->cm[0] = cmforce;
            extracap->np = 1;

            /* make sure new polygon contains enough space */
            np = poly->np + 1;
            dnp = 0;
            ier = room_poly(&polys[*npoly], np, dnp, 0);
            if (ier == -1) goto out_of_memory;

            /* combination of polygon with new circle */
            poly_poly(poly, extracap, polys[*npoly]);

            /* increment number of polygons */
            (*npoly)++;

            /* flag that split was forced */
            nret = 1;
        }

    }

    /* if some polygons were lassoed and others not, add complement of all new caps to polygon */
    if (*npoly > 0 && *npoly < *npoly_try) {
        /* not enough polygons for a new one */
        if (*npoly >= npolys) {
            (*npoly)++;
            return(0);
        }

        /* put complement of all new caps into new polygon */
        np = *npoly;
        dnp = DNP;
        ier = room_poly(&extracap, np, dnp, 0);
        if (ier == -1) goto out_of_memory;
        for (np = 0; np < *npoly; np++) {
            ip = polys[np]->np - 1;
            for (i = 0; i < 3; i++) {
                extracap->rp[np][i] = polys[np]->rp[ip][i];
            }
            extracap->cm[np] = - polys[np]->cm[ip];
        }
        extracap->np = *npoly;

        /* make sure new polygon contains enough space */
        np = poly->np + *npoly;
        dnp = 0;
        ier = room_poly(&polys[*npoly], np, dnp, 0);
        if (ier == -1) goto out_of_memory;

        /* poly with complement of new caps from other polygons */
        poly_poly(poly, extracap, polys[*npoly]);

        /* increment number of polygons */
        (*npoly)++;
    }

    /* trim new polygons to suppress obviously coincident caps */
    for (ip = 0; ip < *npoly; ip++) {
        trim_poly(polys[ip]);
    }

    return(nret);

    /* ---------------- error returns ---------------- */
out_of_memory:
    fprintf(stderr, "part_poly: failed to allocate memory for polygon of %d caps\n", np + dnp);
    return(-1);
}
Ejemplo n.º 6
0
/*------------------------------------------------------------------------------
  Partition disconnected polygon into connected polygons.
  Identifies the groups of boundaries of the polygon
  (two circles are friends, belonging to the same group, if they intersect,
  and friends of friends are friends),
  calls partition_gpoly to partition each group polygon into its parts,
  and combines parts from each group.

  The value of the flag overwrite_original determines whether the
  original polygon in poly is overwritten or not.

   Input: *poly is a polygon.
	  npolys = maximum number of polygons available in polys array.
	  mtol = initial angular tolerance within which to merge multiple intersections.
	  all_oneboundary = 2 to lasso all one-boundary polygons,
			    1 to lasso only those one-boundary polygons
			      with more caps than vertices,
			    0 never to lasso one-boundary polygons;
			    in all cases, all multi-boundary polygons are lassoed.
	  adjust_lasso = how to tighten lasso:
		       = 0 as tight as possible,
			 1 for balkanize,
			 2 for ransack.
	  force_split = 1 to force a polygon to be split
			  even if no boundary can be lassoed;
			0 otherwise.
	  overwrite_original = 2 to overwrite original polygon poly in all cases,
				 whether or not partitioning succeeds;
			       1 to overwrite poly only if partitioning succeeds;
			       0 never to overwrite original poly.
  Output: (*poly and) polys[i], i = 0 to *npoly-1, are the parts of *poly.
	  *npoly = number of polygons in polys;
		   if *npoly > npolys, then there was not enough space.
  Return value: -1 if error occurred;
		 0 if *poly was fully partitioned into its parts;
		 1 if *poly was partially partioned;
		   the parts of *poly constitute a valid set of parts,
		   whose union equals the input *poly,
		   though some parts are disconnected.
*/
int partition_poly(polygon **poly, int npolys, polygon *polys[/*npolys*/], long double mtol, int all_oneboundary, int adjust_lasso, int force_split, int overwrite_original, int *npoly)
{
    const int do_vcirc = 1;
    const int per = 0;
    const int nve = 2;
    int dnp, dnpoly, ier, iev, igp, ip, ipoly, jpoly, kpoly, nev, nev0, ngp, np, nret, nv, verb;
    long double area, areag, atol, tol;
    int *ipv, *gp_tmp, *ev;
    long double *angle;
    vec *ve;
    /* work arrays */
    int *gp = 0x0, *gpg = 0x0;
    polygon *gpoly = 0x0;

    /* initialize return value to normal */
    nret = 0;

    /* initialize number of polygon parts in polys to zero */
    *npoly = 0;

    /* call gverts to determine which groups connected boundaries belong to */
    tol = mtol;
    ier = gverts(*poly, do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp_tmp, &nev, &nev0, &ev);
    if (ier) goto error;

    /* no boundaries */
    if (nev == 0) return(0);

    /* polygon has 1 connected boundary, and not too many caps */
    if (!all_oneboundary && nev == 1 && (*poly)->np <= nv + 1) return(0);

    /* allocate memory for gp and gpg */
    gp = (int *) malloc(sizeof(int) * (*poly)->np);
    if (!gp) {
        fprintf(stderr, "partition_poly: failed to allocate memory for %d ints\n", (*poly)->np);
        return(-1);
    }
    gpg = (int *) malloc(sizeof(int) * (*poly)->np);
    if (!gpg) {
        fprintf(stderr, "partition_poly: failed to allocate memory for %d ints\n", (*poly)->np);
        return(-1);
    }

    /* copy group numbers, because they will be destroyed by subsequent call to gverts() */
    for (ip = 0; ip < (*poly)->np; ip++) {
        gp[ip] = gp_tmp[ip];
    }

    /* distinct groups */
    ngp = 0;
    for (iev = 0; iev < nev; iev++) {
        if (ngp == 0 || gp[ipv[ev[iev] - 1]] != gpg[ngp - 1]) {
            gpg[ngp] = gp[ipv[ev[iev] - 1]];
            ngp++;
        }
    }

    /* accept error messages from garea */
    verb = 1;

    /* each group of connected boundaries */
    for (igp = 0; igp < ngp; igp++) {

        /* polygon contains only one group of connected boundaries */
        if (ngp == 1) {
            /* point group polygon gpoly at original polygon */
            gpoly = *poly;

            /* polygon contains more than one group of connected boundaries */
        } else {
            /* make sure group polygon gpoly contains enough space */
            np = (*poly)->np;
            dnp = 0;
            ier = room_poly(&gpoly, np, dnp, 0);
            if (ier == -1) goto out_of_memory;

            /* make group polygon */
            group_poly(*poly, gp, gpg[igp], gpoly);

        }

        /* partition group polygon */
        ier = partition_gpoly(gpoly, npolys - *npoly, &polys[*npoly], tol, all_oneboundary, adjust_lasso, force_split, &dnpoly);
        if (ier == -1) goto error;

        /* flag that partitioning was only partly successful */
        if (ier == 1) nret = 1;

        /* just one group */
        if (ngp == 1) {
            /* number of polygon parts */
            *npoly = dnpoly;

            /* not enough polygons */
            if (*npoly > npolys) return(0);

            /* two or more groups */
        } else {
            /* first group */
            if (igp == 0) {
                if (dnpoly == 0) {
                    /* not enough polygons */
                    if (*npoly >= npolys) {
                        (*npoly)++;
                        return(0);
                    }

                    /* move group polygon into cumulative polygon polys[*npoly] */
                    free_poly(polys[*npoly]);
                    polys[*npoly] = gpoly;
                    gpoly = 0x0;
                    (*npoly)++;
                } else {
                    *npoly = dnpoly;
                }

                /* subsequent groups */
            } else {
                dnp = DNP;

                /* index of next polygon after cumulative and group polygons */
                kpoly = *npoly + dnpoly;

                /* accumulate polygons */
                for (ipoly = 0; ipoly < *npoly; ipoly++) {

                    /* area of cumulative polygon polys[ipoly] */
                    atol = tol;
                    ier = garea(polys[ipoly], &atol, verb, &area);
                    if (ier) goto error;

                    /* not enough polygons */
                    if (kpoly >= npolys) {
                        *npoly = kpoly + 1;
                        return(0);
                    }

                    /* intersection of cumulative polygon polys[ipoly] with group polygon gpoly */
                    np = polys[ipoly]->np + gpoly->np;
                    ier = room_poly(&polys[kpoly], np, dnp, 0);
                    if (ier == -1) goto out_of_memory;
                    poly_poly(polys[ipoly], gpoly, polys[kpoly]);

                    /* area of intersection of cumulative polygon polys[ipoly] with group polygon gpoly */
                    ier = garea(polys[kpoly], &atol, verb, &areag);
                    if (ier) goto error;

                    /* paranoid check: group polygon gpoly does not intersect cumulative polygon polys[ipoly]: should not happen */
                    if (areag == 0.) {
                        fprintf(stderr, "partition_poly: group %d does not intersect part %d of polygon with input id %lld; should not happen; continuing ...\n", igp, ipoly, polys[ipoly]->id);
                        /* goto error; */
                        /* group polygon gpoly encloses cumulative polygon polys[ipoly], so offers no further constraint */
                    } else if (areag == area) {
                        continue;
                    }

                    /* group polygon was not partitioned */
                    if (dnpoly == 0) {
                        /* replace cumulative polygon polys[ipoly] with intersection polygon polys[kpoly] */
                        free_poly(polys[ipoly]);
                        polys[ipoly] = polys[kpoly];
                        polys[kpoly] = 0x0;

                        /* group polygon was partitioned */
                    } else {
                        /* intersect cumulative polygon polys[ipoly] with each part of group polygon */
                        for (jpoly = *npoly; jpoly < *npoly + dnpoly; jpoly++) {
                            /* not enough polygons */
                            if (kpoly >= npolys) {
                                *npoly = kpoly + 1;
                                return(0);
                            }
                            np = polys[ipoly]->np + polys[jpoly]->np;
                            ier = room_poly(&polys[kpoly], np, dnp, 0);
                            if (ier == -1) goto out_of_memory;
                            poly_poly(polys[ipoly], polys[jpoly], polys[kpoly]);
                            /* increment number of polygons */
                            kpoly++;
                        }

                        /* replace cumulative polygon polys[ipoly] with last intersected part polys[kpoly - 1] */
                        free_poly(polys[ipoly]);
                        kpoly--;
                        polys[ipoly] = polys[kpoly];
                        polys[kpoly] = 0x0;

                    }

                }

                if (dnpoly > 0) {
                    /* free parts of group polygon */
                    for (jpoly = *npoly; jpoly < *npoly + dnpoly; jpoly++) {
                        free_poly(polys[jpoly]);
                    }
                    /* decrement number of polygons */
                    kpoly -= dnpoly;
                    /* move down cumulative polygons */
                    for (ipoly = *npoly; ipoly < kpoly; ipoly++) {
                        polys[ipoly] = polys[ipoly + dnpoly];
                    }
                    /* nullify vacated polygons */
                    for (ipoly = kpoly; ipoly < kpoly + dnpoly; ipoly++) {
                        polys[ipoly] = 0x0;
                    }
                }

                /* revised number of polygons */
                *npoly = kpoly;

            }

        }

    }

    /* polygon contains just one group of connected boundaries */
    if (ngp == 1) {
        /* point original polygon at group polygon */
        *poly = gpoly;

        /* polygon contains more than one group of connected boundaries */
    } else {
        /* free group polygon */
        free_poly(gpoly);

    }

    /* move final polygon part to poly */
    if (*npoly > 0
            && (overwrite_original == 2
                || (overwrite_original == 1 && ier == 0))) {

        /* free input poly */
        free_poly(*poly);

        /* point poly at last polygon part */
        *poly = polys[*npoly - 1];

        /* nullify last polygon part */
        polys[*npoly - 1] = 0x0;

        /* decrement number of polygons */
        (*npoly)--;
    }

    if (gp) free(gp);
    if (gpg) free(gpg);

    return(nret);

    /* ---------------- error returns ---------------- */
error:
    if (gp) free(gp);
    if (gpg) free(gpg);
    return(-1);

out_of_memory:
    fprintf(stderr, "partition_poly: failed to allocate memory for polygon of %d caps\n", np + dnp);
    if (gp) free(gp);
    if (gpg) free(gpg);
    return(-1);
}
Ejemplo n.º 7
0
int rasterize(int nhealpix_poly, int npoly, polygon *polys[/*npoly*/], int nweights, long double weights[/*nweights*/])
{
  int min_pixel, max_pixel, ier, ier_h, ier_i, i, j, ipix, ipoly, begin_r, end_r, begin_m, end_m, verb, np, iprune;
  int *start_r, *start_m, *total_r, *total_m;
  long double *areas, area_h, area_i, tol;

  static polygon *polyint = 0x0;

  /* make sure weights are all zero for rasterizer pixels */
  for (i = 0; i < nhealpix_poly; i++) {
      polys[i]->weight = 0.;
  }

  /* allocate memory for rasterizer areas array */
  areas = (long double *) malloc(sizeof(long double) * (nweights));
  if (!areas) {
    fprintf(stderr, "rasterize: failed to allocate memory for %d long doubles\n", nweights);
    exit(1);
  }

  /* initialize rasterizer areas array to 0 */
  for (i = 0; i < nweights; i++) areas[i] = 0.;

  /* allow error messages from garea */
  verb = 1;

  /* find areas of rasterizer pixels for later use */
  for (i = 1; i <= nweights; i++) {
    for (j = 0; j < nhealpix_poly; j++) {
      if (polys[j]->id == i) {
        tol = mtol;
        ier_h = garea(polys[j], &tol, verb, &area_h);
        if (ier_h == 1) {
          fprintf(stderr, "fatal error in garea\n");
          exit(1);
        }
        if (ier_h == -1) {
          fprintf(stderr, "failed to allocate memory in garea\n");
          exit(1);
        }
        areas[i-1] += area_h;
      }
    }
  }

  /* sort arrays by pixel number */
  poly_sort(nhealpix_poly, polys, 'p');
  poly_sort(npoly-nhealpix_poly, &(polys[nhealpix_poly]), 'p');

  /* allocate memory for pixel info arrays start_r, start_m, total_r, and total_m */
  min_pixel = polys[0]->pixel;
  max_pixel = (polys[nhealpix_poly-1]->pixel+1>polys[npoly-1]->pixel+1)?(polys[nhealpix_poly-1]->pixel+1):(polys[npoly-1]->pixel+1);
  start_r = (int *) malloc(sizeof(int) * max_pixel);
  if (!start_r) {
    fprintf(stderr, "rasterize: failed to allocate memory for %d integers\n", max_pixel);
    return(-1);
  }
  start_m = (int *) malloc(sizeof(int) * max_pixel);
  if (!start_m) {
    fprintf(stderr, "rasterize: failed to allocate memory for %d integers\n", max_pixel);
    return(-1);
  }
  total_r = (int *) malloc(sizeof(int) * max_pixel);
  if (!total_r) {
    fprintf(stderr, "rasterize: failed to allocate memory for %d integers\n", max_pixel);
    return(-1);
  }
  total_m = (int *) malloc(sizeof(int) * max_pixel);
  if (!total_m) {
    fprintf(stderr, "rasterize: 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(nhealpix_poly, polys, max_pixel, start_r, total_r);
  if (ier == -1) {
    fprintf(stderr, "rasterize: error building pixel index lists for rasterizer polygons\n");
    return(-1);
  }

  ier = pixel_list(npoly-nhealpix_poly, &(polys[nhealpix_poly]), max_pixel, start_m, total_m);
  if (ier == -1) {
    fprintf(stderr, "rasterize: error building pixel index lists for input mask polygons\n");
    return(-1);
  }

  /* correction due to the start_m array's offset */
  for (i = min_pixel; i < max_pixel; i++) {
    start_m[i] += nhealpix_poly;
  }

  /* compute intersection of each input mask polygon with each rasterizer polygon */
  for (ipix = min_pixel; ipix < max_pixel; ipix++) {
    begin_r = start_r[ipix];
    end_r = start_r[ipix] + total_r[ipix];
    begin_m = start_m[ipix];
    end_m = start_m[ipix] + total_m[ipix];

    for (ipoly = begin_m; ipoly < end_m; ipoly++) {
      /* disregard any null polygons */
      if (!polys[ipoly]) continue;

      for (i = begin_r; i < end_r; i++) {

	/* make sure polyint contains enough space for intersection */
	np = polys[ipoly]->np + polys[i]->np;
	ier = room_poly(&polyint, np, DNP, 0);
	if (ier == -1) goto out_of_memory;

	poly_poly(polys[ipoly], polys[i], polyint);

	/* suppress coincident boundaries, to make garea happy */
	iprune = trim_poly(polyint);

	/* intersection of polys[ipoly] and polys[i] is null polygon */
	if (iprune >= 2) area_i = 0.;

	else {
	  tol = mtol;
	  ier_i = garea(polyint, &tol, verb, &area_i);
	  if (ier_i == 1) {
	    fprintf(stderr, "fatal error in garea\n");
	    return(-1);
	  }
	  if (ier_i == -1) {
	    fprintf(stderr, "failed to allocate memory in garea\n");
	    return(-1);
	  }
	}
	    
	weights[(polys[i]->id)-1] += (area_i)*(polys[ipoly]->weight);
      }
    }
  }

  for (i=0; i<nweights; i++) {
    if(areas[i]!=0){
      weights[i] = weights[i]/areas[i];
    }
    else{
      weights[i]=0;
      fprintf(stderr,"WARNING: rasterize: area of rasterizer polygon %d is zero.  Assigning zero weight.\n",i);
    }
  }

  return(i+1);

  /* ----- error return ----- */
  out_of_memory:
  fprintf(stderr, "rasterize: failed to allocate memory for polygon of %d caps\n", np + DNP);
  return(-1);

}