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