Grid.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. #define MAX_NORMAL 1743392200 // -MAX_NORMAL .. MAX_NORMAL is the biggest normal cell that doesn't overflow
  5. /******************************************************************************
  6. Grid supports all indexes (INT_MIN .. INT_MAX)
  7. Sample Grid:
  8. ((-13 -12 -11) (-10 -9 -8) (-7 -6 -5)) ((-4 -3 -2) (-1 0 1) (2 3 4)) ((5 6 7) (8 9 10) (11 12 13))
  9. \ | / \ | / \ | /
  10. \ | / \ | / \ | /
  11. \ | / \ | / \ | /
  12. -13, -11, -8, -5 -4, -2, 1, 4 5, 7, 10, 13
  13. \ | /
  14. \ | /
  15. \ | /
  16. -13 -5 4 13
  17. -40 -14 -13 -5 4 13 14 40
  18. /******************************************************************************
  19. Normally _x[1], _x[2], _x[3] don't overlap, however around INT_MIN/INT_MAX there's special case when they can, because of int range clamping inside 'createAsParent'
  20. _y[1], _y[2], _y[3]
  21. Because of this, all codes should check first for _x[1], then for _x[2], then for _x[3], and not for example:
  22. -some codes check first for _x[1], then for _x[2], then for _x[3]
  23. -some other codes check first for _x[3], then for _x[2], then for _x[1]
  24. /******************************************************************************/
  25. // MANAGE
  26. /******************************************************************************/
  27. void _Cell::del(_Grid &grid)
  28. {
  29. // delete children
  30. REPA(_g)if(_g[i])_g[i]->del(grid);
  31. // first delete the data because as they exist in this area, they still can reference the area
  32. if(_data)
  33. {
  34. if(grid._del)grid._del(_data);else Exit("'_Cell.del' Cell has data but no data destructor");
  35. }
  36. // then remove from grid and parent
  37. if(final() && Cuts(xy(), grid._fast_access_rect))grid.fastAccessCell(xy())=null;
  38. if(_parent)
  39. {
  40. _Cell *(&pg)[9]=_parent->_g;
  41. REPA(pg)if(pg[i]==this){Delete(pg[i]); return;} // !! 'this' is now DELETED, therefore return IMMEDIATELY !!
  42. }
  43. }
  44. _Cell* _Cell::create(Int x, Int y, _Cell *parent, _Grid &grid)
  45. {
  46. T._x[0]=T._x[1]=T._x[2]=T._x[3]=x;
  47. T._y[0]=T._y[1]=T._y[2]=T._y[3]=y;
  48. T._parent=parent;
  49. if(Cuts(xy(), grid._fast_access_rect))grid.fastAccessCell(xy())=this;
  50. if(grid._new)grid._new(_data, VecI2(x, y), grid.user); // call this at the end, when the _Cell is ready
  51. return this;
  52. }
  53. _Cell* _Cell::create(Int x0, Int y0, Int x1, Int y1, _Cell *parent, _Grid &grid)
  54. {
  55. // need to check for x0>=x1 and y0>=y1 because outside MAX_NORMAL range, one index can overlap, but other not (for example x0=x1=-9, but y0=0, y1=4, x is the same, but y different)
  56. if(x0>=x1){if(y0>=y1)return create(x1, y1, parent, grid); _x[0]=_x[1]=_x[2]=_x[3]=x1;}else{_x[0]=x0; _x[3]=x1; UInt dx=x1-x0; if(dx>=3)dx-=2; dx/=3; _x[1]=x0+dx; _x[2]=x0+dx*2+1;} // {use x1 instead of x0 beacuse x0 is set as parent+1 and may be out of range} else {this avoids under/over-flow: _x[1]=x0+(x1-x0-2)/3; _x[2]=x0+(x1-x0-2)/3*2+1;}
  57. if(y0>=y1){ _y[0]=_y[1]=_y[2]=_y[3]=y1;}else{_y[0]=y0; _y[3]=y1; UInt dy=y1-y0; if(dy>=3)dy-=2; dy/=3; _y[1]=y0+dy; _y[2]=y0+dy*2+1;} // {use y1 instead of y0 beacuse y0 is set as parent+1 and may be out of range} else {this avoids under/over-flow: _y[1]=y0+(y1-y0-2)/3; _y[2]=y0+(y1-y0-2)/3*2+1;}
  58. T._parent=parent;
  59. #if 0 // normally this should be:
  60. DEBUG_ASSERT(_x[0]<=_x[1] && _x[1]<_x[2] && _x[2]<_x[3]
  61. && _y[0]<=_y[1] && _y[1]<_y[2] && _y[2]<_y[3], "Grid invalid indexes");
  62. #else // however around INT_MIN/INT_MAX there's special case where indexes overlap
  63. DEBUG_ASSERT(_x[0]<=_x[1] && _x[1]<=_x[2] && _x[2]<=_x[3]
  64. && _y[0]<=_y[1] && _y[1]<=_y[2] && _y[2]<=_y[3], "Grid invalid indexes");
  65. #endif
  66. return this;
  67. }
  68. _Cell* _Cell::createAsParent(_Cell *child, _Grid &grid)
  69. {
  70. // align
  71. Int cx=child->_x[0],
  72. cy=child->_y[0];
  73. Long x=cx, y=cy, div=ULong(Long(child->_x[3])-x+1)*3, div_2=div/2;
  74. // formula below works as 'AlignRound', it's needed so the parent will contain the child, it will always create parents at the same coordinates regardless where the first cell was located (for example, if first element is -13, then parent will always be correctly aligned, and located towards zero)
  75. if(x>0)x+=div_2;else x-=div_2; x=(x/div)*div;
  76. if(y>0)y+=div_2;else y-=div_2; y=(y/div)*div;
  77. // create new root
  78. Long x0=x-div_2, x1=x+div_2,
  79. y0=y-div_2, y1=y+div_2;
  80. if(x0<INT_MIN || x1>INT_MAX
  81. || y0<INT_MIN || y1>INT_MAX) // if any index overflows
  82. {
  83. DEBUG_ASSERT(cx==-MAX_NORMAL && child->_x[3]==MAX_NORMAL
  84. && cy==-MAX_NORMAL && child->_y[3]==MAX_NORMAL, "invalid max child size");
  85. // setup middle to be exactly as the child
  86. T._x[0]=INT_MIN; T._x[1]=cx-1; T._x[2]=child->_x[3]; T._x[3]=INT_MAX;
  87. T._y[0]=INT_MIN; T._y[1]=cy-1; T._y[2]=child->_y[3]; T._y[3]=INT_MAX;
  88. T._parent=null;
  89. }else create(x0, y0, x1, y1, null, grid);
  90. // link
  91. DEBUG_ASSERT(child->_x[0]>=T._x[0] && child->_x[3]<=T._x[3]
  92. && child->_y[0]>=T._y[0] && child->_y[3]<=T._y[3], "Grid parent doesn't contain child");
  93. if(cx<=T._x[1])
  94. {
  95. if(cy<=T._y[1])_lb=child;else
  96. if(cy<=T._y[2])_l =child;else
  97. _lf=child;
  98. }else
  99. if(cx<=T._x[2])
  100. {
  101. if(cy<=T._y[1]) _b=child;else
  102. if(cy<=T._y[2]) _c=child;else
  103. _f=child;
  104. }else
  105. {
  106. if(cy<=T._y[1])_rb=child;else
  107. if(cy<=T._y[2])_r =child;else
  108. _rf=child;
  109. }
  110. child->_parent=this;
  111. return this;
  112. }
  113. /******************************************************************************/
  114. // GET / FIND
  115. /******************************************************************************/
  116. _Cell* _Cell::get(C VecI2 &xy, _Grid &grid)
  117. {
  118. if(xy.x>=T._x[0] && xy.x<=T._x[3]
  119. && xy.y>=T._y[0] && xy.y<=T._y[3])
  120. {
  121. if(final())return this;
  122. if(xy.x<=T._x[1])
  123. {
  124. if(xy.y<=T._y[1]){if(!_lb)New(_lb)->create(T._x[0] , T._y[0] , T._x[1], T._y[1], this, grid); return _lb->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  125. if(xy.y<=T._y[2]){if(!_l )New(_l )->create(T._x[0] , T._y[1]+1, T._x[1], T._y[2], this, grid); return _l ->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  126. {if(!_lf)New(_lf)->create(T._x[0] , T._y[2]+1, T._x[1], T._y[3], this, grid); return _lf->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  127. }
  128. if(xy.x<=T._x[2])
  129. {
  130. if(xy.y<=T._y[1]){if(! _b)New( _b)->create(T._x[1]+1, T._y[0] , T._x[2], T._y[1], this, grid); return _b->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  131. if(xy.y<=T._y[2]){if(! _c)New( _c)->create(T._x[1]+1, T._y[1]+1, T._x[2], T._y[2], this, grid); return _c->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  132. {if(! _f)New( _f)->create(T._x[1]+1, T._y[2]+1, T._x[2], T._y[3], this, grid); return _f->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  133. }
  134. {
  135. if(xy.y<=T._y[1]){if(!_rb)New(_rb)->create(T._x[2]+1, T._y[0] , T._x[3], T._y[1], this, grid); return _rb->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  136. if(xy.y<=T._y[2]){if(!_r )New(_r )->create(T._x[2]+1, T._y[1]+1, T._x[3], T._y[2], this, grid); return _r ->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  137. {if(!_rf)New(_rf)->create(T._x[2]+1, T._y[2]+1, T._x[3], T._y[3], this, grid); return _rf->get(xy, grid);} // first allocate and assign, then create (in case child accesses grid)
  138. }
  139. }
  140. return null;
  141. }
  142. _Cell* _Cell::find(C VecI2 &xy)
  143. {
  144. if(xy.x>=T._x[0] && xy.x<=T._x[3]
  145. && xy.y>=T._y[0] && xy.y<=T._y[3])
  146. {
  147. if(final())return this;
  148. if(xy.x<=T._x[1])
  149. {
  150. if(xy.y<=T._y[1])return _lb ? _lb->find(xy) : null;
  151. if(xy.y<=T._y[2])return _l ? _l ->find(xy) : null;
  152. return _lf ? _lf->find(xy) : null;
  153. }
  154. if(xy.x<=T._x[2])
  155. {
  156. if(xy.y<=T._y[1])return _b ? _b->find(xy) : null;
  157. if(xy.y<=T._y[2])return _c ? _c->find(xy) : null;
  158. return _f ? _f->find(xy) : null;
  159. }
  160. {
  161. if(xy.y<=T._y[1])return _rb ? _rb->find(xy) : null;
  162. if(xy.y<=T._y[2])return _r ? _r ->find(xy) : null;
  163. return _rf ? _rf->find(xy) : null;
  164. }
  165. }
  166. return null;
  167. }
  168. /******************************************************************************/
  169. // SIZE
  170. /******************************************************************************/
  171. Bool _Cell::getLeft(Int &value)C
  172. {
  173. if(final())
  174. {
  175. if(x()<value)
  176. {
  177. value=x();
  178. return true;
  179. }
  180. }else
  181. {
  182. Bool ok=false;
  183. if(_x[0]<value) // some elements in range x0..x1 can decrease 'value'
  184. {
  185. if(_lf)ok|=_lf->getLeft(value);
  186. if(_l )ok|=_l ->getLeft(value);
  187. if(_lb)ok|=_lb->getLeft(value);
  188. if( ok)return true;
  189. }
  190. if(_x[1]+1<value) // some elements in range x1+1..x2 can decrease 'value'
  191. {
  192. if(_f)ok|=_f->getLeft(value);
  193. if(_c)ok|=_c->getLeft(value);
  194. if(_b)ok|=_b->getLeft(value);
  195. if(ok)return true;
  196. }
  197. if(_x[2]+1<value) // some elements in range x2+1..x3 can decrease 'value'
  198. {
  199. if(_rf)ok|=_rf->getLeft(value);
  200. if(_r )ok|=_r ->getLeft(value);
  201. if(_rb)ok|=_rb->getLeft(value);
  202. if( ok)return true;
  203. }
  204. }
  205. return false;
  206. }
  207. Bool _Cell::getRight(Int &value)C
  208. {
  209. if(final())
  210. {
  211. if(x()>value)
  212. {
  213. value=x();
  214. return true;
  215. }
  216. }else
  217. {
  218. Bool ok=false;
  219. if(_x[3]>value) // some elements in range x2+1..x3 can increase 'value'
  220. {
  221. if(_rf)ok|=_rf->getRight(value);
  222. if(_r )ok|=_r ->getRight(value);
  223. if(_rb)ok|=_rb->getRight(value);
  224. if( ok)return true;
  225. }
  226. if(_x[2]>value) // some elements in range x1+1..x2 can increase 'value'
  227. {
  228. if(_f)ok|=_f->getRight(value);
  229. if(_c)ok|=_c->getRight(value);
  230. if(_b)ok|=_b->getRight(value);
  231. if(ok)return true;
  232. }
  233. if(_x[1]>value) // some elements in range x0..x1 can increase 'value'
  234. {
  235. if(_lf)ok|=_lf->getRight(value);
  236. if(_l )ok|=_l ->getRight(value);
  237. if(_lb)ok|=_lb->getRight(value);
  238. if( ok)return true;
  239. }
  240. }
  241. return false;
  242. }
  243. Bool _Cell::getBottom(Int &value)C
  244. {
  245. if(final())
  246. {
  247. if(y()<value)
  248. {
  249. value=y();
  250. return true;
  251. }
  252. }else
  253. {
  254. Bool ok=false;
  255. if(_y[0]<value) // some elements in range y0..y1 can decrease 'value'
  256. {
  257. if(_lb)ok|=_lb->getBottom(value);
  258. if( _b)ok|= _b->getBottom(value);
  259. if(_rb)ok|=_rb->getBottom(value);
  260. if( ok)return true;
  261. }
  262. if(_y[1]+1<value) // some elements in range y1+1..y2 can decrease 'value'
  263. {
  264. if(_l)ok|=_l->getBottom(value);
  265. if(_c)ok|=_c->getBottom(value);
  266. if(_r)ok|=_r->getBottom(value);
  267. if(ok)return true;
  268. }
  269. if(_y[2]+1<value) // some elements in range y2+1..y3 can decrease 'value'
  270. {
  271. if(_lf)ok|=_lf->getBottom(value);
  272. if( _f)ok|= _f->getBottom(value);
  273. if(_rf)ok|=_rf->getBottom(value);
  274. if( ok)return true;
  275. }
  276. }
  277. return false;
  278. }
  279. Bool _Cell::getTop(Int &value)C
  280. {
  281. if(final())
  282. {
  283. if(y()>value)
  284. {
  285. value=y();
  286. return true;
  287. }
  288. }else
  289. {
  290. Bool ok=false;
  291. if(_y[3]>value) // some elements in range y2+1..y3 can increase 'value'
  292. {
  293. if(_lf)ok|=_lf->getTop(value);
  294. if( _f)ok|= _f->getTop(value);
  295. if(_rf)ok|=_rf->getTop(value);
  296. if( ok)return true;
  297. }
  298. if(_y[2]>value) // some elements in range y1+1..y2 can increase 'value'
  299. {
  300. if(_l)ok|=_l->getTop(value);
  301. if(_c)ok|=_c->getTop(value);
  302. if(_r)ok|=_r->getTop(value);
  303. if(ok)return true;
  304. }
  305. if(_y[1]>value) // some elements in range y0..y1 can increase 'value'
  306. {
  307. if(_lb)ok|=_lb->getTop(value);
  308. if( _b)ok|= _b->getTop(value);
  309. if(_rb)ok|=_rb->getTop(value);
  310. if( ok)return true;
  311. }
  312. }
  313. return false;
  314. }
  315. /******************************************************************************/
  316. // FUNC
  317. /******************************************************************************/
  318. void _Cell::func(void func(_Cell &cell, Ptr user), Ptr user)
  319. {
  320. if(final())func(T, user);else
  321. FREPA(_g)if(_g[i])_g[i]->func(func, user); // FREPA is faster in this case
  322. }
  323. void _Cell::func(C RectI &rect, void func(_Cell &cell, Ptr user), Ptr user)
  324. {
  325. if(rect.min.x<=T._x[3] && rect.max.x>=T._x[0]
  326. && rect.min.y<=T._y[3] && rect.max.y>=T._y[0])
  327. {
  328. if(final())func(T, user);else
  329. FREPA(_g)if(_g[i])_g[i]->func(rect, func, user); // FREPA is faster in this case
  330. }
  331. }
  332. void _Cell::funcCreate(C RectI &rect, void func(_Cell &cell, Ptr user), Ptr user, _Grid &grid)
  333. {
  334. if(rect.min.x<=T._x[3] && rect.max.x>=T._x[0]
  335. && rect.min.y<=T._y[3] && rect.max.y>=T._y[0])
  336. {
  337. if(final())func(T, user);else
  338. {
  339. if(rect.min.x<=T._x[1]/* && rect.max.x>=T._x[0]*/)
  340. {
  341. if( rect.min.y<=T._y[1]/* && rect.max.y>=T._y[0]*/){if(!_lb)New(_lb)->create(T._x[0] , T._y[0] , T._x[1], T._y[1], this, grid); _lb->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  342. if( rect.min.y<=T._y[2] && rect.max.y> T._y[1] ){if(!_l )New(_l )->create(T._x[0] , T._y[1]+1, T._x[1], T._y[2], this, grid); _l ->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  343. if(/*rect.min.y<=T._y[3] && */rect.max.y> T._y[2] ){if(!_lf)New(_lf)->create(T._x[0] , T._y[2]+1, T._x[1], T._y[3], this, grid); _lf->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  344. }
  345. if(rect.min.x<=T._x[2] && rect.max.x>T._x[1])
  346. {
  347. if( rect.min.y<=T._y[1]/* && rect.max.y>=T._y[0]*/){if(! _b)New( _b)->create(T._x[1]+1, T._y[0] , T._x[2], T._y[1], this, grid); _b->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  348. if( rect.min.y<=T._y[2] && rect.max.y> T._y[1] ){if(! _c)New( _c)->create(T._x[1]+1, T._y[1]+1, T._x[2], T._y[2], this, grid); _c->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  349. if(/*rect.min.y<=T._y[3] && */rect.max.y> T._y[2] ){if(! _f)New( _f)->create(T._x[1]+1, T._y[2]+1, T._x[2], T._y[3], this, grid); _f->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  350. }
  351. if(/*rect.min.x<=T._x[3] && */rect.max.x>T._x[2])
  352. {
  353. if( rect.min.y<=T._y[1]/* && rect.max.y>=T._y[0]*/){if(!_rb)New(_rb)->create(T._x[2]+1, T._y[0] , T._x[3], T._y[1], this, grid); _rb->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  354. if( rect.min.y<=T._y[2] && rect.max.y> T._y[1] ){if(!_r )New(_r )->create(T._x[2]+1, T._y[1]+1, T._x[3], T._y[2], this, grid); _r ->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  355. if(/*rect.min.y<=T._y[3] && */rect.max.y> T._y[2] ){if(!_rf)New(_rf)->create(T._x[2]+1, T._y[2]+1, T._x[3], T._y[3], this, grid); _rf->funcCreate(rect, func, user, grid);} // first allocate and assign, then create (in case child accesses grid)
  356. }
  357. }
  358. }
  359. }
  360. /******************************************************************************/
  361. // GRID
  362. /******************************************************************************/
  363. static void SetFastAccess(_Cell &cell, Ptr user)
  364. {
  365. _Grid &grid=*(_Grid*)user;
  366. grid.fastAccessCell(cell.xy())=&cell;
  367. }
  368. /******************************************************************************/
  369. static _Cell& GetCell(_Cell* &root, C VecI2 &xy, _Grid &grid)
  370. {
  371. if(root)
  372. {
  373. parent:
  374. // set new roots on top of current one until we can hold the new element below root
  375. for(;;)
  376. {
  377. if(_Cell *get=root->get(xy, grid))return *get; // if root contains the element
  378. DEBUG_ASSERT(root->x()!=INT_MIN, "failed to find cell"); // root.x==INT_MIN means the biggest root possible
  379. _Cell *child=root;
  380. New(root)->createAsParent(child, grid); // creating parent doesn't create data objects, so whether we first create or assign (the order) it doesn't matter
  381. }
  382. }else
  383. {
  384. if(xy.x<-MAX_NORMAL || xy.x>MAX_NORMAL // check each component separately (instead of using 'Abs' because of "Abs(INT_MIN)!=-INT_MIN")
  385. || xy.y<-MAX_NORMAL || xy.y>MAX_NORMAL) // if the cell to be created first lies outside of normal range, then we first need to create at least one cell in the normal area, because 'createAsParent' will work incorrectly for cells outside of normal range ('div' calculation)
  386. {
  387. New(root)->create(-MAX_NORMAL, -MAX_NORMAL, MAX_NORMAL, MAX_NORMAL, null, grid);
  388. goto parent;
  389. }
  390. New(root)->create(xy.x, xy.y, null, grid); // first allocate and assign, then create (in case child accesses grid)
  391. return *root;
  392. }
  393. }
  394. /******************************************************************************/
  395. void _Grid:: del( ) {if(_root)_root->del(T); Delete(_root);}
  396. void _Grid:: del( _Cell *cell) {if( cell) cell->del(T); if(cell==_root)Delete(_root);}
  397. _Cell& _Grid:: get(C VecI2 &xy ) {if(Cuts(xy, _fast_access_rect))if(_Cell *cell=fastAccessCell(xy))return *cell; return GetCell(_root, xy, T) ;} // when using fast_access lookup then return only if it was found, otherwise create it
  398. _Cell* _Grid::find(C VecI2 &xy )C {if(Cuts(xy, _fast_access_rect))return fastAccessCell(xy) ; return _root ? _root->find(xy) : null;} // when using fast_access lookup then always return because we're not creating it when not found
  399. Bool _Grid::size( RectI &rect)C
  400. {
  401. // set to max invalid first, because methods below will adjust existing values
  402. rect.min=INT_MAX;
  403. rect.max=INT_MIN;
  404. if(_root)
  405. {
  406. _root->getLeft (rect.min.x); _root->getBottom(rect.min.y);
  407. _root->getRight(rect.max.x); _root->getTop (rect.max.y);
  408. if(rect.valid())return true;
  409. }
  410. rect.zero(); return false;
  411. }
  412. void _Grid::fastAccess(C RectI *rect)
  413. {
  414. RectI invalid; if(!rect || !rect->valid())rect=&invalid.set(0, 0, -1, -1);
  415. if(_fast_access_rect!=*rect)
  416. {
  417. _fast_access_mul = rect->w()+1;
  418. _fast_access_rect=*rect;
  419. _fast_access_cell.setNum(_fast_access_mul*(rect->h()+1));
  420. ZeroN(_fast_access_cell.data(), _fast_access_cell.elms()); // set to null initially in case not all cells are created in that area
  421. func(*rect, SetFastAccess, this);
  422. }
  423. }
  424. void _Grid::func ( void func(_Cell &cell, Ptr user), Ptr user) {if(_root)_root->func( func, user);}
  425. void _Grid::func (C RectI &rect, void func(_Cell &cell, Ptr user), Ptr user) {if(_root)_root->func(rect, func, user);}
  426. void _Grid::funcCreate(C RectI &rect, void func(_Cell &cell, Ptr user), Ptr user)
  427. {
  428. // create or move root above to cover all required areas
  429. if(!_root || _root->_x[0]>rect.min.x || _root->_y[0]>rect.min.y)GetCell(_root, rect.min, T); // get min corner
  430. if(!_root || _root->_x[3]<rect.max.x || _root->_y[3]<rect.max.y)GetCell(_root, rect.max, T); // get max corner
  431. // now create and call the callback
  432. if(_root)_root->funcCreate(rect, func, user, T);
  433. }
  434. static void ListCells(_Cell &cell, Memt<_Cell*> &cells)
  435. {
  436. cells.add(&cell);
  437. }
  438. void _Grid::mtFunc(Threads &threads, void func(_Cell &cell, Ptr user, Int thread_index), Ptr user)
  439. {
  440. if(_root)
  441. {
  442. Memt<_Cell*> cells; _root->func(ListCells, cells); // get all valid cells
  443. threads.process1(cells, func, user);
  444. }
  445. }
  446. void _Grid::mtFunc(Threads &threads, C RectI &rect, void func(_Cell &cell, Ptr user, Int thread_index), Ptr user)
  447. {
  448. if(_root)
  449. {
  450. Memt<_Cell*> cells; _root->func(rect, ListCells, cells); // get all valid cells
  451. threads.process1(cells, func, user);
  452. }
  453. }
  454. /******************************************************************************/
  455. }
  456. /******************************************************************************/