001 /* 002 * $Id: GeoSubsetRubberBandBox.java,v 1.11 2012/02/19 17:35:45 davep 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; 032 033 import edu.wisc.ssec.mcidasv.data.hydra.MyRubberBandBoxRendererJ3D; 034 import edu.wisc.ssec.mcidasv.data.hydra.SubsetRubberBandBox; 035 //import edu.wisc.ssec.mcidasv.data.hydra.DataToDisplayCoordinateSystem; 036 037 import ucar.unidata.view.geoloc.MapProjectionDisplay; 038 import ucar.visad.display.Displayable; 039 import ucar.visad.display.DisplayMaster; 040 import ucar.visad.display.LineDrawing; 041 042 import visad.*; 043 import visad.bom.*; 044 import visad.georef.MapProjection; 045 046 import java.rmi.RemoteException; 047 048 import java.awt.event.InputEvent; 049 050 051 public class GeoSubsetRubberBandBox extends SubsetRubberBandBox { 052 053 /** x type for the box */ 054 private RealType xType; 055 056 /** y type for the box */ 057 private RealType yType; 058 059 /** renderer */ 060 private MyRubberBandBoxRendererJ3D rubberBandBox; 061 062 /** bounds defined by the rubber band box */ 063 private Gridded2DSet bounds; 064 065 /** mouse event mask */ 066 private int mask; 067 068 private FlatField data; 069 private boolean isLL; 070 private boolean lastBoxOn; 071 072 private CoordinateSystem dataCS; 073 074 private CoordinateSystem displayCS; 075 private DisplayMaster dispMaster; 076 077 private GeoDataToDisplayCoordinateSystem new_cs; 078 079 private static int count = 0; 080 081 /** 082 * Construct a RubberBandBox using xType as the X coordinate and 083 * yType as the Y coordinate of the box. 084 * 085 * @param xType RealType of the X coordinate of the box 086 * @param yType RealType of the Y coordinate of the box 087 * 088 * @throws VisADException VisAD error 089 * @throws RemoteException Remote error 090 */ 091 public GeoSubsetRubberBandBox(FlatField data, CoordinateSystem displayCS) 092 throws VisADException, RemoteException { 093 this(false, data, displayCS, 0); 094 } 095 096 public GeoSubsetRubberBandBox(FlatField data, CoordinateSystem displayCS, int mask) 097 throws VisADException, RemoteException { 098 this(false, data, displayCS, mask); 099 } 100 101 public GeoSubsetRubberBandBox(boolean isLL, FlatField data, CoordinateSystem displayCS, int mask) 102 throws VisADException, RemoteException { 103 this(isLL, data, displayCS, mask, true); 104 } 105 106 public GeoSubsetRubberBandBox(FlatField data, CoordinateSystem displayCS, int mask, boolean lastBoxOn) 107 throws VisADException, RemoteException { 108 this(false, data, displayCS, mask, lastBoxOn); 109 } 110 111 112 113 /** 114 * Construct a RubberBandBox using xType as the X coordinate and 115 * yType as the Y coordinate of the box. 116 * 117 * @param xType RealType of the X coordinate of the box 118 * @param yType RealType of the Y coordinate of the box 119 * @param mask key mask to use for rubberbanding 120 * 121 * @throws VisADException VisAD error 122 * @throws RemoteException Remote error 123 */ 124 public GeoSubsetRubberBandBox(boolean isLL, FlatField data, CoordinateSystem displayCS, int mask, boolean lastBoxOn) 125 throws VisADException, RemoteException { 126 super(isLL, data, displayCS, mask, lastBoxOn); 127 128 this.data = data; 129 this.displayCS = displayCS; 130 this.isLL = isLL; 131 this.lastBoxOn = lastBoxOn; 132 133 RealTupleType rtype = ((FunctionType)data.getType()).getDomain(); 134 dataCS = rtype.getCoordinateSystem(); 135 if (dataCS == null) { 136 dataCS = new GridCoordinateSystem((GriddedSet)data.getDomainSet()); 137 } 138 139 IdentityCoordinateSystem iCS = 140 new IdentityCoordinateSystem( 141 new RealTupleType(new RealType[] {RealType.getRealType("ZZtop")})); 142 143 CoordinateSystem cs = 144 new CartesianProductCoordinateSystem(new CoordinateSystem[] {dataCS, iCS}); 145 146 new_cs = new GeoDataToDisplayCoordinateSystem(isLL, cs, displayCS); 147 resetExtremes(); 148 149 150 DisplayRealType displayLineType = 151 new DisplayRealType("displayLine_"+count, true, 0.0, 10000.0, 0.0, null); 152 DisplayRealType displayElemType = 153 new DisplayRealType("displayElem_"+count, true, 0.0, 10000.0, 0.0, null); 154 DisplayRealType displayAltType = 155 new DisplayRealType("displayAlt_"+count, true, -1.0, 1.0, 0.0, null); 156 DisplayTupleType dtt = 157 new DisplayTupleType(new DisplayRealType[] {displayLineType, displayElemType, displayAltType}, new_cs); 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 166 ScalarMap elemMap = new ScalarMap(elemType, displayElemType); 167 ScalarMap lineMap = new ScalarMap(lineType, displayLineType); 168 169 GriddedSet domainSet = (GriddedSet) data.getDomainSet(); 170 float[] low = domainSet.getLow(); 171 float[] hi = domainSet.getHi(); 172 173 elemMap.setRange(low[1], hi[1]); 174 lineMap.setRange(low[0], hi[0]); 175 176 addScalarMap(elemMap); 177 addScalarMap(lineMap); 178 179 setData(bounds); 180 count += 1; 181 } 182 183 /** 184 * Constructor for creating a RubberBandBox from another instance 185 * 186 * @param that other instance 187 * 188 * @throws VisADException VisAD error 189 * @throws RemoteException Remote error 190 */ 191 protected GeoSubsetRubberBandBox(GeoSubsetRubberBandBox that) 192 throws VisADException, RemoteException { 193 194 super(that); 195 } 196 197 protected void setDisplayMaster(DisplayMaster dspMaster) { 198 dispMaster = dspMaster; 199 new_cs.setDisplayMaster(dispMaster); 200 } 201 202 public float[] getRanges() { 203 float[] extrms = new_cs.getExtremes(); 204 resetExtremes(); 205 return extrms; 206 } 207 208 protected void resetExtremes() { 209 new_cs.resetExtremes(); 210 } 211 212 protected GeoDataToDisplayCoordinateSystem getDisplayCoordSystem() { 213 return new_cs; 214 } 215 } 216 217 class GeoDataToDisplayCoordinateSystem extends CoordinateSystem { 218 private CoordinateSystem dataCS; 219 private CoordinateSystem displayCS; 220 private boolean isLL; 221 private MapProjectionDisplay mapProjDisp; 222 private double scaleX; 223 private double scaleY; 224 private double offsetX; 225 private double offsetY; 226 227 private float lineLo; 228 private float lineHi; 229 private float eleLo; 230 private float eleHi; 231 232 GeoDataToDisplayCoordinateSystem(boolean isLL, CoordinateSystem dataCS, CoordinateSystem displayCS) throws VisADException { 233 super(displayCS.getReference(), null); 234 try { 235 this.dataCS = dataCS; 236 this.displayCS = displayCS; 237 this.isLL = isLL; 238 } catch (Exception e) { 239 System.out.println("e=" + e); 240 } 241 } 242 243 protected void setDisplayMaster(DisplayMaster dspMaster) { 244 if (dspMaster instanceof MapProjectionDisplay) { 245 mapProjDisp = (MapProjectionDisplay)dspMaster; 246 this.mapProjDisp = mapProjDisp; 247 MapProjection mapProj = mapProjDisp.getMapProjection(); 248 java.awt.geom.Rectangle2D bounds = 249 mapProj.getDefaultMapArea(); 250 scaleX = bounds.getWidth() / 2.0; 251 scaleY = bounds.getHeight() / 2.0; 252 offsetX = bounds.getX() + scaleX; 253 offsetY = bounds.getY() + scaleY; 254 } 255 } 256 257 public float[] getExtremes() { 258 float[] extremes = new float[4]; 259 extremes[0] = eleLo; 260 extremes[1] = lineLo; 261 extremes[2] = eleHi; 262 extremes[3] = lineHi; 263 return extremes; 264 } 265 266 public void resetExtremes() { 267 lineLo = (float)99999.0; 268 lineHi = (float)0.0; 269 eleLo = (float)99999.0; 270 eleHi = (float)0.0; 271 } 272 273 public float[][] toReference(float[][] values) throws VisADException { 274 275 if (values[0][0] < eleLo) eleLo = values[0][0]; 276 if (values[0][0] > eleHi) eleHi = values[0][0]; 277 if (values[1][0] < lineLo) lineLo = values[1][0]; 278 if (values[1][0] > lineHi) lineHi = values[1][0]; 279 280 float[][] new_values = bypassToReference(values); 281 return new_values; 282 } 283 284 private float[][] bypassToReference(float[][] xyz) { 285 if ((xyz == null) || (xyz[0].length < 1)) { 286 return xyz; 287 } 288 int numpoints = xyz[0].length; 289 float x, y; 290 float[]t2ax = xyz[0]; 291 float[]t2ay = xyz[1]; 292 for (int i = 0; i < numpoints; i++) { 293 float t2x = t2ax[i]; 294 float t2y = t2ay[i]; 295 if (t2x!=t2x || t2y!=t2y) { 296 x = Float.NaN; 297 y = Float.NaN; 298 } else { 299 x = (float) ((t2x - offsetX) / scaleX); 300 y = (float) ((t2y - offsetY) / scaleY); 301 } 302 xyz[0][i] = x; 303 xyz[1][i] = y; 304 } 305 return xyz; 306 } 307 308 public float[][] fromReference(float[][] values) throws VisADException { 309 float[][] new_values = bypassFromReference(values); 310 return new_values; 311 } 312 313 /** 314 * Transform display XYZ values to latitude/longitude/altitude 315 * 316 * @param xyz array of Display.DisplaySpatialCartesianTuple XYZ values 317 * @return array of display lat/lon/alt values. 318 * 319 * @throws VisADException can't create the necessary VisAD object 320 */ 321 private float[][] bypassFromReference(float[][] xyz) throws VisADException { 322 if ((xyz == null) || (xyz[0].length < 1)) { 323 return xyz; 324 } 325 int numpoints = xyz[0].length; 326 for (int i = 0; i < numpoints; i++) { 327 if (Float.isNaN(xyz[0][i]) || Float.isNaN(xyz[0][i])) { 328 continue; 329 } 330 xyz[0][i] = (float) (xyz[0][i] * scaleX + offsetX); 331 xyz[1][i] = (float) (xyz[1][i] * scaleY + offsetY); 332 } 333 return xyz; 334 } 335 336 public double[][] toReference(double[][] values) throws VisADException { 337 //- if (isLL) values = reverseArrayOrder(values); 338 double[][] new_values = dataCS.toReference(values); 339 if (isLL) new_values = reverseArrayOrder(new_values); 340 new_values = displayCS.toReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 341 return new_values; 342 } 343 344 345 public double[][] fromReference(double[][] values) throws VisADException { 346 //- if (isLL) values = reverseArrayOrder(values); 347 double[][] new_values = displayCS.fromReference(values); 348 if (isLL) new_values = reverseArrayOrder(new_values); 349 new_values = dataCS.fromReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 350 return new_values; 351 } 352 353 public boolean equals(Object obj) { 354 return true; 355 } 356 357 private double[][] reverseArrayOrder(double[][] in) { 358 if (in.length < 2) return in; 359 int len1 = 2; 360 int len2 = in[0].length; 361 double[][] out = new double[in.length][len2];; 362 for (int i=0; i<len1; i++) { 363 for (int j=0; j<len2; j++) { 364 out[len1-i-1][j] = in[i][j]; 365 } 366 } 367 if (in.length > 2) { 368 for (int i=2; i<in.length; i++) { 369 for (int j=0; j<len2; j++) { 370 out[i][j] = in[i][j]; 371 } 372 } 373 } 374 return out; 375 } 376 377 378 private float[][] reverseArrayOrder(float[][] in) { 379 if (in.length < 2) return in; 380 int len1 = 2; 381 int len2 = in[0].length; 382 float[][] out = new float[in.length][len2];; 383 for (int i=0; i<len1; i++) { 384 for (int j=0; j<len2; j++) { 385 out[len1-i-1][j] = in[i][j]; 386 } 387 } 388 if (in.length > 2) { 389 for (int i=2; i<in.length; i++) { 390 for (int j=0; j<len2; j++) { 391 out[i][j] = in[i][j]; 392 } 393 } 394 } 395 return out; 396 } 397 }