001 /*
002 * $Id: SubsetRubberBandBox.java,v 1.13 2012/03/27 21:58:01 rink Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv.data.hydra;
032
033 import edu.wisc.ssec.mcidasv.data.hydra.MyRubberBandBoxRendererJ3D;
034
035 import ucar.visad.display.Displayable;
036 import ucar.visad.display.LineDrawing;
037
038 import visad.*;
039 import visad.bom.*;
040
041 import java.rmi.RemoteException;
042
043 import java.awt.event.InputEvent;
044
045
046 public class SubsetRubberBandBox extends LineDrawing {
047
048 /** x type for the box */
049 private RealType xType;
050
051 /** y type for the box */
052 private RealType yType;
053
054 /** renderer */
055 private MyRubberBandBoxRendererJ3D rubberBandBox;
056
057 /** bounds defined by the rubber band box */
058 private Gridded2DSet bounds;
059
060 /** mouse event mask */
061 private int mask;
062
063 private FlatField data;
064 private boolean isLL;
065 private boolean lastBoxOn;
066
067 private CoordinateSystem dataCS;
068
069 private CoordinateSystem displayCS;
070
071 private static int count = 0;
072
073 /**
074 * Construct a RubberBandBox using xType as the X coordinate and
075 * yType as the Y coordinate of the box.
076 *
077 * @param xType RealType of the X coordinate of the box
078 * @param yType RealType of the Y coordinate of the box
079 *
080 * @throws VisADException VisAD error
081 * @throws RemoteException Remote error
082 */
083 public SubsetRubberBandBox(FlatField data, CoordinateSystem displayCS)
084 throws VisADException, RemoteException {
085 this(false, data, displayCS, 0);
086 }
087
088 public SubsetRubberBandBox(FlatField data, CoordinateSystem displayCS, int mask)
089 throws VisADException, RemoteException {
090 this(false, data, displayCS, mask);
091 }
092
093 public SubsetRubberBandBox(boolean isLL, FlatField data, CoordinateSystem displayCS, int mask)
094 throws VisADException, RemoteException {
095 this(isLL, data, displayCS, mask, true);
096 }
097
098 public SubsetRubberBandBox(FlatField data, CoordinateSystem displayCS, int mask, boolean lastBoxOn)
099 throws VisADException, RemoteException {
100 this(false, data, displayCS, mask, lastBoxOn);
101 }
102
103
104
105 /**
106 * Construct a RubberBandBox using xType as the X coordinate and
107 * yType as the Y coordinate of the box.
108 *
109 * @param xType RealType of the X coordinate of the box
110 * @param yType RealType of the Y coordinate of the box
111 * @param mask key mask to use for rubberbanding
112 *
113 * @throws VisADException VisAD error
114 * @throws RemoteException Remote error
115 */
116 public SubsetRubberBandBox(boolean isLL, FlatField data, CoordinateSystem displayCS, int mask, boolean lastBoxOn)
117 throws VisADException, RemoteException {
118 super("Subset Rubber Band Box");
119
120 this.data = data;
121 this.displayCS = displayCS;
122 this.isLL = isLL;
123 this.lastBoxOn = lastBoxOn;
124
125 RealTupleType rtype = ((FunctionType)data.getType()).getDomain();
126 dataCS = rtype.getCoordinateSystem();
127 if (dataCS == null) {
128 dataCS = new GridCoordinateSystem((GriddedSet)data.getDomainSet());
129 }
130
131 IdentityCoordinateSystem iCS =
132 new IdentityCoordinateSystem(
133 new RealTupleType(new RealType[] {RealType.getRealType("ZZtop")}));
134
135 CoordinateSystem cs =
136 new CartesianProductCoordinateSystem(new CoordinateSystem[] {dataCS, iCS});
137
138 CoordinateSystem new_cs = new DataToDisplayCoordinateSystem(isLL, cs, displayCS);
139
140
141 DisplayRealType displayLineType =
142 new DisplayRealType("displayLine_"+count, true, 0.0, 10000.0, 0.0, null);
143 DisplayRealType displayElemType =
144 new DisplayRealType("displayElem_"+count, true, 0.0, 10000.0, 0.0, null);
145 DisplayRealType displayAltType =
146 new DisplayRealType("displayAlt_"+count, true, -1.0, 1.0, 0.0, null);
147 DisplayTupleType dtt =
148 new DisplayTupleType(new DisplayRealType[] {displayLineType, displayElemType, displayAltType}, new_cs);
149
150
151 RealType elemType = RealType.getRealType("elem_"+count);
152 RealType lineType = RealType.getRealType("line_"+count);
153 this.xType = lineType;
154 this.yType = elemType;
155 this.mask = mask;
156 bounds = new Gridded2DSet(new RealTupleType(xType, yType), null, 1);
157
158 ScalarMap elemMap = new ScalarMap(elemType, displayElemType);
159 ScalarMap lineMap = new ScalarMap(lineType, displayLineType);
160
161 GriddedSet domainSet = (GriddedSet) data.getDomainSet();
162 float[] low = domainSet.getLow();
163 float[] hi = domainSet.getHi();
164
165 elemMap.setRange(low[1], hi[1]);
166 lineMap.setRange(low[0], hi[0]);
167
168 addScalarMap(elemMap);
169 addScalarMap(lineMap);
170
171 setData(bounds);
172 count += 1;
173 }
174
175 /**
176 * Constructor for creating a RubberBandBox from another instance
177 *
178 * @param that other instance
179 *
180 * @throws VisADException VisAD error
181 * @throws RemoteException Remote error
182 */
183 protected SubsetRubberBandBox(SubsetRubberBandBox that)
184 throws VisADException, RemoteException {
185
186 super(that);
187
188 this.xType = that.xType;
189 this.yType = that.yType;
190 this.bounds = that.bounds;
191 }
192
193 /**
194 * Invoked when box mouse is released. Subclasses should invoke
195 * super.dataChange() to ensure the the bounds are set.
196 *
197 * @throws RemoteException
198 * @throws VisADException
199 */
200 protected void dataChange() throws VisADException, RemoteException {
201
202 bounds = (Gridded2DSet) getData();
203 float[] highs = bounds.getHi();
204 float[] lows = bounds.getLow();
205 if (highs != null && lows != null)
206 super.dataChange();
207 }
208
209 /**
210 * Return the bounds of the RubberBandBox. The Gridded2DSet that
211 * is returned contains the opposite (starting and ending) corners
212 * of the box.
213 *
214 * @return set containing the opposite corners of the box.
215 */
216 public Gridded2DSet getBounds() {
217 return bounds;
218 }
219
220 /**
221 * Get the DataRenderer used for this displayable.
222 *
223 * @return RubberBandBoxRendererJ3D associated with this displayable
224 */
225 protected DataRenderer getDataRenderer() {
226 rubberBandBox = new MyRubberBandBoxRendererJ3D(xType, yType, mask,
227 mask);
228 rubberBandBox.setKeepLastBoxOn(lastBoxOn);
229
230 return rubberBandBox;
231 }
232
233 /**
234 * Returns a clone of this instance suitable for another VisAD display.
235 * Underlying data objects are not cloned.
236 *
237 * @return A semi-deep clone of this instance.
238 *
239 * @throws VisADException VisAD failure.
240 * @throws RemoteException Java RMI failure.
241 */
242 public Displayable cloneForDisplay()
243 throws RemoteException, VisADException {
244 return new SubsetRubberBandBox(this);
245 }
246
247 public void setBox(SubsetRubberBandBox rbb) {
248 rubberBandBox.setLastBox((MyRubberBandBoxRendererJ3D)rbb.getDataRenderer());
249 }
250
251 public Gridded3DSet getLastBox() {
252 return rubberBandBox.last_box;
253 }
254 }
255
256
257 class DataToDisplayCoordinateSystem extends CoordinateSystem {
258 private CoordinateSystem dataCS;
259 private CoordinateSystem displayCS;
260 private boolean isLL;
261
262
263 DataToDisplayCoordinateSystem(boolean isLL, CoordinateSystem dataCS, CoordinateSystem displayCS) throws VisADException {
264 super(displayCS.getReference(), null);
265 try {
266 this.dataCS = dataCS;
267 this.displayCS = displayCS;
268 this.isLL = isLL;
269 } catch (Exception e) {
270 System.out.println("e=" + e);
271 }
272 }
273
274 public float[][] toReference(float[][] values) throws VisADException {
275 //- if (isLL) values = reverseArrayOrder(values);
276 float[][] new_values = dataCS.toReference(values);
277 if (isLL) new_values = reverseArrayOrder(new_values);
278 new_values = displayCS.toReference(new float[][] {new_values[1], new_values[0], new_values[2]});
279 return new_values;
280 }
281
282 public float[][] fromReference(float[][] values) throws VisADException {
283 //- if (isLL) values = reverseArrayOrder(values);
284 float[][] new_values = displayCS.fromReference(values);
285 if (isLL) new_values = reverseArrayOrder(new_values);
286 new_values = dataCS.fromReference(new float[][] {new_values[1], new_values[0], new_values[2]});
287
288 return new_values;
289 }
290
291 public double[][] toReference(double[][] values) throws VisADException {
292 //- if (isLL) values = reverseArrayOrder(values);
293 double[][] new_values = dataCS.toReference(values);
294 if (isLL) new_values = reverseArrayOrder(new_values);
295 new_values = displayCS.toReference(new double[][] {new_values[1], new_values[0], new_values[2]});
296
297 return new_values;
298 }
299
300 public double[][] fromReference(double[][] values) throws VisADException {
301 //- if (isLL) values = reverseArrayOrder(values);
302 double[][] new_values = displayCS.fromReference(values);
303 if (isLL) new_values = reverseArrayOrder(new_values);
304 new_values = dataCS.fromReference(new double[][] {new_values[1], new_values[0], new_values[2]});
305 return new_values;
306 }
307
308 public boolean equals(Object obj) {
309 return true;
310 }
311
312 private double[][] reverseArrayOrder(double[][] in) {
313 if (in.length < 2) return in;
314 int len1 = 2;
315 int len2 = in[0].length;
316 double[][] out = new double[in.length][len2];;
317 for (int i=0; i<len1; i++) {
318 for (int j=0; j<len2; j++) {
319 out[len1-i-1][j] = in[i][j];
320 }
321 }
322 if (in.length > 2) {
323 for (int i=2; i<in.length; i++) {
324 for (int j=0; j<len2; j++) {
325 out[i][j] = in[i][j];
326 }
327 }
328 }
329 return out;
330 }
331
332
333 private float[][] reverseArrayOrder(float[][] in) {
334 if (in.length < 2) return in;
335 int len1 = 2;
336 int len2 = in[0].length;
337 float[][] out = new float[in.length][len2];;
338 for (int i=0; i<len1; i++) {
339 for (int j=0; j<len2; j++) {
340 out[len1-i-1][j] = in[i][j];
341 }
342 }
343 if (in.length > 2) {
344 for (int i=2; i<in.length; i++) {
345 for (int j=0; j<len2; j++) {
346 out[i][j] = in[i][j];
347 }
348 }
349 }
350 return out;
351 }
352 }