首页/文章/ 详情

ANSA二次开发:获取与视角一致的单元法向量

15小时前浏览3

ANSA二次开发中经常获取当前视角下被选中单元和视角一致的法向量以备后续操作。本文主要通过创建视角向量和被选中单元的法向量来展示这一过程。

首先,需要对中的错误进行更正:ansaGetViewAngles函数旋转顺序为Z->Y->Z;且以顺时针为正,和一般笛卡尔坐标相反。因此有:




























































































































































































































import mathfrom typing import ListTuplefrom ansa import basefrom ansa import constantsfrom ansa import calc
class ANSATYPE(object):  '''  不同求解器对应关键字名字  '''  @class method  def eshell(cls, deck:int)->str:    typDict:dict = {      constants.LSDYNA: 'ELEMENT_SHELL',      constants.ABAQUS:'SHELL',      constants.NASTRAN: 'SHELL',      constants.RADIOSS: 'SHELL',      constants.ANSYS: 'SHELL',      22'SHELL'# OPTISTRUCT      23'SHELL' # MARC      }    try:      _type = typDict[deck]    except KeyError:      raise ValueError('ERROR: 模型Deck设置有误')    return _type  @class method  def node(cls, deck:int)->str:    typDict:dict = {      constants.LSDYNA: 'NODE',      constants.ABAQUS:'NODE',      constants.NASTRAN: 'GRID',      constants.RADIOSS: 'NODE',      constants.ANSYS: 'NODE',      22'GRID'# OPTISTRUCT      23'NODE' # MARC      }    try:      _type = typDict[deck]    except KeyError:      raise ValueError('ERROR: 模型Deck设置有误')    return _type

class Vector(object):  @class method  def point2Point(cls, point1:List[float], point2:List[float], unit:bool=True)->List[float]:    '''    计算两点构成的向量. 向量由point1指向point2,即point2-point1    '''    if isinstance(point1, base.Entity): point1 = point1.position    if isinstance(point2, base.Entity): point2 = point2.position    vect:List[float] = [p2-p1 for p1, p2 in zip(point1, point2)]    return cls.unit(vect) if unit else vect  @staticmethod  def unit(vector:List[float])->List[float]:    '''    将一个向量单位化    '''    return calc.Normalize(vector)  @staticmethod  def distance(point1:List[float], point2:List[float])->float:    '''    计算两点间的距离    '''    if isinstance(point1, base.Entity): point1 = point1.position    if isinstance(point2, base.Entity): point2 = point2.position    return math.dist(point1, point2)  @class method  def angleCos(cls, vector1:List[float], vector2:List[float])->float:    '''    计算两个空间向量的夹角的余弦值。    '''    unit_vect01 = cls.unit(vector1)    unit_vect02 = cls.unit(vector2)    return sum([v1*v2 for v1, v2 in zip(unit_vect01, unit_vect02)])  @staticmethod  def angle(vector1:List[float], vector2:List[float])->float:    '''    计算两个空间向量的夹角,返回值以弧度形式存在    '''    return calc.CalcAngleOfVectors(vector1, vector2)  @class method  def elemNormal(cls, shellElem:base.Entity)->List[float]:    '''    根据单元的前三个节点计算单元的法向量    '''    vect:List[float] = base.GetNormalVectorOfShell(shellElem)    if isinstance(vect, list):      return vect    else:      nodeType:str = ANSATYPE.node(DECK)      nodes:List[base.Entity] = base.CollectEntities(DECK, shellElem, nodeType, recursive=True)      return cls.vec3Point(nodes[0], nodes[1], nodes[2])      @class method  def vec3Point(cls, point1:List[float], point2:List[float], point3:List[float])->List[float]:    '''    计算空间三点构成平面的法向量    '''    vect1:List[float] = cls.point2Point(point1, point2)    vect2:List[float] = cls.point2Point(point1, point3)    return calc.CrossProduct(vect1, vect2)def getViewVector()->List[float]:  '''  通过视角函数获取视角旋转角并将其装换为视角向量  '''  # 获取视角转动角  angles:List[float] = base.GetViewAngles()  angleRad = list(map(math.radians, angles))  angleSin: List[float] = list(map(math.sin, angleRad))  angleCos: List[float] = list(map(math.cos, angleRad))  # 计算视角向量三分量  x:float = -angleSin[1]  y:float = angleSin[0]*angleCos[1]  z:float = angleCos[0]*angleCos[1]  return [x, y, z]
def getShellViewVector(elem:base.Entity)->List[float]:  '''  名称:  getShellViewVector  描述:  获取shell单元与当前视角方向一致的法向向量  参数:  elem object shell类型单元  返回值:  返回一个向量(list),该向量表示输入shell单元与当前视角一致的单元法向量。  '''  # 对输入对象进行参数检查  if not isinstance(elem, base.Entity):    raise TypeError('请输入ansa对象')  shellType = ANSATYPE.eshell(DECK)  elemType = elem.ansa_type(DECK)  if elemType != shellType and elemType != 'SOLIDFACET':    raise TypeError(f'''输入ansaType类型有误, 此函数要求输入的为shell单元或solid单元的表面类型(SOLIDFACET), 现输入类型为{elemType}''')  # 获取单元法向量  elemVect:List[float] = Vector.elemNormal(elem)  # 获取视角向量  viewVect:List[float] = getViewVector()  # 计算两个向量的夹角,若为锐角,单元法向量为所求方向;若为钝角,单元法向量反方向为所求方向  angle:float = Vector.angle(elemVect, viewVect)  if angle==-math.pi:    raise ValueError(f'输入向量有误, 现输入向量为{elemVect}{viewVect}, 请核查')  if angle>math.pi/2.0:    elemVect = [-vect for vect in elemVect]  return elemVect
def calcCog(entities:List[base.Entity])->List[float]:  '''  名称:  calcCog  描述:  计算输入的entities对象的cog  参数:  entities List[base.Entity] 存在cog的可迭代对象或entity对象  返回值:  返回一个Cog向量(list)  '''  if isinstance(entities, base.Entity): entities = [entities]  length = len(entities)  if length==0return[0.00.00.0]  if length==1return base.Cog(entities[0])  x, y, z = 0.00.00.0  for ent in entities:    cog = base.Cog(ent)    x += cog[0]    y += cog[1]    z += cog[2]  return [x/length, y/length, z/length]
def getMinDistEntityFromPoint(point:List[float], entities:List[base.Entity])->base.Entity:  '''  名称:    getMinDistEntityFromPoint  描述:    从输入的entities对象中选出距point最近的对象。  参数:    point List[float] 参考点坐标    entities List[base.Entity] 存在cog的可迭代对象或entity对象  返回值:    返回距point点最近的对象。  '''  if not entities: return None  if isinstance(entities, base.Entity): return entities  if len(entities)==1return entities[0]  minDistance:float = math.inf  minEntity:base.Entity = None  for ent in entities:    cog = base.Cog(ent)    distance = Vector.distance(cog, point)    if distance<minDistance:      minDistance = distance      minEntity = ent  return minEntity
def main():  types:Tuple[str] = (ANSATYPE.eshell(DECK), 'SOLIDFACET')  entities:List[base.Entity] = base.PickEntities(DECK, types, initial_type=types[0])  if not entities: return None  if len(entities)==1:    entity = entities[0]    cog = base.Cog(entity)  else:    cog = calcCog(entities)  entity = getMinDistEntityFromPoint(cog, entities)  vect = getShellViewVector(entity)  fields = {'XT': cog[0], 'YT': cog[1], 'ZT': cog[2],             'XH': cog[0]+vect[0], 'YH': cog[1]+vect[1], 'ZH': cog[2]+vect[2],             'Name''element normal vector'}  base.CreateEntity(DECK, 'DEFINE_VECTOR', fields)  viewVect = getViewVector()  fields = {'XT': cog[0], 'YT': cog[1], 'ZT': cog[2],             'XH': cog[0]+viewVect[0], 'YH': cog[1]+viewVect[1], 'ZH': cog[2]+viewVect[2],             'Name''view vector'}  base.CreateEntity(DECK, 'DEFINE_VECTOR', fields)  return Noneif __name__ == '__main__':    main()
来源:檐苔
RADIOSSOptiStructNastranMarcAbaqus二次开发
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-08-26
最近编辑:15小时前
青瓦松
硕士 签名征集中
获赞 12粉丝 0文章 45课程 0
点赞
收藏
作者推荐

实验硬点数据拟合(python版)

程序功能: 该程序主要要用于对硬点数据进行拟合并输入拟合数据集及对应图集。 1、数据集输出到原始数据文件夹下,名字为*.bus 2、图片集输出到原始数据文件夹下,名字为PicLics.docx程序开发环境: notepad++、Python3.7.0、Anaconda4.8.3前期处理: 一个硬点包括6个自由度[三平动(x, y, z)三转动(rx, ry, rz)],通常分六个xlsx文件存储。须先按如图1格式存入一个xlsx文件中。该文件名按使用者需求命名,该名字将会和后面生成的图片相关联。将六个自由度的数据按下图格式存入该文件中。若某自由度数据缺失,直接如图进行补0。新建一个文件夹,将新生成的所有xlxsx文件均放入该文件夹下。程序使用方法: 1、使用者根据自己电脑已安装Python编译器运行该程序[本机以为notepad++配置了Python运行快捷键(ctrl+R)]。 2、弹出控制台提示框,在框内输入前期处理中创建的文件夹的绝对路径,如下图: 3、键入enter后,弹出下图控制平台,拟合度deg默认为10,可通过调整该值点击curve重新生成曲线。在生成的曲线图片中,对比原始数据曲线(ini)和拟合曲线(reg)是否符合要求。若符合,点击ok确定,完成一组数据的拟合。结果说明: 结束该程序后在前期处理中创建的文件夹生成一个PicLics.docx文件及一系列*.bus文件。PicLics.docx文件用于存储所有生成的图片。一个*.bus文件对应一个xlsx文件用于存储硬点自由度拟合后曲线数据。程序源码链接: 链接: https://pan.baidu.com/s/1FwtCUESVA03t4f1RkZ6SEQ 提取码: rtu3来源:檐苔

有附件
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈