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();
    node.addChild(leaf);
    layer.addChild(node);

                              // 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
See Also:
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
See Also:
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
See Also:
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
See Also:
ZDrawingSurface.pick(int, int)

addTransformListener

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
See Also:
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
See Also:
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();
     node1.addChild(leaf1);
     layer.addChild(node1);

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

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

     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();
     node1.addChild(leaf1);
     layer.addChild(node1);

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

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

     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
See Also:
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.