2242x
001596
2019-05-13

Metodi per la selezione di elementi tramite interfaccia COM

Durante la modifica di elementi tramite l'interfaccia COM, la selezione degli elementi rappresenta spesso un problema poiché non può essere eseguita visivamente tramite la finestra di lavoro. Soprattutto nei modelli creati tramite l'interfaccia del programma e che poi devono essere modificati tramite un programma proprio, la selezione può risultare difficile. Oltre all'eccezione che la selezione sia stata effettuata prima tramite RFEM, ci sono diverse alternative per la programmazione.

Selezione tramite commento

Il metodo probabilmente più semplice è che, durante la creazione degli elementi, siano stati assegnati dei commenti che poi possono essere ricercati specificamente. Di seguito viene mostrata una funzione esemplare che cerca i membri secondo il loro commento e restituisce i numeri di membri trovati:


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)
    ' ciclo sui membri
    For i = 0 To UBound(members, 1)
        If (members(i).comment = comment) Then
            ' aumenta la dimensione dell'array intero di 1
            ReDim Preserve intArr(0 To j)
            intArr(j) = members(i).no
            j = j + 1
        End If
    Next i
    ' restituisce l'array intero
    getMemberNosByComment = intArr
End Function

La funzione ha un ciclo sui membri passati e, se c'è una corrispondenza tra la stringa in "comment" e il commento del membro, il numero del membro viene aggiunto al campo intero. Alla fine, viene restituito il campo intero con tutti i numeri dei membri.

Selezione di nodi finali del membro

La selezione degli elementi nel programma, e quindi anche tramite l'interfaccia COM, avviene utilizzando le stringhe. Ad esempio, per una linea, i nodi correlati vengono passati tramite una stringa in cui i numeri dei nodi sono salvati separati da una virgola. L'uso delle stringhe richiede la conversione in valori numerici e viceversa durante la programmazione. Di seguito quindi la funzione, che può convertire i numeri dei membri ottenuti dalla funzione sopra in una stringa. I numeri dei membri vengono convertiti singolarmente in caratteri tramite la funzione CStr e, dopo ogni numero, viene aggiunta una virgola alla stringa. La virgola superflua alla fine della stringa viene ignorata da RFEM/RSTAB e può quindi rimanere.


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

Grazie a questa funzione, ora è possibile selezionare i membri filtrati tramite commento tramite l'interfaccia COM.


    ' selezionare membri tramite commento
    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

Spesso non basta solo selezionare determinati elementi, ma sono necessari elementi subordinati. Di seguito viene mostrato in modo esemplare il metodo per trovare i nodi iniziali di un membro. Poiché in RFEM il procedimento è un po' più complesso rispetto a RSTAB, poiché qui ogni membro è associato a una linea, è stato scelto questo metodo.

Innanzitutto, bisogna trovare i numeri delle linee corrispondenti ai membri. La seguente funzione presuppone che siano già disponibili dei numeri di membri e cerca i numeri di linee associati.


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
                ' aumenta la dimensione dell'array di 1
                ReDim Preserve intArr(0 To k)
                intArr(k) = members(i).LineNo
                k = k + 1
                ' esce dal ciclo sui member_nos
                Exit For
            End If
        
        Next j
    Next i
    
    getLineNosByMemberNos = intArr
    
End Function

Questa funzione possiede due cicli annidati. Il ciclo principale attraversa i membri e il ciclo subordinato i numeri dei membri. Per ogni membro, il campo con numeri dei membri viene completamente traversato. Per accelerare questo processo, il ciclo interno viene lasciato non appena si verifica una corrispondenza tra i numeri dei membri. Se si verifica una corrispondenza, il campo con i numeri delle linee viene esteso di un elemento e il nuovo numero viene aggiunto (k è l'indice per i numeri di linee trovati).

Affinché il nodo iniziale della linea o del membro venga trovato, è necessaria un'altra funzione. Questa funzione deve attraversare le linee e, in caso di corrispondenza con i numeri delle linee dati, leggere il nodo iniziale. Poiché i numeri dei nodi sono memorizzati in una stringa, è ora necessaria una funzione che converta la stringa in un campo numerico.


Function strToIntArr(intList As String) As Integer()
    ' possibili caratteri "1-9 ; - ,"
    ' esempio: 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)
        
        ' se la stringa contiene "-" una serie è segnalata
        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 = ""
        ' se l'ultimo carattere è raggiunto o una virgola o un punto e virgola è il carattere successivo
        ElseIf ((curChar = ",") Or (curChar = ";") Or (i = Len(intList) - 1)) Then
        
            ' l'ultimo carattere è raggiunto, il numero o la serie è terminato
            If (i = Len(intList) - 1) Then
                curInt = curInt & curChar
            End If
            
            ' gestisce la serie
            If span Then
                ' crea tutti i numeri tra la serie
                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
                
                ' estende ints e aggiunge nuovi numeri all'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
            
            ' aggiunge una nuova cifra
            Else
                ' estende ints e aggiunge un nuovo numero a 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
    
    ' l'array è un elemento troppo lungo e viene ridotto
    ReDim Preserve ints(0 To UBound(ints, 1) - 1)
    
    strToIntArr = ints
End Function

Questa funzione attraversa la stringa e esamina ciascun carattere. Se si tratta di un numero o di più, questi vengono raccolti fino a quando non si raggiunge la fine o un altro carattere. Quando si raggiunge un trattino, viene riconosciuta una serie di numeri e i numeri intermedi vengono generati automaticamente.

La funzione effettiva per estrarre il punto iniziale di una linea può ora essere creata e risulta molto chiara.


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
                ' aggiunge il numero di linea trovato all'array
                ReDim Preserve intArr(0 To k)
                str = lines(j).NodeList
                tmpIntArr = strToIntArr(str)
                intArr(k) = tmpIntArr(0)
                k = k + 1
                ' esce dal ciclo su line_nos_cpy
                Exit For
            End If
        
        Next j
    Next i
    
    getLineStartNodeNosByLineNos = intArr
End Function

Anche qui ci sono di nuovo due cicli annidati, come nella funzione getLineNosByMemberNos. Questa volta l'ordine è di grande importanza, altrimenti viene persa l'assegnazione dei nodi alle linee. Il ciclo esterno attraversa i numeri delle linee e, se si verifica una corrispondenza con una linea all'interno del ciclo interno, i numeri dei nodi vengono estratti tramite la funzione strToIntArr, di cui viene usato qui il primo.

L'intero processo per ottenere i nodi iniziali appare quindi come segue. Innanzitutto, vengono recuperati i numeri delle linee dai membri con i numeri dei membri corrispondenti e poi i nodi iniziali delle linee.


    ' selezionare i nodi iniziali dai membri
    '   ottenere i numeri delle linee da tutti i membri
    Dim line_nos() As Integer
    line_nos = getLineNosByMemberNos(mems, mem_nos)
    '   ottenere i numeri iniziali da tutte le linee
    Dim stNodes_nos() As Integer
    stNodes_nos = getLineStartNodeNosByLineNos(lines, line_nos)

Sommario e prospettive

La funzione getLineNosByMemberNos costituisce la base per ulteriori funzioni di selezione, come anche per la funzione getLineStartNodeNosByLineNos. Seguendo questo schema, è possibile anche trovare i carichi associati ai membri. Come strumenti sono poi disponibili le funzioni strToIntArr e intArrToStr, con l'aiuto delle quali la selezione basata su stringhe di RFEM può essere convertita in array numerici.

Un'altra possibilità è la selezione tramite coordinate. Ad esempio, è possibile specificare uno spazio definito e selezionare tutti gli elementi all'interno di questo spazio. Questo tipo di selezione verrà descritto in un articolo successivo.


Autore

Il signor Günthel fornisce supporto tecnico per i clienti di Dlubal Software e si prende cura delle loro richieste.

Link
Download


;