1742 lines
51 KiB
C++
1742 lines
51 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
//[->][\ensuremath{\Rightarrow}]
|
|
//[<>][\ensuremath{\neq}]
|
|
|
|
|
|
*/
|
|
#ifndef RASTER2_RASTERSTORAGE_H
|
|
#define RASTER2_RASTERSTORAGE_H
|
|
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <list>
|
|
#include <unordered_map>
|
|
|
|
#include <SecondoSMI.h>
|
|
#include <Algebras/RTree/RTreeAlgebra.h>
|
|
#include <WinUnix.h>
|
|
|
|
#include "util/noncopyable.h"
|
|
|
|
namespace raster2
|
|
{
|
|
/*******************************************************************************
|
|
1 Interface
|
|
|
|
1.1 Class Template ~RasterStorage~
|
|
|
|
The ~RasterStorage~ class template provides a non-technical interface to the
|
|
storage of raster objects. The template parameters are:
|
|
|
|
* *T* -- is the data type that is stored in raster cells. values of this type
|
|
must be
|
|
|
|
* *dim* -- is the number of coordinates that are used to identify a raster
|
|
cell
|
|
|
|
* *Undef* -- is a functor or function pointer that accepts a ~const T\&~ as
|
|
argument and yields boolean true iff the value is considered to be
|
|
undefined.
|
|
|
|
* *undef* -- is a ~T~ that is used when undefined values must be written.
|
|
|
|
Template parameters of the same name have in other class templates have the same
|
|
meaning as the respective template parameter in this class template.
|
|
|
|
It is forward declared, because it is a friend of many other classes of this
|
|
header file.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)> class RasterStorage;
|
|
|
|
/*
|
|
1.2 Class Template ~RasterIndex~
|
|
|
|
The ~RasterIndex~ class template encapsulates an array of integers that is used
|
|
to identify a cell within a raster. It mainly provides methods for calculations
|
|
in cell indices.
|
|
|
|
*/
|
|
template <int dim> class RasterIndex
|
|
{
|
|
public:
|
|
RasterIndex();
|
|
RasterIndex(const int (&)[dim]);
|
|
RasterIndex(const int*);
|
|
|
|
int& operator[] (int);
|
|
int operator[] (int) const;
|
|
|
|
bool operator< (const RasterIndex<dim>&) const;
|
|
bool operator> (const RasterIndex<dim>&) const;
|
|
bool operator<=(const RasterIndex<dim>&) const;
|
|
bool operator>=(const RasterIndex<dim>&) const;
|
|
bool operator==(const RasterIndex<dim>&) const;
|
|
bool operator!=(const RasterIndex<dim>&) const;
|
|
|
|
RasterIndex<dim>& operator+=(const RasterIndex<dim>&);
|
|
RasterIndex<dim>& operator-=(const RasterIndex<dim>&);
|
|
|
|
RasterIndex<dim>& increment
|
|
(const RasterIndex<dim>&, const RasterIndex<dim>&);
|
|
|
|
private:
|
|
int index[dim];
|
|
};
|
|
|
|
template <int dim> inline RasterIndex<dim>
|
|
operator+(const RasterIndex<dim>&, const RasterIndex<dim>&);
|
|
|
|
template <int dim> inline RasterIndex<dim>
|
|
operator-(const RasterIndex<dim>&, const RasterIndex<dim>&);
|
|
|
|
template <int dim> inline std::ostream&
|
|
operator<<(std::ostream&, const RasterIndex<dim>&);
|
|
|
|
|
|
/*
|
|
1.3 Class Template ~RasterRegion~
|
|
|
|
The ~RasterRegion~ class template represents a bounding box by specifying
|
|
the lowest cell and the highest cell.
|
|
|
|
*/
|
|
template <int dim>
|
|
struct RasterRegion {
|
|
RasterRegion();
|
|
RasterRegion(const RasterIndex<dim>& min, const RasterIndex<dim>& max);
|
|
bool operator< (const RasterRegion<dim>& other) const;
|
|
|
|
RasterIndex<dim> Min;
|
|
RasterIndex<dim> Max;
|
|
};
|
|
|
|
template <int dim> inline
|
|
std::ostream& operator<<(std::ostream&, const RasterRegion<dim>&);
|
|
|
|
/*
|
|
1.4 Class Template ~RasterValueProxy~
|
|
|
|
The ~RasterValueProxy~ class template wraps the information that is needed to
|
|
write to a cell of a raster. It is meant to be transparent to the user and
|
|
can be used both as an ~lvalue~ and an ~rvalue~ for objects of type ~T~. This
|
|
means, objects of class ~RasterValueProxy$<$T, dim, Undef$>$~ are implicitly
|
|
cast to type ~T~ and values of type can be assigned to a
|
|
~RasterValueProxy$<$T, dim, Undef$>$~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterValueProxy {
|
|
friend class RasterStorage<T, dim, Undef>;
|
|
|
|
public:
|
|
operator T() const;
|
|
RasterValueProxy<T, dim, Undef>& operator=(const T& rhs);
|
|
RasterValueProxy<T, dim, Undef>& operator=
|
|
(const RasterValueProxy<T, dim, Undef>& rhs);
|
|
|
|
private:
|
|
RasterValueProxy (const RasterIndex<dim>&,
|
|
RasterStorage<T, dim, Undef>*);
|
|
|
|
RasterIndex<dim> index;
|
|
RasterStorage<T, dim, Undef>* storage;
|
|
};
|
|
|
|
/*
|
|
1.5 Class Template ~RasterStorageIterator~
|
|
|
|
The ~RasterStorageIterator~ class template is used to iterate over the cells in
|
|
a ~RasterStorage~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterStorageIterator {
|
|
friend class RasterStorage<T, dim, Undef>;
|
|
public:
|
|
RasterStorageIterator& operator++();
|
|
RasterStorageIterator operator++(int);
|
|
RasterValueProxy<T, dim, Undef> operator*();
|
|
bool operator==(const RasterStorageIterator<T, dim, Undef>& rhs);
|
|
bool operator!=(const RasterStorageIterator<T, dim, Undef>& rhs);
|
|
const RasterIndex<dim>& getIndex() const;
|
|
|
|
private:
|
|
RasterStorageIterator(const RasterIndex<dim>& from,
|
|
const RasterIndex<dim>& to,
|
|
RasterStorage<T, dim, Undef>* storage);
|
|
|
|
RasterIndex<dim> from;
|
|
RasterIndex<dim> to;
|
|
RasterIndex<dim> pos;
|
|
RasterStorage<T, dim, Undef>* storage;
|
|
bool valid;
|
|
};
|
|
|
|
/*
|
|
1.6 Class Template ~RasterStorageRegionIterator~
|
|
|
|
The ~RasterStorageRegionIterator~ class template is used to iterate over the
|
|
regions in a ~RasterStorage~, that likely contain values.
|
|
|
|
*/
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterStorageRegionIterator {
|
|
friend class RasterStorage<T, dim, Undef>;
|
|
public:
|
|
RasterStorageRegionIterator& operator++();
|
|
RasterStorageRegionIterator operator++(int);
|
|
const RasterIndex<dim>& operator*() const;
|
|
const RasterIndex<dim>* operator->() const;
|
|
bool operator==(const RasterStorageRegionIterator<T, dim, Undef>& rhs);
|
|
bool operator!=(const RasterStorageRegionIterator<T, dim, Undef>& rhs);
|
|
|
|
static const RasterIndex<dim> region_size;
|
|
|
|
private:
|
|
RasterStorageRegionIterator(const RasterIndex<dim>& from,
|
|
const RasterIndex<dim>& to,
|
|
R_Tree<dim, RasterIndex<dim> >* tree);
|
|
|
|
R_Tree<dim, RasterIndex<dim> >* tree;
|
|
R_TreeLeafEntry<dim, RasterIndex<dim> > current;
|
|
bool valid;
|
|
};
|
|
|
|
/*
|
|
1.7 Class Template ~RasterRectangle~
|
|
|
|
The class template ~RasterRectangle~ works around the problem that
|
|
~Rectangle~ objects from the RectangleAlgebra cannot be stored in a C++
|
|
map. Elements in a map must be default constructible and copyable. The
|
|
~Rectangle~ does not initialize its values when default-constructed, the copy
|
|
constructor then raises an assertion error when such an object is copied.
|
|
|
|
Casting from and to ~Rectangle~ objects is done implicitly.
|
|
|
|
*/
|
|
template <int dim>
|
|
class RasterRectangle {
|
|
public:
|
|
inline RasterRectangle();
|
|
inline RasterRectangle(const double *i, const double *x );
|
|
inline RasterRectangle(const RasterRectangle<dim>& r);
|
|
inline RasterRectangle(const Rectangle<dim>& r);
|
|
|
|
bool operator== (const RasterRectangle<dim>& rhs) const;
|
|
|
|
operator Rectangle<dim> () const;
|
|
|
|
private:
|
|
void initialize(const double* i, const double* x);
|
|
|
|
static const double* getDefault();
|
|
|
|
double min[dim];
|
|
double max[dim];
|
|
};
|
|
|
|
/*
|
|
1.8 Class Template ~RasterCacheItem<T, dim, Undef>~
|
|
|
|
Class invariants are
|
|
|
|
* dirty [->] writable
|
|
|
|
* dirty [->] smi\_record [<>] 0
|
|
|
|
* dirty [->] buffer [<>] 0
|
|
|
|
The constructor takes ownership of the SmiRecord-pointer, but not of the
|
|
RasterStorageFile- and RasterCache-pointers.
|
|
|
|
*/
|
|
class RasterStorageFile;
|
|
template <class T, int dim, bool Undef(const T&)> class RasterCache;
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterCacheItem : util::noncopyable {
|
|
public:
|
|
RasterCacheItem(const T& undef, RasterIndex<dim> i);
|
|
RasterCacheItem(const T& undef, RasterIndex<dim> i, SmiRecord* r,
|
|
RasterStorageFile* f, RasterCache<T, dim, Undef>* c,
|
|
bool w, bool n);
|
|
~RasterCacheItem();
|
|
|
|
bool isWritable();
|
|
|
|
void set(SmiSize offset, const T& value);
|
|
T get(SmiSize offset);
|
|
|
|
void flush();
|
|
void discard();
|
|
|
|
private:
|
|
int getOffset(const RasterIndex<dim>& index);
|
|
|
|
T undefined;
|
|
RasterIndex<dim> index;
|
|
SmiRecord* smi_record;
|
|
RasterStorageFile* file;
|
|
RasterCache<T, dim, Undef>* cache;
|
|
bool writable;
|
|
bool dirty;
|
|
bool has_tree_entry;
|
|
char* buffer;
|
|
SmiSize length;
|
|
};
|
|
|
|
/*
|
|
1.9 Class Template ~RasterCache<T, dim, Undef>~
|
|
|
|
The ~RasterCache<T, dim, Undef>~ class template manages the cache for a
|
|
~RasterStorage<T, dim, Undef>~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterCache : util::noncopyable {
|
|
friend class RasterCacheItem<T, dim, Undef>;
|
|
public:
|
|
typedef RasterCacheItem<T, dim, Undef> Item;
|
|
typedef RasterIndex<dim> Index;
|
|
typedef RasterRectangle<dim> TreeEntry;
|
|
|
|
typedef std::list<Index> LRU_List;
|
|
typedef typename std::list<Index>::iterator LRU_Pointer;
|
|
|
|
typedef std::pair<Item*, LRU_Pointer> ValuePair;
|
|
typedef std::unordered_map<Index, ValuePair> DataCache;
|
|
typedef std::unordered_map<Index, TreeEntry> TreeCache;
|
|
|
|
RasterCache(size_t s, R_Tree<dim, Index>* t);
|
|
~RasterCache();
|
|
|
|
bool isCached(const Index& i);
|
|
void cacheItem(const Index&, Item*);
|
|
Item* getItem(const Index& i);
|
|
|
|
void flush();
|
|
void discard();
|
|
void setSize(size_t s);
|
|
void ensureSize(size_t s);
|
|
void clear(const bool flush);
|
|
|
|
void insertRectangle(const Index& i, const TreeEntry& b);
|
|
void removeRectangle(const Index& i, const TreeEntry& b);
|
|
|
|
private:
|
|
size_t size;
|
|
DataCache cache;
|
|
LRU_List history;
|
|
TreeCache tree_insert;
|
|
TreeCache tree_remove;
|
|
R_Tree<dim, Index>* tree;
|
|
};
|
|
|
|
/*
|
|
1.10 Class ~RasterStorageFile~
|
|
|
|
The ~RasterStorageFile~ class is derived from ~SmiKeyedFile~, because
|
|
~SmiKeyedFile~ has purely virtual functions and cannot be instantiated.
|
|
|
|
*/
|
|
class RasterStorageFile : public SmiKeyedFile
|
|
{
|
|
public:
|
|
virtual ~RasterStorageFile() {};
|
|
RasterStorageFile(bool isTemporary) :
|
|
SmiKeyedFile(SmiFile::KeyedHash, SmiKey::String, true, isTemporary)
|
|
{}
|
|
};
|
|
|
|
/*
|
|
1.10 Definition of the ~RasterStorage~ Class.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
class RasterStorage : util::noncopyable {
|
|
friend class RasterValueProxy<T, dim, Undef>;
|
|
|
|
public:
|
|
typedef RasterIndex<dim> index_type;
|
|
typedef RasterCache<T, dim, Undef> cache_type;
|
|
|
|
static const int tile_size;
|
|
static const int cell_count;
|
|
static const index_type region_size;
|
|
|
|
explicit RasterStorage(const T& undefined);
|
|
RasterStorage(const T& undefined, SmiFileId f, SmiFileId t);
|
|
~RasterStorage();
|
|
|
|
T operator[] (const index_type& index) const;
|
|
|
|
RasterValueProxy<T, dim, Undef> operator[]
|
|
(const index_type& index);
|
|
|
|
void remove();
|
|
RasterRegion<dim> bbox();
|
|
SmiFileId getRasterFileId();
|
|
SmiFileId getTreeFileId();
|
|
|
|
void setCacheSize(size_t);
|
|
void ensureCacheSize(size_t);
|
|
void flushCache();
|
|
|
|
RasterStorageIterator<T, dim, Undef> begin();
|
|
RasterStorageIterator<T, dim, Undef> end();
|
|
RasterStorageIterator<T, dim, Undef> iterate
|
|
(const index_type& from, const index_type& to);
|
|
|
|
RasterStorageRegionIterator<T, dim, Undef> begin_regions();
|
|
RasterStorageRegionIterator<T, dim, Undef> end_regions();
|
|
RasterStorageRegionIterator<T, dim, Undef> iterate_regions
|
|
(const index_type& from, const index_type& to);
|
|
static RasterIndex<dim> getRegion(const RasterIndex<dim>& i);
|
|
|
|
|
|
void clear();
|
|
|
|
const R_Tree<dim, index_type >* getTree();
|
|
|
|
private:
|
|
void set(const index_type& index, const T& value);
|
|
T get(const index_type& index) const;
|
|
RasterCacheItem<T, dim, Undef>* getRecord(
|
|
const SmiKey&, const index_type&, bool = false) const;
|
|
void splitIndex(const index_type& index,
|
|
index_type& offset, SmiSize* pos = 0,
|
|
index_type* grid = 0, SmiKey* key = 0) const;
|
|
|
|
T undef;
|
|
mutable RasterStorageFile* file;
|
|
mutable R_Tree<dim, index_type >* tree;
|
|
mutable size_t cache_size;
|
|
mutable RasterCache<T, dim, Undef> cache;
|
|
};
|
|
|
|
/*******************************************************************************
|
|
2 Implementation
|
|
|
|
2.1 Logging
|
|
|
|
Operations on the ~RasterCache~ can be logged to a file. to activate logging,
|
|
define the ~RASTERSTORAGE\_LOGFILE~ macro to be the name of the log file.
|
|
|
|
The log file is overwritten on each invocation of Secondo.
|
|
|
|
*/
|
|
#ifdef RASTERSTORAGE_LOGFILE
|
|
extern std::ofstream rslog;
|
|
#else
|
|
#define rslog if (false) std::clog
|
|
#endif
|
|
|
|
/*
|
|
2.2 Methods and Operators of class ~RasterStorage~.
|
|
|
|
2.2.1 Create new storage files
|
|
|
|
The following constructor creates a ~RasterStorage~ object by creating the
|
|
necessary files to store raster data.
|
|
|
|
* *undefined* -- is the undefined value of type ~T~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorage<T, dim, Undef>::RasterStorage(const T& undefined)
|
|
: undef(undefined),
|
|
file(new RasterStorageFile(false)),
|
|
tree(new R_Tree<dim, index_type>(
|
|
WinUnix::getPageSize()-2*dim*int(sizeof(double)),false)),
|
|
cache_size(10),
|
|
cache(cache_size, tree)
|
|
{
|
|
file->Create();
|
|
}
|
|
|
|
/*
|
|
2.1.2 Read existing storage files
|
|
|
|
The following constructor creates a ~RasterStorage~ object to access existing
|
|
raster data.
|
|
|
|
* *undefined* -- is the undefined value of type ~T~.
|
|
|
|
* *f* -- is the ID of the record file.
|
|
|
|
* *t* -- is the IF of the file that holds the R\_Tree.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorage<T, dim, Undef>::RasterStorage(
|
|
const T& undefined, SmiFileId f, SmiFileId t)
|
|
: undef(undefined),
|
|
file(new RasterStorageFile(false)),
|
|
tree(new R_Tree<dim, index_type>(t, true, false)),
|
|
cache_size(10),
|
|
cache(cache_size, tree)
|
|
{
|
|
file->Open(f);
|
|
}
|
|
|
|
/*
|
|
2.1.3 Destructor
|
|
|
|
This releases the resources of a ~RasterStorage~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorage<T, dim, Undef>::~RasterStorage() {
|
|
cache.flush();
|
|
// tree and file are zero when the files have been removed and might
|
|
// be zero when the constructor threw an exception.
|
|
if (file != 0) {
|
|
file->Close(true);
|
|
delete file;
|
|
}
|
|
if (tree != 0) {
|
|
// Calling tree->CloseFile() here prevents writing the header,
|
|
// leading to a corrupt SmiFile. Deleting the R\_Tree object
|
|
// automatically closes the file.
|
|
delete tree;
|
|
}
|
|
}
|
|
|
|
/*
|
|
2.1.4 File Management
|
|
|
|
The following functions deal with managing the files associated with a
|
|
~RasterStorage~ object.
|
|
|
|
* *remove()* -- removes the files from the persistent storage. After this
|
|
function is called, the ~RasterStorage~ object is unusable and
|
|
the only sensible operation is to destroy it.
|
|
|
|
* *getRasterFileId()* --
|
|
|
|
* *getTreeFileId()* -- retrieve the ~SmiFileId~ associated with this
|
|
~RasterStorage~ object.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::remove() {
|
|
cache.discard();
|
|
file->Close(true);
|
|
file->Drop();
|
|
delete file;
|
|
file = 0;
|
|
tree->DeleteFile();
|
|
delete tree;
|
|
tree = 0;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
SmiFileId RasterStorage<T, dim, Undef>::getRasterFileId() {
|
|
if (file == 0) {
|
|
return 0;
|
|
}
|
|
return file->GetFileId();
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
SmiFileId RasterStorage<T, dim, Undef>::getTreeFileId() {
|
|
if (tree == 0) {
|
|
return 0;
|
|
}
|
|
return tree->FileId();
|
|
}
|
|
|
|
/*
|
|
2.1.7 Cache Management
|
|
|
|
*/
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::setCacheSize(size_t s) {
|
|
cache.setSize(s);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::ensureCacheSize(size_t s) {
|
|
cache.ensureSize(s);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::flushCache() {
|
|
cache.flush();
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.6 Accessing Raster Data
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterRegion<dim>
|
|
RasterStorage<T, dim, Undef>::bbox() {
|
|
cache.flush();
|
|
RasterRegion<dim> result;
|
|
BBox<dim> bbox(tree->Root().BoundingBox());
|
|
if(bbox.IsDefined() && !bbox.IsEmpty()){
|
|
for (int i = 0; i < dim; ++i) {
|
|
result.Min[i] = int(bbox.MinD(i));
|
|
result.Max[i] = int(bbox.MaxD(i));
|
|
}
|
|
}else {
|
|
for (int i = 0; i < dim; ++i) {
|
|
result.Min[i] = 0;
|
|
result.Max[i] = 0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::iterate
|
|
(const index_type& from, const index_type& to)
|
|
{
|
|
RasterStorageIterator<T, dim, Undef> it(from, to, this);
|
|
while (it.valid && Undef(*it)) ++it;
|
|
return it;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::begin()
|
|
{
|
|
RasterRegion<dim> rbb = bbox();
|
|
RasterStorageIterator<T, dim, Undef> iter(rbb.Min, rbb.Max, this);
|
|
if (Undef(*iter)) ++iter;
|
|
return iter;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::end()
|
|
{
|
|
index_type i;
|
|
return RasterStorageIterator<T, dim, Undef>(i, i, this);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::iterate_regions
|
|
(const index_type& from, const index_type& to)
|
|
{
|
|
return RasterStorageRegionIterator<T, dim, Undef>(from, to, this->tree);
|
|
}
|
|
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void
|
|
RasterStorage<T, dim, Undef>::clear(){
|
|
file->Truncate();
|
|
tree->Clear();
|
|
cache.clear(false);
|
|
}
|
|
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const R_Tree<dim, RasterIndex<dim> >*
|
|
RasterStorage<T, dim, Undef>::getTree(){
|
|
return tree;
|
|
}
|
|
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::begin_regions()
|
|
{
|
|
RasterRegion<dim> rbb = bbox();
|
|
return RasterStorageRegionIterator<T, dim, Undef>
|
|
(rbb.Min, rbb.Max, this->tree);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::end_regions()
|
|
{
|
|
index_type i;
|
|
return RasterStorageRegionIterator<T, dim, Undef>(i, i, 0);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterIndex<dim>
|
|
RasterStorage<T, dim, Undef>::getRegion(const RasterIndex<dim>& index)
|
|
{
|
|
index_type result = index;
|
|
for (int i = 0; i < dim; ++i) {
|
|
result[i] -= index[i] >= 0 ?
|
|
index[i] % tile_size :
|
|
index[i] % tile_size + tile_size;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
inline T RasterStorage<T, dim, Undef>::operator[]
|
|
(const index_type& index) const
|
|
{
|
|
return get(index);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
inline RasterValueProxy<T, dim, Undef>
|
|
RasterStorage<T, dim, Undef>::operator[] (const index_type& index)
|
|
{
|
|
return RasterValueProxy<T, dim, Undef>(index, this);
|
|
}
|
|
|
|
/*
|
|
2.1.7 Private Functions
|
|
|
|
~getRecord()~ is used to retrieve items from the cache.
|
|
|
|
Returns a non-null pointer to a cache item. The caller is responsible for
|
|
deleting the pointed to object.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterCacheItem<T, dim, Undef>*
|
|
RasterStorage<T, dim, Undef>::getRecord(
|
|
const SmiKey& key, const index_type& index, bool writable) const
|
|
{
|
|
RasterCacheItem<T, dim, Undef>* item =
|
|
cache.getItem(index);
|
|
if (item == 0 || (writable && !item->isWritable())) {
|
|
|
|
SmiRecord* record = new SmiRecord;
|
|
bool exists = file->SelectRecord
|
|
(key, *record, writable ? SmiFile::Update : SmiFile::ReadOnly);
|
|
|
|
if (exists) {
|
|
item = new RasterCacheItem<T, dim, Undef>
|
|
(undef, index, record, file, &cache, writable, false);
|
|
} else if (writable) {
|
|
file->InsertRecord(key, *record);
|
|
|
|
T* empty_record = new T[cell_count];
|
|
for (int i = 0; i < cell_count; ++i) {
|
|
empty_record[i] = undef;
|
|
}
|
|
double zeros[2*dim] = {0.0};
|
|
record->Write(zeros);
|
|
record->Write(empty_record,
|
|
cell_count * sizeof(T),
|
|
2*dim*sizeof(double));
|
|
delete[] empty_record;
|
|
|
|
item = new RasterCacheItem<T, dim, Undef>
|
|
(undef, index, record, file, &cache, true, true);
|
|
} else {
|
|
item = new RasterCacheItem<T, dim, Undef>(undef, index);
|
|
delete record;
|
|
}
|
|
cache.cacheItem(index, item);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
/**
|
|
* @pre key != 0 => grid != 0
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::splitIndex(const index_type& index,
|
|
index_type& offset, SmiSize* pos,
|
|
index_type* grid, SmiKey* key) const
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
offset[i] = index[i] % tile_size;
|
|
if (offset[i] < 0) offset[i] += tile_size;
|
|
}
|
|
|
|
if (pos != 0) {
|
|
*pos = 0;
|
|
for (int i = 0, multiplier = 1; i < dim;
|
|
++i, multiplier *= tile_size)
|
|
{
|
|
*pos += offset[i] * sizeof(T) * multiplier;
|
|
}
|
|
*pos += 2*sizeof(double)*dim;
|
|
}
|
|
|
|
if (grid != 0) {
|
|
*grid = index - offset;
|
|
}
|
|
|
|
if (key != 0) {
|
|
assert(grid != 0);
|
|
*key = SmiKey(std::string(reinterpret_cast<char*>(grid),
|
|
sizeof(index_type)));
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
void RasterStorage<T, dim, Undef>::set(
|
|
const index_type& index, const T& value)
|
|
{
|
|
index_type offset, grid;
|
|
SmiSize pos;
|
|
SmiKey key;
|
|
|
|
splitIndex(index, offset, &pos, &grid, &key);
|
|
|
|
RasterCacheItem<T, dim, Undef>* item = getRecord(key, grid, true);
|
|
assert(item != 0); // record should have been created on demand
|
|
item->set(pos, value);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
T RasterStorage<T, dim, Undef>::get(const index_type& index) const
|
|
{
|
|
index_type offset, grid;
|
|
SmiSize pos;
|
|
SmiKey key;
|
|
|
|
splitIndex(index, offset, &pos, &grid, &key);
|
|
|
|
RasterCacheItem<T, dim, Undef>* item = getRecord(key, grid, false);
|
|
return item->get(pos);
|
|
}
|
|
|
|
/*
|
|
2.2 Implementation of ~RasterIndex~
|
|
|
|
*/
|
|
|
|
template <int dim> inline
|
|
RasterIndex<dim>::RasterIndex()
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
index[i] = 0;
|
|
}
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterIndex<dim>::RasterIndex(const int (&ri)[dim])
|
|
{
|
|
std::memcpy(&index, &ri, dim*sizeof(int));
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterIndex<dim>::RasterIndex(const int* ri)
|
|
{
|
|
std::memcpy(&index, ri, dim*sizeof(int));
|
|
}
|
|
|
|
template <int dim> inline int&
|
|
RasterIndex<dim>::operator[] (int i)
|
|
{
|
|
assert(0 <= i && i < dim);
|
|
return index[i];
|
|
}
|
|
|
|
template <int dim> inline int
|
|
RasterIndex<dim>::operator[] (int i) const
|
|
{
|
|
assert(0 <= i && i < dim);
|
|
return index[i];
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator<(const RasterIndex<dim>& rhs) const
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
if (index[i] < rhs.index[i]) {
|
|
return true;
|
|
} else if (index[i] > rhs.index[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator==(const RasterIndex<dim>& rhs) const
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
if (index[i] != rhs[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator>(const RasterIndex<dim>& rhs) const
|
|
{
|
|
return !(*this == rhs) && !(*this < rhs);
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator!=(const RasterIndex<dim>& rhs) const
|
|
{
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator<=(const RasterIndex<dim>& rhs) const
|
|
{
|
|
return *this < rhs || *this == rhs;
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterIndex<dim>::operator>=(const RasterIndex<dim>& rhs) const
|
|
{
|
|
return rhs <= *this;
|
|
}
|
|
|
|
template <int dim> inline RasterIndex<dim>&
|
|
RasterIndex<dim>::operator+=(const RasterIndex<dim>& rhs)
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
index[i] += rhs.index[i];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <int dim> inline RasterIndex<dim>&
|
|
RasterIndex<dim>::operator-=(const RasterIndex<dim>& rhs) {
|
|
for (int i = 0; i < dim; ++i) {
|
|
index[i] -= rhs.index[i];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <int dim> inline RasterIndex<dim>&
|
|
RasterIndex<dim>::increment
|
|
(const RasterIndex<dim>& from, const RasterIndex<dim>& to)
|
|
{
|
|
int i = 0;
|
|
while (i < dim && index[i] >= to[i] - 1) {
|
|
++i;
|
|
}
|
|
if (i < dim) {
|
|
++index[i];
|
|
for (int j = 0; j < i; ++j) {
|
|
index[j] = from[j];
|
|
}
|
|
} else {
|
|
*this = to;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <int dim>
|
|
std::ostream& operator<<(std::ostream& os, const RasterIndex<dim>& ri) {
|
|
os << "( ";
|
|
for (int i = 0; i < dim; ++i) {
|
|
os << ri[i] << " ";
|
|
}
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
template <int dim>
|
|
RasterIndex<dim> operator+(const RasterIndex<dim>& lhs,
|
|
const RasterIndex<dim>& rhs)
|
|
{
|
|
RasterIndex<dim> result = lhs;
|
|
result += rhs;
|
|
return result;
|
|
}
|
|
|
|
template <int dim>
|
|
RasterIndex<dim> operator-(const RasterIndex<dim>& lhs,
|
|
const RasterIndex<dim>& rhs)
|
|
{
|
|
RasterIndex<dim> result = lhs;
|
|
result -= rhs;
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
2.2 Methods and Operators of ~RasterRegion~
|
|
|
|
*/
|
|
|
|
template<int dim> inline
|
|
RasterRegion<dim>::RasterRegion()
|
|
: Min(), Max()
|
|
{}
|
|
|
|
template<int dim> inline
|
|
RasterRegion<dim>::RasterRegion
|
|
(const RasterIndex<dim>& min, const RasterIndex<dim>& max)
|
|
: Min(min), Max(max)
|
|
{}
|
|
|
|
template<int dim> inline bool
|
|
RasterRegion<dim>::operator<(const RasterRegion<dim>& rhs) const
|
|
{
|
|
if (Min < rhs.Min)
|
|
return true;
|
|
else if (rhs.Min < Min)
|
|
return false;
|
|
else
|
|
return Max < rhs.Max;
|
|
}
|
|
|
|
template <int dim>
|
|
std::ostream& operator<<(std::ostream& os, const RasterRegion<dim>& rr) {
|
|
os << "RR:[Min = " << rr.Min << " ; Max = " << rr.Max << "]";
|
|
return os;
|
|
}
|
|
|
|
/*
|
|
2.2 Methods and Operators of ~RasterValueProxy~
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterValueProxy<T, dim, Undef>::RasterValueProxy
|
|
(const RasterIndex<dim>& i, RasterStorage<T, dim, Undef>* s)
|
|
: index(i), storage(s)
|
|
{
|
|
assert(s != 0);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
inline RasterValueProxy<T, dim, Undef>::operator T() const
|
|
{
|
|
return storage->get(index);
|
|
};
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
inline RasterValueProxy<T, dim, Undef>&
|
|
RasterValueProxy<T, dim, Undef>::operator=(const T& rhs)
|
|
{
|
|
storage->set(index, rhs);
|
|
return *this;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
inline RasterValueProxy<T, dim, Undef>&
|
|
RasterValueProxy<T, dim, Undef>::operator=
|
|
(const RasterValueProxy<T, dim, Undef>& rhs)
|
|
{
|
|
storage->set(index, rhs.storage->get(rhs.index));
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
2.2 Methods and Operators of ~RasterRectangle~
|
|
|
|
*/
|
|
template <int dim> inline
|
|
RasterRectangle<dim>::RasterRectangle()
|
|
{
|
|
initialize(getDefault(), getDefault());
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterRectangle<dim>::RasterRectangle(const double *i, const double *x )
|
|
{
|
|
initialize(i, x);
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterRectangle<dim>::RasterRectangle(const RasterRectangle<dim>& r)
|
|
{
|
|
initialize(r.min, r.max);
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterRectangle<dim>::RasterRectangle(const Rectangle<dim>& r)
|
|
{
|
|
if (r.IsDefined()) {
|
|
for (int i = 0; i < dim; ++i) {
|
|
min[i] = r.MinD(i);
|
|
max[i] = r.MaxD(i);
|
|
}
|
|
} else {
|
|
initialize(getDefault(), getDefault());
|
|
}
|
|
}
|
|
|
|
template <int dim> inline bool
|
|
RasterRectangle<dim>::operator== (const RasterRectangle<dim>& rhs) const
|
|
{
|
|
return std::memcmp(min, rhs.min, dim*sizeof(double)) == 0
|
|
&& std::memcmp(max, rhs.max, dim*sizeof(double)) == 0;
|
|
}
|
|
|
|
template <int dim> inline
|
|
RasterRectangle<dim>::operator Rectangle<dim> () const
|
|
{
|
|
return Rectangle<dim>(true, min, max);
|
|
}
|
|
|
|
template <int dim> inline void
|
|
RasterRectangle<dim>::initialize(const double* i, const double* x)
|
|
{
|
|
std::memcpy(&min, i, dim*sizeof(double));
|
|
std::memcpy(&max, x, dim*sizeof(double));
|
|
}
|
|
|
|
template <int dim> inline const double*
|
|
RasterRectangle<dim>::getDefault()
|
|
{
|
|
static double* min = 0;
|
|
if (min == 0) {
|
|
min = new double[dim];
|
|
for (int i = 0; i < dim; ++i) {
|
|
min[i] = 0;
|
|
}
|
|
}
|
|
return min;
|
|
}
|
|
|
|
/*
|
|
2.3 Methods of ~RasterCacheItem~
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)> inline
|
|
RasterCacheItem<T, dim, Undef>::RasterCacheItem(const T& undef,
|
|
RasterIndex<dim> i, SmiRecord* r, RasterStorageFile* f,
|
|
RasterCache<T, dim, Undef>* c, bool w, bool n)
|
|
: undefined(undef), index(i), smi_record(r), file(f), cache(c),
|
|
writable(w), dirty(false), has_tree_entry(!n),
|
|
buffer(0), length(0)
|
|
{
|
|
assert(smi_record != 0);
|
|
assert(file != 0);
|
|
assert(cache != 0);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> inline
|
|
RasterCacheItem<T, dim, Undef>::RasterCacheItem(const T& undef,
|
|
RasterIndex<dim> i)
|
|
: undefined(undef), index(i), smi_record(0), file(0), cache(0),
|
|
writable(false), dirty(false), has_tree_entry(false),
|
|
buffer(0), length(0)
|
|
{ }
|
|
|
|
template <class T, int dim, bool Undef(const T&)> inline
|
|
RasterCacheItem<T, dim, Undef>::~RasterCacheItem()
|
|
{
|
|
flush();
|
|
// SmiRecord::GetData() calls DB::get() with the DB_DBT_MALLOC flag set.
|
|
if(buffer){
|
|
std::free(buffer);
|
|
}
|
|
if(smi_record){
|
|
delete smi_record;
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> inline bool
|
|
RasterCacheItem<T, dim, Undef>::isWritable()
|
|
{
|
|
return writable;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCacheItem<T, dim, Undef>::set(SmiSize offset, const T& value)
|
|
{
|
|
assert(writable);
|
|
if (buffer == 0) {
|
|
buffer = smi_record->GetData(length);
|
|
assert(buffer); // force a result
|
|
}
|
|
T* current = reinterpret_cast<T*>(buffer + offset);
|
|
if ((Undef(*current) ^ Undef(value)) ||
|
|
(!Undef(*current) && !Undef(value) && *current != value))
|
|
{
|
|
std::memcpy(buffer + offset, &value, sizeof(T));
|
|
dirty = true;
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> inline T
|
|
RasterCacheItem<T, dim, Undef>::get(SmiSize offset)
|
|
{
|
|
if (smi_record == 0) {
|
|
return undefined;
|
|
} else if (buffer == 0) {
|
|
buffer = smi_record->GetData(length);
|
|
}
|
|
return *reinterpret_cast<T*>(buffer + offset);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCacheItem<T, dim, Undef>::flush()
|
|
{
|
|
static int arg[dim] = {0};
|
|
static RasterIndex<dim> from = RasterIndex<dim>(arg);
|
|
static RasterIndex<dim> to = RasterStorage<T, dim, Undef>::region_size;
|
|
|
|
if (dirty) {
|
|
rslog << cache->tree->FileId() << " vvvvv " << index << ".\n";
|
|
|
|
bool has_values = false;
|
|
|
|
RasterRegion<dim> bbox;
|
|
for (int i = 0; i < dim; ++i) {
|
|
bbox.Min[i] = RasterStorage<T, dim, Undef>::tile_size;
|
|
bbox.Max[i] = 0;
|
|
}
|
|
int offset;
|
|
for (RasterIndex<dim> i = from; i < to; i.increment(from, to)) {
|
|
offset = getOffset(i);
|
|
T* value = reinterpret_cast<T*>(buffer + offset);
|
|
if (!Undef(*value)) {
|
|
has_values = true;
|
|
for (int d = 0; d < dim; ++d) {
|
|
if (bbox.Min[d] > i[d]) {
|
|
bbox.Min[d] = i[d];
|
|
}
|
|
if (bbox.Max[d] < i[d]) {
|
|
bbox.Max[d] = i[d];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bbox.Min += index;
|
|
bbox.Max += index;
|
|
|
|
double* min = reinterpret_cast<double*>(buffer);
|
|
double* max = reinterpret_cast<double*>(buffer +
|
|
dim*sizeof(double));
|
|
|
|
if (has_tree_entry) {
|
|
cache->removeRectangle
|
|
(index, RasterRectangle<dim>(min, max));
|
|
has_tree_entry = false;
|
|
}
|
|
|
|
if (has_values) {
|
|
for (int i = 0; i < dim; ++i) {
|
|
min[i] = bbox.Min[i];
|
|
max[i] = bbox.Max[i] + 1;
|
|
}
|
|
RasterRectangle<dim> bbnew(min, max);
|
|
cache->insertRectangle
|
|
(index, RasterRectangle<dim>(min,max));
|
|
has_tree_entry = true;
|
|
smi_record->Write(buffer, length, 0);
|
|
} else {
|
|
file->DeleteRecord(
|
|
smi_record->GetKey(), true, smi_record->GetId());
|
|
}
|
|
}
|
|
dirty = false;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCacheItem<T, dim, Undef>::discard()
|
|
{
|
|
// SmiRecord::GetData() calls DB::get() with the DB_DBT_MALLOC flag set.
|
|
std::free(buffer);
|
|
delete smi_record;
|
|
|
|
smi_record = 0;
|
|
file = 0;
|
|
cache = 0;
|
|
writable = false;
|
|
dirty = false;
|
|
has_tree_entry = false;
|
|
buffer = 0;
|
|
length = 0;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> int
|
|
RasterCacheItem<T, dim, Undef>::getOffset(const RasterIndex<dim>& index)
|
|
{
|
|
int offset = 2*sizeof(double)*dim;
|
|
for (int i = 0, multiplier = 1; i < dim;
|
|
++i, multiplier *= RasterStorage<T, dim, Undef>::tile_size)
|
|
{
|
|
offset += index[i] * sizeof(T) * multiplier;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
2.3 Methods of ~RasterCache~
|
|
|
|
*/
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterCache<T, dim, Undef>::RasterCache(size_t s, R_Tree<dim, Index>* t)
|
|
: size(s), cache(), history(), tree_insert(), tree_remove(), tree(t)
|
|
{}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterCache<T, dim, Undef>::~RasterCache() {
|
|
flush();
|
|
for (typename DataCache::iterator it = cache.begin(),
|
|
e = cache.end();
|
|
it != e; ++it)
|
|
{
|
|
delete it->second.first;
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> bool
|
|
RasterCache<T, dim, Undef>::isCached(const Index& i) {
|
|
return cache.find(i) != cache.end();
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::cacheItem(const Index& i, Item* record) {
|
|
// Let S be the size of the cache.
|
|
typename DataCache::iterator cit = cache.find(i); // O(log(1))
|
|
if (cit == cache.end()) { // O(1)
|
|
if (cache.size() >= size) { // O(1)
|
|
typename LRU_List::iterator hit = history.begin();// O(1)
|
|
rslog << tree->FileId() << " <<<<< " << *hit << ".\n";
|
|
delete cache[*hit].first; // O(1)
|
|
cache.erase(*hit); // O(1)
|
|
history.erase(hit); // O(1)
|
|
}
|
|
rslog << tree->FileId() << " >>>>> " << i << ".\n";
|
|
} else {
|
|
rslog << tree->FileId() << " ooooo " << i << ".\n";
|
|
delete cit->second.first; // O(1)
|
|
history.erase(cit->second.second); // O(log(1))
|
|
}
|
|
history.push_back(i);
|
|
cache[i] = std::make_pair(record, --history.end()); // O(log(1))
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterCacheItem<T, dim, Undef>*
|
|
RasterCache<T, dim, Undef>::getItem(const Index& i) {
|
|
// Let S be the size of the cache.
|
|
typename DataCache::iterator it = cache.find(i); // O(log(1))
|
|
if (it == cache.end()) { // O(1)
|
|
return 0; // O(1)
|
|
} else {
|
|
typename LRU_List::iterator tmp = it->second.second;
|
|
if (++tmp != history.end()) {
|
|
rslog << tree->FileId() << " ^^^^^ " << i << ".\n";
|
|
LRU_Pointer cnt = it->second.second; // O(1)
|
|
history.erase(cnt); // O(1)
|
|
history.push_back(i); // O(1)
|
|
it->second.second = --history.end(); // O(1)
|
|
assert(*cache.find(i)->second.second == i);
|
|
}
|
|
return it->second.first; // O(1)
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::flush()
|
|
{
|
|
if (tree == 0) {
|
|
return;
|
|
}
|
|
|
|
for(typename DataCache::iterator it = cache.begin();
|
|
it != cache.end();
|
|
++it)
|
|
{
|
|
it->second.first->flush();
|
|
}
|
|
|
|
for (typename TreeCache::iterator it = tree_remove.begin(),
|
|
e = tree_remove.end();
|
|
it != e; ++it)
|
|
{
|
|
rslog << tree->FileId() << " _|_|_ " << it->first << ".\n";
|
|
tree->Remove(
|
|
R_TreeLeafEntry<dim, Index>(it->second, it->first));
|
|
}
|
|
tree_remove.clear();
|
|
|
|
if (!tree_insert.empty()) {
|
|
// note: avoid bulkloading tree
|
|
// to do this, the elements must be sorted by z_order
|
|
if (false && tree->NodeCount() == 1 && tree->EntryCount() == 0 &&
|
|
tree->InitializeBulkLoad(false))
|
|
{
|
|
rslog << tree->FileId() << " BBBBB.\n";
|
|
tree->InitializeBulkLoad(false);
|
|
for (typename TreeCache::iterator
|
|
it = tree_insert.begin(), e = tree_insert.end();
|
|
it != e; ++it)
|
|
{
|
|
rslog << tree->FileId() << " TTTTT " << it->first << "\n";
|
|
tree->InsertBulkLoad
|
|
(R_TreeLeafEntry<dim, Index>
|
|
(it->second, it->first) );
|
|
}
|
|
tree->FinalizeBulkLoad();
|
|
} else {
|
|
for (typename TreeCache::iterator
|
|
it = tree_insert.begin(), e = tree_insert.end();
|
|
it != e; ++it)
|
|
{
|
|
rslog << tree->FileId() << " ttttt " << it->first << "\n";
|
|
tree->Insert
|
|
(R_TreeLeafEntry<dim, Index>
|
|
(it->second, it->first));
|
|
}
|
|
}
|
|
tree_insert.clear();
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::discard()
|
|
{
|
|
for(typename DataCache::iterator it = cache.begin();
|
|
it != cache.end();
|
|
++it)
|
|
{
|
|
it->second.first->discard();
|
|
delete it->second.first;
|
|
}
|
|
size = 0;
|
|
cache.clear();
|
|
history.clear();
|
|
tree_insert.clear();
|
|
tree_remove.clear();
|
|
tree = 0;
|
|
}
|
|
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::clear(const bool _flush) {
|
|
if(_flush){
|
|
flush();
|
|
}
|
|
for(typename DataCache::iterator it = cache.begin();
|
|
it != cache.end();
|
|
++it)
|
|
{
|
|
it->second.first->discard();
|
|
delete it->second.first;
|
|
}
|
|
cache.clear();
|
|
history.clear();
|
|
tree_insert.clear();
|
|
tree_remove.clear();
|
|
}
|
|
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::setSize(size_t s) {
|
|
if (s < size) {
|
|
size_t actual = cache.size();
|
|
if(actual > s) {
|
|
typename LRU_List::iterator hit;
|
|
for (size_t i = s; i < actual; ++i) {
|
|
hit = history.begin(); // O(1)
|
|
rslog << tree->FileId() << " <<<<< " << *hit << ".\n";
|
|
delete cache[*hit].first; // O(1)
|
|
cache.erase(*hit); // O(1)
|
|
history.erase(hit); // O(1)
|
|
}
|
|
assert(cache.size() == s);
|
|
}
|
|
assert(cache.size() <= s);
|
|
}
|
|
size = s;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::ensureSize(size_t s) {
|
|
if (size < s) {
|
|
size = s;
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::insertRectangle(const Index& i,
|
|
const RasterRectangle<dim>& b)
|
|
{
|
|
tree_insert[i] = b;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> void
|
|
RasterCache<T, dim, Undef>::removeRectangle(const Index& i,
|
|
const RasterRectangle<dim>& b)
|
|
{
|
|
typename TreeCache::iterator it = tree_insert.find(i);
|
|
if (it == tree_insert.end()) {
|
|
tree_remove[i] = b;
|
|
} else {
|
|
assert(it->second == b);
|
|
tree_insert.erase(it);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
2.3 Methods of ~RasterStorageIterator~
|
|
|
|
The constructor of ~RasterStorageIterator~ is private, because
|
|
~RasterStorageIterator~ objects should only be created by its friend class
|
|
~RasterStorage~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>::RasterStorageIterator(
|
|
const RasterIndex<dim>& f,
|
|
const RasterIndex<dim>& t,
|
|
RasterStorage<T, dim, Undef>* s)
|
|
: from(f), to(t), pos(f), storage(s), valid(f < t)
|
|
{}
|
|
|
|
/*
|
|
Accessing elements is done in the same way as in the the standard library.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterValueProxy<T, dim, Undef>
|
|
RasterStorageIterator<T, dim, Undef>::operator*() {
|
|
return (*storage)[pos];
|
|
}
|
|
|
|
/*
|
|
Moving to the next element is done in the same way as in the the C++ standard
|
|
library.
|
|
|
|
Prefix increment is implemented using
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>&
|
|
RasterStorageIterator<T, dim, Undef>::operator++ ()
|
|
{
|
|
if (!valid) {
|
|
return *this;
|
|
}
|
|
|
|
do {
|
|
int i = 0;
|
|
while (i < dim && pos[i] == to[i] - 1) {
|
|
++i;
|
|
}
|
|
if (i < dim) {
|
|
++pos[i];
|
|
for (int j = 0; j < i; ++j) {
|
|
pos[j] = from[j];
|
|
}
|
|
} else {
|
|
valid = false;
|
|
}
|
|
} while (valid && Undef((*storage)[pos]));
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
Postfix increment is implemented using
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageIterator<T, dim, Undef>
|
|
RasterStorageIterator<T, dim, Undef>::operator++ (int)
|
|
{
|
|
RasterStorageIterator<T, dim, Undef> copy(*this);
|
|
++this;
|
|
return copy;
|
|
}
|
|
|
|
/*
|
|
~RasterStorageIterator~ objects can be compared for equality.
|
|
|
|
All invalid iterators are considered equal. No valid iterator is equal to an
|
|
invalid iterator. Valid iterators are equal if they come from the same
|
|
~RasterStorage~ object and point to the same element.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
bool RasterStorageIterator<T, dim, Undef>::operator==
|
|
(const RasterStorageIterator<T, dim, Undef>& rhs)
|
|
{
|
|
if (valid && rhs.valid) {
|
|
return pos == rhs.pos && storage == rhs.storage;
|
|
}
|
|
return !valid && !rhs.valid;
|
|
}
|
|
|
|
/*
|
|
~RasterStorageIterator~ are unequal iff they are not equal.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)> inline bool
|
|
RasterStorageIterator<T, dim, Undef>::operator!=
|
|
(const RasterStorageIterator<T, dim, Undef>& rhs)
|
|
{
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)> inline
|
|
const RasterIndex<dim>&
|
|
RasterStorageIterator<T, dim, Undef>::getIndex() const
|
|
{
|
|
return pos;
|
|
};
|
|
|
|
/*
|
|
2.4 Methods of ~RasterStorageRegionIterator~
|
|
|
|
The constructor of ~RasterStorageRegionIterator~ is private, because
|
|
~RasterStorageRegionIterator~ objects should only be created by its friend class
|
|
~RasterStorage~.
|
|
|
|
*/
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>::RasterStorageRegionIterator(
|
|
const RasterIndex<dim>& from,
|
|
const RasterIndex<dim>& to,
|
|
R_Tree<dim, RasterIndex<dim> >* r)
|
|
: tree(r), current(), valid(r != 0)
|
|
{
|
|
if (valid) {
|
|
double min[dim], max[dim];
|
|
for (int i = 0; i < dim; ++i) {
|
|
min[i] = from[i];
|
|
max[i] = to[i];
|
|
}
|
|
BBox<dim> box(true, min, max);
|
|
valid = tree->First(box, current);
|
|
}
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>&
|
|
RasterStorageRegionIterator<T, dim, Undef>::operator++()
|
|
{
|
|
if (valid) {
|
|
valid = tree->Next(current);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
RasterStorageRegionIterator<T, dim, Undef>
|
|
RasterStorageRegionIterator<T, dim, Undef>::operator++(int) {
|
|
RasterStorageRegionIterator<T, dim, Undef> copy(*this);
|
|
++this;
|
|
return copy;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const RasterIndex<dim>&
|
|
RasterStorageRegionIterator<T, dim, Undef>::operator*() const {
|
|
assert(valid);
|
|
return current.info;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const RasterIndex<dim>*
|
|
RasterStorageRegionIterator<T, dim, Undef>::operator->() const {
|
|
assert(valid);
|
|
return ¤t.info;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
bool RasterStorageRegionIterator<T, dim, Undef>::operator==
|
|
(const RasterStorageRegionIterator<T, dim, Undef>& rhs)
|
|
{
|
|
if (valid && rhs.valid) {
|
|
return current.info == rhs.current.info && tree == rhs.tree;
|
|
}
|
|
return !valid && !rhs.valid;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
bool RasterStorageRegionIterator<T, dim, Undef>::operator!=
|
|
(const RasterStorageRegionIterator<T, dim, Undef>& rhs)
|
|
{
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
/*
|
|
3 Auxiliary Functions and initializations.
|
|
|
|
*/
|
|
template <class T, int dim> int calculatePartialGridSize() {
|
|
double EffectivePageSize = WinUnix::getPageSize()
|
|
- dim * sizeof(int) // for the key
|
|
- 2*sizeof(double)*dim; // for the tree bbox;
|
|
double ValsPerPage = EffectivePageSize/sizeof(T);
|
|
double ValsPerDimension = std::pow(ValsPerPage, 1.0/dim);
|
|
assert(ValsPerDimension >= 1);
|
|
return int(ValsPerDimension);
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const int RasterStorage<T, dim, Undef>::tile_size
|
|
= calculatePartialGridSize<T, dim>();
|
|
|
|
template <class T, int dim> RasterIndex<dim> calculateRegionSize() {
|
|
RasterIndex<dim> result;
|
|
int s = calculatePartialGridSize<T, dim>();
|
|
for (int i = 0; i < dim; ++i) {
|
|
result[i] = s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const RasterIndex<dim>
|
|
RasterStorageRegionIterator<T, dim, Undef>::region_size
|
|
= calculateRegionSize<T, dim>();
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const RasterIndex<dim>
|
|
RasterStorage<T, dim, Undef>::region_size
|
|
= calculateRegionSize<T, dim>();
|
|
|
|
template <class T, int dim> int calculateCellCount() {
|
|
int count = 1;
|
|
int tile_size = calculatePartialGridSize<T, dim>();
|
|
for (int i = 0; i < dim; ++i) {
|
|
count *= tile_size;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
template <class T, int dim, bool Undef(const T&)>
|
|
const int
|
|
RasterStorage<T, dim, Undef>::cell_count = calculateCellCount<T, dim>();
|
|
|
|
}
|
|
|
|
namespace std {
|
|
template<int dim>
|
|
struct hash<raster2::RasterIndex<dim> > {
|
|
size_t operator()(const raster2::RasterIndex<dim>& value) const {
|
|
size_t result = 0;
|
|
for (int i = 0; i < dim; ++i) {
|
|
result ^= static_cast<size_t>(value[i]);
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif /* RASTER2\_RASTERSTORAGE\_H */
|