00001 #include <esg/geometry/BVList.h>
00002 #include <esg/explorer/POGExplorer.h>
00003 #include <esg/explorer/NExtentsExplorer.h>
00004 #include <time.h>
00005 #include <assert.h>
00006
00007 using namespace esg;
00008
00009 unsigned BVList::qsortIndex;
00010
00011 int BVList::qsortCompare(const void * pBV1, const void * pBV2)
00012 {
00013 Interval * i1 = &((*((BVNode**)pBV1))->extents[BVList::qsortIndex]);
00014 Interval * i2 = &((*((BVNode**)pBV2))->extents[BVList::qsortIndex]);
00015 double e1 = i1->min + i1->max;
00016 double e2 = i2->min + i2->max;
00017
00018 return ((e1 < e2) ? -1 : ((e1 == e2) ? 0 : 1));
00019 }
00020
00021 void BVList::_split_by_handles(List<BVNode>& srcList,
00022 List<BVNode>& dstList,
00023 unsigned index)
00024 {
00025 float median;
00026 unsigned i_rand;
00027 long int length = (long int) srcList.length();
00028 BVNode* pMedian = NULL;
00029
00030 assert(length > 1);
00031
00032
00033
00034 i_rand = (unsigned) ESG_INT_RAND(length);
00035 pMedian = srcList.iThItem(i_rand, false);
00036 assert(pMedian);
00037 (void) srcList.remove(pMedian);
00038 length--;
00039
00040 median = pMedian->handle[index];
00041
00042 BVNode * pNode = srcList.firstItem();
00043 for (register unsigned i = 0; i < (unsigned) length; i++) {
00044
00045
00046 if ((pNode->handle[index] < median) ||
00047 ((pNode->handle[index] == median) && (i < i_rand)))
00048 {
00049
00050 pNode = srcList.nextItem();
00051 } else
00052 {
00053 BVNode* pTmp = srcList.nextItem();
00054 dstList.append(srcList.remove(pNode));
00055 pNode = pTmp;
00056 }
00057 }
00058
00059 if (dstList.length() == 0) dstList.append(pMedian);
00060 else srcList.append(pMedian);
00061 }
00062
00063 void BVList::_comp_handle(BVNode* pNode)
00064 {
00065 if (!pNode || !pNode->pObject) return;
00066
00067 POGExplorer explorer;
00068 explorer.explore(*(pNode->pObject));
00069 Vector3 pog = explorer.result();
00070 Vector3 v;
00071
00072 if (pog.x == MAX_VEC_VALUE ||
00073 pog.y == MAX_VEC_VALUE ||
00074 pog.z == MAX_VEC_VALUE)
00075 {
00076 for (register unsigned i = 0; i < _dirs; i++)
00077 pNode->handle[i] = MAXFLOAT;
00078 return;
00079 }
00080
00081 for (register unsigned i = 0; i < _dirs; i++) {
00082 v.set(_dirMat[i][0], _dirMat[i][1], _dirMat[i][2]);
00083 pNode->handle[i] = pog.dot(v);
00084 }
00085 }
00086
00087 void BVList::_comp_extents(BVNode* pNode)
00088 {
00089 if (!pNode || !pNode->pObject) return;
00090
00091 NExtentsExplorer explorer(_dirMat, _dirs);
00092 explorer.explore(*(pNode->pObject));
00093
00094 for (unsigned i = 0; i < _dirs; i++)
00095 pNode->extents[i] = explorer.result(i);
00096 }
00097
00098
00099 unsigned BVList::_index_with_max_extent()
00100 {
00101 #ifdef WIN32
00102 Interval *d = new Interval [_dirs];
00103 #else
00104 Interval d[_dirs];
00105 #endif
00106 BVNode* pNode = _pList->firstItem();
00107
00108 while (pNode) {
00109 for (unsigned i = 0; i < _dirs; i++) {
00110 if (pNode->extents[i].min < d[i].min)
00111 d[i].min = pNode->extents[i].min;
00112 if (pNode->extents[i].max > d[i].max)
00113 d[i].max = pNode->extents[i].max;
00114 }
00115 pNode = _pList->nextItem();
00116 }
00117
00118 unsigned ret = 0;
00119 double dist = -MAXDOUBLE;
00120 double actDist;
00121 for (unsigned i = 0; i < _dirs; i++) {
00122 actDist = d[i].max - d[i].min;
00123 if (actDist > dist) { ret = i; dist = actDist; }
00124 }
00125
00126 #ifdef WIN32
00127 delete [] d;
00128 #endif
00129
00130 return ret;
00131 }
00132
00133 void BVList::_build_area_table(BVNode** nodes, long a, long b, double *areas) const
00134 {
00135 long imin, dir;
00136 double tmin, tmax;
00137 Vector3 bmin(MAX_VEC_VALUE, MAX_VEC_VALUE, MAX_VEC_VALUE);
00138 Vector3 bmax(MIN_VEC_VALUE, MIN_VEC_VALUE, MIN_VEC_VALUE);
00139 Vector3 len;
00140 Interval* e;
00141
00142 if (a < b) { imin = a; dir = 1; }
00143 else { imin = b; dir = -1; }
00144
00145 for (long i = a; i != (b + dir); i += dir) {
00146 e = nodes[i]->extents;
00147
00148 tmin = e[0].min;
00149 tmax = e[0].max;
00150 if (tmin < bmin.x) { bmin.x = tmin; }
00151 if (tmax > bmax.x) { bmax.x = tmax; }
00152
00153 tmin = e[1].min;
00154 tmax = e[1].max;
00155 if (tmin < bmin.y) { bmin.y = tmin; }
00156 if (tmax > bmax.y) { bmax.y = tmax; }
00157
00158 tmin = e[2].min;
00159 tmax = e[2].max;
00160 if (tmin < bmin.z) { bmin.z = tmin; }
00161 if (tmax > bmax.z) { bmax.z = tmax; }
00162
00163 len.set(bmax);
00164 len.sub(bmin);
00165
00166 areas[i - imin] = len.x * (len.y + len.z) + len.y * len.z;
00167 }
00168 }
00169
00170 unsigned BVList::_split_by_extent(List<BVNode>& list)
00171 {
00172 unsigned i, size;
00173 BVNode** qsortArray = NULL;
00174 double bestIndex, newIndex;
00175 unsigned bestLoc;
00176 double* leftArea;
00177 double* rightArea;
00178
00179 size = length();
00180 qsortIndex = _index_with_max_extent();
00181 qsortArray = new BVNode* [size];
00182 leftArea = new double [size];
00183 rightArea = new double [size];
00184 i = 0;
00185
00186 for (BVNode * pN = _pList->firstItem(); pN; pN = _pList->nextItem())
00187 qsortArray[i++] = pN;
00188
00189 delete _pList;
00190 qsort((void*)qsortArray, size, sizeof(BVNode*), BVList::qsortCompare);
00191
00192 _build_area_table(qsortArray, 0, size-1, leftArea);
00193 _build_area_table(qsortArray, size-1, 0, rightArea);
00194
00195 bestIndex = rightArea[0] * (size - 3.);
00196 bestLoc = 0;
00197
00198
00199
00200
00201
00202
00203
00204 for (i = 0; i < size - 1; i++) {
00205 newIndex = (i+1) * leftArea[i] + (size-1-i) * rightArea[i+1];
00206 if (newIndex < bestIndex) {
00207 bestIndex = newIndex;
00208 bestLoc = i;
00209 }
00210 }
00211
00212 delete [] leftArea;
00213 delete [] rightArea;
00214
00215 _pList = new List<BVNode>;
00216 for (i = 0; i < bestLoc + 1; i++) _pList->append(qsortArray[i]);
00217 for (i = bestLoc + 1; i < size; i++) list.append(qsortArray[i]);
00218
00219 delete [] qsortArray;
00220
00221 return qsortIndex;
00222 }
00223
00224 unsigned BVList::_index_with_max_variation()
00225 {
00226 float max_hodn;
00227 unsigned max_variace = MAXUNSIGNED;
00228 float hndl;
00229 double ekohandle2, e2kohandle;
00230
00231 #if defined(_MSC_VER)
00232 float *variace = new float [_dirs];
00233 #else
00234 float variace [_dirs];
00235 #endif
00236
00237 variace[0] = 0;
00238
00239 if (length() > 1) {
00240 for (register unsigned i = 0; i < _dirs; i++) {
00241 BVNode* pNode = _pList->firstItem();
00242 ekohandle2 = 0;
00243 e2kohandle = 0;
00244 while (pNode) {
00245 hndl = pNode->handle[i];
00246 ekohandle2 += (hndl * hndl);
00247 e2kohandle += hndl;
00248 pNode = _pList->nextItem();
00249 }
00250 ekohandle2 /= length();
00251 e2kohandle /= length();
00252 e2kohandle *= e2kohandle;
00253 variace[i] = ekohandle2 - e2kohandle;
00254 }
00255 max_variace = 0;
00256 max_hodn = variace[0];
00257 for (register unsigned i = 1; i < _dirs; i++) {
00258 if (max_hodn < variace[i]) {
00259 max_hodn = variace[i];
00260 max_variace = i;
00261 }
00262 }
00263 }
00264
00265 #if defined(_MSC_VER)
00266 delete [] variace;
00267 #endif
00268
00269 return max_variace;
00270 }
00271
00272 unsigned BVList::_split_by_variation(List<BVNode>& list)
00273 {
00274 if (length() < 2) return MAXUNSIGNED;
00275
00276 unsigned index, ll;
00277 unsigned LL_room, RR_room;
00278
00279 List<BVNode>* rightList = new List<BVNode>;
00280 List<BVNode>* leftList = _pList;
00281
00282 LL_room = length() / 2;
00283 RR_room = length() - LL_room;
00284
00285 if ((index = _index_with_max_variation()) == MAXUNSIGNED) return index;
00286
00287 _pList = new List<BVNode>();
00288
00289
00290
00291 #if 1
00292 while (true) {
00293 if (leftList->length() > 1)
00294 _split_by_handles(*leftList, *rightList, index);
00295 if ((ll = leftList->length()) < LL_room) {
00296 LL_room -= ll;
00297 _pList->append(*leftList);
00298 List<BVNode>* pTmp = leftList;
00299 leftList = rightList;
00300 rightList = pTmp;;
00301 } else {
00302 if (ll == LL_room){
00303 _pList->append(*leftList);
00304 list.append(*rightList);
00305 break;
00306 } else {
00307 RR_room -= rightList->length();
00308 list.append(*rightList);
00309 }
00310 }
00311 }
00312 #endif
00313
00314 #if 0
00315 while (leftList->length()) {
00316 if (leftList->length() > LL_room)
00317 _split_by_handles(*leftList, *rightList, index);
00318
00319 if (rightList->length() == 0) {
00320 for (unsigned i = 0; i < LL_room; i++)
00321 _pList->append(leftList->remove(leftList->firstItem()));
00322 while (leftList->length())
00323 list.append(leftList->remove(leftList->firstItem()));
00324
00325 continue;
00326 }
00327
00328 if (leftList->length() == 0) {
00329 for (unsigned i = 0; i < RR_room; i++)
00330 list.append(rightList->remove(rightList->firstItem()));
00331 while (rightList->length())
00332 _pList->append(rightList->remove(rightList->firstItem()));
00333
00334 continue;
00335 }
00336
00337 if (rightList->length() <= RR_room) {
00338 RR_room -= rightList->length();
00339 while (rightList->length())
00340 list.append(rightList->remove(rightList->firstItem()));
00341
00342 }
00343
00344 if (leftList->length() <= LL_room) {
00345 LL_room -= leftList->length();
00346 while (leftList->length())
00347 _pList->append(leftList->remove(leftList->firstItem()));
00348
00349 List<BVNode>* pTmp = leftList;
00350 leftList = rightList;
00351 rightList = pTmp;;
00352 }
00353 }
00354 #endif
00355
00356 delete leftList;
00357 delete rightList;
00358
00359 return index;
00360 }
00361
00362
00363
00364
00365 BVList::BVList(unsigned s, const float (*m)[3])
00366 : _dirs(s), _dirMat(m)
00367 {
00368 _pList = new List<BVNode>();
00369 }
00370
00371 BVList::~BVList()
00372 {
00373 while (BVNode* pNode=_pList->remove(_pList->firstItem())) { delete pNode; }
00374 delete _pList;
00375 }
00376
00377 void BVList::append(SceneGraphObject* o)
00378 {
00379 BVNode* pnode = new BVNode(_dirs, o);
00380 _comp_handle(pnode);
00381 _comp_extents(pnode);
00382 _pList->append(pnode);
00383 }
00384
00385 SceneGraphObject* BVList::remove(SceneGraphObject* pObj)
00386 {
00387 if (!pObj) return NULL;
00388 BVNode* pItem = _pList->firstItem();
00389
00390 while (pItem && pItem->pObject != pObj)
00391 pItem = _pList->nextItem();
00392
00393 if (pItem && pItem->pObject == pObj) {
00394 SceneGraphObject* pRet = pItem->pObject;
00395 _pList->remove(pItem);
00396 return pRet;
00397 } else
00398 return NULL;
00399 }
00400
00401 unsigned BVList::split(BVList& list, SplitStrategy splitStrategy)
00402 {
00403 if (length() < 2) return MAXUNSIGNED;
00404
00405 switch (splitStrategy) {
00406 case SPLIT_BY_MAX_VARIATION:
00407 return _split_by_variation(*(list._pList));
00408 break;
00409 case SPLIT_BY_MAX_EXTENT:
00410 return _split_by_extent(*(list._pList));
00411 break;
00412 default:
00413 return MAXUNSIGNED;
00414 }
00415 }
00416
00417
00418
00419
00420