Skip to content

Tuple OperationsπŸ”—

Operations are usually described assuming atomic tuples. If the tuple contains more than one element, most operators work as follows:

  • If one of the tuples is of length 1, all elements of the other tuples are combined with that single value for the chosen operation.

  • If both tuples have a length greater than 1, both tuples must have the same length, otherwise a runtime error occurs. In this case, the selected operation is applied to all elements with the same index. The length of the resulting tuples is identical to the length of the input tuples.

  • If one of the tuples is of length 0 ([]), a runtime error occurs.

In Table 1, you can find some examples for arithmetic operations with tuples. Pay special attention to the order in which the string concatenations are performed. The basic arithmetic operations in HDevelopEVO are +, -, *, /.
Note that + is a dimorphic operation: If both operands are numeric, it adds numbers. If at least one of the operands is a string, it concatenates both operands as strings.

Table 1: Examples for arithmetic operations with tuples and strings
Input Result
5 * 5`` 25
[5] * [5] 25
[1,2,3] * 2 [2,4,6]
[1,2,3] * 2.1 + 10 [12.1,14.2,16.3]
[1,2,3] * [1,2,3] [1,4,9]
[1,2,3] * [1,2] runtime error
'Text1' + 'Text2' 'Text1Text2'
17 + '3' '173'
'Text ' + 3.1 * 2 'Text 6.2'
3.1 * (2 + ' Text') runtime error
3.1 + 2 + ' Text' '5.1 Text'
3.1 + (2 + ' Text') '3.12 Text'
Conventions

In all following tables, variables and constants have been substituted by letters, which indicate allowed data types. These letters provide information about possible limitations of the areas of definition. The letters and their meaning are listed in Table 2. Operations on these symbols can only be applied to parameters of the indicated type or to expressions that return a result of the indicated type.

Table 2: Symbols for the operation description
Symbol Types
i integer
a arithmetic, that is: integer or real
b boolean
s string
v all types (atomic)
t all types (tuple)

The symbol names i, a, b, and s can denote atomic tuples (tuples of length 1) as well as tuples with arbitrary length.

AssignmentπŸ”—

In HDevelopEVO, an assignment is treated like an operator. To use an assignment, you can either type it directly into the program window or use the operator assign(Input, Result). In the program text, the assignment is represented by the usual syntax of the assignment operator:
Result := Input

The following example outlines the difference between an assignment in C syntax and its transformed version in HDevelopEVO:

The assignment in C syntax:

u = sin(x) + cos(y);

Can be directly typed in the program window as:

u := sin(x) + cos(y)

Another possibility would be to use the assignment operator:

assign (sin(x) + cos(y), u)

If the result of the expression does not need to be stored in a variable, the expression can directly be used as input value for any operator, or be typed into the program window. Therefore, an assignment is necessary only if the value has to be used several times or if the variable has to be initialized, for example for a loop.

Modifying tuple elementsπŸ”—

Inside the program window, enter the following to change the an element of a tuple:

Result[Index] := Value

Another possibility would be to use the assignment operator assign_at:

assign_at (Index, Value, Result)

Example

Areas := [1,2,3]
Areas[1] := 9

sets Areas to [1,9,3].

To construct a tuple with assign_at, usually an empty tuple is used as initial value and the elements are inserted in a loop:

Tuple := 
for i := 0 to 5 by 1
  Tuple[i] := sqrt(real(i))
endfor

As you can see from the examples, the indices of a tuple start at 0.

An insertion into a tuple can generally be performed in one of the following ways:

  • In case of appending the value at the β€œback” or at the β€œfront”, the tuple concatenation operation β€œ,” (comma) can be used. Here, the operator assign is used with the following parameters:

    assign ([Tuple,NewVal],Tuple)
    

    which is displayed as

    Tuple := [Tuple,NewVal]
    
  • If the index position is somewhere in between, the operator tuple_insert has to be used.

    To insert the tuple [11,12,13] into the tuple [1,2,3] at position 1, use

    tuple_insert ([1,2,3], 1, [11,12,13], Result)

    or as in-line operation

    Result := insert([1,2,3], 1, [11,12,13])
    

    resulting in [1,11,12,13,2,3].

In the following example, regions are dilated with a circle mask and afterwards, the areas are stored into the tuple Areas. In this case, the operator assign_at is used.

Example

read_image (Mreut, 'mreut')
threshold (Mreut, Region, 190, 255)
Areas := 
for Radius := 1 to 50 by 1
  dilation_circle (Region, RegionDilation, Radius)
  area_center (RegionDilation, Area, Row, Column)
  Areas[Radius-1] := Area
endfor

At first, the variable Areas has to be initialized to avoid a runtime error. In the example, Areas is initialized with the empty tuple ([]). Instead of assign_at, the operator assign with tuple concatenation could be used, because the element is appended at the end of the tuple:

Areas := [Areas,Area]

More examples can be found in the program assign.hdev.

Basic Tuple OperationsπŸ”—

A basic tuple operation can be selecting one or more values, combining tuples (concatenation), or getting the number of elements. See Table 3 for operations on tuples containing control data.

Table 3: Basic operations on tuples (control data) and the corresponding HALCON operators
Operation Meaning HALCON operator
t := [t1,t2] concatenate tuples tuple_concat
i := \|t\| get number of elements of tuple t tuple_length
v := t1[t2] select element t2 of tuple t1 tuple_select
t := t1[t2,t3] select elements t2 and t3 of tuple t1 tuple_select
t := t[i1:i2] select from element i1 to element i2 of tuple t tuple_select_range
t := subset(t1,t2) select elements specified in t2 from t1 tuple_select
t := firstn(t,i) select first elements from t up to index i tuple_first_n
t := lastn(t,i) select elements from t from index i to the end tuple_last_n
t := select_mask(t1,t2) select all elements from t1 where the corresponding mask value in t2 is greater than 0 tuple_select_mask
t := remove(t,i) remove elements specified in i from t tuple_remove
t := insert(t1,i,t2) insert elements from t2 at position i in t1 tuple_insert
i := find(t1,t2) get indices of all occurrences of t2 within t1 (or -1 if no match) tuple_find
i := replace(t1,t2,t3) replace elements tuple_replace
i := find_first(t1,t2) get indices of the first occurrences of t2 within t1 (or -1 if no match) tuple_find_first
i := find_last(t1,t2) get indices of the last occurrences of t2 within t1 (or -1 if no match) tuple_find_last
t := uniq(t) discard all but one of successive identical elements from t tuple_uniq
t := [i1:i2:i3] generate a sequence of values from i1 to i3 with an increment value of i2 tuple_gen_sequence
t := [i1:i2] generate a sequence of values from i1 to i2 with an increment value of one tuple_gen_sequence
t := gen_tuple_const(i,t) generate a tuple with i values set to t tuple_gen_const
t := rep(t,i) repeat t i times tuple_repeat
t := rep_elem(t,i) repeat t i times elementwise tuple_repeat_elem

The concatenation accepts one or more variables or constants as input. They are all listed between the brackets, separated by commas. The result again is a tuple.
Note the following: [[t]] = [t] = t.

Number of Elements and IndexesπŸ”—

|t| returns the number of elements of a tuple. The indices of elements range from zero to the number of elements minus one (|t|-1). Therefore, the selection index has to be within this range.1

Tuple := [V1,V2,V3,V4]
for i := 0 to |Tuple|-1 by 1
  fwrite_string (FileHandle,Tuple[i]+'\n')
endfor

Example

In the following, the variable Var contains [2,4,8,16,16,32]:

Input Result
[1,Var,[64,128]] [1,2,4,8,16,16,32,64,128]
| Var| 6
Var[4] 16
Var[4,5] [16,32]
Var[2:4] [8,16,16]
subset(Var,[0,2,4]) [2,8,16]
select_mask(Var,[1,0,0,1,1,1]) [2,16,16,32]
remove(Var,[2,3]) [2,4,16,32]
find(Var,[8,16]) 2
uniq(Var) [2,4,8,16,32]

Other examples can be found in the program tuple.hdev. The HALCON operators that correspond to the basic tuple operations are listed in Table 3.

Tuple Operations for Iconic DataπŸ”—

The direct operations mentioned in the previous section cannot be used for iconic tuples. Iconic objects cannot be selected from a tuple using [] and their number cannot be directly determined using ||.

For iconic data, equivalent HALCON operators exist. In Table 4, you can see tuple operations that work on control data (applied via assign or assign_at) and their counterparts that work on iconic data (which are independent operators). The symbol t represents a control tuple, and the symbols p and q represent iconic tuples.

Table 4: Equivalent tuple operations for control and iconic data
control iconic
[] gen_empty_obj()
[t1,t2] concat_obj(p1, p2, q)
| t | count_obj(p, num)
t[i] select_obj(p, q, i+1)
t[i1:i2] copy_obj(p, q, i1+1, i2-i1+1)

Tuple CreationπŸ”—

The simplest way to create a tuple, as mentioned in Control Types and Constants, is the use of constants together with the operator assign (or, in case of iconic data, one of its equivalents shown in Table 4):

assign (,empty_tuple)
assign (4711,one_integer)
assign ([4711,0.815],two_numbers)

This code is displayed as

empty_tuple := 
one_integer := 4711
two_numbers := [4711,0.815]

This is useful for constant tuples with a fixed (small) length. More general tuples can be created by successive application of the concatenation or the operator together with variables, expressions, or constants. If you want to generate a tuple of length 100, where each element has the value 4711, it can be done like this:

tuple := 
for i := 1 to 100 by 1
  tuple := [tuple,4711]
endfor

Because this is not very convenient, a special function called gen_tuple_const is available to construct a tuple of a given length, where each element has the same value. Using this function, the program from above is reduced to:

tuple := gen_tuple_const(100,4711)

A fast way to create a sequence of values with a common increment is to use tuple_gen_sequence. For example, to create a tuple containing the values 1..1000, use

tuple_gen_sequence(1,1000,1,Sequence)

An alternative syntax to the above is to write:

Sequence := [1:1:1000]

If the increment value is one (as in the above example), it is also possible to write:

Sequence := [1:1000]

If we want to construct a tuple with the same length as a given tuple, there are two ways to get an easy solution. The first one is based on gen_tuple_const:

tuple_new := gen_tuple_const(|tuple_old|,4711)

The second one is trickier and uses arithmetic functions:

tuple_new := (tuple_old * 0) + 4711

Here, we first get a tuple of the same length with every element set to zero. Then, we add the constant to each element.

If the tuples have different values, we have to use the loop version to assign the values to each position:

tuple := 
for i := 1 to 100 by 1
  tuple := [tuple,i*i]
endfor

In this example, we construct a tuple with the square values of \(i\) from \(1^2\) to \(100^2\).


  1. In contrast, the index of objects, for example, select_obj, ranges from 1 to the number of elements. ↩