## edu.umd.cs.jazz Class ZTransformGroup

```java.lang.Object
|
+--edu.umd.cs.jazz.ZSceneGraphObject
|
+--edu.umd.cs.jazz.ZNode
|
+--edu.umd.cs.jazz.ZGroup
|
+--edu.umd.cs.jazz.ZTransformGroup
```
All Implemented Interfaces:
java.lang.Cloneable, java.io.Serializable, ZSerializable, ZTransformable
Direct Known Subclasses:
ZConstraintGroup

public class ZTransformGroup
extends ZGroup
implements ZSerializable, ZTransformable, java.io.Serializable

ZTransformGroup is a group node that specifies an arbitrary affine transform. The transform applies to all the children of this node. In addition, it provides some extra manipulators on the transform. This provides the ability to relatively or absolutely change the translation, scale, rotation and shear of the transform - either immediately, or animated over time.

In order to use transforms effectively, it is important to have a solid understanding of affine transforms, matrix multiplication, and the standard use of matrices for graphics coordinate systems. The best place to start is by reading the documentation on `AffineTransform`. After that, a good next bit is to read a standard 3D graphics text such as "Interactive Computer Graphics: a Top-Down Approach with OpenGL" 2nd Edition by Angel (Addison-Wesley), or "Computer Graphics: Principles and Practice, Second Edition in C" by Foley, van Dam, Feiner, Hughes, and Phillips (Addison-Wesley).

Here is a very short lesson on matrices and graphics. A 2D affine transform is typically represented by a 3x3 matrix which we typically call M, and sometimes denote [M]. An affine transform can represent any 2D translation, scale, rotation, shear or any combination of these 4 operators. Matrices which are pure translations, scales, and rotations are typically denoted T, S, or R ([T], [S], or [R]), respectively. The identity matrix is typically denoted I or [I].

The reason these transforms are so powerful is because they can be combined in a semantically straightforward way by simply concatenating the matrices. Creating a transform results in I. Calling one of the transformation methods on a transform is exactly equivalent to concatenating the transform with a new transform that specifies the transformation. Thus, transform.translate(dx, dy) is equivalent to [M][T] where M represents the original transform, and T represents the translation matrix of dx, dy. Similarly, transform.scale(ds) is equivalent to [M][S]. And, these build up, so

```    ZTransformGroup t = new ZTransformGroup();
t.scale(ds);
t.translate(dx, dy);
t.rotate(Math.PI * 0.5);
```
is equivalent to generating a node with transform of these four matrices concatenated together with standard matrix multiplication [I][S][T][R]

However, a crucial place for confusion with these transforms is that the transforms get applied in the reverse order of how you placed the calls to the transforms in your code. To understand this, you must realize that the object paint methods get called after the transformations are applied. Your paint methods specify geometry (such as points) which get transformed by the current transformation before being painted. For a simple example, think of a point P. Well, the point post-multiplies the current transformation. In the example above, that works out to a new point P' being computed as P' = [S][T][R]P. You can think about this as the original point P first getting multiplied (on the left) by R, then the result gets multipled (on the left) by T, and that gets multiplied (on the left) by S.

Let's go through a simple example with actual numbers. Suppose you want to take a rectangle at (0, 0) with width 50 and height 50, and first translate it 50 units to the right, and then scale the whole thing by 2 about the origin. The result should be that the rectangle actually gets rendered at (100, 0) with dimensions of (100x100). The following code in Jazz implements this example.

```    ZRectangle rect = new ZRectangle(0, 0, 50, 50);
ZVisualLeaf leaf = new ZVisualLeaf(rect);
ZTransformGroup node = new ZTransformGroup();

// Note how we call scale first even though
// the translation will actually be applied before the scale.
node.scale(2);
node.translate(50, 0);
```

Sometimes it is useful to transform an object in global coordinates - even though that object has a transform of its own. For instance, suppose you are implementing an event handler for selection, and want to move an object so that it follows the pointer. In order to do this, you need to translate the object in global coordinates. Since the node you want to move may have a transform already (for instance, it may be scaled), if you simply translate the object, that transform will be applied after the scale, and thus the translation will be modified by the scale. That is, the object may have the matrix [M]. Calling translate will generate [M][T]. If M represents a scale of 2, then the translation will actually translate twice as much as you intended.

The solution is to convert your translation into the local coordinate system of the object. Since there this node is actually part of a tree, there coul be other transforms as well, not to mention the camera transform. So, the goal is to take the amount you want to translate the object in the original coordinate system (in this case the window coords), and convert it into the object's local coordinate system. We do this by building up the concatenation of all the transforms from the window to the node, taking the inverse of that matrix, and finally transform the translation by the resulting inverse matrix. Jazz provides a utility method to make this easier. So, the resulting code would look like this. It takes a desired translation in window coordinates, and uses the utility method ZCamera.cameraToLocal to convert it to the local coordinate system of the specified node, and finally translates the node by the resulting amount.

```    Point2D pt = new Point2D.Double(x, y);
camera.cameraToLocal(pt, node);
node.translate(pt.getX(), pt.getY());
```

`ZSceneGraphEditor` provides a convenience mechanism to locate, create and manage nodes of this type.

Warning: Serialized and ZSerialized objects of this class will not be compatible with future Jazz releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Jazz. A future release of Jazz will provide support for long term persistence.

Author:
Benjamin B. Bederson
`AffineTransform`, Serialized Form

 Field Summary `static boolean` `ANIMATE_METHODS_USE_ANIMATION_FRAMEWORK`           Jazz animation framework was added after ZTransformGroups animate methods were coded.

 Fields inherited from class edu.umd.cs.jazz.ZGroup `children, childrenFindable_DEFAULT, childrenPickable_DEFAULT, childrenVolatileBoundsCache, hasOneChild_DEFAULT`

 Fields inherited from class edu.umd.cs.jazz.ZNode `editorFactory, findable_DEFAULT, parent, pickable_DEFAULT, savable_DEFAULT, selectable_DEFAULT`

 Fields inherited from class edu.umd.cs.jazz.ZSceneGraphObject `bounds, inTransaction, invalidBounds, invalidVolatileBounds, listenerList, volatileBounds, volatileBounds_DEFAULT`

 Constructor Summary `ZTransformGroup()`           Constructs an empty ZTransformGroup. `ZTransformGroup(ZNode child)`           Constructs a new transform group node with the specified node as a child of the new group.

 Method Summary ` void` `addTransformListener(ZTransformListener l)`           Adds the specified transform listener to receive transform events from this node `static void` `animate(ZTransformable[] nodes, java.awt.geom.AffineTransform[] txs, int millis, ZDrawingSurface surface)`           Set the transforms of the specified array of nodes to the specified array of transforms, and animate the change over the specified number of milliseconds using a slow-in slow-out animation. `static void` `animate(ZTransformable[] nodes, java.awt.geom.AffineTransform[] txs, int millis, ZDrawingSurface surface, ZLerp lerpTimeFunction)`           Set the transforms of the specified array of nodes to the specified array of transforms, and animate the change over the specified number of milliseconds using a slow-in slow-out animation. `static void` `animate(ZTransformable node, java.awt.geom.AffineTransform tx, int millis, ZDrawingSurface surface)`           Set the transform of the specified node to the specified transform, and animate the change from its current transformation over the specified number of milliseconds using a slow-in slow-out animation. `static void` `animate(ZTransformable node, java.awt.geom.AffineTransform at, int millis, ZDrawingSurface surface, ZLerp lerpTimeFunction)`           Set the transform of the specified node to the specified transform, and animate the change from its current transformation over the specified number of milliseconds using a slow-in slow-out animation. `protected  void` `computeBounds()`           Recomputes and caches the bounds for this node. `protected  void` `computeInverseTransform()`           Internal method to compute the inverse transform based on the transform. `static double` `computeScale(java.awt.geom.AffineTransform at)`           Given an AffineTransform, this returns the "scale" of the transform. ` void` `concatenate(java.awt.geom.AffineTransform at)`           Concatenates an AffineTransform `at` to this node's transform in the standard way. ` java.lang.String` `dump()`           Generate a string that represents this object for debugging. `protected  java.lang.Object` `duplicateObject()`           Returns a clone of this object. ` java.awt.geom.AffineTransform` `getInverseTransform()`           Returns the inverse of the transform associated with this node. ` java.awt.geom.AffineTransform` `getLocalToGlobalTransform()`           Return the transform that converts local coordinates at this node to global coordinates at the root node. ` void` `getMatrix(double[] flatmatrix)`           Retrieves the 6 specifiable values in the affine transformation, and places them into an array of double precisions values. ` double` `getRotation()`           Returns the current rotation of this node ` double` `getScale()`           Returns the current scale of this transform. ` java.awt.geom.AffineTransform` `getTransform()`           Returns a copy of the transform that that this node specifies. ` java.awt.geom.AffineTransform` `getTransformReference()`           Returns a reference to the transform that that this node specifies. ` double` `getTranslateX()`           Returns the current X translation of this node ` double` `getTranslateY()`           Returns the current Y translation of this node ` java.awt.geom.Point2D` `getTranslation()`           Returns the current translation of this node `static double` `lerp(double t, double a, double b)`           Linearly interpolates between a and b, based on t. ` boolean` `pick(java.awt.geom.Rectangle2D rect, ZSceneGraphPath path)`           Returns the first object under the specified rectangle (if there is one) in the subtree rooted with this as searched in reverse (front-to-back) order. ` void` `position(java.awt.geom.Point2D srcPt, java.awt.geom.Point2D destPt, java.awt.geom.Rectangle2D destBounds, int millis, ZDrawingSurface surface)`           This will calculate the necessary transform in order to make this node appear at a particular position relative to the specified bounding box. ` void` `position(java.awt.geom.Point2D srcPt, java.awt.geom.Point2D destPt, ZNode refNode, int millis, ZDrawingSurface surface)`           This will calculate the necessary transform in order to make this node appear at a particular position relative to the specified node. ` void` `preConcatenate(java.awt.geom.AffineTransform at)`           Pre-Concatenates an AffineTransform `at` to this node's transform in a less commonly used way such that `at` gets pre-multipled with the existing transform rather than the more normal post-multiplication. ` void` `removeTransformListener(ZTransformListener l)`           Removes the specified transform listener so that it no longer receives transform events from this transform. ` void` `render(ZRenderContext renderContext)`           Renders this node which results in its children getting painted. ` void` `repaint(ZBounds repaintBounds)`           Method to pass repaint methods up the tree. ` void` `reshape()`           Overrides ZSceneGraphObject.reshape to invert the transform on the when the this ZTransformGroup is volatile ` void` `rotate(double theta)`           Rotate the node by the specified amount ` void` `rotate(double theta, double xctr, double yctr)`           Rotate the node by the specified amount around the specified anchor point ` void` `rotate(double theta, double xctr, double yctr, int millis, ZDrawingSurface surface)`           Rotate the node, via animation, theta radians about the specified anchor point ` void` `rotate(double theta, int millis, ZDrawingSurface surface)`           Rotate the node, via animation, theta radians ` void` `scale(double dz)`           Scale the node from its current scale to the scale specified by muliplying the current scale and dz. ` void` `scale(double dz, double x, double y)`           Scale the node around the specified point (x, y) from its current scale to the scale specified by muliplying the current scale and dz. ` void` `scale(double dz, double x, double y, int millis, ZDrawingSurface surface)`           Animate the node around the specified point (x, y) from its current scale to the scale specified by muliplying the current scale and dz ` void` `scale(double dz, int millis, ZDrawingSurface surface)`           Animate the node from its current scale to the scale specified by muliplying the current scale and deltaZ ` void` `setRotation(double theta)`           Set the absolute rotation of this node. ` void` `setRotation(double theta, double xctr, double yctr)`           Set the absolute rotation of this node, rotating around the specified anchor point. ` void` `setRotation(double theta, double xctr, double yctr, int millis, ZDrawingSurface surface)`           Set the absolute rotation of this node, via animation, theta radians about the specified anchor point. ` void` `setRotation(double theta, int millis, ZDrawingSurface surface)`           Set the absolute rotation of this node, animating the change over time. ` void` `setScale(double finalz)`           Sets the scale of the transform ` void` `setScale(double finalz, double x, double y)`           Set the scale of the node to the specified target scale, scaling the node around the specified point (x, y). ` void` `setScale(double finalz, double x, double y, int millis, ZDrawingSurface surface)`           Animate the node around the specified point (x, y) to the specified target scale. ` void` `setScale(double finalz, int millis, ZDrawingSurface surface)`           Animate the node from its current scale to the specified target scale. ` void` `setState(java.lang.String fieldType, java.lang.String fieldName, java.lang.Object fieldValue)`           Set some state of this object as it gets read back in. ` void` `setTransform(java.awt.geom.AffineTransform newTransform)`           Sets the transform associated with this node. ` void` `setTransform(double m00, double m10, double m01, double m11, double m02, double m12)`           Sets the transform associated with this node. ` void` `setTransformReference(java.awt.geom.AffineTransform newTransform)`           Sets the transform reference associated with this node. ` void` `setTranslateX(double x)`           Sets the current X translation of this node ` void` `setTranslateY(double y)`           Sets the current Y translation of this node ` void` `setTranslation(double x, double y)`           Translate the node to the specified position ` void` `setTranslation(double x, double y, int millis, ZDrawingSurface surface)`           Animate the node from its current position to the position specified by x, y `static void` `transform(java.awt.geom.Rectangle2D rect, java.awt.geom.AffineTransform at)`           Apply the specified transform to the specified rectangle, modifying the rect. `static void` `transform(ZBounds bounds, java.awt.geom.AffineTransform at)`           Apply the specified transform to the specified bounds, modifying the bounds. ` void` `translate(double dx, double dy)`           Translate the node by the specified deltaX and deltaY ` void` `translate(double dx, double dy, int millis, ZDrawingSurface surface)`           Animate the node from its current position by the specified deltaX and deltaY ` void` `writeObject(ZObjectOutputStream out)`           Write out all of this object's state. ` void` `writeObjectRecurse(ZObjectOutputStream out)`           Specify which objects this object references in order to write out the scenegraph properly

 Methods inherited from class edu.umd.cs.jazz.ZGroup `addChild, addChildImpl, addChildren, addChildren, addGroupListener, childAddedNotification, childRemovedNotification, computeVolatileBounds, extract, findNodes, getChild, getChildren, getChildrenFindable, getChildrenIterator, getChildrenPickable, getChildrenReference, getNumChildren, getShallowBounds, getVolatileBounds, hasOneChild, indexOf, insertAbove, iterator, lower, lowerTo, markInTransaction, markNotInTransaction, raise, raiseTo, removeAllChildren, removeAllChildren, removeChild, removeChild, removeChild, removeChildImpl, removeGroupListener, removeNodeListener, setChildrenFindable, setChildrenPickable, setHasOneChild, trimToSize, updateHasNodeListener`

 Methods inherited from class edu.umd.cs.jazz.ZNode `addNodeListener, editor, getGlobalBounds, getGlobalToLocalTransform, getParent, getRoot, globalToLocal, globalToLocal, globalToLocal, hasNodeListener, isAncestorOf, isDescendentOf, isFindable, isPickable, isSavable, isSelectable, localToGlobal, localToGlobal, localToGlobal, lower, lowerTo, percolateEventUpSceneGraph, raise, raiseTo, remove, repaint, reparent, replaceWith, setEditorFactory, setFindable, setParent, setPickable, setSavable, setSelectable, setVolatileBounds, updateBounds, updateVolatility, writeReplace`

 Methods inherited from class edu.umd.cs.jazz.ZSceneGraphObject `addClientProperty, addMouseListener, addMouseMotionListener, clone, endTransaction, fireEvent, fireMouseEvent, getBounds, getBoundsReference, getClientProperty, getHandles, getListenerList, hasLisenerOfType, hasListenerOfType, hasMouseListener, processMouseEvent, putClientProperty, removeEventListener, removeMouseListener, removeMouseMotionListener, setBounds, startTransaction, updateObjectReferences`

 Methods inherited from class java.lang.Object `equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

 Field Detail

### ANIMATE_METHODS_USE_ANIMATION_FRAMEWORK

`public static boolean ANIMATE_METHODS_USE_ANIMATION_FRAMEWORK`
Jazz animation framework was added after ZTransformGroups animate methods were coded. This flag lets you specify that the animate methods should use the animation framework, by default they will still use the original implementation. These two methods differ in a significant way, the old implementation animates in a hard loop that blocks until the animation finished, while the animation framework is timer based so it is non- blocking.

 Constructor Detail

### ZTransformGroup

`public ZTransformGroup()`
Constructs an empty ZTransformGroup.

### ZTransformGroup

`public ZTransformGroup(ZNode child)`
Constructs a new transform group node with the specified node as a child of the new group. If the specified child was already a member of a tree (i.e., had a parent), then this new node is inserted in the tree above the child so that the original child is still in that tree, but with this node inserted in the middle of the tree. If the specified child does not have a parent, then it is just made a child of this node.

Parameters:
`child` - Child of the new group node.
 Method Detail

### duplicateObject

`protected java.lang.Object duplicateObject()`
Returns a clone of this object.

Overrides:
`duplicateObject` in class `ZGroup`
`ZSceneGraphObject.duplicateObject()`

### render

`public void render(ZRenderContext renderContext)`
Renders this node which results in its children getting painted.

The transform, clip, and composite will be set appropriately when this object is rendered. It is up to this object to restore the transform, clip, and composite of the Graphics2D if this node changes any of them. However, the color, font, and stroke are unspecified by Jazz. This object should set those things if they are used, but they do not need to be restored.

This transform node applies its transform before painting its children.

Overrides:
`render` in class `ZGroup`
Parameters:
`renderContext` - The graphics context to use for rendering.

### computeBounds

`protected void computeBounds()`
Recomputes and caches the bounds for this node. Generally this method is called by reshape when the bounds have changed, and it should rarely directly elsewhere. A ZTransformGroup bounds is the union of its children's bounds, transformed by this node's transform.

Overrides:
`computeBounds` in class `ZGroup`

### repaint

`public void repaint(ZBounds repaintBounds)`
Method to pass repaint methods up the tree. Repaints only the sub- portion of this object specified by the given ZBounds. Note that the input parameter may be modified as a result of this call.

Overrides:
`repaint` in class `ZNode`
Parameters:
`repaintBounds` - The bounds to repaint

### reshape

`public void reshape()`
Overrides ZSceneGraphObject.reshape to invert the transform on the when the this ZTransformGroup is volatile

Overrides:
`reshape` in class `ZSceneGraphObject`
`ZSceneGraphObject.repaint()`

### pick

```public boolean pick(java.awt.geom.Rectangle2D rect,
ZSceneGraphPath path)```
Returns the first object under the specified rectangle (if there is one) in the subtree rooted with this as searched in reverse (front-to-back) order. This performs a depth-first search, first picking children. Only returns a node if this is "pickable".

Overrides:
`pick` in class `ZGroup`
Parameters:
`rect` - Coordinates of pick rectangle in local coordinates
`path` - The path through the scenegraph to the picked node. Modified by this call.
Returns:
The picked node, or null if none
`ZDrawingSurface.pick(int, int)`

`public void addTransformListener(ZTransformListener l)`
Adds the specified transform listener to receive transform events from this node

Parameters:
`l` - the transform listener

### removeTransformListener

`public void removeTransformListener(ZTransformListener l)`
Removes the specified transform listener so that it no longer receives transform events from this transform.

Parameters:
`l` - the transform listener

### getTransform

`public java.awt.geom.AffineTransform getTransform()`
Returns a copy of the transform that that this node specifies.

Returns:
The current transform.

### getTransformReference

`public java.awt.geom.AffineTransform getTransformReference()`
Returns a reference to the transform that that this node specifies.

Returns:
A reference to the current transform.

### getMatrix

`public void getMatrix(double[] flatmatrix)`
Retrieves the 6 specifiable values in the affine transformation, and places them into an array of double precisions values. The values are stored in the array as { m00 m10 m01 m11 m02 m12 }. An array of 4 doubles can also be specified, in which case only the first four elements representing the non-transform parts of the array are retrieved and the values are stored into the array as { m00 m10 m01 m11 }

Specified by:
`getMatrix` in interface `ZTransformable`
Parameters:
`flatmatrix` - the double array used to store the returned values.

### setTransform

`public void setTransform(java.awt.geom.AffineTransform newTransform)`
Sets the transform associated with this node. This transform applies to the sub-tree rooted at this node.

Parameters:
`newTransform` -

### setTransform

```public void setTransform(double m00,
double m10,
double m01,
double m11,
double m02,
double m12)```
Sets the transform associated with this node. This transform applies to the sub-tree rooted at this node.

Specified by:
`setTransform` in interface `ZTransformable`

### setTransformReference

`public void setTransformReference(java.awt.geom.AffineTransform newTransform)`
Sets the transform reference associated with this node. This is different then the other setTransform methods because they set the transform using this.transform.setTransform(newTransform). This method uses this.transform = newTransform, and can be useful if you want the ZTransformGroup to use your own subclass of AffineTransform internally.

### concatenate

`public void concatenate(java.awt.geom.AffineTransform at)`
Concatenates an AffineTransform `at` to this node's transform in the standard way. This has the affect of applying `at` in this node's local coordinate system.

Parameters:
`at` - The transform to concatenate
`preConcatenate(java.awt.geom.AffineTransform)`

### preConcatenate

`public void preConcatenate(java.awt.geom.AffineTransform at)`
Pre-Concatenates an AffineTransform `at` to this node's transform in a less commonly used way such that `at` gets pre-multipled with the existing transform rather than the more normal post-multiplication. This has the affect of applying the transform `at` in the coordinate system above this node, rather than within the local coordinate system of this node.

Parameters:
`at` - The transform to pre-concatenate
`concatenate(java.awt.geom.AffineTransform)`

### getLocalToGlobalTransform

`public java.awt.geom.AffineTransform getLocalToGlobalTransform()`
Return the transform that converts local coordinates at this node to global coordinates at the root node.

Overrides:
`getLocalToGlobalTransform` in class `ZNode`
Returns:
The concatenation of transforms from the root down to this node.

### computeInverseTransform

`protected void computeInverseTransform()`
Internal method to compute the inverse transform based on the transform. This gets called from within ZTransformGroup whenever the inverse transform cache has been invalidated, and it is needed.

### getInverseTransform

`public java.awt.geom.AffineTransform getInverseTransform()`
Returns the inverse of the transform associated with this node.

Returns:
The current inverse transform.

### getTranslation

`public java.awt.geom.Point2D getTranslation()`
Returns the current translation of this node

Returns:
the translation

### getTranslateX

`public double getTranslateX()`
Returns the current X translation of this node

Returns:
the translation

### setTranslateX

`public void setTranslateX(double x)`
Sets the current X translation of this node

### getTranslateY

`public double getTranslateY()`
Returns the current Y translation of this node

Returns:
the translation

### setTranslateY

`public void setTranslateY(double y)`
Sets the current Y translation of this node

### translate

```public void translate(double dx,
double dy)```
Translate the node by the specified deltaX and deltaY

Parameters:
`dx` - X-coord of translation
`dy` - Y-coord of translation

### translate

```public void translate(double dx,
double dy,
int millis,
ZDrawingSurface surface)```
Animate the node from its current position by the specified deltaX and deltaY

Parameters:
`dx` - X-coord of translation
`dy` - Y-coord of translation
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### setTranslation

```public void setTranslation(double x,
double y)```
Translate the node to the specified position

Parameters:
`x` - X-coord of translation
`y` - Y-coord of translation

### setTranslation

```public void setTranslation(double x,
double y,
int millis,
ZDrawingSurface surface)```
Animate the node from its current position to the position specified by x, y

Parameters:
`x` - X-coord of translation
`y` - Y-coord of translation
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### getScale

`public double getScale()`
Returns the current scale of this transform. Note that this is implemented by applying the transform to a diagonal line and returning the length of the resulting line. If the transform is sheared, or has a non-uniform scaling in X and Y, the results of this method will be ill-defined.

Returns:
the scale

### scale

`public void scale(double dz)`
Scale the node from its current scale to the scale specified by muliplying the current scale and dz.

Parameters:
`dz` - scale factor

### scale

```public void scale(double dz,
double x,
double y)```
Scale the node around the specified point (x, y) from its current scale to the scale specified by muliplying the current scale and dz.

Parameters:
`dz` - scale factor
`x` - X coordinate of the point to scale around
`y` - Y coordinate of the point to scale around

### scale

```public void scale(double dz,
int millis,
ZDrawingSurface surface)```
Animate the node from its current scale to the scale specified by muliplying the current scale and deltaZ

Parameters:
`dz` - scale factor
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### scale

```public void scale(double dz,
double x,
double y,
int millis,
ZDrawingSurface surface)```
Animate the node around the specified point (x, y) from its current scale to the scale specified by muliplying the current scale and dz

Parameters:
`dz` - scale factor
`x` - X coordinate of the point to scale around
`y` - Y coordinate of the point to scale around
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### setScale

`public void setScale(double finalz)`
Sets the scale of the transform

### setScale

```public void setScale(double finalz,
double x,
double y)```
Set the scale of the node to the specified target scale, scaling the node around the specified point (x, y).

Parameters:
`finalz` - scale factor
`x` - X coordinate of the point to scale around
`y` - Y coordinate of the point to scale around

### setScale

```public void setScale(double finalz,
int millis,
ZDrawingSurface surface)```
Animate the node from its current scale to the specified target scale.

Parameters:
`finalz` - scale factor
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### setScale

```public void setScale(double finalz,
double x,
double y,
int millis,
ZDrawingSurface surface)```
Animate the node around the specified point (x, y) to the specified target scale.

Parameters:
`finalz` - scale factor
`x` - X coordinate of the point to scale around
`y` - Y coordinate of the point to scale around
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### getRotation

`public double getRotation()`
Returns the current rotation of this node

Returns:
the rotation angle in radians.

### setRotation

`public void setRotation(double theta)`
Set the absolute rotation of this node.

Parameters:
`theta` - angle to rotate (in radians)

### setRotation

```public void setRotation(double theta,
int millis,
ZDrawingSurface surface)```
Set the absolute rotation of this node, animating the change over time.

Parameters:
`theta` - angle to rotate (in radians)
`millis` - Time to animate scale in milliseconds
`surface` - The surface to updated during animation.

### setRotation

```public void setRotation(double theta,
double xctr,
double yctr)```
Set the absolute rotation of this node, rotating around the specified anchor point.

Parameters:
`theta` - angle to rotate (in radians)
`xctr` - X-coord of anchor point
`yctr` - Y-coord of anchor point

### setRotation

```public void setRotation(double theta,
double xctr,
double yctr,
int millis,
ZDrawingSurface surface)```
Set the absolute rotation of this node, via animation, theta radians about the specified anchor point.

Parameters:
`theta` - angle to rotate (in radians)
`xctr` - X-coord of anchor point
`yctr` - Y-coord of anchor point
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### rotate

`public void rotate(double theta)`
Rotate the node by the specified amount

Parameters:
`theta` - angle to rotate (in radians)

### rotate

```public void rotate(double theta,
double xctr,
double yctr)```
Rotate the node by the specified amount around the specified anchor point

Parameters:
`theta` - angle to rotate (in radians)
`xctr` - X-coord of anchor point
`yctr` - Y-coord of anchor point

### rotate

```public void rotate(double theta,
int millis,
ZDrawingSurface surface)```
Rotate the node, via animation, theta radians

Parameters:
`theta` - angle to rotate (in radians)
`millis` - Time to animate scale in milliseconds
`surface` - The surface to updated during animation.

### rotate

```public void rotate(double theta,
double xctr,
double yctr,
int millis,
ZDrawingSurface surface)```
Rotate the node, via animation, theta radians about the specified anchor point

Parameters:
`theta` - angle to rotate (in radians)
`xctr` - X-coord of anchor point
`yctr` - Y-coord of anchor point
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### position

```public void position(java.awt.geom.Point2D srcPt,
java.awt.geom.Point2D destPt,
ZNode refNode,
int millis,
ZDrawingSurface surface)```
This will calculate the necessary transform in order to make this node appear at a particular position relative to the specified node. The source point specifies a point in the unit square (0, 0) - (1, 1) that represents an anchor point on the corresponding node to this transform. The destination point specifies an anchor point on the reference node. The position method then computes the transform that results in transforming this node so that the source anchor point coincides with the reference anchor point. This can be useful for layout algorithms as it is straightforward to position one object relative to another.

For example, If you have two nodes, A and B, and you call

```     Point2D srcPt = new Point2D.Double(1.0, 0.0);
Point2D destPt = new Point2D.Double(0.0, 0.0);
A.position(srcPt, destPt, B, 750, null);
```
The result is that A will move so that its upper-right corner is at the same place as the upper-left corner of B, and the transition will be smoothly animated over a period of 750 milliseconds.

Parameters:
`srcPt` - The anchor point on this transform's node (normalized to a unit square)
`destPt` - The anchor point on destination bounds (normalized to a unit square)
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to be updated during animation.

### position

```public void position(java.awt.geom.Point2D srcPt,
java.awt.geom.Point2D destPt,
java.awt.geom.Rectangle2D destBounds,
int millis,
ZDrawingSurface surface)```
This will calculate the necessary transform in order to make this node appear at a particular position relative to the specified bounding box. The source point specifies a point in the unit square (0, 0) - (1, 1) that represents an anchor point on the corresponding node to this transform. The destination point specifies an anchor point on the reference node. The position method then computes the transform that results in transforming this node so that the source anchor point coincides with the reference anchor point. This can be useful for layout algorithms as it is straightforward to position one object relative to another.

For example, If you have two nodes, A and B, and you call

```     Point2D srcPt = new Point2D.Double(1.0, 0.0);
Point2D destPt = new Point2D.Double(0.0, 0.0);
A.position(srcPt, destPt, B.getGlobalBounds(), 750, null);
```
The result is that A will move so that its upper-right corner is at the same place as the upper-left corner of B, and the transition will be smoothly animated over a period of 750 milliseconds.

Parameters:
`srcPt` - The anchor point on this transform's node (normalized to a unit square)
`destPt` - The anchor point on destination bounds (normalized to a unit square)
`destBounds` - The bounds (in global coordinates) used to calculate this transform's node
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### computeScale

`public static double computeScale(java.awt.geom.AffineTransform at)`
Given an AffineTransform, this returns the "scale" of the transform. The scale of an affine transform is computed by transforming a vector and seeing how its length changes.

### lerp

```public static double lerp(double t,
double a,
double b)```
Linearly interpolates between a and b, based on t. Specifically, it computes lerp(a, b, t) = a + t*(b - a). This produces a result that changes from a (when t = 0) to b (when t = 1).

Parameters:
`a` - from point
`b` - to Point
`t` - variable 'time' parameter

### transform

```public static void transform(ZBounds bounds,
java.awt.geom.AffineTransform at)```
Apply the specified transform to the specified bounds, modifying the bounds.

Parameters:
`bounds` - The bounds to be transformed
`at` - The transform to use to transform the rectangle

### transform

```public static void transform(java.awt.geom.Rectangle2D rect,
java.awt.geom.AffineTransform at)```
Apply the specified transform to the specified rectangle, modifying the rect.

Parameters:
`rect` - The rectangle to be transformed
`at` - The transform to use to transform the rectangle

### animate

```public static void animate(ZTransformable node,
java.awt.geom.AffineTransform tx,
int millis,
ZDrawingSurface surface)```
Set the transform of the specified node to the specified transform, and animate the change from its current transformation over the specified number of milliseconds using a slow-in slow-out animation. The surface specifies which surface should be updated during the animation. Note that another version of animate lets you specify the timing of the animation so you can avoid the slow-in slow-out animation if you prefer.

If millis is 0, then the transform is updated once, and the scene is not repainted immediately, but rather a repaint request is queued, and will be processed by an event handler.

Parameters:
`node` - The node to be animated
`tx` - Final transformation
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### animate

```public static void animate(ZTransformable node,
java.awt.geom.AffineTransform at,
int millis,
ZDrawingSurface surface,
ZLerp lerpTimeFunction)```
Set the transform of the specified node to the specified transform, and animate the change from its current transformation over the specified number of milliseconds using a slow-in slow-out animation. The surface specifies which surface should be updated during the animation. Note that another version of animate lets you specify the timing of the animation so you can avoid the slow-in slow-out animation if you prefer.

If millis is 0, then the transform is updated once, and the scene is not repainted immediately, but rather a repaint request is queued, and will be processed by an event handler.

The timing of the animation is controlled by the lerpTimeFunction. This is used to specify the rate the animation occurs over time. If this parameter is specified as null, then a standard linear interpolation is used, and the animation goes at a constant speed from beginning to end. The caller can specify alternate functions, however, which can do things like perform a slow-in, slow-out animation.

Parameters:
`node` - The node to be animated
`at` - Final transformation
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.
`lerpTimeFunction` - The function that determines how the timing of the animation should be calculated

### animate

```public static void animate(ZTransformable[] nodes,
java.awt.geom.AffineTransform[] txs,
int millis,
ZDrawingSurface surface)```
Set the transforms of the specified array of nodes to the specified array of transforms, and animate the change over the specified number of milliseconds using a slow-in slow-out animation. The surface specifies which surface should be updated during the animation. (Note that another version of animate lets you specify the timing of the animation so you can avoid the slow-in slow-out animation if you prefer.)

If the size of the nodes and txs arrays are not equal, then only those nodes for which transforms are specified will be animated. That is, the smaller of the two array sizes will be used.

If millis is 0, then the transform is updated once, and the scene is not repainted immediately, but rather a repaint request is queued, and will be processed by an event handler.

The following code fragment demonstrates the use of this animate method. It creates three rectangles, and animates two of them simultaneously.

```     ZRectangle rect1, rect2, rect3;
ZVisualLeaf leaf1, leaf2, leaf3;
ZTransformable node1, node2, node3;

rect1 = new ZRectangle(0, 0, 50, 50);
rect1.setFillColor(Color.red);
leaf1 = new ZVisualLeaf(rect1);
node1 = new ZTransformable();

rect2 = new ZRectangle(25, 25, 50, 50);
rect2.setFillColor(Color.blue);
leaf2 = new ZVisualLeaf(rect2);
node2 = new ZNode();

rect3 = new ZRectangle(100, 100, 50, 50);
rect3.setFillColor(Color.orange);
leaf3 = new ZVisualLeaf(rect3);
node3 = new ZNode(rect3);

ZTransformable[] nodes = new ZTransformable[2];
nodes[0] = node1;
nodes[1] = node2;
AffineTransform[] txs = new AffineTransform[2];
txs[0] = new AffineTransform();
txs[0].scale(2.0, 2.0);
txs[1] = new AffineTransform();
txs[1].translate(100.0, 25.0);
txs[1].scale(0.5, 0.5);

ZTransform.animate(nodes, txs, 1000, surface);
```

Parameters:
`nodes` - The array of nodes to be animated
`txs` - The array of final transformations of the nodes
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.

### animate

```public static void animate(ZTransformable[] nodes,
java.awt.geom.AffineTransform[] txs,
int millis,
ZDrawingSurface surface,
ZLerp lerpTimeFunction)```
Set the transforms of the specified array of nodes to the specified array of transforms, and animate the change over the specified number of milliseconds using a slow-in slow-out animation. The surface specifies which surface should be updated during the animation. (Note that another version of animate lets you specify the timing of the animation so you can avoid the slow-in slow-out animation if you prefer.)

If the size of the nodes and txs arrays are not equal, then only those nodes for which transforms are specified will be animated. That is, the smaller of the two array sizes will be used.

If millis is 0, then the transform is updated once, and the scene is not repainted immediately, but rather a repaint request is queued, and will be processed by an event handler.

The timing of the animation is controlled by the lerpTimeFunction. This is used to specify the rate the animation occurs over time. If this parameter is specified as null, then a standard linear interpolation is used, and the animation goes at a constant speed from beginning to end. The caller can specify alternate functions, however, which can do things like perform a slow-in, slow-out animation.

The following code fragment demonstrates the use of this animate method. It creates three rectangles, and animates two of them simultaneously.

```     ZRectangle rect1, rect2, rect3;
ZVisualLeaf leaf1, leaf2, leaf3;
ZTransformable node1, node2, node3;

rect1 = new ZRectangle(0, 0, 50, 50);
rect1.setFillColor(Color.red);
leaf1 = new ZVisualLeaf(rect1);
node1 = new ZTransformable();

rect2 = new ZRectangle(25, 25, 50, 50);
rect2.setFillColor(Color.blue);
leaf2 = new ZVisualLeaf(rect2);
node2 = new ZNode();

rect3 = new ZRectangle(100, 100, 50, 50);
rect3.setFillColor(Color.orange);
leaf3 = new ZVisualLeaf(rect3);
node3 = new ZNode(rect3);

ZTransformable[] nodes = new ZTransformable[2];
nodes[0] = node1;
nodes[1] = node2;
AffineTransform[] txs = new AffineTransform[2];
txs[0] = new AffineTransform();
txs[0].scale(2.0, 2.0);
txs[1] = new AffineTransform();
txs[1].translate(100.0, 25.0);
txs[1].scale(0.5, 0.5);

ZTransform.animate(nodes, txs, 1000, surface);
```

Parameters:
`nodes` - The array of nodes to be animated
`txs` - The array of final transformations of the nodes
`millis` - Number of milliseconds over which to perform the animation
`surface` - The surface to updated during animation.
`lerpTimeFunction` - The function that determines how the timing of the animation should be calculated

### dump

`public java.lang.String dump()`
Generate a string that represents this object for debugging.

Overrides:
`dump` in class `ZGroup`
Returns:
the string that represents this object for debugging
`ZDebug.dump(edu.umd.cs.jazz.ZNode)`

### writeObject

```public void writeObject(ZObjectOutputStream out)
throws java.io.IOException```
Write out all of this object's state.

Specified by:
`writeObject` in interface `ZSerializable`
Overrides:
`writeObject` in class `ZGroup`
Parameters:
`out` - The stream that this object writes into
`java.io.IOException`

### writeObjectRecurse

```public void writeObjectRecurse(ZObjectOutputStream out)
throws java.io.IOException```
Specify which objects this object references in order to write out the scenegraph properly

Specified by:
`writeObjectRecurse` in interface `ZSerializable`
Overrides:
`writeObjectRecurse` in class `ZGroup`
Parameters:
`out` - The stream that this object writes into
`java.io.IOException`

### setState

```public void setState(java.lang.String fieldType,
java.lang.String fieldName,
java.lang.Object fieldValue)```
Set some state of this object as it gets read back in. After the object is created with its default no-arg constructor, this method will be called on the object once for each bit of state that was written out through calls to ZObjectOutputStream.writeState() within the writeObject method.

Specified by:
`setState` in interface `ZSerializable`
Overrides:
`setState` in class `ZGroup`
Parameters:
`fieldType` - The fully qualified type of the field
`fieldName` - The name of the field
`fieldValue` - The value of the field

Copyright � 2003 by University of Maryland, College Park, MD 20742, USA All rights reserved.