#ifndef __GEOWORLDSTRATUM_H__ #define __GEOWORLDSTRATUM_H__ #include #include #include #include #include #include namespace geoworld { class StratumData { public: typedef std::vector< GeoStratumField::View * > FieldList; class Offset { public: StratumData * const data; const StratumData * const_data; const signed int x, y; Offset (StratumData * const pData, const signed int x, const signed int y) : data(pData), const_data(pData), x(x), y(y) {} Offset (const StratumData * pData, const signed int x, const signed int y) : data(NULL), const_data(pData), x(x), y(y) {} void operator >> (StratumData & other) const { const_data->copySection(other, x, y); } void operator << (const StratumData & other) { assert(data != NULL); other.copySection(*data, x, y); } }; FieldList fields; GeoHeightMap::View * baseview; // DEPS: Unbounded view depends on GeoHeightMap::Precision StratumData (const size_t nLayers, const unsigned short nWidth, const unsigned short nHeight, const mars::GridType engt = mars::Normal); StratumData (StratumData * pParent, const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom); ~StratumData(); void operator >> (StratumData & dest) const; void operator << (const StratumData & src); inline void operator >> (Offset dest) const { copySection(*dest.data, dest.x, dest.y); } inline void operator << (const Offset src) { src.const_data->copySection(*this, src.x, src.y); } private: const StratumData * _pParent; void copySection (StratumData & dest, const signed int x, const signed int y) const; }; class StratumView { private: typedef std::vector< std::pair< size_t, size_t > > IdxMap; typedef std::vector< size_t > ElemCounts; mars::RangeX< GeoHeightMap::Precision > _z; GeoHeightMap::Precision _zBase, _zBasedMin; mutable StratumData _data; IdxMap _idx0map; // DEPS: Implication made in fetchSurfaceViewIndices() ElemCounts _counts; const WorldUnit _one; mutable size_t _nViewRefCount; GW_MUTEX(atomic); protected: StratumView(const size_t nLayers, const mars::BBox< WorldUnit > & bbox, const WorldUnit z0, const WorldUnit zN, const WorldUnit zBase, const unsigned short nLOD, const mars::GridType engt = mars::Normal); StratumView(StratumData * pParentData, const mars::BBox< WorldUnit > & bbox, const WorldUnit z0, const WorldUnit zN, const WorldUnit zBase, const unsigned short nLOD); StratumView(const StratumView * const pParent, const mars::BBox< WorldUnit > & bbox); StratumView(StratumView && move) : _z(move._z), _zBase(move._zBase), _zBasedMin(move._zBasedMin), _data(move._data), _idx0map(move._idx0map), _counts(move._counts), _one(move._one), _nViewRefCount(move._nViewRefCount), abswidth(move.abswidth), absheight(move.absheight), absdepth(move.absdepth), width(move.width), height(move.height), depth(move.depth), lod(move.lod), layers(move.layers) {} inline static StratumView createHosted (const size_t nLayers, const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nBasement, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nCeiling, const unsigned short nLOD, const mars::GridType engt = mars::Normal) { return createHosted(nLayers, mars::BBox< WorldUnit > (nLeft, nTop, nRight, nBottom), nBasement, nCeiling, nLOD, engt); } inline static StratumView createHosted (const size_t nLayers, const mars::BBox< WorldUnit > & bbox, const WorldUnit nBasement, const WorldUnit nCeiling, const unsigned short nLOD, const mars::GridType engt = mars::Normal) { return StratumView( nLayers, bbox, nBasement, nCeiling, nBasement, nLOD, engt ); } const GeoStratumField::Element & getDominantElement( std::vector< unsigned short > & indices ) const; public: const unsigned long abswidth, absheight, absdepth; const unsigned short width, height, depth, lod; class Ex : public std::exception { public: const std::string message; Ex (const char * szMsg) : message(szMsg) {} }; class Offset { public: StratumView * const view; const StratumView * const_view; const WorldUnit x, y; Offset (StratumView * const pView, const WorldUnit x, const WorldUnit y) : view(pView), const_view(pView), x(x), y(y) {} Offset (const StratumView * pView, const WorldUnit x, const WorldUnit y) : view(NULL), const_view(pView), x(x), y(y) {} void operator >> (StratumView & other) const { const_view->_data >> StratumData::Offset(&other._data, x >> const_view->lod, y >> const_view->lod); } void operator << (const StratumView & other) { assert(view != NULL); other._data << StratumData::Offset(&view->_data, x >> const_view->lod, y >> const_view->lod); } }; typedef StratumView View; const size_t layers; ~StratumView(); inline StratumData::FieldList::iterator beginFields () { return _data.fields.begin(); } inline StratumData::FieldList::iterator endFields () { return _data.fields.end(); } inline StratumData::FieldList::const_iterator beginFields () const { return _data.fields.begin(); } inline StratumData::FieldList::const_iterator endFields () const { return _data.fields.end(); } inline GeoStratumField::View & field(const size_t c) { return *_data.fields[c]; } inline const GeoStratumField::View & field(const size_t c) const { return *_data.fields[c]; } template< typename Fn > void warp (const signed int x, const signed int y, const GeoHeightMap::Precision nAmt, const Fn & fn) { const signed int xlo = static_cast< signed int > (x >> lod), ylo = static_cast< signed int > (y >> lod); GeoHeightMap::Precision zi = 0; (*_data.baseview)(xlo, ylo) += static_cast< GeoHeightMap::Precision > (static_cast< float > (nAmt) * fn.f(0.0f)); for (size_t c = 0; c < _data.fields.size(); ++c) { GeoStratumField::View & view = *_data.fields[c]; const GeoHeightMap::Precision nAlt0 = view.altitude(xlo, ylo); zi += nAlt0; view.altitude(xlo, ylo) += nAmt * fn.f(zi); } } void fetchViewElements (std::set< GeoStratumField::Element > & st) const; void fetchViewIndices (std::set< unsigned short > & st) const; const GeoStratumField::Element & getDominantElementVN3 (const WorldUnit x, const WorldUnit y, const WorldUnit z) const; const GeoStratumField::Element & getDominantElementVN (const WorldUnit x, const WorldUnit y) const; inline GeoHeightMap::Precision & altitude(const WorldUnit x, const WorldUnit y) { return (*_data.baseview)(x >> lod, y >> lod); } inline const GeoHeightMap::Precision & altitude(const WorldUnit x, const WorldUnit y) const { return (*_data.baseview)(x >> lod, y >> lod); } unsigned short getIndex (const WorldUnit x, const WorldUnit y, const WorldUnit z) const; const GeoStratumField::Element & getElement (const WorldUnit x, const WorldUnit y, const WorldUnit z) const; inline const GeoStratumField::Element & getElement (const size_t nIdx) const { const std::pair< size_t, size_t > & pair = _idx0map[nIdx]; return _data.fields[pair.first] ->getElement(nIdx - pair.second); } signed int findIndex (const GeoStratumField::Element & elem) const; // Retrieve total concatenated range of all strata and top-level DEM mars::Range< WorldUnit > getRange() const; inline GeoHeightMap::View & getBase () { return *_data.baseview; } inline const GeoHeightMap::View & getBase () const { return *_data.baseview; } inline GeoStratumField::View & operator [] (const size_t c) { return *_data.fields[c]; } inline const GeoStratumField::View & operator [] (const size_t c) const { return *_data.fields[c]; } inline size_t size() const { return _data.fields.size(); } virtual void updateIndexMap (); const StratumView * createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nShallow, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nDeep ) const; const StratumView * createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nRight, const WorldUnit nBottom ) const; StratumView * createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nShallow, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nDeep ); StratumView * createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nRight, const WorldUnit nBottom ); void releaseView (const StratumView * pView) const; inline void operator >> (StratumView & dest) const { assert(width == dest.width && height == dest.height && lod == dest.lod); _data >> dest._data; dest.updateIndexMap(); } inline void operator << (const StratumView & src) { assert(width == src.width && height == src.height && lod == src.lod); _data << src._data; updateIndexMap(); } inline void operator >> (Offset dest) const { assert(lod == dest.view->lod); _data >> StratumData::Offset(&dest.view->_data, dest.x >> lod, dest.y >> lod); dest.view->updateIndexMap(); } inline void operator << (const Offset src) { assert(lod == src.const_view->lod); _data << StratumData::Offset(&src.const_view->_data, src.x >> lod, src.y >> lod); updateIndexMap(); } void applyDEM(const GeoHeightMap::View & hmv, const unsigned short nDEMLOD); }; class Stratum : public StratumView { private: WorldUnit _nActualDepth; public: Stratum (const size_t nLayers, const WorldUnit nWidth, const WorldUnit nHeight, const WorldUnit nDepth, const unsigned short nLOD, const mars::GridType engt = mars::Normal); // Stratum (const Stratum & copy); inline void operator >> (StratumView & dest) const { StratumView::operator >> (dest); } inline void operator << (const StratumView & other) { StratumView::operator << (other); } inline void operator >> (Offset dest) const { StratumView::operator >> (dest); } inline void operator << (const Offset src) { StratumView::operator << (src); } std::ostream & operator >> (std::ostream & outs) const; std::istream & operator << (std::istream & ins); }; } #endif