不规则八叉树的空间分割与检索
不同规则八叉树,在每一次分割时,需要判断选择一个合适的分割维度(x或y或z),而不是每次都对xyz做分割。这样可以很大程度避免叶子节点为空的情况,检索起来速度也较快。但是叶子节点的形状不再是规则的正立方体,而是相互不等长方体。
树的建立:
int OcTree::buildOcTree() { ptree->root = new ocTreeNode; ptree->root->data = new size_t[pointsSize]; for (size_t j = 0; j < pointsSize; j++) { ptree->root->data[j] = j; } ptree->root->numOfData = pointsSize; ptree->root->father = NULL; ptree->root->dim = 1; ptree->root->nodePos = 0; ocTreeNode* tempNode = ptree->root; std::queue<ocTreeNode*> octreeNodePtrQue; octreeNodePtrQue.push(tempNode); int slipnum = 0; float deltaNum = 0.0; //创建kdtree while (true) { //slipnum = tempkdnode->nodeDepth % 3; if (tempNode->numOfData==0) //说明为空节点 { octreeNodePtrQue.pop(); if (octreeNodePtrQue.size() == 0) { break; } tempNode = octreeNodePtrQue.front(); continue; } //计算树的节点分割线 float xtempMin = pointCloud[tempNode->data[0]].x; float ytempMin = pointCloud[tempNode->data[0]].y; float ztempMin = pointCloud[tempNode->data[0]].z; float xtempMax = xtempMin; float ytempMax = ytempMin; float ztempMax = ztempMin; for (size_t j = 0; j < tempNode->numOfData; j++) { if (xtempMin>pointCloud[tempNode->data[j]].x) { xtempMin = pointCloud[tempNode->data[j]].x; } if (xtempMax<pointCloud[tempNode->data[j]].x) { xtempMax = pointCloud[tempNode->data[j]].x; } if (ytempMin>pointCloud[tempNode->data[j]].y) { ytempMin = pointCloud[tempNode->data[j]].y; } if (ytempMax<pointCloud[tempNode->data[j]].y) { ytempMax = pointCloud[tempNode->data[j]].y; } if (ztempMin>pointCloud[tempNode->data[j]].z) { ztempMin = pointCloud[tempNode->data[j]].z; } if (ztempMax<pointCloud[tempNode->data[j]].z) { ztempMax = pointCloud[tempNode->data[j]].z; } } float xtemp = xtempMax - xtempMin; float ytemp = ytempMax - ytempMin; float ztemp = ztempMax - ztempMin; if (xtemp>ytemp && xtemp>ztemp) { slipnum = 1; tempNode->splitScale[0] = xtempMin; tempNode->splitScale[1] = xtempMax; } else if (ytemp>xtemp && ytemp>ztemp) { slipnum = 2; tempNode->splitScale[0] = ytempMin; tempNode->splitScale[1] = ytempMax; } else { slipnum = 3; tempNode->splitScale[0] = ztempMin; tempNode->splitScale[1] = ztempMax; } deltaNum = tempNode->splitScale[1] - tempNode->splitScale[0]; //首先判断是否符合叶子节点 if (tempNode->numOfData < numOfLeafData || deltaNum < scaleOfLeafNode) { tempNode->dim = -1; //可用判断是否是叶子节点 octreeNodePtrQue.pop(); if (octreeNodePtrQue.size() == 0) { break; } tempNode = octreeNodePtrQue.front(); continue; } //构造8个节点子树 for (size_t i= 0; i < 8; i++) { ocTreeNode* tempOcTreenode = new ocTreeNode; tempNode->ocTreeNodePtrVect.push_back(tempOcTreenode); } std::vector<size_t> *dataIndexTemp = new std::vector<size_t>[8]; //数据分割到8子节点上 for (size_t i = 0; i < tempNode->numOfData; i++) { if (slipnum == 1) { tempNode->dim = 1; if (pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + (deltaNum / 8))) { dataIndexTemp[0].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 2 * (deltaNum / 8))) { dataIndexTemp[1].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + 2 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 3 * (deltaNum / 8))) { dataIndexTemp[2].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + 3 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 4 * (deltaNum / 8))) { dataIndexTemp[3].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + 4 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 5 * (deltaNum / 8))) { dataIndexTemp[4].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + 5 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 6 * (deltaNum / 8))) { dataIndexTemp[5].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].x >= (tempNode->splitScale[0] + 6 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].x < (tempNode->splitScale[0] + 7 * (deltaNum / 8))) { dataIndexTemp[6].push_back((tempNode->data)[i]); } else { dataIndexTemp[7].push_back((tempNode->data)[i]); } } else if (slipnum == 2) { tempNode->dim = 2; if (pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + (deltaNum / 8))) { dataIndexTemp[0].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 2 * (deltaNum / 8))) { dataIndexTemp[1].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + 2 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 3 * (deltaNum / 8))) { dataIndexTemp[2].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + 3 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 4 * (deltaNum / 8))) { dataIndexTemp[3].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + 4 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 5 * (deltaNum / 8))) { dataIndexTemp[4].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + 5 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 6 * (deltaNum / 8))) { dataIndexTemp[5].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].y >= (tempNode->splitScale[0] + 6 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].y < (tempNode->splitScale[0] + 7 * (deltaNum / 8))) { dataIndexTemp[6].push_back((tempNode->data)[i]); } else { dataIndexTemp[7].push_back((tempNode->data)[i]); } } else { tempNode->dim = 3; if (pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + (deltaNum / 8))) { dataIndexTemp[0].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 2 * (deltaNum / 8))) { dataIndexTemp[1].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + 2 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 3 * (deltaNum / 8))) { dataIndexTemp[2].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + 3 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 4 * (deltaNum / 8))) { dataIndexTemp[3].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + 4 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 5 * (deltaNum / 8))) { dataIndexTemp[4].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + 5 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 6 * (deltaNum / 8))) { dataIndexTemp[5].push_back((tempNode->data)[i]); } else if (pointCloud[(tempNode->data)[i]].z >= (tempNode->splitScale[0] + 6 * (deltaNum / 8)) && pointCloud[(tempNode->data)[i]].z < (tempNode->splitScale[0] + 7 * (deltaNum / 8))) { dataIndexTemp[6].push_back((tempNode->data)[i]); } else { dataIndexTemp[7].push_back((tempNode->data)[i]); } } } //更新子树 for (size_t i = 0; i < 8; i++) { tempNode->ocTreeNodePtrVect[i]->data = new size_t[dataIndexTemp[i].size()]; for (size_t t = 0; t < dataIndexTemp[i].size(); t++) { tempNode->ocTreeNodePtrVect[i]->data[t] = dataIndexTemp[i][t]; } tempNode->ocTreeNodePtrVect[i]->numOfData = dataIndexTemp[i].size(); tempNode->ocTreeNodePtrVect[i]->nodePos = i; tempNode->ocTreeNodePtrVect[i]->father = tempNode; octreeNodePtrQue.push(tempNode->ocTreeNodePtrVect[i]); } octreeNodePtrQue.pop(); if (octreeNodePtrQue.size() == 0) { break; } tempNode = octreeNodePtrQue.front(); //更新节点 } return 0; }