001: /*
002: * $RCSfile: FloatSegment.java,v $
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.model;
027:
028: import com.sun.perseus.platform.MathSupport;
029:
030: /**
031: * Represents float segment in an animation. A float segment may have
032: * multiple components and multiple dimensions.
033: *
034: * For example, an rgb color segment is represented with one component
035: * and 3 dimensions. A stroke dash array value is represented with
036: * as many components as there are dashes and one dimension for each
037: * component.
038: *
039: * @version $Id: FloatSegment.java,v 1.3 2006/06/29 10:47:31 ln156897 Exp $
040: */
041: class FloatSegment implements Segment {
042: /**
043: * The segment's begin value.
044: * There is an array for each component and an value in the
045: * array for each dimension.
046: */
047: float[][] start;
048:
049: /**
050: * The segment's end value.
051: * @see #start
052: */
053: float[][] end;
054:
055: /**
056: * @return the start value.
057: */
058: public Object[] getStart() {
059: return start;
060: }
061:
062: /**
063: * @return set end value.
064: */
065: public Object[] getEnd() {
066: return end;
067: }
068:
069: /**
070: * Sets the start value to its notion of 'zero'.
071: * For a FloatSegment, a 'zero' start means zero all all
072: * dimensions for all components.
073: */
074: public void setZeroStart() {
075: for (int ci = 0; ci < start.length; ci++) {
076: for (int di = 0; di < start[ci].length; di++) {
077: start[ci][di] = 0;
078: }
079: }
080: }
081:
082: /**
083: * Sets the start value.
084: *
085: * @param newStart the new segment start value.
086: */
087: public void setStart(Object[] newStart) {
088: start = (float[][]) newStart;
089: }
090:
091: /**
092: * Collapses this segment with the one passed as a parameter.
093: * Note that if the input segment is not of the same class
094: * as this one, an IllegalArgumentException is thrown. The
095: * method also throws an exception if the input segment's
096: * end does not have the same number of components as this
097: * segment's end.
098: *
099: * After this method is called, this segment's end value
100: * is the one of the input <code>seg</code> parameter.
101: *
102: * @param seg the Segment to collapse with this one.
103: * @param anim the Animation this segment is part of.
104: */
105: public void collapse(final Segment seg, final Animation anim) {
106: FloatSegment mseg = (FloatSegment) seg;
107: if (mseg.end.length != end.length) {
108: throw new IllegalArgumentException();
109: }
110:
111: end = mseg.end;
112: }
113:
114: /**
115: * Adds the input value to this Segment's end value.
116: *
117: * @param by the value to add. Throws IllegalArgumentException if this
118: * Segment type is not additive or if the input value is incompatible (e.g.,
119: * different number of components or different number of dimensions on a
120: * component).
121: */
122: public void addToEnd(Object[] by) {
123: if (by == null || !(by instanceof float[][])) {
124: throw new IllegalArgumentException();
125: }
126:
127: float[][] add = (float[][]) by;
128: if (add.length != end.length) {
129: throw new IllegalArgumentException();
130: }
131:
132: for (int ci = 0; ci < add.length; ci++) {
133: float[] v = end[ci];
134: float[] av = add[ci];
135: int vl = v != null ? v.length : 0;
136: int avl = av != null ? av.length : 0;
137: if (vl != avl) {
138: throw new IllegalArgumentException();
139: }
140:
141: for (int di = 0; di < vl; di++) {
142: v[di] += av[di];
143: }
144: }
145: }
146:
147: /**
148: * @return true if this segment type supports addition. false
149: * otherwise.
150: */
151: public boolean isAdditive() {
152: return true;
153: }
154:
155: /**
156: * @return the length of the segment.
157: */
158: public float getLength() {
159: float length = 0;
160: final int nc = start.length;
161:
162: for (int ci = 0; ci < nc; ci++) {
163: // Start value for the requested component.
164: float[] s = start[ci];
165:
166: // End value for the requested component.
167: float[] e = end[ci];
168:
169: // Number of dimensions.
170: int nd = s.length;
171:
172: float clength = 0;
173: for (int di = 0; di < nd; di++) {
174: clength += (e[di] - s[di]) * (e[di] - s[di]);
175: }
176:
177: length += MathSupport.sqrt(clength);
178: }
179:
180: return length;
181: }
182:
183: /**
184: * Computes an interpolated value for the given penetration in the
185: * segment. Note that the start and end segment values must be set
186: * <em>before</em> calling this method. Otherwise, a NullPointerException
187: * is thrown.
188: *
189: * @param p the segment penetration. Should be in the [0, 1] range.
190: * @param w array where the computed value should be stored.
191: */
192: public void compute(final float p, final float[][] w) {
193: // For each component
194: int nc = w.length;
195: int nd = 0;
196: for (int ci = 0; ci < nc; ci++) {
197: // For each dimension
198: nd = w[ci].length;
199: for (int di = 0; di < nd; di++) {
200: w[ci][di] = p * end[ci][di] + (1 - p) * start[ci][di];
201: }
202: }
203: }
204:
205: /**
206: * Debug helper.
207: */
208: public String toString() {
209: StringBuffer sb = new StringBuffer();
210: sb.append("FloatSegment[");
211: if (start == null) {
212: sb.append("null");
213: } else {
214: sb.append("start[" + start.length + "] : {");
215: for (int ci = 0; ci < start.length; ci++) {
216: float[] fc = start[ci];
217: if (fc == null) {
218: sb.append("null");
219: } else {
220: sb.append("float[" + fc.length + "{");
221: for (int di = 0; di < fc.length; di++) {
222: sb.append(fc[di]);
223: if (di < fc.length - 1) {
224: sb.append(", ");
225: }
226: }
227: sb.append("}");
228: }
229: if (ci < start.length - 1) {
230: sb.append(", ");
231: }
232: }
233: sb.append("} ");
234: }
235:
236: if (end == null) {
237: sb.append("null");
238: } else {
239: sb.append("end[" + end.length + "] : {");
240: for (int ci = 0; ci < end.length; ci++) {
241: float[] fc = end[ci];
242: if (fc == null) {
243: sb.append("null");
244: } else {
245: sb.append("float[" + fc.length + "{");
246: for (int di = 0; di < fc.length; di++) {
247: sb.append(fc[di]);
248: if (di < fc.length - 1) {
249: sb.append(", ");
250: }
251: }
252: sb.append("}");
253: }
254: if (ci < end.length - 1) {
255: sb.append(", ");
256: }
257: }
258: sb.append("}");
259: }
260:
261: return sb.toString();
262: }
263:
264: /**
265: * Should be called after the segment's configuration is complete
266: * to give the segment's implementation a chance to initialize
267: * internal data and cache values.
268: */
269: public void initialize() {
270: }
271:
272: }
|