FileDocCategorySizeDatePackage
CompositeMotionSegment.javaAPI DocphoneME MR2 API (J2ME)6619Wed May 02 18:00:36 BST 2007com.sun.perseus.model

CompositeMotionSegment

public class CompositeMotionSegment extends Object implements MotionSegment
A composite implementation of the Segment interface. This is used in AnimateMotion to handle linearization of quadratic and cubic segments.
version
$Id: CompositeMotionSegment.java,v 1.3 2006/04/21 06:36:43 st125089 Exp $

Fields Summary
MotionSegment[]
segments
The list of segment components.
float
length
The cached segment length.
float[]
nSegLength
The cached, normalized segment length
Constructors Summary
Methods Summary
public voidaddToEnd(java.lang.Object[] by)
Adds the input value to this Segment's end value.

param
by the value to add. Throws IllegalArgumentException if this Segment type is not additive or if the input value is incompatible (e.g., different number of components or different number of dimensions on a component).

        segments[segments.length - 1].addToEnd(by);
    
public voidcollapse(Segment seg, Animation anim)
Collapses this segment with the one passed as a parameter. Note that if the input segment is not of the same class as this one, an IllegalArgumentException is thrown. The method also throws an exception if the input segment's end does not have the same number of components as this segment's end. After this method is called, this segment's end value is the one of the input seg parameter.

param
seg the Segment to collapse with this one.
param
anim the Animation this segment is part of.

        CompositeMotionSegment cseg = (CompositeMotionSegment) seg;
        MotionSegment[] newSegments = 
            new MotionSegment[segments.length + cseg.segments.length];

        System.arraycopy(segments, 
                         0, 
                         newSegments, 
                         0, 
                         segments.length);

        System.arraycopy(cseg.segments, 
                         0, 
                         newSegments, 
                         segments.length, 
                         cseg.segments.length);

        segments = newSegments;
    
public voidcompute(float p, float[][] w)
Computes an interpolated value for the given penetration in the segment.

param
p the segment penetration. Should be in the [0, 1] range.
param
w array where the computed value should be stored.
return
the interpolated value.

        // First, identify the child MotionSegment at the desired 
        // normalized distance.
        int si = segments.length - 1;
        float prevSegLength = 0;

        if (p < 1) {
            for (si = 0; si < segments.length; si++) {
                if (p < nSegLength[si]) {
                    break;
                }
                prevSegLength = nSegLength[si];
            }
        } else {
            if (si > 0) {
                prevSegLength = nSegLength[si - 1];
            }
        }

        // The sub-segment is at index si. Now, we need to 
        // compute the penetration in that segment.
        if (nSegLength[si] > prevSegLength) {
            p = (p - prevSegLength) / (nSegLength[si] - prevSegLength);
        } else {
            p = 1;
        }

        segments[si].compute(p, w);
    
public java.lang.Object[]getEnd()

return
set end value.

        return segments[segments.length - 1].getEnd();
    
public floatgetLength()
Computes this segment's length

        return length;
    
public java.lang.Object[]getStart()

return
the start value.

        return segments[0].getStart();
    
public voidinitialize()
Should be called after the segment's configuration is complete to give the segment's implementation a chance to initialize internal data and cache values.

        // Initialize the component segments.
        final int ns = segments.length;
        for (int si = 0; si < ns; si++) {
            segments[si].initialize();
        }

        // Now, initialize the length cache.
        length = 0;
        nSegLength = new float[ns];        
        for (int si = 0; si < segments.length; si++) {
            nSegLength[si] = segments[si].getLength();
            length += nSegLength[si];
        }
        
        // Now, initialize the normalized segment lengths array
        if (length > 0) {
            float curLength = 0;
            for (int si = 0; si < ns - 1; si++) {
                curLength += nSegLength[si];
                nSegLength[si] = curLength / length;
            }
        } else {
            for (int si = 0; si < ns - 1; si++) {
                nSegLength[si] = 0;
            }
        }
        
        // Make sure that, in all cases, the last value is 1.
        nSegLength[ns - 1] = 1;
    
public booleanisAdditive()

return
true if this segment type supports addition. false otherwise.

        return segments[0].isAdditive();
    
public voidsetStart(java.lang.Object[] newStart)
Sets the start value.

param
newStart the new segment start value.

        segments[0].setStart(newStart);
    
public voidsetZeroStart()
Sets the start value to its notion of 'zero'

        segments[0].setZeroStart();