| 1 | cycrow | 1 | /*
 | 
        
           |  |  | 2 |   defines bob_point_map - class that is responsible for the tricky
 | 
        
           |  |  | 3 |   "point compression" when converting from binary to text
 | 
        
           |  |  | 4 |   | 
        
           |  |  | 5 |   it acts as kind of Search Tree but not binary search tree
 | 
        
           |  |  | 6 |   | 
        
           |  |  | 7 |   the map itself is created by linked list consisting of p_node objects.
 | 
        
           |  |  | 8 |   p_node means "point node" although it does not contain any point.
 | 
        
           |  |  | 9 |   pp_node means "point point node" because it does contain bob_dom_point :)
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 |   if you add a point into this map:
 | 
        
           |  |  | 12 |   | 
        
           |  |  | 13 |   - I will take the X coordinate
 | 
        
           |  |  | 14 |   - I will take its 1th byte (left most) of the coordinate and try to find it in list.
 | 
        
           |  |  | 15 |   Either I will find it or I will add new p_node object.
 | 
        
           |  |  | 16 |   - I will take the 2nd byte and try to find it in the previously returned p_node which
 | 
        
           |  |  | 17 |   is now the "base"
 | 
        
           |  |  | 18 |   - I will continue with the remaining 3 bytes
 | 
        
           |  |  | 19 |   - I will repeat this for Y and Z coordinates
 | 
        
           |  |  | 20 |   - when adding the last byte of the Z coordinate, the last object created is not p_node
 | 
        
           |  |  | 21 |   but pp_node which also contain the point we are adding to the map
 | 
        
           |  |  | 22 |   | 
        
           |  |  | 23 |   I "found" this "algorithm" when I looked at raw output of points coords exported in hexadecimal
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 |   It should be rewritten to either AVL or Red Black Tree but I don't understand the way 2-3-4 trees
 | 
        
           |  |  | 26 |   (RB trees) are balanced and standard AVL trees are not exactly what I want because I would have to
 | 
        
           |  |  | 27 |   first find the point and then insert if unsuccessfull.
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 |   Althouhg this map is not as fast as it would probaly could with binary search trees, it's still
 | 
        
           |  |  | 30 |   damned fast compared to linear search which I and CheckerTwo were using.
 | 
        
           |  |  | 31 |   | 
        
           |  |  | 32 | */
 | 
        
           |  |  | 33 |   | 
        
           |  |  | 34 | #ifndef BOB_POINT_MAP_INCLUDED
 | 
        
           |  |  | 35 | #define BOB_POINT_MAP_INCLUDED
 | 
        
           |  |  | 36 |   | 
        
           |  |  | 37 | #include "../common/ext_array.h"
 | 
        
           |  |  | 38 | #include "../common/ext_simple_list.h"
 | 
        
           |  |  | 39 |   | 
        
           |  |  | 40 | //#include "bob_point_bst.h"
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 | class bob_point_map
 | 
        
           |  |  | 43 | {
 | 
        
           |  |  | 44 | 	private:
 | 
        
           |  |  | 45 | 		struct p_node
 | 
        
           |  |  | 46 | 		{
 | 
        
           |  |  | 47 | 			unsigned char id;
 | 
        
           |  |  | 48 | 			p_node *next;
 | 
        
           |  |  | 49 | 			p_node *child;
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 | 			p_node() { next=0; child=0;  }
 | 
        
           |  |  | 52 | 		};
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 | 		struct pp_node : public p_node
 | 
        
           |  |  | 55 | 		{
 | 
        
           |  |  | 56 | 			int index;
 | 
        
           |  |  | 57 | 			bob_dom_point *pnt;
 | 
        
           |  |  | 58 | 			pp_node() { pnt=0; index=0; }
 | 
        
           |  |  | 59 | 		};
 | 
        
           |  |  | 60 |   | 
        
           |  |  | 61 | 		p_node m_root;
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 | 		p_node * addNode(p_node *parent, unsigned char id)
 | 
        
           |  |  | 64 | 		{
 | 
        
           |  |  | 65 | 			p_node *n, *old;
 | 
        
           |  |  | 66 | 			for(n=parent->child; n!=NULL; old=n, n=n->next){
 | 
        
           |  |  | 67 | 				m_compCount++;
 | 
        
           |  |  | 68 | 				if(n->id==id) return n;
 | 
        
           |  |  | 69 | 			}
 | 
        
           |  |  | 70 | 			if(parent->child==NULL)
 | 
        
           |  |  | 71 | 				n=parent->child=new p_node();
 | 
        
           |  |  | 72 | 			else
 | 
        
           |  |  | 73 | 				n=old->next=new p_node();
 | 
        
           |  |  | 74 | 			n->id=id;
 | 
        
           |  |  | 75 | 			return n;
 | 
        
           |  |  | 76 | 		}
 | 
        
           |  |  | 77 |   | 
        
           |  |  | 78 | 		pp_node * addPPNode(p_node *parent)
 | 
        
           |  |  | 79 | 		{
 | 
        
           |  |  | 80 | 			p_node *n, *old;
 | 
        
           |  |  | 81 | 			pp_node *pp;
 | 
        
           |  |  | 82 | 			for(n=parent->child; n!=NULL; old=n, n=n->next)
 | 
        
           |  |  | 83 | 				;;
 | 
        
           |  |  | 84 |   | 
        
           |  |  | 85 | 			if(parent->child==NULL)
 | 
        
           |  |  | 86 | 				parent->child=pp=new pp_node();
 | 
        
           |  |  | 87 | 			else
 | 
        
           |  |  | 88 | 				old->next=pp=new pp_node();
 | 
        
           |  |  | 89 | 			return pp;
 | 
        
           |  |  | 90 | 		}
 | 
        
           |  |  | 91 |   | 
        
           |  |  | 92 | 		p_node * findNode(p_node *parent, unsigned char id)
 | 
        
           |  |  | 93 | 		{
 | 
        
           |  |  | 94 | 			p_node *ch;
 | 
        
           |  |  | 95 | 			for(ch=parent->child; ch!=NULL; ch=ch->next){
 | 
        
           |  |  | 96 | 				if(ch->id==id) return ch;
 | 
        
           |  |  | 97 | 			}
 | 
        
           |  |  | 98 | 			return NULL;
 | 
        
           |  |  | 99 | 		}
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 | 		void deleteChilds(p_node *parent)
 | 
        
           |  |  | 102 | 		{
 | 
        
           |  |  | 103 | 			p_node *ch, *old;
 | 
        
           |  |  | 104 | 			for(old=0, ch=parent->child; ch!=NULL; old=ch, ch=ch->next){
 | 
        
           |  |  | 105 | 				deleteChilds(ch);
 | 
        
           |  |  | 106 | 				delete old;
 | 
        
           |  |  | 107 | 			}
 | 
        
           |  |  | 108 | 			delete old;
 | 
        
           |  |  | 109 | 		}
 | 
        
           |  |  | 110 |   | 
        
           |  |  | 111 | 	private:
 | 
        
           |  |  | 112 | 		typedef ext::array<bob_dom_point*> point_array;
 | 
        
           |  |  | 113 | 		typedef ext::array<int> int_array;
 | 
        
           |  |  | 114 | 		typedef ext::simple_list<int> int_list;
 | 
        
           |  |  | 115 |   | 
        
           |  |  | 116 | 		point_array m_points; // all points
 | 
        
           |  |  | 117 | 		int_array m_indexes; // converted indexes
 | 
        
           |  |  | 118 | 		int m_pointSize; // size of points
 | 
        
           |  |  | 119 |   | 
        
           |  |  | 120 | 		int_list m_uniqueIndexes; // list of indexes to unique points in points array
 | 
        
           |  |  | 121 | 		int_list::iterator m_unique_it;
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 | 	public:
 | 
        
           |  |  | 124 | 		class point_rec
 | 
        
           |  |  | 125 | 		{
 | 
        
           |  |  | 126 | 			private:
 | 
        
           |  |  | 127 | 				const pp_node *m_node;
 | 
        
           |  |  | 128 |   | 
        
           |  |  | 129 | 			public:
 | 
        
           |  |  | 130 | 				point_rec(const pp_node *node) { m_node=node; }
 | 
        
           |  |  | 131 | 				point_rec(const point_rec& other) { m_node=other.m_node; }
 | 
        
           |  |  | 132 |   | 
        
           |  |  | 133 | 				bob_dom_point * operator *() { return m_node->pnt; }
 | 
        
           |  |  | 134 | 		};
 | 
        
           |  |  | 135 |   | 
        
           |  |  | 136 | 		class point_bucket
 | 
        
           |  |  | 137 | 		{
 | 
        
           |  |  | 138 | 			private:
 | 
        
           |  |  | 139 | 				size_t m_size;
 | 
        
           |  |  | 140 | 				const pp_node *m_first;
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 | 			public:
 | 
        
           |  |  | 143 | 				size_t size() const { return m_size; }
 | 
        
           |  |  | 144 |   | 
        
           |  |  | 145 | 				point_bucket(const pp_node *first)
 | 
        
           |  |  | 146 | 				{
 | 
        
           |  |  | 147 | 					m_first=first;
 | 
        
           |  |  | 148 | 					m_size=0;
 | 
        
           |  |  | 149 | 					for(const p_node *n=m_first; n!=0; n=n->next)
 | 
        
           |  |  | 150 | 						m_size++;
 | 
        
           |  |  | 151 | 				}
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 | 				point_bucket(const point_bucket& other) { m_size=other.m_size; m_first=other.m_first; }
 | 
        
           |  |  | 154 |   | 
        
           |  |  | 155 | 				int index() { return m_first->index; }
 | 
        
           |  |  | 156 | 				void index(int idx) { ((pp_node*)m_first)->index=idx; }
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 | 				point_rec operator[](size_t idx)
 | 
        
           |  |  | 159 | 				{
 | 
        
           |  |  | 160 | 					size_t i;
 | 
        
           |  |  | 161 | 					const p_node *n;
 | 
        
           |  |  | 162 | 					for(n=m_first, i=0; i < idx; i++, n=n->next)
 | 
        
           |  |  | 163 | 						;;
 | 
        
           |  |  | 164 | 					return point_rec((const pp_node*)n);
 | 
        
           |  |  | 165 | 				}
 | 
        
           |  |  | 166 | 		};
 | 
        
           |  |  | 167 | 	private:
 | 
        
           |  |  | 168 | 		point_bucket _addPoint(bob_dom_point *pnt)
 | 
        
           |  |  | 169 | 		{
 | 
        
           |  |  | 170 | 			p_node *n;
 | 
        
           |  |  | 171 | 			int v;
 | 
        
           |  |  | 172 | 			v=pnt->x;
 | 
        
           |  |  | 173 | 			n=&m_root;
 | 
        
           |  |  | 174 | 			unsigned char id;
 | 
        
           |  |  | 175 | 			for(int i=3; i >= 0; i--){
 | 
        
           |  |  | 176 | 				id=v >> (i * 8);
 | 
        
           |  |  | 177 | 				n=addNode(n, id);
 | 
        
           |  |  | 178 | 			}
 | 
        
           |  |  | 179 |   | 
        
           |  |  | 180 | 			v=pnt->y;
 | 
        
           |  |  | 181 | 			for(int i=3; i >= 0; i--){
 | 
        
           |  |  | 182 | 				id=v >> (i * 8);
 | 
        
           |  |  | 183 | 				n=addNode(n, id);
 | 
        
           |  |  | 184 | 			}
 | 
        
           |  |  | 185 |   | 
        
           |  |  | 186 | 			v=pnt->z;
 | 
        
           |  |  | 187 | 			for(int i=3; i >= 0; i--){
 | 
        
           |  |  | 188 | 				id=v >> (i * 8);
 | 
        
           |  |  | 189 | 				n=addNode(n, id);
 | 
        
           |  |  | 190 | 			}
 | 
        
           |  |  | 191 |   | 
        
           |  |  | 192 | 			pp_node *pp=addPPNode(n);
 | 
        
           |  |  | 193 | 			pp->pnt=pnt;
 | 
        
           |  |  | 194 |   | 
        
           |  |  | 195 | 			return point_bucket((pp_node*)n->child);
 | 
        
           |  |  | 196 | 		}
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 | 	public:
 | 
        
           |  |  | 199 | 		typedef point_array::iterator iterator;
 | 
        
           |  |  | 200 | 		typedef int_list::const_iterator const_index_iterator;
 | 
        
           |  |  | 201 |   | 
        
           |  |  | 202 | 		iterator begin() { return m_points.begin(); }
 | 
        
           |  |  | 203 | 		iterator end() { return m_points.end(); }
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 | 		const_index_iterator indexBegin() const { return m_uniqueIndexes.begin(); }
 | 
        
           |  |  | 206 | 		const_index_iterator indexEnd() const { return m_uniqueIndexes.end(); }
 | 
        
           |  |  | 207 |   | 
        
           |  |  | 208 | 		//>>>>>>>>>>>>>
 | 
        
           |  |  | 209 | 		//bob_point_bst map2;
 | 
        
           |  |  | 210 | 		//<<<<<<<<<<<<<
 | 
        
           |  |  | 211 |   | 
        
           |  |  | 212 | 		size_t m_compCount;
 | 
        
           |  |  | 213 |   | 
        
           |  |  | 214 | 		void create(size_t size)
 | 
        
           |  |  | 215 | 		{
 | 
        
           |  |  | 216 | 			m_points.resize(size, 0);
 | 
        
           |  |  | 217 | 			m_indexes.resize(size);
 | 
        
           |  |  | 218 | 			m_pointSize=0;
 | 
        
           |  |  | 219 | 			m_compCount=0;
 | 
        
           |  |  | 220 | 		}
 | 
        
           |  |  | 221 |   | 
        
           |  |  | 222 | 		void addPoint(bob_dom_point * pnt)
 | 
        
           |  |  | 223 | 		{
 | 
        
           |  |  | 224 | 			point_bucket pb=_addPoint(pnt);
 | 
        
           |  |  | 225 |   | 
        
           |  |  | 226 | 			if(pb.size() == 1){
 | 
        
           |  |  | 227 | 				pb.index((int)m_uniqueIndexes.size());
 | 
        
           |  |  | 228 | 				m_uniqueIndexes.push_back(m_pointSize);
 | 
        
           |  |  | 229 | 			}
 | 
        
           |  |  | 230 | 			m_points[m_pointSize]=pnt;
 | 
        
           |  |  | 231 | 			m_indexes[m_pointSize]=pb.index();
 | 
        
           |  |  | 232 | 			m_pointSize++;
 | 
        
           |  |  | 233 |   | 
        
           |  |  | 234 | 			//map2.addPoint(pnt);
 | 
        
           |  |  | 235 | 		}
 | 
        
           |  |  | 236 |   | 
        
           |  |  | 237 | 		// c-tor
 | 
        
           |  |  | 238 | 		bob_point_map() { m_pointSize=0; m_unique_it=m_uniqueIndexes.end(); }
 | 
        
           |  |  | 239 | 		// d-tor
 | 
        
           |  |  | 240 | 		~bob_point_map() { clear(); }
 | 
        
           |  |  | 241 |   | 
        
           |  |  | 242 | 		void clear()
 | 
        
           |  |  | 243 | 		{
 | 
        
           |  |  | 244 | 			deleteChilds(&m_root); m_root.child=0;
 | 
        
           |  |  | 245 |   | 
        
           |  |  | 246 | 			for(point_array::iterator &it=m_points.begin(); it!=m_points.end(); ++it){
 | 
        
           |  |  | 247 | 				delete *it;
 | 
        
           |  |  | 248 | 			}
 | 
        
           |  |  | 249 | 			m_points.clear();
 | 
        
           |  |  | 250 | 			m_indexes.clear();
 | 
        
           |  |  | 251 | 			m_pointSize=0;
 | 
        
           |  |  | 252 |   | 
        
           |  |  | 253 | 			m_unique_it=m_uniqueIndexes.end();
 | 
        
           |  |  | 254 | 		}
 | 
        
           |  |  | 255 |   | 
        
           |  |  | 256 | 		bob_dom_point * operator[](int idx) { return m_points[idx]; }
 | 
        
           |  |  | 257 | 		const bob_dom_point * operator[](int idx) const { return m_points[idx]; }
 | 
        
           |  |  | 258 |   | 
        
           |  |  | 259 | 		int uniqueIndex(int idx) const { return (size_t)idx < m_points.size() ? m_indexes[idx] : -1; }
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 | 		size_t pointsSize() const { return m_points.size(); }
 | 
        
           |  |  | 262 | 		size_t uniquePointsSize() const { return m_uniqueIndexes.size(); }
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 | 		bob_dom_point * nextUniquePoint()
 | 
        
           |  |  | 265 | 		{
 | 
        
           |  |  | 266 | 			++m_unique_it;
 | 
        
           |  |  | 267 | 			bob_dom_point *p=(m_unique_it!=m_uniqueIndexes.end() ? m_points[*m_unique_it] : 0);
 | 
        
           |  |  | 268 | 			return p;
 | 
        
           |  |  | 269 | 		}
 | 
        
           |  |  | 270 | };
 | 
        
           |  |  | 271 |   | 
        
           |  |  | 272 | #endif // !defined(BOB_POINT_MAP_INCLUDED)
 |