From de83752acda1445a8710dcf057df0931ed6969bf Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 3 Feb 2004 16:51:44 +0000 Subject: [PATCH] Added support for better merging of height fields which ignores NoData values. Fixed various problems with handing of coordinates systems. Added support for halving levels in x and y respectively, in addition to the previous divide in both x and y at the same time, which allows long line/short tall regions to be handled better. --- examples/osgdem/DataSet.cpp | 257 ++++++++++++++++++++++++++++++------ examples/osgdem/DataSet.h | 3 +- examples/osgdem/osgdem.cpp | 2 +- 3 files changed, 216 insertions(+), 46 deletions(-) diff --git a/examples/osgdem/DataSet.cpp b/examples/osgdem/DataSet.cpp index 72d91935e..1bf794df1 100644 --- a/examples/osgdem/DataSet.cpp +++ b/examples/osgdem/DataSet.cpp @@ -46,33 +46,34 @@ bool areCoordinateSystemEquivilant(const osgTerrain::CoordinateSystem* lhs,const // use compare on ProjectionRef strings. if (*lhs == *rhs) return true; - char** stringList = new char* [2]; - stringList[0] = strdup(lhs->getProjectionRef().c_str()); - stringList[1] = 0; + // set up LHS SpatialReference + char* projection_string = strdup(lhs->getProjectionRef().c_str()); + char* importString = projection_string; OGRSpatialReference lhsSR; - lhsSR.importFromWkt(stringList); + lhsSR.importFromWkt(&importString); - free(stringList[0]); - stringList[0] = 0; + free(projection_string); + + // set up RHS SpatialReference + projection_string = strdup(rhs->getProjectionRef().c_str()); + importString = projection_string; OGRSpatialReference rhsSR; - stringList[0] = strdup(lhs->getProjectionRef().c_str()); - stringList[1] = 0; + rhsSR.importFromWkt(&importString); - rhsSR.importFromWkt(stringList); - - free(stringList[0]); - stringList[0] = 0; + free(projection_string); - delete stringList; - int result = lhsSR.IsSame(&rhsSR); -// std::cout<<"areCoordinateSystemEquivilant "<GetNoDataValue(&success); + if (success) + { + std::cout<<"We have NoDataValue = "<GetOffset(&success); + if (success) + { + std::cout<<"We have Offset = "<GetScale(&success); + if (success) + { + std::cout<<"We have Scale = "<getHeight(destX,destY+destHeight-1))); // start at the top - - unsigned int numBytesPerZvalue = 4; - int lineSpace=-(hf->getNumColumns()*numBytesPerZvalue); //and work down (note - sign) std::cout<<"reading height field"<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,floatdata,destWidth,destHeight,GDT_Float32,numBytesPerZvalue,lineSpace); + bandSelected->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,heightData,destWidth,destHeight,GDT_Float32,0,0); std::cout<<" scaling height field"<=destY;--r) { for(int c=destX;cgetHeight(c,r)==0.0) std::cout<<"."; -// else std::cout<<"** "<getHeight(c,r)<<" **"<setHeight(c,r,hf->getHeight(c,r)*heightRatio); + float h = *heightPtr++; + if (h!=noDataValue) hf->setHeight(c,r,offset + h*scale); + else if (!ignoreNoDataValue) hf->setHeight(c,r,noDataValueFill); } } + + delete [] heightData; + } - } } @@ -1372,6 +1421,43 @@ void DataSet::DestinationTile::equalizeBoundaries() equalizeEdge(ABOVE); } + +void DataSet::DestinationTile::optimizeResolution() +{ + if (_terrain.valid() && _terrain->_heightField.valid()) + { + osg::HeightField* hf = _terrain->_heightField.get(); + + // compute min max of height field + float minHeight = hf->getHeight(0,0); + float maxHeight = minHeight; + for(unsigned int r=0;rgetNumRows();++r) + { + for(unsigned int c=0;cgetNumColumns();++c) + { + float h = hf->getHeight(c,r); + if (hmaxHeight) maxHeight = h; + } + } + + if (minHeight==maxHeight) + { + std::cout<<"******* We have a flat tile ******* "<allocate(2,2); + hf->setOrigin(osg::Vec3(_extents.xMin(),_extents.yMin(),0.0f)); + hf->setXInterval(_extents.xMax()-_extents.xMin()); + hf->setYInterval(_extents.yMax()-_extents.yMin()); + hf->setHeight(0,0,minHeight); + hf->setHeight(1,0,minHeight); + hf->setHeight(1,1,minHeight); + hf->setHeight(0,1,minHeight); + + } + } +} + osg::Node* DataSet::DestinationTile::createScene() { @@ -1436,9 +1522,12 @@ osg::Node* DataSet::DestinationTile::createScene() void DataSet::DestinationTile::readFrom(CompositeSource* sourceGraph) { + allocate(); + std::cout<<"DestinationTile::readFrom() "<getSourceData(); if (data) { @@ -1447,6 +1536,9 @@ void DataSet::DestinationTile::readFrom(CompositeSource* sourceGraph) if (_terrain.valid()) data->read(*_terrain); } } + + optimizeResolution(); + } void DataSet::DestinationTile::addRequiredResolutions(CompositeSource* sourceGraph) @@ -1731,7 +1823,7 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord DataSet::CompositeDestination* destinationGraph = new DataSet::CompositeDestination(cs,extents); - destinationGraph->_maxVisibleDistance = extents.radius()*10.0f; + destinationGraph->_maxVisibleDistance = extents.radius()*11.0f; // first create the topmost tile @@ -1739,6 +1831,10 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord std::ostringstream os; os << _tileBasename << "_L"<getProjectionRef()<_name = os.str(); tile->_dataSet = this; @@ -1750,7 +1846,6 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord tile->setMaximumImagerySize(maxImageSize,maxImageSize); tile->setMaximumTerrainSize(maxTerrainSize,maxTerrainSize); tile->computeMaximumSourceResolution(_sourceGraph.get()); - tile->allocate(); insertTileToQuadMap(tile); @@ -1794,6 +1889,14 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord unsigned int newX = currentX*2; unsigned int newY = currentY*2; + if (needToDivideX && needToDivideY) + { + float aspectRatio = (extents.yMax()- extents.yMin())/(extents.xMax()- extents.xMin()); + + if (aspectRatio>1.414) needToDivideX = false; + else if (aspectRatio<.707) needToDivideY = false; + } + if (needToDivideX && needToDivideY) { std::cout<<"Need to Divide X + Y for level "<_maxVisibleDistance = cutOffDistance; } - } else if (needToDivideX) { std::cout<<"Need to Divide X only"<_children.push_back(createDestinationGraph(cs, + left, + maxImageSize, + maxTerrainSize, + newLevel, + newX, + newY, + maxNumLevels)); + + destinationGraph->_children.push_back(createDestinationGraph(cs, + right, + maxImageSize, + maxTerrainSize, + newLevel, + newX+1, + newY, + maxNumLevels)); + + + // Set all there max distance to the same value to ensure the same LOD bining. + float cutOffDistance = destinationGraph->_maxVisibleDistance*0.5f; + + for(CompositeDestination::ChildList::iterator citr=destinationGraph->_children.begin(); + citr!=destinationGraph->_children.end(); + ++citr) + { + (*citr)->_maxVisibleDistance = cutOffDistance; + } + } else if (needToDivideY) { std::cout<<"Need to Divide Y only"<_children.push_back(createDestinationGraph(cs, + bottom, + maxImageSize, + maxTerrainSize, + newLevel, + newX, + newY, + maxNumLevels)); + + destinationGraph->_children.push_back(createDestinationGraph(cs, + top, + maxImageSize, + maxTerrainSize, + newLevel, + newX, + newY+1, + maxNumLevels)); + + // Set all there max distance to the same value to ensure the same LOD bining. + float cutOffDistance = destinationGraph->_maxVisibleDistance*0.5f; + + for(CompositeDestination::ChildList::iterator citr=destinationGraph->_children.begin(); + citr!=destinationGraph->_children.end(); + ++citr) + { + (*citr)->_maxVisibleDistance = cutOffDistance; + } + } else { diff --git a/examples/osgdem/DataSet.h b/examples/osgdem/DataSet.h index e4f47dd62..36a899d46 100644 --- a/examples/osgdem/DataSet.h +++ b/examples/osgdem/DataSet.h @@ -669,9 +669,10 @@ class DataSet : public osg::Referenced void equalizeCorner(Position position); void equalizeEdge(Position position); - void equalizeBoundaries(); + void optimizeResolution(); + osg::Node* createScene(); diff --git a/examples/osgdem/osgdem.cpp b/examples/osgdem/osgdem.cpp index 13f2c2e27..db31c90d6 100644 --- a/examples/osgdem/osgdem.cpp +++ b/examples/osgdem/osgdem.cpp @@ -115,7 +115,7 @@ int main( int argc, char **argv ) } - if (false) + if (true) { // set up the coordinate system OGRSpatialReference oSRS;