void print_Plist(const Plist& L, str s) { printf("%s \n",s.c_str()); int n = L.size(); for (int i=0; i<n; i++) printf("%5d : (%d,%d)\n",i,L[i].f,L[i].s); printf("\n"); }
int isfound(pair p, const Plist& L) { int j = p.f; int k = p.s; if (L.size()==0) return -1; for (int i=0; i<L.size(); i++) if (L[i].f==j && L[i].s==k) return i; return -1; }
//=========================================================================== void cCollisionSpheresNode::ConstructChildren(Plist &a_primList) { // ensure that there are at least two primitives so that it makes sense // to split them into left and right subtrees Plist::iterator primIter; assert(a_primList.size() >= 2); // declare and initialize local variables for splitting primitives Plist leftList, rightList; double min[3] = {LARGE, LARGE, LARGE}; double max[3] = {-LARGE, -LARGE, -LARGE}; // find minimum and maximum values for each coordinate of primitves' centers for (primIter = a_primList.begin(); primIter != a_primList.end(); primIter++) { cCollisionSpheresGenericShape *cur = *primIter; const cVector3d ¢er = cur->getCenter(); for (int i = 0; i < 3; i++) { if (center.get(i) < min[i]) min[i] = center.get(i); if (center.get(i) > max[i]) max[i] = center.get(i); } } // find the coordinate index with the largest range (max to min) int split = 0; if ((max[1] - min[1]) > (max[split] - min[split])) split = 1; if ((max[2] - min[2]) > (max[split] - min[split])) split = 2; // sort the primitives according to the coordinate with largest range cCollisionSpheresGenericShape::m_split = split; std::sort(a_primList.begin(), a_primList.end()); // put first half in left subtree and second half in right subtree unsigned int s; for (s=0; s<a_primList.size()/2; s++) leftList.insert(leftList.end(), a_primList[s]); for (s=a_primList.size()/2; s<a_primList.size(); s++) rightList.insert(rightList.end(), a_primList[s]); // if the left subtree is empty, transfer one from the right list if (leftList.size() == 0) { leftList.insert(leftList.begin(), *rightList.begin()); rightList.erase(rightList.begin()); } // create new internal nodes as roots for left and right subtree lists, or // a leaf node if the subtree list has only one primitive if (leftList.size() == 1) m_left = new(g_nextLeafNode++) cCollisionSpheresLeaf(*(leftList.begin()), this); else m_left = new(g_nextInternalNode++) cCollisionSpheresNode(leftList, this); if (rightList.size() == 1) m_right = new(g_nextLeafNode++) cCollisionSpheresLeaf(*(rightList.begin()), this); else m_right = new(g_nextInternalNode++) cCollisionSpheresNode(rightList, this); // get centers and radii of left and right children const cVector3d &lc = m_left->m_center; const cVector3d &rc = m_right->m_center; double lr = m_left->getRadius(); double rr = m_right->getRadius(); // compute new radius as one-half the sum of the distance between the two // childrens' centers and the two childrens' radii double dist = lc.distance(rc); m_radius = (dist + lr + rr) / 2.0; // compute new center along line between childrens' centers if (dist != 0) { double lambda = (m_radius - lr) / dist; m_center.x = lc.x + lambda*(rc.x - lc.x); m_center.y = lc.y + lambda*(rc.y - lc.y); m_center.z = lc.z + lambda*(rc.z - lc.z); } // if the left and right children have the same center, use this as the // new center else { m_center = lc; } // if one sphere is entirely contained within the other, set this sphere's // new center and radius equal to those of the larger one if (lr > dist + rr) { m_center = lc; m_radius = lr; } if (rr > dist + lr) { m_center = rc; m_radius = rr; } m_radius*=1.001; }