From 8a4caa0a594d0b1c0ce7bd60fa68ca12a43030c7 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 4 Dec 2007 14:46:08 +0000 Subject: [PATCH] Added optional double support via new Vec3dArray support in osg::Geometry. To enable double usage set the option string "double" i.e. osgviewer myshapefile.shf -O "double" --- src/osgPlugins/shp/ESRIShapeParser.cpp | 78 ++++++++++---------- src/osgPlugins/shp/ESRIShapeParser.h | 67 ++++++++++++++++- src/osgPlugins/shp/ESRIShapeReaderWriter.cpp | 8 +- 3 files changed, 113 insertions(+), 40 deletions(-) diff --git a/src/osgPlugins/shp/ESRIShapeParser.cpp b/src/osgPlugins/shp/ESRIShapeParser.cpp index 2e10fcc6f..edcb2f667 100644 --- a/src/osgPlugins/shp/ESRIShapeParser.cpp +++ b/src/osgPlugins/shp/ESRIShapeParser.cpp @@ -12,8 +12,9 @@ using namespace ESRIShape; -ESRIShapeParser::ESRIShapeParser( const std::string fileName ): - _valid(false) +ESRIShapeParser::ESRIShapeParser( const std::string fileName, bool useDouble ): + _valid(false), + _useDouble(useDouble) { int fd = 0; if( !fileName.empty() ) @@ -209,8 +210,11 @@ osg::Geode *ESRIShapeParser::getGeode() void ESRIShapeParser::_combinePointToMultipoint() { if( !_valid ) return; + + osg::notify(osg::NOTICE)<<"_combinePointToMultipoint()"< coords = new osg::Vec3Array; unsigned int numDrawables = _geode->getNumDrawables(); for( unsigned int i = 0; i < numDrawables; i++ ) @@ -218,9 +222,7 @@ void ESRIShapeParser::_combinePointToMultipoint() osg::Geometry *geom = dynamic_cast(_geode->getDrawable(i)); if( geom != 0L ) { - osg::Vec3Array *va = dynamic_cast(geom->getVertexArray()); - if( va != 0L ) - coords->push_back( va->front() ); + coords.add( geom->getVertexArray(), 0 ); } } @@ -228,7 +230,7 @@ void ESRIShapeParser::_combinePointToMultipoint() osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); - geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size())); + geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size())); _geode->addDrawable( geometry.get() ); } @@ -239,8 +241,9 @@ void ESRIShapeParser::_process( const std::vector &pts ) std::vector::const_iterator p; for( p = pts.begin(); p != pts.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; - coords->push_back( osg::Vec3( p->x, p->y, 0.0 )); + ArrayHelper coords(_useDouble); + + coords.add( p->x, p->y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1)); @@ -258,13 +261,14 @@ void ESRIShapeParser::_process( const std::vector &mpts ) std::vector::const_iterator p; for( p = mpts.begin(); p != mpts.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); + for( int i = 0; i < p->numPoints ; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); - geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size())); + geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size())); _geode->addDrawable( geometry.get() ); } @@ -277,11 +281,11 @@ void ESRIShapeParser::_process(const std::vector &lines ) std::vector::const_iterator p; for( p = lines.begin(); p != lines.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); @@ -307,16 +311,14 @@ void ESRIShapeParser::_process( const std::vector &polys ) std::vector::const_iterator p; for( p = polys.begin(); p != polys.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); - - for( i = 0; i < p->numParts; i++ ) { int index = p->parts[i]; @@ -347,8 +349,8 @@ void ESRIShapeParser::_process( const std::vector &ptms ) std::vector::const_iterator p; for( p = ptms.begin(); p != ptms.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; - coords->push_back( osg::Vec3( p->x, p->y, 0.0 )); + ArrayHelper coords(_useDouble); + coords.add( p->x, p->y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1)); @@ -365,15 +367,15 @@ void ESRIShapeParser::_process( const std::vector &mptms std::vector::const_iterator p; for( p = mptms.begin(); p != mptms.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); // Here is where we would use the 'M' (?) for( int i = 0; i < p->numPoints ; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); - geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size())); + geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size())); _geode->addDrawable( geometry.get() ); } @@ -386,11 +388,11 @@ void ESRIShapeParser::_process(const std::vector &linems ) std::vector::const_iterator p; for( p = linems.begin(); p != linems.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); @@ -416,10 +418,10 @@ void ESRIShapeParser::_process( const std::vector &polyms ) std::vector::const_iterator p; for( p = polyms.begin(); p != polyms.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 )); + coords.add( p->points[i].x, p->points[i].y, 0.0 ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); @@ -445,8 +447,8 @@ void ESRIShapeParser::_process( const std::vector &ptzs ) std::vector::const_iterator p; for( p = ptzs.begin(); p != ptzs.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; - coords->push_back( osg::Vec3( p->x, p->y, p->z )); + ArrayHelper coords(_useDouble); + coords.add( p->x, p->y, p->z ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1)); @@ -463,15 +465,15 @@ void ESRIShapeParser::_process( const std::vector &mptzs std::vector::const_iterator p; for( p = mptzs.begin(); p != mptzs.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); // Here is where we would use the 'M' (?) for( int i = 0; i < p->numPoints ; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] )); + coords.add( p->points[i].x, p->points[i].y, p->zArray[i] ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); - geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size())); + geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size())); _geode->addDrawable( geometry.get() ); } @@ -484,11 +486,11 @@ void ESRIShapeParser::_process(const std::vector &linezs ) std::vector::const_iterator p; for( p = linezs.begin(); p != linezs.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] )); + coords.add( p->points[i].x, p->points[i].y, p->zArray[i] ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); @@ -514,11 +516,11 @@ void ESRIShapeParser::_process( const std::vector &polyzs ) std::vector::const_iterator p; for( p = polyzs.begin(); p != polyzs.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] )); + coords.add( p->points[i].x, p->points[i].y, p->zArray[i] ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); @@ -544,11 +546,11 @@ void ESRIShapeParser::_process( const std::vector &mpatch std::vector::const_iterator p; for( p = mpatches.begin(); p != mpatches.end(); p++ ) { - osg::ref_ptr coords = new osg::Vec3Array; + ArrayHelper coords(_useDouble); int i; for( i = 0; i < p->numPoints; i++ ) - coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] )); + coords.add( p->points[i].x, p->points[i].y, p->zArray[i] ); osg::ref_ptr geometry = new osg::Geometry; geometry->setVertexArray(coords.get()); diff --git a/src/osgPlugins/shp/ESRIShapeParser.h b/src/osgPlugins/shp/ESRIShapeParser.h index 1af1586c5..ca10e74fa 100644 --- a/src/osgPlugins/shp/ESRIShapeParser.h +++ b/src/osgPlugins/shp/ESRIShapeParser.h @@ -8,15 +8,80 @@ namespace ESRIShape { +class ArrayHelper +{ + public: + ArrayHelper(bool useDouble) + { + if (useDouble) _vec3darray = new osg::Vec3dArray; + else _vec3farray = new osg::Vec3Array; + } + + osg::Array* get() { return _vec3farray.valid() ? + static_cast(_vec3farray.get()) : + static_cast(_vec3darray.get()); } + + unsigned int size() { return _vec3farray.valid() ? + _vec3farray->size() : + _vec3darray->size(); } + + void add(double x, double y, double z) + { + if (_vec3farray.valid()) _vec3farray->push_back(osg::Vec3(x,y,z)); + else _vec3darray->push_back(osg::Vec3d(x,y,z)); + } + + void add(const osg::Vec3& v) + { + if (_vec3farray.valid()) _vec3farray->push_back(v); + else _vec3darray->push_back(osg::Vec3d(v.x(),v.y(),v.z())); + } + + void add(const osg::Vec3d& v) + { + if (_vec3farray.valid()) _vec3farray->push_back(osg::Vec3(v.x(),v.y(),v.z())); + else _vec3darray->push_back(v); + } + + void add(osg::Array* array, unsigned int index) + { + osg::Vec3Array* vec3Array = dynamic_cast(array); + if (vec3Array && indexsize()) add((*vec3Array)[index]); + + osg::Vec3dArray* vec3dArray = dynamic_cast(array); + if (vec3dArray && indexsize()) add((*vec3dArray)[index]); + } + + osg::ref_ptr _vec3farray; + osg::ref_ptr _vec3darray; +}; + + class ESRIShapeParser { public: - ESRIShapeParser( const std::string fileName="" ); + + ESRIShapeParser( const std::string fileName, bool useDouble); osg::Geode *getGeode(); +#if 0 +#if 1 + typedef osg::Vec3d ShapeVec3; + typedef osg::Vec3dArray ShapeVec3Array; +#else + typedef osg::Vec3 ShapeVec3; + typedef osg::Vec3Array ShapeVec3Array; +#endif +#endif + private: + + + bool _valid; + bool _useDouble; + osg::ref_ptr _geode; void _combinePointToMultipoint(); diff --git a/src/osgPlugins/shp/ESRIShapeReaderWriter.cpp b/src/osgPlugins/shp/ESRIShapeReaderWriter.cpp index 03d52a0e0..a292e5bb0 100644 --- a/src/osgPlugins/shp/ESRIShapeReaderWriter.cpp +++ b/src/osgPlugins/shp/ESRIShapeReaderWriter.cpp @@ -29,7 +29,13 @@ class ESRIShapeReaderWriter : public osgDB::ReaderWriter std::string fileName = osgDB::findDataFile(file, options); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; - ESRIShape::ESRIShapeParser sp(fileName); + bool useDouble = false; + if (options && options->getOptionString().find("double")!=std::string::npos) + { + useDouble = true; + } + + ESRIShape::ESRIShapeParser sp(fileName, useDouble); return sp.getGeode(); }