1935x
001596
2019-10-23

Métodos para selecionar elementos através da interface COM

Ao editar elementos através da interface COM, a seleção de elementos é frequentemente um problema, porque não pode ser efetuada visualmente através da janela de trabalho. A seleção pode ser difícil, especialmente para os modelos que foram criados através da interface do programa e que foram depois ser modificados através de um programa separado. Além da exceção, quando a seleção foi efetuada anteriormente através do RFEM, existem várias alternativas para a programação.

Seleção por comentário

O mais simples pode ser que os comentários tenham sido atribuídos durante a criação dos elementos, os quais podem depois ser pesquisados especificamente. No texto a seguir, é apresentado um exemplo de uma função que pesquisa barras através de comentário e devolve os números de barra encontrados:

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

A função tem um loop sobre as barras transferidas e, se a string em "comentário" e o comentário da barra correspondem, o número da barra é adicionado ao campo inteiro. Finalmente, o campo inteiro com todos os números de barra é retornado.

Seleção de nós de extremidade de barra

A seleção de elementos no programa e, portanto, através da interface COM é realizada através de strings. Para uma linha, por exemplo, os nós relacionados são transferidos através de uma string na qual os números dos nós são separados por vírgulas. A utilização de strings requer a conversão em valores numéricos durante a programação e vice-versa. A seguinte função, portanto, apresenta uma maneira de converter os números de barra determinados com a função acima numa string. Os números de barra são convertidos individualmente em caracteres utilizando a função CStr e após cada número é adicionada uma vírgula à string. O RFEM/RSTAB ignora a vírgula redundante no final do string, que pode, portanto, permanecer.

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

Esta função agora permite a seleção das barras filtradas por comentário através da interface COM.

' selecionar barras por comentário
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

Frequentemente, não basta apenas selecionar elementos específicos; são necessários elementos subordinados. O exemplo a seguir mostra como encontrar os nós iniciais de uma barra. Uma vez que isso é um pouco mais difícil no RFEM do que no RSTAB e uma linha pertence a cada barra, foi escolhido este método.

Primeiro, é necessário encontrar os números de linha pertencentes às barras. A seguinte função assume que os números de barra já estão disponíveis e procura os números de linha relacionados.

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

Esta função tem duas voltas adjacentes. A volta principal atravessa as barras e a volta subordinado vai através dos números das barras. Para cada barra, o campo que contém os números da barra é passado completamente pelo campo que contém os números da barra. Para acelerar este processo, a volta subordinada será interrompida assim que os números de barra coincidirem. Sempre que existe uma correspondência, é adicionado um elemento ao campo que contém os números de linha e o novo número é adicionado (k é o índice para os números de linha encontrados).

Para encontrar o nó inicial da linha ou barra, é necessária outra função. Esta função tem de percorrer as linhas e, se corresponderem aos números de linhas fornecidos, ler o nó inicial. Uma vez que os números dos nós são armazenados numa string, é necessária uma nova função para converter a string num campo numérico.

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

Essa função percorre a string e analisa cada caractere. Se o caractere contiver um ou mais números, eles serão coletados até que outro caractere ou o final sejam alcançados. Quando é alcançado um hífen, é reconhecida uma série/intervalo de números e os números intermédios são gerados automaticamente.

A função real para extrair o ponto inicial de uma linha pode agora ser criada e está, portanto, muito clara.

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

Novamente, existem dois loops aninhados, como na função getLineNosByMemberNos. Desta vez, a sequência é muito importante porque, caso contrário, a atribuição dos nós às linhas é perdida. O ciclo externo percorre os números das linhas e, se uma linha dentro do ciclo interno for correspondente, a função strToIntArr é utilizada para extrair os números dos nós, dos quais o primeiro é utilizado aqui.

O procedimento completo para obter os nós iniciais é o seguinte. Primeiro, são retirados os números de linha das barras com os números de barra correspondentes, seguidos pelos nós iniciais da linha.

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

Resumo and Outlook

A função getLineNosByMemberNos é a base para outras funções de seleção, tal como com a função getLineStartNodeNosByLineNos. Utilizando este padrão, pode, por exemplo, encontrar cargas para barras. As funções strToIntArr e intArrToStr estão também disponíveis como ferramentas para converter a seleção baseada em strings do RFEM para campos numéricos.

Outra opção é a seleção através de coordenadas. Por exemplo, pode especificar um espaço definido e selecionar todos os elementos nesse espaço. Esta forma de seleção será descrita num artigo futuro.


Autor

O Eng. Günthel opera na área do apoio técnico para clientes.

Ligações
Downloads