void Photonmap::BalanceSegment( Photon* porg , int index , int st , int en ) { if ( st == en ) { photons[index] = porg[st]; return; } int med = 1; while ( 4 * med <= en - st + 1 ) med <<= 1; if ( 3 * med <= en - st + 1 ) med = med * 2 + st - 1; else med = en + 1 - med; int axis = 2; if ( box_max.x - box_min.x > box_max.y - box_min.y && box_max.x - box_min.x > box_max.z - box_min.z ) axis = 0; else if ( box_max.y - box_min.y > box_max.z - box_min.z ) axis = 1; MedianSplit( porg , st , en , med , axis ); photons[index] = porg[med]; photons[index].plane = axis; if ( st < med ) { double tmp = box_max.GetCoord( axis ); box_max.GetCoord( axis ) = photons[index].pos.GetCoord( axis ); BalanceSegment( porg , index * 2 , st , med - 1 ); box_max.GetCoord( axis ) = tmp; } if ( med < en ) { double tmp = box_min.GetCoord( axis ); box_min.GetCoord( axis ) = photons[index].pos.GetCoord( axis ); BalanceSegment( porg , index * 2 + 1 , med + 1 , en ); box_min.GetCoord( axis ) = tmp; } }
void Photonmap::Balance() { Photon* porg = new Photon[stored_photons + 1]; for ( int i = 0 ; i <= stored_photons ; i++ ) porg[i] = photons[i]; BalanceSegment( porg , 1 , 1 , stored_photons ); delete[] porg; }
void Balance(bool complete) { if (!complete) { // photon-map was not filled to capacity; // this means we must now get rid of the // excess reserved NULL nodes size_t nullNodeIdx = 1; // find the first node that is still NULL while (nullNodeIdx < nodes.size() && nodes[nullNodeIdx] != NULL) { nullNodeIdx++; } // shrink the vector if (nullNodeIdx < nodes.size()) { nodes.resize(nullNodeIdx); } } if (nodes.size() > 1) { // use two temporary buffers for balancing // // at every level of the recursion, these // represent and store the left and right // subtrees with respect to the new median // point along the splitting axis (subtrees // are delineated by start- and end-indices) // // note: could we do this in-place instead? std::vector<T> lftSegment(nodes.size(), NULL); std::vector<T> rgtSegment(nodes.size(), NULL); for (size_t i = 0; i < nodes.size(); i++) { lftSegment[i] = NULL; rgtSegment[i] = nodes[i]; } BalanceSegment(lftSegment, rgtSegment, 1, 1, (nodes.size() - 1)); BuildHeap(lftSegment); } }
void BalanceSegment( std::vector<T>& lftSegment, std::vector<T>& rgtSegment, const int rNodeNum, // index of node representing root of segment const int sNodeNum, // index of node representing start of segment const int eNodeNum // index of node representing end of segment ) { assert(sNodeNum >= 0); assert(eNodeNum < int(lftSegment.size())); int newMedianIdx = 1; int splitAxisIdx = 2; { // compute index of new median node based on start- and end-node indices (?) while ((4 * newMedianIdx) <= (eNodeNum - sNodeNum + 1)) { newMedianIdx <<= 1; } if ((3 * newMedianIdx) <= (eNodeNum - sNodeNum + 1)) { newMedianIdx <<= 1; newMedianIdx += (sNodeNum - 1); } else { newMedianIdx = eNodeNum - newMedianIdx + 1; } } { // find the axis to split along if (((maxs.x - mins.x) > (maxs.y - mins.y)) && ((maxs.x - mins.x) > (maxs.z - mins.z))) { splitAxisIdx = 0; } else { if ((maxs.y - mins.y) > (maxs.z - mins.z)) { splitAxisIdx = 1; } } } // partition block of nodes around the new median MedianSplitSegment(rgtSegment, sNodeNum, eNodeNum, newMedianIdx, splitAxisIdx); lftSegment[rNodeNum] = rgtSegment[newMedianIdx]; lftSegment[rNodeNum]->SetAxis(splitAxisIdx); { if (newMedianIdx > sNodeNum) { // recursively balance the left block if (sNodeNum < (newMedianIdx - 1)) { const float v = maxs[splitAxisIdx]; maxs[splitAxisIdx] = lftSegment[rNodeNum]->GetPos()[splitAxisIdx]; BalanceSegment(lftSegment, rgtSegment, (rNodeNum << 1), sNodeNum, newMedianIdx - 1); maxs[splitAxisIdx] = v; } else { lftSegment[(rNodeNum << 1)] = rgtSegment[sNodeNum]; } } if (newMedianIdx < eNodeNum) { // recursively balance the right block if ((newMedianIdx + 1) < eNodeNum) { const float v = mins[splitAxisIdx]; mins[splitAxisIdx] = lftSegment[rNodeNum]->GetPos()[splitAxisIdx]; BalanceSegment(lftSegment, rgtSegment, (rNodeNum << 1) + 1, newMedianIdx + 1, eNodeNum); mins[splitAxisIdx] = v; } else { lftSegment[(rNodeNum << 1) + 1] = rgtSegment[eNodeNum]; } } } }