Выбор по комментарию
Самым простым является назначение комментариев при создании элементов, которые затем могут быть целенаправленно найдены. Ниже приведена примерная функция, которая ищет балки по их комментарию и возвращает найденные номера балок:
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)
' цикл по балкам
For i = 0 To UBound(members, 1)
If (members(i).comment = comment) Then
' размер массива увеличивается на 1
ReDim Preserve intArr(0 To j)
intArr(j) = members(i).no
j = j + 1
End If
Next i
' возвращает массив целых чисел
getMemberNosByComment = intArr
End Function
Функция осуществляет цикл по переданным балкам, и если происходит совпадение строки в "comment" и комментария балки, номер балки добавляется в массив целых чисел. В конце массив чисел с номерами балок возвращается.
Выбор конечных узлов балки
Выбор элементов в программе, а также через интерфейс 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.
' выбрать балки по комментарию
Dim mems() As RFEM5.Member
Dim mem_nos() As Integer
Dim str As String
str = "тестовый комментарий"
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
' увеличить размер массива на 1
ReDim Preserve intArr(0 To k)
intArr(k) = members(i).LineNo
k = k + 1
' выйти из цикла по member_nos
Exit For
End If
Next j
Next i
getLineNosByMemberNos = intArr
End Function
Функция содержит два вложенных цикла. Главный цикл проходит по балкам, а вложенный цикл - по номерам балок. Для каждой балки массив с номерами балок полностью проходит. Чтобы ускорить этот процесс, подцикл завершается, как только происходит совпадение номеров балок. При совпадении массив с номерами линий каждый раз продлевается на элемент и новая строка добавляется (k - индекс для найденных номеров линий).
Для того, чтобы найти стартовый узел линии или балки, требуется еще одна функция. Эта функция должна пройти по линиям и при совпадении с заданными номерами линий прочитать стартовый узел. Поскольку номера узлов хранятся в строке, теперь потребуется еще одна функция, которая преобразует строку в массив чисел.
Function strToIntArr(intList As String) As Integer()
' возможные символы "1-9 ; - ,"
' пример: 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 (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 = ""
' если достигнут последний символ или запятая, или следующая точка с запятой
ElseIf ((curChar = ",") Or (curChar = ";") Or (i = Len(intList) - 1)) Then
' последний символ достигнут, или диапазон завершается
If (i = Len(intList) - 1) Then
curInt = curInt & curChar
End If
' обработать диапазон
If span Then
' создать все числа между диапазоном
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
' расширить ints и добавить новые числа в массив
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
' добавить новую цифру
Else
'расширить ints и добавить новое число в 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
' массив на один элемент слишком длинный и уменьшается
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
' добавить найденный номер линии в массив
ReDim Preserve intArr(0 To k)
str = lines(j).NodeList
tmpIntArr = strToIntArr(str)
intArr(k) = tmpIntArr(0)
k = k + 1
' выйти из цикла по line_nos_cpy
Exit For
End If
Next j
Next i
getLineStartNodeNosByLineNos = intArr
End Function
Здесь также два вложенных цикла, как в функции getLineNosByMemberNos. На этот раз порядок очень важен, иначе будет утеряно соответствие узлов линиям. Внешний цикл проходит по номерам линий, и когда во внутреннем цикле встречается совпадение с линией, с помощью функции strToIntArr извлекаются номера узлов, из которых здесь используется первый.
Весь процесс для получения стартовых узлов выглядит следующим образом. Сначала извлекаются номера линий балок с их правильными номерами, затем стартовые узлы линий.
' выбрать начальные узлы из балок
' получить номера линий любых балок
Dim line_nos() As Integer
line_nos = getLineNosByMemberNos(mems, mem_nos)
' получить начальные номера всех линий
Dim stNodes_nos() As Integer
stNodes_nos = getLineStartNodeNosByLineNos(lines, line_nos)
Резюме и перспективы
Функция getLineNosByMemberNos служит основой для дальнейших функций выбора, таких как getLineStartNodeNosByLineNos. По этому шаблону можно, например, также определить нагрузки для балок. В качестве инструментов еще доступны функции strToIntArr и intArrToStr, которые помогают преобразовать основанный на строках выбор RFEM в числовые массивы.
Еще один способ — выбор по координатам. Например, можно задать определенное пространство, и все элементы внутри этого пространства будут выбраны. Этот вид выбора будет описан в последующей статье.