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_VARDaraufhin 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_VARaContainerStructure | 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, TO_ULINT(cNumberOfSubContainers), hr);
FOR i:=0 TO (cNumberOfSubContainers-1) DO
hr := F_VN_CreateContainer(ipHelper, ContainerType_Vector_REAL, TO_ULINT(aContainerStructure[i]), hr);
hr := F_VN_AppendToContainer_ITcVnContainer(ipHelper, ipContainerBase, hr);
END_FORDaraufhin 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 := ipContainerFiltered,
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(ipContainerFiltered, 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_ITcVnContainerDie 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 : BOOLBei jedem Aufruf der Methode wird die aktuelle Sub-Container als Eingangsparameter übergeben:
VAR_INPUT
ipElement : ITcVnContainer;
END_VARIn 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_IFDie benötigten Variablen sind wie folgt deklariert:
VAR
nNumberOfElements : ULINT;
hr : HRESULT;
END_VARSowohl der Funktionsblock selbst als auch die Methode Condition müssen das Compiler-Attribut {attribute 'c++_compatible'} enthalten.