RandCache.h

00001 // This file may be redistributed and modified only under the terms of
00002 // the GNU General Public License (See COPYING for details).
00003 // Copyright (C) 2004 Damien McGinnes, Ron Steinke, Alistair Riddoch
00004 
00005 #ifndef MERCATOR_RANDCACHE_H
00006 #define MERCATOR_RANDCACHE_H
00007 
00008 #include <vector>
00009 #include <wfmath/MersenneTwister.h>
00010 
00011 // construct with something like:
00012 // RandCache r(seed, new MyOrdering(args));
00013 // where MyOrdering is derived from RandCache::Ordering.
00014 
00015 class RandCache
00016 {
00017  public:
00018   typedef WFMath::MTRand::uint32 uint32;
00019   typedef std::vector<uint32>::size_type size_type;
00020 
00021   struct Ordering {
00022     virtual ~Ordering() {}
00023     virtual size_type operator()(int x, int y) = 0;
00024   };
00025 
00026   RandCache(uint32 seed, Ordering* o) :
00027         m_rand(seed), m_ordering(o) {}
00028   RandCache(uint32* seed, uint32 seed_len, Ordering* o) :
00029         m_rand(seed, seed_len), m_ordering(o) {}
00030   ~RandCache() {delete m_ordering;}
00031 
00032   double operator()(int x, int y)
00033   {
00034     size_type cache_order = (*m_ordering)(x, y);
00035 
00036     // make sure we've cached the value
00037     if(cache_order >= m_cache.size()) {
00038       size_type old_size = m_cache.size();
00039       m_cache.resize(cache_order + 64); //do 64 at once
00040       while(old_size < m_cache.size())
00041         m_cache[old_size++] = m_rand.randInt();
00042     }
00043 
00044     return double(m_cache[cache_order] * (1.0/4294967295.0));
00045   }
00046 
00047  private:
00048   WFMath::MTRand m_rand;
00049   std::vector<uint32> m_cache;
00050   Ordering* m_ordering;
00051 };
00052 
00053 //a spiral around 0,0
00054 class ZeroSpiralOrdering : public RandCache::Ordering
00055 {
00056 public:
00057     RandCache::size_type operator () (int x, int y) 
00058     {
00059         if (x==0 && y==0) return 0;
00060         
00061         int d=std::max(std::abs(x), std::abs(y));
00062         int min=(2*d-1)*(2*d-1);
00063 
00064         if (y == d)  return min + 2*d - x;
00065         if (x == -d) return min + 4*d - y;
00066         if (y == -d) return min + 6*d + x;
00067         else { //if (x == d) {
00068             if (y >=0) return min + y;
00069             else return min + 8*d + y;
00070         }
00071     }
00072 };
00073 
00074 //A spiral around x,y
00075 class SpiralOrdering : public ZeroSpiralOrdering
00076 {
00077 private:
00078     int m_x, m_y;
00079 public:
00080     SpiralOrdering(int x, int y) : ZeroSpiralOrdering(), m_x(x), m_y(y) {}
00081     RandCache::size_type operator () (int x, int y) 
00082     {
00083         return ZeroSpiralOrdering::operator()(x-m_x, y-m_y);
00084     }
00085 };
00086 
00087 
00088 #endif
00089 
00090 
00091 

Generated on Mon Aug 20 15:30:36 2007 for Mercator by  doxygen 1.5.2