×
INTELLIGENT WORK FORUMS
FOR ENGINEERING PROFESSIONALS

Log In

Come Join Us!

Are you an
Engineering professional?
Join Eng-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Eng-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

API: Freebody Objects - GetElements Method

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())
'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

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

RE: API: Freebody Objects - GetElements Method

(OP)
This explanation was beyond excellent. I appreciate your timely and detailed response.

RE: API: Freebody Objects - GetElements Method

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.

RE: API: Freebody Objects - GetElements Method

(OP)
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!

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Eng-Tips Forums free from inappropriate posts.
The Eng-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Eng-Tips forums is a member-only feature.

Click Here to join Eng-Tips and talk with other members! Already a Member? Login


Resources

eBook - 10 Reasons to Choose CATIA on the Cloud
To compete in today’s fast-paced and competitive market, smaller and newer firms need a powerful platform that will enable them to compete with bigger players, without the heavy investments needed in computer hardware, software and personnel. Download Now
White Paper - Smart Manufacturing for Electronics
This white paper describes a transformative approach to electronics manufacturing made possible by the addition of Mentor Graphics to the Siemens family. It describes a completely digitalized strategy that supports both printed circuit board (PCB) and mechanical design and manufacturing, uniting the entire product lifecycle – from idea and production to customers and back. Download Now

Close Box

Join Eng-Tips® Today!

Join your peers on the Internet's largest technical engineering professional community.
It's easy to join and it's free.

Here's Why Members Love Eng-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close