Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations waross on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

API: Freebody Objects - GetElements Method 1

Status
Not open for further replies.

vectorKZ

New member
Nov 11, 2015
6
0
0
US
Hello Eng-Tips,

I am writing a quick piece of code to store all of the freebody object properties in an active model session.
I am having difficulty using the GetElements method to retrieve all elements stored in the freebody entity. Documentation and examples for freebody objects in the API are sparse.

'Basic subroutine:
'Connect to existing femap session
Dim App As femap.model
Set App = GetObject(, "femap.model")


'Create freebody object
Dim fe_fbd As Object
Set fe_fbd = App.feFreebody


fe_fbd.First()

Dim rc as variant ' GetElements returns: 1. elm count(long), 2. elms (long)(array)
Dim elmcount as long
Dim elms(30) as long
' the 30# is just an example here

'walk the freebodies
While (fe_fbd.Next())
'do stuff here​
rc = fe_fbd.GetElements​

from this point I encounter numerous argument and type mismatch errors. Please help me with data structure or GetElements....

Regards,

KZ

 
Replies continue below

Recommended for you

The errors you're seeing are due to a mismatch with the second argument in the GetElements method. In FEMAP, when arrays are passed back via the API, almost always (check the documentation to be sure or look at what Intellisense is telling you), the variable that's passed in needs to be a variant, not any sort of typed array, especially if it's been pre-dimensioned. The following API will show you how to get all the elements in all freebody objects (will work for nodes as well if you use GetNodes() ):

Code:
Sub Main
    Dim App As femap.model
    Set App = feFemap()

    ' Declare FEMAP variables for freebody object and set object to hold freebody IDs
    Dim ffb As femap.Freebody
    Dim fsfb As femap.Set

    ' Declare variables for number of elements and variant array
    Dim nElem As Long
    Dim vnIDs As Variant

    ' Only initialize the set
    Set fsfb = App.feSet

    ' Add all freebody IDs to the set object
    fsfb.AddAll( FT_FREEBODY )

    ' Go BEFORE the first ID in the set
    fsfb.Reset()

    ' Use while loop to loop through all IDs in set containing entity IDs
    While( fsfb.Next() )
    	' Initialize freebody object within loop
    	Set ffb = App.feFreebody
    	ffb.Get( fsfb.CurrentID )
    	ffb.GetElements( n, nid )
    Wend

End Sub

The first thing I'll point out here is that while this code works, it's not what I'd consider "standard." While writing this up I discovered a bug in certain versions of FEMAP that may not clear out variants before returning them if the freebody object is used before. That's why the "Set xxx = App.feFreebody" instruction is nested inside the loop; it effectively forces everything inside the object to be reset. This is fixed for the upcoming 11.3 release, however the code presented above works for all versions. Because everything in the object is reset this way, it's not usable inside of a loop where you're looking for Next() as a fail condition to exit your loop.

This is the type of code I would recommend in most circumstances:

Code:
Sub Main
    Dim App As femap.model
    Set App = feFemap()

    ' Declare / set variable for freebody and element set
    Dim ffb As femap.Freebody
    Dim fsE As femap.Set

    Set ffb = App.feFreebody
    Set fsE = App.feSet()

    ' Declare long for element count and variant for array of element ids
    Dim nCount As Long
    Dim vnIDs As Variant

    ' Move pointer BEFORE start of first entity....
    ' Next() will move the pointer to the first entity
    ' No further Get() is required with this method
    ffb.Reset()

    While( ffb.Next() )
    	If ffb.GetElements( nCount, vnIDs ) = FE_OK Then
    		fsE.Clear()
    		fsE.AddArray( nCount, vnIDs )
    		App.feViewShow( FT_ELEM, fsE.ID )
    		App.feAppMessage( FCM_NORMAL, "First 2 elements in freebody " + Str$( ffb.ID ) )
    		App.feAppMessage( FCM_NORMAL, Str$( vnIDs(0) ) + ", " + Str$( vnIDs(1) ) + ", " + Str$( vnIDs(2) ) )
    		MsgBox( "Showing elements in freebody " + Str$( ffb.ID ) )
    		App.feViewRegenerate( 0 )
    	End If
    Wend
    
End Sub

As you can see in both examples, a variant is passed in for the return array, rather than a dynamic long array or a pre-dimensioned long array. As I mentioned before, retrieving arrays of data from FEMAP works this way in the majority of circumstances.

One other thing I'll point out is that when dealing with Set objects or Entity objects, I like to recommend calling Reset() prior to any looping if the intent is to walk through all the IDs in the model. Calling Reset() will move the pointer BEFORE the first ID (sets) / entity (entity objects) and the CurrentID (set) or ID (entity) property is set to -1, indicating that you're before the start of any entities. Calling Next() will move the pointer to the next available ID / entity, and for entity objects, it effectively "Gets" that entity from the database as well. First(), on the other hand, will move the pointer TO the first ID in a set of the first entity in a database. Just like Next(), First() will also retrieve the entity from the database, eliminating the need for an additional Get(). The big difference in how you walk the entities, however, lie in the loops.

Lets assume that we have a node object and there are nodes 1 through 5 in the database

** Using First() **

Code:
    fn.First()

    Do
    	Debug.Print Str$( fn.ID )
    Loop Until Not fn.Next()

** Using Next() **

Code:
    fn.Reset()

    While( fn.Next() )
    	Debug.Print Str$( fn.ID )
    Wend

The difference between the two is where the conditional check lies... With First(), you need to perform the conditional check after you handle the data within the first entity, whereas with Next(), you do it after the conditional check because nothing has been retrieved from the database yet. In both of these cases, the debug window will print out:

Code:
1
2
3
4
5

If you were to use the While/Wend structure with First(), you'd actually get this:

Code:
2
3
4
5

You would effectively be skipping the first ID/entity in the database.

While both are perfectly acceptable, I almost always recommend Reset() followed by a While/Wend, because of minor differences between what Next() actually returns for entities and sets (the differences lie in how each object works), both for IDs within a range or when you get to the final ID or the maximum label in a model.

Hope that helps; please post back if you have any further trouble getting going.

Patrick
 
One more thing I thought of that might help and probably explains why this wasn't a straightforward error...

When declaring variables for FEMAP objects, both of these are technically okay:

Code:
Dim fn as femap.node
Dim fnObj as Object

Both cases will work and your compiler (or in the case of the API programming window, the interpreter) doesn't know the difference, however in the case of the latter, whenever something is declared as an Object, the code completion in whatever IDE you happen to be using is unlikely to be able to give you hints on what arguments are required or the data types. Depending on where you happen to be coding, you'll need to make sure the proper namespace is referenced.
 
gtae2002,

Thanks to your assistance I whipped up a handy copy/paster for freebody data structures using Excel VBA.

keep it simple:
PULL button copies freebodies from active model
then switch tabs in femap to another model
PUSH button pastes freebodies wherever you want it

I am a lazy coder, and Python buff so the code syntax is kind of strange and brute force but it gets the job done. I plan on adding to it- but for now, check it out and critique if you like. I'm all about getting things right.

Check out the attachment and give it a shot!
 
 http://files.engineering.com/getfile.aspx?folder=f594cd71-599c-4803-8d4c-7591dfd29168&file=tryme_-_FEMAP_freebody_Copier.zip
Status
Not open for further replies.
Back
Top