2044x
001596
23.10.2019

Metody výběru prvků přes rozhraní COM

Při zpracování prvků přes rozhraní COM je často problémem vybrat příslušné prvky, protože výběr nelze provést vizuálně v pracovním okně. Právě u modelů, které byly vytvořeny v programovém prostředí a následně mají být upraveny v samostatném programu, může být výběr obtížný. Kromě výjimky, kdy výběr již předem proběhl v programu RFEM, máme několik možností, jak výběr naprogramovat.

Výběr podle komentáře

Asi nejjednodušší způsob je cílené vyhledávání podle komentáře, který byl uveden při vytvoření prvků. Níže ukážeme pro příklad funkci, která umožní procházet pruty podle jejich komentáře a která nám vrátí čísla nalezených prutů:

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

Funkce má smyčku nad převáděnými pruty, a pokud se vyskytne shoda mezi znakovým řetězcem v „comment“ a mezi komentářem k určitému prutu, zařadí se číslo prutu do pole Integer. Nakonec se vrátí pole Integer se všemi čísly prutů.

Výběr koncových uzlů prutů

Výběr prvků v programu, a tím i v rozhraní COM, se provádí pomocí znakových řetězců. Příslušné uzly na linii se například převedou pomocí znakového řetězce, v němž jsou čísla uzlů oddělena čárkou. Použití řetězců vyžaduje při programování konverzi na číselné hodnoty a naopak. Nyní tedy následuje funkce, která čísla prutů získaná výše uvedenou funkcí konvertuje do znakového řetězce. Es werden die Stabnummern über die Funktion CStr einzeln in Zeichen umgewandelt und nach jeder Zahl wird der Zeichenkette ein Komma hinzugefügt. Nadbytečná čárka na konci znakového řetězce program RFEM/RSTAB ignoruje, a může tam tudíž zůstat.

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

Tato funkce nyní umožňuje vybrat v rozhraní COM pruty vyfiltrované podle komentáře.

    ' 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

Často nestačí vybrat pouze určité prvky, ale je třeba vybrat i podřízené prvky. Níže si pro příklad ukážeme, jak lze najít počáteční uzly prutu. Protože je v programu RFEM postup o něco složitější vzhledem k tomu, že ke každému prutu patří navíc linie, zvolíme právě tento postup.

Nejdříve je třeba nalézt čísla linií k příslušným prutům. Následující funkce předpokládá, že jsou již k dispozici čísla prutů, a hledá příslušná čísla linií.

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

Tato funkce má dvě vnořené smyčky. Hlavní smyčka přitom prochází pruty a podřízená smyčka čísla prutů. U každého prutu se kompletně prochází pole s čísly prutů. Pro urychlení tohoto procesu se podřízená smyčka opustí po nalezení shody v číslech prutů. Při každé shodě se pole s čísly linií pokaždé doplní o jeden prvek a připojí se nové číslo (k je index nalezených čísel linií).

Má-li být nalezen počáteční uzel linie, respektive prutu, je zapotřebí ještě další funkce. Tato funkce musí procházet linie a při shodě s danými čísly linií musí načíst počáteční uzel. Protože se čísla uzlů ukládají do znakového řetězce, potřebujeme nyní ještě funkci, která konvertuje znakový řetězec do číselného pole.

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

Tato funkce prochází daný řetězec a analyzuje každý znak. Pokud se jedná o jedno nebo několik čísel, shromažďuje je až po dosažení konce nebo jiného znaku. V případě pomlčky je rozpoznána řada nebo rozsah čísel a automaticky se vygenerují všechna obsažená čísla.

Nyní můžeme vytvořit vlastní funkci pro vypsání počátečního bodu linie, která je tak velmi přehledná.

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. Tentokrát je pořadí velmi důležité, protože jinak nelze správně přiřadit uzly k liniím. Vnější smyčka prochází čísla linií, a jestliže je ve vnitřní smyčce nalezena shoda s určitou linií, vypíšou se pomocí funkce strToIntArr čísla uzlů a první z nich se zde použije.

Celý postup pro získání počátečních uzlů pak vypadá následovně. Nejdříve se načtou čísla linií příslušných prutů s odpovídajícími čísly prutů a následně počáteční uzly linií.

    ' 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)

Shrnutí a výhled

Die Funktion getLineNosByMemberNos bildet die Grundlage für weitere Selektionsfunktionen wie auch bei der Funktion getLineStartNodeNosByLineNos. Tento vzor lze například použít také pro vyhledání zatížení u prutů. 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.

Další možnost představuje výběr pomocí souřadnic. Lze tak například zadat určitý prostor, v němž se vyberou veškeré prvky. Tento způsob výběru popíšeme v některém našem příštím příspěvku.


Autor

Ing. Günthel zajišťuje technickou podporu zákazníkům.

Odkazy
Stahování


;