c++ - Storing a billion polygons in quad-tree -


i need store 1 billion spatial polygons (specified using minimum bounding rectangles) in quad-tree. doing so, wrote following code. however, turns out 1 billion points code running slowly. there way may improve code may run bit faster. if yes, can please same

//--------------------------------------------------------------------------- struct mbr {     double xright, xleft, ybottom, ytop;     mbr *zero,*first,*second,*third;     unsigned level=0;     vector<unsigned> result; //contains resulting intersecting spatial ids }; bool intersects(mbr& spatialid,mbr& mbr)  {     if (mbr.ybottom > spatialid.ytop || mbr.ytop < spatialid.ybottom) return false;     if (mbr.xleft > spatialid.xright || mbr.xright < spatialid.xleft) return false;             return true;     } //--------------------------------------------------------------------------- bool contains(mbr& spatialid,mbr& mbr)  {     if (mbr.ybottom > spatialid.ybottom || mbr.ytop < spatialid.ytop) return false;     if (mbr.xleft > spatialid.xleft || mbr.xright < spatialid.xright) return false;     return true;     } //--------------------------------------------------------------------------- bool touches(mbr& spatialid,mbr& mbr)  {     if (    (mbr.ybottom >= spatialid.ybottom + std::numeric_limits<double>::epsilon() &&              mbr.ybottom <= spatialid.ybottom - std::numeric_limits<double>::epsilon()) ||             (mbr.ytop >= spatialid.ytop + std::numeric_limits<double>::epsilon() &&             mbr.ytop <= spatialid.ytop - std::numeric_limits<double>::epsilon()))             return true;     if (    (mbr.xleft >= spatialid.xleft + std::numeric_limits<double>::epsilon() &&             mbr.xleft <= spatialid.xleft - std::numeric_limits<double>::epsilon()) ||             (mbr.xright >= spatialid.xright + std::numeric_limits<double>::epsilon() &&             mbr.xright <= spatialid.xright - std::numeric_limits<double>::epsilon()))             return true;         return false;     } //--------------------------------------------------------------------------- mbr mbr1,mbr2,mbr3,mbr4; vector<unsigned> spatialids; //contain 1 billion spatial identifiers intersected mbr1, mbr2, mbr3, mbr4 //mbr1, mbr2, mbr3, mbr4 again specified using minimum bounding rectangles     stack<mbr**> stackquadtree; mbr *root=new mbr(); (*root).ybottom=-90; (*root).ytop=90; (*root).xleft=-180; (*root).xright=180; (*root).level=0; stackquadtree.push(&root);  while(!stackquadtree.empty()) {     mbr** node=&(*stackquadtree.front());     if((*node)->level==50)         break;      (*node)->zero=new mbr(); (*node)->first=new mbr(); (*node)->second=new mbr(); (*node)->third=new mbr();     (*node)->zero->ybottom=(*node)->ybottom; (*node)->zero->ytop=((*node)->ybottom+(*node)->ytop)/2;     (*node)->zero->xleft=(*node)->xleft; (*node)->zero->xright=((*node)->xleft+(*node)->xright)/2;                             (*node)->zero->level=(*node)->level+1;      (*node)->first->ybottom=((*node)->ybottom+(*node)->ytop)/2; (*node)->first->ytop=(*node)->ytop;      (*node)->first->xleft=(*node)->xleft; (*node)->first->xright=((*node)->xleft+(*node)->xright)/2;               (*node)->first->level=(*node)->level+1;      (*node)->second->ybottom=(*node)->ybottom; (*node)->second->ytop=((*node)->ybottom+(*node)->ytop)/2;     (*node)->second->xleft=((*node)->xleft+(*node)->xright)/2; (*node)->second->xright=(*node)->xright;             (*node)->second->level=(*node)->level+1;      (*node)->third->ybottom=((*node)->ybottom+(*node)->ytop)/2; (*node)->third->ytop=(*node)->ytop;     (*node)->third->xleft=((*node)->xleft+(*node)->xright)/2; (*node)->third->xright=(*node)->xright;                             (*node)->third->level=(*node)->level+1;      mbr* node=*stackquadtree.top();     stackquadtree.pop();             for(vector<mbr>::iterator itspatialid=spatialids.begin(),lspatialid=spatialids.end();itspatialid!=lspatialid;++itspatialid)     {         if(intersects((*itspatialid),&(*node)->zero)||contains((*itspatialid),&(*node)->zero)||touches((*itspatialid),&(*node)->zero))         {             (*node)->zero->result.push_back((*itspatialid));             stackquadtree.push(*(*node)->zero);         }          if(intersects((*itspatialid),&(*node)->first)||contains((*itspatialid),&(*node)->first)||touches((*itspatialid),&(*node)->first))         {             (*node)->first->result.push_back((*itspatialid));             stackquadtree.push(*(*node)->first);         }                              if(intersects((*itspatialid),&(*node)->second)||contains((*itspatialid),&(*node)->second)||touches((*itspatialid),&(*node)->second))         {             (*node)->second->result.push_back((*itspatialid));             stackquadtree.push(*(*node)->second);         }             if(intersects((*itspatialid),&(*node)->third)||contains((*itspatialid),&(*node)->third)||touches((*itspatialid),&(*node)->third))         {             (*node)->third->result.push_back((*itspatialid));             stackquadtree.push(*(*node)->third);         }        } } 

log2(1 billion) approximately 30

in order reduce operations count, consider data structure more rapidly gets right neighborhood.

for example, if know objects located within grid 10km x 10km, consider breaking down 10x10 grid (1kmx1km) then, object falls within particular grid can jump 1% of objects (assuming evenly distributed).

obviously, can have recursive structure, don't need more 1 or 2 10x10 splits. why not try top level, each subgrid quadtree?

i notice have odd construction:

mbr.ytop >= spatialid.ytop + std::numeric_limits<double>::epsilon()  

i think can simplify to:

spatialid.ytop < mbr.ytop 

that kind of definition of floating point resolution, isn't it? if i'm right, should speed code lot that's constant factor.

class grid { private:   stackquadtree qt[100]; // 10x10 array of quadtrees public:   grid(double xmin, double xmax, double ymin, double ymax) {     // store 10x10 grid in grid object     gridsizex = 1/10 of size of grid in x     gridsizey = 1/10 of size of grid in y   }    stackquadtree& findgrid(mbr& mbr) {     int = (mbr.xleft - xmin) / gridsizex;     int j = (mbr.ytop - ymin) / gridsizey;     return qt[i*10+j];   }    void add(mbr& mbr) {     // add right quadtree , add object in   } }; 

Comments