Jump to content
Jeffersondhv

Duplication of elements with different orientation

Recommended Posts

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.

image.png.3fecf883a2fc328860c2adcafa7ffa22.png

 

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.

image.png.b714f9b1374eca63d827615eb1046212.png

 

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

 

Share this post


Link to post
Share on other sites
On 11/21/2018 at 7:58 PM, tinh 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

Share this post


Link to post
Share on other sites

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

 

 

Share this post


Link to post
Share on other sites

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
}

 

Livil Lyle and vipin like this

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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]

}

 

Share this post


Link to post
Share on other sites

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_
	}
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
You are posting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...