1928x
001596
2019-10-23

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

При редактировании элементов посредством интерфейса COM, становится самым частым затруднением сам выбор элементов, так как его нельзя выполнить визуально с помощью рабочего окна. Особые затруднения он может вызывать у моделей, созданных посредством интерфейса программы, которые затем требуют проведение дальнейших изменений в отдельной программе. Neben der Ausnahme, dass die Auswahl zuvor über RFEM getroffen wurde, gibt es mehrere Alternativen für die Programmierung.

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

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

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

Функция имеет цикл по переданным элементам, и если строка в «комментарии» и комментарий элемента совпадают, номер элемента добавляется в целочисленное поле. Благодаря этому, мы в конечном итоге получаем цифровое поле с номерами всех требуемых стержней.

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

Выбор элементов в программе и, следовательно, через интерфейс COM осуществляется с помощью строк. Например, соответствующие узлы на линии передаются с помощью строки, в которой номера узлов разделены запятыми. Использование строк требует преобразования в числовые значения во время программирования и наоборот. Следовательно, следующая функция представляет способ преобразования номеров элементов, определенных с помощью функции выше, в строку. Номера элементов по отдельности преобразуются в символы с помощью функции CStr, и после каждого числа к строке добавляется запятая. RFEM/RSTAB игнорирует лишнюю запятую в конце строки, которая, следовательно, может остаться.

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

Эта функция теперь позволяет выбирать элементы, отфильтрованные по комментариям через интерфейс COM.

' 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

Часто бывает недостаточно просто выбрать определенные элементы; подчиненные элементы обязательны. В следующем примере показано, как найти начальные узлы элемента. Поскольку в RFEM это оказывается несколько сложнее, чем в RSTAB, так как линия принадлежит каждому стержню, был выбран этот метод.

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

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

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

Фактическая функция для извлечения начальной точки линии теперь может быть создана и, следовательно, очень понятна.

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

Опять же, есть два вложенных цикла, как в функции getLineNosByMemberNos. На этот раз последовательность очень важна, потому что в противном случае привязка узлов к линиям будет потеряна. Внешний цикл циклически перебирает номера строк, и, если строка во внутреннем цикле совпадает, функция strToIntArr используется для извлечения номеров узлов, из которых здесь используется первый.

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

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

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

Функция getLineNosByMemberNos является основой для дальнейших функций выбора, как и функция getLineStartNodeNosByLineNos. Используя данный шаблон, можно, например, найти нагрузки у стержней. Пользователю также доступны функции strToIntArr и intArrToStr в качестве инструментов для преобразования выбора из программы RFEM, основанного на символьной строке, в числовое поле.

Другой вариант - выбор по координатам. Например, можно указать определенное пространство и выбрать все элементы в этом пространстве. Данная форма выбора будет описана в одной из дальнейших статей.


Автор

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

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