1932x
001596
2019-10-23

Métodos para seleccionar elementos a través de la interfaz COM

Al editar elementos a través de la interfaz COM, a menudo la selección de elementos es un problema porque no se puede llevar a cabo visualmente por medio de la ventana de trabajo. La selección puede ser especialmente difícil para los modelos que se han creado mediante la interfaz del programa y después se van a modificar utilizando un programa por separado. Neben der Ausnahme, dass die Auswahl zuvor über RFEM getroffen wurde, gibt es mehrere Alternativen für die Programmierung.

Selección por comentario

El más simple puede ser que se hayan asignado los comentarios durante la creación de los elementos, que luego se pueden buscar específicamente. En el siguiente texto, se muestra un ejemplo de una función que busca miembros por su comentario y devuelve los números de miembro 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

La función tiene un bucle sobre los miembros transferidos, y si la cadena en "comentario" y el comentario del miembro coinciden, el número de miembro se agrega al campo entero. Finalmente, se devuelve el campo numérico entero con todos los números de las barras.

Selección de los nudos del extremo de barra

La selección de elementos en el programa y, por lo tanto, a través de la interfaz COM se realiza mediante cadenas. Para una línea, por ejemplo, los nodos relacionados se transfieren a través de una cadena en la que los números de nodo están separados por comas. El uso de cadenas requiere la conversión a valores numéricos durante la programación y viceversa. La siguiente función, por lo tanto, presenta una forma de convertir los números de barra determinados con la función anterior en una cadena. Los números de los miembros se convierten individualmente en caracteres usando la función CStr, y después de cada número, se agrega una coma a la cadena. RFEM/RSTAB ignora la coma redundante al final de la cadena, que, por lo tanto, puede 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 función ahora permite la selección de los miembros filtrados por comentario a través de la interfaz COM.

' 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

A menudo, no basta con seleccionar elementos específicos; Se requieren elementos subordinados. El siguiente ejemplo muestra cómo encontrar los nodos de inicio de una barra. Dado que esto resulta algo más difícil en RFEM que en RSTAB, debido a que una línea pertenece a cada miembro, se eligió este método.

Primero, hay que encontrar los números de línea que pertenecen a las barras. La siguiente función asume que los números de barras ya están disponibles y busca los números de línea 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 función tiene dos bucles anidados. El bucle principal recorre las barras y el bucle subordinado a través de los números de barras. Para cada miembro, el campo que contiene los números de miembro se pasa por completo. Para acelerar este proceso, el sub-bucle se deja tan pronto como coincidan los números de barras. Cada vez que hay una coincidencia, se añade un elemento al campo que contiene los números de línea y se agrega el nuevo número (k es el índice para los números de línea encontrados).

Para encontrar el nudo de inicio de la línea o barra, se requiere otra función. Esta función tiene que pasar por las líneas y, si coinciden con los números de línea dados, leer el nodo de inicio. Como los números de nudo se almacenan en una cadena, se necesita una nueva función para convertir la secuencia en un 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

Esta función recorre la cadena y analiza cada carácter. Si el personaje contiene uno o más números, se recopilan hasta que se llega a otro personaje o al final. Cuando se alcanza un guión, se reconoce una serie/rango de números y los números intermedios se generan automáticamente.

La función real para extraer el punto inicial de una línea ahora se puede crear y, por lo tanto, es muy 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

Nuevamente, hay dos bucles anidados, como en la función getLineNosByMemberNos. Esta vez, la secuencia es muy importante porque de lo contrario, se pierde la asignación de los nodos a las líneas. El bucle externo recorre los números de línea y, si una línea dentro del bucle interno coincide, se usa la función strToIntArr para extraer los números de nodo, de los cuales el primero se usa aquí.

El procedimiento completo para obtener los nudos de inicio es el siguiente. En primer lugar, se recogen los números de línea de las barras con los números de barras correspondientes, seguidos por los nudos de inicio de línea.

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

Resumen y perspectiva

La función getLineNosByMemberNos es la base para otras funciones de selección, al igual que con la función getLineStartNodeNosByLineNos. Usando este patrón, puede, por ejemplo, encontrar cargas para las barras. Las funciones strToIntArr e intArrToStr también están disponibles como herramientas para convertir la selección basada en cadenas de RFEM en campos de número.

Otra opción es la selección mediante coordenadas. Por ejemplo, puede especificar un espacio definido y seleccionar todos los elementos dentro de ese espacio. Esta forma de selección se describirá en un artículo futuro.


Autor

El Sr. Günthel proporciona soporte técnico para los clientes de Dlubal Software y se ocupa de sus solicitudes.

Enlaces
Descargas