Duplication of elements with different orientation
Hello all,
I'm working on a script to duplicate elements from a reference component containing a solid to a new component with the same exact solid, but in another position and orientation.
The translation part was easy as the hm_getcentroid function provides the solid centroid position, so I can use the command *translatemark to translate the desired mesh to the correct position.
But to match the orientation, it has been a task more difficult that I was expecting.
My approach has been to extract the moment of inertia of the reference solid and the target solid using hm_getmoiofsolid. Once I get these values, I compute the principal moment of inertia for each solid, so I have a comparable reference to use. Then I calculate the Euler parameters (or Quaternions) to obtain the rotation angles that I can use to rotate the elements from the reference solid to match the target solid orientation.
The problem I'm facing is that it seems that the inertia calculation performed by hm_getmoiofsolid seems not to be consistent, in a sense that even extracting the principal moments of inertia from them, these principal directions do not coincide with the solid orientation.
What could be done in this case?
Thanks in advance,
Jefferson Vieira
Answers
-
Hi, you should use *positionmark command
0 -
Altair Forum User said:
Hi, you should use *positionmark command
Thanks for the answer tinh.
I have actually already tried using *positionmark in one of my code versions, but I still get some cases where the elements end up somewhat flipped.
I guess I might need to properly order the inertia tensor to get the correct orientation.
Right now I'm using an auxiliary Python code to compute the principal moments of inertia for the solids. Is there a way to do this using Hypermesh's or TCL's functions?
Thanks,
Jefferson Vieira
0 -
I think yes.
Could you show the code using *positionmark? Perhaps something's wrong, it must work
0 -
Sure, here are my codes.
0 -
Your code is very long, so it is not efficient
I see some comps are reflected, so *positionmark will not work on them (need *reflectmark to eliminate flipping)
I think approach can be simplify based on specification of the comp:
- it has 1 max surface
- its max surf is irregular
So we will match max surf of source comp to target ones
To do that, we take 3 mid nodes of 3 edges of the max surf
0 -
Code is like this
proc p_GetMaxSurf {SurfList {n 1}} { set SaList {} foreach SurfId $SurfList { lappend SaList '$SurfId [hm_getareaofsurface surfs $SurfId]' } lrange [dict keys [join [lsort -decreasing -real -index 1 $SaList]]] 0 $n-1 } proc p_GetMaxLine {LineList {n 1}} { set ElList {} foreach EdgeId $LineList { lappend ElList '$EdgeId [hm_linelength $EdgeId]' } lrange [dict keys [join [lsort -decreasing -real -index 1 $ElList]]] 0 $n-1 } proc p_Mcopy args { *createmarkpanel comps 1 'Select source comp:' if {[hm_marklength comps 1]!=1} {return -code error 'Select 1 comp only'} set SourceComp [hm_getmark comps 1] *createmark elems 1 'by comp id' $SourceComp if {![hm_marklength elems 1]} {return -code error 'Comp #$SourceComp has no element'} set SourceElems [hm_getmark elems 1] *createmark surfs 1 'by comp id' $SourceComp if {![hm_marklength comps 1]} {return -code error 'Comp #$SourceComp has no surface'} set SourceSurfs [hm_getmark surfs 1] set MaxSurf [p_GetMaxSurf $SourceSurfs] lassign [p_GetMaxLine [join [hm_getsurfaceedges $MaxSurf]] 3] Line1 Line2 Line3 *createmark lines 1 $Line1 *nodecreateonlines lines 1 1 0 0 set N1 [hm_latestentityid nodes] *createmark lines 1 $Line2 *nodecreateonlines lines 1 1 0 0 set N2 [hm_latestentityid nodes] *createmark lines 1 $Line3 *nodecreateonlines lines 1 1 0 0 set N3 [hm_latestentityid nodes] ############################################### *createmarkpanel comps 1 'Select target comps:' hm_markremove comps 1 $SourceComp foreach TargetComp [hm_getmark comps 1] { *createmark surfs 1 'by comp id' $TargetComp if {[hm_marklength surfs 1]} { set MaxSurf [p_GetMaxSurf [hm_getmark surfs 1]] lassign [p_GetMaxLine [join [hm_getsurfaceedges $MaxSurf]] 3] Line1 Line2 Line3 *createmark lines 1 $Line1 *nodecreateonlines lines 1 1 0 0 set N1_ [hm_latestentityid nodes] *createmark lines 1 $Line2 *nodecreateonlines lines 1 1 0 0 set N2_ [hm_latestentityid nodes] *createmark lines 1 $Line3 *nodecreateonlines lines 1 1 0 0 set N3_ [hm_latestentityid nodes] *currentcollector comps [hm_getcollectorname comps $TargetComp] eval *createmark elems 1 $SourceElems *duplicatemark elems 1 1 *positionmark elems 1 $N1 $N2 $N3 $N1_ $N2_ $N3_ } } *clearmark all 1 }
0 -
Thanks a lot. That is very helpful. I haven't thought about this approach.
As I would like to have this code more general, what could be done if the max surface is regular?
Thank you
0 -
Hi
In general, you have to identify an unique specification of the comp, it could be an irregular surf smaller than max surf, or 3 holes,... which forms a fundamental system. Inertial axles is such a system
As the comp could be regular shapes like sphere, cube,... then it is simple case
0 -
Got it.
So do you know a way to compute the principal moments of inertia for the solids using TCL?
I found that to compute eigenvalues and eigenvectors I would need to add a TCL extension, but I really don't want to use that as it would add an additional step to be able to share this code with my colleagues.
I see that using the approaches you suggested it works for a lot of cases, but I would like to use the inertia as it would provide me a more general solution.
Thanks
0 -
Yes, you don't need tcllib extension package
use templex.exe of hyperworks:
proc p_GetPrincInertia {Ixx Iyy Izz Ixy Iyz Izx} { set fpt [open GetEIGRL.tpl w] puts $fpt '{eigvalreal({{$Ixx,$Ixy,$Izx},{$Ixy,$Iyy,$Iyz},{$Izx,$Iyz,$Izz}})}' close $fpt exec [file join [hm_info -appinfo ALTAIR_HOME] hw bin [file tail [hm_info -appinfo HMBIN_DIR]] templex.exe] [file normalize GetEIGRL.tpl] }
0 -
You don't need eigen values but eigen vectors,
So change eigvalreal to eigvecreal
0 -
But I think using principle vectors are not as exact as using max surf
code is like this
proc p_GetEIGRL {Ixx Iyy Izz Ixy Iyz Izx} { set fpt [open GetEIGRL.tpl w] puts $fpt '{eigvalreal({{$Ixx,$Ixy,$Izx},{$Ixy,$Iyy,$Iyz},{$Izx,$Iyz,$Izz}})}' puts $fpt '{eigvecreal({{$Ixx,$Ixy,$Izx},{$Ixy,$Iyy,$Iyz},{$Izx,$Iyz,$Izz}})}' close $fpt exec [file join [hm_info -appinfo ALTAIR_HOME] hw bin [file tail [hm_info -appinfo HMBIN_DIR]] templex.exe] [file normalize GetEIGRL.tpl] } proc p_MCopy args { *createmarkpanel comps 1 'Select source comp:' if {[hm_marklength comps 1]!=1} {return -code error 'Select 1 source comp only'} set SourceComp [hm_getmark comps 1] *createmark elems 1 'by comp id' $SourceComp set ElemList [hm_getmark elems 1] if {![llength $ElemList]} {return -code error 'Not found element in comp #$SourceComp'} *createmark solids 1 'by comp id' $SourceComp set SolidId [hm_getmark solids 1] if {[llength $SolidId]!=1} {return -code error 'Source comp must have 1 solid'} set PrincInertia [string map {, ''} [eval p_GetEIGRL [hm_getmoiofsolid $SolidId]]] eval *createnode [hm_getcentroidofsolids 1] set Node1 [hm_latestentityid nodes] lassign $PrincInertia > > > V1 V2 V3 *createmark nodes 1 $Node1 *duplicatemark nodes 1 25 set Node2 [hm_getmark nodes 1] eval *createvector 1 $V1 *translatemark nodes 1 1 1 *createmark nodes 1 $Node1 *duplicatemark nodes 1 25 set Node3 [hm_getmark nodes 1] eval *createvector 1 $V2 *translatemark nodes 1 1 1 *createmarkpanel comps 1 'Select target comps:' foreach TargetComp [hm_getmark comps 1] { *createmark solids 1 'by comp id' $TargetComp if {[hm_marklength solids 1]!=1} continue set PrincInertia [string map {, ''} [eval p_GetEIGRL [hm_getmoiofsolid [hm_getmark solids 1]]]] eval *createnode [hm_getcentroidofsolids 1] set Node1_ [hm_latestentityid nodes] lassign $PrincInertia > > > V1 V2 V3 *createmark nodes 1 $Node1_ *duplicatemark nodes 1 25 set Node2_ [hm_getmark nodes 1] eval *createvector 1 $V1 *translatemark nodes 1 1 1 *createmark nodes 1 $Node1_ *duplicatemark nodes 1 25 set Node3_ [hm_getmark nodes 1] eval *createvector 1 $V2 *translatemark nodes 1 1 1 eval *createmark elems 1 $ElemList *currentcollector comps [hm_getcollectorname comps $TargetComp] *duplicatemark elems 1 1 *positionmark elems 1 $Node1 $Node2 $Node3 $Node1_ $Node2_ $Node3_ } }
0 -
Thank you, that's very helpful.
It seems like the max surf does the job better, but I've found some cases where it does not work well.
I'll run further tests and comment later.
0