void build_lfm_lookup()
{
double b, r, ls, lamdas, pre_gxs, gis,gjs, gi, gj, rl,
       cos_dlamda, sin_dlamda, sin_s, cos_s,
       sin_ls, cos_ls, sin_l, cos_l, sin_b, cos_b,
       cos_lamdas_prime, sin_lamdas_prime;

int    is[LFMMX_IDX],js[LFMMX_IDX],iaz,irg,
       lfmbox,lfm_i,lfm_j,
       status;

static int    ika[]    = {1, 4, 10};
static double ka[]     = {1.0, 4.0, 10.0};
static int    offset[] = {7, 49, 66};

  sin_ls = 0.;
  cos_ls = 0.;

/* If the site latitude or longitude doesnt match the
   table latitude or longitude .... create the tables*/
  if ((sadpt.rda_lat != a314c1.grid_lat)||(sadpt.rda_lon != a314c1.grid_lon)||
      (sadpt.rda_lat != a314c1.end_lat) ||(sadpt.rda_lon != a314c1.end_lon))
  {
/** Convert adaptation data lat/long to double precision data*/
    ls = sadpt.rda_lat/scale_factor;
    lamdas = sadpt.rda_lon/scale_factor;

/** Initialize tables before starting lookup table generation*/
    init_polar_to_lfm_tables( );

/** Compute common part of the gis and gjs equations*/
     pre_gxs=r2ko*cos_ls/(ONE+sin_ls);

/** Compute parts of equations used multiple times later*/
     cos_lamdas_prime = cos((lamdas+prime)*DTR);
     sin_lamdas_prime = sin((lamdas+prime)*DTR);
     sin_ls = sin(ls*DTR);
     cos_ls = cos(ls*DTR);

/** Compute common part of the gis and gjs equations*/
     pre_gxs = r2ko*cos_ls/(ONE+sin_ls);

/** Compute regerence grid box coordinates*/
     gis = pre_gxs*sin_lamdas_prime+ip;
     gjs = pre_gxs*cos_lamdas_prime+jp;

/** Compute grid box numbers for box 0,0 of local grids*/
     is[lfm4_idx] = (int)gis-offset[lfm4_idx];
     js[lfm4_idx] = (int)gjs-offset[lfm4_idx];

     is[lfm16_idx] = ika[lfm16_idx]*(int)gis-offset[lfm16_idx];
     js[lfm16_idx] = ika[lfm16_idx]*(int)gjs-offset[lfm16_idx];

     is[lfm40_idx] = (int)(ka[lfm40_idx]*gis)-offset[lfm40_idx];
     js[lfm40_idx] = (int)(ka[lfm40_idx]*gjs)-offset[lfm40_idx];

/** Initialize bearing*/
     b=-HALF;

/** Do for all bearings*/
    for ( iaz=0; iaz<MAX_AZMTH; iaz++ ) 
    {
       b = b+ONE;
       sin_b = sin(b*DTR);
       cos_b = cos(b*DTR);

/** Initialize range*/
       r = -HALF;

/** Do for each input data range values (comp refl to rcm first)*/
       for ( irg=0; irg<RNG_LFM16; irg++ ) 
       {
          r = r+ONE;
          sin_s = (r/re_proj)*(ONE-(const_val*r/re_proj_sq));
          cos_s = sqrt(ONE-sin_s*sin_s);
          sin_l = sin_ls*cos_s+cos_ls*sin_s*cos_b;
          cos_l = sqrt(ONE-sin_l*sin_l);
          sin_dlamda = sin_s*sin_b/cos_l;
          cos_dlamda = sqrt(ONE-sin_dlamda*sin_dlamda);
          rl = r2ko*cos_l/(ONE+sin_l);
          gi = rl*(sin_dlamda*cos_lamdas_prime+
                 cos_dlamda*sin_lamdas_prime)+ip;
          gj = rl*(cos_dlamda*cos_lamdas_prime-
                 sin_dlamda*sin_lamdas_prime)+jp;

/** Compute 1/16 lfm i and j coordinates of the range/azimuth bin*/
          lfm_i = (int)(gi*ka[lfm16_idx])-is[lfm16_idx];
          lfm_j = (int)(gj*ka[lfm16_idx])-js[lfm16_idx];

/** If lfm coordinates are within local grid save it into the lookup
    table and set the 1/16 lfm box range number table to within range*/
          if ((lfm_i>0)&&(lfm_i<=HYZ_LFM16)&&(lfm_j>0)&&(lfm_j<=HYZ_LFM16))
          {
            lfmbox = (lfm_j-1)*HYZ_LFM16+lfm_i;
            a314c1.lfm16grid[iaz][irg] = lfmbox;
            a314c1.lfm16flag[FLAG_RNG][lfmbox-1] = WITHIN_RANGE;
          }
       }/*end loop RNG_LFM16*/

/** Initialize range*/
       r = -ONE;

/** Do for each input data range values (hydro application next)*/
       for ( irg=0; irg<MAX_HBINS; irg++ ) 
       {
          r = r+RNG_INC;
          sin_s = (r/re_proj)*(ONE-(const_val*r/re_proj_sq));
          cos_s = sqrt(ONE-sin_s*sin_s);
          sin_l = sin_ls*cos_s+cos_ls*sin_s*cos_b;
          cos_l = sqrt(ONE-sin_l*sin_l);
          sin_dlamda = sin_s*sin_b/cos_l;
          cos_dlamda = sqrt(ONE-sin_dlamda*sin_dlamda);
          rl = r2ko*cos_l/(ONE+sin_l);
          gi = rl*(sin_dlamda*cos_lamdas_prime+
                 cos_dlamda*sin_lamdas_prime)+ip;
          gj = rl*(cos_dlamda*cos_lamdas_prime-
                 sin_dlamda*sin_lamdas_prime)+jp;

/** Compute 1/4 lfm i and j coordinates of the range/azimuth bin*/
          lfm_i = (int)(gi*ka[lfm4_idx])-is[lfm4_idx];
          lfm_j = (int)(gj*ka[lfm4_idx])-js[lfm4_idx];

/** If lfm coordinates are within local grid save it into the lookup
    table and set the 1/4 lfm box range number table to within range*/
          if ((lfm_i>0)&&(lfm_i<=HYZ_LFM4)&&(lfm_j>0)&&(lfm_j<=HYZ_LFM4))
          {
            lfmbox = (lfm_j-1)*HYZ_LFM4+lfm_i;
            a314c1.lfm4grid[iaz][irg] = lfmbox;
            a314c1.lfm4flag[FLAG_RNG][lfmbox-1] = WITHIN_RANGE;
          }

/** Compute 1/40 lfm i and j coordinates of the range/azimuth bin*/
          lfm_i = (int)(gi*ka[lfm40_idx])-is[lfm40_idx];
          lfm_j = (int)(gj*ka[lfm40_idx])-js[lfm40_idx];

/** If lfm coordinates are within local grid save it into the lookup
    table and set the 1/40 lfm box range number table to within range*/
          if ((lfm_i>0)&&(lfm_i<=HYZ_LFM40)&&(lfm_j>0)&&(lfm_j<=HYZ_LFM40))
          {
            lfmbox = (lfm_j-1)*HYZ_LFM40+lfm_i;
            a314c1.lfm40grid[iaz][irg] = lfmbox;
            a314c1.lfm40flag[FLAG_RNG][lfmbox-1] = WITHIN_RANGE;
          }

       } /*end loop MAX_HBINS*/

    } /*end loop MAX_AZMTH*/
    
/** Find holes and determine hole filling data*/
    find_holes( ls, lamdas );

/** Set grid_lat and grid_lon ... then write to A314C1 (ITC)*/
    a314c1.grid_lat=sadpt.rda_lat;
    a314c1.grid_lon=sadpt.rda_lon;
    a314c1.end_lat=sadpt.rda_lat;
    a314c1.end_lon=sadpt.rda_lon;

/* Write LFM grids to Inter-Task Common block A314C1 */
    RPGC_itc_write( A314C1, &status );
    if ( status != 0 )
    {
      RPGC_log_msg( GL_ERROR,"Failed to call RPGC_itc_write..( %d )\n",
                                                              status );
    }

  }
}
示例#2
0
void find_holes(Seg_t segs[], int nsegs, int **pholesizes, int *pnholes) {
  int *xorder, *yorder, found;
  int nx, ny, i,j,k, y1, y2, x1, x2, t, x, y, *queue, head, tail, qlen;
  char *array;
  int hole_total;

  xorder = malloc(2*nsegs*sizeof(xorder[0])); assert(xorder);
  yorder = malloc(2*nsegs*sizeof(yorder[0])); assert(yorder);

  for( i = 0, j = 0, k = 0; i < nsegs; i++ ) {
    xorder[j++] = segs[i].p1.x;
    xorder[j++] = segs[i].p2.x;
    yorder[k++] = segs[i].p1.y;
    yorder[k++] = segs[i].p2.y;
  }

  qsort(xorder, j, sizeof(*xorder), int_cmp);
  qsort(yorder, k, sizeof(*yorder), int_cmp);

  /* uniqify the arrays xorder and yorder. */
  for( i = 1, j = 0; i < nsegs*2; /* nil */ )
    if( xorder[i] != xorder[j] ) xorder[++j] = xorder[i++]; else i++;

  nx = j + 1;

  for( i = 1, j = 0; i < nsegs*2; /* nil */ )
    if( yorder[i] != yorder[j] ) yorder[++j] = yorder[i++]; else i++;

  ny = j + 1;

  /* now allocate our happy array. */
  array = calloc( (2*nx+1) * (2*ny+1) , sizeof(*array) );
  
  for( i = 0; i < nsegs; i++ ) {
    if( isVert(segs[i])) {
      x = y1 = y2 = -1;
      for( j = 0; j < ny; j++ ) {
	if( segs[i].p1.y == yorder[j] ) y1 = j;
	if( segs[i].p2.y == yorder[j] ) y2 = j;
      }
      for( j = 0; j < nx; j++ ) if( segs[i].p1.x == xorder[j] ) x  = j;
      /* assert(y1 != -1 && y2 != -1 && x != -1);*/
      if( y1 > y2 ) swap(y1,y2,t);
      
      x = x*2 + 1;
      for( j = 2*y1+1; j <= 2*y2+1; j ++ ) {
	a(x,j) = '*';
      }
      
    } else if( isHorz(segs[i])) {
      y = x1 = x2 = -1;
      for( j = 0; j < nx; j++ ) {
	if( segs[i].p1.x == xorder[j] ) x1 = j;
	if( segs[i].p2.x == xorder[j] ) x2 = j;
      }
      for( j = 0; j < ny; j++ ) if( segs[i].p1.y == yorder[j] ) y  = j;
      /* assert(x1 != -1 && x2 != -1 && y != -1); */
      if( x1 > x2 ) swap(x1,x2,t);
      y = y * 2 + 1;
      for( j = 2*x1+1; j <= 2*x2+1; j ++ ) {
	a(j,y) = '*';
      }
    } else {
      assert(0); /* must be either horizontal or vertical. */
    }
  }
  if( debug ) dump_array(array, nx, ny);

  /* now the array is filled in with the segment boundaries */
  /* flood fill from the outside. */
  
  /* well, first set up the bfs queue. */

  /* this should be quite big enough. I claim that 2 * ... would
   * be enough. */
  /* the entries of the queue are encoded as:
   * x<<16 | y */
  qlen = 4 * ( (2*nx+1) + (2*ny+1));
  queue = malloc(qlen*sizeof(queue[0])); assert(queue);

  head = tail = 0;
  queue[tail++] = 0;
  a(0,0) = 1; /* visited is marked 1. */

  while( head != tail ) {
    x = queue[head]; 
    head = (head + 1) % qlen;
    y = x & 0xffff; x >>= 16;

    for( t = 0; t < 4; t++ ) {
      switch(t) {
      case 0: i = x-1; j = y  ; break;
      case 1: i = x  ; j = y-1; break;
      case 2: i = x+1; j = y  ; break;
      case 3: i = x  ; j = y+1; break;
      default:
      }

      if( i >= 0 && i <= 2*nx && j >= 0 && j <= 2*ny && !a(i,j) ) {
	queue[tail] = i << 16 | j;
	tail = (tail + 1) % qlen;
	a(i,j) = 1;
      }
    }
  }

  if(debug) dump_array(array, nx, ny);

  /* now the array has been flooded from the outside. condense
   * adjacent holes by dissolving the boundaries between them. */

  /* the bounds of these for loops are shrunk by one because
   * by construction the entire array has boundaries 1 now,
   * so we don't need to check them. */
  for( i = 1; i < 2*nx; i++ ) {
    for( j = 1; j < 2*ny; j++ ) {
      if( a(i,j) == '*' &&
	((a(i-1,j) == 0 && a(i+1,j) == 0) || (a(i,j-1) == 0 && a(i,j+1) == 0)))
	a(i,j) = 0;
    }
  }
  if(debug) dump_array(array, nx, ny);

  /* now while there is a still an element of the array with coordinates
   * of form (2k,2m) set to zero, flood fill and measure the area. */
  *pholesizes = NULL; *pnholes = 0;
  do {
    found = 0;
    for( i = 2; i <= 2*nx; i += 2 ) {
      for( j = 2; j <= 2*ny; j += 2 ) {
	if( ! a(i,j) ) { found = 1; goto zero_found; }
      }
    }
    /* ! found */ break;
    
  zero_found:
    hole_total = head = tail = 0;
    queue[tail++] = i << 16 | j;
    a(i,j) = 1; /* visited is marked 1. */
    
    while( head != tail ) {
      x = queue[head]; 
      head = (head + 1) % qlen;
      y = x & 0xffff; x >>= 16;
      if( !(x&1) && !(y&1) ) {
	/* an even-coordinate square. that means, measure it. */
	hole_total += 
	  (xorder[x/2] - xorder[(x/2)-1]) * (yorder[y/2] - yorder[(y/2)-1]);
      }
      /* and enqueue its neigbours. */
      for( t = 0; t < 4; t++ ) {
	switch(t) {
	case 0: i = x-1; j = y  ; break;
	case 1: i = x  ; j = y-1; break;
	case 2: i = x+1; j = y  ; break;
	case 3: i = x  ; j = y+1; break;
	default:
	}
	if( i >= 0 && i <= 2*nx && j >= 0 && j <= 2*ny && !a(i,j) ) {
	  queue[tail] = i << 16 | j;
	  tail = (tail + 1) % qlen;
	  a(i,j) = 1;
	}
      }
    } /* end loop bfs flood filling this hole */
    
    if( *pholesizes == NULL ) {
      *pholesizes = malloc((*pnholes + 1) * sizeof((*pholesizes)[0]));
      assert(*pholesizes);
    } else {
      *pholesizes = realloc( *pholesizes, 
			     (*pnholes + 1) * sizeof((*pholesizes)[0]));
      assert(*pholesizes);
    }
    (*pholesizes)[(*pnholes)++] = hole_total;
  } while(1); /* broken when zero elements are exhausted. */
  free(queue); free(array); free(xorder); free(yorder);
}

int main() {
  int i,x1,y1,x2,y2,nsegs, *holes, nholes;
  Seg_t *segs;

  segs = NULL; nsegs = 0;

  while(scanf("%d %d %d %d", &x1, &y1, &x2, &y2) == 4 ){
    segs = segs 
      ? realloc(segs, ++nsegs * sizeof(segs[0])) 
      : malloc(++nsegs * sizeof(segs[0]));
    
    segs[nsegs-1].p1.x = x1; segs[nsegs-1].p1.y = y1;
    segs[nsegs-1].p2.x = x2; segs[nsegs-1].p2.y = y2;
  }

  find_holes(segs, nsegs, &holes, &nholes);
  printf("There are %d holes.\n", nholes);

  for( i = 0; i < nholes; i++ )
    printf("Hole of size %d\n", holes[i]);
  return 0;
}