2242x
001596
2019-05-13

Metody wybierania elementów za pomocą interfejsu COM

Podczas edytowania elementów za pośrednictwem interfejsu COM często pojawia się problem z selekcją elementów, gdyż nie można jej przeprowadzić wizualnie w oknie roboczym. W przypadku modeli, które zostały utworzone przy użyciu interfejsu programu, a następnie mają być zmodyfikowane za pomocą własnego programu, wybór może być trudny. Oprócz wyjątku, gdy wybór został wcześniej dokonany za pomocą RFEM, istnieje kilka alternatyw do programowania.

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.


Autor

Pan Günthel zapewnia wsparcie techniczne klientom firmy Dlubal Software i zajmuje się ich zapytaniami.

Odnośniki
Pobrane


;