构建规则格网进行体积计算


总体步骤:

  1. 生成凸包多边形
  2. 构建规则格网
  3. 计算体积

构建规则格网进行体积计算的第一大步骤----生成凸包多边形
生成凸包多边形又有快速凸包法、Gram Scan法等方法。

在文章[凸包多边形生成算法—快速凸包法]中,我们根据散点集生成凸包点
本文章进行构建规则格网以及计算体积的介绍

1.构建规则格网

根据散点集计算出的四个顶点,确定规则格网的边界。
在这里插入图片描述
这里可以创建两个新的类
点类----gridpoint:表示每一个格网中心点对象
格网类----Grid:表示整个格网对象
在这里插入图片描述
在这里插入图片描述

class gridpoint
    {
    
    
        public float x,y,h;
        public int n;//标记网格点是否在凸包内。1在,0或2不在
    }
    class Grid
    {
    
    
        //格网的xmax,xmin,ymax,ymin从peaks中获取
        public float xmax, xmin, ymax, ymin;
        public float L;//网格边长
        public double r;//搜索半径
        public int in_num;//凸包内网格数
        public List<gridpoint> gridps = new List<gridpoint>();//所有格网点g
   }
   //方法在文章后面给出

1.1生成所有格网点

//获取格网中心点的坐标
        public void GetGridpoint(List<point> peaks)
        {
    
    
            xmax = (float)peaks[2].x;
            xmin = (float)peaks[0].x;
            ymax = (float)peaks[1].y;
            ymin = (float)peaks[3].y;//格网边界
            //搜索半径
            r = (ymax - ymin + xmax - xmin) *0.5 * 0.4;
            int m = (int)((ymax-ymin)/L);//网格数
            int n = (int)((xmax-xmin)/L);
            //格网中线点坐标
            for (int i = 0; i < m; i++)
            {
    
    
                for (int j = 0; j < n; j++)
                {
    
    
                    gridpoint gp = new gridpoint();
                    gp.n = 0;
                    gp.x = xmin + j * L + L / 2;
                    gp.y = ymin + i * L + L / 2;
                    gridps.Add(gp);
                }
            }
        }

此步得到所有格网点中心的坐标(x,y),不包含h,h由散点插值得到

2.计算体积

第一步:计算凸包所包含的所有格网点
第二步:插值计算凸包所包含的格网点的高程
第三步:根据公式计算体积

2.1计算凸包所包含的所有格网点

格网点类中有个属性n,用于标识是否在凸包内。

在这里插入图片描述
判断点是否位于凸包内的方法:
for遍历所有的散点
for遍历凸包的每一条边
if(点的y坐标位于边两个端点的y之间)//只可能与2或0条边水平相交 判断点是否位于线的左侧,若是,该点的n 加1;

n == 0 无交点 点在凸包的右侧
n == 2 两个单侧边交点,点位于凸包的左侧
n == 1 一个但侧边交点,点位于凸包的内部

 //函数---判断点是否在线左边
        public int judge(gridpoint a,point b,point c)
        {
    
    
            double m = (c.x - b.x) / (c.y - b.y) * (a.y - b.y) + b.x;
            if (m > a.x)//点a在线bc左边,单线交点+1
            {
    
    
                return 1;
            }
            else
                return 0;
        }
 //函数---判断点是否在凸包内
        public void Find_in(List<point> convex)
        {
    
    
            for (int i = 0; i < gridps.Count; i++)//遍历每一个网格点
            {
    
    
                for (int j = 0; j < convex.Count-1; j++)//遍历凸包点
                {
    
    
                    if (gridps[i].y<Math.Max(convex[j].y, convex[j+1].y)
                        &&
                        gridps[i].y>=Math.Min(convex[j].y, convex[j + 1].y)
                        )
                    {
    
    
                        gridps[i].n += judge(gridps[i], convex[j], convex[j + 1]);
                    }
                }
            }

        }
 

2.2插值计算凸包内格网点的高程

对凸包内部的格网点进行插值计算。
注意,这里计算的是格网单元四个顶点的高程

首先需要设置一个搜索半径,用于搜索待插值点周围的散点,然后根据反距离权重计算

函数—输入散点集,待插点坐标,返回待插点高程

//函数---插值计算点高程,进而计算网格顶点高程
        public double Get_h(List<point> allps ,float X,float Y)
        {
    
    
            double D=0,h_sum=0,D_sum=0;
            double h;
            for (int i = 0; i < allps.Count; i++)
            {
    
    
                D = Math.Sqrt((allps[i].x-X)*(allps[i].x - X) +(allps[i].y - Y) *(allps[i].y - Y));
                if (D<r)
                {
    
    
                //反距离加权
                    D_sum += allps[i].h / D;
                    h_sum += 1 / D;
                }   
            }
            h = D_sum / h_sum;
            return h;
        }

2.3计算体积

//体积计算
        public double Cal_V(List<point> allps,double h0)
        {
    
    
            double V = 0;
            for (int i = 0; i < gridps.Count; i++)//遍历所有网格点
            {
    
    
                if (gridps[i].n == 1)//凸包内部的点
                {
    
    
                    in_num +=1;
                    //内部点的四个格网顶点高程
                    double h1 = Get_h(allps, gridps[i].x - L / 2, gridps[i].y - L / 2);
                    double h2 = Get_h(allps, gridps[i].x + L / 2, gridps[i].y + L / 2);
                    double h3 = Get_h(allps, gridps[i].x - L / 2, gridps[i].y + L / 2);
                    double h4 = Get_h(allps, gridps[i].x + L / 2, gridps[i].y - L / 2);
                    //计算公式
                    V += ((h1 + h2 + h3 + h4) / 4 - h0) * L * L;
                }
            }
            return V;
        }

猜你喜欢

转载自blog.csdn.net/weixin_51205206/article/details/124517184