std::string AlbersConEqArea::wkt() { OGRSpatialReference sr; int epsg = DATUM2EPSG[datum()]; char **wkt = 0; std::string output = ""; OGRErr err; sr.SetProjCS("Albers Conic Equal Area"); if (epsg != -1) { sr.importFromEPSG(epsg); sr.SetACEA(param(2), param(3), param(5), param(4), param(6), param(7)); err = sr.exportToPrettyWkt(wkt); } else { return output; } if (err == OGRERR_NONE) { output = *wkt; OGRFree(wkt); } return output; }
GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo ) { open_mode_type open_mode = MODE_VISIR; GDALOpenInfo* open_info = poOpenInfo; if (!poOpenInfo->bStatOK) { if ( EQUALN(poOpenInfo->pszFilename, "HRV:", 4) ) { open_info = new GDALOpenInfo(&poOpenInfo->pszFilename[4], poOpenInfo->eAccess); open_mode = MODE_HRV; } else if ( EQUALN(poOpenInfo->pszFilename, "RAD:", 4 ) ) { open_info = new GDALOpenInfo(&poOpenInfo->pszFilename[4], poOpenInfo->eAccess); open_mode = MODE_RAD; } } /* -------------------------------------------------------------------- */ /* Before trying MSGNOpen() we first verify that there is at */ /* least one "\n#keyword" type signature in the first chunk of */ /* the file. */ /* -------------------------------------------------------------------- */ if( open_info->fp == NULL || open_info->nHeaderBytes < 50 ) return NULL; /* check if this is a "NATIVE" MSG format image */ if( !EQUALN((char *)open_info->pabyHeader, "FormatName : NATIVE", 36) ) { return NULL; } /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { CPLError( CE_Failure, CPLE_NotSupported, "The MSGN driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ MSGNDataset *poDS; poDS = new MSGNDataset(); poDS->fp = open_info->fp; open_info->fp = NULL; /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ // first reset the file pointer, then hand over to the msg_reader_core VSIFSeek( poDS->fp, 0, SEEK_SET ); poDS->msg_reader_core = new Msg_reader_core(poDS->fp); if (!poDS->msg_reader_core->get_open_success()) { delete poDS; return NULL; } poDS->nRasterXSize = poDS->msg_reader_core->get_columns(); poDS->nRasterYSize = poDS->msg_reader_core->get_lines(); if (open_mode == MODE_HRV) { poDS->nRasterXSize *= 3; poDS->nRasterYSize *= 3; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ unsigned int i; unsigned int band_count = 1; unsigned int missing_band_count = 0; unsigned char* bands = poDS->msg_reader_core->get_band_map(); unsigned char band_map[MSG_NUM_CHANNELS+1]; // map GDAL band numbers to MSG channels for (i=0; i < MSG_NUM_CHANNELS; i++) { if (bands[i]) { bool ok_to_add = false; switch (open_mode) { case MODE_VISIR: ok_to_add = i < MSG_NUM_CHANNELS - 1; break; case MODE_RAD: ok_to_add = (i <= 2) || (Msg_reader_core::Blackbody_LUT[i+1].B != 0); break; case MODE_HRV: ok_to_add = i == MSG_NUM_CHANNELS - 1; break; } if (ok_to_add) { poDS->SetBand( band_count, new MSGNRasterBand( poDS, band_count, open_mode, i+1, i+1 - missing_band_count)); band_map[band_count] = i+1; band_count++; } } else { missing_band_count++; } } double pixel_gsd_x; double pixel_gsd_y; double origin_x; double origin_y; if (open_mode != MODE_HRV) { pixel_gsd_x = 1000 * poDS->msg_reader_core->get_col_dir_step(); // convert from km to m pixel_gsd_y = 1000 * poDS->msg_reader_core->get_line_dir_step(); // convert from km to m origin_x = -pixel_gsd_x * (-(Conversions::nlines / 2.0) + poDS->msg_reader_core->get_col_start()); origin_y = -pixel_gsd_y * ((Conversions::nlines / 2.0) - poDS->msg_reader_core->get_line_start()); } else { pixel_gsd_x = 1000 * poDS->msg_reader_core->get_col_dir_step() / 3.0; // convert from km to m, approximate for HRV pixel_gsd_y = 1000 * poDS->msg_reader_core->get_line_dir_step() / 3.0; // convert from km to m, approximate for HRV origin_x = -pixel_gsd_x * (-(3*Conversions::nlines / 2.0) + 3*poDS->msg_reader_core->get_col_start()); origin_y = -pixel_gsd_y * ((3*Conversions::nlines / 2.0) - 3*poDS->msg_reader_core->get_line_start()); } poDS->adfGeoTransform[0] = origin_x; poDS->adfGeoTransform[1] = pixel_gsd_x; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = origin_y; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -pixel_gsd_y; OGRSpatialReference oSRS; oSRS.SetProjCS("Geostationary projection (MSG)"); oSRS.SetGEOS( 0, 35785831, 0, 0 ); oSRS.SetGeogCS( "MSG Ellipsoid", "MSG_DATUM", "MSG_SPHEROID", Conversions::rpol * 1000.0, 1 / ( 1 - Conversions::rpol/Conversions::req) ); oSRS.exportToWkt( &(poDS->pszProjection) ); CALIBRATION* cal = poDS->msg_reader_core->get_calibration_parameters(); char tagname[30]; char field[300]; poDS->SetMetadataItem("Radiometric parameters format", "offset slope"); for (i=1; i < band_count; i++) { sprintf(tagname, "ch%02d_cal", band_map[i]); sprintf(field, "%.12e %.12e", cal[band_map[i]-1].cal_offset, cal[band_map[i]-1].cal_slope); poDS->SetMetadataItem(tagname, field); } sprintf(field, "%04d%02d%02d/%02d:%02d", poDS->msg_reader_core->get_year(), poDS->msg_reader_core->get_month(), poDS->msg_reader_core->get_day(), poDS->msg_reader_core->get_hour(), poDS->msg_reader_core->get_minute() ); poDS->SetMetadataItem("Date/Time", field); sprintf(field, "%d %d", poDS->msg_reader_core->get_line_start(), poDS->msg_reader_core->get_col_start() ); poDS->SetMetadataItem("Origin", field); if (open_info != poOpenInfo) { delete open_info; } return( poDS ); }
void PDSDataset::ParseSRS() { const char *pszFilename = GetDescription(); /* ==================================================================== */ /* Get the geotransform. */ /* ==================================================================== */ /*********** Grab Cellsize ************/ //example: //MAP_SCALE = 14.818 <KM/PIXEL> //added search for unit (only checks for CM, KM - defaults to Meters) const char *value; //Georef parameters double dfULXMap=0.5; double dfULYMap = 0.5; double dfXDim = 1.0; double dfYDim = 1.0; double xulcenter = 0.0; double yulcenter = 0.0; value = GetKeyword("IMAGE_MAP_PROJECTION.MAP_SCALE"); if (strlen(value) > 0 ) { dfXDim = atof(value); dfYDim = atof(value) * -1; CPLString unit = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",2); //KM //value = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",3); //PIXEL if((EQUAL(unit,"M")) || (EQUAL(unit,"METER")) || (EQUAL(unit,"METERS"))) { // do nothing } else if (EQUAL(unit,"CM")) { // convert from cm to m dfXDim = dfXDim / 100.0; dfYDim = dfYDim / 100.0; } else { //defaults to convert km to m dfXDim = dfXDim * 1000.0; dfYDim = dfYDim * 1000.0; } } /* -------------------------------------------------------------------- */ /* Calculate upper left corner of pixel in meters from the */ /* upper left center pixel sample/line offsets. It doesn't */ /* mean the defaults will work for every PDS image, as these */ /* values are used inconsistantly. Thus we have included */ /* conversion options to allow the user to override the */ /* documented PDS3 default. Jan. 2011, for known mapping issues */ /* see GDAL PDS page or mapping within ISIS3 source (USGS) */ /* $ISIS3DATA/base/translations/pdsProjectionLineSampToXY.def */ /* -------------------------------------------------------------------- */ // defaults should be correct for what is documented in the PDS3 standard double dfSampleOffset_Shift; double dfLineOffset_Shift; double dfSampleOffset_Mult; double dfLineOffset_Mult; dfSampleOffset_Shift = atof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "-0.5" )); dfLineOffset_Shift = atof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "-0.5" )); dfSampleOffset_Mult = atof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") ); dfLineOffset_Mult = atof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") ); /*********** Grab LINE_PROJECTION_OFFSET ************/ value = GetKeyword("IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET"); if (strlen(value) > 0) { yulcenter = atof(value); dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult); //notice dfYDim is negative here which is why it is again negated here } /*********** Grab SAMPLE_PROJECTION_OFFSET ************/ value = GetKeyword("IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET"); if( strlen(value) > 0 ) { xulcenter = atof(value); dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult); } /* ==================================================================== */ /* Get the coordinate system. */ /* ==================================================================== */ int bProjectionSet = TRUE; double semi_major = 0.0; double semi_minor = 0.0; double iflattening = 0.0; double center_lat = 0.0; double center_lon = 0.0; double first_std_parallel = 0.0; double second_std_parallel = 0.0; OGRSpatialReference oSRS; /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. MARS ***/ CPLString target_name = GetKeyword("TARGET_NAME"); CleanString( target_name ); /********** Grab MAP_PROJECTION_TYPE *****/ CPLString map_proj_name = GetKeyword( "IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE"); CleanString( map_proj_name ); /****** Grab semi_major & convert to KM ******/ semi_major = atof(GetKeyword( "IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0; /****** Grab semi-minor & convert to KM ******/ semi_minor = atof(GetKeyword( "IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0; /*********** Grab CENTER_LAT ************/ center_lat = atof(GetKeyword( "IMAGE_MAP_PROJECTION.CENTER_LATITUDE")); /*********** Grab CENTER_LON ************/ center_lon = atof(GetKeyword( "IMAGE_MAP_PROJECTION.CENTER_LONGITUDE")); /********** Grab 1st std parallel *******/ first_std_parallel = atof(GetKeyword( "IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL")); /********** Grab 2nd std parallel *******/ second_std_parallel = atof(GetKeyword( "IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL")); /*** grab PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/ // Need to further study how ocentric/ographic will effect the gdal library. // So far we will use this fact to define a sphere or ellipse for some projections // Frank - may need to talk this over char bIsGeographic = TRUE; value = GetKeyword("IMAGE_MAP_PROJECTION.COORDINATE_SYSTEM_NAME"); if (EQUAL( value, "PLANETOCENTRIC" )) bIsGeographic = FALSE; /** Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS "AITOFF", ** Not supported in GDAL?? "ALBERS", "BONNE", "BRIESEMEISTER", ** Not supported in GDAL?? "CYLINDRICAL EQUAL AREA", "EQUIDISTANT", "EQUIRECTANGULAR", "GNOMONIC", "HAMMER", ** Not supported in GDAL?? "HENDU", ** Not supported in GDAL?? "LAMBERT AZIMUTHAL EQUAL AREA", "LAMBERT CONFORMAL", "MERCATOR", "MOLLWEIDE", "OBLIQUE CYLINDRICAL", "ORTHOGRAPHIC", "SIMPLE CYLINDRICAL", "SINUSOIDAL", "STEREOGRAPHIC", "TRANSVERSE MERCATOR", "VAN DER GRINTEN", ** Not supported in GDAL?? "WERNER" ** Not supported in GDAL?? **/ CPLDebug( "PDS","using projection %s\n\n", map_proj_name.c_str()); if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) || (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) ) { oSRS.SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { oSRS.SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "SINUSOIDAL" )) { oSRS.SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MERCATOR" )) { oSRS.SetMercator ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "STEREOGRAPHIC" )) { oSRS.SetStereographic ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC")) { oSRS.SetPS ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) { oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) { oSRS.SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) { oSRS.SetLAEA( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "CYLINDRICAL_EQUAL_AREA" )) { oSRS.SetCEA ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) { oSRS.SetMollweide ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "ALBERS" )) { oSRS.SetACEA ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "BONNE" )) { oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "GNOMONIC" )) { oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { // hope Swiss Oblique Cylindrical is the same oSRS.SetSOC ( center_lat, center_lon, 0, 0 ); } else { CPLDebug( "PDS", "Dataset projection %s is not supported. Continuing...", map_proj_name.c_str() ); bProjectionSet = FALSE; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword CPLString proj_target_name = map_proj_name + " " + target_name; oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System CPLString geog_name = "GCS_" + target_name; //The datum and sphere names will be the same basic name aas the planet CPLString datum_name = "D_" + target_name; CPLString sphere_name = target_name; // + "_IAU_IAG"); //Might not be IAU defined so don't add //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ compatibility //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" ))) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... sphere_name += "_polarRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) || (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || (EQUAL( map_proj_name, "SINUSOIDAL" )) ) { //isis uses the spherical equation for these projections so force a sphere oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major sphere_name += "_localRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); osProjection = pszResult; CPLFree( pszResult ); } /* ==================================================================== */ /* Check for a .prj and world file to override the georeferencing. */ /* ==================================================================== */ { CPLString osPath, osName; VSILFILE *fp; osPath = CPLGetPath( pszFilename ); osName = CPLGetBasename(pszFilename); const char *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" ); fp = VSIFOpenL( pszPrjFile, "r" ); if( fp != NULL ) { char **papszLines; OGRSpatialReference oSRS; VSIFCloseL( fp ); papszLines = CSLLoad( pszPrjFile ); if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE ) { char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); osProjection = pszResult; CPLFree( pszResult ); } CSLDestroy( papszLines ); } } if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 ) { bGotTransform = TRUE; adfGeoTransform[0] = dfULXMap; adfGeoTransform[1] = dfXDim; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = dfULYMap; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = dfYDim; } if( !bGotTransform ) bGotTransform = GDALReadWorldFile( pszFilename, "psw", adfGeoTransform ); if( !bGotTransform ) bGotTransform = GDALReadWorldFile( pszFilename, "wld", adfGeoTransform ); }
GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this look like a CUBE or an IMAGE Primary Data Object? */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Open the file using the large file API. */ /* -------------------------------------------------------------------- */ VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpQube == NULL ) return NULL; ISIS2Dataset *poDS; poDS = new ISIS2Dataset(); if( ! poDS->oKeywords.Ingest( fpQube, 0 ) ) { VSIFCloseL( fpQube ); delete poDS; return NULL; } VSIFCloseL( fpQube ); /* -------------------------------------------------------------------- */ /* We assume the user is pointing to the label (ie. .lab) file. */ /* -------------------------------------------------------------------- */ // QUBE can be inline or detached and point to an image name // ^QUBE = 76 // ^QUBE = ("ui31s015.img",6441<BYTES>) - has another label on the image // ^QUBE = "ui31s015.img" - which implies no label or skip value const char *pszQube = poDS->GetKeyword( "^QUBE" ); GUIntBig nQube = 0; int bByteLocation = FALSE; CPLString osTargetFile = poOpenInfo->pszFilename; if( pszQube[0] == '"' ) { CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); CPLString osFilename = pszQube; poDS->CleanString( osFilename ); osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); poDS->osExternalCube = osTargetFile; } else if( pszQube[0] == '(' ) { CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,""); poDS->CleanString( osFilename ); osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); poDS->osExternalCube = osTargetFile; nQube = atoi(poDS->GetKeywordSub("^QUBE",2,"1")); if( strstr(poDS->GetKeywordSub("^QUBE",2,"1"),"<BYTES>") != NULL ) bByteLocation = true; } else { nQube = atoi(pszQube); if( strstr(pszQube,"<BYTES>") != NULL ) bByteLocation = true; } /* -------------------------------------------------------------------- */ /* Check if file an ISIS2 header file? Read a few lines of text */ /* searching for something starting with nrows or ncols. */ /* -------------------------------------------------------------------- */ GDALDataType eDataType = GDT_Byte; OGRSpatialReference oSRS; //image parameters int nRows, nCols, nBands = 1; GUIntBig nSkipBytes = 0; int itype; int s_ix, s_iy, s_iz; // check SUFFIX_ITEMS params. int record_bytes; int bNoDataSet = FALSE; char chByteOrder = 'M'; //default to MSB //Georef parameters double dfULXMap=0.5; double dfULYMap = 0.5; double dfXDim = 1.0; double dfYDim = 1.0; double dfNoData = 0.0; double xulcenter = 0.0; double yulcenter = 0.0; //projection parameters int bProjectionSet = TRUE; double semi_major = 0.0; double semi_minor = 0.0; double iflattening = 0.0; double center_lat = 0.0; double center_lon = 0.0; double first_std_parallel = 0.0; double second_std_parallel = 0.0; VSILFILE *fp; /* -------------------------------------------------------------------- */ /* Checks to see if this is valid ISIS2 cube */ /* SUFFIX_ITEM tag in .cub file should be (0,0,0); no side-planes */ /* -------------------------------------------------------------------- */ s_ix = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 1 )); s_iy = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 2 )); s_iz = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 3 )); if( s_ix != 0 || s_iy != 0 || s_iz != 0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "*** ISIS 2 cube file has invalid SUFFIX_ITEMS parameters:\n" "*** gdal isis2 driver requires (0, 0, 0), thus no sideplanes or backplanes\n" "found: (%i, %i, %i)\n\n", s_ix, s_iy, s_iz ); delete poDS; return NULL; } /**************** end SUFFIX_ITEM check ***********************/ /*********** Grab layout type (BSQ, BIP, BIL) ************/ // AXIS_NAME = (SAMPLE,LINE,BAND) /***********************************************************/ const char *value; char szLayout[10] = "BSQ"; //default to band seq. value = poDS->GetKeyword( "QUBE.AXIS_NAME", "" ); if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) strcpy(szLayout,"BSQ"); else if (EQUAL(value,"(BAND,LINE,SAMPLE)") ) strcpy(szLayout,"BIP"); else if (EQUAL(value,"(SAMPLE,BAND,LINE)") || EQUAL(value,"") ) strcpy(szLayout,"BSQ"); else { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return NULL; } /*********** Grab samples lines band ************/ nCols = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",1)); nRows = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",2)); nBands = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",3)); /*********** Grab Qube record bytes **********/ record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES")); if (nQube > 0 && bByteLocation ) nSkipBytes = (nQube - 1); else if( nQube > 0 ) nSkipBytes = (nQube - 1) * record_bytes; else nSkipBytes = 0; /*********** Grab samples lines band ************/ CPLString osCoreItemType = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" ); if( (EQUAL(osCoreItemType,"PC_INTEGER")) || (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) || (EQUAL(osCoreItemType,"PC_REAL")) ) { chByteOrder = 'I'; } /******** Grab format type - isis2 only supports 8,16,32 *******/ itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES","")); switch(itype) { case 1 : eDataType = GDT_Byte; dfNoData = NULL1; bNoDataSet = TRUE; break; case 2 : if( strstr(osCoreItemType,"UNSIGNED") != NULL ) { dfNoData = 0; eDataType = GDT_UInt16; } else { dfNoData = NULL2; eDataType = GDT_Int16; } bNoDataSet = TRUE; break; case 4 : eDataType = GDT_Float32; dfNoData = NULL3; bNoDataSet = TRUE; break; case 8 : eDataType = GDT_Float64; dfNoData = NULL3; bNoDataSet = TRUE; break; default : CPLError( CE_Failure, CPLE_AppDefined, "Itype of %d is not supported in ISIS 2.", itype); delete poDS; return NULL; } /*********** Grab Cellsize ************/ value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.MAP_SCALE"); if (strlen(value) > 0 ) { dfXDim = (float) atof(value) * 1000.0; /* convert from km to m */ dfYDim = (float) atof(value) * 1000.0 * -1; } /*********** Grab LINE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET"); if (strlen(value) > 0) { yulcenter = (float) atof(value); yulcenter = ((yulcenter) * dfYDim); dfULYMap = yulcenter - (dfYDim/2); } /*********** Grab SAMPLE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET"); if( strlen(value) > 0 ) { xulcenter = (float) atof(value); xulcenter = ((xulcenter) * dfXDim); dfULXMap = xulcenter - (dfXDim/2); } /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. MARS ***/ CPLString target_name = poDS->GetKeyword("QUBE.TARGET_NAME"); /*********** Grab MAP_PROJECTION_TYPE ************/ CPLString map_proj_name = poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE"); poDS->CleanString( map_proj_name ); /*********** Grab SEMI-MAJOR ************/ semi_major = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0; /*********** Grab semi-minor ************/ semi_minor = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0; /*********** Grab CENTER_LAT ************/ center_lat = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LATITUDE")); /*********** Grab CENTER_LON ************/ center_lon = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LONGITUDE")); /*********** Grab 1st std parallel ************/ first_std_parallel = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL")); /*********** Grab 2nd std parallel ************/ second_std_parallel = atof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL")); /*** grab PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/ // Need to further study how ocentric/ographic will effect the gdal library. // So far we will use this fact to define a sphere or ellipse for some projections // Frank - may need to talk this over char bIsGeographic = TRUE; value = poDS->GetKeyword("CUBE.IMAGE_MAP_PROJECTION.PROJECTION_LATITUDE_TYPE"); if (EQUAL( value, "\"PLANETOCENTRIC\"" )) bIsGeographic = FALSE; CPLDebug("ISIS2","using projection %s", map_proj_name.c_str() ); //Set oSRS projection and parameters if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) || (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ) { oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if ((EQUAL( map_proj_name, "SINUSOIDAL" )) || (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" ))) { oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MERCATOR" )) { oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )) { oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) { oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) { oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "") ) { /* no projection */ bProjectionSet = FALSE; } else { CPLDebug( "ISIS2", "Dataset projection %s is not supported. Continuing...", map_proj_name.c_str() ); bProjectionSet = FALSE; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword CPLString proj_target_name = map_proj_name + " " + target_name; oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System CPLString geog_name = "GCS_" + target_name; //The datum and sphere names will be the same basic name aas the planet CPLString datum_name = "D_" + target_name; CPLString sphere_name = target_name; // + "_IAU_IAG"); //Might not be IAU defined so don't add //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" ))) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... sphere_name += "_polarRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" )) || (EQUAL( map_proj_name, "SINUSOIDAL" )) ) { //isis uses the sphereical equation for these projections so force a sphere oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ) { //Calculate localRadius using ISIS3 simple elliptical method // not the more standard Radius of Curvature method //PI = 4 * atan(1); double radLat, localRadius; if (center_lon == 0) { //No need to calculate local radius oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else { radLat = center_lat * PI / 180; // in radians localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2) + pow(semi_major*sin(radLat),2) ); sphere_name += "_localRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, localRadius, 0.0, "Reference_Meridian", 0.0 ); CPLDebug( "ISIS2", "local radius: %f", localRadius); } } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } /* END ISIS2 Label Read */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* -------------------------------------------------------------------- */ /* Did we get the required keywords? If not we return with */ /* this never having been considered to be a match. This isn't */ /* an error! */ /* -------------------------------------------------------------------- */ if( nRows < 1 || nCols < 1 || nBands < 1 ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nCols; poDS->nRasterYSize = nRows; /* -------------------------------------------------------------------- */ /* Open target binary file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( osTargetFile, "rb" ); else poDS->fpImage = VSIFOpenL( osTargetFile, "r+b" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s with write permission.\n%s", osTargetFile.c_str(), VSIStrerror( errno ) ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Compute the line offset. */ /* -------------------------------------------------------------------- */ int nItemSize = GDALGetDataTypeSize(eDataType)/8; int nLineOffset, nPixelOffset, nBandOffset; if( EQUAL(szLayout,"BIP") ) { nPixelOffset = nItemSize * nBands; nLineOffset = nPixelOffset * nCols; nBandOffset = nItemSize; } else if( EQUAL(szLayout,"BSQ") ) { nPixelOffset = nItemSize; nLineOffset = nPixelOffset * nCols; nBandOffset = nLineOffset * nRows; } else /* assume BIL */ { nPixelOffset = nItemSize; nLineOffset = nItemSize * nBands * nCols; nBandOffset = nItemSize * nCols; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ int i; poDS->nBands = nBands;; for( i = 0; i < poDS->nBands; i++ ) { RawRasterBand *poBand; poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, nPixelOffset, nLineOffset, eDataType, #ifdef CPL_LSB chByteOrder == 'I' || chByteOrder == 'L', #else chByteOrder == 'M', #endif TRUE ); if( bNoDataSet ) poBand->SetNoDataValue( dfNoData ); poDS->SetBand( i+1, poBand ); // Set offset/scale values at the PAM level. poBand->SetOffset( CPLAtofM(poDS->GetKeyword("QUBE.CORE_BASE","0.0"))); poBand->SetScale( CPLAtofM(poDS->GetKeyword("QUBE.CORE_MULTIPLIER","1.0"))); } /* -------------------------------------------------------------------- */ /* Check for a .prj file. For isis2 I would like to keep this in */ /* -------------------------------------------------------------------- */ CPLString osPath, osName; osPath = CPLGetPath( poOpenInfo->pszFilename ); osName = CPLGetBasename(poOpenInfo->pszFilename); const char *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" ); fp = VSIFOpenL( pszPrjFile, "r" ); if( fp != NULL ) { char **papszLines; OGRSpatialReference oSRS; VSIFCloseL( fp ); papszLines = CSLLoad( pszPrjFile ); if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE ) { char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } CSLDestroy( papszLines ); } if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 ) { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = dfULXMap; poDS->adfGeoTransform[1] = dfXDim; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfULYMap; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = dfYDim; } if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", poDS->adfGeoTransform ); if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this look like a VICAR dataset? */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Open the file using the large file API. */ /* -------------------------------------------------------------------- */ VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpQube == NULL ) return NULL; VICARDataset *poDS = new VICARDataset(); if( ! poDS->oKeywords.Ingest( fpQube, poOpenInfo->pabyHeader ) ) { VSIFCloseL( fpQube ); delete poDS; return NULL; } VSIFCloseL( fpQube ); /***** CHECK ENDIANNESS **************/ const char *value = poDS->GetKeyword( "INTFMT" ); if (!EQUAL(value,"LOW") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } value = poDS->GetKeyword( "REALFMT" ); if (!EQUAL(value,"RIEEE") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } char chByteOrder = 'M'; value = poDS->GetKeyword( "BREALFMT" ); if (EQUAL(value,"VAX") ) { chByteOrder = 'I'; } /************ CHECK INSTRUMENT *****************/ /************ ONLY HRSC TESTED *****************/ bool bIsDTM = false; value = poDS->GetKeyword( "DTM.DTM_OFFSET" ); if (!EQUAL(value,"") ) { bIsDTM = true; } value = poDS->GetKeyword( "BLTYPE" ); if (!EQUAL(value,"M94_HRSC") && !bIsDTM ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s instrument not tested. Continue with caution!\n\n", value); } /*********** Grab layout type (BSQ, BIP, BIL) ************/ char szLayout[10] = "BSQ"; //default to band seq. value = poDS->GetKeyword( "ORG" ); if (!EQUAL(value,"BSQ") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } strcpy(szLayout,"BSQ"); const int nCols = atoi(poDS->GetKeyword("NS")); const int nRows = atoi(poDS->GetKeyword("NL")); const int nBands = atoi(poDS->GetKeyword("NB")); /*********** Grab record bytes **********/ int nSkipBytes = atoi(poDS->GetKeyword("NBB")); GDALDataType eDataType = GDT_Byte; double dfNoData = 0.0; if (EQUAL( poDS->GetKeyword( "FORMAT" ), "BYTE" )) { eDataType = GDT_Byte; dfNoData = NULL1; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "HALF" )) { eDataType = GDT_Int16; dfNoData = NULL2; chByteOrder = 'I'; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "FULL" )) { eDataType = GDT_UInt32; dfNoData = 0; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "REAL" )) { eDataType = GDT_Float32; dfNoData = NULL3; chByteOrder = 'I'; } else { CPLError( CE_Failure, CPLE_AppDefined, "Could not find known VICAR label entries!\n"); delete poDS; return NULL; } if( nRows < 1 || nCols < 1 || nBands < 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "File %s appears to be a VICAR file, but failed to find some " "required keywords.", poDS->GetDescription() ); return FALSE; } /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nCols; poDS->nRasterYSize = nRows; double dfULXMap=0.5; double dfULYMap = 0.5; double dfXDim = 1.0; double dfYDim = 1.0; double xulcenter = 0.0; double yulcenter = 0.0; value = poDS->GetKeyword("MAP.MAP_SCALE"); if (strlen(value) > 0 ) { dfXDim = CPLAtof(value); dfYDim = CPLAtof(value) * -1; dfXDim = dfXDim * 1000.0; dfYDim = dfYDim * 1000.0; } double dfSampleOffset_Shift = CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "-0.5" )); double dfLineOffset_Shift = CPLAtof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "-0.5" )); double dfSampleOffset_Mult = CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") ); double dfLineOffset_Mult = CPLAtof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") ); /*********** Grab LINE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("MAP.LINE_PROJECTION_OFFSET"); if (strlen(value) > 0) { yulcenter = CPLAtof(value); dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult); } /*********** Grab SAMPLE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("MAP.SAMPLE_PROJECTION_OFFSET"); if( strlen(value) > 0 ) { xulcenter = CPLAtof(value); dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult); } /* ==================================================================== */ /* Get the coordinate system. */ /* ==================================================================== */ bool bProjectionSet = true; /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. MARS ***/ const CPLString target_name = poDS->GetKeyword("MAP.TARGET_NAME"); /********** Grab MAP_PROJECTION_TYPE *****/ const CPLString map_proj_name = poDS->GetKeyword( "MAP.MAP_PROJECTION_TYPE"); /****** Grab semi_major & convert to KM ******/ const double semi_major = CPLAtof(poDS->GetKeyword( "MAP.A_AXIS_RADIUS")) * 1000.0; /****** Grab semi-minor & convert to KM ******/ const double semi_minor = CPLAtof(poDS->GetKeyword( "MAP.C_AXIS_RADIUS")) * 1000.0; /*********** Grab CENTER_LAT ************/ const double center_lat = CPLAtof(poDS->GetKeyword( "MAP.CENTER_LATITUDE")); /*********** Grab CENTER_LON ************/ const double center_lon = CPLAtof(poDS->GetKeyword( "MAP.CENTER_LONGITUDE")); /********** Grab 1st std parallel *******/ const double first_std_parallel = CPLAtof(poDS->GetKeyword( "MAP.FIRST_STANDARD_PARALLEL")); /********** Grab 2nd std parallel *******/ const double second_std_parallel = CPLAtof(poDS->GetKeyword( "MAP.SECOND_STANDARD_PARALLEL")); /*** grab PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/ // Need to further study how ocentric/ographic will effect the gdal library. // So far we will use this fact to define a sphere or ellipse for some projections // Frank - may need to talk this over bool bIsGeographic = true; value = poDS->GetKeyword("MAP.COORDINATE_SYSTEM_NAME"); if (EQUAL( value, "PLANETOCENTRIC" )) bIsGeographic = false; /** Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS "AITOFF", ** Not supported in GDAL?? "ALBERS", "BONNE", "BRIESEMEISTER", ** Not supported in GDAL?? "CYLINDRICAL EQUAL AREA", "EQUIDISTANT", "EQUIRECTANGULAR", "GNOMONIC", "HAMMER", ** Not supported in GDAL?? "HENDU", ** Not supported in GDAL?? "LAMBERT AZIMUTHAL EQUAL AREA", "LAMBERT CONFORMAL", "MERCATOR", "MOLLWEIDE", "OBLIQUE CYLINDRICAL", "ORTHOGRAPHIC", "SIMPLE CYLINDRICAL", "SINUSOIDAL", "STEREOGRAPHIC", "TRANSVERSE MERCATOR", "VAN DER GRINTEN", ** Not supported in GDAL?? "WERNER" ** Not supported in GDAL?? **/ CPLDebug( "PDS", "using projection %s\n\n", map_proj_name.c_str()); OGRSpatialReference oSRS; if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) || (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) ) { oSRS.SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { oSRS.SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "SINUSOIDAL" )) { oSRS.SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MERCATOR" )) { oSRS.SetMercator ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "STEREOGRAPHIC" )) { oSRS.SetStereographic ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC")) { oSRS.SetPS ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) { oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) { oSRS.SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) { oSRS.SetLAEA( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "CYLINDRICAL_EQUAL_AREA" )) { oSRS.SetCEA ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) { oSRS.SetMollweide ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "ALBERS" )) { oSRS.SetACEA ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "BONNE" )) { oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "GNOMONIC" )) { oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { // hope Swiss Oblique Cylindrical is the same oSRS.SetSOC ( center_lat, center_lon, 0, 0 ); } else { CPLDebug( "VICAR", "Dataset projection %s is not supported. Continuing...", map_proj_name.c_str() ); bProjectionSet = false; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword CPLString proj_target_name = map_proj_name + " " + target_name; oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System CPLString geog_name = "GCS_" + target_name; //The datum and sphere names will be the same basic name aas the planet CPLString datum_name = "D_" + target_name; CPLString sphere_name = target_name; // + "_IAU_IAG"); //Might not be IAU defined so don't add //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) double iflattening = 0.0; if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ compatibility //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" ))) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... sphere_name += "_polarRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) || (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || (EQUAL( map_proj_name, "SINUSOIDAL" )) ) { //isis uses the spherical equation for these projections so force a sphere oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major sphere_name += "_localRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = dfULXMap; poDS->adfGeoTransform[1] = dfXDim; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfULYMap; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = dfYDim; } CPLString osQubeFile = poOpenInfo->pszFilename; if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( osQubeFile, "psw", poDS->adfGeoTransform ); if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( osQubeFile, "wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Open target binary file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( osQubeFile, "r" ); else poDS->fpImage = VSIFOpenL( osQubeFile, "r+" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s with write permission.\n%s", osQubeFile.c_str(), VSIStrerror( errno ) ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Compute the line offsets. */ /* -------------------------------------------------------------------- */ const long int nItemSize = GDALGetDataTypeSize(eDataType)/8; const long int nPixelOffset = nItemSize; const long int nLineOffset = nPixelOffset * nCols + atoi(poDS->GetKeyword("NBB")) ; const long int nBandOffset = nLineOffset * nRows; nSkipBytes = atoi(poDS->GetKeyword("LBLSIZE")); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int i = 0; i < nBands; i++ ) { GDALRasterBand *poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, nPixelOffset, nLineOffset, eDataType, #ifdef CPL_LSB chByteOrder == 'I' || chByteOrder == 'L', #else chByteOrder == 'M', #endif TRUE ); poDS->SetBand( i+1, poBand ); poBand->SetNoDataValue( dfNoData ); if (bIsDTM) { poBand->SetScale( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_SCALING_FACTOR") ) ); poBand->SetOffset( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_OFFSET") ) ); const char* pszMin = poDS->GetKeyword( "DTM.DTM_MINIMUM_DN", NULL ); const char* pszMax = poDS->GetKeyword( "DTM.DTM_MAXIMUM_DN", NULL ); if (pszMin != NULL && pszMax != NULL ) poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),0,0); const char* pszNoData = poDS->GetKeyword( "DTM.DTM_MISSING_DN", NULL ); if (pszNoData != NULL ) poBand->SetNoDataValue( CPLAtofM(pszNoData) ); } else if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" )) { float scale=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_SCALING_FACTOR","-1.")); if (scale < 0.) { scale = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_SCALING_FACTOR","1.")); } poBand->SetScale( scale ); float offset=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_OFFSET","-1.")); if (offset < 0.) { offset = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_OFFSET","0.")); } poBand->SetOffset( offset ); } const char* pszMin = poDS->GetKeyword( "STATISTICS.MINIMUM", NULL ); const char* pszMax = poDS->GetKeyword( "STATISTICS.MAXIMUM", NULL ); const char* pszMean = poDS->GetKeyword( "STATISTICS.MEAN", NULL ); const char* pszStdDev = poDS->GetKeyword( "STATISTICS.STANDARD_DEVIATION", NULL ); if (pszMin != NULL && pszMax != NULL && pszMean != NULL && pszStdDev != NULL ) poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),CPLAtofM(pszMean),CPLAtofM(pszStdDev)); } /* -------------------------------------------------------------------- */ /* Instrument-specific keywords as metadata. */ /* -------------------------------------------------------------------- */ /****************** HRSC ******************************/ if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" ) ) { poDS->SetMetadataItem( "SPACECRAFT_NAME", poDS->GetKeyword( "M94_INSTRUMENT.INSTRUMENT_HOST_NAME") ); poDS->SetMetadataItem( "PRODUCT_TYPE", poDS->GetKeyword( "TYPE")); if (EQUAL( poDS->GetKeyword( "M94_INSTRUMENT.DETECTOR_ID"), "MEX_HRSC_SRC" )) { static const char *apszKeywords[] = { "M94_ORBIT.IMAGE_TIME", "FILE.EVENT_TYPE", "FILE.PROCESSING_LEVEL_ID", "M94_INSTRUMENT.DETECTOR_ID", "M94_CAMERAS.EXPOSURE_DURATION", "HRCONVER.INSTRUMENT_TEMPERATURE", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } else { static const char *apszKeywords[] = { "M94_ORBIT.START_TIME", "M94_ORBIT.STOP_TIME", "M94_INSTRUMENT.DETECTOR_ID", "M94_CAMERAS.MACROPIXEL_SIZE", "FILE.EVENT_TYPE", "M94_INSTRUMENT.MISSION_PHASE_NAME", "HRORTHO.SPICE_FILE_NAME", "HRCONVER.MISSING_FRAMES", "HRCONVER.OVERFLOW_FRAMES", "HRCONVER.ERROR_FRAMES", "HRFOOT.BEST_GROUND_SAMPLING_DISTANCE", "DLRTO8.RADIANCE_SCALING_FACTOR", "DLRTO8.RADIANCE_OFFSET", "DLRTO8.REFLECTANCE_SCALING_FACTOR", "DLRTO8.REFLECTANCE_OFFSET", "HRCAL.RADIANCE_SCALING_FACTOR", "HRCAL.RADIANCE_OFFSET", "HRCAL.REFLECTANCE_SCALING_FACTOR", "HRCAL.REFLECTANCE_OFFSET", "HRORTHO.DTM_NAME", "HRORTHO.EXTORI_FILE_NAME", "HRORTHO.GEOMETRIC_CALIB_FILE_NAME", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i], NULL ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } } if (bIsDTM && EQUAL( poDS->GetKeyword( "MAP.TARGET_NAME"), "MARS" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "MARS_EXPRESS" ); poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM"); static const char *apszKeywords[] = { "DTM.DTM_MISSING_DN", "DTM.DTM_OFFSET", "DTM.DTM_SCALING_FACTOR", "DTM.DTM_A_AXIS_RADIUS", "DTM.DTM_B_AXIS_RADIUS", "DTM.DTM_C_AXIS_RADIUS", "DTM.DTM_DESC", "DTM.DTM_MINIMUM_DN", "DTM.DTM_MAXIMUM_DN", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } /****************** DAWN ******************************/ else if (EQUAL( poDS->GetKeyword( "INSTRUMENT_ID"), "FC2" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" ); static const char *apszKeywords[] = {"ORBIT_NUMBER","FILTER_NUMBER", "FRONT_DOOR_STATUS", "FIRST_LINE", "FIRST_LINE_SAMPLE", "PRODUCER_INSTITUTION_NAME", "SOURCE_FILE_NAME", "PROCESSING_LEVEL_ID", "TARGET_NAME", "LIMB_IN_IMAGE", "POLE_IN_IMAGE", "REFLECTANCE_SCALING_FACTOR", "SPICE_FILE_NAME", "SPACECRAFT_CENTRIC_LATITUDE", "SPACECRAFT_EASTERN_LONGITUDE", "FOOTPRINT_POSITIVE_LONGITUDE", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } else if (bIsDTM && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" ); poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM"); static const char *apszKeywords[] = { "DTM_MISSING_DN", "DTM_OFFSET", "DTM_SCALING_FACTOR", "DTM_A_AXIS_RADIUS", "DTM_B_AXIS_RADIUS", "DTM_C_AXIS_RADIUS", "DTM_MINIMUM_DN", "DTM_MAXIMUM_DN", "MAP_PROJECTION_TYPE", "COORDINATE_SYSTEM_NAME", "POSITIVE_LONGITUDE_DIRECTION", "MAP_SCALE", "CENTER_LONGITUDE", "LINE_PROJECTION_OFFSET", "SAMPLE_PROJECTION_OFFSET", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } /* -------------------------------------------------------------------- */ /* END Instrument-specific keywords as metadata. */ /* -------------------------------------------------------------------- */ if (EQUAL(poDS->GetKeyword( "EOL"), "1" )) poDS->SetMetadataItem( "END-OF-DATASET_LABEL", "PRESENT" ); poDS->SetMetadataItem( "CONVERSION_DETAILS", "http://www.lpi.usra.edu/meetings/lpsc2014/pdf/1088.pdf" ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
/** * Captures Geolocation information from a COSMO-SKYMED * file. * The geoid will allways be WGS84 * The projection type may be UTM or UPS, depending on the * latitude from the center of the image. * @param iProductType type of CSK subproduct, see HDF5CSKProduct */ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType) { double *dfProjFalseEastNorth; double *dfProjScaleFactor; double *dfCenterCoord; //Set the ellipsoid to WGS84 oSRS.SetWellKnownGeogCS( "WGS84" ); if(iProductType == PROD_CSK_L1C||iProductType == PROD_CSK_L1D) { //Check if all the metadata attributes are present if(HDF5ReadDoubleAttr("Map Projection False East-North", &dfProjFalseEastNorth) == CE_Failure|| HDF5ReadDoubleAttr("Map Projection Scale Factor", &dfProjScaleFactor) == CE_Failure|| HDF5ReadDoubleAttr("Map Projection Centre", &dfCenterCoord) == CE_Failure|| GetMetadataItem("Projection_ID") == NULL) { pszProjection = CPLStrdup(""); pszGCPProjection = CPLStrdup(""); CPLError( CE_Failure, CPLE_OpenFailed, "The CSK hdf5 file geolocation information is malformed\n" ); } else { //Fetch projection Type CPLString osProjectionID = GetMetadataItem("Projection_ID"); //If the projection is UTM if(EQUAL(osProjectionID,"UTM")) { // @TODO: use SetUTM oSRS.SetProjCS(SRS_PT_TRANSVERSE_MERCATOR); oSRS.SetTM(dfCenterCoord[0], dfCenterCoord[1], dfProjScaleFactor[0], dfProjFalseEastNorth[0], dfProjFalseEastNorth[1]); } else { //TODO Test! I didn't had any UPS projected files to test! //If the projection is UPS if(EQUAL(osProjectionID,"UPS")) { oSRS.SetProjCS(SRS_PT_POLAR_STEREOGRAPHIC); oSRS.SetPS(dfCenterCoord[0], dfCenterCoord[1], dfProjScaleFactor[0], dfProjFalseEastNorth[0], dfProjFalseEastNorth[1]); } } //Export Projection to Wkt. //In case of error then clean the projection if (oSRS.exportToWkt(&pszProjection) != OGRERR_NONE) pszProjection = CPLStrdup(""); CPLFree(dfCenterCoord); CPLFree(dfProjScaleFactor); CPLFree(dfProjFalseEastNorth); } } else { //Export GCPProjection to Wkt. //In case of error then clean the projection if(oSRS.exportToWkt(&pszGCPProjection) != OGRERR_NONE) pszGCPProjection = CPLStrdup(""); } }
IRaster* ingestGDALRaster() { GDALDataset* ds = gdalDataset; cout << "Reading raster metadata..."; GDALRasterBand* band = ds->GetRasterBand(bandNum); int xSize = band->GetXSize(); int ySize = band->GetYSize(); int hasNoDataValue; double noDataValue = band->GetNoDataValue(&hasNoDataValue); if (hasNoDataValue != 0) noDataValue = NULL_DOUBLE_; double xForm[6]; ds->GetGeoTransform(xForm); double minX = xForm[0]; double cellSizeX = xForm[1]; double skewX = xForm[2]; double minY = xForm[3]; double skewY = xForm[4]; double cellSizeY = xForm[5]; string* spatialRef = new string(ds->GetProjectionRef()); if( ds->GetMetadataItem("NC_GLOBAL#IOAPI_VERSION", "") != NULL) { // Get georeference from IOAPI metadata // See: http://www.baronams.com/products/ioapi/GRIDS.html#horiz // Build the affine transform from metadata minX = atof(ds->GetMetadataItem("NC_GLOBAL#XORIG", "")); minY = atof(ds->GetMetadataItem("NC_GLOBAL#YORIG", "")); cellSizeX = atof(ds->GetMetadataItem("NC_GLOBAL#XCELL", "")); cellSizeY = atof(ds->GetMetadataItem("NC_GLOBAL#YCELL", "")); skewX = 0; skewY = 0; // Build the SpatialReference double xcent, ycent, p_alp, p_bet, p_gam; char *gdnam; OGRSpatialReference* sref = new OGRSpatialReference(""); // Assume datum is WGS84 (may not be, but IO/API files don't (can't?) say...) sref->SetWellKnownGeogCS("WGS84"); int gdtyp = atoi(ds->GetMetadataItem("NC_GLOBAL#GDTYP", "")); switch(gdtyp) { case 0: // Unknown projection (we assume lat-lon) break; case 1: // LATGRD3 -- Latitude/longitude break; case 2: // LAMGRD3 -- Lambert Conformal Conic (two standard parallels) xcent = atof(ds->GetMetadataItem("NC_GLOBAL#XCENT", "")); ycent = atof(ds->GetMetadataItem("NC_GLOBAL#YCENT", "")); p_alp = atof(ds->GetMetadataItem("NC_GLOBAL#P_ALP", "")); p_bet = atof(ds->GetMetadataItem("NC_GLOBAL#P_BET", "")); sref->SetLCC(p_alp, p_bet, ycent, xcent, 0, 0); gdnam = (char *)ds->GetMetadataItem("NC_GLOBAL#GDNAM", ""); sref->SetProjCS(gdnam); break; case 9: // ALBGRD3 -- Albers Equal-Area Conic xcent = atof(ds->GetMetadataItem("NC_GLOBAL#XCENT", "")); ycent = atof(ds->GetMetadataItem("NC_GLOBAL#YCENT", "")); p_alp = atof(ds->GetMetadataItem("NC_GLOBAL#P_ALP", "")); p_bet = atof(ds->GetMetadataItem("NC_GLOBAL#P_BET", "")); sref->SetACEA(p_alp, p_bet, ycent, xcent, 0, 0); gdnam = (char *)ds->GetMetadataItem("NC_GLOBAL#GDNAM", ""); sref->SetProjCS(gdnam); break; case 10: // LEQGRID3 -- Lambert Azimuthal Equal-Area p_alp = atof(ds->GetMetadataItem("NC_GLOBAL#P_ALP", "")); // Correct for bad metadata on some files if(p_alp == 0.0) { xcent = atof(ds->GetMetadataItem("NC_GLOBAL#XCENT", "")); ycent = atof(ds->GetMetadataItem("NC_GLOBAL#YCENT", "")); p_alp = ycent; p_gam = xcent; } else { p_gam = atof(ds->GetMetadataItem("NC_GLOBAL#P_GAM", "")); } sref->SetLAEA(p_alp, p_gam, 0, 0); gdnam = (char *)ds->GetMetadataItem("NC_GLOBAL#GDNAM", ""); sref->SetProjCS(gdnam); break; default: throw new runtime_error("ERROR: Unable to parse IO/API GDTYP variable"); } char* wktSrStr = new char[spatialRef->length()]; strcpy((char *)spatialRef->c_str(), wktSrStr); sref->exportToWkt(&wktSrStr); //CPLFree(sref); spatialRef->assign(wktSrStr); } cout << "...Done.\nReading raster band " << bandNum << "..."; IRaster* result = NULL; CPLErr retval; switch (band->GetRasterDataType()) { //retval = band->RasterIO(GF_Read, 0, 0, band->XSize, band->YSize, floatArray, band->XSize, band->YSize, 0, 0); case GDT_Float32: { float* floatArray = new float[xSize * ySize]; retval = band->RasterIO(GF_Read, 0, 0, xSize, ySize, floatArray, xSize, ySize, band->GetRasterDataType(), 0, 0); if (retval != CE_None) throw new runtime_error("GDALRasterBand::ReadBlock() returned error"); result = new Raster<float>(floatArray, xSize, ySize, cellSizeX, cellSizeY, minX, minY, skewX, skewY, spatialRef, noDataValue); cout << " -- Pixel type: Float32 -- ...Done\n"; } break; case GDT_Float64: { double* doubleArray = new double[xSize * ySize]; retval = band->RasterIO(GF_Read, 0, 0, xSize, ySize, doubleArray, xSize, ySize, band->GetRasterDataType(), 0, 0); if (retval != CE_None) throw new runtime_error("GDALRasterBand::ReadBlock() returned error"); result = new Raster<double>(doubleArray, xSize, ySize, cellSizeX, cellSizeY, minX, minY, skewX, skewY, spatialRef, noDataValue); cout << " -- Pixel type: Float64 -- ...Done\n"; } break; case GDT_Int32: { int* intArray = new int[xSize * ySize]; retval = band->RasterIO(GF_Read, 0, 0, xSize, ySize, intArray, xSize, ySize, band->GetRasterDataType(), 0, 0); if (retval != CE_None) throw new runtime_error("GDALRasterBand::ReadBlock() returned error"); result = new Raster<int>(intArray, xSize, ySize, cellSizeX, cellSizeY, minX, minY, skewX, skewY, spatialRef, noDataValue); cout << " -- Pixel type: Int32 -- ...Done\n"; } break; case GDT_Int16: { short* shortArray = new short[xSize * ySize]; retval = band->RasterIO(GF_Read, 0, 0, xSize, ySize, shortArray, xSize, ySize, band->GetRasterDataType(), 0, 0); if (retval != CE_None) throw new runtime_error("GDALRasterBand::ReadBlock() returned error"); result = new Raster<short>(shortArray, xSize, ySize, cellSizeX, cellSizeY, minX, minY, skewX, skewY, spatialRef, noDataValue); cout << " -- Pixel type: Int32 -- ...Done\n"; } break; case GDT_Byte: { char* byteArray = new char[xSize * ySize]; retval = band->RasterIO(GF_Read, 0, 0, xSize, ySize, byteArray, xSize, ySize, band->GetRasterDataType(), 0, 0); if (retval != CE_None) throw new runtime_error("GDALRasterBand::ReadBlock() returned error"); result = new Raster<char>(byteArray, xSize, ySize, cellSizeX, cellSizeY, minX, minY, skewX, skewY, spatialRef, noDataValue); cout << " -- Pixel type: Byte -- ...Done\n"; } break; default: throw new runtime_error("Unsupported pixel type"); } return result; }
GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this look like a CUBE dataset? */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Open the file using the large file API. */ /* -------------------------------------------------------------------- */ VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpQube == NULL ) return NULL; ISIS3Dataset *poDS; poDS = new ISIS3Dataset(); if( ! poDS->oKeywords.Ingest( fpQube, 0 ) ) { VSIFCloseL( fpQube ); delete poDS; return NULL; } VSIFCloseL( fpQube ); /* -------------------------------------------------------------------- */ /* Assume user is pointing to label (ie .lbl) file for detached option */ /* -------------------------------------------------------------------- */ // Image can be inline or detached and point to an image name // the Format can be Tiled or Raw // Object = Core // StartByte = 65537 // Format = Tile // TileSamples = 128 // TileLines = 128 //OR----- // Object = Core // StartByte = 1 // ^Core = r0200357_detatched.cub // Format = BandSequential //OR----- // Object = Core // StartByte = 1 // ^Core = r0200357_detached_tiled.cub // Format = Tile // TileSamples = 128 // TileLines = 128 /* -------------------------------------------------------------------- */ /* What file contains the actual data? */ /* -------------------------------------------------------------------- */ const char *pszCore = poDS->GetKeyword( "IsisCube.Core.^Core" ); CPLString osQubeFile; if( EQUAL(pszCore,"") ) osQubeFile = poOpenInfo->pszFilename; else { CPLString osPath = CPLGetPath( poOpenInfo->pszFilename ); osQubeFile = CPLFormFilename( osPath, pszCore, NULL ); poDS->osExternalCube = osQubeFile; } /* -------------------------------------------------------------------- */ /* Check if file an ISIS3 header file? Read a few lines of text */ /* searching for something starting with nrows or ncols. */ /* -------------------------------------------------------------------- */ GDALDataType eDataType = GDT_Byte; OGRSpatialReference oSRS; int nRows = -1; int nCols = -1; int nBands = 1; int nSkipBytes = 0; int tileSizeX = 0; int tileSizeY = 0; double dfULXMap=0.5; double dfULYMap = 0.5; double dfXDim = 1.0; double dfYDim = 1.0; double scaleFactor = 1.0; double dfNoData = 0.0; int bNoDataSet = FALSE; char chByteOrder = 'M'; //default to MSB char szLayout[32] = "BandSequential"; //default to band seq. const char *target_name; //planet name //projection parameters const char *map_proj_name; int bProjectionSet = TRUE; char proj_target_name[200]; char geog_name[60]; char datum_name[60]; char sphere_name[60]; char bIsGeographic = TRUE; double semi_major = 0.0; double semi_minor = 0.0; double iflattening = 0.0; float center_lat = 0.0; float center_lon = 0.0; float first_std_parallel = 0.0; float second_std_parallel = 0.0; double radLat, localRadius; VSILFILE *fp; /************* Skipbytes *****************************/ nSkipBytes = atoi(poDS->GetKeyword("IsisCube.Core.StartByte","")) - 1; /******* Grab format type (BandSequential, Tiled) *******/ const char *value; value = poDS->GetKeyword( "IsisCube.Core.Format", "" ); if (EQUAL(value,"Tile") ) { //Todo strcpy(szLayout,"Tiled"); /******* Get Tile Sizes *********/ tileSizeX = atoi(poDS->GetKeyword("IsisCube.Core.TileSamples","")); tileSizeY = atoi(poDS->GetKeyword("IsisCube.Core.TileLines","")); if (tileSizeX <= 0 || tileSizeY <= 0) { CPLError( CE_Failure, CPLE_OpenFailed, "Wrong tile dimensions : %d x %d", tileSizeX, tileSizeY); delete poDS; return NULL; } } else if (EQUAL(value,"BandSequential") ) strcpy(szLayout,"BSQ"); else { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return NULL; } /*********** Grab samples lines band ************/ nCols = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Samples","")); nRows = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Lines","")); nBands = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Bands","")); /****** Grab format type - ISIS3 only supports 8,U16,S16,32 *****/ const char *itype; itype = poDS->GetKeyword( "IsisCube.Core.Pixels.Type" ); if (EQUAL(itype,"UnsignedByte") ) { eDataType = GDT_Byte; dfNoData = NULL1; bNoDataSet = TRUE; } else if (EQUAL(itype,"UnsignedWord") ) { eDataType = GDT_UInt16; dfNoData = NULL1; bNoDataSet = TRUE; } else if (EQUAL(itype,"SignedWord") ) { eDataType = GDT_Int16; dfNoData = NULL2; bNoDataSet = TRUE; } else if (EQUAL(itype,"Real") || EQUAL(value,"") ) { eDataType = GDT_Float32; dfNoData = NULL3; bNoDataSet = TRUE; } else { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout type not supported. Abort\n\n", itype); delete poDS; return NULL; } /*********** Grab samples lines band ************/ value = poDS->GetKeyword( "IsisCube.Core.Pixels.ByteOrder"); if (EQUAL(value,"Lsb")) chByteOrder = 'I'; /*********** Grab Cellsize ************/ value = poDS->GetKeyword("IsisCube.Mapping.PixelResolution"); if (strlen(value) > 0 ) { dfXDim = atof(value); /* values are in meters */ dfYDim = -atof(value); } /*********** Grab UpperLeftCornerY ************/ value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerY"); if (strlen(value) > 0) { dfULYMap = atof(value); } /*********** Grab UpperLeftCornerX ************/ value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerX"); if( strlen(value) > 0 ) { dfULXMap = atof(value); } /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. Mars ***/ target_name = poDS->GetKeyword("IsisCube.Mapping.TargetName"); /*********** Grab MAP_PROJECTION_TYPE ************/ map_proj_name = poDS->GetKeyword( "IsisCube.Mapping.ProjectionName"); /*********** Grab SEMI-MAJOR ************/ semi_major = atof(poDS->GetKeyword( "IsisCube.Mapping.EquatorialRadius")); /*********** Grab semi-minor ************/ semi_minor = atof(poDS->GetKeyword( "IsisCube.Mapping.PolarRadius")); /*********** Grab CENTER_LAT ************/ center_lat = atof(poDS->GetKeyword( "IsisCube.Mapping.CenterLatitude")); /*********** Grab CENTER_LON ************/ center_lon = atof(poDS->GetKeyword( "IsisCube.Mapping.CenterLongitude")); /*********** Grab 1st std parallel ************/ first_std_parallel = atof(poDS->GetKeyword( "IsisCube.Mapping.FirstStandardParallel")); /*********** Grab 2nd std parallel ************/ second_std_parallel = atof(poDS->GetKeyword( "IsisCube.Mapping.SecondStandardParallel")); /*********** Grab scaleFactor ************/ scaleFactor = atof(poDS->GetKeyword( "IsisCube.Mapping.scaleFactor")); /*** grab LatitudeType = Planetographic ****/ // Need to further study how ocentric/ographic will effect the gdal library // So far we will use this fact to define a sphere or ellipse for some // projections // Frank - may need to talk this over value = poDS->GetKeyword("IsisCube.Mapping.LatitudeType"); if (EQUAL( value, "\"Planetocentric\"" )) bIsGeographic = FALSE; //Set oSRS projection and parameters //############################################################ //ISIS3 Projection types // Equirectangular // LambertConformal // Mercator // ObliqueCylindrical //Todo // Orthographic // PolarStereographic // SimpleCylindrical // Sinusoidal // TransverseMercator #ifdef DEBUG CPLDebug( "ISIS3", "using projection %s", map_proj_name); #endif if ((EQUAL( map_proj_name, "Equirectangular" )) || (EQUAL( map_proj_name, "SimpleCylindrical" )) ) { oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "Orthographic" )) { oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "Sinusoidal" )) { oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "Mercator" )) { oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, scaleFactor, 0, 0 ); } else if (EQUAL( map_proj_name, "PolarStereographic" )) { oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, scaleFactor, 0, 0 ); } else if (EQUAL( map_proj_name, "TransverseMercator" )) { oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, scaleFactor, 0, 0 ); } else if (EQUAL( map_proj_name, "LambertConformal" )) { oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else { CPLDebug( "ISIS3", "Dataset projection %s is not supported. Continuing...", map_proj_name ); bProjectionSet = FALSE; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword strcpy(proj_target_name, map_proj_name); strcat(proj_target_name, " "); strcat(proj_target_name, target_name); oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System strcpy(geog_name, "GCS_"); strcat(geog_name, target_name); //The datum name will be the same basic name as the planet strcpy(datum_name, "D_"); strcat(datum_name, target_name); strcpy(sphere_name, target_name); //strcat(sphere_name, "_IAU_IAG"); //Might not be IAU defined so don't add //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "Stereographic" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "PolarStereographic" )) ) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... strcat(sphere_name, "_polarRadius"); oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SimpleCylindrical" )) || (EQUAL( map_proj_name, "Orthographic" )) || (EQUAL( map_proj_name, "Stereographic" )) || (EQUAL( map_proj_name, "Sinusoidal" )) ) { //isis uses the sphereical equation for these projections so force a sphere oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if (EQUAL( map_proj_name, "Equirectangular" )) { //Calculate localRadius using ISIS3 simple elliptical method // not the more standard Radius of Curvature method //PI = 4 * atan(1); radLat = center_lat * PI / 180; // in radians localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2) + pow(semi_major*sin(radLat),2) ); strcat(sphere_name, "_localRadius"); oSRS.SetGeogCS( geog_name, datum_name, sphere_name, localRadius, 0.0, "Reference_Meridian", 0.0 ); } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } /* END ISIS3 Label Read */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* -------------------------------------------------------------------- */ /* Is the CUB detached - if so, reset name to binary file? */ /* -------------------------------------------------------------------- */ #ifdef notdef // Frank - is this correct? //The extension already added on so don't add another. But is this needed? char *pszPath = CPLStrdup( CPLGetPath( poOpenInfo->pszFilename ) ); char *pszName = CPLStrdup( CPLGetBasename( poOpenInfo->pszFilename ) ); if (bIsDetached) pszCUBFilename = CPLFormCIFilename( pszPath, detachedCub, "" ); #endif /* -------------------------------------------------------------------- */ /* Did we get the required keywords? If not we return with */ /* this never having been considered to be a match. This isn't */ /* an error! */ /* -------------------------------------------------------------------- */ if( nRows < 1 || nCols < 1 || nBands < 1 ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nCols; poDS->nRasterYSize = nRows; /* -------------------------------------------------------------------- */ /* Open target binary file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( osQubeFile, "r" ); else poDS->fpImage = VSIFOpenL( osQubeFile, "r+" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s with write permission.\n%s", osQubeFile.c_str(), VSIStrerror( errno ) ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Compute the line offset. */ /* -------------------------------------------------------------------- */ int nItemSize = GDALGetDataTypeSize(eDataType)/8; int nLineOffset=0, nPixelOffset=0, nBandOffset=0; if( EQUAL(szLayout,"BSQ") ) { nPixelOffset = nItemSize; nLineOffset = nPixelOffset * nCols; nBandOffset = nLineOffset * nRows; } else /* Tiled */ { } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ int i; #ifdef CPL_LSB int bNativeOrder = !(chByteOrder == 'M'); #else int bNativeOrder = (chByteOrder == 'M'); #endif for( i = 0; i < nBands; i++ ) { GDALRasterBand *poBand; if( EQUAL(szLayout,"Tiled") ) { poBand = new ISISTiledBand( poDS, poDS->fpImage, i+1, eDataType, tileSizeX, tileSizeY, nSkipBytes, 0, 0, bNativeOrder ); } else { poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, nPixelOffset, nLineOffset, eDataType, #ifdef CPL_LSB chByteOrder == 'I' || chByteOrder == 'L', #else chByteOrder == 'M', #endif TRUE ); } poDS->SetBand( i+1, poBand ); if( bNoDataSet ) ((GDALPamRasterBand *) poBand)->SetNoDataValue( dfNoData ); // Set offset/scale values at the PAM level. poBand->SetOffset( CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Base","0.0"))); poBand->SetScale( CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Multiplier","1.0"))); } /* -------------------------------------------------------------------- */ /* Check for a .prj file. For ISIS3 I would like to keep this in */ /* -------------------------------------------------------------------- */ CPLString osPath, osName; osPath = CPLGetPath( poOpenInfo->pszFilename ); osName = CPLGetBasename(poOpenInfo->pszFilename); const char *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" ); fp = VSIFOpenL( pszPrjFile, "r" ); if( fp != NULL ) { char **papszLines; OGRSpatialReference oSRS; VSIFCloseL( fp ); papszLines = CSLLoad( pszPrjFile ); if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE ) { char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } CSLDestroy( papszLines ); } if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 ) { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = dfULXMap; poDS->adfGeoTransform[1] = dfXDim; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfULYMap; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = dfYDim; } if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", poDS->adfGeoTransform ); if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
void SavePolygons( const std::vector< std::string > InFilenames, const char *OutFilename, const cv::Mat klabels, const std::vector< cv::Mat > raster, const std::vector< u_int32_t > labelpixels, const std::vector< std::vector <double> > sumCH, const std::vector< std::vector <double> > avgCH, const std::vector< std::vector <double> > stdCH, std::vector< std::vector< LINE > >& linelists ) { CPLLocaleC oLocaleCForcer(); CPLErrorReset(); const char *pszDriverName = "ESRI Shapefile"; GDALDriver *liDriver; liDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName ); if( liDriver == NULL ) { printf( "\nERROR: %s driver not available.\n", pszDriverName ); exit( 1 ); } const size_t m_bands = raster.size(); const size_t m_labels = labelpixels.size(); GDALDataset *liDS; liDS = liDriver->Create( OutFilename, 0, 0, 0, GDT_Unknown, NULL ); if( liDS == NULL ) { printf( "\nERROR: Creation of output file failed.\n" ); exit( 1 ); } // dataset GDALDataset* piDataset; piDataset = (GDALDataset*) GDALOpen(InFilenames[0].c_str(), GA_ReadOnly); // spatialref OGRSpatialReference oSRS; oSRS.SetProjCS( piDataset->GetProjectionRef() ); OGRLayer *liLayer; liLayer = liDS->CreateLayer( "segments", &oSRS, wkbPolygon, NULL ); if( liLayer == NULL ) { printf( "\nERROR: Layer creation failed.\n" ); exit( 1 ); } // spatial transform double adfGeoTransform[6]; double oX = 0.0f; double oY = 0.0f; double mX = 1.0f; double mY = -1.0f; if( piDataset->GetGeoTransform( adfGeoTransform ) == CE_None ) { oX = adfGeoTransform[0]; oY = adfGeoTransform[3]; mX = adfGeoTransform[1]; mY = adfGeoTransform[5]; } GDALClose( (GDALDatasetH) piDataset ); OGRFieldDefn *clsIdField = new OGRFieldDefn( "CLASS", OFTInteger ); liLayer->CreateField( clsIdField ); OGRFieldDefn *pixArField = new OGRFieldDefn( "AREA", OFTInteger ); liLayer->CreateField( pixArField ); for ( size_t b = 0; b < m_bands; b++ ) { stringstream value; value << b+1; std::string FieldName = value.str() + "_AVERAGE"; OGRFieldDefn *lavrgField = new OGRFieldDefn( FieldName.c_str(), OFTReal ); liLayer->CreateField( lavrgField ); } for ( size_t b = 0; b < m_bands; b++ ) { stringstream value; value << b+1; std::string FieldName = value.str() + "_STDDEV"; OGRFieldDefn *lavrgField = new OGRFieldDefn( FieldName.c_str(), OFTReal ); liLayer->CreateField( lavrgField ); } int multiring = 0; printf ("Write File: %s (polygon)\n", OutFilename); for (size_t k = 0; k < m_labels; k++) { if (multiring == 1) { k = k - 1; multiring = 0; } if (linelists[k].size() == 0) continue; // insert field data OGRFeature *liFeature; liFeature = OGRFeature::CreateFeature( liLayer->GetLayerDefn() ); liFeature->SetField( "CLASS", (int) k ); liFeature->SetField( "AREA", (int) labelpixels.at(k) ); for ( size_t b = 0; b < m_bands; b++ ) { stringstream value; value << b+1; std::string FieldName = value.str() + "_AVERAGE"; liFeature->SetField( FieldName.c_str(), (double) avgCH[b].at(k) ); } for ( size_t b = 0; b < m_bands; b++ ) { stringstream value; value << b+1; std::string FieldName = value.str() + "_STDDEV"; liFeature->SetField( FieldName.c_str(), stdCH[b].at(k) ); } // initiate polygon start OGRLinearRing linestring; linestring.setCoordinateDimension(2); linestring.addPoint( oX + (double) linelists[k][0].sX * mX, oY + mY * (double) linelists[k][0].sY ); linestring.addPoint( oX + (double) linelists[k][0].eX * mX, oY + mY * (double) linelists[k][0].eY ); linelists[k].erase( linelists[k].begin() ); // construct polygon from lines while ( linelists[k].size() > 0 ) { if (multiring == 1) break; vector<LINE>::iterator it = linelists[k].begin(); for (; it != linelists[k].end(); ++it) { double ltX = linestring.getX(linestring.getNumPoints()-1); double ltY = linestring.getY(linestring.getNumPoints()-1); double csX = oX + (double) it->sX * mX; double csY = oY + mY * (double) it->sY; double ceX = oX + (double) it->eX * mX; double ceY = oY + mY * (double) it->eY; if ( ( csX == ltX ) && ( csY == ltY ) ) { linestring.addPoint(ceX, ceY); linelists[k].erase(it); break; } if ( ( ceX == ltX ) && ( ceY == ltY ) ) { linestring.addPoint(csX, csY); linelists[k].erase(it); break; } if (it == linelists[k].end()-1) { multiring = 1; break; } } } OGRPolygon polygon; linestring.closeRings(); // simplify poligons // remove colinear vertices OGRLinearRing linesimple; float pointPrevX = 0, pointPrevY = 0; for (int i = 0; i < linestring.getNumPoints(); i++) { OGRPoint point; linestring.getPoint(i, &point); // start if ( i == 0) { linesimple.addPoint( &point ); pointPrevX = point.getX(); pointPrevY = point.getY(); continue; } // end vertex if ( i == linestring.getNumPoints() - 1 ) { linesimple.addPoint( &point ); continue; } OGRPoint pointNext; linestring.getPoint(i+1, &pointNext); // | x1 y1 1 | // det | x2 y2 1 | = 0 => p1,p2,p3 are colinear // | x3 y3 1 | // x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) == 0 // only if not colinear with previous and next if ( pointPrevX*(point.getY()-pointNext.getY()) + point.getX()*(pointNext.getY()-pointPrevY) + pointNext.getX()*(pointPrevY-point.getY()) != 0 ) { linesimple.addPoint( &point ); pointPrevX = point.getX(); pointPrevY = point.getY(); } } // as polygon geometry polygon.addRing( &linesimple ); liFeature->SetGeometry( &polygon ); if( liLayer->CreateFeature( liFeature ) != OGRERR_NONE ) { printf( "\nERROR: Failed to create feature in shapefile.\n" ); exit( 1 ); } OGRFeature::DestroyFeature( liFeature ); GDALTermProgress( (float)(k+1) / (float)(m_labels), NULL, NULL ); } GDALTermProgress( 1.0f, NULL, NULL ); GDALClose( liDS ); }