Wybór przez komentarz
Najprostszą metodą jest przypisanie komentarzy do elementów podczas ich tworzenia, które można następnie przeszukiwać. Poniżej przedstawiono przykładową funkcję, która przeszukuje pręty według ich komentarzy i zwraca znalezione numery 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)
' pętla po prętach
For i = 0 To UBound(members, 1)
If (members(i).comment = comment) Then
' rozmiar tablicy int zwiększa się o 1
ReDim Preserve intArr(0 To j)
intArr(j) = members(i).no
j = j + 1
End If
Next i
' zwróć tablicę int
getMemberNosByComment = intArr
End Function
Funkcja ta zawiera pętlę po przekazanych prętach i jeśli wystąpi zgodność między ciągiem znaków w "comment" a komentarzem pręta, numer pręta zostanie dodany do tablicy integer. Na końcu zwracana jest tablica integer ze wszystkimi numerami prętów.
Wybór węzłów końcowych pręta
Wybór elementów w programie, a także za pośrednictwem interfejsu COM, odbywa się przy pomocy ciągów znaków. Na przykład dla linii, powiązane węzły są przekazywane jako ciąg znaków, w którym numery węzłów są zapisane oddzielone przecinkami. Korzystanie z ciągów znaków wymaga w programowaniu przekształcenia na wartości liczbowe i odwrotnie. Poniżej przedstawiona jest funkcja, która zamienia numery prętów uzyskane z powyższej funkcji na ciąg znaków. Numery prętów są zamieniane pojedynczo na znaki za pomocą funkcji CStr, a po każdej liczbie dodawany jest przecinek do ciągu znaków. Niepotrzebny przecinek na końcu ciągu znaków jest ignorowany przez RFEM/RSTAB i może zostać pozostawiony.
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
Korzystając z tej funkcji, możliwe jest teraz wybranie prętów przefiltrowanych przez komentarz za pośrednictwem interfejsu COM.
' wybierz pręty po komentarzu
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 wystarczy tylko wybór określonych elementów, ale wymaga się elementów podrzędnych. Przykładowo przedstawiony zostanie sposób, jak znaleźć węzły początkowe pręta. Ponieważ w RFEM jest to nieco bardziej skomplikowane niż w RSTAB, ponieważ do każdego pręta należy jeszcze linia, wybrano tę drogę.
Najpierw należy znaleźć numery linii dla prętów. Poniższa funkcja zakłada, że numery prętów już istnieją i wyszukuje powiązane 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
' zakończ pętlę po member_nos
Exit For
End If
Next j
Next i
getLineNosByMemberNos = intArr
End Function
Funkcja ta zawiera dwie zagnieżdżone pętle. Główna pętla przegląda pręty, a podrzędna pętla numery prętów. Przy każdym pręcie pole z numerami prętów jest całkowicie przeglądane. Aby przyspieszyć ten proces, podrzędna pętla jest opuszczana, gdy tylko nastąpi zgodność numerów prętów. Przy zgodności pole z numerami linii jest za każdym razem powiększane o jeden element i dodawany nowy numer (k jest indeksorem dla znalezionych numerów linii).
Aby znaleźć węzeł początkowy linii lub pręta, potrzebna jest jeszcze jedna funkcja. Musi ona przeglądać linie i przy zgodności z podanymi numerami linii odczytać węzeł początkowy. Ponieważ numery węzłów są zapisane w formie ciągu znaków, potrzebna jest funkcja, która przekształci ciąg znaków w tablicę liczb.
Function strToIntArr(intList As String) As Integer()
' możliwe znaki "1-9 ; - ,"
' przykład: 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)
' jeśli ciąg zawiera "-", zanotowano przedział
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 = ""
' jeśli ostatni znak jest osiągnięty lub następny znak to przecinek lub średnik
ElseIf ((curChar = ",") Or (curChar = ";") Or (i = Len(intList) - 1)) Then
' ostatni znak jest osiągnięty, całkowita lub przedział są zamykane
If (i = Len(intList) - 1) Then
curInt = curInt & curChar
End If
' obsługa przedziału
If span Then
' stworzenie wszystkich liczb w przedziale
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
' rozszerz ints i dodaj nowe liczby do tablicy
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
' dodaj nową liczbę
Else
'rozszerz ints i dodaj nową liczbę do 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
' tablica jest o jeden element za długa i jest zmniejszona
ReDim Preserve ints(0 To UBound(ints, 1) - 1)
strToIntArr = ints
End Function
Ta funkcja przegląda ciąg znaków i bada każdy znak. Jeśli jest to liczba lub kilka, są one zbierane, aż do końca lub innego znaku. Kiedy osiągnięty zostanie myślnik, rozpoznawany jest ich zakres/przedział, a liczby między nimi są generowane automatycznie.
Właściwa funkcja do ekstrakcji węzła początkowego linii może teraz zostać utworzona i 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
Tutaj również znajdują się dwie zagnieżdżone pętle, podobnie jak w funkcji getLineNosByMemberNos. Tym razem kolejność jest bardzo ważna, ponieważ inaczej zostanie utracone przyporządkowanie węzłów do linii. Zewnętrzna pętla przechodzi przez numery linii, a jeśli wewnętrzna pętla napotka zgodność z linią, numery węzłów są wyodrębniane za pomocą funkcji strToIntArr, z których tutaj wykorzystywany jest pierwszy.
Cały proces pobrania węzłów początkowych wygląda wtedy następująco. Najpierw uzyskiwane są numery linii prętów za pomocą odpowiednich numerów prętów, a następnie węzły początkowe linii.
' wybierz węzły początkowe z prętów
' uzyskaj numery linii ze wszystkich prętów
Dim line_nos() As Integer
line_nos = getLineNosByMemberNos(mems, mem_nos)
' uzyskaj numery początkowe ze wszystkich linii
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. Wykorzystując ten wzorzec, można na przykład określić obciążenia dla prętów. Dostępne są wtedy funkcje strToIntArr i intArrToStr, które umożliwiają przekształcenie selekcji bazujących na ciągach znaków z RFEM na tablice liczb.
Inną możliwością jest wybór przez współrzędne. Na przykład można określić zdefiniowaną przestrzeń, a wszystkie elementy wewnątrz tej przestrzeni zostaną wybrane. Tego rodzaju selekcja zostanie opisana w przyszłym artykule.