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 ); } } }
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; }