API: Freebody Objects - GetElements Method
API: Freebody Objects - GetElements Method
(OP)
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())
from this point I encounter numerous argument and type mismatch errors. Please help me with data structure or GetElements....
Regards,
KZ
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





RE: API: Freebody Objects - GetElements Method
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 SubThe 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 SubAs 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 ) WendThe 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 -->
If you were to use the While/Wend structure with First(), you'd actually get this:
CODE -->
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
RE: API: Freebody Objects - GetElements Method
RE: API: Freebody Objects - GetElements Method
When declaring variables for FEMAP objects, both of these are technically okay:
CODE -->
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.
RE: API: Freebody Objects - GetElements Method
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!