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 }