Пример #1
0
void airsar_to_latlon(meta_parameters *meta,
                      double xSample, double yLine, double height,
                      double *lat, double *lon)
{
    if (!meta->airsar)
        asfPrintError("airsar_to_latlon() called with no airsar 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 airsar block) which doesn't match what we cached for)
    static meta_airsar *cached_airsar_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_airsar_block ||
        cached_airsar_block->lat_peg_point != meta->airsar->lat_peg_point ||
        cached_airsar_block->lon_peg_point != meta->airsar->lon_peg_point ||
        cached_airsar_block->head_peg_point != meta->airsar->head_peg_point;

    if (recalc) {
        // cache airsar block, so we can be sure we're not reusing
        // the stored data incorrectly
        if (cached_airsar_block)
            free(cached_airsar_block);
        cached_airsar_block = meta_airsar_init();
        *cached_airsar_block = *(meta->airsar);

        asfPrintStatus("Calculating airsar transformation parameters...\n");

        // now precalculate data
        double lat_peg = meta->airsar->lat_peg_point*D2R;
        double lon_peg = meta->airsar->lon_peg_point*D2R;
        double head_peg = meta->airsar->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->airsar->cross_track_offset;
    double s0 = meta->airsar->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);
}
Пример #2
0
meta_parameters* airsar2meta(airsar_header *header,
			     airsar_param_header *params,
			     airsar_dem_header *dem)
{
  meta_parameters *meta;
  hms_time hms;

  // Allocate memory for metadata structure
  meta = raw_init();

  // General block
  sprintf(meta->general->basename, "%s", params->site_name);
  sprintf(meta->general->sensor, "AIRSAR");
  strcpy(meta->general->sensor_name, "SAR");
  if (strlen(header->processor)>0) {
    header->processor[4] = '\0';
    strcpy(meta->general->processor, "JPL version ");
    strcat(meta->general->processor, header->processor);
  } else {
    strcpy(meta->general->processor, MAGIC_UNSET_STRING);
  }
  // FIXME: various data types - InSAR vs. polarimetric
  date_sec2hms(params->acquisition_seconds, &hms);
  sprintf(meta->general->acquisition_date, "%s %d:%d:%.3lf",
      params->acquisition_date, hms.hour, hms.min, hms.sec);
  meta->general->orbit = params->cct_id; // close enough
  // no frame number
  // FIXME: decide how to separate interferometric/polarimetric data
  meta->general->band_count = 1;
  meta->general->line_count = header->line_count;
    //header->line_count - header->first_data_offset / header->sample_count;
  meta->general->sample_count = header->sample_count;
  meta->general->start_line = 0;
  meta->general->start_sample = 0;
  meta->general->x_pixel_size = header->x_pixel_size;
  meta->general->y_pixel_size = header->y_pixel_size;
  meta->general->center_latitude = params->center_lat;
  meta->general->center_longitude = params->center_lon;
  meta->general->re_major = 6378137.0; // WGS84
  meta->general->re_minor = 6356752.314; // WGS84
  // no information on bit error rate, missing lines and no data

  // SAR block
  meta->sar = meta_sar_init();
  // The CCT type 'CM' stands for 'Compressed Stokes Matrix' which implies
  // that you have fully polarimetric data
  if (strncmp_case(params->cct_type, "CM", 2) == 0) {
    meta->general->image_data_type = POLARIMETRIC_IMAGE;
    meta->general->radiometry = r_SIGMA;
    strcpy(meta->sar->polarization, "QUAD-POL");
    meta->general->band_count = 8;
  }
  if (strncmp_case(header->range_projection, "GROUND", 6) == 0)
    meta->sar->image_type = 'G';
  // no information on look direction
  if (params->deskewed == 1)
    meta->sar->deskewed = 1;
  else if (params->deskewed == 2)
    meta->sar->deskewed = 0;
  meta->sar->original_line_count = header->line_count;
  meta->sar->original_sample_count = header->sample_count;
  meta->sar->line_increment = 1;
  meta->sar->sample_increment = 1;
  // no information on azimuth and range time per pixel
  // no information on slant and time shift
  meta->sar->slant_range_first_pixel = params->near_slant_range;
  meta->sar->wavelength = params->wavelength;
  meta->sar->prf = params->prf;
  // no information on earth radius and satellite height
  // no time information
  // no Doppler information
  meta->sar->azimuth_processing_bandwidth = params->chirp_bandwidth;
  // no chirp rate information
  meta->sar->pulse_duration = params->pulse_length;
  meta->sar->range_sampling_rate = params->range_sampling_rate;
  // FIXME: check polarizations for interferometric/polarimetric data
  // FIXME: multilook flag depends on data type
  
  // AirSAR block
  meta->airsar = meta_airsar_init();
  meta->airsar->scale_factor = 1.0; // Bruce Chapman said so.
  meta->airsar->gps_altitude = params->gps_altitude;
  if (dem) {
    meta->airsar->lat_peg_point = dem->lat_peg_point;
    meta->airsar->lon_peg_point = dem->lon_peg_point;
    meta->airsar->head_peg_point = dem->head_peg_point;
    meta->airsar->along_track_offset = dem->along_track_offset;
    meta->airsar->cross_track_offset = dem->cross_track_offset;
  }
  else {
    meta->airsar->lat_peg_point = params->lat_peg_point;
    meta->airsar->lon_peg_point = params->lon_peg_point;
    meta->airsar->head_peg_point = params->head_peg_point;
    meta->airsar->along_track_offset = params->along_track_offset;
    meta->airsar->cross_track_offset = params->cross_track_offset;
  }
  // The DEM header of Rick's prime test data did not have a valid peg point.
  // Without that the other numbers (along-track and cross-track offsets
  // as well as corner coordinates) don't make sense.
  // Will take the numbers out of the parameter header. Seems to work fine
  // with the prime test data set. Extract only elevation offset and increment
  // out of the DEM header
  if (dem) {
    meta->airsar->elevation_increment = dem->elevation_increment;
    meta->airsar->elevation_offset = dem->elevation_offset;
  }

  // Location block
  meta->location = meta_location_init();
  if (dem) {
    meta->location->lat_start_near_range = dem->corner1_lat;
    meta->location->lon_start_near_range = dem->corner1_lon;
    meta->location->lat_start_far_range = dem->corner2_lat;
    meta->location->lon_start_far_range = dem->corner2_lon;
    meta->location->lat_end_near_range = dem->corner4_lat;
    meta->location->lon_end_near_range = dem->corner4_lon;
    meta->location->lat_end_far_range = dem->corner3_lat;
    meta->location->lon_end_far_range = dem->corner3_lon;
  }
    
  return meta;
}