2044x
001596
2019-10-23

Способы выбора элементов через COM-интерфейс

При редактировании элементов посредством интерфейса COM, становится самым частым затруднением сам выбор элементов, так как его нельзя выполнить визуально с помощью рабочего окна. Особые затруднения он может вызывать у моделей, созданных посредством интерфейса программы, которые затем требуют проведение дальнейших изменений в отдельной программе. Кроме исключения, когда выбор был уже сделан посредством программы RFEM, пользователю предлагается несколько альтернатив, с помощью которых можно легко запрограммировать выбор.

Выбор по комментариям

Самым простым способом выбора элементов, является, наверное, направленный поиск по конкретным комментариям, заданным во время создания элементов. Далее показан пример функции, которая ищет стержни по их комментариям и возвращает их найденные номера:

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

Die Funktion hat eine Schleife über die übergebenen Stäbe und wenn es zu einer Übereinstimmung mit der Zeichenkette in "comment" und dem Kommentar des Stabes kommt, wird die Stabnummer dem Integer-Feld hinzugefügt. Благодаря этому, мы в конечном итоге получаем цифровое поле с номерами всех требуемых стержней.

Выбор по конечным узлам стержней

Die Auswahl von Elementen im Programm und damit auch über die COM-Schnittstelle erfolgt mit Hilfe von Zeichenketten. Например, соответствующие узлы на линии передаются с помощью строки, в которой номера узлов разделены запятыми. Die Verwendung von Zeichenketten bedarf bei der Programmierung der Umwandlung in Zahlenwerte und umgekehrt. Im Folgenden daher die Funktion, welche die aus der obigen Funktion ermittelten Stabnummern in eine Zeichenkette umwandeln kann. Es werden die Stabnummern über die Funktion CStr einzeln in Zeichen umgewandelt und nach jeder Zahl wird der Zeichenkette ein Komma hinzugefügt. Das überflüssige Komma am Ende der Zeichenkette wird von RFEM/RSTAB ignoriert und kann daher bleiben.

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

Mit Hilfe dieser Funktion ist es jetzt möglich, die durch Kommentar gefilterten Stäbe über die COM-Schnittstelle zu selektieren.

    ' 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

Oft genügt nicht nur die Selektion bestimmter Elemente, sondern es werden untergeordnete Elemente benötigt. Exemplarisch wird im Folgenden der Weg aufgezeigt, wie man die Startknoten eines Stabes finden kann. Da sich der Weg in RFEM etwas schwieriger gestaltet als in RSTAB, da hier zu jedem Stab noch eine Linie gehört, wurde dieser Weg gewählt.

Сначала требуется найти номера линий, принадлежащих стержням. У следующей функции предполагается, что у нас уже есть номера стержней, и функция выполняет поиск соответствующих номеров линий.

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

Данная функция содержит два вложенных цикла. Основной цикл просматривает стержни, а подчиненный цикл - номера стержней. У каждого стержня полностью считывается поле, содержащее номер стержня. Чтобы ускорить этот процесс, подчиненный цикл прекращается, как только номера стержней совпадут. Каждый раз, когда имеет место соответствие, к полю, содержащему номера линий, добавляется один элемент, и добавляется новый номер (k - индекс найденных номеров линий).

Чтобы найти начальный узел линии или стержня, требуется еще одна функция. Данная функция должна считывать линии и, если они соответствуют заданным номерам линий, считывать начальный узел. Поскольку номера узлов сохраняются в строке, требуется новая функция для преобразования строки в числовое поле.

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

Данная функция просматривает строку и анализирует каждый символ. Wenn es sich um eine Zahl oder mehrere handelt, dann werden diese gesammelt, bis das Ende oder ein anderes Zeichen erreicht werden. Wenn ein Bindestrich erreicht wird, wird eine Reihe/Spanne von Zahlen erkannt und die Zahlen dazwischen automatisch generiert.

Die eigentliche Funktion zum Extrahieren des Startpunktes einer Linie kann jetzt erstellt werden und wird dadurch sehr übersichtlich.

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

Es gibt auch hier wieder zwei verschachtelte Schlaufen, wie in der Funktion getLineNosByMemberNos. Diesmal ist die Reihenfolge von großer Bedeutung, da sonst die Zuordnung der Knoten zu den Linien verloren geht. Die äußere Schleife durchläuft die Liniennummern und wenn es innerhalb der inneren Schleife zur Übereinstimmung mit einer Linie kommt, werden mit der Funktion strToIntArr die Knotennummern extrahiert von denen hier die erste verwendet wird.

Процесс получения начальных узлов выглядит следующим образом: Сначала выбираются номера линий стержней с соответствующими номерами стержней, а затем начальные узлы линий.

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

Резюме и перспективы

Die Funktion getLineNosByMemberNos bildet die Grundlage für weitere Selektionsfunktionen wie auch bei der Funktion getLineStartNodeNosByLineNos. Используя данный шаблон, можно, например, найти нагрузки у стержней. Als Werkzeuge stehen dann noch die Funktionen strToIntArr und intArrToStr zur Verfügung mit deren Hilfe die Zeichenketten basierte Selektion von RFEM in Zahlenfelder umgewandelt werden kann.

Eine weitere Möglichkeit ist die Selektion über Koordinaten. Например, можно указать определенное пространство и выбрать все элементы в этом пространстве. Данная форма выбора будет описана в одной из дальнейших статей.


Автор

Г-н Гюнтель осуществляет техническую поддержку пользователей Dlubal Software.

Ссылки
Скачивания


;