美文网首页
第12节 实例-挖方填方量的计算

第12节 实例-挖方填方量的计算

作者: 杨石兴 | 来源:发表于2021-06-17 23:38 被阅读0次

感谢

感谢网友热心提出这个问题,大家有问题也可以在评论区提出。

资源下载

本文集包括本节所有资源包括模型代码都在此下载,按节的序号有文件或文件夹:

注意:务必使用浏览器打开:
链接:https://pan.baidu.com/s/13gwJLwo_LbRnN3Bl2NXXXw
提取码:xrf5

功能

1.我们先画一个盒子,长宽高是10,8,7,再随便旋转个30度,盒子的体积是560。这样我们就好看看我们自己的方式算的准不准。
2.点击w键,会采样变密,点击s键会采样变粗,命令行中打印出采样的间隔以及算出的体积和盒子本身的体积560的对比来看看误差。

image.png

具体实现

思想:我寻思填方是把一个坑填平喽,挖方是再把填的挖出来,因此应该是一个算法。我们找到要填的几何体,这里是一个盒子然后算出包围球,这样就求出来全覆盖这个包围球的xyz,然后以xy为平面,固定间隔连一条直线,然后与盒子求交,求出来的交点以采样间隔为长宽,以交点间的距离为高,然后算出来体积,这么多体积相加,就是总体积。有点微积分的味道。

实现:具体实现也没有什么好说的,直线和物体求交也就是个函数的API,没有什么好讲的。看代码吧。

结果:有一点是肯定的,当采样越密的时候,精度就越高,这个是可以显见收敛的。有些人可能说我采样往粗了变,怎么有时候误差大有时候误差小呢?这就是采样过粗是不行的。因此以采样点密为要。如果要非常精确,不考虑实时性,可以增加采样点,肯定会越来越精确。

扩展思考:如果有些几何体特别复杂,比如你溶洞似的,那么怎么办呢?这就牵扯到一条线可能有多个交点的问题,一般情况下交点必为偶数个则才成为一个封闭的体,则两两认为是在一个空间,是要求的。自己想象一下。

具体代码如下:

#include <osgViewer/viewer>
#include <osgDB/ReadFile>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osgUtil/IntersectionVisitor>

//定义全局变量用着方便
osg::Group* _root = nullptr;
osg::Node* _box = nullptr;
osg::Group* _shiyi = nullptr;

osg::Geode* CreateBox(osg::Vec3 from, osg::Vec3 to, float stepSize)
{
    osg::Geode* gnode = new osg::Geode;
    gnode->addDrawable(new osg::ShapeDrawable(new osg::Box((from+to)/2, stepSize, stepSize, std::abs(to.z()-from.z()))));
    return gnode;
}

//画一个盒子
osg::Node* CreateScene()
{
    osg::Group* root = new osg::Group;
    _root = root;

    osg::MatrixTransform* mt = new osg::MatrixTransform;
    _box = mt;
    root->addChild(mt);
    mt->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0), osg::Vec3(1.0, 1.0, 1.0)));

    osg::Geode* gnode = new osg::Geode;
    osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 10, 8, 7));
    gnode->addDrawable(sd);

    mt->addChild(gnode);

    return root;
}

class MyEventHandler : public osgGA::GUIEventHandler
{
public:
    MyEventHandler()
    {
        _jiange = 0.5;
    }

    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
        if (ea.getEventType() == ea.KEYDOWN)
        {
            bool _push = false;
            if ((ea.getKey() == 'w') || (ea.getKey() == 'W'))
            {
                _push = true;
                _jiange /= 1.5;
            }
            
            if ((ea.getKey() == 's') || (ea.getKey() == 'S'))
            {
                _push = true;
                _jiange *= 1.5;
            }

            if (_push)
            {
                //清空上一次采样结果
                if (_shiyi != nullptr)
                {
                    _root->removeChild(_shiyi);
                    _shiyi = nullptr;
                }

                _shiyi = new osg::Group();
                _root->addChild(_shiyi);

                std::cout << "采样间隔:"<<_jiange << std::endl;
                //求要求的场景的boudingbox
                osg::BoundingSphere bs = _box->getBound();
                //求出xyz的最小值和最大值,然后根据间隔来求
                osg::Vec3 center = bs.center();
                float r = bs.radius();
                float areas = 0.0;
                for (float fromx = center.x() - r; fromx <= center.x() + r; fromx += _jiange)
                {
                    for (float fromy = center.y() - r; fromy <= center.y() + r; fromy += _jiange)
                    {
                        osg::Vec3 from = osg::Vec3(fromx, fromy, center.z() - r);
                        osg::Vec3 to = osg::Vec3(fromx, fromy, center.z() + r);
                        osgUtil::LineSegmentIntersector::Intersections intersections;
                        osg::ref_ptr<osgUtil::LineSegmentIntersector> ls = new osgUtil::LineSegmentIntersector(from, to);
                        osg::ref_ptr<osgUtil::IntersectionVisitor> iv = new osgUtil::IntersectionVisitor(ls);
                        _box->accept(*iv.get());

                        if (ls->containsIntersections())
                        {
                            intersections = ls->getIntersections();
                            //判断当前交点数
                            if (intersections.size() == 2)
                            {
                                osgUtil::LineSegmentIntersector::Intersections::iterator iter = intersections.begin();
                                osg::Vec3 firstInter = iter->getWorldIntersectPoint();
                                iter++;
                                osg::Vec3 secondInter = iter->getWorldIntersectPoint();
                                _shiyi->addChild(CreateBox(firstInter, secondInter, _jiange));
                                areas += (_jiange*_jiange*std::abs(firstInter.z() - secondInter.z()));
                            }
                        }
                    }
                }

                std::cout << "实际面积:560 计算面积:" << areas << std::endl;
            }
        }

        return false;
    }

    float _jiange;
};


int main()
{
    osgViewer::Viewer viewer;
    viewer.addEventHandler(new MyEventHandler());
    viewer.setSceneData(CreateScene());
    return viewer.run();
}

相关文章

  • 第12节 实例-挖方填方量的计算

    感谢 感谢网友热心提出这个问题,大家有问题也可以在评论区提出。 资源下载 本文集包括本节所有资源包括模型代码都在此...

  • 三维分析之填挖方分析

    (一)功能介绍 填挖方分析:填挖方分析用于计算绘制的填挖三维面与模型图层或地形图层之间的填挖量。常用于工程中计算挖...

  • 基于GIS的填挖方平衡分析

    一、问题描述 计算填挖方量与平衡填挖方是竖向规划的一项重要内容。尤其在山地市,需要充分利用自然地形,合理确定规划用...

  • 清明假期的感想

    现在是凌晨1点。我刚刚算土方量,算了一遍。我不敢说自己算完了,因为最后几百的填方量和室友几十的填方量差距实...

  • 第17节 实例-倾斜摄影数据挖填方

    致谢 感谢网友提出这个问题。大家有问题也可以在评论区提出,有问必有答。 问题描述 在第12节(这是第17节,往前翻...

  • 【算法笔记】算法的平均时间复杂度A(n)的公式及示例

    算法平均时间复杂度计算公式 其中: 是规模为的实例集 实例的概率为 实例的基本运算次数(也就是工作量)为 举例:检...

  • 00005. 在朴素Bayes模型中,为什么需要Laplace平

    统计学上,在计算实例的概率时,如果某个量x,在观察样本库(训练集)中没有出现过,会导致整个实例的概率结果是0。然而...

  • 填方格

    电影巜根西岛文学与土豆皮馅饼俱乐部》,一部描写“真诚”的浪漫电影,我喜欢。 周末时间,我会连着看几部电影,主要选择...

  • 表面分析(填挖方分析)

    今天做的是填挖方分析, 看帮助主要用于两表面体积之间的变化。实际用到的情况可能包括矿山开采的体积计算、土壤修复量计...

  • 实例分析填方区的基础选型如何进行

    某市郊区拟建一住宅小区,其中包括多栋多层和多栋小高层住宅,均为钢筋混凝土框架结构。预计多层住宅的最大柱底力为250...

网友评论

      本文标题:第12节 实例-挖方填方量的计算

      本文链接:https://www.haomeiwen.com/subject/uvvhyltx.html