| #ifndef MULT_RES_H
|
| #define MULT_RES_H
|
|
|
| #include <Vector3.h>
|
| #include <Atom.h>
|
| #include <GeomHash.h>
|
| #include <numerics.h>
|
|
|
| template<class PointT>
|
| class MultiResolution {
|
| public:
|
|
|
|
|
| class Node {
|
|
|
| public:
|
|
|
| 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) {}
|
|
|
|
|
|
|
| void incrementAsNum(unsigned int num) { asNum_ += num; }
|
|
|
|
|
| void addChildren(const std::vector<const Node *>& children) {
|
| lowLevelPointers_.insert(lowLevelPointers_.begin(), children.begin(), children.end());
|
| }
|
|
|
|
|
|
|
| const PointT* getPoint() const { return point_; }
|
|
|
|
|
| Vector3 position() const { return point_->position(); }
|
|
|
|
|
| short getLevel() const { return level_; }
|
|
|
|
|
| float getRadius() const { return lowLevelRadius_; }
|
|
|
|
|
| unsigned int getSubtreeSize() const { return subtreeSize_; }
|
|
|
|
|
| unsigned int getAsNum() const { return asNum_; }
|
|
|
|
|
| const std::vector<const Node *>& getChildren() const { return lowLevelPointers_; }
|
|
|
| protected:
|
|
|
| const PointT* point_;
|
|
|
| short level_;
|
|
|
| float lowLevelRadius_;
|
|
|
| unsigned int subtreeSize_;
|
|
|
| unsigned int asNum_;
|
|
|
| std::vector<const Node *> lowLevelPointers_;
|
|
|
| };
|
|
|
| typedef std::vector<Node> Level;
|
|
|
|
|
|
|
|
|
| MultiResolution(const std::vector<PointT>& pointSet, float density=10.0, float gridMargins=6.0);
|
| MultiResolution(float density=10.0, float gridMargins=6.0);
|
|
|
|
|
| void setPointSet(const std::vector<PointT>& pointSet) { pointSet_ = pointSet; }
|
| void buildTree();
|
| void buildTree(const std::vector<bool>& as);
|
| void countActiveSitePoints(const std::vector<bool>& as);
|
|
|
|
|
| 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<PointT> pointSet_;
|
| std::vector<Level> tree_;
|
| int asPointsNumber_;
|
| float binSize_;
|
| };
|
|
|
| template<class PointT>
|
| MultiResolution<PointT>::MultiResolution(const std::vector<PointT>& 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) {
|
| tree_.push_back(l);
|
| }
|
|
|
| }
|
|
|
| template<class PointT>
|
| MultiResolution<PointT>::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) {
|
| tree_.push_back(l);
|
| }
|
|
|
| }
|
|
|
|
|
| template<class PointT>
|
| void MultiResolution<PointT>::createHighLevel(const int lowLevelIndex, float binSize) {
|
| const Level& lowLevel = tree_[lowLevelIndex];
|
|
|
| GeomHash<Vector3, const Node* > gHash(3, binSize);
|
| for(unsigned int i=0; i< lowLevel.size(); i++)
|
| gHash.insert(lowLevel[i].position(), &lowLevel[i]);
|
|
|
|
|
| short levelIndex = lowLevelIndex+1;
|
| Level& highLevel = tree_[levelIndex];
|
|
|
|
|
| typename GeomHash<Vector3, const Node*>::BucketsPointerList *bucketList = gHash.getBuckets();
|
| typename GeomHash<Vector3, const Node*>::BucketsPointerList::const_iterator bIter, bEndIter = bucketList->end();
|
| for(bIter = bucketList->begin(); bIter != bEndIter; bIter++) {
|
| const std::vector<const Node*>& currBucket = **bIter;
|
|
|
|
|
| Vector3 average;
|
| unsigned int subTreeSize=0;
|
| typename std::vector<const Node*>::const_iterator currBucketIter, bucketEndIter = currBucket.end();
|
| for(currBucketIter = currBucket.begin(); currBucketIter != bucketEndIter; currBucketIter++) {
|
| average+= (*currBucketIter)->position();
|
| subTreeSize+=(*currBucketIter)->getSubtreeSize();
|
| }
|
| average/=currBucket.size();
|
|
|
|
|
| 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;
|
| }
|
| }
|
|
|
|
|
| float maxDist2 = MIN_FLOAT;
|
| for(currBucketIter = currBucket.begin(); currBucketIter != bucketEndIter; currBucketIter++)
|
| findMaxRadiusForPoint(selectedNode->position(), *currBucketIter, maxDist2);
|
|
|
|
|
| Node newNode(selectedNode->getPoint(), levelIndex, sqrt(maxDist2), subTreeSize);
|
| newNode.addChildren(currBucket);
|
| highLevel.push_back(newNode);
|
| }
|
| delete bucketList;
|
|
|
| }
|
|
|
| template<class PointT>
|
| void MultiResolution<PointT>::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;
|
| }
|
|
|
| float radius = currNode->getRadius();
|
| float dist = sqrt(dist2);
|
| if(sqr(radius+dist) < currMaxRadius2) return;
|
| const std::vector<const Node*>& lowLevelPointersForPoint = currNode->getChildren();
|
| typename std::vector<const Node*>::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<class PointT>
|
| void MultiResolution<PointT>::buildTree() {
|
|
|
| Level& lowLevel = tree_[0];
|
| for(unsigned int i=0; i<pointSet_.size(); i++) {
|
| Node node(&pointSet_[i], 0, 0, 1);
|
| lowLevel.push_back(node);
|
| }
|
|
|
|
|
|
|
| float radius = binSize_;
|
| for(unsigned int i=0; i< tree_.size()-1; i++) {
|
|
|
| createHighLevel(i, radius);
|
| radius*=2;
|
| }
|
|
|
| }
|
|
|
| template<class PointT>
|
| void MultiResolution<PointT>::buildTree(const std::vector<bool>& as) {
|
| buildTree();
|
| countActiveSitePoints(as);
|
| }
|
|
|
| template<class PointT>
|
| void MultiResolution<PointT>::countActiveSitePoints(const std::vector<bool>& as) {
|
| Level& lowLevel = tree_[0];
|
| if(as.size() != lowLevel.size()) {
|
| std::cerr << "Error in active site array" << std::endl;
|
| return;
|
| }
|
|
|
| asPointsNumber_=0;
|
| for(unsigned int i=0; i<lowLevel.size(); i++) {
|
| lowLevel[i].incrementAsNum(as[i]);
|
| if(as[i]==1) asPointsNumber_++;
|
| }
|
|
|
| for(unsigned int levelIndex=1; levelIndex<tree_.size(); levelIndex++) {
|
| Level& currLevel = tree_[levelIndex];
|
| for(unsigned int nodeIndex=0; nodeIndex<currLevel.size(); nodeIndex++) {
|
| Node& currNode = currLevel[nodeIndex];
|
| const std::vector<const Node *>& lowLevelPointers = currNode.getChildren();
|
| for(unsigned int lowLevelIndex=0; lowLevelIndex<lowLevelPointers.size(); lowLevelIndex++)
|
| currNode.incrementAsNum(lowLevelPointers[lowLevelIndex]->getAsNum());
|
| }
|
| }
|
| }
|
|
|
| template<class PointT>
|
| void MultiResolution<PointT>::printTree(std::ofstream& outFile)
|
| {
|
| int count=0;
|
| for(unsigned int levelIndex=0; levelIndex<tree_.size(); levelIndex++) {
|
| Level& currLevel = tree_[levelIndex];
|
| for(unsigned int nodeIndex=0; nodeIndex<currLevel.size(); nodeIndex++) {
|
| Node& currNode = currLevel[nodeIndex];
|
| if(currNode.asNum_ > 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
|
|
|