28 #include <boost/archive/basic_archive.hpp> 29 #include <boost/serialization/vector.hpp> 30 #include <boost/algorithm/string.hpp> 31 #include <boost/iostreams/device/mapped_file.hpp> 39 #define NUM_CHILDREN 50 40 #define LEAF_SIZE (16 * 1024) 42 template <
class id_t,
class data_t>
47 template <
class _id_t,
class _data_t,
48 size_t leaf_elements = ((
LEAF_SIZE -
sizeof(uint16_t)) / (
sizeof(uint32_t) +
sizeof(data_t)))>
54 _id_t
ids[leaf_elements];
55 _data_t
data[leaf_elements];
68 bool isFull() {
return (size == leaf_elements); }
85 children[
size] = index;
90 bool isLeaf()
const {
return (size > 0 && children[0] == (uint32_t) -1); }
93 friend class boost::serialization::access;
94 template<
typename Archive>
104 void build(std::vector<data_t>&
data,
const string& leafPath);
105 bool search ( boost::shared_ptr<std::vector<id_t> >& result,
106 const FixedRect& rect,
bool returnOnFirst =
false )
const;
109 shared_ptr<std::vector<id_t> > geoIDs = boost::make_shared< std::vector<id_t> >();
110 return search(geoIDs, rect,
true);
116 input.open(path, length, offset);
117 if (!
input.is_open())
125 boost::iostreams::mapped_file_source
input;
129 void buildLeaves (
const std::vector<data_t>& rects,
const string& leafPath);
130 void writeLeaves (
const std::vector<id_t>&
ids,
const std::vector<data_t>& rects,
const string& leafPath);
133 void getSubTree ( uint32_t rootIdx, boost::shared_ptr<std::vector<id_t> >&
ids )
const;
141 boost::shared_ptr<std::vector<id_t> >& result,
143 bool returnOnFirst)
const;
145 boost::shared_ptr<std::vector<id_t> >& result,
147 bool returnOnFirst)
const;
154 friend class boost::serialization::access;
155 template<
typename Archive>
159 template<
typename Archive>
164 BOOST_SERIALIZATION_SPLIT_MEMBER()
168 template<
class id_t,
class data_t>
171 LOG_SEV(geo_log, info) <<
"Objects: " << data.size();
177 LOG_SEV(geo_log, info) <<
" - build levels";
180 LOG_SEV(geo_log, info) <<
" - reverse";
181 std::reverse(
tree.begin(),
tree.end());
188 node.children[i] = tree.size() - 1 - node.children[i];
194 template<
class id_t,
class data_t>
202 template<
class id_t,
class data_t>
209 template<
class id_t,
class data_t>
217 template<
class id_t,
class data_t>
223 template<
class id_t,
class data_t>
226 LOG_SEV(geo_log, info) <<
" - computing ids";
227 std::vector<id_t>
ids;
228 for (
int i = 0; i < data.size(); i++)
229 ids.push_back(id_t(i));
231 LOG_SEV(geo_log, info) <<
" - sorting leaves";
232 std::sort(ids.begin(), ids.end(),
235 return (this->
getX(data[a.getRaw()]) < this->
getX(data[b.getRaw()]));
242 size_t p = ceil(data.size() / (double) n);
244 size_t s = ceil(sqrt(p));
248 for (
size_t start = 0; start < data.size(); start += t)
250 size_t end = start + t;
251 if ( end > data.size() )
255 std::sort(ids.begin()+start, ids.begin()+end,
258 return (this->
getY(data[a.getRaw()]) < this->
getY(data[b.getRaw()]));
267 template<
class id_t,
class data_t>
269 const std::vector<data_t>&
data,
270 const string& leafPath)
272 LOG_SEV(geo_log, info) <<
" - writing leaves";
274 std::ofstream output(leafPath, std::ios::out | std::ios::binary);
281 leaf.
addData(data[
id.getRaw()],
id);
288 tree.push_back(node);
292 output.write((
char*) &leaf,
sizeof(leaf));
304 tree.push_back(node);
308 output.write((
char*) &leaf,
sizeof(leaf));
313 tree.push_back(node);
317 template<
class id_t,
class data_t>
321 size_t end =
tree.size() - 1;
331 for (
size_t i = start; i <= end; i++)
337 tree.push_back(node);
344 tree.push_back(node);
349 end =
tree.size() - 1;
352 LOG_SEV(geo_log, info) <<
" -> " << levels <<
" levels.";
356 template<
class id_t,
class data_t>
369 template<
class id_t,
class data_t>
372 for (
int i = 0; i <
tree.size(); i++)
379 for (
int c = 0; c < node.
size; c++)
383 if (bounds != node.
bounds[c])
389 for (
int c = 0; c < node.
size; c++)
391 uint32_t childIdx = node.
children[c];
393 if (bounds != node.
bounds[c])
402 template<
class id_t,
class data_t>
404 boost::shared_ptr<std::vector<id_t> >& result,
406 bool returnOnFirst)
const 408 for (
int j = 0; j < leaf->
size; j++)
414 result->push_back(leaf->
ids[j]);
422 template<
class id_t,
class data_t>
424 boost::shared_ptr<std::vector<id_t> >& result,
426 bool returnOnFirst)
const 428 for (
int j = 0; j < leaf->
size; j++)
434 result->push_back(leaf->
ids[j]);
442 template<
class id_t,
class data_t>
445 bool returnOnFirst)
const 447 if (
tree.size() == 0)
451 std::stack<uint32_t> stack;
456 uint32_t idx = stack.top();
464 for (
int i = 0; i < node.
size; i++)
473 result->insert(result->end(), &leaf->
ids[0], &leaf->
ids[leaf->
size]);
479 bool containedData =
searchLeaf(leaf, result, rect, returnOnFirst);
481 if (returnOnFirst && containedData)
490 for (
int i = 0; i < node.
size; i++)
506 }
while (!stack.empty());
508 return (result->size() > 0);
512 template<
class id_t,
class data_t>
515 std::stack<uint32_t> subTreeStack;
516 subTreeStack.push(rootIdx);
520 uint32_t idx = subTreeStack.top();
526 for (
int i = 0; i < node.
size; i++)
534 for (
int i = 0; i < node.
size; i++)
535 subTreeStack.push(node.
children[i]);
537 }
while (!subTreeStack.empty());
541 template<
class id_t,
class data_t>
546 for (
int i = 1; i <
size; i++)
553 template<
class id_t,
class data_t>
556 FixedRect bound(keys[0].x, keys[0].y, keys[0].x, keys[0].y);
558 for (
int i = 1; i <
size; i++)
565 template<
class id_t,
class data_t>
568 std::ofstream log(leafPath +
".log", std::ios::out);
570 for (
int i =
tree.size() - 1; i >= 0 &&
tree[i].isLeaf(); i--)
573 for (
int c = 0; c <
tree[i].size; c++)
576 log <<
"R(" << r.
minX <<
", " << r.
minY <<
", " << r.
maxX <<
", " << r.
maxY <<
"), ";
583 template<
class id_t,
class data_t>
588 while (start <
tree.size())
590 if (
tree[start].isLeaf()) {
593 for (
int c = 0; c <
tree[start].size; c++)
596 printf(
" %i", leafID);
602 size_t end =
tree[start].children[
tree[start].size - 1];
603 for (
int i = start; i < end; i++)
607 for (
int c = 0; c < node.
size; c++)
void build(std::vector< data_t > &data, const string &leafPath)
starts to build the tree for the given data
bool searchLeaf(const RLeaf< id_t, FixedPoint > *leaf, boost::shared_ptr< std::vector< id_t > > &result, const FixedRect &rect, bool returnOnFirst) const
Specialisation for point based data.
_data_t data[leaf_elements]
void save(Archive &ar, const unsigned int version) const
void getSubTree(uint32_t rootIdx, boost::shared_ptr< std::vector< id_t > > &ids) const
used when a sub-tree is fully contained in the search rectangle
uint8_t size
number of contained elements
bool intersects(const basic_rect< T > &bounding) const
void printTree() const
For debugging.
FixedRect getBoundingBox(const FixedRect keys[], size_t size) const
size muste be greater than 0
void buildLeaves(const std::vector< data_t > &rects, const string &leafPath)
bool contains(const basic_vector2< T > &p) const
bool contains(const FixedRect &rect) const
void load(Archive &ar, const unsigned int version)
static size_t num_elements()
std::vector< RNode > tree
void buildLevels()
builds all levels above leafs
boost::iostreams::mapped_file_source input
#define LOG_SEV(log, lvl)
bool search(boost::shared_ptr< std::vector< id_t > > &result, const FixedRect &rect, bool returnOnFirst=false) const
if returnOnFirst is set it return true if it found data in the querry rectangle
Thrown if a file was not found.
uint16_t size
number of contained elements
void enclose(const basic_rect< T > &other)
void writeLeaves(const std::vector< id_t > &ids, const std::vector< data_t > &rects, const string &leafPath)
Fills first tree layer for leaf RNode objects an saves RLeaf objects to file.
FixedRect bounds[NUM_CHILDREN]
uint32_t children[NUM_CHILDREN]
coord_t getX(const FixedPoint &p)
get x coordinate of point based types
void addData(const _data_t &d, _id_t id)
coord_t getY(const FixedPoint &p)
get x coordinate of point based types
void serialize(Archive &ar, const unsigned int version)
bool validate() const
debugging function to check validity of bounding boxes
boost::error_info< struct TagFileName, string > InfoFileName
Use this to inform about a file name.
void setLeafFile(const string &path, uint64_t offset, uint64_t length)
is called after deserialisation to set offets in the archive
void printLeaves(const string &leafPath) const
For debugging.
RLeaf< id_t, data_t > * readLeaf(uint32_t nodeIdx, uint32_t childIdx) const
reads a leaf from file
void addChild(const FixedRect &bound, uint32_t index=(uint32_t)-1)
basic_vector2< T > getCenter() const