bool ot_dist_traverse(OT_NODE *subtree, const Vector3d& point, int bounce_depth, bool (*function)(OT_BLOCK *block, void *handle1), void *handle) // only those blocks with this recur depth { #ifdef RADSTATS extern long ot_seenodecount, ot_seeblockcount; #endif int i; bool oksofar; OT_NODE *this_node; OT_BLOCK *this_block; #ifdef RADSTATS ot_seenodecount++; #endif // First, recurse to the child nodes oksofar = true; for (i = 0; i < 8 && oksofar; i++) { // for each potential kid this_node = subtree->Kids[i]; if (this_node != NULL) { // ...which exists if (ot_point_in_node(point, &this_node->Id)) { // ...and in range if(!ot_dist_traverse(this_node, point, bounce_depth, function, handle)) oksofar = false; } } } // Now, call the specified routine for each data block hung off this tree // node // if ( ot_point_in_node(point, &subtree->Id) ) { this_block = subtree->Values; while (oksofar && (this_block != NULL)) { #ifdef RADSTATS if (subtree->Id.Size < 100 || subtree->Id.Size > 140 ) { Debug_Info("bounds error, unreasonable size %d\n", subtree->Id.Size); } ot_seeblockcount++; #endif if ((int)this_block->Bounce_Depth == bounce_depth) { //oksofar = (*function) (this_block, handle); if (!( (*function) (this_block, handle))) oksofar = false; } this_block = this_block->next; } } return oksofar; }
void ot_index_box(const Vector3d& min_point, const Vector3d& max_point, OT_ID *id) { // TODO OPTIMIZE DBL dx, dy, dz, desiredSize; DBL bsized, maxord; POW2OP_DECLARE() // Calculate the absolute minimum required size of the node, assuming it is perfectly centered within the node; // Node size must be a power of 2, and be large enough to accomodate box's biggest dimensions with maximum overhang to all sides // compute ideal size of the node for a perfect fit without any overhang dx = max_point.x() - min_point.x(); dy = max_point.y() - min_point.y(); dz = max_point.z() - min_point.z(); desiredSize = max3(dx, dy, dz); // compute ideal size of the node for a perfect fit with full overhang to all sides // desiredSize /= (1 + 2 * 0.5); // compute best-matching power-of-two size for a perfect fit with overhang // (Note: theoretically this might pick a size larger than required if desiredSize is already a power of two) // desiredSize *= 2.0; POW2OP_FLOOR(bsized,desiredSize) // avoid divisions by zero if(bsized == 0.0) bsized = 1.0; #ifdef SAFE_METHOD // This block checks for the case where the node id would cause integer // overflow, since it is a small buffer far away maxord = max3(fabs(min_point[X]), fabs(min_point[Y]), fabs(min_point[Z])); maxord += OT_BIAS; while (maxord / bsized > 1000000000.0) { #ifdef RADSTATS overflows++; #endif bsized *= 2.0; } #endif // SAFE_METHOD // The node we chose so far would be ideal for a box of identical size positioned at the node's center, // but the actual box is probably somewhat off-center and therefore may have excessive overhang in some directions; // check and possibly fix this. Vector3d center = (min_point + max_point) / 2; id->x = (int) floor((center[X] + OT_BIAS) / bsized); id->y = (int) floor((center[Y] + OT_BIAS) / bsized); id->z = (int) floor((center[Z] + OT_BIAS) / bsized); POW2OP_ENCODE(id->Size, bsized) #ifdef RADSTATS thisloops = 0; #endif while (!ot_point_in_node(min_point, id) || !ot_point_in_node(max_point, id)) { // Debug_Info("looping %d,%d,%d,%d min=%d, max=%d\n", test_id.x, test_id.y, // test_id.z, test_id.Size, ot_point_in_node(min_point, &test_id), // ot_point_in_node(max_point, &test_id)); ot_parent(id, id); #ifdef RADSTATS totloops++; thisloops++; #endif } #ifdef RADSTATS if (thisloops < minloops) minloops = thisloops; if (thisloops > maxloops) maxloops = thisloops; #endif #ifdef OT_DEBUG if (id->Size > 139) { Debug_Info("unusually large id, maxdel=%.4f, bsized=%.4f, isize=%d\n", maxdel, bsized, id->Size); } #endif }