Selektieren von Container-Elementen
In diesem Beispiel werden Container-Elemente mit Hilfe einer benutzerdefinierten Bedingung gefiltert. Dazu wird die Funktion F_VN_CopyContainerElementsConditional_ITcVnContainer genutzt, da es sich bei den Container-Elementen wiederum um Container handelt. Falls die Container-Elemente Iteratoren sind, kann dazu auch die Funktion F_VN_CopyContainerElementsConditional_ITcVnForwardIterator genutzt werden.
Erklärung
Wenn die Elemente von mehrdimensionalen Containern gefiltert werden sollen, entsteht durch den Zugriff auf die Sub-Elemente schnell großer Programmieraufwand. Um dem entgegenzuwirken, stellt TwinCAT Vision genau dafür eine Funktionalität bereit, die z.B. wie folgt genutzt wird:
Es wird ein Funktionsblock angelegt, der das Interface ITcVnCustomElementCondition_ITcVnContainer
implementiert. Dieses Interface besitzt die Methode Condition
, welche ein Element vom Typ ITcVnContainer
entgegennimmt. In der Implementierung dieser Methode wird die Filterbedingung festgelegt, die auf das Element angewandt werden soll. Der Funktionsblock mit der Filterbedingung wird dann an die Funktion F_VN_CopyContainerElementsConditional_ITcVnContainer
übergeben, um die Filterung aller Elemente eines Containers durchzuführen. In diesem Beispiel werden die Elemente danach gefiltert, ob sie mehr als fünf Sub-Elemente besitzen.
Anwendung
Beispielhaft werden die Sub-Container eines Containers danach gefiltert, wie viele Elemente sie jeweils besitzen. Konkret sollen nur die Sub-Container in einen neuen Container übernommen werden, die mehr als fünf Elemente haben. Die Struktur des Containers kann mittels des Arrays aContainerStructure
variiert werden. Die Elemente geben an, wie viele Sub-Elemente jeder Sub-Container hat. Wenn ebenfalls die Anzahl der der Sub-Container selbst variiert wird, muss die Konstante cNumberOfSubContainers
darauf abgestimmt werden.
Programm
MAIN
Zunächst wird ein konstanter Integer definiert, um die Anzahl der Sub-Container einfach variieren zu können:
VAR CONSTANT
cNumberOfSubContainers : INT := 5;
END_VAR
Daraufhin werden alle benötigten Variablen deklariert:
VAR
aContainerStructure : ARRAY [0..(cNumberOfSubContainers-1)] OF INT := [2, 7, 3, 5, 12];
ipHelper : ITcVnContainer;
ipContainerBase : ITcVnContainer;
ipContainerFiltered : ITcVnContainer;
fbCondition : FB_ConditionMoreThanFive;
nSelectedContainers : ULINT;
hr : HRESULT;
i : INT;
END_VAR
aContainerStructure | Definition der Container-Struktur. Ein Array der Länge Die Länge des Arrays wird durch die Konstante |
ipHelper | Hilfs-Interface-Pointer, der dazu benutzt wird, den Hauptcontainer |
ipContainerBase | Container, in dem die in |
fbCondition | Funktionsblock, der die Filterbedingung enthält. |
ipContainerFiltered | Container, der am Ende nur die Sub-Container aus |
nSelectedContainers | Integer, der anzeigt, wie viele Sub-Container die Filterbedingung tatsächlich erfüllen. |
hr | Statusvariable vom Typ HRESULT. |
i | Hilfsvariable |
Im Programmteil wird ein Container erstellt, der mit den oben definierten Sub-Containern gefüllt wird. Der Aufruf von F_VN_ReserveContainerMemory ist dabei optional und dient nur einer besseren Performance.
hr := F_VN_CreateContainer(ipContainerBase, ContainerType_Vector_Vector_REAL, 0, hr);
hr := F_VN_ReserveContainerMemory(ipContainerBase, cNumberOfSubContainers, hr);
FOR i:=0 TO (cNumberOfSubContainers-1) DO
hr := F_VN_CreateContainer(ipHelper, ContainerType_Vector_REAL, aContainerStructure[i], hr);
hr := F_VN_AppendToContainer_ITcVnContainer(ipHelper, ipContainerBase, hr);
END_FOR
Daraufhin wird der gerade erstellte Container gefiltert. Als Filterbedingung wird der Funktionsblock mit der selbst-geschriebenen Bedingung angegeben.
hr := F_VN_CopyContainerElementsConditional_ITcVnContainer(
ipSrcContainer := ipContainerBase,
ipDestContainer := ipContainerSelection,
ipConditionFB := fbCondition,
hr);
Um die Funktionalität der Funktion nachzuvollziehen, werden die Elemente, die die geschriebene Bedingung erfüllen, gezählt. Die Variable nSelectedContainers
ändert sich nun abhängig von den Sub-Containern und der Filterbedingung.
hr := F_VN_GetNumberOfElements(ipContainerSelection, nSelectedContainers, hr);
In diesem Fall gibt die Anzahl an, wie viele der Sub-Container mehr als fünf Sub-Elemente haben.
Funktionsblock mit Filterbedingung
Die Filterbedingung wird als Funktionsblock mit einer Methode Condition
übergeben. Damit ein selbst-geschriebener Funktionsblock an die Funktion übergeben werden kann, muss dieser das Interface
ITcVnCustomElementCondition_ITcVnContainer implementieren:
FUNCTION_BLOCK FB_ConditionMoreThanFive IMPLEMENTS ITcVnCustomElementCondition_ITcVnContainer
Die Methode Condition
definiert die Filterbedingung. Sie wird für jeden Sub-Container einzeln aufgerufen. Je nachdem, ob der Rückgabewert TRUE
oder FALSE
ist, wird der jeweilige Sub-Container in den neuen Container übernommen oder nicht.
METHOD Condition : BOOL
Bei jedem Aufruf der Methode wird die aktuelle Sub-Container als Eingangsparameter übergeben:
VAR_INPUT
ipElement : ITcVnContainer;
END_VAR
In diesem Fall soll ein Element übernommen werden, wenn es mehr als fünf Sub-Elemente hat. Dafür wird die Anzahl der Sub-Elemente berechnet und abhängig vom Ergebnis der Wert TRUE
oder FALSE
zurückgegeben.
hr := F_VN_GetNumberOfElements(ipElement, nNumberOfElements, hr);
IF FAILED(hr) OR nNumberOfElements <= 5 THEN
Condition := FALSE;
ELSE
Condition := TRUE;
END_IF
Die benötigten Variablen sind wie folgt deklariert:
VAR
nNumberOfElements : ULINT;
hr : HRESULT;
END_VAR
Sowohl der Funktionsblock selbst als auch die Methode Condition
müssen das Compiler-Attribut {attribute 'c++_compatible'}
enthalten.