Hypermesh二次开发系列003

1 *createmark 应用案例

1.1 需求描述

  一个面被划分过网格了,需要在某一个指定位置,扩个孔出来,但现在面的几何信息已经被删除了。如图1所示
Hypermesh二次开发系列003_第1张图片Hypermesh二次开发系列003_第2张图片

图1 功能描述

1.2 问题分析

  这类问题暂且线定义为网格编辑。没有几何信息,只能直接操作和编辑单元与节点。使用界面操作的思路:

  1. 在指定位置创建临时节点:Geom>>nodes
  2. 据此为圆心做圆(创建几何元素:线):Geom>>lines
  3. 删除完全在圆内的单元,可能会留下锯齿状单元。
  4. 使用project功能把上一步生成的锯齿状单元的节点投影到圆周上:Tool>>Project>>to line

  上述是操作步骤,过程效果如图2。
Hypermesh二次开发系列003_第3张图片

图2 过程效果示意图
  是的,此过程GUI操作过程繁琐,而且容易出错。最好的办法就是不要遇到这样的需求,如果不可以的话,退而求次按照上述步骤细心操作,实在没办法就学习下hypermesh的二次开发吧,至少能做出如图3的效果,只要源码跑起来,指哪里就可以扩哪里,想扩多大就扩多大。

Hypermesh二次开发系列003_第4张图片

图3 TCL批量操作效果图

1.3代码剖析

  指定圆心位置和半径的功能块。

*clearmark elem 1
*clearmark node 1
#x0 y0 z0 为圆心坐标,rad为孔半径
set y0 0.0
set z0 0.0
set rad 20.0
set h 50
set elemSize 0
set r1 [expr $rad+$elemSize]
*nodemodify 1 0 0 0 

  选出半径范围内的所有节点,然后同节点选出单元,并获取单元编号。

*createmark node 1 "by cylinder" $x0 $y0 $z0 0 0 1 [expr $rad+$elemSize] $h "inside" 1 1 0
*isolateentitybymark 1
*findmark nodes 1 257 1 elements 0 1
set elemList [hm_getvalue elems mark=1 dataname=id]

  然后是一顿猛如虎的操作:删除单元,投影节点。代码如下:

foreach elemId $elemList {
    set count 0
    set ndId [hm_getvalue elems id=$elemId dataname=nodes]
    foreach i $ndId {
        foreach { dis x y z } [hm_getdistance nodes 1 $i 0] {}
        if {[expr $dis-$rad] <= 0.000001} {
            incr count 
        } 
    }    
    if {$count ==4} {
        *createmark elements 1 $elemId
        *deletemark elements 1
    } elseif {$count ==3}  {
        foreach i $ndId {
            foreach { dis x y z } [hm_getdistance nodes 1 $i 0] {}
            if {[expr $dis-$rad] >= 0.000001} {
                *nodemodify $i [expr $rad/$dis*($x)+$x0] [expr $rad/$dis*($y)+$y0] [expr $rad/$dis*($z)+$z0] 
            } 
        }
        *createmark elements 1 $elemId
        *deletemark elements 1
    } elseif {$count ==1} {
        foreach i $ndId {
            foreach { dis x y z } [hm_getdistance nodes 1 $i 0] {}
            if {[expr $dis-$rad] <= 0.000001} {
                *nodemodify $i [expr $rad/$dis*($x)+$x0] [expr $rad/$dis*($y)+$y0] [expr $rad/$dis*($z)+$z0] 
            }
        }
    } else {        
        set distList []
        foreach i $ndId {
            foreach { dis x y z } [hm_getdistance nodes 1 $i 0] {}
            set t1 [expr abs($dis-$rad)]
            lappend distList [list $i $t1]
        }
        set distListSorted [lsort -real -index 1 $distList]
        set nd1 [lindex $distListSorted 0 0] 
        set nd2 [lindex $distListSorted 1 0] 
        foreach { dis x y z } [hm_getdistance nodes 1 $nd1 0] {}
        *nodemodify $nd1 [expr $rad/$dis*($x)+$x0] [expr $rad/$dis*($y)+$y0] [expr $rad/$dis*($z)+$z0] 
        foreach { dis x y z } [hm_getdistance nodes 1 $nd2 0] {}
        *nodemodify $nd2 [expr $rad/$dis*($x)+$x0] [expr $rad/$dis*($y)+$y0] [expr $rad/$dis*($z)+$z0]
    }
}

一波操作后效果如图4,然鹅并不是很满意。
Hypermesh二次开发系列003_第5张图片

图4 一波操作后图
再简单粗暴的继续上一轮操作,效果如图3所示,其中精髓只有自己亲自码一遍才会拍着大腿想明白。

1.4结论

  两波操作组合起来看似完美,但是不能满足工程需要。原因有三:

  1. 这里仅仅是“挖”了个孔,但是没有扩一层单元孔出来。(干过白车身的都知道
  2. 有pillow单元的存在,单元质量不符合要求。
  3. 以上代码没进行异常处理、用户交互输入等,且代码有冗余其实是没认真写)。

  关于第二点pillow单元处理,有专门的处理和优化算法和数据结构,二维、三维情况都适应。
以上代码仅用来交流和学习,不能代表博主撸码实力。

你可能感兴趣的:(HyperMesh二次开发)