2 Structure of a GLG Drawing
When you look at a GLG drawing, you see a collection of colored shapes that may be moving and changing according to a set of predefined instructions. This picture, however, is only the surface representation of the internal structure of a drawing. Internally, a GLG drawing actually consists of an arrangement of abstract data objects and the links between them. When you edit a drawing with the GLG Graphics Builder, or animate it with a program, you are accessing and modifying data within this data structure. The rendering of this elaborate internal structure into a simple two-dimensional image is the last and most superficial of the many steps that go into animating a drawing.
Of course, the two-dimensional image is not only what you see when the drawing is displayed, but also what you see when you create and edit a drawing. To understand what is really going on when you edit or operate a GLG drawing, however, you must understand the underlying structure of that drawing. This chapter introduces the basic elements of that structure.
The concept of the object is fundamental to GLG. Every component of a GLG drawing may be considered an object, and a drawing is nothing more than an arrangement of these objects and the links between them. The definition of a GLG object is similar to that of an object in C++ or some other object-oriented programming system. That is, an object is simply a thing that may be represented as a collection of data and the methods used to access that data. Some objects have a graphical appearance. For example, a polygon appears on the screen as a flat shape bounded by a line. Within the context of the GLG Toolkit, however, it is more useful to think of that polygon as a simple collection of points, colors, and line types (the data) and interfaces to access these data (the methods). Since the graphical appearance of the object is completely defined by its data, the program can control the way the object is rendered on the screen by changing these data using just a handful of methods common for all GLG objects.
An object's data are referred to as its attributes. Using the same example, a polygon's color, the width of its border lines, and the position of its vertex points, are each attributes of the object. Most of these attributes are stored as data objects, which keep the value, name and some other properties of each attribute. The notion of an attribute in GLG is recursive, as the attribute's value and name are attributes of an attribute object itself.
Some properties of an object are kept as plain data instead of using data objects. For example, the name attribute is kept as a character string to avoid infinite recursion of a name object having its own name attribute, and so on.
An object may contain other objects. An object that contains other objects is said to be their parent object. An object contained in some parent object is said to be its child object. We have already seen one example of this, since attributes represented by data objects are the children of the parent objects they describe. Other objects, such as the group, are designed to be containers of other objects. This arrangement of parent objects and their children defines the object hierarchy, about which more is said below.
In addition to a polygon, there are several other GLG graphical objects, such as circles, markers, viewports, and text objects. These are the objects that make up the visible aspect of a GLG drawing.
GLG differs from other drawing systems, however, in its assortment of non-graphical objects. You cannot see these objects, but they are a crucial part of the organization of the drawing. For example, a group object acts as a "container" for other objects, a series object defines a group of identical objects, a frame defines a set of anchor points to which other objects may be attached, and a transformation object contains directions for modifying the object to which it is attached.
Resources and Objects
To access an object at run-time, it has to be named. A named object becomes a resource which can be accessed by its name using the programming API. Resource mechanism provides a convenient way to manipulate objects in the drawing at run-time. In the Graphics Builder, the Resource Browser may be used to browse resources of the drawing.
The Attribute Object
An object is completely described by its attributes. A unique set of attributes defines a unique object. The particular set of attributes that make up an object is dependent on the type of the object. For example, a text object has a font, a color, a position, an angle, and so on, while a polygon has a fill color, a line width, and vertex positions. The term property is often used as a synonym for attribute.
Most of the attributes of a GLG object are themselves objects. In the same way that a polygon is a collection of positions, colors, and line widths, an attribute is also a collection of information. The information contained in an attribute object includes the data value of the attribute object, its data type and name. The type indicates whether the data value is a double-precision scalar number (signified throughout the GLG documentation by a D), a position in a three-dimensional coordinate system (G for "geometrical"), or a character string (S). The color values use G data type as well, since they represent coordinates in RGB color space.
The attribute's name is used to access the attribute as a resource. Named attributes become resources which can be accessed at run-time to supply dynamic data. In the Graphics Builder, the Resource Browser may be used to browse resources of individual objects or of the whole drawing. Each attribute also has a default attribute name which depends on the attribute type and may be used to access unnamed attributes. For example, the default attribute name of the polygon's line width is LineWidth. While attributes can always be accessed using their default attribute names, attribute names may be used to assign custom, application specific names to some attributes. For example, the LineWidth attribute may be given a custom name box_width. Attribute names take precedence over default attribute names, so it is a good idea to use names different from the default attribute names.
Note that there are several multi-valued data values used in a GLG drawing. Data flags, line types, font selections and so forth are all displayed as selections from a list of options. Internally, these are all D values, stored as the simple index to the table of choices. For binary attributes, where the value is TRUE or FALSE, or YES or NO, a zero value indicates false (NO) and any other value-usually one-indicates true (YES). One exception to this rule is the Visibility attribute of an object. This attribute is a floating point value that can range from 0 to 1 and defines not only the object visibility (1-visible, 0-invisible), but also its transparency.
To avoid an infinite regression, the type, name and data values and some other attributes of the attribute object are not objects themselves. Among other such attributes are the HasResources flag, the Global flag, and the flag.
Resources and Attributes
GLG uses the terms attribute and resource to refer to the same object. There is, however, a distinction between the two that involves the method of access. An object such as a polygon has several attributes, and these are accessible by their default names. You can think of these as places within its data structure for data to modify an aspect of the polygon. For example, a blue polygon has a FillColor attribute that specifies its color is blue. This object consists of a data type (G), and a data value (0 0 1), and some housekeeping data.
The FillColor default attribute name is not an independent name. This name is not part of the attribute object's data. It only means something relative to the polygon to which it refers. For example, if a second polygon has its edge color attribute constrained to the fill color of the first polygon, the data object may be accessed either as FillColor of the first polygon or as EdgeColor of the second polygon. However, the attribute object can have its own name. If you name that object, it becomes a resource, and is accessible by its own name rather than only by its connection to the parent polygon.
Consider the diagram below. A polygon's data is depicted with three attributes: the FillColor, LineWidth, and LineType. (Of course a polygon has more attributes than this, but we have omitted most of them for clarity.) The LineWidth and LineType attributes are represented by identical objects; they are each given their meaning-and their default names-by where they are attached to the parent polygon object. The important point is that the default attribute names are recorded in the parent polygon, not in the attribute object data.
The FillColor attribute object, on the other hand, has both a default attribute name, given it by its position relative to the parent polygon, and its own name, fill_color, recorded in its own data. This attribute is a named resource, accessible independently from the parent polygon.
Supplying Data for Animation
Since everything in a GLG drawing is an object, and any attribute of an object can be accessed as a named resource, it becomes quite simple to change any aspect of a drawing by modifying its resources. For example, you can change the color of a polygon, rotate a group, move a viewport, even change the number of data samples in a graph by changing drawing resources. This is, in fact, the mechanism by which GLG drawings are animated. A program animates a GLG drawing by changing named resources with data from an external source.
Alternatively, data tags may be used for supplying data from specified data sources as described in Tags for Data Connectivity below.
Hierarchy of Objects
The arrangement of GLG objects in a drawing can be visualized as a hierarchy. Specialized container objects like groups and viewports are collections of disparate objects, while any GLG object can be said to contain its attribute objects.
Because a GLG object may contain other objects, the attributes of those secondary objects may be considered subsidiary attributes of the first object. This arrangement defines a drawing's object hierarchy. For example, consider a group object that contains two polygons.
Call the parent object GRP, and call the polygons PY1 and PY2. Each polygon has an attribute called FillColor that indicates the color of the interior of that polygon. (This is part of the definition of the polygon object.)
You might also think of the GRP group as containing two "attributes," namely PY1 and PY2. These objects in turn contain other attributes, like FillColor. In this case, the default name of the FillColor attribute of the PY1 polygon would be PY1/FillColor. From a point outside the GRP group itself, the fill color of the PY1 polygon would be called GRP/PY1/FillColor. In other words, there is a hierarchy of objects in a GLG drawing precisely comparable to the hierarchy of directory and file names used to denote the location of a file on a disk.
Hierarchy of Resources
The object hierarchy is a fixed representation of the parent-child relationships between objects in a GLG drawing. The FillColor attribute attached to PY2 is always attached to PY2. In addition to the object hierarchy, however, a GLG drawing contains a resource hierarchy which represents relationships between the names of objects in a drawing. This hierarchy may or may not reflect the underlying reality of the object hierarchy. This can be quite useful when you wish to shield a user from a very complex object hierarchy, or when it is conceptually simpler to address a drawing in terms defined by the resources. You typically use resources to animate a drawing.
An example will illustrate the use of having two separate hierarchies to represent the same objects. Using the objects in the drawing shown in the previous section, there is another way to consider the relationship between the two FillColor attributes and the GRP object. Suppose that the two polygons in the group are used to render two faces of a three-dimensional object. A cube, created by joining two-dimensional objects together at their edges, is an example of this technique. The object hierarchy would reflect the fact that this is a composite object, but we can construct the resource hierarchy so that it will appear to be a single object. In this case, one would want to specify one color for the entire object, rather than colors for each face, and the names PY1 and PY2 would likely not be useful for such an object.
In this case, to make the drawing act as you might expect, the color should be an attribute of the group. This way, the cube's color may be changed by accessing a resource called GRP/fill_color. Of course this would not reflect the reality of the object hierarchy, but you can arrange a GLG drawing this way by modifying the resource hierarchy. (We have here renamed the attribute for reasons explained below.)
To make the resources of the child polygons appear to belong to the parent group, you can make the polygons resource-transparent. The resources of a resource-transparent object appear to belong to its parent. This way, the color attribute of the polygons will appear to be an attribute of the group itself.
Whether or not an object is resource-transparent is controlled by an attribute of that object called the HasResources flag. This flag indicates whether an object has resources of its own (HasResources=YES) or if its resources appear to belong to its parent (HasResources=NO). More specifically, a resource-transparent object's resources appear to belong to the first object above it in the resource hierarchy that is not itself resource-transparent.
Note that an object's default attribute names appear in the resource hierarchy as its children no matter if the object is resource-transparent or not. That is, even if PY1 is resource-transparent, its FillColor attribute will appear under it. If we name the attribute fill_color, we can make it appear at different places in the resource hierarchy by modifying the resource-transparency of the parent object.
Since resource names are used to access objects, all resource names on the same level of hierarchy must be unique to avoid resource name conflicts. If two or more resources on the same hierarchy level have the same name, the first found resource object will be returned when the resource is accessed. Resources on different hierarchy levels may have the same names. For example, if both PY1 and PY2 polygons have HasResources=YES, each of the polygons may have its own fill_color resource accessible as PY1/fill_color for the first polygon and PY2/fill_color for the second one. Using such identical resource hierarchies is a powerful technique for drawings with a large number of similar objects.
The following diagram represents the hierarchy of objects in the drawing on page 38. If each object has resources (the HasResources flag is set to YES), and all objects are named, then the resource hierarchy is identical to this object hierarchy. Again, note that to avoid confusion about default attribute names (which always appear at the object level regardless of the HasResources flag), we have renamed the attributes shown in the diagram.
The following diagram shows the case where polygon PY2 is resource transparent. Here, all the resources of the transparent polygon appear to be resources of the parent.
Note that the name of a resource transparent polygon is not used to access any of its named resources, but may still be used to access its named or unnamed attributes using their default names. Also, the default names of the PY2 polygon attributes, such as FillColor, will still appear as resources of that polygon. This can be experimented with using the Builder's Resource Browser.
The Alias object may also be used to map a short logical name to an arbitrary resource hierarchy, defining custom shortcuts. Refer to the Alias section on page 155 for details. The Builder's Resource Browser provides controls to browse named resources, default resource names and aliases in any combination.
Organizing resources in hierarchies is a great way to simplify the complexity of a large drawing. When such drawing is browsed in the Builder using the Resource Browser, only the top-level resources will be visible on the drawing's level, and their sub-resources will be displayed only when a particular resource is selected. GLG does not have any limit for the depth of the resource hierarchies, and each of the sub-objects in the drawing may have its own hierarchy of resources inside it, and so on. While the resource mechanism is very flexible and powerful, the application has to know the exact path of all resources it needs to access. Tags, described in the next chapter, provides an alternative data access mechanism with a flat hierarchy.
Tags for Data Connectivity
A data tag may be attached to any attribute or resource object for an alternative tag-based access to the resource value. In addition to accessing an attribute object by a hierarchical resource name, it may be accessed by a global tag. Unlike resources, which are hierarchical and defined by a resource path, tags are global and can be accessed directly without specifying a path. The tags provide a convenient mechanism for defining data connectivity for run-time animation from the application data sources.
Tags are similar to resources and, same as resources, are used to update attributes with new data at run time. There is one important difference, though: while resources are hierarchical, the tags are global and their hierarchy is flat. All tags defined in the drawing are visible at the top level. Tags provide a way to associate a name of a data source variable with the object attribute that needs to be updated with data. In the Builder or the HMI Configurator, the Tag Browser may be used to view tags of individual objects, as well as all tags defined in the drawing.
A tag object has TagName and TagSource attributes which facilitate data connectivity. The TagSource attribute contains the name of the data source variable that will supply dynamic data for updating the attribute at run time. The TagName attribute defines a tag name which makes it easy for the user to persistently identify the tag regardless of the changes to its TagSource. To change the data source mapping, the user can browse tags and change their tag sources. The tag object also contains the TagComment attribute that may hold any user-defined information associated with the tag. If the attribute the tag is attached to has a range transformation, the tag editing dialog will also allow entering values for the InLow and InHigh parameters of the range transformation. The TagAccessType and TagEnabled attributes provide additional control over the use of a tag in an application. Refer to the Tag section on page 153 for more information.
At run time, the application will receive new data and push the new values into the graphics based on the tags defined in the drawing using the SetTag methods of the GLG API, which take the tag source and the new data value. Since tags are global, the tag value can be set via its TagSource without the need to know a resource path of the attribute the tag is attached to. If several attribute objects have tags with the same TagSource, all of them will be updated when a new tag value is supplied at run-time.
GLG API includes methods for supplying data using both tags and resources. Refer to Tag-Based Data Access and Data Connectivity on page 232 for details of different ways of using tags for accessing data. Tags provide the most convenient method for animating the drawing with data. For other tasks, such as accessing objects in the drawing programmatically, resources provide a more flexible and powerful alternative.
In the Builder, the user can browse resources of a drawing and add tags to resources that need to be updated with data at run time. For example, consider a drawing that has an object named Valve1 which has a resource named State controlling the valve's open state, which needs to be updated from the data source variable named valve1_state. The user can select the State resource in the Resource Browser, add a tag to it and set the valve1_state string as the value of the tag's TagSource. At run time, the application will receive data from the valve1_state data source variable and will set the new value for the valve1_state tag when the variable value changes.
The Builder's Tag Browser may be used to examine tags attached to individual objects in the drawing, as well as display a list of all tags defined in the drawing. The Tag Browser has controls for sorting and filtering the tag list by either Tag Names or Tag Sources. The Tag Browser's Unique Tag Sources/Names toggle controls how tags with the same name are displayed. If it is turned on, only one tag will be displayed for each set of tags with the same TagSource or TagName; otherwise, all tag objects will be displayed, including multiple tags with the same TagSource or TagName.
The Tag Export and Tag Import features described in Tag Export and Import Features for Run-Time Tag Mapping on page 234 may be used for modifying all tags defined in the drawing. The tag import file may be used for changing the run-time mapping of all tags defined in the drawing by using the GlgImportTags API method. The GlgCreateTagList API method may be used in an application to query all tags defined in the drawing, as shown in the Simple Viewer source code example, as well as in the SCADA Viewer demo.
After you have made both the polygons in the diagram on page 38 resource-transparent, the colors of the faces are still accessed individually. True, we can now refer to the colors as attributes of the GRP object, but there are still two different polygons with two different colors. Worse, if the names have not been chosen well, there may exist name conflicts, where two different attributes have the same name.
Our goal is to create a complex object with a single color attribute (which may be accessed as a single resource), so the natural next step is to constrain the fill colors of the two polygons to be the same. This way, whenever the color of one is changed, the other one automatically changes as well. A constraint on some object's attribute is simply a requirement that the value of that attribute is always the same as the attribute of the other object.
We now have a group object called GRP that contains a single resource controlling the color of the entire complex object. You can now rename the group to have some more evocative name (for example, "cube"), and forget that it is, in fact, nothing more than a collection of simple graphical objects. Setting the "fill_color" attribute of this "cube" will change the color of all its faces.
The Builder's Edit All group option provides an easy way to attach constraints to attributes of all objects in the group without repeating the constrain operation for each individual object. This is a convenient way to constrain the fill color attributes of all faces of the three-dimensional cube described above.
Constraints may be established between any two attribute objects of the same data type. These constraints connect one branch to another within the object hierarchy. Note that since GLG uses only three data types, a number of surprising constraints are possible. For example, you can constrain a polygon fill color to the position of a polygon vertex in 3-D space, since each is represented as a triple (geometrical) value.
Since point positions are simply object attributes, constraints may also tie one point of an object to another. Each vertex of a polygon is an object, whose value can be constrained to be the same as the value of a vertex of another polygon. You can use this method to construct arbitrarily complex three-dimensional shapes from the simplest components. The constraints tracing option described in the Constraints Tracing section on page 288 may be useful for debugging constraints defined in the drawing.
Note that there is no precedence or hierarchy associated with a constraint. When two attributes are constrained to each other, they behave as the same attribute object with the same name, value and flag settings. This means that one of the original objects, the one being constrained, and all its attributes (name, value, etc.) are thrown away. There is no concept of "master" or "slave" attributes; the resulting attribute may be accessed using any path in the resource hierarchy. For example, both cube/PY1/FillColor, cube/PY2/FillColor and cube/fill_color names may be used to access the constrained fill_color attribute of the above cube example.
In the following figure, the FillColor attribute of one of the polygons is constrained to the FillColor of the other. Now that the constraint has been established, there is no way to tell which object was thrown away and which kept. (Unless one of the original FillColor attribute objects was named, in which case, you can tell from the name of the remaining object. In general, the object you constrain is thrown away, and the one you constrain it to is kept.)
The constraints tracing feature of the GLG Graphics Builder may be used to examine constraints defined in the GLG drawing. When this feature is activated using the Options, Trace/Highlight, Trace Tags, Resources & Constraints menu option, it highlights all objects in the drawing that depend on the selected tag, resource or attribute.
In explaining the structure of a GLG drawing, we have made several references to graphical objects. The following sections describe the components of such an object. For a complete list and description of all the available graphical objects, see GLG Objects.
Note that while the set of atomic GLG objects consists of one- and two-dimensional objects such as lines and polygons, they are placed in a three-dimensional space within a GLG drawing. This can be the source of what initially seems odd behavior. For example, when you move one of the control points of a circle object, it may appear that the circle is being squashed into an ellipse. This is not the case; you are rotating it in space, and an ellipse is what you see when you look at a circle from off-center.
Any graphical object has a set of default attributes that let you see the object rendered on a computer screen. A polygon's color, the width and hue of its border, its position in the drawing (whether it appears to be in front of or behind other objects), and whether it is open or closed, are among the attributes necessary to render that polygon. Most of the attributes in GLG are themselves objects and their editing dialogs in the Graphics Builder may be accessed by pressing the ellipsis button positioned next to an attribute name in the Object Properties dialog.
A special attribute of any graphical object is its Visibility. This controls whether the object is rendered at all in the drawing. The ability to create invisible objects is useful for a variety of tasks. For example, it is usually desirable for a path polygon, which defines a track for another object to move along, to be invisible to the user. You can also use the visibility attribute to implement blinking objects or layers of objects that can be toggled on and off. The visibility attribute may be given values of 1 or 0 to make the object visible or invisible. It may also be set to a fractional value in the range of 0 to 1 to define transparency. For example, setting the visibility to 0.5 will result in an object which is half-transparent. On Windows, transparency is supported only with the OpenGL renderer.
A graphical object contains one or more control points that specify its shape and position. For example, a line is a polygon with two control points that specify the position of the line's ends. A point marker has only one control point, controlling its position. More elaborate objects have more control points. You can use these control points to vary the size and shape of the object. By constraining the control points of one object to the control points of another, you can construct complex drawings made up of many component objects, but controlled by a small number of points. The control points are themselves objects and their editing dialogs in the Graphics Builder may be accessed by Shift-clicking on them with the left mouse button.
Note that an object's control points are sometimes distinct from the set of points that describe its boundary. For example, a parallelogram consists of three control points, defining the positions of three of its corners. The fourth point is generated dynamically from the others. Therefore, a parallelogram cannot be constrained by the fourth corner. (Although you can constrain other objects to that fourth point.)
Similarly, a circle object has two control points, which represent opposite ends of a vector perpendicular to the middle of the circle. You can use these control points to rotate the circle into a different plane from the one in which it was created. But what about the points that describe the circle's perimeter? These points are created dynamically by GLG, based on attributes of the circle object, such as its radius and resolution, as well as the positions of the control points. That is, they do not have a persistent existence as objects in the hierarchy. Therefore, it is impossible to constrain another object to them.
By now, you understand how objects in a GLG drawing are built and constrained to each other, and how objects can be grouped together to make other objects. We have also introduced the concept of resources, by which object attributes are named-and can be changed-through the GLG editor or API. Using just these concepts, you can create and use sophisticated animated drawings.
GLG lets you control the shape of a graphical object not only by controlling its attributes, but also by attaching a transformation to it. This can provide a considerable savings in computation time and drawing complexity. For example, consider a rectangle defined by three control points. To control the length of the rectangle using the rectangle resources, you would have to directly control the position of at least one of the control points. This involves editing and setting at least one geometrical value, which consists of three spatial coordinates, as illustrated in the following figure:
A simpler way to control the length of a rectangle is to create a resource that directly controls the length of the rectangle, and control that resource. This can be done by defining a ScaleX transformation and attaching it to the rectangle. The computational savings in this example may not seem great, but the advantages become more apparent when you consider an operation like rotating a ten point polygon around its center.
Several simple geometric transformations that may be applied to graphical objects, such as rotation, move, scale, and shear, can be defined with a matrix. The points of a graphical object, transformed with this matrix, produce the points of a new, transformed, graphical object. The details of the matrix construction are not important here, though they can be found in most introductory computer graphics texts.
There are two types of geometric transformations possible in a GLG drawing: static and dynamic transformations. They are sometimes called matrix transformations and parametric transformations, respectively.
GLG also provides transformations that can be applied to scalar and string data objects. The scalar transformations include various options for modifying a scalar (double) value, such as multiplication, division, range conversion, selecting a value from a list of values, etc. The string transformations are used for formatting the string text, displaying a scalar value as a text string and selecting a string from a list of strings.
Transformations as Objects
Like other GLG data, transformations are stored as objects. They are attached as child objects to the object they transform. There are geometrical transformations used to transform data objects of G-type, such as control points containing XYZ coordinates or color values containing RGB triplets, and non-geometrical attribute transformations used to transform double (D) and string (S) values.
Several geometrical transformations can be attached to an object as a list of transformations. Before rendering an object in a drawing, GLG updates the coordinates of that object with whatever transformations are attached to it, and this produces rotations, shears, translations, and scale changes as specified in the list of transformations.
Note that a transformation may be attached to a control point or directly to a polygon or other drawable object. The GLG rendering engine processes the transformations attached to the control points first, using the transformations to convert the world coordinates of the control points into transformed values in the world coordinate system. The next step of the rendering process calculates the effect of all transformations attached to the drawable object, including any zooming transformations of the viewport and the world-to-screen transformation of the screen object. The resulting combined transformation is then applied to the transformed world coordinates of each object's control point to calculate the screen coordinates used for rendering.
The transformation attached to an object does not change the coordinates of its control points, but rather "projects" the object to appear in a place different from the position defined by the coordinates. If the transformation is attached to the control point, it also affects any other objects constrained to that point. However, if the transformation is attached to the object (such as a polygon, for example), then the transformation is applied to the polygon after the point position has been read by the rendering routines. While the transformation affects the polygon, it does not affect anything constrained to its control points.
This means that if two polygons have a constrained point and a move transformation is attached to one of polygons, only the transformed polygon moves, as the transformation "projects" it into a different position. The transformation doesn't change the coordinates of the constrained control point that is the child of both polygons, and the other polygon remains in place. Any changes to the constrained point will still affect both polygons: if the constrained point is moved (by the mouse, for example), both polygons will move but each in its own "projected" space.
The following diagrams illustrate the situation. In the figure below, two polygons are constrained at a control point CP2. A move transformation is applied to PY2, which moves it somewhere.
When the move transformation is applied, Polygon PY2 moves, but Polygon PY1 does not, even though one of its control points is constrained to a point of PY2, since the coordinates of the control point are unaffected by the transformation (see Fig.1 and Fig.2 below). The transformation affects only PY2 by projecting it into a different position without changing the control point. If the control point CP2 moves (Fig.3), both polygons move, each in its own space.
To apply a move transformation to a polygon in a way that will make all the constrained points to respond to the move transformation, apply constrained copies of the transformation to the control points themselves, as in the diagram below.
Now, when PY2 is moved by the mean of changing move transformation's parameters, as shown below, it will drag along part of PY1. To move all of PY1 with PY2, the same transformation could be attached to the CP1 control point.
An alternative way to move both objects together would be to create a group containing the two polygons and apply the transformation to that group. You could also attach a constrained copy of the PY1 transformation to the PY2 object.
A constrained transformation is a transformation of the same type as the original transformation and with all parameters constrained to the corresponding parameters of the original transformation object. It may be created in the Builder by marking the original transformation with the Mark Object button of the transformation properties dialog and then using the Use Marked transformation option when attaching a new transformation. The Builder's Attribute Clone Type option must be set to Constrained Clone, which is the default value, to create constrained transformations.
The simplest kind of geometric transformation is the static transformation. This transformation type contains the actual matrix used to transform the parent object, and is therefore sometimes called a matrix transformation. Before the parent object is rendered, its defining points are transformed using this matrix.
The disadvantage to the simplicity of this transformation object is its lack of flexibility. Once you create a static transformation object, editing it is cumbersome, although it may be easily combined with other static transformations or deleted. If a static transformation attached to some object defines a move of 50 units in the X direction, changing the transformation to move the parent object 75 units involves either combining it with a new static move transformation of 25 units, or discarding the 50-unit move object and creating an entirely new 75-unit move.
In the Builder, when a static transformation is attached to an object which already has a static transformation, both transformations are merged, and the object's single static transformation is modified to contain the resulting combined matrix.
Naturally, while useful for creating and editing graphical objects in drawings, this sort of transformation is not very useful for animation.
Transforming Object Points
Instead of attaching a transformation to an object as a child, the transformation may be used to physically change the coordinates of object's control points. In this case, no transformation is attached to the object, and instead the transformation is used to recalculate coordinates of the objects' control points.
For example, when an object is moved, stretched or rotated with the mouse in the Builder, the corresponding transformation is used to change the object's points. The Builder also provides the Transform Object Points option which may be used to change object's points by applying user-defined transformations. The GLG API also provides methods for transforming both an individual control point and all points of an object with a user-supplied transformation.
The object's flag controls the way the transformation is applied using Transform Object Points. If it is not set, the coordinates of the object's control points are changed. If the flag is set, the transformation will be attached to the object instead of transforming it's point coordinates when the object is moved, stretched, or otherwise transformed, both in the Builder and programmatically.
In order to animate a transformation, you must use a dynamic transformation. This type of transformation stores various parameters used to generate the transformation matrix on the fly, which are then used to transform the parent object. For example, the object that defines a rotation transformation contains the center of the rotation (a geometrical value), and an angle. Before rendering the parent object, the center and the angle are used to generate a rotation matrix, which is then applied to the parent. If the center or angle parameters are changed, the rotation matrix will be recalculated, changing the position of the object the transformation is attached to. If the angle parameter is named, an application program can change its value at run time by accessing the angle parameter as a named resource. This will result in animating the object the rotate transformation is attached to. It will rotate according to the changing angle value.
Since this style of transformation uses certain parameters to generate the transformation matrix, it is sometimes called a parametric transformation.
Geometrical dynamic transformations typically use two numbers multiplied together to specify the effective value to use for its main parameter. For example, a rotation transformation uses an "angle" and a "factor" to define the rotation angle (the effective angle value used for rendering will be the product of these two parameters). This lets you control the input range of the controlling parameter.
For example, you could set up a rectangle that rotates through 90 degrees by setting the angle to 90, and letting the factor range from zero to one to accommodate an application which defines the maximum rotation angle of 90 degrees and then supplies a normalized value in the range of 0 to 1 to control the rectangle's rotation within this 90 degree span. The [0;1] range of the factor may be changed by attaching a range transformation to the factor attribute object itself.
If an application wants to control the rotation by supplying the rotation angle instead of a normalized value in some range, the factor of the rotate transformation may be set to 1: then the angle value will control the rotation directly. A common mistake is setting the factor to 0, in which case changing the angle value will not do anything, since the product of the two numbers will still be equal to 0.
For a complete list of the available dynamic transformations, see the Transformation Object section of GLG Objects.
An alarm object can be attached to any data or attribute object to monitor its value. Internally, alarms are implemented as a special type of a transformation object whose only action is to produce an alarm message when the alarm conditions are met. Refer to the Alarm Object section of GLG Objects for a list of available alarm objects.
A GLG graphical object exists in its own three-dimensional coordinate space. In order to draw a picture of that object on your two-dimensional screen, a mapping must be established between the object and the screen. Because an object can consist of several other objects, each with its own coordinate system, the mapping entails several steps. The steps involved in the mapping are also referred to as modeling transformations.
The graphical objects in a GLG drawing are all defined by points in three-dimensional space. The coordinates of any point indicate a position for that point relative to some origin. It is possible, however, that two different points can be defined relative to different origins, and that their coordinates can have altogether different meanings.
The position of the origin, the units, and the directions of the unit vectors all define a coordinate system. Components of a single drawing can refer to several different coordinate systems, each related to another through a series of implicit and explicit transformations.
There are several layers of geometrical transformations that affect the way the object is rendered. The transformations may be attached to the object's control points, to the object itself, as well as to any of the object's parents. In addition, there may be user-defined viewing transformations attached to the viewport, as well as internal transformations that control the viewport's integrated zooming and panning. Finally, there is a world-to-screen transformation used by a screen object to map the world coordinate system of the drawing to the changing viewport size.
Each transformation changes the coordinate system by transforming all objects affected by it according to the transformation type, thus defining a new coordinate system. In GLG, the following types of coordinate systems are defined:
The parent coordinate system defines the position of the origin relative to the object's parent, and the orientation of the parent in three-dimensional space. The parent coordinate system includes a combined effect of all transformations attached to the object's parent as well all its grand-parents.
In the editor, the parent coordinate system is used by default when the object is created. Consider an example when a circle centered about the origin (0,0,0) is created inside a group. If the group is transformed by a move transformation with a move vector (100,100,100), the origin of the circle will appear at (100,100,100) instead of (0,0,0).
If none of the object's parents have transformations attached to them, the parent coordinate system coincides with the drawing coordinate system.
Since any GLG object can have a transformation attached to it, its coordinate system may be different from its parent coordinate system. The object coordinate system includes a combined effect of all transformations attached to the object as well as all transformations attached to all of its parents. If the object does not have any transformations attached to it, its object coordinate system coincides with its parent coordinate system.
In the Builder, the coordinate values of the object's control points are entered with respect to the object coordinate system. The rendered position of each control point in the drawing is then defined by all transformations attached to the object. Alternatively, the point position can be entered in any of the defined coordinate systems and the point coordinates in the object coordinates system will be automatically calculated and stored in the control point object.
If an object does not have any transformations attached to it, the object coordinate system coincides with the parent coordinate system.
The drawing coordinate system is defined by the particular view you have of a drawing. The main view of a drawing is defined to be the one where the Z axis is pointing directly at the viewer, the X axis is level and pointing to the right, and the Y axis is pointing up. The view coordinates are defined by the matrix transformation that rotates, zooms, and moves this main view into the view of the drawing that is actually seen. The drawing coordinate system includes the combined effect of any viewing transformations attached to the viewport, the viewport's integrated zooming and panning transformations and the world-to-screen mapping transformations of the screen object.
If the viewport does not have any viewing or zooming and panning transformations, its drawing coordinate system coincides with the world coordinate system.
The world coordinate system includes only the effect of the world-to-screen mapping transformations of the screen object.
The viewport's world coordinate system depends on the settings of the Resizable attribute of the viewport's screen. If the viewport's Resizable attribute is set to YES (WORLD), the world coordinate system's origin is positioned at the center of the viewport, and the extent of the visible portion of the viewport in world coordinates is [-1000;+1000] by default. The viewport's default extent settings are stored in the SpanX and SpanY properties of the viewport's screen object, which could be changed to match the viewport's aspect ratio.
For resizable widgets created with one of the aspect ratio options in either the File, New, Widget (Resize and Stretch) or File, New, Widget (Resize, No Stretch) menu, the SpanX and SpanY properties will be preset to the following values:
- SpanX=1000 and SpanY=1000 for widgets created with the 1:1 aspect ratio
- SpanX=1200 and SpanY=900 for widgets with the 4:3 aspect ratio, and
- SpanX=1600 and SpanY=900 for widgets with the 16:9 ratio.
The exact coordinate mapping is also affected by the settings of the screen's Stretch and PushIn attributes. The X axis points to the right, the Y axis points up, and the Z axis points to the viewer. When the viewport is resized, objects in the drawing are resized with the drawing area.
If the Resizable attribute is set to NO (SCREEN), which would be the case for widgets created with the File, New, Widget (Fixed Scale) menu option, the world coordinate system is the same as the screen coordinate system, with the origin at the upper left corner of the viewport's window and the X and Y axes pointing to the right and down respectively. The Z axis points away from the viewer to maintain a right-hand coordinate system used for 3D rendering. The coordinate mapping does not change when the viewport's window is resized, keeping the size of the objects in the drawing constant.
If the Resizable attribute is set to NO (GLG SCREEN), the world coordinate system has the origin at the upper left corner of the viewport's window as well, but the X and Y axes are directed to the right and up to match the direction of the axes in the default WORLD coordinate system. The coordinate mapping does not change when the viewport's window is resized, keeping the size of the objects in the drawing constant.
If the Resizable attribute is set to NO (SCREEN CENTER), the world coordinate system's origin is always positioned in the center of the viewport's window, and the X and Y axes are directed to the right and up respectfully. When the viewport's window is resized, the coordinate mapping changes to keep the origin in the center of the window, but the size of the objects in the drawing is kept constant.
When a new widget is created, the Resizable attribute of the widget's viewport is set automatically depending on the selected Stretch/Resize option for creating a new widget. For example, the GLG SCREEN setting is used for a widget created using the File, New, Widget (Fixed Scale) menu option.
Refer to the the Screen section on page 93 for more information on the Resizable attribute.
The GIS coordinate system is a special type of the world coordinate system used to render objects on top of the map in the GIS Rendering Mode. In this mode, X and Y coordinates are specified using the GIS longitude and latitude, respectively.
The GLG Toolkit provides an integrated GIS Object for rendering GIS maps in the GLG drawing. Any graphical object added to the GIS Object will be displayed on top of the map using the GIS Rendering Mode, providing a convenient way to position dynamic objects on the map using lat/lon coordinates.
The screen coordinate system uses the screen coordinates of the native windowing system. Its origin is always located in the upper left corner of the viewport.
The final mapping transformation takes the drawing from an internal representation of three-dimensional space into a two-dimensional one. The origin of this coordinate system is defined to be the upper left corner of the window and the horizontal and vertical extent of the visible part of the viewport's window are equal to the window's width and height, respectively.
In order to see an object in three-dimensional space, there must be a source of light to illuminate it. The GLG system provides two different sources of lighting: illumination and ambience.
Illumination is the simplest form of lighting to understand, because it is the most obvious analogy to what we observe in the real world. Illumination is the light cast by a point light source in a certain direction. For example, a light source on the right side of some object leaves the left side of that object in shadow. Each viewport in a GLG drawing can have a light source to shine in it.
The viewport uses a Light object to store all lighting attributes. This allows for space for viewports that do not use lighting and 3D shading to be conserved. The Light object has attributes that allow you to position and aim the light.
The other form of lighting used in a GLG drawing is ambient light. Unlike illumination, ambient light is cast evenly on all objects, no matter which direction they face. A Light object's attributes let you determine the proportion of light cast by illumination and ambience.
The lighting facility provided with GLG is a limited one; it is useful for dynamic visualization of three-dimensional objects, but is not really appropriate for photo-realistic rendering a scene. For example, a user may position the light, but the objects do not cast shadows on other objects.
A polygon's Shading attribute provides additional control over shading of individual polygons in the viewport.
GLG provides a variety of input handlers used to build input objects, such as buttons, toggles, sliders, knobs, etc. An input handler is an object that processes input events and converts them into the corresponding resource changes, depending on the type of the input handler. For example, a slider input handler (GlgSlider) converts the mouse move and mouse click events into value changes of the resource that controls the slider knob's position.
An input handler is attached to a viewport by entering the handler's name into the viewport's Handler attribute (the viewport's DisableInput attribute must be set to NO to enable the handler). Each handler type implements predefined logic associated with a particular input object. For example, the GlgButton handler implements the input logic of the push button and toggle widget.
Each handler searches for some predefined set of resources to control in the viewport they are attached to. For example, the GlgKnob handler searches for the resource named Value and then changes its value to rotate the knob when it is moved with the mouse.
The knob widget is designed in such a way that the Value resource controls the angle of the knob's rotation, and changing this resource from 0 to 1 moves the knob from the start angle to the end angle. The handler always changes the resources it controls in the range of 0 to 1. A range transformation may be used to convert the default range of 0 to 1 to a different range.
The behavior of an input handler may be modified by defining certain resource names it recognizes. For example, the GlgButton handler searches for the resource named OnState. If this resource is found, the handler implements a toggle. Otherwise a push button is implemented.
An input handler searches for resources at the top level of the viewport hierarchy, so any controlling resources must be visible at the viewport's top level. Alias objects may be used to make resources defined inside the hierarchy be visible at the top level. It is also important to set the HasResources flag for the viewport when adding a handler to it. Without it, the viewport will be resource-transparent, and all its resources will "leak" through and will be visible at the level of its parent, instead of the viewport's level.
When an input handler processes input events and changes the values of resources it controls, it also generates messages which are sent to the application program via the Input callback. This lets the program react to the user input depending on the message's Action type. Refer to Callback Events of the GLG Programming Reference for details.
Actions, Commands and Custom Data
Action objects can be attached to graphical objects in the drawing to specify actions that will be performed when the user interacts with the objects using the mouse. Actions may include notifying the application of the object selection, highlighting an object on a mouse move or mouse click, displaying a tooltip or executing a custom command such as displaying a popup menu or popup dialog.
Custom data may also be attached to the graphical objects to keep application-specific data, such as a widget type or data to be used when an action command is executed.
Integrated Features of the GLG Drawing
The GLG drawing provides integrated support for zoom and pan, object tooltips, mouse over highlight, integrated input, selection and custom selection events. These integrated features greatly simplify application development. Refer to Integrated Features of the GLG Drawing on page 215 for details.
Generic Logic, Inc.