1925x
001596
2019-10-23

Methods for Selecting Elements via COM Interface

When editing elements via the COM interface, selecting elements is often a problem because it cannot be carried out visually via the work window. The selection can be particularly difficult for models that have been created via the program interface and are then to be modified using a separate program. Apart from the exception, when the selection was made previously via RFEM, there are several alternatives for programming.

Selection by Comment

The simplest one may be that comments were assigned during the creation of elements, which can then be searched for specifically. In the following text, an example of a function is shown that searches for members by their comment and returns the member numbers found:

Function getMemberNosByComment(members() As RFEM5.Member, comment As String) As Integer()
    Dim intArr() As Integer
    Dim i As Long
    Dim j As Long
    j = 0
    ReDim intArr(0 To 0)
    ' loop over members
    For i = 0 To UBound(members, 1)
        If (members(i).comment = comment) Then
            ' size if integer array is increased by 1
            ReDim Preserve intArr(0 To j)
            intArr(j) = members(i).no
            j = j + 1
        End If
    Next i
    ' return integer array
    getMemberNosByComment = intArr
End Function

The function has a loop over the transferred members, and if the string in "comment" and the comment of the member match, the member number is added to the integer field. Finally, the integer field with all member numbers is returned.

Selection of Member End Nodes

The selection of elements in the program and thus via the COM interface is carried out using strings. For a line, for example, the related nodes are transferred through a string in which the node numbers are separated by commas. The use of strings requires conversion into numerical values during programming, and vice versa. The following function, therefore, presents a way to convert the member numbers determined with the function above into a string. The member numbers are individually converted into characters using the CStr function, and after each number, a comma is added to the string. RFEM/RSTAB ignores the redundant comma at the end of the string, which can, therefore, remain.

Function intArrToStr(intArr() As Integer) As String
    Dim str As String
    Dim i As Long
    
    For i = 0 To UBound(intArr, 1)
        str = str + CStr(intArr(i)) + ","
    Next i
    
    intArrToStr = str
End Function

This function now allows selection of the members filtered by comment via the COM interface.

    ' select members by comment
    Dim mems() As RFEM5.Member
    Dim mem_nos() As Integer
    Dim str As String
    
    str = "test comment"
    mem_nos = getMemberNosByComment(mems, str)
    
    iModelData.EnableSelections (True)
    
    str = intArrToStr(mem_nos)
    iModelData.SelectObjects MemberObject, str

Often, it is not enough to just select specific elements; subordinate elements are required. The following example shows how to find the start nodes of a member. Since this proves somewhat more difficult in RFEM than in RSTAB, because a line belongs to each member, this method was chosen.

First, one has to find the line numbers belonging to the members. The following function assumes that member numbers are already available and searches for the related line numbers.

Function getLineNosByMemberNos(members() As RFEM5.Member, member_nos() As Integer) As Integer()
    
    Dim intArr() As Integer
    Dim i As Long
    Dim j As Long
    Dim k As Long
    
    k = 0
    ReDim intArr(0 To 0)
    
    For i = 0 To UBound(members, 1)
        For j = 0 To UBound(member_nos, 1)
            If (members(i).no = member_nos(j)) Then
                ' increase array size by 1
                ReDim Preserve intArr(0 To k)
                intArr(k) = members(i).LineNo
                k = k + 1
                ' exit loop over member_nos
                Exit For
                        End If
        
        Next j
        Next i
    
    getLineNosByMemberNos = intArr
    
End Function

This function has two nested loops. The main loop goes through the members and the subordinate loop through the member numbers. For each member, the field containing the member numbers is passed through completely. To speed up this process, the sub-loop is left as soon as the member numbers match. Every time there is a match, one element is added to the field containing the line numbers and the new number is added (k is the index for the found line numbers).

To find the start node of the line or member, another function is required. This function has to go through the lines and, if they match the given line numbers, read out the start node. Since the node numbers are stored in a string, a new function is needed to convert the string into a numerical field.

Function strToIntArr(intList As String) As Integer()
    '  possible chars "1-9 ; - ,"
    '  example: 1-4,5;100 > 1,2,3,4,5,100
    Dim ints() As Integer
    Dim tmpInts() As Integer
    ReDim ints(0)
    
    Dim span As Boolean
    Dim curInt As String
    curInt = ""
    Dim i As Integer
    i = 0
    Dim j As Integer
    Dim curChar As String
    
    Do While (i < Len(intList))
        curChar = Mid(intList, i + 1, 1)
        
        ' if string contains "-" a span is noted
        If (curChar = "-") Then
        
            span = True
            tmpInts = ints
            ReDim Preserve tmpInts(0 To UBound(tmpInts, 1) + 1)
            tmpInts(UBound(tmpInts, 1) - 1) = CInt(curInt)
            ints = tmpInts
            curInt = ""
        ' if last char is reached or a comma or a semicolon is the next char
        ElseIf ((curChar = ",") Or (curChar = ";") Or (i = Len(intList) - 1)) Then
        
            ' last char is reached, integer or span are terminated
            If (i = Len(intList) - 1) Then
                curInt = curInt & curChar
            End If
            
            ' treat the span
            If span Then
                ' create all integers between the span
                Dim firstNum As Integer
                Dim lastNum As Integer
                firstNum = ints(UBound(ints, 1) - 1)
                lastNum = CInt(curInt)
                curInt = ""
                
                If (firstNum > lastNum) Then
                    Dim tmp1 As Integer
                    tmp1 = lastNum
                    lastNum = firstNum
                    firstNum = tmp1
                    ints(UBound(ints, 1) - 1) = firstNum
                    
                End If
                
                ' extend ints and add new numbers to array
                tmpInts = ints
                ReDim Preserve tmpInts(0 To UBound(tmpInts, 1) + (lastNum - firstNum))
                
                For j = 0 To (lastNum - firstNum) - 1
                    tmpInts(UBound(ints, 1) + j) = j + firstNum + 1
                Next j
                
                ints = tmpInts
                span = False
            
            ' add new digit
            Else
                'extend ints and add new number to ints
                tmpInts = ints
                ReDim Preserve tmpInts(0 To UBound(tmpInts, 1) + 1)
                tmpInts(UBound(tmpInts, 1) - 1) = CInt(curInt)
                ints = tmpInts
                curInt = ""
            End If
        
        Else
        
            curInt = curInt & curChar
        End If
    
        i = i + 1
    Loop
    
    ' array is one element too long and is decreased
    ReDim Preserve ints(0 To UBound(ints, 1) - 1)
    
    strToIntArr = ints
End Function

This function goes through the string and analyzes each character. If the character contains one or more numbers, they are collected until another character or the end is reached. When a hyphen is reached, a series/range of numbers is recognized and the numbers in between are generated automatically.

The actual function for extracting the start point of a line can now be created and is, therefore, very clear.

Function getLineStartNodeNosByLineNos(lines() As RFEM5.RfLine, line_nos() As Integer) As Integer()
    Dim intArr() As Integer
    Dim tmpIntArr() As Integer
    Dim str As String
    Dim i As Long
    Dim j As Long
    Dim k As Long
    
    k = 0
    ReDim intArr(0 To 0)
    
    For i = 0 To UBound(line_nos, 1)
        For j = 0 To UBound(lines, 1)
            If (lines(j).no = line_nos(i)) Then
                ' add found line number to array
                ReDim Preserve intArr(0 To k)
                str = lines(j).NodeList
                tmpIntArr = strToIntArr(str)
                intArr(k) = tmpIntArr(0)
                k = k + 1
                ' exit loop over line_nos_cpy
                Exit For
            End If
        
        Next j
    Next i
    
    getLineStartNodeNosByLineNos = intArr
End Function

Again, there are two nested loops, as in the getLineNosByMemberNos function. This time, the sequence is very important because otherwise, the assignment of the nodes to the lines is lost. The outer loop cycles through the line numbers and, if a line within the inner loop is a match, the strToIntArr function is used to extract the node numbers, of which the first one is used here.

The entire procedure for getting the start nodes is then as follows. First, the line numbers of the members with the corresponding member numbers are fetched, followed by the line start nodes.

    ' select start nodes from members
    '   get line numbers from all members
    Dim line_nos() As Integer
    line_nos = getLineNosByMemberNos(mems, mem_nos)
    '   get start numbers from all lines
    Dim stNodes_nos() As Integer
    stNodes_nos = getLineStartNodeNosByLineNos(lines, line_nos)

Summary and Outlook

The getLineNosByMemberNos function is the basis for further selection functions, just as with the getLineStartNodeNosByLineNos function. Using this pattern, you can, for example, find loads for members. The strToIntArr and intArrToStr functions are also available as tools for converting the strings-based selection of RFEM into number fields.

Another option is selection via coordinates. For example, you can specify a defined space and select all elements within that space. This form of selection will be described in a future article.


Author

Mr. Günthel provides technical support for our customers.

Links
Downloads