1 *createmark 应用案例
1.1 需求描述
一个面被划分过网格了,需要在某一个指定位置,扩个孔出来,但现在面的几何信息已经被删除了。如图1所示
图1 功能描述
1.2 问题分析
这类问题暂且线定义为网格编辑。没有几何信息,只能直接操作和编辑单元与节点。使用界面操作的思路:
- 在指定位置创建临时节点:Geom>>nodes
- 据此为圆心做圆(创建几何元素:线):Geom>>lines
- 删除完全在圆内的单元,可能会留下锯齿状单元。
- 使用project功能把上一步生成的锯齿状单元的节点投影到圆周上:Tool>>Project>>to line
上述是操作步骤,过程效果如图2。
图2 过程效果示意图
是的,此过程GUI操作过程繁琐,而且容易出错。最好的办法就是不要遇到这样的需求,如果不可以的话,退而求次按照上述步骤细心操作,实在没办法就学习下hypermesh的二次开发吧,至少能做出如图3的效果,只要源码跑起来,指哪里就可以扩哪里,想扩多大就扩多大。
图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,然鹅并不是很满意。
图4 一波操作后图
再简单粗暴的继续上一轮操作,效果如图3所示,其中精髓只有自己亲自码一遍才会拍着大腿想明白。
1.4结论
两波操作组合起来看似完美,但是不能满足工程需要。原因有三:
- 这里仅仅是“挖”了个孔,但是没有扩一层单元孔出来。(干过白车身的都知道)
- 有pillow单元的存在,单元质量不符合要求。
- 以上代码没进行异常处理、用户交互输入等,且代码有冗余(其实是没认真写)。
关于第二点pillow单元处理,有专门的处理和优化算法和数据结构,二维、三维情况都适应。
以上代码仅用来交流和学习,不能代表博主撸码实力。