static void line_samp_to_proj(ImageInfo *ii, double line, double samp, double *x, double *y) { meta_parameters *meta = ii->meta; if (meta_supports_meta_get_latLon(meta)) { double lat, lon, projZ; meta_get_latLon(meta, line, samp, 0, &lat, &lon); if (meta->projection && meta->projection->type != LAT_LONG_PSEUDO_PROJECTION) { latlon_to_proj(meta->projection, 'R', lat*D2R, lon*D2R, 0, x, y, &projZ); } else { int zone; if (meta_is_valid_double(meta->general->center_longitude) && meta->general->center_longitude > -180 && meta->general->center_longitude < 180) { zone = utm_zone(meta->general->center_longitude); } else { zone = utm_zone(lon); } latLon2UTM_zone(lat, lon, 0, zone, x, y); } } else { *x = samp; *y = line; } }
void fill_in_utm(double lat, double lon, project_parameters_t *pps) { pps->utm.zone = utm_zone(lon); pps->utm.scale_factor = 0.9996; pps->utm.lon0 = (double) (pps->utm.zone - 1) * 6.0 - 177.0; pps->utm.lat0 = 0.0; pps->utm.false_easting = 500000.0; if (lat > 0.0) pps->utm.false_northing = 0.0; else pps->utm.false_northing = 10000000.0; }
static int proj_getls(double *line, double *samp) { meta_parameters *meta = curr->meta; if (meta->projection || (meta->sar&&meta->state_vectors) || meta->transform || meta->airsar) { double x = get_double_from_entry("go_to_projx_entry"); double y = get_double_from_entry("go_to_projy_entry"); double lat, lon; if (curr->meta->projection) { double h; proj_to_latlon(curr->meta->projection, x, y, 0, &lat, &lon, &h); if (lat==y && lon==x) { // this is usually indicative of failure... an error will have // been printed out already by libproj return FALSE; } lat *= R2D; lon *= R2D; } else { int zone = utm_zone(curr->meta->general->center_longitude); asfPrintStatus("Unprojected data -- assuming UTM (zone: %d)\n", zone); UTM2latLon(x, y, 0, zone, &lat, &lon); if (lat==y*R2D && lon==x*R2D) { // this is usually indicative of failure... an error will have // been printed out already by libproj return FALSE; } } int bad = meta_get_lineSamp(curr->meta, lat, lon, 0, line, samp); return !bad; } else { asfPrintWarning("No geolocation information available -- GoTo will only\n" "work for GoTo by Line/Sample.\n"); return FALSE; } }
void location_to_latlon(meta_parameters *meta, double x, double y, double z, double *lat_d, double *lon, double *height) { double x_ul, y_ul, x_ur, y_ur, x_ll, y_ll, x_lr, y_lr; // Define the UTM zone to make sure everything happens to make sure that // everything happens in the right coordinate space. int zone = utm_zone(meta->general->center_longitude); // Get corner coordinates into UTM latLon2UTM_zone(meta->location->lat_start_near_range, meta->location->lon_start_near_range, 0.0, zone, &x_ul, &y_ul); latLon2UTM_zone(meta->location->lat_start_far_range, meta->location->lon_start_far_range, 0.0, zone, &x_ur, &y_ur); latLon2UTM_zone(meta->location->lat_end_near_range, meta->location->lon_end_near_range, 0.0, zone, &x_ll, &y_ll); latLon2UTM_zone(meta->location->lat_end_far_range, meta->location->lon_end_far_range, 0.0, zone, &x_lr, &y_lr); // Bilinear interpolation to determine line/sample position in UTM coords double x_scale = x / meta->general->sample_count; double y_scale = y / meta->general->line_count; double x_up = x_ul + x_scale*(x_ur - x_ul); double y_up = y_ul + x_scale*(y_ur - y_ul); double x_down = x_ll + x_scale*(x_lr - x_ll); double y_down = y_ll + x_scale*(y_lr - y_ll); double x_sample = x_up + y_scale*(x_down - x_up); double y_line = y_up + y_scale*(y_down - y_up); // Convert from UTM coordinates back to lat/lon and call it a day UTM2latLon(x_sample, y_line, 0.0, zone, lat_d, lon); *height = 0.0; }
static Poly * get_viewable_region(stateVector *st, BeamModeInfo *bmi, double look_angle, int target_zone, double target_lat, double target_lon, double *region_clat, double *region_clon) { static const int verbose = FALSE; if (bmi->min_look_angle>0) { assert(look_angle >= D2R*(bmi->min_look_angle-.0001)); assert(look_angle <= D2R*(bmi->max_look_angle+.0001)); } double center_lat, center_lon, center_x, center_y; get_target_latlon(st, look_angle, ¢er_lat, ¢er_lon); // return NULL if we are "far away" (UTM only) if (is_utm(target_zone)) { int zone = utm_zone(center_lon); if (iabs(zone - target_zone) > 2) return NULL; } if (fabs(center_lat - target_lat) > 20) return NULL; ll2pr(center_lat, center_lon, target_zone, ¢er_x, ¢er_y); if (verbose) { printf("--------------------------------------------------------------\n"); printf("center: x,y: %f %f lat,lon: %f %f\n", center_x, center_y, center_lat, center_lon); } // location of a point just a bit ahead of us stateVector ahead_st = propagate(*st, 0, 1); double ahead_lat, ahead_lon, ahead_x, ahead_y; get_target_latlon(&ahead_st, look_angle, &ahead_lat, &ahead_lon); ll2pr(ahead_lat, ahead_lon, target_zone, &ahead_x, &ahead_y); if (verbose) printf("ahead: x,y: %f %f lat,lon: %f %f\n", ahead_x, ahead_y, ahead_lat, ahead_lon); // now we know the orientation of the rectangle on the ground // ==> can find the 4 corners double tilt = atan2(ahead_y-center_y, ahead_x-center_x); double xl = bmi->length_m; double yl = bmi->width_m; double x_side1 = cos(tilt)*xl; double y_side1 = sin(tilt)*xl; double x_side2 = sin(tilt)*yl; double y_side2 = cos(tilt)*yl; double x[4], y[4]; //x[0] = center_x + x_side1/2. - x_side2/2.; //y[0] = center_y + y_side1/2. - y_side2/2.; x[0] = center_x + x_side1/2. - x_side2/2.; y[0] = center_y + y_side1/2. + y_side2/2.; x[1] = x[0] - x_side1; y[1] = y[0] - y_side1; x[2] = x[1] + x_side2; y[2] = y[1] - y_side2; x[3] = x[2] + x_side1; y[3] = y[2] + y_side1; if (verbose) { int i; printf("corners:\n"); double xa=0, ya=0; for (i=0; i<4; ++i) { double lat, lon; pr2ll(x[i],y[i],target_zone,&lat,&lon); printf("x,y: %f %f lat,lon: %f %f\n", x[i], y[i], lat, lon); xa += x[i]; ya += y[i]; } xa/=4.; ya/=4.; double lata, lona; pr2ll(xa,ya,target_zone, &lata, &lona); printf("avg x,y: %f %f lat,lon: %f %f\n\n", xa, ya, lata, lona); } if (region_clat) *region_clat = center_lat; if (region_clon) *region_clon = center_lon; return polygon_new_closed(4, x, y); }
int main(int c, char *v[]) { if (c < 6 || c > 48) { help(v[0]); return 1; } // utm zone and hemisphere: true for 'N' and false for 'S' int zone; bool hem; const char *utm_string = pick_option(&c, &v, "-utm-zone", "no_utm_zone"); parse_utm_string(&zone, &hem, utm_string); // ascii flag bool ascii = pick_option(&c, &v, "-ascii", NULL); // longitude-latitude bounding box double lon_m = atof(pick_option(&c, &v, "-lon-m", "-inf")); double lon_M = atof(pick_option(&c, &v, "-lon-M", "inf")); double lat_m = atof(pick_option(&c, &v, "-lat-m", "-inf")); double lat_M = atof(pick_option(&c, &v, "-lat-M", "inf")); // x-y bounding box double col_m = atof(pick_option(&c, &v, "-col-m", "-inf")); double col_M = atof(pick_option(&c, &v, "-col-M", "inf")); double row_m = atof(pick_option(&c, &v, "-row-m", "-inf")); double row_M = atof(pick_option(&c, &v, "-row-M", "inf")); // mask on the unrectified image grid const char *msk_orig_fname = pick_option(&c, &v, "-mask-orig", ""); int msk_orig_w, msk_orig_h; float *msk_orig = iio_read_image_float(msk_orig_fname, &msk_orig_w, &msk_orig_h); // rectifying homography double href_inv[9], hsec_inv[9]; int n_hom; const char *hom_string_ref = pick_option(&c, &v, "href", ""); if (*hom_string_ref) { double *hom = alloc_parse_doubles(9, hom_string_ref, &n_hom); if (n_hom != 9) fail("can not read 3x3 matrix from \"%s\"", hom_string_ref); invert_homography(href_inv, hom); } const char *hom_string_sec = pick_option(&c, &v, "hsec", ""); if (*hom_string_sec) { double *hom = alloc_parse_doubles(9, hom_string_sec, &n_hom); if (n_hom != 9) fail("can not read 3x3 matrix from \"%s\"", hom_string_sec); invert_homography(hsec_inv, hom); } // open disp and mask input images int w, h, nch, ww, hh, pd; float *dispy; float *dispx = iio_read_image_float_split(v[2], &w, &h, &nch); if (nch > 1) dispy = dispx + w*h; else dispy = calloc(w*h, sizeof(*dispy)); float *mask = iio_read_image_float(v[3], &ww, &hh); if (w != ww || h != hh) fail("disp and mask image size mismatch\n"); // open color images if provided uint8_t *clr = NULL; if (c > 6) { clr = iio_read_image_uint8_vec(v[6], &ww, &hh, &pd); if (w != ww || h != hh) fail("disp and color image size mismatch\n"); } // read input rpc models struct rpc rpc_ref[1], rpc_sec[1]; read_rpc_file_xml(rpc_ref, v[4]); read_rpc_file_xml(rpc_sec, v[5]); // outputs double p[2], q[2], X[3]; // count number of valid pixels, and determine utm zone int npoints = 0; for (int row=0; row<h; row++) for (int col=0; col<w; col++) { int pix = row*w + col; if (!mask[pix]) continue; // compute coordinates of pix in the full reference image double a[2] = {col, row}; apply_homography(p, href_inv, a); // check that it lies in the image domain bounding box if (round(p[0]) < col_m || round(p[0]) > col_M || round(p[1]) < row_m || round(p[1]) > row_M) continue; // check that it passes the image domain mask int x = (int) round(p[0]) - col_m; int y = (int) round(p[1]) - row_m; if ((x < msk_orig_w) && (y < msk_orig_h)) if (!msk_orig[y * msk_orig_w + x]) continue; // compute (lon, lat, alt) of the 3D point float dx = dispx[pix]; float dy = dispy[pix]; double b[2] = {col + dx, row + dy}; apply_homography(q, hsec_inv, b); intersect_rays(X, p, q, rpc_ref, rpc_sec); // check with lon/lat bounding box if (X[0] < lon_m || X[0] > lon_M || X[1] < lat_m || X[1] > lat_M) continue; // if it passed all these tests then it's a valid point npoints++; // if not defined, utm zone is that of the first point if (zone < 0) utm_zone(&zone, &hem, X[1], X[0]); } // print header for ply file FILE *ply_file = fopen(v[1], "w"); write_ply_header(ply_file, ascii, npoints, zone, hem, (bool) clr, false); // loop over all the pixels of the input disp map // a 3D point is produced for each non-masked disparity for (int row=0; row<h; row++) for (int col=0; col<w; col++) { int pix = row*w + col; if (!mask[pix]) continue; // compute coordinates of pix in the full reference image double a[2] = {col, row}; apply_homography(p, href_inv, a); // check that it lies in the image domain bounding box if (round(p[0]) < col_m || round(p[0]) > col_M || round(p[1]) < row_m || round(p[1]) > row_M) continue; // check that it passes the image domain mask int x = (int) round(p[0]) - col_m; int y = (int) round(p[1]) - row_m; if ((x < msk_orig_w) && (y < msk_orig_h)) if (!msk_orig[y * msk_orig_w + x]) continue; // compute (lon, lat, alt) of the 3D point float dx = dispx[pix]; float dy = dispy[pix]; double b[2] = {col + dx, row + dy}; apply_homography(q, hsec_inv, b); intersect_rays(X, p, q, rpc_ref, rpc_sec); // check with lon/lat bounding box if (X[0] < lon_m || X[0] > lon_M || X[1] < lat_m || X[1] > lat_M) continue; // convert (lon, lat, alt) to utm utm_alt_zone(X, X[1], X[0], zone); // colorization: if greyscale, copy the grey level on each channel uint8_t rgb[3]; if (clr) { for (int k = 0; k < pd; k++) rgb[k] = clr[k + pd*pix]; for (int k = pd; k < 3; k++) rgb[k] = rgb[k-1]; } // write to ply if (ascii) { fprintf(ply_file, "%0.17g %0.17g %0.17g ", X[0], X[1], X[2]); if (clr) fprintf(ply_file, "%d %d %d", rgb[0], rgb[1], rgb[2]); fprintf(ply_file, "\n"); } else { double XX[3] = {X[0], X[1], X[2]}; fwrite(XX, sizeof(double), 3, ply_file); if (clr) { unsigned char C[3] = {rgb[0], rgb[1], rgb[2]}; fwrite(rgb, sizeof(unsigned char), 3, ply_file); } } } fclose(ply_file); return 0; }
// return TRUE if there is any overlap between the two scenes static int test_overlap(meta_parameters *meta1, meta_parameters *meta2) { if (!meta_is_valid_double(meta1->general->center_longitude)) { int nl = meta1->general->line_count; int ns = meta1->general->sample_count; meta_get_latLon(meta1, nl/2, ns/2, 0, &meta1->general->center_latitude, &meta1->general->center_longitude); } if (!meta_is_valid_double(meta2->general->center_longitude)) { int nl = meta2->general->line_count; int ns = meta2->general->sample_count; meta_get_latLon(meta2, nl/2, ns/2, 0, &meta2->general->center_latitude, &meta2->general->center_longitude); } int zone1 = utm_zone(meta1->general->center_longitude); int zone2 = utm_zone(meta2->general->center_longitude); // if zone1 & zone2 differ by more than 1, we can stop now if (iabs(zone1-zone2) > 1) { return FALSE; } // The Plan: // Generate polygons for each metadata, then test of any pair of // line segments between the polygons intersect. // Other possibility: meta1 is completely contained within meta2, // or the reverse. // corners of meta1. double xp_1[5], yp_1[5]; if (meta1->location) { // use the location block if available latLon2UTM_zone(meta1->location->lat_start_near_range, meta1->location->lon_start_near_range, 0, zone1, &xp_1[0], &yp_1[0]); latLon2UTM_zone(meta1->location->lat_start_far_range, meta1->location->lon_start_far_range, 0, zone1, &xp_1[1], &yp_1[1]); latLon2UTM_zone(meta1->location->lat_end_far_range, meta1->location->lon_end_far_range, 0, zone1, &xp_1[2], &yp_1[2]); latLon2UTM_zone(meta1->location->lat_end_near_range, meta1->location->lon_end_near_range, 0, zone1, &xp_1[3], &yp_1[3]); } else { double lat, lon; int nl1 = meta1->general->line_count; int ns1 = meta1->general->sample_count; // must call meta_get_latLon for each corner meta_get_latLon(meta1, 0, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[0], &yp_1[0]); meta_get_latLon(meta1, nl1-1, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[1], &yp_1[1]); meta_get_latLon(meta1, nl1-1, ns1-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[2], &yp_1[2]); meta_get_latLon(meta1, 0, ns1-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[3], &yp_1[3]); } // close the polygon xp_1[4] = xp_1[0]; yp_1[4] = yp_1[0]; // corners of meta2. double xp_2[5], yp_2[5]; if (meta2->location) { // use the location block if available latLon2UTM_zone(meta2->location->lat_start_near_range, meta2->location->lon_start_near_range, 0, zone1, &xp_2[0], &yp_2[0]); latLon2UTM_zone(meta2->location->lat_start_far_range, meta2->location->lon_start_far_range, 0, zone1, &xp_2[1], &yp_2[1]); latLon2UTM_zone(meta2->location->lat_end_far_range, meta2->location->lon_end_far_range, 0, zone1, &xp_2[2], &yp_2[2]); latLon2UTM_zone(meta2->location->lat_end_near_range, meta2->location->lon_end_near_range, 0, zone1, &xp_2[3], &yp_2[3]); } else { double lat, lon; int nl2 = meta2->general->line_count; int ns2 = meta2->general->sample_count; // must call meta_get_latLon for each corner meta_get_latLon(meta2, 0, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[0], &yp_2[0]); meta_get_latLon(meta2, nl2-1, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[1], &yp_2[1]); meta_get_latLon(meta2, nl2-1, ns2-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[2], &yp_2[2]); meta_get_latLon(meta2, 0, ns2-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[3], &yp_2[3]); } // close the polygon xp_2[4] = xp_2[0]; yp_2[4] = yp_2[0]; // loop over each pair of line segments, testing for intersection int i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { if (lineSegmentsIntersect( xp_1[i], yp_1[i], xp_1[i+1], yp_1[i+1], xp_2[j], yp_2[j], xp_2[j+1], yp_2[j+1])) { return TRUE; } } } // test for containment: meta2 in meta1 int all_in=TRUE; for (i=0; i<4; ++i) { if (!pnpoly(5, xp_1, yp_1, xp_2[i], yp_2[i])) { all_in=FALSE; break; } } if (all_in) return TRUE; // test for containment: meta1 in meta2 all_in = TRUE; for (i=0; i<4; ++i) { if (!pnpoly(5, xp_2, yp_2, xp_1[i], yp_1[i])) { all_in=FALSE; break; } } if (all_in) return TRUE; // no overlap return FALSE; }
// External entry point // --> meta: SAR metadata // --> dem_cla_arg: either (1) a DEM, (2) a directory with DEMs, // (3) a file containing directories of DEMs. // In case (1), nothing is done, return value is dem_cla_arg. // In case (2), the directory is scanned and a DEM is built from // the DEMs found in that directory. // In case (3), All of the directories are scanned, and a DEM is // built from the DEMs in all of the directories. char *build_dem(meta_parameters *meta, const char *dem_cla_arg, const char *dir_for_tmp_dem) { char *ext = findExt(dem_cla_arg); if (ext) { // check against known DEM extensions if (strcmp_case(ext, ".img") == 0 || strcmp_case(ext, ".tif") == 0 || strcmp_case(ext, ".tiff") == 0) { asfPrintStatus("%s: DEM.\n", dem_cla_arg); // presumably, this is a DEM -- case (1) above. return STRDUP(dem_cla_arg); } } else { // no extension -- user may have just provided the basename if (try_ext(dem_cla_arg, ".img")) { asfPrintStatus("%s: DEM.\n", dem_cla_arg); return STRDUP(dem_cla_arg); } else if (try_ext(dem_cla_arg, ".tiff")) { asfPrintStatus("%s: DEM.\n", dem_cla_arg); return STRDUP(dem_cla_arg); } else if (try_ext(dem_cla_arg, ".tif")) { asfPrintStatus("%s: DEM.\n", dem_cla_arg); return STRDUP(dem_cla_arg); } } char **list_of_dems = NULL; // Eliminated case (1) -- try case (2) if (is_dir_s(dem_cla_arg)) { asfPrintStatus("%s: directory containing DEMs.\n", dem_cla_arg); int n; list_of_dems = find_overlapping_dems_dir(meta, dem_cla_arg, &n); } else { // this is case (3) asfPrintStatus("%s: file containing directories of DEMs.\n", dem_cla_arg); if (fileExists(dem_cla_arg)) { int n; list_of_dems = find_overlapping_dems(meta, dem_cla_arg, &n); } } if (list_of_dems) { // form a bounding box double lat_lo, lat_hi, lon_lo, lon_hi; get_bounding_box_latlon(meta, &lat_lo, &lat_hi, &lon_lo, &lon_hi); // hard-coded name of the built dem char *built_dem; if (strlen(dir_for_tmp_dem) > 0) { built_dem = MALLOC(sizeof(char)*(strlen(dir_for_tmp_dem)+10)); sprintf(built_dem, "%s/built_dem", dir_for_tmp_dem); } else built_dem = STRDUP("built_dem"); // always geocode to utm -- we may wish change this to use the // user's preferred projection... asf_mosaic_utm(list_of_dems, built_dem, utm_zone(meta->general->center_longitude), lat_lo, lat_hi, lon_lo, lon_hi, meta->general->no_data); asfPrintStatus("Constructed DEM: %s\n", built_dem); return built_dem; } else { asfPrintError("DEM not found: %s\n", dem_cla_arg); return NULL; // not reached } }