void RDirNode::setInitialPosition() { RDirNode* parentP = parent->getParent(); pos = parent->getPos(); //offset position by some pseudo-randomness if(parentP != 0) { pos += ((parent->getPos() - parentP->getPos()).normal() * 2.0 + vec2Hash(abspath)).normal(); } else { pos += vec2Hash(abspath); } //the spline point spos = pos - (parent->getPos() - pos) * 0.5; position_initialized=true; }
void Gource::updateBounds() { user_bounds.reset(); for(std::map<std::string,RUser*>::iterator it = users.begin(); it!=users.end(); it++) { RUser* u = it->second; if(!u->isIdle()) { user_bounds.update(u->getPos()); } } dir_bounds.reset(); for(std::map<std::string,RDirNode*>::iterator it = gGourceDirMap.begin(); it!=gGourceDirMap.end(); it++) { RDirNode* node = it->second; if(node->isVisible()) { dir_bounds.update(node->getPos()); } } }
void RDirNode::applyForces(QuadTree& quadtree) { //child nodes for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* node = (*it); node->applyForces(quadtree); } if(parent == 0) return; std::vector<QuadItem*> inbounds; int found = quadtree.getItemsInBounds(inbounds, quadItemBounds); std::set<std::string> seen; std::set<std::string>::iterator seentest; //apply forces with other that are inside the 'box' of this nodes radius for(std::vector<QuadItem*>::iterator it = inbounds.begin(); it != inbounds.end(); it++) { RDirNode* d = (RDirNode*) (*it); if(d==this) continue; if(d==parent) continue; if(d->parent==this) continue; if((seentest = seen.find(d->getPath())) != seen.end()) { continue; } seen.insert(d->getPath()); if(isParentOf(d)) continue; if(d->isParentOf(this)) continue; applyForceDir(d); gGourceDirNodeInnerLoops++; } //always call on parent no matter how far away applyForceDir(parent); //pull towards parent float parent_dist = distanceTo(parent); // * dirs should attract to sit on the radius of the parent dir ie: // should attract to distance_to_parent * normal_to_parent accel += gGourceForceGravity * parent_dist * (parent->getPos() - pos).normal(); // * dirs should be pushed along the parent_parent to parent normal by a force smaller than the parent radius force RDirNode* pparent = parent->getParent(); if(pparent != 0) { vec2f parent_edge = (parent->getPos() - pparent->getPos()); vec2f parent_edge_normal = parent_edge.normal(); vec2f dest = (parent->getPos() + (parent->getRadius() + getRadius()) * parent_edge_normal) - pos; accel += dest; } // * dirs should repulse from other dirs of this parent std::list<RDirNode*>* siblings = parent->getChildren(); if(siblings->size() > 0) { vec2f sib_accel; int visible = 1; for(std::list<RDirNode*>::iterator it = siblings->begin(); it != siblings->end(); it++) { RDirNode* node = (*it); if(node == this) continue; if(!node->isVisible()) continue; visible++; sib_accel -= (node->getPos() - pos).normal(); } //parent circumfrence divided by the number of visible child nodes if(visible>1) { float slice_size = (parent->getRadius() * PI) / (float) (visible+1); sib_accel *= slice_size; accel += sib_accel; } } }
bool RDirNode::addFile(RFile* f) { //doesnt match this path at all if(f->path.find(abspath) != 0) { if(parent!=0) return false; RDirNode* newparent; std::string common = commonPathPrefix(f->path); if(common.size()==0) common = "/"; newparent = new RDirNode(0, common); newparent->addNode(this); return newparent->addFile(f); } //simply change path of node and add this to it if( parent==0 && abspath == "/" && f->path.compare(abspath) != 0 && fileCount()==0 && dirCount()==0) { debugLog("modifying root path to %s\n", f->path.c_str()); changePath(f->path); } //is this dir - add to this node if(f->path.compare(abspath) == 0) { //debugLog("addFile %s to %s\n", f->fullpath.c_str(), abspath.c_str()); files.push_back(f); if(!f->isHidden()) visible_count++; f->setDir(this); fileUpdated(false); return true; } //does this belong to one of the children ? for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* child = (*it); bool added = child->addFile(f); if(added) return true; } //add new child, add it to that //if commonpath is longer than abspath, add intermediate node, else just add at the files path RDirNode* node = new RDirNode(this, f->path); node->addFile(f); addNode(node); // do we have dir nodes, with a common path element greater than abspath, // if so create another node, and move those nodes there std::string commonpath; vec2f commonPos; for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* child = (*it); std::string common = child->commonPathPrefix(f->path); if(common.size() > abspath.size() && common != f->path) { commonpath = common; commonPos = child->getPos(); break; } } // redistribute to new common node if(commonpath.size() > abspath.size()) { //debugLog("common path %s\n", commonpath.c_str()); RDirNode* cnode = new RDirNode(this, commonpath); cnode->setPos(commonPos); for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end();) { RDirNode* child = (*it); if(child->prefixedBy(commonpath)) { //debugLog("this path = %s, commonpath = %s, path = %s\n", abspath.c_str(), commonpath.c_str(), child->getPath().c_str()); it = children.erase(it); cnode->addNode(child); continue; } it++; } addNode(cnode); } return true; }
void RDirNode::applyForces(QuadTree & quadtree) { //child nodes for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* node = (*it); node->applyForces(quadtree); } if(parent == 0) return; DirForceFunctor dff(this); quadtree.visitItemsInBounds(quadItemBounds, dff); gGourceDirNodeInnerLoops += dff.getLoopCount(); //always call on parent no matter how far away applyForceDir(parent); //pull towards parent float parent_dist = distanceToParent(); // * dirs should attract to sit on the radius of the parent dir ie: // should attract to distance_to_parent * normal_to_parent accel += gGourceForceGravity * parent_dist * normalise(parent->getPos() - pos); // * dirs should be pushed along the parent_parent to parent normal by a force smaller than the parent radius force RDirNode* pparent = parent->getParent(); if(pparent != 0) { vec2 parent_edge = (parent->getPos() - pparent->getPos()); vec2 parent_edge_normal = normalise(parent_edge); vec2 dest = (parent->getPos() + (parent->getRadius() + getRadius()) * parent_edge_normal) - pos; accel += dest; } // * dirs should repulse from other dirs of this parent const std::list<RDirNode*> & siblings = parent->getChildren(); if(!siblings.empty()) { vec2 sib_accel; int visible = 1; for(std::list<RDirNode*>::const_iterator it = siblings.begin(); it != siblings.end(); it++) { RDirNode* node = (*it); if(node == this) continue; if(!node->isVisible()) continue; visible++; sib_accel -= normalise(node->getPos() - pos); } //parent circumfrence divided by the number of visible child nodes if(visible>1) { float slice_size = (parent->getRadius() * PI) / (float) (visible+1); sib_accel *= slice_size; accel += sib_accel; } } }
bool RDirNode::addFile(RFile* f) { //doesnt match this path at all if(f->path.find(abspath) != 0) { if(parent != 0) return false; //if this is the root node (ie no parent), we fork it //if we encounter a file with a non matching path to the //current root path. the calling process then checks if //the root now has a parent node, and changes the pointer. RDirNode* newparent; std::string common = commonPathPrefix(f->path); if(common.size()==0) common = "/"; newparent = new RDirNode(0, common); newparent->addNode(this); return newparent->addFile(f); } //simply change path of node and add this to it if( parent==0 && abspath == "/" && f->path.compare(abspath) != 0 && noFiles() && noDirs()) { debugLog("modifying root path to %s", f->path.c_str()); changePath(f->path); } //is this dir - add to this node if(f->path.compare(abspath) == 0) { //debugLog("addFile %s to %s\n", f->fullpath.c_str(), abspath.c_str()); files.push_back(f); if(!f->isHidden()) visible_count++; f->setDir(this); fileUpdated(false); return true; } bool added = false; //does this belong to one of the children ? for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* child = (*it); added = child->addFile(f); if(added) break; } if(added && parent != 0) return true; //do we have a file in this directory thats fullpath is a prefix of this file, if so //that file is actually a directory - the file should be removed, and a directory with that path added //if this is the root node we do this regardless of if the file was added to a child node for(std::list<RFile*>::const_iterator it = files.begin(); it != files.end(); it++) { RFile* file = (*it); if(f->path.find(file->fullpath) == 0) { //fprintf(stderr, "removing %s as is actually the directory of %s\n", file->fullpath.c_str(), f->fullpath.c_str()); file->remove(true); break; } } if(added) return true; //add new child, add it to that //if commonpath is longer than abspath, add intermediate node, else just add at the files path RDirNode* node = new RDirNode(this, f->path); node->addFile(f); addNode(node); // do we have dir nodes, with a common path element greater than abspath, // if so create another node, and move those nodes there std::string commonpath; vec2 commonPos; for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { RDirNode* child = (*it); std::string common = child->commonPathPrefix(f->path); if(common.size() > abspath.size() && common != f->path) { commonpath = common; commonPos = child->getPos(); break; } } // redistribute to new common node if(commonpath.size() > abspath.size()) { //debugLog("common path %s\n", commonpath.c_str()); RDirNode* cnode = new RDirNode(this, commonpath); cnode->setPos(commonPos); for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end();) { RDirNode* child = (*it); if(child->prefixedBy(commonpath)) { //debugLog("this path = %s, commonpath = %s, path = %s\n", abspath.c_str(), commonpath.c_str(), child->getPath().c_str()); it = children.erase(it); cnode->addNode(child); continue; } it++; } addNode(cnode); } return true; }