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; } } }
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; } } }