meta_parameters* uavsar_insar2meta(uavsar_insar *params) { meta_parameters *meta; // Allocate memory for metadata structure meta = raw_init(); // General block sprintf(meta->general->basename, "%s", params->site); sprintf(meta->general->sensor, "UAVSAR"); strcpy(meta->general->sensor_name, "InSAR"); strcpy(meta->general->processor, "JPL version "); strcat(meta->general->processor, params->processor); if (params->type == INSAR_AMP || params->type == INSAR_AMP_GRD) { if (params->type == INSAR_AMP) strcpy(meta->general->mode, "AMP"); else if (params->type == INSAR_AMP_GRD) strcpy(meta->general->mode, "AMP_GRD"); meta->general->image_data_type = AMPLITUDE_IMAGE; } else if (params->type == INSAR_INT || params->type == INSAR_INT_GRD) { if (params->type == INSAR_INT) strcpy(meta->general->mode, "INT"); else if (params->type == INSAR_INT_GRD) strcpy(meta->general->mode, "INT_GRD"); meta->general->image_data_type = INTERFEROGRAM; } else if (params->type == INSAR_UNW || params->type == INSAR_UNW_GRD) { if (params->type == INSAR_UNW) strcpy(meta->general->mode, "UNW"); else if (params->type == INSAR_UNW_GRD) strcpy(meta->general->mode, "UNW_GRD"); meta->general->image_data_type = UNWRAPPED_PHASE; } else if (params->type == INSAR_COR || params->type == INSAR_COR_GRD) { if (params->type == INSAR_COR) strcpy(meta->general->mode, "COR"); else if (params->type == INSAR_COR_GRD) strcpy(meta->general->mode, "COR_GRD"); meta->general->image_data_type = COHERENCE_IMAGE; } else if (params->type == INSAR_HGT_GRD) { strcpy(meta->general->mode, "HGT_GRD"); meta->general->image_data_type = DEM; } else strcpy(meta->general->mode, "unknown"); meta->general->data_type = REAL32; strcpy(meta->general->acquisition_date, params->acquisition_date); meta->general->band_count = 1; meta->general->line_count = params->row_count; meta->general->sample_count = params->column_count; meta->general->start_line = 0; meta->general->start_sample = 0; meta->general->x_pixel_size = params->range_pixel_spacing; meta->general->y_pixel_size = fabs(params->azimuth_pixel_spacing); meta->general->re_major = params->semi_major; double a = params->semi_major; double ecc2 = params->eccentricity; meta->general->re_minor = sqrt((1-ecc2)*a*a); // no information on bit error rate, missing lines and no data // SAR block meta->sar = meta_sar_init(); strcpy(meta->sar->polarization, params->polarization); if (strcmp_case(params->projection, "SCX") == 0) meta->sar->image_type = 'S'; else if (strcmp_case(params->projection, "EQA") == 0) meta->sar->image_type = 'P'; if (strcmp_case(params->look_direction, "Left") == 0) meta->sar->look_direction = 'L'; else if (strcmp_case(params->look_direction, "Right") == 0) meta->sar->look_direction = 'R'; meta->sar->azimuth_look_count = params->azimuth_look_count; meta->sar->range_look_count = params->range_look_count; meta->sar->multilook = 1; meta->sar->deskewed = 1; meta->sar->original_line_count = params->row_count; meta->sar->original_sample_count = params->column_count; meta->sar->line_increment = 1; meta->sar->sample_increment = 1; // no information on azimuth and range time per pixel meta->sar->time_shift = 0.0; meta->sar->slant_shift = 0.0; meta->sar->slant_range_first_pixel = params->slant_range_first_pixel * 1000.0; meta->sar->wavelength = params->wavelength / 100.0; // no information on pulse repetition frequency // no information on earth radius and satellite height // no time information // no Doppler information meta->sar->yaw = params->yaw; meta->sar->pitch = params->pitch; meta->sar->roll = params->roll; meta->sar->azimuth_processing_bandwidth = params->bandwidth; // no chirp rate information meta->sar->pulse_duration = params->pulse_length / 1000.0; // no information on range sampling rate // FIXME: check polarizations for interferometric/polarimetric data // FIXME: multilook flag depends on data type // UAVSAR block meta->uavsar = meta_uavsar_init(); strcpy(meta->uavsar->id, params->id); meta->uavsar->scale_factor = 1.0; meta->uavsar->gps_altitude = params->altitude; meta->uavsar->lat_peg_point = params->lat_peg_point; meta->uavsar->lon_peg_point = params->lon_peg_point; meta->uavsar->head_peg_point = params->head_peg_point; meta->uavsar->along_track_offset = params->along_track_offset; meta->uavsar->cross_track_offset = params->cross_track_offset; // Projection block if (params->type >= INSAR_AMP_GRD && params->type <= INSAR_HGT_GRD) { meta->projection = meta_projection_init(); meta->projection->type = LAT_LONG_PSEUDO_PROJECTION; strcpy (meta->projection->units, "degrees"); if (params->along_track_offset >= 0.0) meta->projection->hem = 'N'; else meta->projection->hem = 'S'; meta->projection->re_major = meta->general->re_major; meta->projection->re_minor = meta->general->re_minor; meta->projection->height = 0.0; meta->projection->spheroid = WGS84_SPHEROID; meta->projection->datum = WGS84_DATUM; // FIXME: Check that the following is correct - needs some data // Coordinate reference: Point // UAVSAR lat/lon projected data is calculated from center // pixel. Thus we have to add in a half-pixel shift. meta->projection->startX = params->cross_track_offset - params->range_pixel_spacing / 2.0; meta->projection->startY = params->along_track_offset - params->azimuth_pixel_spacing / 2.0; meta->projection->perX = params->range_pixel_spacing; meta->projection->perY = params->azimuth_pixel_spacing; meta->general->center_latitude = params->along_track_offset + params->azimuth_pixel_spacing * params->row_count / 2.0; meta->general->center_longitude = params->cross_track_offset + params->range_pixel_spacing * params->column_count / 2.0; } // Location block meta->location = meta_location_init(); meta->location->lat_start_near_range = params->lat_upper_left; meta->location->lon_start_near_range = params->lon_upper_left; meta->location->lat_start_far_range = params->lat_upper_right; meta->location->lon_start_far_range = params->lon_upper_right; meta->location->lat_end_near_range = params->lat_lower_left; meta->location->lon_end_near_range = params->lon_lower_left; meta->location->lat_end_far_range = params->lat_lower_right; meta->location->lon_end_far_range = params->lon_lower_right; return meta; }
void uavsar_to_latlon(meta_parameters *meta, double xSample, double yLine, double height, double *lat, double *lon) { if (!meta->uavsar) asfPrintError("uavsar_to_latlon() called with no uavsar block!\n"); const double a = 6378137.0; // semi-major axis const double b = 6356752.3412; // semi-minor axis const double e2 = 0.00669437999014; // ellipticity const double e12 = 0.00673949674228; // second eccentricity // we try to cache the matrices needed for the computation // this makes sure we don't reuse the cache incorrectly (i.e., on // data (=> an uavsar block) which doesn't match what we cached for) static meta_uavsar *cached_uavsar_block = NULL; // these are the cached transformation parameters static matrix *m = NULL; static double ra=-999, o1=-999, o2=-999, o3=-999; if (!m) m = matrix_alloc(3,3); // only needs to be done once // if we aren't calculating with the exact same airsar block, we // need to recalculate the transformation block int recalc = !cached_uavsar_block || cached_uavsar_block->lat_peg_point != meta->uavsar->lat_peg_point || cached_uavsar_block->lon_peg_point != meta->uavsar->lon_peg_point || cached_uavsar_block->head_peg_point != meta->uavsar->head_peg_point; if (recalc) { // cache airsar block, so we can be sure we're not reusing // the stored data incorrectly if (cached_uavsar_block) free(cached_uavsar_block); cached_uavsar_block = meta_uavsar_init(); *cached_uavsar_block = *(meta->uavsar); // now precalculate data double lat_peg = meta->uavsar->lat_peg_point*D2R; double lon_peg = meta->uavsar->lon_peg_point*D2R; double head_peg = meta->uavsar->head_peg_point*D2R; double re = a / sqrt(1-e2*sin(lat_peg)*sin(lat_peg)); double rn = (a*(1-e2)) / pow(1-e2*sin(lat_peg)*sin(lat_peg), 1.5); ra = (re*rn) / (re*cos(head_peg)*cos(head_peg)+rn*sin(head_peg)*sin(head_peg)); matrix *m1, *m2; m1 = matrix_alloc(3,3); m2 = matrix_alloc(3,3); m1->coeff[0][0] = -sin(lon_peg); m1->coeff[0][1] = -sin(lat_peg)*cos(lon_peg); m1->coeff[0][2] = cos(lat_peg)*cos(lon_peg); m1->coeff[1][0] = cos(lon_peg); m1->coeff[1][1] = -sin(lat_peg)*sin(lon_peg); m1->coeff[1][2] = cos(lat_peg)*sin(lon_peg); m1->coeff[2][0] = 0.0; m1->coeff[2][1] = cos(lat_peg); m1->coeff[2][2] = sin(lat_peg); m2->coeff[0][0] = 0.0; m2->coeff[0][1] = sin(head_peg); m2->coeff[0][2] = -cos(head_peg); m2->coeff[1][0] = 0.0; m2->coeff[1][1] = cos(head_peg); m2->coeff[1][2] = sin(head_peg); m2->coeff[2][0] = 1.0; m2->coeff[2][1] = 0.0; m2->coeff[2][2] = 0.0; o1 = re*cos(lat_peg)*cos(lon_peg)-ra*cos(lat_peg)*cos(lon_peg); o2 = re*cos(lat_peg)*sin(lon_peg)-ra*cos(lat_peg)*sin(lon_peg); o3 = re*(1-e2)*sin(lat_peg)-ra*sin(lat_peg); matrix_mult(m,m1,m2); matrix_free(m1); matrix_free(m2); } // Make sure we didn't miss anything assert(ra != -999 && o1 != -999 && o2 != -999 && o3 != -999); //------------------------------------------------------------------ // Now the actual computation, using the cached matrix etc // convenience aliases double c0 = meta->uavsar->cross_track_offset; double s0 = meta->uavsar->along_track_offset; double ypix = meta->general->y_pixel_size/meta->general->line_scaling; double xpix = meta->general->x_pixel_size/meta->general->sample_scaling; // radar coordinates double c_lat = (xSample*xpix+c0)/ra; double s_lon = (yLine*ypix+s0)/ra; //height += meta->airsar->gps_altitude; // radar coordinates in WGS84 double t1 = (ra+height)*cos(c_lat)*cos(s_lon); double t2 = (ra+height)*cos(c_lat)*sin(s_lon); double t3 = (ra+height)*sin(c_lat); double c1 = m->coeff[0][0]*t1 + m->coeff[0][1]*t2 + m->coeff[0][2]*t3; double c2 = m->coeff[1][0]*t1 + m->coeff[1][1]*t2 + m->coeff[1][2]*t3; double c3 = m->coeff[2][0]*t1 + m->coeff[2][1]*t2 + m->coeff[2][2]*t3; // shift into local Cartesian coordinates double x = c1 + o1;// + 9.0; double y = c2 + o2;// - 161.0; double z = c3 + o3;// - 179.0; // local Cartesian coordinates into geographic coordinates double d = sqrt(x*x+y*y); double theta = atan2(z*a, d*b); *lat = R2D*atan2(z+e12*b*sin(theta)*sin(theta)*sin(theta), d-e2*a*cos(theta)*cos(theta)*cos(theta)); *lon = R2D*atan2(y, x); }
meta_parameters* uavsar_polsar2meta(uavsar_polsar *params) { meta_parameters *meta; // Allocate memory for metadata structure meta = raw_init(); // General block sprintf(meta->general->basename, "%s", params->site); sprintf(meta->general->sensor, "UAVSAR"); strcpy(meta->general->sensor_name, "PolSAR"); strcpy(meta->general->processor, "JPL version "); strcat(meta->general->processor, params->processor); if (params->type == POLSAR_SLC) { strcpy(meta->general->mode, "SLC"); meta->general->image_data_type = POLARIMETRIC_S2_MATRIX; } else if (params->type == POLSAR_MLC) { strcpy(meta->general->mode, "MLC"); meta->general->image_data_type = POLARIMETRIC_C3_MATRIX; } else if (params->type == POLSAR_DAT) { strcpy(meta->general->mode, "DAT"); meta->general->image_data_type = POLARIMETRIC_STOKES_MATRIX; } else if (params->type == POLSAR_GRD) { strcpy(meta->general->mode, "GRD"); meta->general->image_data_type = POLARIMETRIC_C3_MATRIX; meta->general->no_data = 0; } else if (params->type == POLSAR_HGT) { strcpy(meta->general->mode, "HGT"); meta->general->image_data_type = DEM; } else strcpy(meta->general->mode, "unknown"); meta->general->radiometry = r_GAMMA; meta->general->data_type = REAL32; strcpy(meta->general->acquisition_date, params->acquisition_date); meta->general->band_count = 1; meta->general->line_count = params->row_count; meta->general->sample_count = params->column_count; meta->general->start_line = 0; meta->general->start_sample = 0; meta->general->x_pixel_size = params->range_pixel_spacing; meta->general->y_pixel_size = fabs(params->azimuth_pixel_spacing); meta->general->re_major = params->semi_major; double re = params->semi_major; double ecc2 = params->eccentricity; double rp = sqrt((1-ecc2)*re*re); meta->general->re_minor = rp; // no information on bit error rate, missing lines and no data // SAR block meta->sar = meta_sar_init(); strcpy(meta->sar->polarization, "QUAD-POL"); if (strcmp_case(params->projection, "SCX") == 0) meta->sar->image_type = 'S'; else if (strcmp_case(params->projection, "EQA") == 0) meta->sar->image_type = 'P'; if (strcmp_case(params->look_direction, "Left") == 0) meta->sar->look_direction = 'L'; else if (strcmp_case(params->look_direction, "Right") == 0) meta->sar->look_direction = 'R'; if (params->type == POLSAR_SLC) { meta->sar->azimuth_look_count = 1; meta->sar->range_look_count = 1; meta->sar->multilook = 0; } else { // FIXME: Update once range look count is introduced to metadata structure meta->sar->azimuth_look_count = params->azimuth_look_count; meta->sar->range_look_count = params->range_look_count; meta->sar->multilook = 1; } meta->sar->deskewed = 1; meta->sar->original_line_count = params->row_count; meta->sar->original_sample_count = params->column_count; meta->sar->line_increment = 1; meta->sar->sample_increment = 1; // no information on azimuth and range time per pixel meta->sar->time_shift = 0.0; meta->sar->slant_shift = 0.0; meta->sar->slant_range_first_pixel = params->slant_range_first_pixel * 1000.0; meta->sar->wavelength = params->wavelength / 100.0; // no information on pulse repetition frequency double tan_lat = params->lat_peg_point*D2R; meta->sar->earth_radius = rp*sqrt(1 + tan_lat*tan_lat) / sqrt(rp*rp/(re*re) + tan_lat*tan_lat); // no information on satellite height // no time information // no Doppler information meta->sar->yaw = params->yaw; meta->sar->pitch = params->pitch; meta->sar->roll = params->roll; meta->sar->azimuth_processing_bandwidth = params->bandwidth; // no chirp rate information meta->sar->pulse_duration = params->pulse_length / 1000.0; // no information on range sampling rate // FIXME: check polarizations for interferometric/polarimetric data // FIXME: multilook flag depends on data type // UAVSAR block meta->uavsar = meta_uavsar_init(); strcpy(meta->uavsar->id, params->id); meta->uavsar->scale_factor = 1.0; meta->uavsar->gps_altitude = params->altitude; meta->uavsar->lat_peg_point = params->lat_peg_point; meta->uavsar->lon_peg_point = params->lon_peg_point; meta->uavsar->head_peg_point = params->head_peg_point; meta->uavsar->along_track_offset = params->along_track_offset; meta->uavsar->cross_track_offset = params->cross_track_offset; // Location block meta->location = meta_location_init(); meta->location->lat_start_near_range = params->lat_upper_left; meta->location->lon_start_near_range = params->lon_upper_left; meta->location->lat_start_far_range = params->lat_upper_right; meta->location->lon_start_far_range = params->lon_upper_right; meta->location->lat_end_near_range = params->lat_lower_left; meta->location->lon_end_near_range = params->lon_lower_left; meta->location->lat_end_far_range = params->lat_lower_right; meta->location->lon_end_far_range = params->lon_lower_right; // Projection block if (params->type == POLSAR_GRD || params->type == POLSAR_HGT) { meta->projection = meta_projection_init(); meta->projection->type = LAT_LONG_PSEUDO_PROJECTION; strcpy (meta->projection->units, "degrees"); if (params->along_track_offset >= 0.0) meta->projection->hem = 'N'; else meta->projection->hem = 'S'; meta->projection->re_major = meta->general->re_major; meta->projection->re_minor = meta->general->re_minor; meta->projection->height = 0.0; meta->projection->spheroid = WGS84_SPHEROID; meta->projection->datum = WGS84_DATUM; // Coordinate reference: Point // UAVSAR lat/lon projected data is calculated from center // pixel. Thus we have to add in a half-pixel shift. meta->projection->startX = params->cross_track_offset - params->range_pixel_spacing / 2.0; meta->projection->startY = params->along_track_offset - params->azimuth_pixel_spacing / 2.0; meta->projection->perX = params->range_pixel_spacing; meta->projection->perY = params->azimuth_pixel_spacing; meta->general->center_latitude = params->along_track_offset + params->azimuth_pixel_spacing * params->row_count / 2.0; meta->general->center_longitude = params->cross_track_offset + params->range_pixel_spacing * params->column_count / 2.0; } else { meta_get_latLon(meta, meta->general->line_count/2, meta->general->sample_count/2, 0, &meta->general->center_latitude, &meta->general->center_longitude); } return meta; }