|
SUMO - Simulation of Urban MObility
|
00001 #include <stdio.h> 00002 #include <memory.h> 00003 #include <crtdbg.h> 00004 00005 #include "RTree.h" 00006 00007 00008 // 00009 // MemoryTest.cpp 00010 // 00011 // This demonstrates a use of RTree 00012 // 00013 00014 // Use CRT Debug facility to dump memory leaks on app exit 00015 #ifdef WIN32 00016 // The following macros set and clear, respectively, given bits 00017 // of the C runtime library debug flag, as specified by a bitmask. 00018 #ifdef _DEBUG 00019 #define SET_CRT_DEBUG_FIELD(a) \ 00020 _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) 00021 #define CLEAR_CRT_DEBUG_FIELD(a) \ 00022 _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) 00023 #else 00024 #define SET_CRT_DEBUG_FIELD(a) ((void) 0) 00025 #define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) 00026 #endif 00027 #endif //WIN32 00028 00029 // 00030 // Get a random float b/n two values 00031 // The returned value is >= min && < max (exclusive of max) 00032 // Note this is a low precision random value since it is generated from an int. 00033 // 00034 static float RandFloat(float a_min, float a_max) 00035 { 00036 const float ooMax = 1.0f / (float)(RAND_MAX+1); 00037 00038 float retValue = ( (float)rand() * ooMax * (a_max - a_min) + a_min); 00039 00040 ASSERT(retValue >= a_min && retValue < a_max); // Paranoid check 00041 00042 return retValue; 00043 } 00044 00045 00047 struct Vec3 00048 { 00050 Vec3() {} 00051 00053 Vec3(float a_x, float a_y, float a_z) 00054 { 00055 v[0] = a_x; 00056 v[1] = a_y; 00057 v[2] = a_z; 00058 } 00059 00061 Vec3 operator+ (const Vec3& a_other) const 00062 { 00063 return Vec3(v[0] + a_other.v[0], 00064 v[1] + a_other.v[1], 00065 v[2] + a_other.v[2]); 00066 } 00067 00068 float v[3]; 00069 }; 00070 00071 00072 static bool BoxesIntersect(const Vec3& a_boxMinA, const Vec3& a_boxMaxA, 00073 const Vec3& a_boxMinB, const Vec3& a_boxMaxB) 00074 { 00075 for(int axis=0; axis<3; ++axis) 00076 { 00077 if(a_boxMinA.v[axis] > a_boxMaxB.v[axis] || 00078 a_boxMaxA.v[axis] < a_boxMinB.v[axis]) 00079 { 00080 return false; 00081 } 00082 } 00083 return true; 00084 } 00085 00086 00088 struct SomeThing 00089 { 00090 SomeThing() 00091 { 00092 ++s_outstandingAllocs; 00093 } 00094 ~SomeThing() 00095 { 00096 --s_outstandingAllocs; 00097 } 00098 00099 int m_creationCounter; 00100 Vec3 m_min, m_max; 00101 00102 static int s_outstandingAllocs; 00103 }; 00104 00106 int SomeThing::s_outstandingAllocs = 0; 00107 00108 00110 bool _cdecl QueryResultCallback(SomeThing* a_data, void* a_context) 00111 { 00112 printf("search found %d\n", a_data->m_creationCounter); 00113 00114 return true; 00115 } 00116 00117 00118 int main(int argc, char* argv[]) 00119 { 00120 const int NUM_OBJECTS = 40; // Number of objects in test set, must be > FRAC_OBJECTS for this test 00121 const int FRAC_OBJECTS = 4; 00122 const float MAX_WORLDSIZE = 10.0f; 00123 const float FRAC_WORLDSIZE = MAX_WORLDSIZE / 2; 00124 00125 // typedef the RTree useage just for conveniance with iteration 00126 typedef RTree<SomeThing*, float, 3> SomeThingTree; 00127 00128 ASSERT( NUM_OBJECTS > FRAC_OBJECTS ); 00129 00130 int index; // general purpose counter, declared here because MSVC 6 is not ansi compliant with 'for' loops. 00131 SomeThing* thingArray[NUM_OBJECTS * 2]; // Store objects in another container to test with, sized larger than we need 00132 00133 memset(thingArray, 0, sizeof(thingArray)); // Nullify array, size is known here 00134 00135 00136 // Create intance of RTree 00137 00138 SomeThingTree tree; 00139 00140 00141 // Add some nodes 00142 int counter = 0; 00143 for( index = 0; index < NUM_OBJECTS; ++index ) 00144 { 00145 SomeThing* newThing = new SomeThing; 00146 00147 newThing->m_creationCounter = counter++; 00148 newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE)); 00149 Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE)); 00150 newThing->m_max = newThing->m_min + extent; 00151 00152 thingArray[counter-1] = newThing; 00153 00154 tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing); 00155 printf("inserting %d\n", newThing->m_creationCounter); 00156 } 00157 00158 printf("tree count = %d\n", tree.Count()); 00159 00160 int numToDelete = NUM_OBJECTS / FRAC_OBJECTS; 00161 int numToStep = FRAC_OBJECTS; 00162 00163 // Delete some nodes 00164 for( index = 0; index < NUM_OBJECTS; index += numToStep ) 00165 { 00166 SomeThing* curThing = thingArray[index]; 00167 00168 if(curThing) 00169 { 00170 tree.Remove(curThing->m_min.v, curThing->m_max.v, curThing); 00171 printf("removing %d\n", curThing->m_creationCounter); 00172 00173 delete curThing; 00174 thingArray[index] = NULL; 00175 } 00176 } 00177 00178 printf("tree count = %d\n", tree.Count()); 00179 00180 // Add some more nodes 00181 for( index = 0; index < numToDelete; ++index ) 00182 { 00183 SomeThing* newThing = new SomeThing; 00184 00185 newThing->m_creationCounter = counter++; 00186 newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE)); 00187 Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE)); 00188 newThing->m_max = newThing->m_min + extent; 00189 00190 thingArray[counter-1] = newThing; 00191 00192 tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing); 00193 printf("inserting %d\n", newThing->m_creationCounter); 00194 } 00195 00196 printf("tree count = %d\n", tree.Count()); 00197 00198 Vec3 searchMin(0,0,0); 00199 Vec3 searchMax(FRAC_WORLDSIZE, FRAC_WORLDSIZE, FRAC_WORLDSIZE); 00200 tree.Search(searchMin.v, searchMax.v, &QueryResultCallback, NULL); 00201 00202 // NOTE: Even better than just dumping text, it would be nice to render the 00203 // tree contents and search result for visualization. 00204 00205 00206 // List values. Iterator is NOT delete safe 00207 SomeThingTree::Iterator it; 00208 for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) ) 00209 { 00210 SomeThing* curThing = tree.GetAt(it); 00211 00212 if(BoxesIntersect(searchMin, searchMax, curThing->m_min, curThing->m_max)) 00213 { 00214 printf("brute found %d\n", curThing->m_creationCounter); 00215 } 00216 } 00217 00218 // Delete our nodes, NOTE, we are NOT deleting the tree nodes, just our data 00219 // of course the tree will now contain invalid pointers that must not be used any more. 00220 for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) ) 00221 { 00222 SomeThing* removeElem = tree.GetAt(it); 00223 if(removeElem) 00224 { 00225 printf("deleting %d\n", removeElem->m_creationCounter); 00226 delete removeElem; 00227 } 00228 } 00229 00230 // Remove all contents (This would have happened automatically during destructor) 00231 tree.RemoveAll(); 00232 00233 if(SomeThing::s_outstandingAllocs > 0) 00234 { 00235 printf("Memory leak!\n"); 00236 printf("s_outstandingAllocs = %d\n", SomeThing::s_outstandingAllocs); 00237 } 00238 else 00239 { 00240 printf("No memory leaks detected by app\n"); 00241 } 00242 00243 // Wait for keypress on exit so we can read console output 00244 getchar(); 00245 00246 #ifdef WIN32 00247 // Use CRT Debug facility to dump memory leaks on app exit 00248 SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); 00249 #endif //WIN32 00250 00251 return 0; 00252 }