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