00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef __GZ_SPATIAL_H__
00023 #define __GZ_SPATIAL_H__
00024
00030 #include "gzBasicTypes.h"
00031 #include "gzXYZ.h"
00032
00033
00034 template <class T> class gzSpatialDataIterator;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 template <class T> class gzSpatialData
00051 {
00052 public:
00053
00054 gzSpatialData(const gzDoubleXYZ& position_1=gzDoubleXYZ(0,0,0) , const gzDoubleXYZ& position_2=gzDoubleXYZ(1,1,1),gzULong divisions=3,gzULong splitItems=0);
00055
00056 ~gzSpatialData();
00057
00058 gzVoid insert(const gzDoubleXYZ &position,const T &data,const gzDoubleXYZ &delta=gzDoubleXYZ(0,0,0));
00059
00060 gzULong entries();
00061
00062 gzVoid clear();
00063
00064 private:
00065
00066 friend class gzSpatialDataIterator<T>;
00067
00068 class _item;
00069
00070 class _holder
00071 {
00072 public:
00073
00074 _holder(const gzDoubleXYZ &min , const gzDoubleXYZ &max,_holder *parent,gzULong index):m_min(min),m_max(max),m_parent(parent),m_subspace(NULL),m_index(index)
00075 {
00076 m_itemList.reuseLinks(TRUE);
00077 }
00078
00079 ~_holder()
00080 {
00081 if(m_subspace)
00082 {
00083 for(gzULong i=0;i<m_size;i++)
00084 if(m_subspace[i])
00085 delete m_subspace[i];
00086
00087 delete [] m_subspace;
00088 }
00089
00090 m_itemList.clearAndDestroy();
00091 }
00092
00093 gzVoid createSubspace(gzULong divisions)
00094 {
00095 if(!m_subspace)
00096 {
00097 m_size=divisions*divisions*divisions;
00098 m_firstIndex=m_size;
00099
00100 m_subspace=new _holder *[m_size];
00101 memset(m_subspace,0,m_size*sizeof(_holder *));
00102 }
00103 }
00104
00105 gzList<_item> m_itemList;
00106 _holder ** m_subspace;
00107 _holder * m_parent;
00108 gzULong m_index;
00109 gzDoubleXYZ m_max;
00110 gzDoubleXYZ m_min;
00111 gzULong m_size;
00112 gzULong m_firstIndex;
00113 };
00114
00115 class _item
00116 {
00117 public:
00118
00119 T m_data;
00120 gzDoubleXYZ m_position;
00121 gzDoubleXYZ m_delta;
00122 };
00123
00124 _holder * m_space;
00125
00126 gzDoubleXYZ m_minPosition;
00127
00128 gzDoubleXYZ m_stepping;
00129
00130 gzULong m_divisions;
00131
00132 gzULong m_splitItems;
00133
00134 gzULong m_entries;
00135 };
00136
00137 template <class T> inline gzSpatialData<T>::gzSpatialData(const gzDoubleXYZ& position_1 , const gzDoubleXYZ& position_2,gzULong divisions,gzULong splitItems)
00138 {
00139 m_minPosition=gzDoubleXYZ(gzMin(position_1.x,position_2.x),gzMin(position_1.y,position_2.y),gzMin(position_1.z,position_2.z));
00140
00141 m_stepping=(gzDoubleXYZ(gzMax(position_1.x,position_2.x),gzMax(position_1.y,position_2.y),gzMax(position_1.z,position_2.z))-m_minPosition)/divisions;
00142
00143 if(!m_stepping.x)
00144 m_stepping.x=1;
00145
00146 if(!m_stepping.y)
00147 m_stepping.y=1;
00148
00149 if(!m_stepping.z)
00150 m_stepping.z=1;
00151
00152 m_divisions=divisions;
00153
00154 m_splitItems=splitItems;
00155
00156 m_space=NULL;
00157
00158 m_entries=0;
00159 }
00160
00161 template <class T> inline gzSpatialData<T>::~gzSpatialData()
00162 {
00163 if(m_space)
00164 delete m_space;
00165 }
00166
00167 template <class T> inline gzVoid gzSpatialData<T>::clear()
00168 {
00169 if(m_space)
00170 delete m_space;
00171
00172 m_space=NULL;
00173 m_entries=0;
00174 }
00175
00176 template <class T> inline gzULong gzSpatialData<T>::entries()
00177 {
00178 return m_entries;
00179 }
00180
00181 template <class T> inline gzVoid gzSpatialData<T>::insert(const gzDoubleXYZ &position,const T &data,const gzDoubleXYZ &delta)
00182 {
00183 if( ((position.x+delta.x)>=(m_minPosition.x+m_divisions*m_stepping.x))
00184 || ((position.y+delta.y)>=(m_minPosition.y+m_divisions*m_stepping.y))
00185 || ((position.z+delta.z)>=(m_minPosition.z+m_divisions*m_stepping.z)) )
00186 {
00187 _holder *old=m_space;
00188 gzULong index=(m_divisions-1)/2;
00189
00190 gzULong mixIndex=index*(m_divisions*m_divisions)+index*m_divisions+index;
00191
00192
00193 m_stepping=m_stepping*m_divisions;
00194 m_minPosition=m_minPosition-m_stepping*index;
00195
00196 m_space=new _holder(m_minPosition,m_minPosition+m_stepping*m_divisions,NULL,0);
00197
00198 if(old)
00199 {
00200 m_space->createSubspace(m_divisions);
00201 m_space->m_subspace[mixIndex]=old;
00202 m_space->m_firstIndex=mixIndex;
00203 old->m_parent=m_space;
00204 old->m_index=mixIndex;
00205 }
00206
00207 insert(position,data,delta);
00208 return;
00209 }
00210
00211 if( ((position.x-delta.x)<m_minPosition.x)
00212 || ((position.y-delta.y)<m_minPosition.y)
00213 || ((position.z-delta.z)<m_minPosition.z) )
00214 {
00215 _holder *old=m_space;
00216 gzULong index=m_divisions/2;
00217 gzULong mixIndex=index*(m_divisions*m_divisions)+index*m_divisions+index;
00218
00219 m_stepping=m_stepping*m_divisions;
00220 m_minPosition=m_minPosition-m_stepping*index;
00221
00222 m_space=new _holder(m_minPosition,m_minPosition+m_stepping*m_divisions,NULL,0);
00223
00224 if(old)
00225 {
00226 m_space->createSubspace(m_divisions);
00227 m_space->m_subspace[mixIndex]=old;
00228 m_space->m_firstIndex=mixIndex;
00229 old->m_parent=m_space;
00230 old->m_index=mixIndex;
00231 }
00232
00233 insert(position,data,delta);
00234 return;
00235 }
00236
00237 gzULong index_x=0,index_y=0,index_z=0;
00238
00239 _holder *holder=m_space,*parent=NULL;
00240
00241 gzDoubleXYZ stepping=m_stepping;
00242 gzDoubleXYZ minPosition=m_minPosition;
00243
00244 while(holder)
00245 {
00246 index_x=(gzULong)((position.x-delta.x-minPosition.x)/stepping.x);
00247 index_y=(gzULong)((position.y-delta.y-minPosition.y)/stepping.y);
00248 index_z=(gzULong)((position.z-delta.z-minPosition.z)/stepping.z);
00249
00250 if( ((gzULong)((position.x+delta.x-minPosition.x)/stepping.x))!=index_x)
00251 break;
00252
00253 if( ((gzULong)((position.y+delta.y-minPosition.y)/stepping.y))!=index_y)
00254 break;
00255
00256 if( ((gzULong)((position.z+delta.z-minPosition.z)/stepping.z))!=index_z)
00257 break;
00258
00259 if(holder->m_itemList.entries()>=m_splitItems)
00260 {
00261 minPosition.x=minPosition.x+index_x*stepping.x;
00262 minPosition.y=minPosition.y+index_y*stepping.y;
00263 minPosition.z=minPosition.z+index_z*stepping.z;
00264
00265 stepping=stepping/m_divisions;
00266
00267 if(!holder->m_subspace)
00268 holder->createSubspace(m_divisions);
00269
00270
00271 parent=holder;
00272 holder=holder->m_subspace[index_x*(m_divisions*m_divisions)+index_y*m_divisions+index_z];
00273
00274 continue;
00275 }
00276 else
00277 break;
00278 }
00279
00280 if(!holder)
00281 {
00282 gzULong mixIndex=index_x*(m_divisions*m_divisions)+index_y*m_divisions+index_z;
00283
00284 holder=new _holder(minPosition,minPosition+stepping*m_divisions,parent,mixIndex);
00285
00286 if(!parent)
00287 m_space=holder;
00288 else
00289 {
00290 if(parent->m_firstIndex>mixIndex)
00291 parent->m_firstIndex=mixIndex;
00292 parent->m_subspace[mixIndex]=holder;
00293 }
00294 }
00295
00296
00297
00298 _item *item=new _item;
00299
00300 holder->m_itemList.insert(item);
00301
00302 item->m_data=data;
00303 item->m_position=position;
00304 item->m_delta=delta;
00305
00306 ++m_entries;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 template <class T> class gzSpatialDataIterator
00325 {
00326 public:
00327
00328 gzSpatialDataIterator(gzSpatialData<T> &owner,const gzDoubleXYZ& position=gzDoubleXYZ(0,0,0) , const gzDoubleXYZ& delta=gzDoubleXYZ(DBL_MAX,DBL_MAX,DBL_MAX));
00329
00330 ~gzSpatialDataIterator();
00331
00332 gzBool operator()(T &data,gzDoubleXYZ *pos=NULL,gzDoubleXYZ *delta=NULL);
00333
00334 gzVoid remove();
00335
00336 private:
00337
00338 gzSpatialData<T> & m_owner;
00339
00340 const gzDoubleXYZ m_position;
00341 const gzDoubleXYZ m_delta;
00342 const gzDouble dx_p,dy_p,dz_p,dx_m,dy_m,dz_m;
00343
00344 typename gzSpatialData<T>::_holder * m_currentHolder;
00345 gzULong m_maxIndex;
00346 gzListIterator<typename gzSpatialData<T>::_item> m_iterator;
00347 gzBool m_validIterator;
00348 };
00349
00350 template <class T> inline gzSpatialDataIterator<T>::gzSpatialDataIterator(gzSpatialData<T> &owner,const gzDoubleXYZ& position , const gzDoubleXYZ& delta)
00351 :m_owner(owner),
00352 m_position(position),
00353 m_delta(delta),
00354 m_iterator(NULL),
00355 dx_m(position.x-delta.x),
00356 dy_m(position.y-delta.y),
00357 dz_m(position.z-delta.z),
00358 dx_p(position.x+delta.x),
00359 dy_p(position.y+delta.y),
00360 dz_p(position.z+delta.z)
00361 {
00362 m_maxIndex=m_owner.m_divisions*m_owner.m_divisions*m_owner.m_divisions;
00363 m_currentHolder=m_owner.m_space;
00364 m_validIterator=FALSE;
00365 }
00366
00367 template <class T> inline gzSpatialDataIterator<T>::~gzSpatialDataIterator()
00368 {
00369 }
00370
00371 template <class T> inline gzVoid gzSpatialDataIterator<T>::remove()
00372 {
00373 if(m_validIterator)
00374 {
00375 delete m_iterator.remove();
00376 --m_owner.m_entries;
00377 }
00378 }
00379
00380 template <class T> inline gzBool gzSpatialDataIterator<T>::operator()(T &data,gzDoubleXYZ *pos,gzDoubleXYZ *delta)
00381 {
00382 if(!m_currentHolder)
00383 return FALSE;
00384
00385 gzBool isValid;
00386
00387 typename gzSpatialData<T>::_holder *parent;
00388 typename gzSpatialData<T>::_item *item;
00389
00390 gzULong offset;
00391
00392 while(TRUE)
00393 {
00394
00395
00396 if(!m_validIterator)
00397 {
00398 isValid=TRUE;
00399
00400 if( m_currentHolder->m_max.x < dx_m )
00401 isValid=FALSE;
00402 else if( m_currentHolder->m_min.x > dx_p )
00403 isValid=FALSE;
00404 else if( m_currentHolder->m_max.y < dy_m)
00405 isValid=FALSE;
00406 else if( m_currentHolder->m_min.y > dy_p)
00407 isValid=FALSE;
00408 else if( m_currentHolder->m_max.z < dz_m)
00409 isValid=FALSE;
00410 else if( m_currentHolder->m_min.z > dz_p)
00411 isValid=FALSE;
00412
00413 if(!isValid)
00414 {
00415
00416
00417 while(TRUE)
00418 {
00419 if(!m_currentHolder->m_parent)
00420 {
00421 return FALSE;
00422 }
00423
00424 offset=m_currentHolder->m_index+1;
00425
00426 parent=NULL;
00427
00428 while(offset<m_maxIndex)
00429 {
00430 parent=m_currentHolder->m_parent->m_subspace[offset];
00431
00432 if(parent)
00433 {
00434 m_currentHolder=parent;
00435 break;
00436 }
00437
00438 ++offset;
00439 }
00440
00441 if(parent)
00442 break;
00443
00444
00445 m_currentHolder=m_currentHolder->m_parent;
00446 }
00447
00448
00449
00450 continue;
00451 }
00452
00453
00454
00455 m_validIterator=TRUE;
00456 m_iterator.setList(m_currentHolder->m_itemList);
00457 }
00458
00459
00460
00461 item=m_iterator();
00462
00463 if(!item)
00464 {
00465
00466 m_validIterator=FALSE;
00467
00468
00469
00470 if(m_currentHolder->m_subspace)
00471 {
00472
00473 m_currentHolder=m_currentHolder->m_subspace[m_currentHolder->m_firstIndex];
00474 }
00475 else
00476 {
00477
00478
00479 while(TRUE)
00480 {
00481 if(!m_currentHolder->m_parent)
00482 {
00483 return FALSE;
00484 }
00485
00486 offset=m_currentHolder->m_index+1;
00487
00488 parent=NULL;
00489
00490 while(offset<m_maxIndex)
00491 {
00492 parent=m_currentHolder->m_parent->m_subspace[offset];
00493
00494 if(parent)
00495 {
00496 m_currentHolder=parent;
00497 break;
00498 }
00499
00500 ++offset;
00501 }
00502
00503 if(parent)
00504 break;
00505
00506
00507 m_currentHolder=m_currentHolder->m_parent;
00508 }
00509
00510
00511
00512 continue;
00513 }
00514 }
00515 else
00516 {
00517 if( (item->m_position.x+item->m_delta.x) < dx_m )
00518 continue;
00519
00520 if( (item->m_position.x-item->m_delta.x) > dx_p )
00521 continue;
00522
00523 if( (item->m_position.y+item->m_delta.y) < dy_m )
00524 continue;
00525
00526 if( (item->m_position.y-item->m_delta.y) > dy_p )
00527 continue;
00528
00529 if( (item->m_position.z+item->m_delta.z) < dz_m )
00530 continue;
00531
00532 if( (item->m_position.z-item->m_delta.z) > dz_p )
00533 continue;
00534
00535
00536
00537 if(pos)
00538 *pos=item->m_position;
00539
00540 if(delta)
00541 *delta=item->m_delta;
00542
00543 data=item->m_data;
00544
00545 return TRUE;
00546 }
00547 }
00548 }
00549
00550 #endif // __GZ_SPATIAL_H__