Selections of container elements

In this sample, container elements are filtered with the help of a user-defined condition. The function F_VN_CopyContainerElementsConditional_ITcVnContainer is used for this, as the container elements are in turn containers. If the container elements are iterators, the function F_VN_CopyContainerElementsConditional_ITcVnForwardIterator can also be used for this.

Explanation

If the elements of multidimensional containers are to be filtered, this can quickly result in a great deal of programming effort due to the access to the sub-elements. To counteract this, TwinCAT Vision provides a function precisely for this, which is used as follows, for example:

A function block is created that implements the interface ITcVnCustomElementCondition_ITcVnContainer. This interface possesses the Condition method, which accepts an element of the type ITcVnContainer. The filter condition that is to be applied to the element is defined in the implementation of this method. The function block with the filter condition is then transferred to the function F_VN_CopyContainerElementsConditional_ITcVnContainer in order to carry out the filtering of all elements of a container. In this sample the elements are filtered according to whether they possess more than five sub-elements.

Application

By way of example, the sub-containers of a container are filtered according to how many elements each of them possesses. Specifically, only those sub-containers that have more than five elements are to be accepted into a new container. The structure of the container can be varied by means of the array aContainerStructure. The elements indicate how many sub-elements each sub-container has. If the number of sub-containers itself is likewise varied, the constant cNumberOfSubContainers must be matched to it.

Program

MAIN

First of all a constant integer is defined in order to be able to simply vary the sub-containers to be filtered:

VAR CONSTANT
    cNumberOfSubContainers  :   INT := 5;
END_VAR

Then all necessary variables are declared:

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 of the container structure. An array of the length 5 with the initialization values [2, 7, 3, 5, 12] means, for example, that a container with 5 sub-containers is to be created in the sample. The first sub-containers is to have 2 elements, the second sub-container 7 elements and so on.

The length of the array is defined by the constant cNumberOfSubContainers.

ipHelper

Auxiliary interface pointer that is used to fill the main container ipContainer with sub-containers.

ipContainerBase

Container in which the sub-containers defined in aNumberOfElement are created.

fbCondition

Function block that contains the filter condition.

ipContainerFiltered

Container that, at the end, is to contain only the sub-containers from ipContainer that fulfill the filter condition.

nSelectedContainers

Integer that indicates how many sub-containers actually fulfill the filter condition.

hr

Status variable of the type HRESULT.

i

Auxiliary variable

In the program part, a container is created that is filled with the sub-containers defined above. The calling of F_VN_ReserveContainerMemory is optional and only serves to achieve a better 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

The container that has just been created is then filtered. The function block with the self-written condition is specified as the filter condition.

hr := F_VN_CopyContainerElementsConditional_ITcVnContainer(
    ipSrcContainer      :=  ipContainerBase,
    ipDestContainer     :=  ipContainerSelection,
    ipConditionFB       :=  fbCondition,
    hr);

In order to comprehend the functionality of the function, the elements that fulfill the described condition are counted. The variable nSelectedContainers now changes depending on the sub-containers and the filter condition.

hr := F_VN_GetNumberOfElements(ipContainerSelection, nSelectedContainers, hr);

In this case the number indicates how many sub-containers have more than five sub-elements.

Function block with filter condition

The filter condition is transferred as a function block with a Condition method. So that a self-written function block can be transferred to the function, it must implement the interface ITcVnCustomElementCondition_ITcVnContainer:

FUNCTION_BLOCK FB_ConditionMoreThanFive IMPLEMENTS ITcVnCustomElementCondition_ITcVnContainer

The Condition method defines the filter condition. It is called individually for each sub-container. Depending on whether the return value is TRUE or FALSE, the respective sub-container is accepted into the new container or not.

METHOD Condition : BOOL

With each call of the method, the current sub-container is transferred as the input parameter:

VAR_INPUT
    ipElement           :   ITcVnContainer;
END_VAR

In this case an element is to be accepted if it has more than five sub-elements. For this purpose the number of sub-elements is calculated and, depending on the result, the value TRUE or FALSE is returned.

hr := F_VN_GetNumberOfElements(ipElement, nNumberOfElements, hr);
IF FAILED(hr) OR nNumberOfElements <= 5 THEN
    Condition := FALSE;
ELSE
    Condition := TRUE;
END_IF

The required variables are declared as follows:

VAR
    nNumberOfElements   :   ULINT;
    hr                  :   HRESULT;
END_VAR

Both the function block itself and the Condition method must contain the compiler attribute {attribute 'c++_compatible'}.