#ifndef MULT_RES_H #define MULT_RES_H #include #include #include #include template class MultiResolution { public: //// TreeNode class Node { public: // GROUP: Constructors Node(const PointT* point, short level=0, float lowLevelRadius=0.0, unsigned int subtreeSize=1, unsigned int asNum=0): point_(point), level_(level), lowLevelRadius_(lowLevelRadius), subtreeSize_(subtreeSize), asNum_(asNum) {} // GROUP: Modifiers //// update asNum void incrementAsNum(unsigned int num) { asNum_ += num; } //// add children to node void addChildren(const std::vector& children) { lowLevelPointers_.insert(lowLevelPointers_.begin(), children.begin(), children.end()); } // GROUP: Queries //// return point pointer const PointT* getPoint() const { return point_; } //// return point position Vector3 position() const { return point_->position(); } //// get node level short getLevel() const { return level_; } //// get radius float getRadius() const { return lowLevelRadius_; } //// get subtree size unsigned int getSubtreeSize() const { return subtreeSize_; } //// get number of active nodes in the subtree unsigned int getAsNum() const { return asNum_; } //// get pointers to node children const std::vector& getChildren() const { return lowLevelPointers_; } protected: // point const PointT* point_; // level short level_; // radius of lower level points float lowLevelRadius_; // number of subtree nodes unsigned int subtreeSize_; // number of active site nodes unsigned int asNum_; // pointers to lower level std::vector lowLevelPointers_; }; typedef std::vector Level; // GROUP: Contructors //// The initial bin size is computed based on density and number of tree // levels is computed based on the size of the grid margins MultiResolution(const std::vector& pointSet, float density=10.0, float gridMargins=6.0); MultiResolution(float density=10.0, float gridMargins=6.0); // GROUP: Modifiers void setPointSet(const std::vector& pointSet) { pointSet_ = pointSet; } void buildTree(); void buildTree(const std::vector& as); void countActiveSitePoints(const std::vector& as); // GROUP: Queries Level& getLevel(unsigned int num) { return tree_[num]; } unsigned int size() const { return tree_.size(); } int getAsPointsNumber() const { return asPointsNumber_; } void printTree(std::ofstream& outFile); private: void createHighLevel(const int lowLevelIndex, float radius); void findMaxRadiusForPoint(const Vector3& point, const Node* currNode, float& currMaxRadius2); private: std::vector pointSet_; std::vector tree_; int asPointsNumber_; float binSize_; }; template MultiResolution::MultiResolution(const std::vector& pointSet, float density, float gridMargins) : pointSet_(pointSet) { unsigned int POINTS_PER_CUBE = 5; binSize_ = POINTS_PER_CUBE/density; Level l; for(float cs=binSize_; cs <= gridMargins*2; cs*=2) { //-1 tree_.push_back(l); } // cout << "Tree size: " << tree_.size() << endl; } template MultiResolution::MultiResolution(float density, float gridMargins) { unsigned int POINTS_PER_CUBE = 5; binSize_ = POINTS_PER_CUBE/density; Level l; for(float cs=binSize_; cs <= gridMargins*2; cs*=2) { //-1 tree_.push_back(l); } // cout << "Tree size: " << tree_.size() << endl; } template void MultiResolution::createHighLevel(const int lowLevelIndex, float binSize) { const Level& lowLevel = tree_[lowLevelIndex]; // insert to ghash GeomHash gHash(3, binSize); for(unsigned int i=0; i< lowLevel.size(); i++) gHash.insert(lowLevel[i].position(), &lowLevel[i]); // init Level short levelIndex = lowLevelIndex+1; Level& highLevel = tree_[levelIndex]; // compute high resolution - iterate over each Bucket typename GeomHash::BucketsPointerList *bucketList = gHash.getBuckets(); typename GeomHash::BucketsPointerList::const_iterator bIter, bEndIter = bucketList->end(); for(bIter = bucketList->begin(); bIter != bEndIter; bIter++) { const std::vector& currBucket = **bIter; // compute average bucket point // compute subtree size Vector3 average; unsigned int subTreeSize=0; typename std::vector::const_iterator currBucketIter, bucketEndIter = currBucket.end(); for(currBucketIter = currBucket.begin(); currBucketIter != bucketEndIter; currBucketIter++) { average+= (*currBucketIter)->position(); subTreeSize+=(*currBucketIter)->getSubtreeSize(); } average/=currBucket.size(); // find point closest to average float minDist2 = MAX_FLOAT; const Node* selectedNode=NULL; for(currBucketIter = currBucket.begin(); currBucketIter != bucketEndIter; currBucketIter++) { float currDist2 = average.dist2((*currBucketIter)->position()); if(currDist2 < minDist2) { selectedNode = *currBucketIter; minDist2 = currDist2; } } // find radius of pts == maxDist from average float maxDist2 = MIN_FLOAT; for(currBucketIter = currBucket.begin(); currBucketIter != bucketEndIter; currBucketIter++) findMaxRadiusForPoint(selectedNode->position(), *currBucketIter, maxDist2); // create new node Node newNode(selectedNode->getPoint(), levelIndex, sqrt(maxDist2), subTreeSize); newNode.addChildren(currBucket); highLevel.push_back(newNode); } delete bucketList; // cout << ": " << highLevel.size() << " "; } template void MultiResolution::findMaxRadiusForPoint(const Vector3& point, const Node* currNode, float& currMaxRadius2) { int levelIndex = currNode->getLevel(); float dist2 = currNode->position().dist2(point); if(levelIndex==0) { if(dist2 > currMaxRadius2) currMaxRadius2=dist2; return; } // check if distance to (point+radius)^2 < currMaxRadius2 float radius = currNode->getRadius(); float dist = sqrt(dist2); if(sqr(radius+dist) < currMaxRadius2) return; const std::vector& lowLevelPointersForPoint = currNode->getChildren(); typename std::vector::const_iterator iter, endIter=lowLevelPointersForPoint.end(); if(levelIndex==1) { for(iter=lowLevelPointersForPoint.begin(); iter!=endIter; iter++) { float dist2=point.dist2((*iter)->position()); if(dist2 > currMaxRadius2) currMaxRadius2=dist2; } return; } if(levelIndex > 1) { for(iter=lowLevelPointersForPoint.begin(); iter!=endIter; iter++) { findMaxRadiusForPoint(point, *iter, currMaxRadius2); } return; } return; } template void MultiResolution::buildTree() { // initiate lowest level Level& lowLevel = tree_[0]; for(unsigned int i=0; i void MultiResolution::buildTree(const std::vector& as) { buildTree(); countActiveSitePoints(as); } template void MultiResolution::countActiveSitePoints(const std::vector& as) { Level& lowLevel = tree_[0]; if(as.size() != lowLevel.size()) { std::cerr << "Error in active site array" << std::endl; return; } // mark low level leaves asPointsNumber_=0; for(unsigned int i=0; i& lowLevelPointers = currNode.getChildren(); for(unsigned int lowLevelIndex=0; lowLevelIndexgetAsNum()); } } } template void MultiResolution::printTree(std::ofstream& outFile) { int count=0; for(unsigned int levelIndex=0; levelIndex 0) { Atom atom(currNode.position(), 'A', count++, levelIndex, "INT", 'X'); outFile << atom << std::endl; } else { Atom atom(currNode.position(), 'A', count++, levelIndex, "PRB", 'X'); outFile << atom << std::endl; } } } } #endif