#ifndef __GWPAGINGUTILITIES_H__ #define __GWPAGINGUTILITIES_H__ #include #include #include #include #include #include #include #include #include #include "vmpdg.h" #include "gwtypes.h" #include "sphpack.h" #include "mindb.h" #include "stratum.h" namespace geoworld { template< typename T, typename ST = mars::Numerics< T > > class TileBlock : public mars::ScalarField< T, ST > { private: TileBlock (const TileBlock & copy); public: typedef mars::ScalarFieldView< T, ST > SFType; typedef typename SFType::Offset SFOffs; using super = mars::ScalarField< T, ST >; using superview = mars::ScalarFieldView< T, ST >; const unsigned short vdim, pdim; const unsigned int vsize, psize; TileBlock (const unsigned short nTileDim) : super (nTileDim + 1, nTileDim + 1), vdim(nTileDim), pdim(nTileDim + 1), vsize(static_cast< unsigned int > (mars::SQ(nTileDim))), psize(static_cast< unsigned int > (mars::SQ(nTileDim + 1))) { assert(nTileDim > 0); assert(((nTileDim - 1) & nTileDim) == 0); // Ensures that nTileDim is a power of 2 } inline void operator >> (super & dest) const { super::operator >> (dest); } inline void operator << (const super & other) { super::operator << (other); } inline void operator >> (superview & dest) const { super::operator >> (dest); } inline void operator << (const superview & other) { super::operator << (other); } inline std::istream & operator << (std::istream & ins) { return super::operator << (ins); } inline std::ostream & operator >> (std::ostream & outs) const { return super::operator >> (outs); } inline void copyTo (SFType & hm, const unsigned short nBlockX, const unsigned short nBlockY ) const { super::operator >> (SFOffs(&hm, static_cast< signed int > (nBlockX) * vdim, static_cast< signed int > (nBlockY) * vdim)); } inline void copyFrom (const SFType & hm, const unsigned short nBlockX, const unsigned short nBlockY ) { super::operator << (SFOffs(&hm, static_cast< signed int > (nBlockX) * vdim, static_cast< signed int > (nBlockY) * vdim)); } }; class TileMapDetails { private: unsigned short _nLOD, _nTileDim; unsigned int _nTilesW, _nTilesH; public: TileMapDetails (const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH, const unsigned short nLOD = 0); inline unsigned short getLOD () const { return _nLOD; } inline unsigned int getTilesWide () const { return _nTilesW; } inline unsigned int getTilesHigh () const { return _nTilesH; } inline unsigned short getVirtualTileDim () const { return _nTileDim >> _nLOD; } inline unsigned short getPhysicalTileDim () const { return (_nTileDim >> _nLOD) + 1; } inline unsigned long getVirtualWidth () const { return (static_cast< unsigned long > (_nTilesW) * _nTileDim) >> _nLOD; } inline unsigned long getVirtualHeight () const { return (static_cast< unsigned long > (_nTilesH) * _nTileDim) >> _nLOD; } inline unsigned long getTileCount () const { return static_cast< unsigned long > (_nTilesH) * _nTilesW; } inline unsigned int getVirtualTileSize () const { return mars::SQ(static_cast< unsigned int > (_nTileDim >> _nLOD)); } inline unsigned int getPhysicalTileSize () const { return mars::SQ(static_cast< unsigned int > ((_nTileDim >> _nLOD) + 1)); } inline unsigned long getVirtualUnitCount () const { return static_cast< unsigned long > (getTileCount()) * mars::SQ(static_cast< unsigned long > (_nTileDim >> _nLOD)); } inline unsigned long getPhysicalUnitCount () const { return static_cast< unsigned long > (getTileCount()) * mars::SQ(static_cast< unsigned long > ((_nTileDim >> _nLOD) + 1)); } inline unsigned long getWorldWidth () const { return static_cast< unsigned long > (_nTilesW) * _nTileDim; } inline unsigned long getWorldHeight () const { return static_cast< unsigned long > (_nTilesH) * _nTileDim; } }; class FileChunk { private: std::streampos _szFileOffset; protected: const std::streampos & getFileOffset () const; void setFileOffset(const std::streamoff & szFileOffset); bool isSetFileOffset () const; public: FileChunk (); virtual void init(const std::streamoff & szFileOffset); virtual std::streampos end () const = 0; }; class StaticFileChunk : public FileChunk { private: std::streamoff _szSize; protected: void setSize (const std::streamoff & szSize); public: std::streampos end () const; }; class VariableFileChunk : public FileChunk { private: FileChunk * _pNextChunk, * _pPrevChunk; bool _bDirty; std::streamoff _szChunkEnd; mars::ptr< std::fstream > _pfhFile; protected: std::streampos end () const; virtual void writeVariableData () = 0; virtual void readVariableData() = 0; public: VariableFileChunk (const mars::ptr< std::fstream > & pfhFile); virtual void init (FileChunk * pPreviousChunk); void dirty(); void load(); void commit (); }; namespace filesource { struct InfoHeader { char IDENT[4]; unsigned long endian; unsigned short version; unsigned short tdim; unsigned int tx, ty; unsigned short depth; struct GeoHost { unsigned short layers, lod; inline GeoHost () : layers (0), lod(0) {} } geohost; InfoHeader (); bool validate () const; }; class Ex : public std::exception { public: const std::string message; Ex (const char * szMsg) : message(szMsg) {} }; } template< typename T, typename ST = mars::Numerics< T > > class StreamTileMap : public TileMapDetails, public StaticFileChunk { private: mars::ptr< std::fstream > _pfhFile; protected: void assertPosition( const std::streamoff pos0, const std::streamoff pos, const std::ios_base::seekdir dir, const int nTileX, const int nTileY ) const { const std::streamoff dpos = pos - pos0; assert(pos < static_cast< std::streampos > (getPhysicalUnitCount()) * sizeof(T) + getFileOffset()); switch (dir) { case std::ios::cur: assert(dpos == computeBlockOffset(nTileX, nTileY)); break; case std::ios::beg: assert(pos == computeBlockOffset(nTileX, nTileY) + getFileOffset()); break; case std::ios::end: assert(pos == (static_cast< std::streampos > (getPhysicalUnitCount()) * sizeof(T) + getFileOffset()) - computeBlockOffset(nTileX, nTileY)); break; } } std::streamoff computeBlockOffset (const int nTileX, const int nTileY) const { using namespace std; return (static_cast< streamoff > (nTileY) * static_cast< streamoff > (getTilesWide()) + static_cast< streamoff > (nTileX)) * static_cast< streamoff > (getPhysicalTileSize()) * sizeof(T); } public: typedef TileBlock< T, ST > Block; StreamTileMap ( mars::ptr< std::fstream > & pfhFile, const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH, const unsigned short nLOD = 0 ) : _pfhFile(pfhFile), TileMapDetails(nTileDim, nTilesW, nTilesH, nLOD) { setSize(static_cast< std::streamsize > (getPhysicalUnitCount()) * sizeof(T)); } void seekg( const int nTileX, const int nTileY, const std::ios_base::seekdir dir = std::ios_base::cur ) { assert(getFileOffset() >= sizeof(filesource::InfoHeader)); #ifdef _DEBUG const std::streamoff pos0 = _pfhFile->tellg(); #endif _pfhFile->seekg(computeBlockOffset(nTileX, nTileY) + (dir == std::ios_base::beg ? getFileOffset() : static_cast< std::streampos > (0)), dir); if (_pfhFile->fail()) throw filesource::Ex("Seek read failed"); LOG(mars::Log::Debug) << "tellg=" << _pfhFile->tellg(); #ifdef _DEBUG assertPosition(pos0, _pfhFile->tellg(), dir, nTileX, nTileY); #endif // _DEBUG } void seekp( const int nTileX, const int nTileY, const std::ios_base::seekdir dir = std::ios_base::cur ) { assert(getFileOffset() >= sizeof(filesource::InfoHeader)); #ifdef _DEBUG const std::streamoff pos0 = _pfhFile->tellp(); #endif _pfhFile->seekp(computeBlockOffset(nTileX, nTileY) + (dir == std::ios_base::beg ? getFileOffset() : static_cast< std::streampos> (0)), dir); if (_pfhFile->fail()) throw filesource::Ex("Seek write failed"); LOG(mars::Log::Debug) << "tellp=" << _pfhFile->tellp(); #ifdef _DEBUG assertPosition(pos0, _pfhFile->tellp(), dir, nTileX, nTileY); #endif // _DEBUG } inline Block * createBlock () const { return new Block(getVirtualTileDim()); } void operator >> (Block & tile) { #ifdef _DEBUG const std::streamoff pos0 = _pfhFile->tellg(); #endif tile << *_pfhFile; if (_pfhFile->fail()) throw filesource::Ex("Read failed"); LOG(mars::Log::Debug) << "tellg=" << _pfhFile->tellg(); #ifdef _DEBUG assert(_pfhFile->tellg() - pos0 == static_cast< std::streamoff > (getPhysicalTileSize() * sizeof(T))); #endif } void operator << (const Block & tile) { #ifdef _DEBUG const std::streamoff pos0 = _pfhFile->tellp(); #endif tile >> *_pfhFile; if (_pfhFile->fail()) throw filesource::Ex("Write failed"); LOG(mars::Log::Debug) << "tellp=" << _pfhFile->tellp(); #ifdef _DEBUG assert(_pfhFile->tellp() - pos0 == static_cast< std::streamoff > (getPhysicalTileSize() * sizeof(T))); #endif } void operator >> ( mars::ScalarFieldView< T, ST > & view ) { Block block (getVirtualTileDim()); seekg(0, 0, std::ios_base::beg); for (unsigned int j = 0; j < getTilesHigh(); ++j) for (unsigned int i = 0; i < getTilesWide(); ++i) { block << *this; block.copyTo(view, i, j); } } void operator << ( const mars::ScalarFieldView< T, ST > & view ) { Block block (getVirtualTileDim()); seekp(0, 0, std::ios_base::beg); for (unsigned int j = 0; j < getTilesHigh(); ++j) for (unsigned int i = 0; i < getTilesWide(); ++i) { block.copyFrom(view, i, j); block >> *this; } } }; template< typename T, typename ST > void operator << (TileBlock< T, ST > & tile, StreamTileMap< T, ST > & tmap) { tmap >> tile; } template< typename T, typename ST > void operator >> (const TileBlock< T, ST > & tile, StreamTileMap< T, ST > & tmap) { tmap << tile; } class FileSource : public TileMapDetails { private: template< typename T > static T dimXp2 (const T nMinDim) { const unsigned int nL2 = mars::LOG2(nMinDim); T t = 1 << nL2; if (t < nMinDim) t *= 2; return t; } static FileSource * open (const std::string & sFileName, const std::ios::openmode nMode); public: static const unsigned short MAX_TILE_DIM = 1024; static const unsigned int MAX_AXIS_TILES = 1024; static const unsigned short MAX_WORLD_DEPTH = 30000; typedef StreamTileMap< GeoHeightMap::Precision > MainDEM; inline unsigned short getWorldDepth () const { return _nDepth; } MainDEM tilemap; class MineralHostMap : public VariableFileChunk, public TileMapDetails { public: typedef StreamTileMap< typename GeoHeightMap::Precision > TopDEM; const unsigned short count; TopDEM top; class LayerMap : public StreamTileMap< typename GeoStratumField::Precision, typename GeoStratumField::ScalarTraits > { public: typedef std::vector< std::string > DefList; typedef mars::Range< GeoStratumField::AltitudePrecision > RangeType; RangeType range; LayerMap(mars::ptr< std::fstream > & pfhFile, const unsigned short nLOD, const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH, const std::vector< std::string > & vsDefs = std::vector< std::string > ()); inline void operator >> ( GeoStratumField::View & field ) { retrieveField(field); } inline void operator << ( const GeoStratumField::View & field) { commitField(field); } inline void operator >> (Block & tile) { StreamTileMap::operator >> (tile); } inline void operator << (const Block & tile) { StreamTileMap::operator << (tile); } inline DefList::const_iterator beginDefs() const { return _vsDefs.begin(); } inline DefList::const_iterator endDefs() const { return _vsDefs.end(); } void putDefs (GeoStratumField::View & field) const; void setDefs (const GeoStratumField::View & field); void operator << (mars::ObjectStream & ins) { ins >> _vsDefs; ins >> range; } void operator >> (mars::ObjectStream & outs) { outs << _vsDefs; outs << range; } private: DefList _vsDefs; void operator >> ( GeoStratumField::ScalarFieldView & view ); void operator << ( const GeoStratumField::ScalarFieldView & view ); inline void retrieveField ( GeoStratumField::View & field ) { putDefs(field); StreamTileMap::operator >> (field); } inline void commitField ( const GeoStratumField::View & field) { StreamTileMap::operator << (field); setDefs(field); } }; class Offset { protected: MineralHostMap * const _pMap; public: const signed int x, y; Offset (MineralHostMap * const pMap, const signed int x, const signed int y); void operator >> (Stratum & stratum); void operator << (const Stratum & stratum); }; MineralHostMap (mars::ptr< std::fstream > & pfhFile, const unsigned short nLayers, const unsigned short nLOD, const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH); ~MineralHostMap (); void init(const std::streamoff & szFileOffset, MainDEM * pPrevChunk); void operator >> (Stratum & stratum); void operator << (const Stratum & stratum); inline LayerMap::Block * createLayerBlock () const { return new LayerMap::Block(getVirtualTileDim()); } inline TopDEM::Block * createTopDEMBlock () const { return new TopDEM::Block(getVirtualTileDim()); } inline const LayerMap & layer (const unsigned short i) const { return *_ppLayers[i]; } inline LayerMap & layer (const unsigned short i) { return *_ppLayers[i]; } protected: void writeVariableData (); void readVariableData (); private: LayerMap ** _ppLayers; std::streamoff _szLayers; mars::ptr< std::fstream > _pfhFile; void init(const std::streamoff & szFileOffset) {} } geohost; class MineralMap : public TileMapDetails, public VariableFileChunk { public: typedef std::set< MineralPtr > MineralSet; typedef mars::QuadTree_SphereIndexed< MineralPtr, GeoSpherePack::SCALAR > QuadTreeSpherePacks; typedef std::pair< QuadTreeSpherePacks::Region, size_t > SphereIndexReference; typedef std::vector< SphereIndexReference > SphRefVector; typedef std::pair< const MineralPtr, const QuadTreeSpherePacks::Region & > SphereReference; class MinDefCache { private: const std::vector< MineralPtr > * _pidxMinDefs; public: MinDefCache (const std::vector< MineralPtr > * pidxMinDefs) : _pidxMinDefs(pidxMinDefs) {} inline SphereReference convert (const SphereIndexReference & ref) const { assert(ref.second < _pidxMinDefs->size()); return SphereReference((*_pidxMinDefs)[ref.second], ref.first); } }; class TileResult : private SphRefVector { public: class const_iterator : private SphRefVector::const_iterator, public std::iterator< std::input_iterator_tag, SphereReference > { public: const_iterator (const MinDefCache & cache, const SphRefVector::const_iterator & i) : SphRefVector::const_iterator(i), _cache(cache) {} inline const SphereReference operator * () const { return _cache.convert(SphRefVector::const_iterator::operator * ()); } inline const_iterator & operator ++ () { SphRefVector::const_iterator::operator ++ (); return *this; } inline const_iterator operator ++ (int) { const_iterator i0 = *this; SphRefVector::const_iterator::operator ++ (0); return i0; } inline const_iterator & operator -- () { SphRefVector::const_iterator::operator -- (); return *this; } inline const_iterator operator -- (int) { const_iterator i0 = *this; SphRefVector::const_iterator::operator -- (0); return i0; } inline const_iterator & operator += (const size_t nOff) { SphRefVector::const_iterator::operator += (nOff); return *this; } inline const_iterator operator + (const size_t nOff) const { const_iterator i0 = *this; return i0 += nOff; } inline const_iterator & operator -= (const size_t nOff) { SphRefVector::const_iterator::operator -= (nOff); return *this; } inline const_iterator operator - (const size_t nOff) const { const_iterator i0 = *this; return i0 -= nOff; } inline bool operator != (const const_iterator & other) const { const_iterator i0 = *this; return i0 != other; } private: const MinDefCache & _cache; }; TileResult (const MinDefCache & cache, const SphRefVector & list) : SphRefVector(list), _cache(cache) {} inline const SphereReference operator [] (const size_t i) const { return _cache.convert(std::vector< SphereIndexReference >::operator [] (i)); } inline const_iterator begin () const { return const_iterator(_cache, SphRefVector::begin()); } inline const_iterator end () const { return const_iterator(_cache, SphRefVector::end()); } inline size_t size () const { return SphRefVector::size(); } private: MinDefCache _cache; }; MineralMap (mars::ptr< std::fstream > & pfhFile, const std::ios::openmode nOpenMode, const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH); void add (const MineralPtr & pMin, const QuadTreeSpherePacks::MyCylindricalRegion & rr); TileResult operator () (const unsigned int i, const unsigned int j); protected: void writeVariableData(); void readVariableData (); private: typedef std::map< MineralPtr, size_t > MineralIndex; struct MinMapHeader { std::streamoff mapoffs, listsoff; // DEPS: _bInitDefs } _header; static QuadTreeSpherePacks createQuadTree (const unsigned short nTileDim, const unsigned int nTilesW, const unsigned int nTilesH); std::vector< MineralPtr > _mins; MineralSet _setMinerals; QuadTreeSpherePacks _qtMinerals; mars::ptr< std::fstream > _pfhFile; } minerals; static FileSource * create (const std::string & sFileName, const unsigned long nMinWidth, const unsigned long nMinHeight, const unsigned short nDepth, const unsigned short nTileDim, const unsigned short nGeoHostLOD, const unsigned short nGeoHostLayerCount); static inline FileSource * open (const std::string & sFileName) { return open (sFileName, std::ios::in | std::ios::out); } static FileSource * view (const std::string & sFileName) { return open (sFileName, std::ios::in); } void applyDEM (const GeoHeightMap * pHM, const float fCoarseness); void load (); void commit (); ~FileSource(); protected: FileSource(mars::ptr< std::fstream >& pfhFile, const std::ios_base::openmode nMode, const short unsigned int nTileDim, const unsigned int nTilesW, const unsigned int nTilesH, const short unsigned int nDepth, const short unsigned int nGeoHostLOD, const short unsigned int nGeoHostLayers); static bool validate(const filesource::InfoHeader & header, mars::ptr< std::fstream > & pfhFile); private: mars::ptr< std::fstream > _pfhFile; std::ios::openmode _nOpenMode; std::streamoff _nHeaderEnd; unsigned short _nDepth; }; } #endif