KrisLibrary  1.0.0
RangeMap2D.h
1 #ifndef RANGE_MAP_2D_H
2 #define RANGE_MAP_2D_H
3 
4 #include "IntTuple.h"
5 #include <KrisLibrary/structs/array2d.h>
6 #include <map>
7 using namespace std;
8 
12 template <class T>
14 {
15  public:
16  typedef map<IntPair>::iterator iterator;
17  typedef map<IntPair>::const_iterator const_iterator;
18 
19  RangeMap2D();
20  void clear();
21  inline bool empty() { return items.empty(); }
22  void setRange(const IntPair& indexmin,const IntPair& indexmax);
23  void expandRange(const IntPair& index);
24  void insert(const IntPair& index);
25  template <class It>
26  void insert(It first,It last);
27  void erase(iterator it);
28  void erase(const IntPair& item);
29  template <class It>
30  void erase(It first,It last);
31  inline iterator begin() { return items.begin(); }
32  inline const_iterator begin() const { return items.begin(); }
33  inline iterator end() { return items.end(); }
34  inline const_iterator end() const { return items.end(); }
35  size_t size() const { return items.size(); }
36  int count(const IntPair& item);
37  iterator find(const IntPair& item);
38  const_iterator find(const IntPair& item) const;
39  inline bool isRangeEmpty() const { return imax.a < imin.a; }
40  inline const IntPair& minimum() const { return imin; }
41  inline const IntPair& maximum() const { return imax; }
42  inline bool inRange(const IntPair& item) const { return item.a >= imin.a && item.a <= imax.a && item.b >= imin.b && item.b <= imax.b; }
43  inline iterator cacheGet(const IntPair& item) const { return contains(item.a-imin.a,item.b-imin.b); }
44  inline void cacheSet(const IntPair& item,iterator it) { contains(item.a-imin.a,item.b-imin.b)=it; }
45 
46  void BuildCache();
47  void ClearCache();
48  inline bool IsCacheBuilt() const { return hasContainmentCache; }
49 
50  private:
51  map<IntPair,T> items;
52  IntPair imin,imax;
53  bool hasContainmentCache;
54  Array2D<iterator> contains;
55 };
56 
57 RangeMap2D::RangeMap2D()
58  :imin(1,1),imax(0,0),hasContainmentCache(false)
59 {}
60 
61 void RangeMap2D::clear()
62 {
63  imin.set(1,1);
64  imax.set(0,0);
65  hasContainmentCache=false;
66  items.clear();
67  contains.clear();
68 }
69 
70 void RangeMap2D::setRange(const IntPair& _imin,const IntPair& _imax)
71 {
72  if(imin < imax) //already has a range
73  Assert(_imin.a <= imin.a && _imin.b <= imin.b &&
74  _imax.a >= imax.a && _imax.b >= imax.b);
75  if(hasContainmentCache) {
76  FatalError("Already have cache set up");
77  }
78  imin=_imin;
79  imax=_imax;
80 }
81 
82 void RangeMap2D::expandRange(const IntPair& item)
83 {
84  if(isRangeEmpty()) { //has no range
85  imin = imax = item;
86  return;
87  }
88  if(hasContainmentCache) {
89  if(!inRange(item))
90  FatalError("RangeMap2D::expandRange(): error, item out of bounds");
91  }
92  else {
93  if(item.a < imin.a) imin.a=item.a;
94  else if(item.a > imax.a) imax.a=item.a;
95  if(item.b < imin.b) imin.b=item.b;
96  else if(item.b > imax.b) imax.b=item.b;
97  }
98 }
99 
100 void RangeMap2D::insert(const IntPair& item)
101 {
102  if(hasContainmentCache) {
103  if(!inRange(item))
104  FatalError("RangeMap2D::insert(): error, item out of bounds");
105  iterator it=cacheGet(item);
106  if(it == end()) {
107  iterator it=items.insert(item);
108  cacheSet(item,it);
109  }
110  }
111  else {
112  items.insert(item);
113  if(item.a < imin.a) imin.a=item.a;
114  else if(item.a > imax.a) imax.a=item.a;
115  if(item.b < imin.b) imin.b=item.b;
116  else if(item.b > imax.b) imax.b=item.b;
117  }
118 }
119 
120 void RangeMap2D::erase(const IntPair& item)
121 {
122  if(!inRange(item)) return;
123  if(hasContainmentCache) {
124  iterator it=cacheGet(item);
125  if(it != end()) {
126  items.erase(it);
127  cacheSet(item,items.end());
128  }
129  }
130  else {
131  items.erase(items.find(item));
132  }
133 }
134 
135 int RangeMap2D::count(const IntPair& item)
136 {
137  if(!inRange(item)) return 0;
138  if(hasContainmentCache) {
139  if(cacheGet(item)!=items.end()) return 1;
140  return 0;
141  }
142  return items.count(item);
143 }
144 
145 RangeMap2D::iterator RangeMap2D::find(const IntPair& item)
146 {
147  if(!inRange(item)) return items.end();
148  if(hasContainmentCache)
149  return cacheGet(item);
150  else
151  return items.find(item);
152 }
153 
154 RangeMap2D::const_iterator RangeMap2D::find(const IntPair& item) const
155 {
156  if(!inRange(item)) return items.end();
157  if(hasContainmentCache)
158  return cacheGet(item);
159  else
160  return items.find(item);
161 }
162 
163 void RangeMap2D::BuildCache()
164 {
165  if(imax < imin) return; //no items
166  if(hasContainmentCache) return;
167  contains.resize(imax.a-imin.a+1,imax.b-imin.b+1);
168  contains.set(items.end());
169  for(const_iterator i=items.begin();i!=items.end();i++)
170  cacheSet(*i,i);
171  hasContainmentCache = true;
172 }
173 
174 void RangeMap2D::ClearCache()
175 {
176  hasContainmentCache=false;
177  contains.clear();
178 }
179 
180 
181 #endif
A lightweight integer 2-tuple class.
Definition: IntPair.h:9
Definition: rayprimitives.h:132
Same as RangeSet2D but a map. O(1) find as well as count.
Definition: RangeMap2D.h:13