View Javadoc

1   /* -------------------------------------------------------------------
2    * Java source file for the class LookupTable
3    * 
4    * Copyright (c), 2003, Masahiro Takatsuka.
5    * All Rights Researved.
6    * 
7    * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8    * $Author: takatsukam $
9    * 
10   * $Date: 2004/03/03 11:53:05 $
11   * 
12   * $Id: LookupTable.java,v 1.3 2004/03/03 11:53:05 takatsukam Exp $
13   * 
14   * Reference:		Document no:
15   * ___				___
16   * 
17   * To Do:
18   * ___
19   * 
20  ------------------------------------------------------------------- */
21  
22  /* --------------------------- Package ---------------------------- */
23  package net.jbeans.j3d.data;
24  
25  /* ------------------ Import classes (packages) ------------------- *//package-summary/html">class="comment"> ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment"> ------------------ Import classes (packages) ------------------- */
26  import net.jbeans.util.time.*;
27  
28  /*====================================================================
29                   Implementation of class LookupTable                  
30  ====================================================================*/
31  /***
32   * LookupTable is an object that map scalar values into other
33   * scalar or vector values.  
34   *
35   * This class is designed as a base class for derivation by other classes. 
36   * The build() methods are abstract method
37   * and may require overloading in subclasses.
38   * 
39   * @version $Revision: 1.3 $
40   * @author Masahiro Takatsuka (masa@jbeans.net)
41   * @see AttributeArray
42   */
43  
44  public abstract class LookupTable extends AttributeArray {
45    	private double[] tableRange = new double[2];
46    	protected TimeStamp insertTime;
47    	protected TimeStamp buildTime;
48  	protected int numberOfLookups;
49  	
50  	/***
51  	 * Construct with range=(0,1); and hsv ranges set up for rainbow color
52  	 * table (from red to blue).
53  	 */
54  	public LookupTable(int dataType, int dim, int size) {
55  		super(dataType);
56  		dim = (dim < 1 ? 1 : dim);
57  		this.data.setDimension(dim);		
58  		this.numberOfLookups = size;
59  		setNumberOfLookups(size);
60  		try {
61  			setTableRange(0.0, 1.0);
62  		} catch (InvalidDataRangeException e) { // never happen!
63  		}
64  		this.insertTime = new TimeStamp();
65  		this.buildTime = new TimeStamp();
66          this.buildTime.setTimeStamp(0L);
67  	}
68  
69  	public LookupTable(int dataType, int dim) {
70  		this(dataType, dim, 1);
71  	}
72  
73  	/***
74  	 * Generate lookup table.
75  	 */
76  	abstract protected void build();
77  	
78  	/***
79  	 * Set the number of colors in the lookup table. Use this method before
80  	 * building the lookup table. Use SetNumberOfTableValues() to change the
81  	 * table size after the lookup table has been built.
82  	 */
83  	public void setNumberOfLookups(int number) {
84  		number = (number < 2 ? 2 : (number > Integer.MAX_VALUE ? Integer.MAX_VALUE : number));
85  		this.numberOfLookups = number;
86  		this.data.setNumberOfTuples(number);
87  	}
88  
89  	public int getNumberOfLookups() {
90  		return this.numberOfLookups;
91  	}
92  
93  	/***
94  	 * Set/Get the minimum/maximum scalar values for scalar mapping. Scalar
95  	 * values less than minimum range value are clamped to minimum range value.
96  	 * Scalar values greater than maximum range value are clamped to maximum
97  	 * range value.
98  	 */
99  	public void setTableRange(double[] r) throws InvalidDataRangeException {
100 		setTableRange(r[0], r[1]);
101 	}
102 	
103 	public void setTableRange(double min, double max) throws InvalidDataRangeException {
104 		if (min >= max) {
105 			throw new InvalidDataRangeException("Bad table range: " + min + " >= " + max);
106 		}
107 		
108 		this.tableRange[0] = min;
109 		this.tableRange[1] = max;
110 		
111 	}
112 	public double[] getTableRange() {
113 		return this.tableRange;
114 	}
115 
116 	/***
117 	 * Map one value through the lookup table.  It returns an array of
118 	 * double containing corresponding mapped value.
119 	 */
120 	public double[] mapValue(double v) {
121 		int indx;
122 		int dim = this.data.getDimension();
123 		
124 		indx = (int)((v - this.tableRange[0])/(this.tableRange[1] - this.tableRange[0]) * this.numberOfLookups);
125 		indx = (indx < 0 ? 0 : (indx >= this.numberOfLookups ? this.numberOfLookups-1 : indx));
126 		
127 		return this.data.getTuple(indx);
128 	}
129 	
130 	/***
131 	 * map a set of scalars through the lookup table
132 	 *
133 	 * @param input an array of primitives (type, char, short, int, long, flost, double).
134 	 */
135 //  	public void mapValues(Object input, double[][] output,
136 //  						   int inputIncrement) {
137 
138 	public void mapValues(Object input, double[] output,
139 						  int numberOfValues,
140 						  int inputIncrement) {
141 		int indx;
142 		int dim = this.data.getDimension();
143 		double tmp = 0;
144 			
145 		Class type = DataType.getArrayType(input.getClass());
146 		int ptr = 0;
147 		double[] tmpArray = new double[dim];
148 		for (int i = 0; i < numberOfValues; i++, ptr += inputIncrement) {
149 			if (type == Byte.TYPE) {
150 				tmp = (double) ((byte[]) input)[ptr];
151 			} else if (type == Character.TYPE) {
152 				tmp = (double) ((char[]) input)[ptr];
153 			} else if (type == Short.TYPE) {
154 				tmp = (double) ((short[]) input)[ptr];				
155 			} else if (type == Integer.TYPE) {
156 				tmp = (double) ((int[]) input)[ptr];				
157 			} else if (type == Long.TYPE) {
158 				tmp = (double) ((long[]) input)[ptr];				
159 			} else if (type == Float.TYPE) {
160 				tmp = (double) ((float[]) input)[ptr];
161 			} else if (type == Double.TYPE) {
162 				tmp = ((double[]) input)[ptr];
163 			}
164 			indx = (int)((tmp - this.tableRange[0])/(this.tableRange[1] - this.tableRange[0]) * this.numberOfLookups);			
165 			indx = (indx < 0 ? 0 : (indx >= this.numberOfLookups ? this.numberOfLookups-1 : indx));
166 			
167 			this.data.getTuple(indx * dim, tmpArray);
168 			System.arraycopy(tmpArray, 0, output, i * dim, dim);
169 		}
170 	}
171 
172 	/***
173 	 * Specify the number of values (i.e., colors) in the lookup
174 	 * table. This method simply allocates memory and prepares the table
175 	 * for use with SetTableValue(). It differs from Build() method in
176 	 * that the allocated memory is not initialized according to HSVA ramps.
177 	 */
178 	public void setNumberOfTableValues(int number) {
179 		setNumberOfLookups(number);
180 	}
181 	
182 	/***
183 	 * Directly load values into lookup table. Use double values for elements.
184 	 * Make sure that you've either used the build() method or used
185 	 * setNumberOfTableValues() prior to using this method.
186 	 */
187 	public void setTableValue (int indx, double[] value) {
188 		this.data.setTuple(indx, value);
189 		this.insertTime.modified();
190 	}
191 	
192 	/***
193 	 * Return a value for the given index into the lookup table.
194 	 * Values are expressed as double values.
195 	 */
196 	public double[] getTableValue(int id) {
197 		return this.data.getTuple(id);
198 	}
199 
200 	/***
201 	 * Return a rgba color value for the given index into the lookup table.
202 	 * Color components are expressed as [0,1] float values.
203 	 */
204 	public void getTableValue (int id, double[] value) {
205 		this.data.getTuple(id, value);		
206 	}
207 }
208