Positioning and Orientation
<-Previous | ^UP^ | Next->
Positioning and Orientation
<-Previous | ^UP^ | Next->
For geometric objects, GendL has a Cartesian axis system to specify coördinates in the X, Y and Z dimensions.
When specifying a geometric object, a number of basic principles apply:
- The axis system applies to the object, but may be moved or re-oriented relative to other objects.
- The center of the object is co-incident with the origin of its axis system #(0.0 0.0 0.0).
- The length dimension of the geometric object correponds with the Y axis.
- The width dimension of the geometric object corresponds with the X axis.
- The height dimension of the geometric object corresponds with the Z axis.
Positioning
By default, the positioning of the center point of a child object is
identical to the center point of its parent. (This is because center is declared internally to be trickle-down. We will cover more about trickle-down-slots and the defaulting
slot modifier later.
If you would like to override the default center which "trickles down" from the parent or a higher ancestor in the tree, then you may position them explicitly, either in an absolute manner (i.e. relative to the global coördinate system), or in a relative manner (i.e. relative to another object, typically the direct parent), by feeding an explicit :center input into the child. Depending on how you specify that :center, the child will end up positioned relative to the parent (or to another object), or relative to the global coördinate system.
Consider the following object definition and its display in Geysr:
(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))))
box-1 does not specify a center, so its center will default to that of its parent, or #(0.0 0.0 0.0). Note in this case the parent (assembly-1) is defined to include the base-object mixin - this provides the basic coördinate system without providing any explicit geometry.
box-2 defines an explicit center using the GendL make-point macro. The coördinates of this point are defined in absolute global coördinates by passing numbers directly into that make-point macro.
GDL-USER> (make-point 2 2 2)
#(2.0 2.0 2.0)
box-3 defines its center relative to the center of box-2 instance by using the translate-along-vector function. translate-along-vector takes the following inputs:
- a 3d-point which is to be translated, in this case the center of box-2;
- a vector which specifies the direction of translation - in this case we are translating in the direction pointed to by an arrow from the origin to one unit in the X direction, one unit in the Y direction and zero units in the Z direction;
- the distance by which the point it to be translated
GDL-USER> (setq self (make-object 'assembly-2))
#<ASSEMBLY-2 #x210462875D>GDL-USER> (translate-along-vector (the box-2 center) (make-vector 1 1 0) 5)
#(5.535533905932738 5.535533905932738 2.0)
Sometimes it is useful to access points and vectors relative to the reference box of the objects you create. When you create a box for example (whose reference box is identical with itself), the faces of the box are identified as :top, :bottom, :left, :right, :front and :rear
Various points relative to the bounding-box may then be accessed using the GendL :functions face-center, edge-center and vertex, whilst vectors may be created normal to a face using the GendL :function face-normal-vector.
So if you wished to position the 3 boxes in assemby-3 such that the rear and front faces of adjoining boxes were coincident, you could achieve that with the following code:
(define-object assembly-3 (base-object):objects((box-1 :type 'box:length 5:width 1:height 1)(box-2 :type 'box:length 10:height 5:width 3:center (translate-along-vector(the box-1 (face-center :rear))(the box-1 (face-normal-vector :rear))(half (the-child length))))(box-3 :type 'box:length 5:height 5:width 5:center (translate-along-vector(the box-2 (face-center :rear))(the box-2 (face-normal-vector :rear))(half (the-child length)))))
Two important concepts are also introduced here
- When referencing a GendL function, you can use a normal referencing chain, but if the function has arguments then you need to wrap that function and its arguments in parentheses. We see examples of this when using the face-center and face-normal-vector functions
GDL-USER> (setq self (make-object 'assembly-3))
#<ASSEMBLY-3 #x210494BB9D>GDL-USER> (the box-1 (face-center :rear))
#(0.0 2.5 0.0)GDL-USER> (the box-1 (face-normal-vector :rear))
#(0.0 1.0 0.0)
- To refer to messages in the child object instances, you can use the macro the-child. In the case of box-2 and box-3, we want to translate the point by half of each one's own length
. These points and vectors could, of cource be computed explicitly in the parent object. However by computing them using expressions relative to the child instances, you can ensure that the design will "hang together" as intended, i.e. that front and rear faces of adjoining boxes will continue to be touching, even if the center and/or orientation of the first box is changed.
Orientation
By default, the orientation of a child object is the same as that for its parent object. However, you can override that by specifying an :orientation as an input to the child instance. To compute an orientation, you can use the GendL alignment function, which will yield an orientation by aligning one, two, or three specified axes of our child instance with one, two, or three specified vectors.
If you compute those specified vectors relative to the coördinate system of the current self (i.e. the parent, then the resultant orientation will also end up relative and will automatically respond to any changes.
The alignment function requires at least one axis-vector pair, but optionally can accept an additional two axis-vector pairs, providing the second axis is orthogonal to the first and the third axis is orthogonal to the first and second
In the example below, the :rear axis of box-2 (aligned with the global positive Y axis, #(0.0 1.0 0.0), is aligned with the vector normal to the :top face of box-1. The center of each box remains the default #(0.0 0.0 0.0).
(define-object assembly-4 (base-object):objects((box-1 :type 'box:length 5:width 1:height 1)(box-2 :type 'box:length 5:width 1:height 1:orientation (alignment :rear (the box-1 (face-normal-vector :top))))))
In the example below, which is an extension of assembly-4, by being more explicit about the :orientation being fed into box-2 and box-3, and aligning them with the :rear axis of each's neighbor, you can ensure that all boxes remain touching regardless of what :orientation may be specified in the future for box-1.
(define-object assembly-5 (base-object):objects((box-1 :type 'box:length 5:width 1:height 1:orientation (alignment :rear (the (face-normal-vector :right))))(box-2 :type 'box:length 10:height 5:width 3:orientation (alignment :rear (the box-1 (face-normal-vector :rear))):center (translate-along-vector (the box-1 (face-center :rear))(the box-1 (face-normal-vector :rear))(half (the-child length))))(box-3 :type 'box:length 5:height 5:width 5:orientation (alignment :rear (the box-2 (face-normal-vector :rear))):center (translate-along-vector (the box-2 (face-center :rear))(the box-2 (face-normal-vector :rear))(half (the-child length)))
Points and Vectors
GendL provides a number of functions for manipulating points and vectors. The Resources file points-and-vectors.lisp gives examples of the most common ones, summarised below. Note that this is not an exhaustive list.
Vectors
- make-vector - creates a vector
- face-normal-vector - (GendL function) returns a vector normal to a specified face
- subtract-vectors - takes 2 3d points and returns the vector from the second point to the first point
- cross-vectors - returns a vector that is orthogonal to the 2 input vectors
- rotate-vector - rotates a vector around a normal vecort by an angle specified in radians
- rotate-vector-d - rotates a vector around a normal vecort by an angle specified in degrees
- angle-between-vectors - returns the angle between 2 vectors in radians
- angle-between-vectors-d - returns the angle between 2 vectors in degrees
Points
- make-point - creates a point
- 3d-distance - the distance between 2 points
- translate-along-vector - returns a point resulting from translating the specified point along the specified vector by the specified distance
- face-center (GendL function) - returns a point which is the center of a specified reference-box face
- edge-center (GendL function) - returns a point which is the center of a specified reference-box edge (coincidence of 2 specified reference-box faces)
- vertex (GendL function) - returns a point which is a vertex (coincidence of 3 specified reference-box faces)
- coincident-points? - returns T is 2 points are within a given tolerance of each other
- get-x, get-y, get-z - returns the X, Y or Z value of a specified point
See the online documentation relating to the :GEOM-BASE package for exact syntax and further details.