StateTreeNode::StateTreeNode( const StateSet &stateSet, int maxDepth, double centerShiftMultiplier ) : numSpacePartitions(pow(2, stateSet.getStates().at(0)->getCoordinates().size())) { const vector<AbstractState*> &states = stateSet.getStates(); unsigned int numCoordinates = states.at(0)->getCoordinates().size(); for(unsigned int n = 1; n < states.size(); n++){ TBTKAssert( numCoordinates == states.at(n)->getCoordinates().size(), "StateTreeNode::StateTreeNode()", "Unable to handle StateSets containing states with different dimensions.", "" ); } //Find bounding box. vector<double> min; vector<double> max; double maxFiniteExtent = 0.; unsigned int n = 0; //Find first state with finite extent and initialize min and max such //that the state is contained inside the corresponding rectangle. for(; n < states.size(); n++){ if(states.at(n)->hasFiniteExtent()){ for(unsigned int c = 0; c < numCoordinates; c++){ min.push_back(states.at(n)->getCoordinates().at(c) - states.at(n)->getExtent()); max.push_back(states.at(n)->getCoordinates().at(c) + states.at(n)->getExtent()); } maxFiniteExtent = states.at(n)->getExtent(); break; } } //If all state have infinite extent, create a dummy box of zero extent. if(n == states.size()){ for(unsigned int c = 0; c < states.at(0)->getCoordinates().size(); c++){ min.push_back(0); max.push_back(0); } } //Loop over all remaining states and update min and max so that every //state is contained in the corresponding rectangle. for(; n < states.size(); n++){ if(!states.at(n)->hasFiniteExtent()) continue; for(unsigned int c = 0; c < numCoordinates; c++){ if(min.at(c) > states.at(n)->getCoordinates().at(c) - states.at(n)->getExtent()) min.at(c) = states.at(n)->getCoordinates().at(c) - states.at(n)->getExtent(); if(max.at(c) < states.at(n)->getCoordinates().at(c) + states.at(n)->getExtent()) max.at(c) = states.at(n)->getCoordinates().at(c) + states.at(n)->getExtent(); } if(maxFiniteExtent < states.at(n)->getExtent()) maxFiniteExtent = states.at(n)->getExtent(); } //Enlarge and shift box to avoid problems with high level partition //boundaries cutting through states. This would be particularly //problematic if the states for example have three dimensional //coordinates, but are contained in a plane. Without shifting the box, //the first partition boundary would cut every state and thereby every //state would be added to the root node. for(unsigned int n = 0; n < max.size(); n++) max.at(n) += centerShiftMultiplier*maxFiniteExtent; for(unsigned int n = 0; n < min.size(); n++) min.at(n) -= 2.*(max.at(n) - min.at(n))*(1 - ROUNDOFF_MARGIN_MULTIPLIER); //Calculate center nad halfSize of the bounding box. halfSize = 0.; for(unsigned int n = 0; n < numCoordinates; n++){ center.push_back((min.at(n) + max.at(n))/2.); if(halfSize < (max.at(n) - min.at(n))/2.) halfSize = (max.at(n) - min.at(n))/2.; } this->maxDepth = maxDepth; for(unsigned int n = 0; n < states.size(); n++) add(states.at(n)); }