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 The length of the array is defined by the constant |
ipHelper | Auxiliary interface pointer that is used to fill the main container |
ipContainerBase | Container in which the sub-containers defined in |
fbCondition | Function block that contains the filter condition. |
ipContainerFiltered | Container that, at the end, is to contain only the sub-containers from |
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'}
.