在ANSA二次开发中经常获取当前视角下被选中单元和视角一致的法向量以备后续操作。本文主要通过创建视角向量和被选中单元的法向量来展示这一过程。首先,需要对中的错误进行更正:ansa中GetViewAngles函数旋转顺序为Z->Y->Z;且以顺时针为正,和一般笛卡尔坐标相反。因此有:importmathfromtypingimportList,TuplefromansaimportbasefromansaimportconstantsfromansaimportcalcclassANSATYPE(object):'''不同求解器对应关键字名字'''@classmethoddefeshell(cls,deck:int)->str:typDict:dict={constants.LSDYNA:'ELEMENT_SHELL',constants.ABAQUS:'SHELL',constants.NASTRAN:'SHELL',constants.RADIOSS:'SHELL',constants.ANSYS:'SHELL',22:'SHELL',#OPTISTRUCT23:'SHELL'#MARC}try:_type=typDict[deck]exceptKeyError:raiseValueError('ERROR:模型Deck设置有误')return_type@classmethoddefnode(cls,deck:int)->str:typDict:dict={constants.LSDYNA:'NODE',constants.ABAQUS:'NODE',constants.NASTRAN:'GRID',constants.RADIOSS:'NODE',constants.ANSYS:'NODE',22:'GRID',#OPTISTRUCT23:'NODE'#MARC}try:_type=typDict[deck]exceptKeyError:raiseValueError('ERROR:模型Deck设置有误')return_typeclassVector(object):@classmethoddefpoint2Point(cls,point1:List[float],point2:List[float],unit:bool=True)->List[float]:'''计算两点构成的向量.向量由point1指向point2,即point2-point1'''ifisinstance(point1,base.Entity):point1=point1.positionifisinstance(point2,base.Entity):point2=point2.positionvect:List[float]=[p2-p1forp1,p2inzip(point1,point2)]returncls.unit(vect)ifunitelsevect@staticmethoddefunit(vector:List[float])->List[float]:'''将一个向量单位化'''returncalc.Normalize(vector)@staticmethoddefdistance(point1:List[float],point2:List[float])->float:'''计算两点间的距离'''ifisinstance(point1,base.Entity):point1=point1.positionifisinstance(point2,base.Entity):point2=point2.positionreturnmath.dist(point1,point2)@classmethoddefangleCos(cls,vector1:List[float],vector2:List[float])->float:'''计算两个空间向量的夹角的余弦值。'''unit_vect01=cls.unit(vector1)unit_vect02=cls.unit(vector2)returnsum([v1*v2forv1,v2inzip(unit_vect01,unit_vect02)])@staticmethoddefangle(vector1:List[float],vector2:List[float])->float:'''计算两个空间向量的夹角,返回值以弧度形式存在'''returncalc.CalcAngleOfVectors(vector1,vector2)@classmethoddefelemNormal(cls,shellElem:base.Entity)->List[float]:'''根据单元的前三个节点计算单元的法向量'''vect:List[float]=base.GetNormalVectorOfShell(shellElem)ifisinstance(vect,list):returnvectelse:nodeType:str=ANSATYPE.node(DECK)nodes:List[base.Entity]=base.CollectEntities(DECK,shellElem,nodeType,recursive=True)returncls.vec3Point(nodes[0],nodes[1],nodes[2])@classmethoddefvec3Point(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)returncalc.CrossProduct(vect1,vect2)defgetViewVector()->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]defgetShellViewVector(elem:base.Entity)->List[float]:'''名称:getShellViewVector描述:获取shell单元与当前视角方向一致的法向向量参数:elemobjectshell类型单元返回值:返回一个向量(list),该向量表示输入shell单元与当前视角一致的单元法向量。'''#对输入对象进行参数检查ifnotisinstance(elem,base.Entity):raiseTypeError('请输入ansa对象')shellType=ANSATYPE.eshell(DECK)elemType=elem.ansa_type(DECK)ifelemType!=shellTypeandelemType!='SOLIDFACET':raiseTypeError(f'''输入ansaType类型有误,此函数要求输入的为shell单元或solid单元的表面类型(SOLIDFACET),现输入类型为{elemType}''')#获取单元法向量elemVect:List[float]=Vector.elemNormal(elem)#获取视角向量viewVect:List[float]=getViewVector()#计算两个向量的夹角,若为锐角,单元法向量为所求方向;若为钝角,单元法向量反方向为所求方向angle:float=Vector.angle(elemVect,viewVect)ifangle==-math.pi:raiseValueError(f'输入向量有误,现输入向量为{elemVect}和{viewVect},请核查')ifangle>math.pi/2.0:elemVect=[-vectforvectinelemVect]returnelemVectdefcalcCog(entities:List[base.Entity])->List[float]:'''名称:calcCog描述:计算输入的entities对象的cog参数:entitiesList[base.Entity]存在cog的可迭代对象或entity对象返回值:返回一个Cog向量(list)'''ifisinstance(entities,base.Entity):entities=[entities]length=len(entities)iflength==0:return[0.0,0.0,0.0]iflength==1:returnbase.Cog(entities[0])x,y,z=0.0,0.0,0.0forentinentities:cog=base.Cog(ent)x+=cog[0]y+=cog[1]z+=cog[2]return[x/length,y/length,z/length]defgetMinDistEntityFromPoint(point:List[float],entities:List[base.Entity])->base.Entity:'''名称:getMinDistEntityFromPoint描述:从输入的entities对象中选出距point最近的对象。参数:pointList[float]参考点坐标entitiesList[base.Entity]存在cog的可迭代对象或entity对象返回值:返回距point点最近的对象。'''ifnotentities:returnNoneifisinstance(entities,base.Entity):returnentitiesiflen(entities)==1:returnentities[0]minDistance:float=math.infminEntity:base.Entity=Noneforentinentities:cog=base.Cog(ent)distance=Vector.distance(cog,point)ifdistance<minDistance:minDistance=distanceminEntity=entreturnminEntitydefmain():types:Tuple[str]=(ANSATYPE.eshell(DECK),'SOLIDFACET')entities:List[base.Entity]=base.PickEntities(DECK,types,initial_type=types[0])ifnotentities:returnNoneiflen(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':'elementnormalvector'}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':'viewvector'}base.CreateEntity(DECK,'DEFINE_VECTOR',fields)returnNoneif__name__=='__main__':main()来源:檐苔