/********************************************************** * meta_incid: Returns the incidence angle * This is the angle measured by the target between straight * up and the satellite. Returns radians.*/ double meta_incid(meta_parameters *meta,double y,double x) { // No effort has been made to make this routine work with // pseudoprojected images. if (strcmp_case(meta->general->sensor, "UAVSAR") == 0) // placeholder for incidence angle information, most likely coming from // a band in the image file return 0.0; else assert (meta->projection == NULL || meta->projection->type != LAT_LONG_PSEUDO_PROJECTION); double sr = meta_get_slant(meta,y,x); if (meta_uses_incid_polynomial(meta)) { // Use the incidence angle polynomial if it is available and non-zero. double R = sr/1000.; double R2=R*R; return meta->sar->incid_a[0] + meta->sar->incid_a[1] * R + meta->sar->incid_a[2] * R2 + meta->sar->incid_a[3] * R2 * R + meta->sar->incid_a[4] * R2 * R2 + meta->sar->incid_a[5] * R2 * R2 * R; } else { double er = meta_get_earth_radius(meta,y,x); double ht = meta_get_sat_height(meta,y,x); return PI-acos((SQR(sr) + SQR(er) - SQR(ht)) / (2.0*sr*er)); } }
quadratic_2d get_incid(char *sarName, meta_parameters *meta) { int ll, kk; quadratic_2d q; stateVector stVec; int projected = FALSE; double *line, *sample, *incidence_angle; double earth_radius, satellite_height, time, range; double firstIncid, re, rp; // Init incidence_angle = (double *) MALLOC(sizeof(double)*GRID*GRID); line = (double *) MALLOC(sizeof(double)*GRID*GRID); sample = (double *) MALLOC(sizeof(double)*GRID*GRID); int nl = meta->general->line_count; int ns = meta->general->sample_count; re = meta->general->re_major; rp = meta->general->re_minor; projected = (meta->projection) ? TRUE : FALSE; // Populate array of incidence angles from er, sh, and r for each pixel // in the grid for (ll = 0; ll < GRID; ll++) { for (kk = 0; kk < GRID; kk++) { line[ll*GRID+kk] = ll * nl / GRID; sample[ll*GRID+kk] = kk * ns / GRID; if (projected) { earth_radius = meta_get_earth_radius(meta, ll, kk); satellite_height = meta_get_sat_height(meta, ll, kk); range = get_slant_range(meta, earth_radius, satellite_height, sample[ll*GRID+kk]); } else { time = meta_get_time(meta, line[ll*GRID+kk], sample[ll*GRID+kk]); stVec = meta_get_stVec(meta, time); earth_radius = get_earth_radius(time, stVec, re, rp); satellite_height = get_satellite_height(time, stVec); range = get_slant_range(meta, earth_radius, satellite_height, sample[ll*GRID+kk]); } incidence_angle[ll*GRID+kk] = get_incidence_angle(earth_radius, satellite_height, range); if (ll==0 && kk==0) { firstIncid = incidence_angle[0]; } } } // Fit a 2D quadratic to the grid of incidence angles q = find_quadratic(incidence_angle, line, sample, GRID*GRID); q.A = firstIncid; // Clean up FREE(line); FREE(sample); FREE(incidence_angle); return q; }
static double map_gr2sr(meta_parameters *meta, double l, double s) { double ht = meta_get_sat_height(meta, l, s); double er = meta_get_earth_radius(meta, l, s); double srfp = meta_get_slant(meta, l, 0); double grfp = er * acos((ht*ht+er*er-srfp*srfp)/(2.*ht*er)); double grcp = grfp + s * meta->transform->target_pixel_size; double srcp = sqrt(ht*ht+er*er-2.*ht*er*cos(grcp/er)); return (srcp - srfp)/meta->transform->source_pixel_size; }
/********************************************************** * meta_look: Return the look angle * This is the angle measured by the satellite between * earth's center and the target point x. Returns radians*/ double meta_look(meta_parameters *meta,double y,double x) { // No effort has been made to make this routine work with // pseudoprojected images. assert (meta->projection == NULL || meta->projection->type != LAT_LONG_PSEUDO_PROJECTION); double sr = meta_get_slant(meta,y,x); double er = meta_get_earth_radius(meta,y,x); double ht = meta_get_sat_height(meta,y,x); return acos((SQR(sr) + SQR(ht) - SQR(er)) / (2.0*sr*ht)); }
static double map_sr2gr(meta_parameters *meta, double l, double s) { double ht = meta_get_sat_height(meta, l, s); double srfp = meta_get_slant(meta, l, 0); double er = meta_get_earth_radius(meta, l, s); double x = 1. + (ht - er)/er; double y0 = srfp / er; double grfp = er * acos((1. + x*x - y0*y0)/(2.*x)); double srcp = srfp + s*meta->transform->source_pixel_size; double y1 = srcp/er; double grcp = er*acos((1. + x*x - y1*y1)/(2.*x)); return (grcp - grfp)/meta->transform->target_pixel_size; }
/******************************************************* * slantRange2groundPixel: * Calculate the ground range pixel from the total slant * range*/ int slantRange2groundPixel(meta_parameters *meta,double slant) { double a,x,y,Gr0, GrX; double Rsc, Re; int groundPixel; Rsc = meta_get_sat_height(meta, meta->general->line_count/2, 0); Re = meta_get_earth_radius(meta, meta->general->line_count/2, 0); a = (Rsc-Re)/Re; x = 1+a; y = meta->sar->slant_range_first_pixel / Re; Gr0 = Re * acos((1.0 + x*x - y*y) / (2.0 * x)); y = slant/Re; GrX = Re * acos((1.0 + x*x - y*y) / (2.0 * x)); if (!meta_is_valid_double(Gr0) || !meta_is_valid_double(GrX)) { asfPrintError("Cannot convert slant range to ground range.\n"); } if (meta && meta->projection && meta_is_valid_double(meta->projection->perX)) { groundPixel = (int) ((GrX-Gr0)/meta->projection->perX)+0.5; // printf("Slant %f :: ",slant); // printf("GP = (%f-%f) / %f = %i\n",GrX,Gr0,meta->projection->perX,groundPixel); } else if (meta && meta->general->data_type != COMPLEX_BYTE && meta->general->data_type != COMPLEX_INTEGER16 && meta->general->data_type != COMPLEX_INTEGER32 && meta->general->data_type != COMPLEX_REAL32 && meta->general->data_type != COMPLEX_REAL64 ) { groundPixel = (int) ((GrX-Gr0)/meta->general->x_pixel_size)+0.5; // printf("Slant %f :: ",slant); // printf("GP = (%f-%f) / %f = %i\n",GrX,Gr0,meta->general->x_pixel_size,groundPixel); } else { groundPixel=0; // just to quiet the compiler warning asfPrintError("Cannot convert slant range to ground range without a valid perX size.\n"); } return(groundPixel);}
void scan_to_latlon(meta_parameters *meta, double x, double y, double z, double *lat_d, double *lon, double *height) { double qlat, qlon; double lat,radius; vector pos; meta_projection *proj = meta->projection; if (z != 0.0) { // height correction applies directly to y (range direction) double line, samp; line = (y-proj->startY)/proj->perY - meta->general->start_line; samp = (x-proj->startX)/proj->perX - meta->general->start_sample; double sr = meta_get_slant(meta,line,samp); double er = proj->param.atct.rlocal; double ht = meta_get_sat_height(meta,line,samp); double cos_ang = (sr*sr + er*er - ht*ht)/(2.0*sr*er); if (cos_ang > 1) cos_ang = 1; if (cos_ang < -1) cos_ang = -1; double incid = PI-acos(cos_ang); x += z*tan(PI/2-incid); } if (meta->sar->look_direction=='R') qlat = -x/proj->param.atct.rlocal; /* Right looking sar */ else qlat = x/proj->param.atct.rlocal; /* Left looking sar */ qlon = y/(proj->param.atct.rlocal*cos(qlat)); sph2cart(proj->param.atct.rlocal, qlat, qlon, &pos); rotate_z(&pos,-proj->param.atct.alpha3); rotate_y(&pos,-proj->param.atct.alpha2); rotate_z(&pos,-proj->param.atct.alpha1); cart2sph(pos,&radius,&lat,lon); *lon *= R2D; lat *= R2D; *lat_d = atand(tand(lat) / (1-ecc2(proj->re_minor,proj->re_major))); *height = z; // FIXME: Do we need to correct the height at all? }
static void gr2sr_vec(meta_parameters *meta, float srinc, float *gr2sr, int apply_pp_earth_radius_fix) { int i; /* Counter */ float r_sc; /* radius from center of the earth for satellite */ float r_earth; /* radius of the earth */ float r_close; /* near slant range distance */ float rg0, rg; /* Ground range to first pixel, G.R. to cur pix */ float a, x, x2, y; /* temporaries */ float grinc; /* Slant and Ground range pixel spacings */ float rslant; /* slant range distance to current pixel */ /* Radius from the center of the earth to the spacecraft, slant range to first pixel, and radius of the earth */ r_sc = meta_get_sat_height(meta, 0, 0); r_close = meta_get_slant(meta,0,0); if (apply_pp_earth_radius_fix) r_earth = meta_get_earth_radius_pp(meta); else r_earth = meta_get_earth_radius(meta,0,0); /* Set the ground range and slant range increments */ grinc = meta->general->x_pixel_size; /* calculate ground range to first point */ a = (r_sc-r_earth)/r_earth; x = 1.0+a; x2 = x * x; y = r_close/r_earth; rg0 = r_earth * acos((1.0 + x2 - y*y) / (2.0*x)); /* begin loop */ for(i = 0; i<MAX_IMG_SIZE; i++) { rslant = r_close + i *srinc; y = rslant/r_earth; rg = r_earth*acos((1.0+x2-y*y)/(2.0*x)); gr2sr[i] = (rg - rg0)/grinc; } }
double meta_get_slant(meta_parameters *meta,double yLine, double xSample) { // No effort has been made to make this routine work with // pseudoprojected images. assert (meta->projection == NULL || meta->projection->type != LAT_LONG_PSEUDO_PROJECTION); if (meta->sar->image_type=='S')/*Slant range is easy.*/ return meta->sar->slant_range_first_pixel + (xSample+meta->general->start_sample) * meta->general->x_pixel_size + meta->sar->slant_shift; else if (meta->sar->image_type=='G')/*Ground range is tougher.*/ {/*We figure out the ground angle, phi, for this pixel, then use that and the law of cosines to find the slant range.*/ double er = meta_get_earth_radius(meta,yLine,xSample); double ht = meta_get_sat_height(meta,yLine,xSample); double minPhi = acos((SQR(ht)+SQR(er) - SQR(meta->sar->slant_range_first_pixel)) / (2.0*ht*er)); double phi = minPhi+ (xSample+meta->general->start_sample)*(meta->general->x_pixel_size / er); double slantRng = sqrt(SQR(ht)+SQR(er)-2.0*ht*er*cos(phi)); return slantRng + meta->sar->slant_shift; } else if (meta->sar->image_type=='P' || meta->sar->image_type=='R') { double time,slant; meta_get_timeSlantDop(meta,yLine,xSample,&time,&slant,NULL); return slant+meta->sar->slant_shift; } else /*Unknown image type.*/ { printf("Error! Unknown SAR image type '%c' passed to meta_get_slant!\n", meta->sar->image_type); exit(1); } return 0.0;/*<- for whining compilers.*/ }
static void sr2gr_vec(meta_parameters *meta, float srinc, float newSize, float *sr2gr) { double rg,rg0;/*Ground range distances from nadir, along curve of earth.*/ double ht,re,sr;/*S/C height, earth radius, slant range [m]*/ int ii; ht = meta_get_sat_height(meta, 0, 0); re = meta_get_earth_radius(meta, 0, 0); sr = meta_get_slant(meta,0,0); /* calculate ground range to first point */ rg0 = re * acos((ht*ht+re*re-sr*sr) / (2*ht*re)); /* begin loop */ rg = rg0; for (ii = 0; ii<MAX_IMG_SIZE; ii++) { double this_slant = sqrt(ht*ht+re*re-2.0*ht*re*cos(rg/re)); sr2gr[ii] = (this_slant - sr) / srinc; rg += newSize; } }
meta_parameters* vp2meta(vexcel_plain *vp) { vp_doppler_centroid_parameters doppler_params; meta_parameters *meta; char *mon[13]={"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep", "Oct","Nov","Dec"}; ymd_date ymd, ref_date; hms_time time, ref_time; julian_date jd; int i, nStVec; // Initialize the meta structure meta = raw_init(); // Fill general block strcpy(meta->general->basename, vp->gli_product.image_desc.title); strcpy(meta->general->sensor, vp->sensor.instrument_name); strcpy(meta->general->sensor_name, vp->sensor.sensor_name); // FIXME: need to handle multibeam data strcpy(meta->general->mode, vp->sensor.beam[0].beam_name); strcpy(meta->general->processor, vp->gli_product.processor_name); if (vp->gli_product.image_desc.bytes_per_pixel == 1) meta->general->data_type = ASF_BYTE; else if (vp->gli_product.image_desc.bytes_per_pixel == 2) meta->general->data_type = INTEGER16; else if (vp->gli_product.image_desc.bytes_per_pixel == 4) meta->general->data_type = REAL32; meta->general->image_data_type = AMPLITUDE_IMAGE; meta->general->radiometry = r_AMP; date_dssr2date(vp->gli_product.orbit_nr_date, &ymd, &time); sprintf(meta->general->acquisition_date, "%2d-%s-%4d", ymd.day, mon[ymd.month], ymd.year); meta->general->orbit = vp->gli_product.orbit_nr; if (strncmp(vp->flight_path_direction, "ASCENDING", 9) == 0) meta->general->orbit_direction = 'A'; else meta->general->orbit_direction = 'D'; meta->general->frame = MAGIC_UNSET_INT; meta->general->band_count = vp->sensor.nr_beams; strcpy(meta->general->bands, "AMP"); meta->general->line_count = vp->gli_product.image_desc.nr_lines;; meta->general->sample_count = vp->gli_product.image_desc.nr_pixels; meta->general->start_line = 0; meta->general->start_sample = 0; meta->general->x_pixel_size = vp->gli_product.image_desc.line_spacing; meta->general->y_pixel_size = vp->gli_product.image_desc.pixel_spacing; meta->general->center_latitude = vp->gli_product.image_desc.coord.center_line_center_pixel.lat; meta->general->center_longitude = vp->gli_product.image_desc.coord.center_line_center_pixel.lon;; meta->general->re_major = vp->gli_product.image_desc.coord.earth_model.major; meta->general->re_minor = vp->gli_product.image_desc.coord.earth_model.minor; meta->general->bit_error_rate = MAGIC_UNSET_DOUBLE; meta->general->missing_lines = 0; meta->general->no_data = MAGIC_UNSET_DOUBLE; // Fill SAR block meta->sar = meta_sar_init(); // working with assumptions here meta->sar->image_type = 'G'; if (vp->sensor.clock_angle >= 0.0) meta->sar->look_direction = 'R'; else meta->sar->look_direction = 'L'; meta->sar->azimuth_look_count = vp->gli_product.azimuth_looks; meta->sar->range_look_count = vp->gli_product.range_looks; meta->sar->deskewed = vp->gli_product.skew_flag; meta->sar->original_line_count = meta->general->line_count; meta->sar->original_sample_count = meta->general->sample_count; meta->sar->line_increment = 1; meta->sar->sample_increment = 1; meta->sar->range_time_per_pixel = fabs((2.0 * vp->gli_product.image_desc.pixel_spacing) / SPD_LIGHT); meta->sar->azimuth_time_per_pixel = vp->gli_product.time_per_line; meta->sar->slant_range_first_pixel = vp->gli_product.near_range; meta->sar->slant_shift = 0.0; if (meta->general->orbit_direction == 'D') meta->sar->time_shift = 0.0; else if (meta->general->orbit_direction == 'A') meta->sar->time_shift = fabs(meta->sar->original_line_count * meta->sar->azimuth_time_per_pixel); else meta->sar->time_shift = MAGIC_UNSET_DOUBLE; meta->sar->wavelength = SPD_LIGHT / vp->sensor.beam[0].carrier_freq; meta->sar->prf = vp->sensor.beam[0].prf; meta->sar->earth_radius_pp = MAGIC_UNSET_DOUBLE; strcpy(meta->sar->satellite_binary_time, MAGIC_UNSET_STRING); strcpy(meta->sar->satellite_clock_time, MAGIC_UNSET_STRING); doppler_params = vp->sensor.beam[0].doppler_centroid_parameters; // FIXME: Check units for higher coefficients meta->sar->range_doppler_coefficients[0] = doppler_params.doppler_centroid_coefficients.a[0]; meta->sar->range_doppler_coefficients[1] = doppler_params.doppler_centroid_coefficients.a[1]; meta->sar->range_doppler_coefficients[2] = doppler_params.doppler_centroid_coefficients.a[2]; for (i=0; i<3; i++) meta->sar->azimuth_doppler_coefficients[i] = 0.0; meta->sar->azimuth_processing_bandwidth = vp->gli_product.processor_bandwidth; meta->sar->chirp_rate = vp->sensor.beam[0].chirp_rate; meta->sar->pulse_duration = vp->sensor.beam[0].pulse_length; meta->sar->range_sampling_rate = vp->sensor.beam[0].sampling_freq; strcpy(meta->sar->polarization, vp->sensor.beam[0].polarization_block.polarization[0].polarization); meta->sar->multilook = 1; meta->sar->pitch = vp->sensor.ephemeris.attitude.pitch; meta->sar->roll = vp->sensor.ephemeris.attitude.roll; meta->sar->yaw = vp->sensor.ephemeris.attitude.yaw; // Fill state vector structure nStVec = vp->sensor.ephemeris.sv_block.nr_sv; meta->state_vectors = meta_state_vectors_init(nStVec); date_dssr2date(vp->sensor.ephemeris.sv_block.state_vector[0].date, &ref_date, &ref_time); meta->state_vectors->year = ref_date.year; date_ymd2jd(&ref_date, &jd); meta->state_vectors->julDay = jd.jd; meta->state_vectors->second = date_hms2sec(&ref_time); meta->state_vectors->vector_count = nStVec; for (i=0; i<nStVec; i++) { date_dssr2date(vp->sensor.ephemeris.sv_block.state_vector[i].date, &ymd, &time); meta->state_vectors->vecs[i].time = date_difference(&ref_date, &ref_time, &ymd, &time); meta->state_vectors->vecs[i].vec.pos.x = vp->sensor.ephemeris.sv_block.state_vector[i].x; meta->state_vectors->vecs[i].vec.pos.y = vp->sensor.ephemeris.sv_block.state_vector[i].y; meta->state_vectors->vecs[i].vec.pos.z = vp->sensor.ephemeris.sv_block.state_vector[i].z; meta->state_vectors->vecs[i].vec.vel.x = vp->sensor.ephemeris.sv_block.state_vector[i].xv; meta->state_vectors->vecs[i].vec.vel.y = vp->sensor.ephemeris.sv_block.state_vector[i].yv; meta->state_vectors->vecs[i].vec.vel.z = vp->sensor.ephemeris.sv_block.state_vector[i].zv; } date_dssr2date(vp->gli_product.first_line, &ymd, &time); double shift = date_difference(&ref_date, &ref_time, &ymd, &time); int sign; if (compare_time(&ymd, &time, &ref_date, &ref_time) > 0) sign = -1; else sign = 1; for (i=0; i<nStVec; i++) meta->state_vectors->vecs[i].time += sign * shift; meta->state_vectors->second = date_hms2sec(&time); double interval = meta->general->line_count * meta->sar->azimuth_time_per_pixel / 2; propagate_state(meta, 3, interval); meta->sar->earth_radius = meta_get_earth_radius(meta, meta->general->line_count/2, meta->general->sample_count/2); meta->sar->satellite_height = meta_get_sat_height(meta, meta->general->line_count/2, meta->general->sample_count/2); // Fill location block meta->location = meta_location_init(); meta->location->lat_start_near_range = vp->gli_product.image_desc.coord.first_line_first_pixel.lat; meta->location->lon_start_near_range = vp->gli_product.image_desc.coord.first_line_first_pixel.lon; meta->location->lat_start_far_range = vp->gli_product.image_desc.coord.first_line_last_pixel.lat; meta->location->lon_start_far_range = vp->gli_product.image_desc.coord.first_line_last_pixel.lon; meta->location->lat_end_near_range = vp->gli_product.image_desc.coord.last_line_first_pixel.lat; meta->location->lon_end_near_range = vp->gli_product.image_desc.coord.last_line_first_pixel.lon; meta->location->lat_end_far_range = vp->gli_product.image_desc.coord.last_line_last_pixel.lat; meta->location->lon_end_far_range = vp->gli_product.image_desc.coord.last_line_last_pixel.lon; return meta; }