001/* 002 * $Id: SubsetRubberBandBox.java,v 1.11 2011/03/24 16:06:33 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 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 031package edu.wisc.ssec.mcidasv.data.hydra; 032 033import edu.wisc.ssec.mcidasv.data.hydra.MyRubberBandBoxRendererJ3D; 034 035import ucar.visad.display.Displayable; 036import ucar.visad.display.LineDrawing; 037 038import visad.*; 039import visad.bom.*; 040 041import java.rmi.RemoteException; 042 043import java.awt.event.InputEvent; 044 045 046public 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 //System.out.println("\n\nSubsetRubberBandBox:"); 126 //System.out.println(" isLL=" + isLL); 127 //System.out.println(" displayCS=" + displayCS.getClass()); 128 //System.out.println(" mask=" + mask); 129 RealTupleType rtype = ((FunctionType)data.getType()).getDomain(); 130 dataCS = rtype.getCoordinateSystem(); 131 if (dataCS == null) { 132 dataCS = new GridCoordinateSystem((GriddedSet)data.getDomainSet()); 133 } 134 //System.out.println(" dataCS=" + dataCS.getClass()); 135 136 IdentityCoordinateSystem iCS = 137 new IdentityCoordinateSystem( 138 new RealTupleType(new RealType[] {RealType.getRealType("ZZtop")})); 139 //System.out.println("iCS=" + iCS); 140 141 CoordinateSystem cs = 142 new CartesianProductCoordinateSystem(new CoordinateSystem[] {dataCS, iCS}); 143 //System.out.println("cs=" + cs); 144 145 CoordinateSystem new_cs = new DataToDisplayCoordinateSystem(isLL, cs, displayCS); 146 //System.out.println("new_cs=" + new_cs); 147 148 149 DisplayRealType displayLineType = 150 new DisplayRealType("displayLine_"+count, true, 0.0, 10000.0, 0.0, null); 151 DisplayRealType displayElemType = 152 new DisplayRealType("displayElem_"+count, true, 0.0, 10000.0, 0.0, null); 153 DisplayRealType displayAltType = 154 new DisplayRealType("displayAlt_"+count, true, -1.0, 1.0, 0.0, null); 155 DisplayTupleType dtt = 156 new DisplayTupleType(new DisplayRealType[] {displayLineType, displayElemType, displayAltType}, new_cs); 157 158 159 RealType elemType = RealType.getRealType("elem_"+count); 160 RealType lineType = RealType.getRealType("line_"+count); 161 this.xType = lineType; 162 this.yType = elemType; 163 this.mask = mask; 164 bounds = new Gridded2DSet(new RealTupleType(xType, yType), null, 1); 165 //System.out.println("bounds=" + bounds); 166 167 ScalarMap elemMap = new ScalarMap(elemType, displayElemType); 168 ScalarMap lineMap = new ScalarMap(lineType, displayLineType); 169 170 GriddedSet domainSet = (GriddedSet) data.getDomainSet(); 171 float[] low = domainSet.getLow(); 172 //System.out.println(" low: " + low[0] + " " + low[1]); 173 float[] hi = domainSet.getHi(); 174 //System.out.println(" hi: " + hi[0] + " " + hi[1]); 175 176 elemMap.setRange(low[1], hi[1]); 177 lineMap.setRange(low[0], hi[0]); 178 //System.out.println("elemMap range: " + low[1] + " - " + hi[1]); 179 //System.out.println("lineMap range: " + low[0] + " - " + hi[0]); 180 181 addScalarMap(elemMap); 182 addScalarMap(lineMap); 183 184 //System.out.println("setData bounds=" + bounds); 185 setData(bounds); 186 count += 1; 187 } 188 189 /** 190 * Constructor for creating a RubberBandBox from another instance 191 * 192 * @param that other instance 193 * 194 * @throws VisADException VisAD error 195 * @throws RemoteException Remote error 196 */ 197 protected SubsetRubberBandBox(SubsetRubberBandBox that) 198 throws VisADException, RemoteException { 199 200 super(that); 201 202 this.xType = that.xType; 203 this.yType = that.yType; 204 this.bounds = that.bounds; 205 } 206 207 /** 208 * Invoked when box mouse is released. Subclasses should invoke 209 * super.dataChange() to ensure the the bounds are set. 210 * 211 * @throws RemoteException 212 * @throws VisADException 213 */ 214 protected void dataChange() throws VisADException, RemoteException { 215 216 bounds = (Gridded2DSet) getData(); 217 float[] highs = bounds.getHi(); 218 float[] lows = bounds.getLow(); 219 if (highs != null && lows != null) 220 /* 221 System.out.println("box: X range = " + lows[0] + " to " + 222 highs[0] + 223 "; Y range = " + lows[1] + " to " + highs[1] ); */ 224 super.dataChange(); 225 } 226 227 /** 228 * Return the bounds of the RubberBandBox. The Gridded2DSet that 229 * is returned contains the opposite (starting and ending) corners 230 * of the box. 231 * 232 * @return set containing the opposite corners of the box. 233 */ 234 public Gridded2DSet getBounds() { 235 return bounds; 236 } 237 238 /** 239 * Get the DataRenderer used for this displayable. 240 * 241 * @return RubberBandBoxRendererJ3D associated with this displayable 242 */ 243 protected DataRenderer getDataRenderer() { 244 rubberBandBox = new MyRubberBandBoxRendererJ3D(xType, yType, mask, 245 mask); 246 rubberBandBox.setKeepLastBoxOn(lastBoxOn); 247 248 return rubberBandBox; 249 } 250 251 /** 252 * Returns a clone of this instance suitable for another VisAD display. 253 * Underlying data objects are not cloned. 254 * 255 * @return A semi-deep clone of this instance. 256 * 257 * @throws VisADException VisAD failure. 258 * @throws RemoteException Java RMI failure. 259 */ 260 public Displayable cloneForDisplay() 261 throws RemoteException, VisADException { 262 return new SubsetRubberBandBox(this); 263 } 264 265 public void setBox(SubsetRubberBandBox rbb) { 266 rubberBandBox.setLastBox((MyRubberBandBoxRendererJ3D)rbb.getDataRenderer()); 267 } 268 269 public Gridded3DSet getLastBox() { 270 return rubberBandBox.last_box; 271 } 272} 273 274 275class DataToDisplayCoordinateSystem extends CoordinateSystem { 276 private CoordinateSystem dataCS; 277 private CoordinateSystem displayCS; 278 private boolean isLL; 279 280 281 DataToDisplayCoordinateSystem(boolean isLL, CoordinateSystem dataCS, CoordinateSystem displayCS) throws VisADException { 282 super(displayCS.getReference(), null); 283 //System.out.println("SubsetRubberBandBox DataToDisplayCoordinateSystem:"); 284 //System.out.println(" dataCS=" + dataCS.getClass()); 285 //System.out.println(" isLL=" + isLL); 286 //System.out.println(" displayCS=" + displayCS.getClass() + "\n"); 287 try { 288 this.dataCS = dataCS; 289 this.displayCS = displayCS; 290 this.isLL = isLL; 291 } catch (Exception e) { 292 System.out.println("e=" + e); 293 } 294 } 295 296 public float[][] toReference(float[][] values) throws VisADException { 297/* 298 System.out.println("\nSubsetRubberBandBox toReference float"); 299 System.out.println(" values[0]: " + values[0][0]); 300 System.out.println(" values[1]: " + values[1][0]); 301*/ 302 //- if (isLL) values = reverseArrayOrder(values); 303 float[][] new_values = dataCS.toReference(values); 304 if (isLL) new_values = reverseArrayOrder(new_values); 305 new_values = displayCS.toReference(new float[][] {new_values[1], new_values[0], new_values[2]}); 306/* 307 System.out.println(" new_values[0]: " + new_values[0][0]); 308 System.out.println(" new_values[1]: " + new_values[1][0]); 309*/ 310 return new_values; 311 } 312 313 public float[][] fromReference(float[][] values) throws VisADException { 314/* 315 System.out.println("SubsetRubberBandBox fromReference float"); 316 System.out.println(" values[0]: " + values[0][0]); 317 System.out.println(" values[1]: " + values[1][0]); 318*/ 319 //- if (isLL) values = reverseArrayOrder(values); 320 float[][] new_values = displayCS.fromReference(values); 321 if (isLL) new_values = reverseArrayOrder(new_values); 322 new_values = dataCS.fromReference(new float[][] {new_values[1], new_values[0], new_values[2]}); 323/* 324 System.out.println(" new_values[0]: " + new_values[0][0]); 325 System.out.println(" new_values[1]: " + new_values[1][0]); 326*/ 327 return new_values; 328 } 329 330 public double[][] toReference(double[][] values) throws VisADException { 331/* 332 System.out.println("SubsetRubberBandBox toReference double"); 333 System.out.println(" values[0]: " + values[0][0]); 334 System.out.println(" values[1]: " + values[1][0]); 335*/ 336 //- if (isLL) values = reverseArrayOrder(values); 337 double[][] new_values = dataCS.toReference(values); 338 if (isLL) new_values = reverseArrayOrder(new_values); 339 new_values = displayCS.toReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 340/* 341 System.out.println(" new_values[0]: " + new_values[0][0]); 342 System.out.println(" new_values[1]: " + new_values[1][0]); 343*/ 344 return new_values; 345 } 346 347 public double[][] fromReference(double[][] values) throws VisADException { 348/* 349 System.out.println("\nSubsetRubberBandBox fromReference double"); 350 System.out.println(" values[0]: " + values[0][0]); 351 System.out.println(" values[1]: " + values[1][0]); 352*/ 353 //- if (isLL) values = reverseArrayOrder(values); 354 double[][] new_values = displayCS.fromReference(values); 355 if (isLL) new_values = reverseArrayOrder(new_values); 356 new_values = dataCS.fromReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 357/* 358 System.out.println(" new_values[0]: " + new_values[0][0]); 359 System.out.println(" new_values[1]: " + new_values[1][0]); 360*/ 361 return new_values; 362 } 363 364 public boolean equals(Object obj) { 365 return true; 366 } 367 368 private double[][] reverseArrayOrder(double[][] in) { 369 if (in.length < 2) return in; 370 int len1 = 2; 371 int len2 = in[0].length; 372 double[][] out = new double[in.length][len2];; 373 for (int i=0; i<len1; i++) { 374 for (int j=0; j<len2; j++) { 375 out[len1-i-1][j] = in[i][j]; 376 } 377 } 378 if (in.length > 2) { 379 for (int i=2; i<in.length; i++) { 380 for (int j=0; j<len2; j++) { 381 out[i][j] = in[i][j]; 382 } 383 } 384 } 385 return out; 386 } 387 388 389 private float[][] reverseArrayOrder(float[][] in) { 390 if (in.length < 2) return in; 391 int len1 = 2; 392 int len2 = in[0].length; 393 float[][] out = new float[in.length][len2];; 394 for (int i=0; i<len1; i++) { 395 for (int j=0; j<len2; j++) { 396 out[len1-i-1][j] = in[i][j]; 397 } 398 } 399 if (in.length > 2) { 400 for (int i=2; i<in.length; i++) { 401 for (int j=0; j<len2; j++) { 402 out[i][j] = in[i][j]; 403 } 404 } 405 } 406 return out; 407 } 408}