diff --git a/src/osgTerrain/DataSet.cpp b/src/osgTerrain/DataSet.cpp index 35e67eaa0..f15d0a749 100644 --- a/src/osgTerrain/DataSet.cpp +++ b/src/osgTerrain/DataSet.cpp @@ -212,6 +212,54 @@ bool areCoordinateSystemEquivalent(const osg::CoordinateSystemNode* lhs,const os return result ? true : false; } +float getInterpolatedValue(GDALRasterBand *band, double x, double y) +{ + double geoTransform[6]; + band->GetDataset()->GetGeoTransform(geoTransform); + double invTransform[6]; + GDALInvGeoTransform(geoTransform, invTransform); + double r, c; + GDALApplyGeoTransform(invTransform, x, y, &c, &r); + + int numRows = band->GetYSize(); + int numCols = band->GetXSize(); + + int rowMin = osg::maximum((int)floor(r), 0); + int rowMax = osg::minimum((int)ceil(r), numRows-1); + int colMin = osg::maximum((int)floor(c), 0); + int colMax = osg::minimum((int)ceil(c), numCols-1); + + 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); + + int success = 0; + float noDataValue = band->GetNoDataValue(&success); + if (success) + { + if (llHeight == noDataValue) llHeight = 0.0f; + if (ulHeight == noDataValue) ulHeight = 0.0f; + if (lrHeight == noDataValue) lrHeight = 0.0f; + if (urHeight == noDataValue) urHeight = 0.0f; + } + + 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; + float result = (float)(w00 + w01 + w10 + w11); + return result; +} + DataSet::SourceData::~SourceData() { if (_gdalDataset) GDALClose(_gdalDataset); @@ -800,21 +848,12 @@ void DataSet::SourceData::readHeightField(DestinationData& destination) my_notify(osg::INFO)<<"Reading height field but it does not intesection destination - ignoring"<getNumColumns()*(intersect_bb.xMin()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),0); int destY = osg::maximum((int)floorf((float)destination._heightField->getNumRows()*(intersect_bb.yMin()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),0); int destWidth = osg::minimum((int)ceilf((float)destination._heightField->getNumColumns()*(intersect_bb.xMax()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),(int)destination._heightField->getNumColumns())-destX; int destHeight = osg::minimum((int)ceilf((float)destination._heightField->getNumRows()*(intersect_bb.yMax()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),(int)destination._heightField->getNumRows())-destY; - my_notify(osg::INFO)<<" copying from "<GetRasterCount(); @@ -886,97 +925,72 @@ void DataSet::SourceData::readHeightField(DestinationData& destination) } my_notify(osg::INFO)<<"********* getLinearUnits = "<RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,floatdata,destWidth,destHeight,GDT_Float32,numBytesPerZvalue,lineSpace); - //bandSelected->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,heightData,destWidth,destHeight,GDT_Float32,0,0); - bandSelected->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,heightData,readWidth,readHeight,GDT_Float32,0,0); - - - if (doResample) - { - my_notify(osg::INFO)<<"Resampling height field."<=destY;--r) + if (interpolateTerrain) { - for(int c=destX;cgetOrigin().x(); + double orig_Y = hf->getOrigin().y(); + double delta_X = hf->getXInterval(); + double delta_Y = hf->getYInterval(); + + for (int c = destX; c < endX; ++c) { - float h = *heightPtr++; - if (h!=noDataValue) hf->setHeight(c,r,offset + h*scale); - else if (!ignoreNoDataValue) hf->setHeight(c,r,noDataValueFill); - - h = hf->getHeight(c,r); + double geoX = orig_X + (delta_X * (double)c); + for (int r = destY; r < endY; ++r) + { + double geoY = orig_Y + (delta_Y * (double)r); + float h = getInterpolatedValue(bandSelected, geoX, geoY); + if (h!=noDataValue) hf->setHeight(c,r,offset + h*scale); + else if (!ignoreNoDataValue) hf->setHeight(c,r,noDataValueFill); + } } } + else + { + // compute dimensions to read from. + int windowX = osg::maximum((int)floorf((float)_numValuesX*(intersect_bb.xMin()-s_bb.xMin())/(s_bb.xMax()-s_bb.xMin())),0); + int windowY = osg::maximum((int)floorf((float)_numValuesY*(intersect_bb.yMin()-s_bb.yMin())/(s_bb.yMax()-s_bb.yMin())),0); + int windowWidth = osg::minimum((int)ceilf((float)_numValuesX*(intersect_bb.xMax()-s_bb.xMin())/(s_bb.xMax()-s_bb.xMin())),(int)_numValuesX)-windowX; + int windowHeight = osg::minimum((int)ceilf((float)_numValuesY*(intersect_bb.yMax()-s_bb.yMin())/(s_bb.yMax()-s_bb.yMin())),(int)_numValuesY)-windowY; - - delete [] heightData; - + my_notify(osg::INFO)<<" copying from "<RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,floatdata,destWidth,destHeight,GDT_Float32,numBytesPerZvalue,lineSpace); + bandSelected->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,heightData,destWidth,destHeight,GDT_Float32,0,0); + + float* heightPtr = heightData; + + for(int r=destY+destHeight-1;r>=destY;--r) + { + for(int c=destX;csetHeight(c,r,offset + h*scale); + else if (!ignoreNoDataValue) hf->setHeight(c,r,noDataValueFill); + + h = hf->getHeight(c,r); + } + } + + delete [] heightData; + } } - } }