osgEarth 2.1.1
|
Public Member Functions | |
GDALTileSource (const TileSourceOptions &options) | |
virtual | ~GDALTileSource () |
void | initialize (const std::string &referenceURI, const Profile *overrideProfile) |
void | pixelToGeo (double x, double y, double &geoX, double &geoY) |
osg::Image * | createImage (const TileKey &key, ProgressCallback *progress) |
bool | isValidValue (float v, GDALRasterBand *band) |
float | getInterpolatedValue (GDALRasterBand *band, double x, double y, bool applyOffset=true) |
osg::HeightField * | createHeightField (const TileKey &key, ProgressCallback *progress) |
bool | intersects (const TileKey &key) |
Static Public Member Functions | |
static GDALRasterBand * | findBand (GDALDataset *ds, GDALColorInterp colorInterp) |
static void | getPalleteIndexColor (GDALRasterBand *band, int index, osg::Vec4ub &color) |
Private Attributes | |
GDALDataset * | _srcDS |
GDALDataset * | _warpedDS |
double | _geotransform [6] |
double | _invtransform [6] |
osg::Vec2d | _extentsMin |
osg::Vec2d | _extentsMax |
const GDALOptions | _options |
unsigned int | _maxDataLevel |
Definition at line 611 of file ReaderWriterGDAL.cpp.
GDALTileSource::GDALTileSource | ( | const TileSourceOptions & | options | ) | [inline] |
Definition at line 614 of file ReaderWriterGDAL.cpp.
: TileSource( options ), _srcDS(NULL), _warpedDS(NULL), _options(options), _maxDataLevel(30) { }
virtual GDALTileSource::~GDALTileSource | ( | ) | [inline, virtual] |
Definition at line 623 of file ReaderWriterGDAL.cpp.
osg::HeightField* GDALTileSource::createHeightField | ( | const TileKey & | key, |
ProgressCallback * | progress | ||
) | [inline, virtual] |
Creates a heightfield for the given TileKey The returned object is new and is the responsibility of the caller.
Reimplemented from osgEarth::TileSource.
Definition at line 1459 of file ReaderWriterGDAL.cpp.
{ if (key.getLevelOfDetail() > _maxDataLevel) { //OE_NOTICE << "Reached maximum data resolution key=" << key.getLevelOfDetail() << " max=" << _maxDataLevel << std::endl; return NULL; } GDAL_SCOPED_LOCK; int tileSize = _options.tileSize().value(); //Allocate the heightfield osg::ref_ptr<osg::HeightField> hf = new osg::HeightField; hf->allocate(tileSize, tileSize); if (intersects(key)) { //Get the meter extents of the tile double xmin, ymin, xmax, ymax; key.getExtent().getBounds(xmin, ymin, xmax, ymax); //Just read from the first band GDALRasterBand* band = _warpedDS->GetRasterBand(1); double dx = (xmax - xmin) / (tileSize-1); double dy = (ymax - ymin) / (tileSize-1); for (int c = 0; c < tileSize; ++c) { double geoX = xmin + (dx * (double)c); for (int r = 0; r < tileSize; ++r) { double geoY = ymin + (dy * (double)r); float h = getInterpolatedValue(band, geoX, geoY); hf->setHeight(c, r, h); } } } else { for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE; } return hf.release(); }
osg::Image* GDALTileSource::createImage | ( | const TileKey & | key, |
ProgressCallback * | progress | ||
) | [inline, virtual] |
Creates an image for the given TileKey. The returned object is new and is the responsibility of the caller.
Implements osgEarth::TileSource.
Definition at line 1019 of file ReaderWriterGDAL.cpp.
{ if (key.getLevelOfDetail() > _maxDataLevel) { OE_DEBUG << LC << "" << getName() << ": Reached maximum data resolution key=" << key.getLevelOfDetail() << " max=" << _maxDataLevel << std::endl; return NULL; } GDAL_SCOPED_LOCK; int tileSize = _options.tileSize().value(); osg::ref_ptr<osg::Image> image; if (intersects(key)) //TODO: I think this test is OBE -gw { //Get the extents of the tile double xmin, ymin, xmax, ymax; key.getExtent().getBounds(xmin, ymin, xmax, ymax); double dx = (xmax - xmin) / (tileSize-1); double dy = (ymax - ymin) / (tileSize-1); int target_width = tileSize; int target_height = tileSize; int tile_offset_left = 0; int tile_offset_top = 0; int off_x = int((xmin - _geotransform[0]) / _geotransform[1]); int off_y = int((ymax - _geotransform[3]) / _geotransform[5]); int width = int(((xmax - _geotransform[0]) / _geotransform[1]) - off_x); int height = int(((ymin - _geotransform[3]) / _geotransform[5]) - off_y); if (off_x + width > _warpedDS->GetRasterXSize()) { int oversize_right = off_x + width - _warpedDS->GetRasterXSize(); target_width = target_width - int(float(oversize_right) / width * target_width); width = _warpedDS->GetRasterXSize() - off_x; } if (off_x < 0) { int oversize_left = -off_x; tile_offset_left = int(float(oversize_left) / width * target_width); target_width = target_width - int(float(oversize_left) / width * target_width); width = width + off_x; off_x = 0; } if (off_y + height > _warpedDS->GetRasterYSize()) { int oversize_bottom = off_y + height - _warpedDS->GetRasterYSize(); target_height = target_height - (int)osg::round(float(oversize_bottom) / height * target_height); height = _warpedDS->GetRasterYSize() - off_y; } if (off_y < 0) { int oversize_top = -off_y; tile_offset_top = int(float(oversize_top) / height * target_height); target_height = target_height - int(float(oversize_top) / height * target_height); height = height + off_y; off_y = 0; } OE_DEBUG << LC << "ReadWindow " << width << "x" << height << " DestWindow " << target_width << "x" << target_height << std::endl; //Return if parameters are out of range. if (width <= 0 || height <= 0 || target_width <= 0 || target_height <= 0) { return 0; } GDALRasterBand* bandRed = findBand(_warpedDS, GCI_RedBand); GDALRasterBand* bandGreen = findBand(_warpedDS, GCI_GreenBand); GDALRasterBand* bandBlue = findBand(_warpedDS, GCI_BlueBand); GDALRasterBand* bandAlpha = findBand(_warpedDS, GCI_AlphaBand); GDALRasterBand* bandGray = findBand(_warpedDS, GCI_GrayIndex); GDALRasterBand* bandPalette = findBand(_warpedDS, GCI_PaletteIndex); //The pixel format is always RGBA to support transparency GLenum pixelFormat = GL_RGBA; if (bandRed && bandGreen && bandBlue) { unsigned char *red = new unsigned char[target_width * target_height]; unsigned char *green = new unsigned char[target_width * target_height]; unsigned char *blue = new unsigned char[target_width * target_height]; unsigned char *alpha = new unsigned char[target_width * target_height]; //Initialize the alpha values to 255. memset(alpha, 255, target_width * target_height); image = new osg::Image; image->allocateImage(tileSize, tileSize, 1, pixelFormat, GL_UNSIGNED_BYTE); memset(image->data(), 0, image->getImageSizeInBytes()); //Nearest interpolation just uses RasterIO to sample the imagery and should be very fast. if (!*_options.interpolateImagery() || _options.interpolation() == INTERP_NEAREST) { bandRed->RasterIO(GF_Read, off_x, off_y, width, height, red, target_width, target_height, GDT_Byte, 0, 0); bandGreen->RasterIO(GF_Read, off_x, off_y, width, height, green, target_width, target_height, GDT_Byte, 0, 0); bandBlue->RasterIO(GF_Read, off_x, off_y, width, height, blue, target_width, target_height, GDT_Byte, 0, 0); if (bandAlpha) { bandAlpha->RasterIO(GF_Read, off_x, off_y, width, height, alpha, target_width, target_height, GDT_Byte, 0, 0); } for (int src_row = 0, dst_row = tile_offset_top; src_row < target_height; src_row++, dst_row++) { for (int src_col = 0, dst_col = tile_offset_left; src_col < target_width; ++src_col, ++dst_col) { *(image->data(dst_col, dst_row) + 0) = red[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 1) = green[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 2) = blue[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 3) = alpha[src_col + src_row * target_width]; } } image->flipVertical(); } else { //Sample each point exactly for (unsigned int c = 0; c < tileSize; ++c) { double geoX = xmin + (dx * (double)c); for (unsigned int r = 0; r < tileSize; ++r) { double geoY = ymin + (dy * (double)r); *(image->data(c,r) + 0) = getInterpolatedValue(bandRed, geoX,geoY,false); *(image->data(c,r) + 1) = getInterpolatedValue(bandGreen,geoX,geoY,false); *(image->data(c,r) + 2) = getInterpolatedValue(bandBlue, geoX,geoY,false); if (bandAlpha != NULL) *(image->data(c,r) + 3) = getInterpolatedValue(bandAlpha,geoX, geoY, false); else *(image->data(c,r) + 3) = 255; } } } delete []red; delete []green; delete []blue; delete []alpha; } else if (bandGray) { unsigned char *gray = new unsigned char[target_width * target_height]; unsigned char *alpha = new unsigned char[target_width * target_height]; //Initialize the alpha values to 255. memset(alpha, 255, target_width * target_height); image = new osg::Image; image->allocateImage(tileSize, tileSize, 1, pixelFormat, GL_UNSIGNED_BYTE); memset(image->data(), 0, image->getImageSizeInBytes()); if (!*_options.interpolateImagery() || _options.interpolation() == INTERP_NEAREST) { bandGray->RasterIO(GF_Read, off_x, off_y, width, height, gray, target_width, target_height, GDT_Byte, 0, 0); if (bandAlpha) { bandAlpha->RasterIO(GF_Read, off_x, off_y, width, height, alpha, target_width, target_height, GDT_Byte, 0, 0); } for (int src_row = 0, dst_row = tile_offset_top; src_row < target_height; src_row++, dst_row++) { for (int src_col = 0, dst_col = tile_offset_left; src_col < target_width; ++src_col, ++dst_col) { *(image->data(dst_col, dst_row) + 0) = gray[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 1) = gray[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 2) = gray[src_col + src_row * target_width]; *(image->data(dst_col, dst_row) + 3) = alpha[src_col + src_row * target_width]; } } image->flipVertical(); } else { for (int c = 0; c < tileSize; ++c) { double geoX = xmin + (dx * (double)c); for (int r = 0; r < tileSize; ++r) { double geoY = ymin + (dy * (double)r); float color = getInterpolatedValue(bandGray,geoX,geoY,false); *(image->data(c,r) + 0) = color; *(image->data(c,r) + 1) = color; *(image->data(c,r) + 2) = color; if (bandAlpha != NULL) *(image->data(c,r) + 3) = getInterpolatedValue(bandAlpha,geoX,geoY,false); else *(image->data(c,r) + 3) = 255; } } } delete []gray; delete []alpha; } else if (bandPalette) { //Pallete indexed imagery doesn't support interpolation currently and only uses nearest //b/c interpolating pallete indexes doesn't make sense. unsigned char *palette = new unsigned char[target_width * target_height]; image = new osg::Image; image->allocateImage(tileSize, tileSize, 1, pixelFormat, GL_UNSIGNED_BYTE); memset(image->data(), 0, image->getImageSizeInBytes()); bandPalette->RasterIO(GF_Read, off_x, off_y, width, height, palette, target_width, target_height, GDT_Byte, 0, 0); for (int src_row = 0, dst_row = tile_offset_top; src_row < target_height; src_row++, dst_row++) { for (int src_col = 0, dst_col = tile_offset_left; src_col < target_width; ++src_col, ++dst_col) { osg::Vec4ub color; getPalleteIndexColor( bandPalette, palette[src_col + src_row * target_width], color ); *(image->data(dst_col, dst_row) + 0) = color.r(); *(image->data(dst_col, dst_row) + 1) = color.g(); *(image->data(dst_col, dst_row) + 2) = color.b(); *(image->data(dst_col, dst_row) + 3) = color.a(); } } image->flipVertical(); delete [] palette; } else { OE_WARN << LC << "Could not find red, green and blue bands or gray bands in " << _options.url()->full() << ". Cannot create image. " << std::endl; return NULL; } } // Moved this logic up into ImageLayer::createImageWrapper. //if (!image.valid()) //{ // //OE_WARN << LC << "Illegal state-- should not get here" << std::endl; // return ImageUtils::createEmptyImage(); //} return image.release(); }
static GDALRasterBand* GDALTileSource::findBand | ( | GDALDataset * | ds, |
GDALColorInterp | colorInterp | ||
) | [inline, static] |
Finds a raster band based on color interpretation
Definition at line 924 of file ReaderWriterGDAL.cpp.
{ GDAL_SCOPED_LOCK; for (int i = 1; i <= ds->GetRasterCount(); ++i) { if (ds->GetRasterBand(i)->GetColorInterpretation() == colorInterp) return ds->GetRasterBand(i); } return 0; }
float GDALTileSource::getInterpolatedValue | ( | GDALRasterBand * | band, |
double | x, | ||
double | y, | ||
bool | applyOffset = true |
||
) | [inline] |
Definition at line 1328 of file ReaderWriterGDAL.cpp.
{ double r, c; GDALApplyGeoTransform(_invtransform, x, y, &c, &r); //Account for slight rounding errors. If we are right on the edge of the dataset, clamp to the edge double eps = 0.0001; if (osg::equivalent(c, 0, eps)) c = 0; if (osg::equivalent(r, 0, eps)) r = 0; if (osg::equivalent(c, (double)_warpedDS->GetRasterXSize(), eps)) c = _warpedDS->GetRasterXSize(); if (osg::equivalent(r, (double)_warpedDS->GetRasterYSize(), eps)) r = _warpedDS->GetRasterYSize(); if (applyOffset) { //Apply half pixel offset r-= 0.5; c-= 0.5; //Account for the half pixel offset in the geotransform. If the pixel value is -0.5 we are still technically in the dataset //since 0,0 is now the center of the pixel. So, if are within a half pixel above or a half pixel below the dataset just use //the edge values if (c < 0 && c >= -0.5) { c = 0; } else if (c > _warpedDS->GetRasterXSize()-1 && c <= _warpedDS->GetRasterXSize()-0.5) { c = _warpedDS->GetRasterXSize()-1; } if (r < 0 && r >= -0.5) { r = 0; } else if (r > _warpedDS->GetRasterYSize()-1 && r <= _warpedDS->GetRasterYSize()-0.5) { r = _warpedDS->GetRasterYSize()-1; } } float result = 0.0f; //If the location is outside of the pixel values of the dataset, just return 0 if (c < 0 || r < 0 || c > _warpedDS->GetRasterXSize()-1 || r > _warpedDS->GetRasterYSize()-1) return NO_DATA_VALUE; if ( _options.interpolation() == INTERP_NEAREST ) { band->RasterIO(GF_Read, (int)osg::round(c), (int)osg::round(r), 1, 1, &result, 1, 1, GDT_Float32, 0, 0); if (!isValidValue( result, band)) { return NO_DATA_VALUE; } } else { int rowMin = osg::maximum((int)floor(r), 0); int rowMax = osg::maximum(osg::minimum((int)ceil(r), (int)(_warpedDS->GetRasterYSize()-1)), 0); int colMin = osg::maximum((int)floor(c), 0); int colMax = osg::maximum(osg::minimum((int)ceil(c), (int)(_warpedDS->GetRasterXSize()-1)), 0); if (rowMin > rowMax) rowMin = rowMax; if (colMin > colMax) colMin = colMax; float urHeight, llHeight, ulHeight, lrHeight; band->RasterIO(GF_Read, colMin, rowMin, 1, 1, &llHeight, 1, 1, GDT_Float32, 0, 0); band->RasterIO(GF_Read, colMin, rowMax, 1, 1, &ulHeight, 1, 1, GDT_Float32, 0, 0); band->RasterIO(GF_Read, colMax, rowMin, 1, 1, &lrHeight, 1, 1, GDT_Float32, 0, 0); band->RasterIO(GF_Read, colMax, rowMax, 1, 1, &urHeight, 1, 1, GDT_Float32, 0, 0); /* if (!isValidValue(urHeight, band)) urHeight = 0.0f; if (!isValidValue(llHeight, band)) llHeight = 0.0f; if (!isValidValue(ulHeight, band)) ulHeight = 0.0f; if (!isValidValue(lrHeight, band)) lrHeight = 0.0f; */ if (!isValidValue(urHeight, band) || (!isValidValue(llHeight, band)) ||(!isValidValue(ulHeight, band)) || (!isValidValue(lrHeight, band))) { return NO_DATA_VALUE; } if ( _options.interpolation() == INTERP_AVERAGE ) { double x_rem = c - (int)c; double y_rem = r - (int)r; double w00 = (1.0 - y_rem) * (1.0 - x_rem) * (double)llHeight; double w01 = (1.0 - y_rem) * x_rem * (double)lrHeight; double w10 = y_rem * (1.0 - x_rem) * (double)ulHeight; double w11 = y_rem * x_rem * (double)urHeight; result = (float)(w00 + w01 + w10 + w11); } else if ( _options.interpolation() == INTERP_BILINEAR ) { //Check for exact value if ((colMax == colMin) && (rowMax == rowMin)) { //OE_NOTICE << "Exact value" << std::endl; result = llHeight; } else if (colMax == colMin) { //OE_NOTICE << "Vertically" << std::endl; //Linear interpolate vertically result = ((float)rowMax - r) * llHeight + (r - (float)rowMin) * ulHeight; } else if (rowMax == rowMin) { //OE_NOTICE << "Horizontally" << std::endl; //Linear interpolate horizontally result = ((float)colMax - c) * llHeight + (c - (float)colMin) * lrHeight; } else { //OE_NOTICE << "Bilinear" << std::endl; //Bilinear interpolate float r1 = ((float)colMax - c) * llHeight + (c - (float)colMin) * lrHeight; float r2 = ((float)colMax - c) * ulHeight + (c - (float)colMin) * urHeight; //OE_INFO << "r1, r2 = " << r1 << " , " << r2 << std::endl; result = ((float)rowMax - r) * r1 + (r - (float)rowMin) * r2; } } } return result; }
static void GDALTileSource::getPalleteIndexColor | ( | GDALRasterBand * | band, |
int | index, | ||
osg::Vec4ub & | color | ||
) | [inline, static] |
Definition at line 935 of file ReaderWriterGDAL.cpp.
{ const GDALColorEntry *colorEntry = band->GetColorTable()->GetColorEntry( index ); GDALPaletteInterp interp = band->GetColorTable()->GetPaletteInterpretation(); if (!colorEntry) { //FIXME: What to do here? //OE_INFO << "NO COLOR ENTRY FOR COLOR " << rawImageData[i] << std::endl; color.r() = 255; color.g() = 0; color.b() = 0; color.a() = 1; } else { if (interp == GPI_RGB) { color.r() = colorEntry->c1; color.g() = colorEntry->c2; color.b() = colorEntry->c3; color.a() = colorEntry->c4; } else if (interp == GPI_CMYK) { // from wikipedia.org short C = colorEntry->c1; short M = colorEntry->c2; short Y = colorEntry->c3; short K = colorEntry->c4; color.r() = 255 - C*(255 - K) - K; color.g() = 255 - M*(255 - K) - K; color.b() = 255 - Y*(255 - K) - K; color.a() = 255; } else if (interp == GPI_HLS) { // from easyrgb.com float H = colorEntry->c1; float S = colorEntry->c3; float L = colorEntry->c2; float R, G, B; if ( S == 0 ) //HSL values = 0 - 1 { R = L; //RGB results = 0 - 1 G = L; B = L; } else { float var_2, var_1; if ( L < 0.5 ) var_2 = L * ( 1 + S ); else var_2 = ( L + S ) - ( S * L ); var_1 = 2 * L - var_2; R = Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) ); G = Hue_2_RGB( var_1, var_2, H ); B = Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) ); } color.r() = static_cast<unsigned char>(R*255.0f); color.g() = static_cast<unsigned char>(G*255.0f); color.b() = static_cast<unsigned char>(B*255.0f); color.a() = static_cast<unsigned char>(255.0f); } else if (interp == GPI_Gray) { color.r() = static_cast<unsigned char>(colorEntry->c1*255.0f); color.g() = static_cast<unsigned char>(colorEntry->c1*255.0f); color.b() = static_cast<unsigned char>(colorEntry->c1*255.0f); color.a() = static_cast<unsigned char>(255.0f); } } }
void GDALTileSource::initialize | ( | const std::string & | referenceURI, |
const Profile * | overrideProfile | ||
) | [inline, virtual] |
Initialize the TileSource. The profile should be computed and set here using setProfile()
Implements osgEarth::TileSource.
Definition at line 640 of file ReaderWriterGDAL.cpp.
{ GDAL_SCOPED_LOCK; if ( !_options.url().isSet() || _options.url()->empty() ) { OE_WARN << LC << "No URL or directory specified " << std::endl; return; } URI uri = _options.url().value(); //Find the full path to the URL //If we have a relative path and the map file contains a server address, just concat the server path and the _url together if (osgEarth::isRelativePath(uri.full()) && osgDB::containsServerAddress(referenceURI)) { uri = URI(osgDB::getFilePath(referenceURI) + std::string("/") + uri.full()); } //If the path doesn't contain a server address, get the full path to the file. if (!osgDB::containsServerAddress(uri.full())) { uri = URI(uri.full(), referenceURI); } StringTokenizer izer( ";" ); StringVector exts; izer.tokenize( *_options.extensions(), exts ); //std::vector<std::string> exts; //tokenize( _options.extensions().value(), exts, ";"); for (unsigned int i = 0; i < exts.size(); ++i) { OE_DEBUG << LC << "Using Extension: " << exts[i] << std::endl; } std::vector<std::string> files; getFiles(uri.full(), exts, files); OE_INFO << LC << "Driver found " << files.size() << " files:" << std::endl; for (unsigned int i = 0; i < files.size(); ++i) { OE_INFO << LC << "" << files[i] << std::endl; } if (files.empty()) { OE_WARN << LC << "Could not find any valid files " << std::endl; return; } //If we found more than one file, try to combine them into a single logical dataset if (files.size() > 1) { _srcDS = (GDALDataset*)build_vrt(files, HIGHEST_RESOLUTION); if (!_srcDS) { OE_WARN << "[osgEarth::GDAL] Failed to build VRT from input datasets" << std::endl; return; } } else { //If we couldn't build a VRT, just try opening the file directly //Open the dataset _srcDS = (GDALDataset*)GDALOpen( files[0].c_str(), GA_ReadOnly ); if ( !_srcDS ) { OE_WARN << LC << "Failed to open dataset " << files[0] << std::endl; return; } } //Create a spatial reference for the source. const char* srcProj = _srcDS->GetProjectionRef(); if ( srcProj != 0L && overrideProfile != 0L ) { OE_WARN << LC << "WARNING, overriding profile of a source that already defines its own SRS (" << this->getName() << ")" << std::endl; } osg::ref_ptr<const SpatialReference> src_srs; if ( overrideProfile ) { src_srs = overrideProfile->getSRS(); } else if ( srcProj ) { src_srs = SpatialReference::create( srcProj ); } // assert SRS is present if ( !src_srs.valid() ) { // not found in the dataset; try loading a .prj file std::string prjLocation = osgDB::getNameLessExtension( uri.full() ) + std::string(".prj"); std::string wkt; if ( HTTPClient::readString( prjLocation, wkt ) == HTTPClient::RESULT_OK ) { src_srs = SpatialReference::create( wkt ); } if ( !src_srs.valid() ) { OE_WARN << LC << "Dataset has no spatial reference information: " << uri.full() << std::endl; return; } } const Profile* profile = NULL; if ( overrideProfile ) { profile = overrideProfile; } if ( !profile && src_srs->isGeographic() ) { profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile(); } //Note: Can cause odd rendering artifacts if we have a dataset that is mercator that doesn't encompass the whole globe // if we take on the global profile. /* if ( !profile && src_srs->isMercator() ) { profile = osgEarth::Registry::instance()->getGlobalMercatorProfile(); }*/ std::string warpedSRSWKT; if ( profile && !profile->getSRS()->isEquivalentTo( src_srs.get() ) ) { if ( profile->getSRS()->isGeographic() && (src_srs->isNorthPolar() || src_srs->isSouthPolar()) ) { _warpedDS = (GDALDataset*)GDALAutoCreateWarpedVRTforPolarStereographic( _srcDS, src_srs->getWKT().c_str(), profile->getSRS()->getWKT().c_str(), GRA_NearestNeighbour, 5.0, NULL); } else { _warpedDS = (GDALDataset*)GDALAutoCreateWarpedVRT( _srcDS, src_srs->getWKT().c_str(), profile->getSRS()->getWKT().c_str(), GRA_NearestNeighbour, 5.0, NULL); } if ( _warpedDS ) { warpedSRSWKT = _warpedDS->GetProjectionRef(); } //GDALAutoCreateWarpedVRT(srcDS, src_wkt.c_str(), t_srs.c_str(), GRA_NearestNeighbour, 5.0, NULL); } else { _warpedDS = _srcDS; warpedSRSWKT = src_srs->getWKT(); } //Get the _geotransform if (overrideProfile) { _geotransform[0] = overrideProfile->getExtent().xMin(); //Top left x _geotransform[1] = overrideProfile->getExtent().width() / (double)_warpedDS->GetRasterXSize();//pixel width _geotransform[2] = 0; _geotransform[3] = overrideProfile->getExtent().yMax(); //Top left y _geotransform[4] = 0; _geotransform[5] = -overrideProfile->getExtent().height() / (double)_warpedDS->GetRasterYSize();//pixel height } else { _warpedDS->GetGeoTransform(_geotransform); } GDALInvGeoTransform(_geotransform, _invtransform); //Compute the extents // polar needs a special case when combined with geographic if ( profile && profile->getSRS()->isGeographic() && (src_srs->isNorthPolar() || src_srs->isSouthPolar()) ) { double ll_lon, ll_lat, ul_lon, ul_lat, ur_lon, ur_lat, lr_lon, lr_lat; pixelToGeo(0.0, 0.0, ul_lon, ul_lat ); pixelToGeo(0.0, _warpedDS->GetRasterYSize(), ll_lon, ll_lat); pixelToGeo(_warpedDS->GetRasterXSize(), _warpedDS->GetRasterYSize(), lr_lon, lr_lat); pixelToGeo(_warpedDS->GetRasterXSize(), 0.0, ur_lon, ur_lat); _extentsMin.x() = osg::minimum( ll_lon, osg::minimum( ul_lon, osg::minimum( ur_lon, lr_lon ) ) ); _extentsMax.x() = osg::maximum( ll_lon, osg::maximum( ul_lon, osg::maximum( ur_lon, lr_lon ) ) ); if ( src_srs->isNorthPolar() ) { _extentsMin.y() = osg::minimum( ll_lat, osg::minimum( ul_lat, osg::minimum( ur_lat, lr_lat ) ) ); _extentsMax.y() = 90.0; } else { _extentsMin.y() = -90.0; _extentsMax.y() = osg::maximum( ll_lat, osg::maximum( ul_lat, osg::maximum( ur_lat, lr_lat ) ) ); } } else { pixelToGeo(0.0, _warpedDS->GetRasterYSize(), _extentsMin.x(), _extentsMin.y()); pixelToGeo(_warpedDS->GetRasterXSize(), 0.0, _extentsMax.x(), _extentsMax.y()); } OE_INFO << LC << "Geo extents: " << _extentsMin.x() << ", " << _extentsMin.y() << " => " << _extentsMax.x() << ", " << _extentsMax.y() << std::endl; if ( !profile ) { profile = Profile::create( warpedSRSWKT, //_warpedDS->GetProjectionRef(), _extentsMin.x(), _extentsMin.y(), _extentsMax.x(), _extentsMax.y() ); OE_INFO << LC << "" << uri.full() << " is projected, SRS = " << warpedSRSWKT << std::endl; //<< _warpedDS->GetProjectionRef() << std::endl; } //Compute the min and max data levels double resolutionX = (_extentsMax.x() - _extentsMin.x()) / (double)_warpedDS->GetRasterXSize(); double resolutionY = (_extentsMax.y() - _extentsMin.y()) / (double)_warpedDS->GetRasterYSize(); double maxResolution = osg::minimum(resolutionX, resolutionY); OE_INFO << LC << "Resolution= " << resolutionX << "x" << resolutionY << " max=" << maxResolution << std::endl; if (_options.maxDataLevel().isSet()) { _maxDataLevel = _options.maxDataLevel().value(); OE_INFO << "Using override max data level " << _maxDataLevel << std::endl; } else { unsigned int max_level = 30; for (unsigned int i = 0; i < max_level; ++i) { _maxDataLevel = i; double w, h; profile->getTileDimensions(i, w, h); double resX = (w / (double)_options.tileSize().value() ); double resY = (h / (double)_options.tileSize().value() ); if (resX < maxResolution || resY < maxResolution) { break; } } OE_INFO << LC << "Max Data Level: " << _maxDataLevel << std::endl; } // record the data extent in profile space: GeoExtent local_extent( SpatialReference::create( warpedSRSWKT ), //_warpedDS->GetProjectionRef() ), _extentsMin.x(), _extentsMin.y(), _extentsMax.x(), _extentsMax.y() ); GeoExtent profile_extent = local_extent.transform( profile->getSRS() ); getDataExtents().push_back( DataExtent(profile_extent, 0, _maxDataLevel) ); OE_INFO << LC << "Data Extents: " << profile_extent.toString() << std::endl; //Set the profile setProfile( profile ); }
bool GDALTileSource::intersects | ( | const TileKey & | key | ) | [inline] |
Definition at line 1506 of file ReaderWriterGDAL.cpp.
{ //Get the native extents of the tile double xmin, ymin, xmax, ymax; key.getExtent().getBounds(xmin, ymin, xmax, ymax); return ! ( xmin >= _extentsMax.x() || xmax <= _extentsMin.x() || ymin >= _extentsMax.y() || ymax <= _extentsMin.y() ); }
bool GDALTileSource::isValidValue | ( | float | v, |
GDALRasterBand * | band | ||
) | [inline] |
Definition at line 1299 of file ReaderWriterGDAL.cpp.
{ GDAL_SCOPED_LOCK; float bandNoData = -32767.0f; int success; float value = band->GetNoDataValue(&success); if (success) { bandNoData = value; } //Check to see if the value is equal to the bands specified no data if (bandNoData == v) return false; //Check to see if the value is equal to the user specified nodata value if (getNoDataValue() == v) return false; //Check to see if the user specified a custom min/max if (v < getNoDataMinValue()) return false; if (v > getNoDataMaxValue()) return false; //Check within a sensible range if (v < -32000) return false; if (v > 32000) return false; return true; }
void GDALTileSource::pixelToGeo | ( | double | x, |
double | y, | ||
double & | geoX, | ||
double & | geoY | ||
) | [inline] |
Definition at line 1013 of file ReaderWriterGDAL.cpp.
{ geoX = _geotransform[0] + _geotransform[1] * x + _geotransform[2] * y; geoY = _geotransform[3] + _geotransform[4] * x + _geotransform[5] * y; }
osg::Vec2d GDALTileSource::_extentsMax [private] |
Definition at line 1524 of file ReaderWriterGDAL.cpp.
osg::Vec2d GDALTileSource::_extentsMin [private] |
Definition at line 1523 of file ReaderWriterGDAL.cpp.
double GDALTileSource::_geotransform[6] [private] |
Definition at line 1520 of file ReaderWriterGDAL.cpp.
double GDALTileSource::_invtransform[6] [private] |
Definition at line 1521 of file ReaderWriterGDAL.cpp.
unsigned int GDALTileSource::_maxDataLevel [private] |
Definition at line 1534 of file ReaderWriterGDAL.cpp.
const GDALOptions GDALTileSource::_options [private] |
Reimplemented from osgEarth::TileSource.
Definition at line 1531 of file ReaderWriterGDAL.cpp.
GDALDataset* GDALTileSource::_srcDS [private] |
Definition at line 1518 of file ReaderWriterGDAL.cpp.
GDALDataset* GDALTileSource::_warpedDS [private] |
Definition at line 1519 of file ReaderWriterGDAL.cpp.