不规则八叉树的空间分割与检索

  不同规则八叉树,在每一次分割时,需要判断选择一个合适的分割维度(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;
}
原文地址:https://www.cnblogs.com/lovebay/p/11757186.html