baidu_27304211 2023-04-13 14:39 采纳率: 26.7%
浏览 170
已结题

解决加载大规模倾斜摄影OSGB数据时卡滞、卡死等问题

欧特克_Glodon 这是我代码编写的思路:

  1. 将实景三维OSGB数据按照四叉树结构进行划分,每个叶子节点包含1个最高精度的osgb数据,四叉树层数为n层,对应n种不同精度的模型,因此共有4的n次方个叶子节点。(本代码例子中n为3)
  2. 对于相邻的4个叶子节点,生成一个父节点并简化模型,得到一个低精度的osgb数据,并将其作为父节点的数据。
  3. 递归重复步骤2,直到根节点被生成。
  4. 在osg中加载并渲染四叉树结构中的节点数据,通过LOD技术,根据数据的center、radius,利用PIXEL_SIZE_ON_SCREEN,动态选择不同精度的模型以提高渲染性能,对暂时不用的节点数据进行卸载。(为了解决加载大规模倾斜摄影OSGB时卡滞、卡死等问题)

目前前三步均已完成,第四步写出来后没有实现LOD的效果,求解答,求真正懂OSG的前来解答,不要拿GPT来糊弄事,谢谢
附数据链接
链接:https://pan.baidu.com/s/1SwF-XSiDuVHZhnp1sVl_XA?pwd=eye2
提取码:eye2

@欧特克_Glodon @shangjianchao @雾的RNA 诚邀几位大 牛前来答疑解惑

#include<iostream>
#include<dirent.h>
#include<string.h>
#include<vector>
#include<filesystem>

#include "gdal_alg.h"
#include <ogr_spatialref.h>
#include <gdalwarper.h>
#include "gdal.h"
#include "cpl_conv.h"
#include "gdal_priv.h"
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osg/PolygonMode>
#include<osg/MatrixTransform>
#include<osg/ComputeBoundsVisitor>
#include<osg/shapeDrawable>
#include<osg/Texture2D>
#include<osg/TexGen>
#include<osg/TexEnv>
#include <osgUtil/DelaunayTriangulator>
#include<osgViewer/Viewer>
#include<osg/LineWidth>
#include<osg/CullFace>
#include <regex>
#include <algorithm>
#include <osgDB/WriteFile>
#include <osgUtil/Simplifier>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osg/ProxyNode>

using namespace std;
using namespace osg;
using namespace osgDB;

//extern int maxLevel;
//using namespace std::filesystem;

// 定义一个结构体,表示一个矩形区域
struct Rect {
    int x; // 左下角的x坐标
    int y; // 左下角的y坐标
    int w; // 宽度
    int h; // 高度

    // 构造函数
    Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}

    // 判断两个矩形是否相交
    bool intersect(const Rect& other) const {
        return (x < other.x + other.w) && (x + w > other.x) && (y < other.y + other.h) && (y + h > other.y);
    }

    // 判断一个矩形是否包含另一个矩形
    bool contain(const Rect& other) const {
        return (x <= other.x) && (x + w >= other.x + other.w) && (y <= other.y) && (y + h >= other.y + other.h);
    }
};

// 定义一个类,表示一个四叉树节点
class QuadTreeNode {
public:
    // 构造函数,传入节点对应的矩形区域和层数
    QuadTreeNode(const Rect& rect, int level) : rect(rect), level(level), osgb(nullptr), children{ nullptr, nullptr, nullptr, nullptr } {}

    // 析构函数,释放子节点和osgb数据
    ~QuadTreeNode() {
        for (int i = 0; i < 4; i++) {
            delete children[i];
        }
        //delete osgb;
    }

    // 判断节点是否是叶子节点
    bool isLeaf() const {
        return children[0] == nullptr;
    }

    // 判断节点是否包含某个矩形区域
    bool contain(const Rect& other) const {
        return rect.contain(other);
    }

    // 判断节点是否与某个矩形区域相交
    bool intersect(const Rect& other) const {
        return rect.intersect(other);
    }

    // 插入一个osgb数据到节点中,如果节点是叶子节点,则直接插入;否则,递归地插入到合适的子节点中
    void insert(osg::Node* osgb, const Rect& range) {
        if (isLeaf()) {
            this->osgb = osgb;
        }
        else {
            for (int i = 0; i < 4; i++) {
                if (children[i]->contain(range)) {
                    children[i]->insert(osgb, range);
                    break;
                }
            }
        }
    }

    // 移除节点中的osgb数据,如果节点是叶子节点,则直接移除;否则,递归地移除合适的子节点中的数据
    void remove(const Rect& range) {
        if (isLeaf()) {
            //delete osgb;
            osgb = nullptr;
        }
        else {
            for (int i = 0; i < 4; i++) {
                if (children[i]->contain(range)) {
                    children[i]->remove(range);
                    break;
                }
            }
        }
    }
    // 查询与某个矩形区域相交的节点中的osgb数据,并执行一个回调函数
    void query(const Rect& range, const std::function<void(osg::Node*)>& callback) {
        if (intersect(range)) {
            if (osgb != nullptr) {
                callback(osgb);
            }
            if (!isLeaf()) {
                for (int i = 0; i < 4; i++) {
                    children[i]->query(range, callback);
                }
            }
        }
    }

    // 生成子节点,将当前节点划分为四个等分的矩形区域,并创建对应的子节点
    void generateChildren() {
        if (isLeaf()) {
            int x = rect.x;
            int y = rect.y;
            int w = rect.w / 2;
            int h = rect.h / 2;
            //int w = rect.w;
            //int h = rect.h;
            int nextLevel = level + 1;
            children[0] = new QuadTreeNode(Rect(x, y, w, h), nextLevel); // 左下
            children[1] = new QuadTreeNode(Rect(x + w, y, w, h), nextLevel); // 右下
            children[2] = new QuadTreeNode(Rect(x, y + h, w, h), nextLevel); // 左上
            children[3] = new QuadTreeNode(Rect(x + w, y + h, w, h), nextLevel); // 右上
        }
    }

    // 获取节点对应的矩形区域
    const Rect& getRect() const {
        return rect;
    }

    // 获取节点对应的osgb数据
    osg::Node* getOsgb() const {
        return osgb;
    }

    // 获取节点对应的层数
    int getLevel() const {
        return level;
    }

public:
    Rect rect; // 节点对应的矩形区域
    int level; // 节点对应的层数
    osg::Node* osgb; // 节点存储的osgb数据
    QuadTreeNode* children[4]; // 节点的四个子节点,按照左下,右下,左上,右上的顺序排列
};

// 定义一个类,表示一个四叉树
class QuadTree {
public:
    // 构造函数,传入根节点对应的矩形区域和最大层数
    QuadTree(const Rect& rect, int maxLevel) : maxLevel(maxLevel) {
        root = new QuadTreeNode(rect, 0); // 创建根节点
        generate(root); // 递归地生成子节点,直到达到最大层数
    }

    // 析构函数,释放根节点
    ~QuadTree() {
        delete root;
    }

    // 插入一个osgb数据到四叉树中,传入osgb数据和对应的矩形区域
    void insert(osg::Node* osgb, const Rect& range) {
        root->insert(osgb, range); // 调用根节点的插入方法
    }

    // 移除一个osgb数据从四叉树中,传入对应的矩形区域
    void remove(const Rect& range) {
        root->remove(range); // 调用根节点的移除方法
    }

    // 查询与某个矩形区域相交的osgb数据,并执行一个回调函数
    void query(const Rect& range, const std::function<void(osg::Node*)>& callback) {
        root->query(range, callback); // 调用根节点的查询方法
    }

private:
    // 递归地生成子节点,直到达到最大层数
    void generate(QuadTreeNode* node) {
        if (node->getLevel() < maxLevel) {
            node->generateChildren(); // 生成子节点
            for (int i = 0; i < 4; i++) {
                generate(node->children[i]); // 递归地生成孙节点
            }
        }
    }

public:
    QuadTreeNode* root; // 根节点
    int maxLevel; // 最大层数
};

// 定义一个函数,用来合并相邻的四个子节点osgb数据,并生成一个父节点osgb数据
osg::Node* merge(osg::Node* LT, osg::Node* RT, osg::Node* LB, osg::Node* RB) {
    // 创建一个空的父节点
    osg::ref_ptr<osg::Group> parent = new osg::Group();

    //经测试,在addChild后,子节点的成员貌似会被释放掉,因此复制出来新的
    osg::ref_ptr<osg::Node> LT_new = (osg::Node*)(LT->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> RT_new = (osg::Node*)(RT->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> LB_new = (osg::Node*)(LB->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> RB_new = (osg::Node*)(RB->clone(osg::CopyOp::DEEP_COPY_ALL));

    // 将四个子节点添加到父节点中
    parent->addChild(LT_new);
    parent->addChild(RT_new);
    parent->addChild(LB_new);
    parent->addChild(RB_new);
    // 对父节点进行简化,去除冗余的顶点和面片,减少数据量
    //osgUtil::Simplifier simplifier(0.7); // 0.5是简化的比例,可以根据需要调整
    //parent->accept(simplifier);
    float sampleRatio = 0.2f;
    ////float maxError = 4.0f;
    osgUtil::Simplifier simplifier(sampleRatio);

    //深拷贝
    osg::ref_ptr<osg::Group> parent_new = (osg::Group*)(parent->clone(osg::CopyOp::DEEP_COPY_ALL));

    parent_new->accept(simplifier);
    // 返回父节点
    //return parent.release();
    //return parent_new.release();
    return parent_new.release();
}

osg::Node* merge_Nosimplify(osg::Node* LT, osg::Node* RT, osg::Node* LB, osg::Node* RB) {
    // 创建一个空的父节点
    osg::ref_ptr<osg::Group> parent = new osg::Group();

    //经测试,在addChild后,子节点的成员貌似会被释放掉,因此复制出来新的
    osg::ref_ptr<osg::Node> LT_new = (osg::Node*)(LT->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> RT_new = (osg::Node*)(RT->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> LB_new = (osg::Node*)(LB->clone(osg::CopyOp::DEEP_COPY_ALL));
    osg::ref_ptr<osg::Node> RB_new = (osg::Node*)(RB->clone(osg::CopyOp::DEEP_COPY_ALL));

    // 将四个子节点添加到父节点中
    parent->addChild(LT_new);
    parent->addChild(RT_new);
    parent->addChild(LB_new);
    parent->addChild(RB_new);

    //深拷贝
    osg::ref_ptr<osg::Group> parent_new = (osg::Group*)(parent->clone(osg::CopyOp::DEEP_COPY_ALL));

    return parent_new.release();
}

// 定义一个函数,用来递归地生成四叉树中每一层的osgb数据
#if 1
void generateOsgb(QuadTreeNode* node, const std::string& dataDir, int maxLevel)
{
    float lodRatio = 0.3;

    osg::ref_ptr<osg::Node> node_Nosimplify = new osg::Node;
    //osg::ref_ptr<osg::Group> group = new osg::Group();
    if (!node->isLeaf()) 
    {
        // 递归地生成子节点的osgb数据
        for (int i = 0; i < 4; i++) 
        {
            generateOsgb(node->children[i], dataDir, maxLevel);
        }
        // 合并子节点的osgb数据,生成当前节点的osgb数据
        node->osgb = merge(node->children[0]->osgb, node->children[1]->osgb, node->children[2]->osgb, node->children[3]->osgb);
        node_Nosimplify = merge_Nosimplify(node->children[0]->osgb, node->children[1]->osgb, node->children[2]->osgb, node->children[3]->osgb);

        // 将当前节点的osgb数据写入到文件中,文件名为节点对应的矩形区域的坐标和尺寸
        int CurLevel = node->getLevel();

        stringstream ssCL;
        ssCL << (CurLevel);

        /*std::string fileName = dataDir + "/L" + ssCL.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + "_" + std::to_string(node->getRect().w) + "_" + std::to_string(node->getRect().h) + ".osgb";*/
        std::string relativeFilePath = "L" + ssCL.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";  //相对路径
        std::string fileName = dataDir + "/" + relativeFilePath;

        osgDB::writeNodeFile(*node_Nosimplify, fileName);

        osg::ref_ptr<osg::PagedLOD> lod = new osg::PagedLOD();

        
        auto bs = node->osgb->getBound();
        auto c = bs.center();    //中心
        auto r = bs.radius();    //半径

        float pixelSize = r * 2.f * lodRatio;

        lod->setCenter(c);
        lod->setRadius(r);
        lod->setRangeMode(osg::PagedLOD::PIXEL_SIZE_ON_SCREEN);    //RangeMode:细节层次调度模式。PIXEL_SIZE_ON_SCREEN:屏幕像素尺寸。DISTANCE_FROM_EYE_POINT:到眼距离。

        lod->setRange(0, 0, pixelSize);            //第一层不可见
        lod->setRange(1, pixelSize, FLT_MAX);

        osg::ref_ptr<osg::Node> node_new = (osg::Node*)(node->osgb->clone(osg::CopyOp::DEEP_COPY_ALL));
        lod->addChild(node_new);

        lod->setFileName(0, "");
        lod->setFileName(1, relativeFilePath);

        osgDB::writeNodeFile(*lod, fileName);

    }
    else 
    {
        stringstream ssmaxLevel;
        ssmaxLevel << (maxLevel);

        // 如果是叶子节点,直接从文件中读取osgb数据,文件名为最高精度的osgb数据的文件名
        std::string relativeFilePath = "L" + ssmaxLevel.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";  //相对路径
        std::string fileName = dataDir + "/" + relativeFilePath;

        // 如果是叶子节点,直接从文件中读取osgb数据,文件名为最高精度的osgb数据的文件名
        //std::string relativeFilePath = "L3_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";  //相对路径
        //std::string relativeFilePath = "L3_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";  //相对路径
        //std::string fileName = dataDir + "/" + relativeFilePath;

        node->osgb = osgDB::readNodeFile(fileName);
 
        osg::ref_ptr<osg::PagedLOD> lod = new osg::PagedLOD();

        auto bs = node->osgb->getBound();
        auto c = bs.center();    //中心
        auto r = bs.radius();    //半径

        float pixelSize = r * 2.f * lodRatio;

        lod->setCenter(c);
        lod->setRadius(r);
        lod->setRangeMode(osg::PagedLOD::PIXEL_SIZE_ON_SCREEN);    //RangeMode:细节层次调度模式。PIXEL_SIZE_ON_SCREEN:屏幕像素尺寸。DISTANCE_FROM_EYE_POINT:到眼距离。

        lod->setRange(0, 0, pixelSize);            //第一层不可见
        lod->setRange(1, pixelSize, FLT_MAX);

        osg::ref_ptr<osg::Node> node_new = (osg::Node*)(node->osgb->clone(osg::CopyOp::DEEP_COPY_ALL));
        lod->addChild(node_new);

        lod->setFileName(0, "");
        lod->setFileName(1, relativeFilePath);

    }
}
#endif

// 定义一个函数,用来递归地生成四叉树中每一层的osgb数据
#if 0
void generateOsgb(QuadTreeNode* node, const std::string& dataDir, int maxLevel)
{

    if (!node->isLeaf())
    {
        // 递归地生成子节点的osgb数据
        for (int i = 0; i < 4; i++)
        {
            generateOsgb(node->children[i], dataDir, maxLevel);
        }
        // 合并子节点的osgb数据,生成当前节点的osgb数据
        node->osgb = merge(node->children[0]->osgb, node->children[1]->osgb, node->children[2]->osgb, node->children[3]->osgb);
        // 将当前节点的osgb数据写入到文件中,文件名为节点对应的矩形区域的坐标和尺寸
        int CurLevel = node->getLevel();

        stringstream ssCL;
        ssCL << (CurLevel);

        /*std::string fileName = dataDir + "/L" + ssCL.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + "_" + std::to_string(node->getRect().w) + "_" + std::to_string(node->getRect().h) + ".osgb";*/
        std::string fileName = dataDir + "/L" + ssCL.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";
        osgDB::writeNodeFile(*node->osgb, fileName);
    }
    else 
    {
        stringstream ssmaxLevel;
        ssmaxLevel << (maxLevel);

        // 如果是叶子节点,直接从文件中读取osgb数据,文件名为最高精度的osgb数据的文件名
        std::string fileName = dataDir + "/L" + ssmaxLevel.str() + "_X" + std::to_string(node->getRect().x) + "_Y" + std::to_string(node->getRect().y) + ".osgb";
        node->osgb = osgDB::readNodeFile(fileName);
    }
}
#endif

//void render(QuadTreeNode* treeNode, osg::Group* scene)
//{
//    //如果节点是叶子节点,就添加PagedLOD节点
//    if (treeNode->isLeaf())
//    {
//        //创建一个PagedLOD节点,用来实现LOD技术和数据分页加载
//        osg::ref_ptr<osg::PagedLOD> lod = new osg::PagedLOD();
//        //设置PagedLOD节点的中心和半径,根据当前节点的矩形区域计算
//
//        auto bs = treeNode->osgb->getBound();
//        auto c = bs.center();    //中心
//        auto r = bs.radius();    //半径
//
//        lod->setCenter(c);
//        lod->setRadius(r);
//        //设置PagedLOD节点的范围模式为PIXEL_SIZE_ON_SCREEN,根据数据在屏幕上的像素大小动态选择不同精度的模型
//        lod->setRangeMode(osg::PagedLOD::PIXEL_SIZE_ON_SCREEN);
//        //创建一个空的Geode节点,用来占位
//        osg::ref_ptr<osg::Geode> geode = new osg::Geode();
//        //将Geode节点和osgb数据添加到PagedLOD节点中,并设置范围
//        lod->addChild(geode.get());
//        lod->addChild(treeNode->osgb);
//        lod->setRange(0, 0, 1.0); // 第一层不可见
//        lod->setRange(1, 1.0, FLT_MAX); // 第二层可见
//        //设置PagedLOD节点的文件名,用来实现数据的卸载和加载,文件名为当前节点对应的osgb数据的文件名
//        std::string fileName = std::to_string(treeNode->getRect().x) + "_" + std::to_string(treeNode->getRect().y) + "_" + std::to_string(treeNode->getRect().w) + "_" + std::to_string(treeNode->getRect().h) + ".osgb";
//        lod->setFileName(0, "");
//        lod->setFileName(1, fileName);
//        //将PagedLOD节点添加到场景图中
//        scene->addChild(lod);
//    }
//    else //如果节点不是叶子节点,就递归遍历其子节点
//    {
//        for (int i = 0; i < 4; i++)
//        {
//            render(treeNode->children[i], scene);
//        }
//    }
//
//}

// 定义一个函数,用来创建一个四叉树对象,并生成osgb数据和渲染场景
void createQuadTree(const std::string& dataDir, int maxLevel) {
    // 获取最高精度的osgb数据的文件列表
    std::vector<std::string> files;
    for (auto& entry : std::filesystem::directory_iterator(dataDir)) {
        if (entry.is_regular_file() && entry.path().extension() == ".osgb") {
            files.push_back(entry.path().string());
        }
    }
    // 计算最高精度的osgb数据的矩形区域的范围,即最小的x,y坐标和最大的宽度,高度
    int minX = FLT_MAX;
    int minY = FLT_MAX;
    int maxX = -FLT_MAX;
    int maxY = -FLT_MAX;
    for (auto& file : files) {
        // 从文件名中解析出x,y坐标
        size_t pos1 = file.find_last_of('X');
        size_t pos2 = file.find_last_of('_');
        size_t pos3 = file.find_last_of('.');
        size_t pos4 = file.find_last_of('Y');
        int x = std::stof(file.substr(pos1 + 1, pos2 - pos1 - 1));
        int y = std::stof(file.substr(pos4 + 1, pos3 - pos4 - 1));
        // 更新范围
        minX = std::min(minX, x);
        minY = std::min(minY, y);
        maxX = std::max(maxX, x);
        maxY = std::max(maxY, y);
    }
    int width = maxX - minX + 1;
    int height = maxY - minY + 1;
    // 创建一个四叉树对象,传入根节点对应的矩形区域和最大层数
    QuadTree* tree = new QuadTree(Rect(minX, minY, width, height), maxLevel);
    QuadTree* tree_new = new QuadTree(Rect(minX, minY, width, height), maxLevel);
    // 遍历最高精度的osgb数据的文件列表,将每个文件对应的osgb数据插入到四叉树中
    for (auto& file : files) {
        // 从文件名中解析出x,y坐标
        size_t pos1 = file.find_last_of('X');
        size_t pos2 = file.find_last_of('_');
        size_t pos3 = file.find_last_of('.');
        size_t pos4 = file.find_last_of('Y');
        int x = std::stof(file.substr(pos1 + 1, pos2 - pos1 - 1));
        int y = std::stof(file.substr(pos4 + 1, pos3 - pos4 - 1));
        // 读取文件中的osgb数据
        osg::Node* osgb = osgDB::readNodeFile(file);
        // 将osgb数据插入到四叉树中,传入osgb数据和对应的矩形区域
        tree->insert(osgb, Rect(x, y, width / pow(4, maxLevel), height / pow(4, maxLevel)));    //width,height应该不起作用
        tree_new->insert(osgb, Rect(x, y, width / pow(4, maxLevel), height / pow(4, maxLevel)));    //width,height应该不起作用
    }
    // 递归地生成四叉树中每一层的osgb数据
    generateOsgb(tree->root, dataDir, maxLevel);
    // 利用OpenSceneGraph加载并渲染四叉树中的所有节点数据
    //render(tree);
    //创建一个空的场景图
    //osg::ref_ptr<osg::Group> scene = new osg::Group();
    ////调用遍历函数
    //render(tree_new->root, scene.get());
    //// 释放四叉树对象
    ////delete tree;

    ////创建一个Viewer对象,用来显示场景图
    //osgViewer::Viewer viewer;
    //viewer.setSceneData(scene);
    //viewer.setUpViewInWindow(50, 50, 800, 600); // 设置窗口位置和大小
    //viewer.run(); // 运行Viewer对象
}

// 定义一个主函数,用来接收命令行参数,并调用createQuadTree函数
int main(int argc, char* argv[]) {

    // 获取数据目录
    std::string dataDir = "F:/test";   
    // 判断数据目录是否存在
    if (!std::filesystem::exists(dataDir)) {
        std::cout << "Data directory does not exist: " << dataDir << std::endl;
        return -1;
    }
    // 获取最大层数
    int maxLevel = 3;   //4块为1,16块为2,类推
    // 判断最大层数是否合法,至少为1
    if (maxLevel < 1) {
        std::cout << "Max level must be at least 1: " << maxLevel << std::endl;
        return -1;
    }
    // 调用createQuadTree函数,传入数据目录和最大层数
    createQuadTree(dataDir, maxLevel);
    // 返回正常退出码
    return 0;
}

  • 写回答

4条回答 默认 最新

  • 美羊羊桑7890 2023-04-13 23:47
    关注

    内容来源与ChatGpt4及newbing和百度:


    你的思路是正确的,将OSGB数据按照四叉树结构进行划分可以有效地解决大规模倾斜摄影数据加载卡顿的问题。除此之外,还可以考虑以下优化策略:

    1. 数据预处理:提前对OSGB数据进行压缩、索引等处理,可以有效减小数据的体积和加载时间。

    2. 数据流式加载:将OSGB数据按需加载,不需要一次性加载全部数据,可以减小内存占用和加载时间。

    3. 并行加载:使用多线程或异步加载的方式,可以加快数据加载速度,提高用户体验。

    4. 数据分片加载:将大规模数据分成多个小块进行加载,可以避免一次性加载过多数据导致卡顿。

    以下是一个简单的代码示例,演示如何使用四叉树结构进行OSGB数据加载:

    // 定义四叉树节点
    struct QuadTreeNode {
        std::vector<OSGBData> data; // 当前节点包含的OSGB数据
        QuadTreeNode* children[4]; // 子节点指针,共4个
    };
    
    // 加载OSGB数据到四叉树
    void LoadOSGBData(QuadTreeNode* node, int level) {
        if (level == maxLevel) { // 达到最大层数,不再划分
            node->data = LoadOSGBDataAtLevel(level);
            return;
        }
        // 将当前节点划分成4个子节点
        for (int i = 0; i < 4; i++) {
            node->children[i] = new QuadTreeNode();
            LoadOSGBData(node->children[i], level+1);
        }
        // 将子节点的OSGB数据合并到当前节点
        for (int i = 0; i < 4; i++) {
            node->data.insert(node->data.end(), node->children[i]->data.begin(), node->children[i]->data.end());
        }
    }
    
    // 搜索包含指定点的叶子节点
    QuadTreeNode* SearchLeafNode(QuadTreeNode* node, const Point& point) {
        if (!node) return nullptr;
        if (node->children[0]) { // 当前节点还有子节点,继续搜索
            int idx = GetChildIndex(node, point);
            return SearchLeafNode(node->children[idx], point);
        } else { // 当前节点是叶子节点,返回
            return node;
        }
    }
    
    // 加载指定区域的OSGB数据
    std::vector<OSGBData> LoadOSGBDataInRegion(const Region& region) {
        QuadTreeNode* root = new QuadTreeNode();
        LoadOSGBData(root, 0);
        std::vector<OSGBData> result;
        for (const auto& point : region.points) {
            QuadTreeNode* leaf = SearchLeafNode(root, point);
            if (leaf) {
                result.insert(result.end(), leaf->data.begin(), leaf->data.end());
            }
        }
        return result;
    }
    

    祝您问题迎刃而解

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月18日
  • 修改了问题 4月14日
  • 修改了问题 4月13日
  • 修改了问题 4月13日
  • 展开全部

悬赏问题

  • ¥15 Arcgis河网分级报错
  • ¥200 java+appium2.1+idea
  • ¥20 请帮我做一个EXE的去重TXT文本
  • ¥15 工价表引用工艺路线,应如何制作py和xml文件
  • ¥15 根据历史数据,推荐问题类型
  • ¥15 需要仿真图,简单的二阶系统实例
  • ¥15 stm32光控照明仿真
  • ¥15 使用人工智能的方法生成满足一定统计参数要求的随机数序列
  • ¥15 SENT协议中相关问题咨询
  • ¥15 URL地址href跳转问题