Files
OpenSceneGraph/src/osgPlugins/gdal/DataSetLayer.cpp
2012-03-21 17:36:20 +00:00

223 lines
7.0 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2007 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include "DataSetLayer.h"
#include <osg/Notify>
#include <osg/io_utils>
#include <cpl_string.h>
#include <gdalwarper.h>
#include <ogr_spatialref.h>
#include <osgDB/ImageOptions>
using namespace GDALPlugin;
DataSetLayer::DataSetLayer():
_dataset(0), _gdalReader(0)
{
}
DataSetLayer::DataSetLayer(const std::string& fileName):
_dataset(0), _gdalReader(0)
{
setFileName(fileName);
open();
}
DataSetLayer::DataSetLayer(const DataSetLayer& dataSetLayer,const osg::CopyOp& copyop):
Layer(dataSetLayer), _gdalReader(dataSetLayer._gdalReader)
{
if (dataSetLayer._dataset) open();
}
DataSetLayer::~DataSetLayer()
{
close();
}
void DataSetLayer::open()
{
if (_dataset) return;
if (getFileName().empty()) return;
OSG_NOTICE<<"DataSetLayer::open()"<<getFileName()<<std::endl;
_dataset = static_cast<GDALDataset*>(GDALOpen(getFileName().c_str(),GA_ReadOnly));
setUpLocator();
}
void DataSetLayer::close()
{
OSG_NOTICE<<"DataSetLayer::close()"<<getFileName()<<std::endl;
if (_dataset)
{
GDALClose(static_cast<GDALDatasetH>(_dataset));
_dataset = 0;
}
}
unsigned int DataSetLayer::getNumColumns() const
{
return _dataset!=0 ? _dataset->GetRasterXSize() : 0;
}
unsigned int DataSetLayer::getNumRows() const
{
return _dataset!=0 ? _dataset->GetRasterYSize() : 0;
}
osgTerrain::ImageLayer* DataSetLayer::extractImageLayer(unsigned int sourceMinX, unsigned int sourceMinY, unsigned int sourceMaxX, unsigned int sourceMaxY, unsigned int targetWidth, unsigned int targetHeight)
{
if (!_dataset || sourceMaxX<sourceMinX || sourceMaxY<sourceMinY) return 0;
if (!_gdalReader) return 0;
osg::ref_ptr<osgDB::ImageOptions> imageOptions = new osgDB::ImageOptions;
imageOptions->_sourceImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
imageOptions->_sourcePixelWindow.windowX = sourceMinX;
imageOptions->_sourcePixelWindow.windowY = sourceMinY;
imageOptions->_sourcePixelWindow.windowWidth = sourceMaxX-sourceMinX;
imageOptions->_sourcePixelWindow.windowHeight = sourceMaxY-sourceMinY;
imageOptions->_destinationPixelWindow.windowX = 0;
imageOptions->_destinationPixelWindow.windowY = 0;
imageOptions->_destinationPixelWindow.windowWidth = targetWidth;
imageOptions->_destinationPixelWindow.windowHeight = targetHeight;
osgDB::ReaderWriter::ReadResult result = _gdalReader->readImage(getFileName(),imageOptions.get());
osg::Image* image = result.getImage();
if (!image) return 0;
osgTerrain::ImageLayer* layer = new osgTerrain::ImageLayer;
layer->setFileName(getFileName());
layer->setImage(image);
return layer;
}
void DataSetLayer::setGdalReader(const osgDB::ReaderWriter* rw)
{
_gdalReader = const_cast<osgDB::ReaderWriter*>(rw);
}
void DataSetLayer::setUpLocator()
{
if (!isOpen()) return;
const char* pszSourceSRS = _dataset->GetProjectionRef();
if (!pszSourceSRS || strlen(pszSourceSRS)==0) pszSourceSRS = _dataset->GetGCPProjection();
osg::ref_ptr<osgTerrain::Locator> locator = new osgTerrain::Locator;
if (pszSourceSRS)
{
locator->setFormat("WKT");
locator->setCoordinateSystem(pszSourceSRS);
}
osg::Matrixd matrix;
double geoTransform[6];
if (_dataset->GetGeoTransform(geoTransform)==CE_None)
{
#ifdef SHIFT_RASTER_BY_HALF_CELL
// shift the transform to the middle of the cell if a raster interpreted as vector
if (data->_dataType == VECTOR)
{
geoTransform[0] += 0.5 * geoTransform[1];
geoTransform[3] += 0.5 * geoTransform[5];
}
#endif
matrix.set( geoTransform[1], geoTransform[4], 0.0, 0.0,
geoTransform[2], geoTransform[5], 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
geoTransform[0], geoTransform[3], 0.0, 1.0);
int nPixels = _dataset->GetRasterXSize();
int nLines = _dataset->GetRasterYSize();
locator->setTransform(
osg::Matrixd::scale(static_cast<double>(nPixels-1), static_cast<double>(nLines-1), 1.0) *
matrix);
locator->setDefinedInFile(true);
setLocator(locator.get());
}
else if (_dataset->GetGCPCount()>0 && _dataset->GetGCPProjection())
{
OSG_NOTICE << " Using GCP's"<< std::endl;
/* -------------------------------------------------------------------- */
/* Create a transformation object from the source to */
/* destination coordinate system. */
/* -------------------------------------------------------------------- */
void *hTransformArg =
GDALCreateGenImgProjTransformer( _dataset, pszSourceSRS,
NULL, pszSourceSRS,
TRUE, 0.0, 1 );
if ( hTransformArg == NULL )
{
OSG_NOTICE<<" failed to create transformer"<<std::endl;
return;
}
/* -------------------------------------------------------------------- */
/* Get approximate output definition. */
/* -------------------------------------------------------------------- */
double adfDstGeoTransform[6];
int nPixels=0, nLines=0;
if( GDALSuggestedWarpOutput( _dataset,
GDALGenImgProjTransform, hTransformArg,
adfDstGeoTransform, &nPixels, &nLines )
!= CE_None )
{
OSG_NOTICE<<" failed to create warp"<<std::endl;
return;
}
GDALDestroyGenImgProjTransformer( hTransformArg );
matrix.set( adfDstGeoTransform[1], adfDstGeoTransform[4], 0.0, 0.0,
adfDstGeoTransform[2], adfDstGeoTransform[5], 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
adfDstGeoTransform[0], adfDstGeoTransform[3], 0.0, 1.0);
locator->setTransform(
osg::Matrixd::scale(static_cast<double>(nPixels-1), static_cast<double>(nLines-1), 1.0) *
matrix);
locator->setDefinedInFile(true);
setLocator(locator.get());
}
else
{
OSG_INFO << "DataSetLayer::setUpLocator(), No GeoTransform or GCP's - unable to compute position in space"<< std::endl;
}
}