Auswahl über Kommentar
Die wohl einfachste ist, dass bei der Erstellung von Elementen Kommentare vergeben wurden, welche dann gezielt gesucht werden können. Im Folgenden wird exemplarisch eine Funktion dargestellt, welche Stäbe nach deren Kommentar durchsucht und die gefundenen Stabnummern zurückgibt:
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. Am Ende wird das Integer-Feld mit allen Stabnummern zurückgegeben.
Selektion von Stabendknoten
Die Auswahl von Elementen im Programm und damit auch über die COM-Schnittstelle erfolgt mit Hilfe von Zeichenketten. So werden zum Beispiel bei einer Linie die zugehörigen Knoten über eine Zeichenkette übergeben, in der die Knotennummern per Komma getrennt gespeichert sind. 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.
Zuerst müssen die Liniennummern zu den Stäben gefunden werden. Die folgende Funktion setzt voraus, dass bereits Stabnummern vorliegen und sucht die zugehörigen Liniennummern.
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
Diese Funktion besitzt zwei verschachtelte Schleifen. Dabei durchläuft die Hauptschleife die Stäbe und die untergeordnete Schleife die Stabnummern. Bei jedem Stab wird das Feld mit den Stabnummern komplett durchlaufen. Um diesen Prozess zu beschleunigen, wird die Unterschleife verlassen, sobald eine Übereinstimmung der Stabnummern eintritt. Bei einer Übereinstimmung wird das Feld mit den Liniennummern jedes Mal um ein Element verlängert und die neue Nummer hinzugefügt (k ist der Index für die gefundenen Liniennummern).
Damit der Startknoten der Linie respektive des Stabes gefunden wird, bedarf es noch einer weiteren Funktion. Diese Funktion muss die Linien durchlaufen und bei einer Übereinstimmung mit den gegebenen Liniennummern den Startknoten auslesen. Da die Knotennummern in einer Zeichenkette gespeichert sind, wird nun noch eine Funktion benötigt, welche die Zeichenkette in ein Feld aus Zahlen umwandelt.
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
Diese Funktion durchläuft die Zeichenkette und untersucht jedes Zeichen. 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.
Der gesamte Ablauf zum Holen der Startknoten sieht dann wie folgt aus. Zuerst werden die Liniennummern der Stäbe mit den entsprechenden Stabnummern geholt und danach die Linienstartknoten.
' 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)
Zusammenfassung und Ausblick
Die Funktion getLineNosByMemberNos bildet die Grundlage für weitere Selektionsfunktionen wie auch bei der Funktion getLineStartNodeNosByLineNos. Über dieses Muster lassen sich beispielsweise auch Lasten zu Stäben herausfinden. 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. So kann zum Beispiel ein definierter Raum angegeben werden und alle Elemente innerhalb dieses Raums werden ausgewählt. Diese Form der Selektion wird in einem späteren Artikel beschrieben.