首页/文章/ 详情

【PFC6.0】随机多边形区域划分及颗粒填充

1年前浏览3450

0 引言

    在做岩石的时候,粗糙一点就认为岩石是一个均匀的整体,对整体参数进行标定,达到一个单元层次的宏观特性对应。精细点做的话就需要考虑矿物,这样我们会认为矿物内部是一个均匀的整体,这样的话就需要对岩石内部的区域进行划分,规定每种矿物成分的区域,然后用颗粒进行填充模拟。

    本文主要目的是将区域进行随机多边形划分,并且往其中填充颗粒。使用到的技术主要是rblock中的merge命令。

1 区域划分

    我们主要使用rblock的建模特性作为过渡,得到随机的多边形区域。

    model new

    model domain extent -10 10geometry set "box"geometry generate box -5 5

    def par    origin_rad_min=0.2    origin_rad_max=origin_rad_min*1.5    scale=3    block_radius_max=origin_rad_max*scale    block_radius_min=origin_rad_min*scaleend@parrblock construct from-geometry "box"  minimum-edge  @origin_rad_min ...        maximum-edge @origin_rad_max group "origin" slot "1"


        第一步是利用rblock construct命令可以对区域进行三角划分,如果可以直接对区域进行多边形划分肯定是更好的。但就我目前对rblock的理解来说,还做不到这种程度,目前只能做到对区域进行三角划分,这里可以指定三角形的边长范围。

        我们生成了一堆三角形的rblock,如下图:

    image.png


        第二步就是用所得到的三角形进行随机的合并,这里我们用的是长方形区域进行合并。


      def inbox(pos,pointer)    groupName=rblock.group(pointer)    if groupName#"1=origin" then        inbox=false        exit    endif    vl=vector(x_pos_random-sousuo_rad_x,y_pos_random-sousuo_rad_y)    vh=vector(x_pos_random sousuo_rad_x,y_pos_random sousuo_rad_y)    rbpos=rblock.pos(pointer)    if comp.x(rbpos)>comp.x(vl) & comp.x(rbpos)<comp.x(vh) &comp.y(rbpos)>comp.y(vl) & comp.y(rbpos)<comp.y(vh) then                inbox=true        exit    endif    inbox=falseend
      def conbine_rblock    stop_flag=true    name_count=1    loop while stop_flag        x_pos_random=math.random.uniform*10-5        y_pos_random=math.random.uniform*10-5        sousuo_rad_x=math.random.uniform*(block_radius_max-block_radius_min) block_radius_min        sousuo_rad_y=math.random.uniform*(block_radius_max-block_radius_min) block_radius_min        ishaveRb=false        loop foreach rb rblock.list            vl=vector(x_pos_random-sousuo_rad_x,y_pos_random-sousuo_rad_y)            vh=vector(x_pos_random sousuo_rad_x,y_pos_random sousuo_rad_y)            if inbox(vl,rb) then                ishaveRb=true                exit loop            endif        endloop        group_name=string.build("zu_%1",name_count)        name_count =1        if ishaveRb=true then                    command                                rblock merge group "new" slot "1" group @group_name slot "10"  ...                        range fish @inbox                model clean            endcommand        endif        orgin_count=0        loop foreach rb rblock.groupmap("origin",1)            orgin_count =1        endloop        if orgin_count==0 then            stop_flag=false        endif    endloopend@conbine_rblock



          我们每次随机获得一个长宽的长方形,将长方形中的“origin”组的rblock合并成一个新的rblock。

          这里有个逻辑需要注意是,merge的概念不一定需要rblock紧贴在一起,就算rblock分开一段距离,他们之间的范围也会合并到新的rblock中,所以合并得到的rblock实际上是有重叠的。

          我们看一下新的rblock。


      image.png



          可以发现的是,大部分的rblock都被合并了,但是有少部分rblock是被“剩余合并”的,所谓“剩余合并”的概念就是某个rblock或者某几个会被单独剩余下来,最终形成一个rblock,而这个rblock是不满足长宽要求的。

          所以我们还需要进行第三步,也就是把这些小的rblock合并到它周围的大rblock中。



        def findMinRb    VLimit=origin_rad_min*origin_rad_min*10    loop foreach rb rblock.groupmap("new",1)        if rblock.vol(rb)<VLimit*4 then            rblock.group(rb,1)="minRB"        endif    endloopend@findMinRb

        def findNearestRb(pos)    minPos=1e100    minId=0    loop foreach rbfind rblock.groupmap("new",1)        vecLenghth=rblock.pos(rbfind)-pos        if math.mag(vecLenghth)<minPos then            minPos=math.mag(vecLenghth)            minId=rblock.id(rbfind)        endif    endloop    findNearestRb=minIdend

        def solveMinRb        loop foreach rb  rblock.groupmap("minRB",1)        rbNearest=rblock.find(findNearestRb(rblock.pos(rb)))        rblock.group(rb,20)="dai"        rblock.group(rbNearest,20)="dai"        group_name=string.build("zu_%1",name_count)        name_count =1        command             rblock merge group "new" slot "1" group @group_name ...                slot "10" range group "20=dai"        endcommand        loop foreach rbdai rblock.groupmap("dai",20)            rblock.group(rbdai,20)="none"        endloop    endloopend@solveMinRb


            通过以上的命令,我们可以找到小的颗粒,当然我们也可以调整“小的颗粒”的范围,从而调整模型中区域的精细度。

            运行完的效果如图:

        image.png


        这个就是我们区域的范围。


        2 颗粒填充


            由于没有指定随机数,导致本文出现的图和我既有算例的分布有区别,这里给出我算完的一个sav。如下图:


        image.png


            可以看到区域大小基本一致,只是形状不同,这里也体现随机性的概念。

        image.png

        image.png

          颗粒填充前我们需要把rblock的边界都导出为geometry,方便后面根据区域进行颗粒生成。


            可以看一下区域图:


        image.png


            由于rblock有重叠,导致geometry也是有重叠的,所以颗粒的生成规则我们需要进行优化。

            首先定一个考虑区域重叠的规则。


            区域交集优先被id小的geometry使用。


            也就是说id为3区域需要减去其与id 1和id 2区域的交集,作为对应颗粒的生成范围。


            榆树我们可以得到某个区域的颗粒投放逻辑,如下:

        image.png

        image.png

         第二个逻辑是颗粒的平衡边界,每个区域的颗粒投放后都需要平衡,其边界应当考虑id小于当前geo id的区域,所以需要控制墙体的生成和删除。

        image.png

        image.png

        image.png

          最后便是函数的调用,每次生成新的区域的时候,旧的区域颗粒需要进行固定。


        效果如下:

        image.png

        每次投放都保存了save文件,可以进行查看。

        网格处理科普岩土结构基础PFC
        著作权归作者所有,欢迎分享,未经许可,不得转载
        首次发布时间:2022-09-09
        最近编辑:1年前
        lobby
        硕士 |擅长颗粒流PFC
        获赞 829粉丝 4385文章 85课程 21
        点赞
        收藏
        未登录
        3条评论
        小瓶子
        签名征集中
        5月前
        为啥7.0这套会跑不起来,也没有语法上的差别
        回复
        ghfgb
        签名征集中
        10月前
        不同矿物之间的接触怎么设置
        回复
        工地狗
        签名征集中
        1年前
        第二段代码的错误有点多啊,大佬
        回复 3条回复

        课程
        培训
        服务
        行家

        VIP会员 学习 福利任务 兑换礼品
        下载APP
        联系我们
        帮助与反馈