Sequences of Objects
In many cases you may have child objects which are of the same type and only differ in the values of inputs they are given. If you know how many objects there are (and assuming not too many), you could define them independently and give each its own name, as we did for example in assembly-2
(define-object assembly-2 (base-object):objects((box-1 :type 'box:length 5:width 1:height 1)(box-2 :type 'box:length 10:height 5:width 3:center (make-point 2 2 2))(box-3 :type 'box:length 5:height 5:width 5:center (translate-along-vector (the box-2 center)(make-vector 1 1 0)5))))
However, there may be times when you do not know in advance how many objects there will be, or you may want to compute the properties of each object based on its identity (e.g. based on its numerical index). In either of these cases, a :sequence of objects may be appropriate.
A :sequence defines an ordered group of objects. There are four types of :sequences:
- A standard sequence - the object specification is defined with the input :sequence (:size <number-expression>) and a number of objects equal to the value of <number-expression> will be created
- A radial sequence - the object specification is defined with the input :sequence (:radial <number-expression>) and a number of objects equal to the value of <number-expression> will be created
- A variable sequence - Allows objects in the groups to be programatically added and deleted. The object specification is defined with the input :sequence (:indices <list-of-indices>)
- A matrix sequence - quantification is generated as a result of specifying :sequence (:matrix <direction-keyword-1> <number-1> <direction-keyword-2><number-2>) in an :objects specification. The direction-keywords can be one of: :lateral, :longitudinal, or :vertical.
In this tutorial we will cover only standard and radial sequences.
When a sequence is generated, each object is assigned a zero-based index number. When referencing the object from outside the :objects specification, its index number must be included with the object name between parentheses. Likewise, from inside the :objects specification, each child can reference its own index slot (or any other of its slots) by using the reference macro the-child.
So consider the following code which defines a sequence of three boxes, each of which has its length and center defined based on its index number.
(define-object assembly-6 (base-object):input-slots((number-of-boxes 3)):computed-slots((first-box-volume-1 (the (boxes 0) volume))(first-box-volume-2 (the-object (the boxes last) volume))(second-box-volume (the (boxes 1) volume))(last-box-volume-1 (the (boxes (- (the number-of-boxes)) volume)))(last-box-volume-1 (the-object (the boxes last) volume))):objects((boxes :type 'box:sequence (:size (the number-of-boxes)):length (+ 2 (* (the-child index) 3)):width 2:height 1:center (make-point (* (the-child index) 6) 0 0))))
Note in the Geysr tree, the the names of the child instances include the index number of each.
Also note in the code example the diferent ways to access the object instances and their messages:
- Using an index -
(the (boxes <index-number>) volume), where
(boxes <index-number>), i.e. the combination of object name and index enclosed in parentheses, evaluates to the object instance which is the desired element of the sequence.
- Using first and last - these are :computed-slots in the sequence definition which return the first and last objects in the sequence.
(the boxes)refers to the whole sequence.
(the (boxes <index>))refers to a specific element within that sequence
GDL-USER> (setq self (make-object 'assembly-6))#<ASSEMBLY-6 #x21045E42CD>
GDL-USER> (the boxes)#<GENDL::STANDARD-SEQUENCE #x21045E3E9D>
GDL-USER> (the (boxes 0))#<BOX #x21046CBA5D>
GDL-USER> (the boxes first)#<BOX #x21046CBA5D>
GDL-USER> (the boxes last)#<BOX #x21082334D8>
GDL-USER> (the (boxes 1) previous)#<BOX #x21046CBA5D>
Consider the following code, identical to the standard sequence example except the :sequence definition is changed to :radial and the :center definition is removed.
(define-object assembly-7 (base-object):input-slots((number-of-boxes 3)):objects((boxes :type 'box:sequence (:radial (the number-of-boxes)):length (+ 2 (* (the-child index) 3)):width 2:height 1
The Geysr image is with View..Perspective..Top enabled to show the effect of the :radial definition. Essentially a :radial sequence orients each obect so it is rotated 360/[number-expression] degrees compared to its predecessor. You can of course override this default behavior by feeding an explicit center and/or orientation into each element.