Wybór na podstawie komentarza
Prawdopodobnie najprostszą metodą jest przypisanie komentarzy do tworzonych elementów, które można następnie wyszukać. Poniżej przedstawiono przykładową funkcję, która przeszukuje pręty według ich komentarzy i zwraca numery znalezionych prętów:
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
Funkcja wykonuje pętlę po przekazanych prętach. Jeżeli ciąg znaków podany w parametrze „comment” jest zgodny z komentarzem pręta, jego numer zostaje dodany do tablicy typu integer. Na końcu zwracana jest tablica zawierająca wszystkie znalezione numery prętów.
Wybór węzłów końcowych pręta
Wybór elementów w programie, a tym samym za pośrednictwem interfejsu COM, odbywa się przy użyciu ciągów znaków. Na przykład w przypadku linii powiązane węzły są przekazywane jako ciąg znaków, w którym numery węzłów są oddzielone przecinkami. Stosowanie ciągów znaków podczas programowania wymaga konwersji wartości liczbowych na tekstowe i odwrotnie. Dlatego poniżej przedstawiono funkcję, która zamienia numery prętów uzyskane za pomocą opisanej wcześniej funkcji w ciąg znaków. W tym celu numery prętów są kolejno konwertowane na znaki za pomocą funkcji CStr, a po każdej liczbie do ciągu znaków dodawany jest przecinek. Nadmiarowy przecinek na końcu ciągu jest ignorowany przez RFEM/RSTAB, dlatego może pozostać bez zmian.
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
Dzięki tej funkcji pręty przefiltrowane na podstawie komentarza mogą być następnie wybrane za pomocą interfejsu COM
' select members by commen
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
Często nie wystarcza samo zaznaczenie określonych elementów – potrzebny jest również dostęp do elementów podrzędnych z nimi powiązanych. Jako przykład poniżej przedstawiono sposób wyznaczania węzłów początkowych pręta. Ponieważ w programie RFEM procedura ta jest nieco bardziej złożona niż w RSTAB, gdyż do każdego pręta przypisana jest tu dodatkowo linia, jako przykład wybrano właśnie ten sposób.
Najpierw należy znaleźć numery linii przypisanych do prętów. Poniższa funkcja zakłada, że numery prętów już istnieją i wyszukuje odpowiadające im numery linii.
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
' zwiększ rozmiar tablicy o 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
Ta funkcja zawiera dwie zagnieżdżone pętle. Główna pętla przegląda pręty, a podrzędna - numery prętów. Dla każdego pręta przeszukiwane jest całe pole zawierające numery prętów. Aby przyspieszyć ten proces, pętla podrzędna jest przerywana w momencie znalezienia zgodności numerów prętów. W przypadku zgodności pole z numerami linii jest każdorazowo rozszerzane o jeden element i dodawany jest nowy numer (k jest indeksem dla znalezionych numerów linii).
Aby znaleźć węzeł początkowy linii lub pręta, potrzebna jest jeszcze jedna funkcja. Musi ona przejść przez linie i – w przypadku zgodności z podanymi numerami linii – odczytać węzeł początkowy. Ponieważ numery węzłów są zapisane w formie ciągu znaków, konieczna jest również funkcja, która przekształci taki ciąg znaków w tablicę wartości liczbowych.
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
Ta funkcja przechodzi przez ciąg znaków i analizuje każdy znak. Jeśli napotkany zostanie znak będący liczbą (jedną lub wieloma cyframi), są one zbierane aż do momentu osiągnięcia końca ciągu lub wystąpienia innego znaku. W przypadku napotkania myślnika rozpoznawany jest zakres (przedział) liczb, a wszystkie liczby znajdujące się pomiędzy wartościami granicznymi są generowane automatycznie.
Właściwa funkcja służąca do wyodrębnienia punktu początkowego linii może zostać teraz utworzona i dzięki temu jest bardzo przejrzysta
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
' dodaj znaleziony numer linii do tablicy
ReDim Preserve intArr(0 To k)
str = lines(j).NodeList
tmpIntArr = strToIntArr(str)
intArr(k) = tmpIntArr(0)
k = k + 1
' zakończ pętlę po line_nos_cpy
Exit For
End If
Next j
Next i
getLineStartNodeNosByLineNos = intArr
End Function
Również tutaj występują dwie zagnieżdżone pętle, podobnie jak w funkcji „getLineNosByMemberNos”. Tym razem kolejność ma kluczowe znaczenie, ponieważ w przeciwnym razie utracone zostałoby przyporządkowanie węzłów do linii. Zewnętrzna pętla przechodzi przez numery linii, a gdy w pętli wewnętrznej zostanie znalezione dopasowanie do danej linii, za pomocą funkcji strToIntArr wyodrębniane są numery węzłów, z których w tym przypadku wykorzystywany jest pierwszy.
Cały proces pobrania węzłów początkowych wygląda następująco. Najpierw dla odpowiednich numerów prętów pobierane są numery linii, a następnie wyznaczane są węzły początkowe tych linii.
' 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)
Podsumowanie i perspektywy
Funkcja getLineNosByMemberNos stanowi podstawę dla innych funkcji selekcji, podobnie jak funkcja getLineStartNodeNosByLineNos. Na bazie tego schematu można na przykład również wyszukiwać obciążenia przypisane do prętów. Jako narzędzia pomocnicze dostępne są funkcje strToIntArr oraz intArrToStr, dzięki którym selekcja oparta na ciągach znaków w RFEM może zostać przekształcona w operacje na tablicach liczbowych.
Inną możliwością jest wybór na podstawie współrzędnych. Można na przykład zdefiniować określoną przestrzeń i zaznaczyć wszystkie elementy znajdujące się w jej obrębie. Ten sposób selekcji zostanie opisany w późniejszym artykule.