001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 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 029package edu.wisc.ssec.mcidasv.data; 030 031import edu.wisc.ssec.mcidasv.data.hydra.MyRubberBandBoxRendererJ3D; 032import edu.wisc.ssec.mcidasv.data.hydra.SubsetRubberBandBox; 033//import edu.wisc.ssec.mcidasv.data.hydra.DataToDisplayCoordinateSystem; 034 035import ucar.unidata.view.geoloc.MapProjectionDisplay; 036import ucar.visad.display.Displayable; 037import ucar.visad.display.DisplayMaster; 038import ucar.visad.display.LineDrawing; 039 040import visad.*; 041import visad.bom.*; 042import visad.georef.MapProjection; 043 044import java.rmi.RemoteException; 045 046import java.awt.event.InputEvent; 047 048 049public 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 data 084 * @param displayCS 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 * Construct a RubberBandBox using xType as the X coordinate and 111 * yType as the Y coordinate of the box. 112 * 113 * @param isLL 114 * @param data 115 * @param displayCS 116 * @param mask Key mask to use for rubberbanding 117 * @param lastBoxOn 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 DisplayRealType displayLineType = 148 new DisplayRealType("displayLine_"+count, true, 0.0, 10000.0, 0.0, null); 149 DisplayRealType displayElemType = 150 new DisplayRealType("displayElem_"+count, true, 0.0, 10000.0, 0.0, null); 151 DisplayRealType displayAltType = 152 new DisplayRealType("displayAlt_"+count, true, -1.0, 1.0, 0.0, null); 153 DisplayTupleType dtt = 154 new DisplayTupleType(new DisplayRealType[] {displayLineType, displayElemType, displayAltType}, new_cs); 155 156 RealType elemType = RealType.getRealType("elem_"+count); 157 RealType lineType = RealType.getRealType("line_"+count); 158 this.xType = lineType; 159 this.yType = elemType; 160 this.mask = mask; 161 bounds = new Gridded2DSet(new RealTupleType(xType, yType), null, 1); 162 163 ScalarMap elemMap = new ScalarMap(elemType, displayElemType); 164 ScalarMap lineMap = new ScalarMap(lineType, displayLineType); 165 166 GriddedSet domainSet = (GriddedSet) data.getDomainSet(); 167 float[] low = domainSet.getLow(); 168 float[] hi = domainSet.getHi(); 169 170 elemMap.setRange(low[1], hi[1]); 171 lineMap.setRange(low[0], hi[0]); 172 173 addScalarMap(elemMap); 174 addScalarMap(lineMap); 175 176 setData(bounds); 177 count += 1; 178 } 179 180 /** 181 * Constructor for creating a RubberBandBox from another instance 182 * 183 * @param that other instance 184 * 185 * @throws VisADException VisAD error 186 * @throws RemoteException Remote error 187 */ 188 protected GeoSubsetRubberBandBox(GeoSubsetRubberBandBox that) 189 throws VisADException, RemoteException { 190 191 super(that); 192 } 193 194 protected void setDisplayMaster(DisplayMaster dspMaster) { 195 dispMaster = dspMaster; 196 new_cs.setDisplayMaster(dispMaster); 197 } 198 199 public float[] getRanges() { 200 float[] extrms = new_cs.getExtremes(); 201 resetExtremes(); 202 return extrms; 203 } 204 205 protected void resetExtremes() { 206 new_cs.resetExtremes(); 207 } 208 209 protected GeoDataToDisplayCoordinateSystem getDisplayCoordSystem() { 210 return new_cs; 211 } 212} 213 214class GeoDataToDisplayCoordinateSystem extends CoordinateSystem { 215 private CoordinateSystem dataCS; 216 private CoordinateSystem displayCS; 217 private boolean isLL; 218 private MapProjectionDisplay mapProjDisp; 219 private double scaleX; 220 private double scaleY; 221 private double offsetX; 222 private double offsetY; 223 224 private float lineLo; 225 private float lineHi; 226 private float eleLo; 227 private float eleHi; 228 229 GeoDataToDisplayCoordinateSystem(boolean isLL, CoordinateSystem dataCS, CoordinateSystem displayCS) throws VisADException { 230 super(displayCS.getReference(), null); 231 try { 232 this.dataCS = dataCS; 233 this.displayCS = displayCS; 234 this.isLL = isLL; 235 } catch (Exception e) { 236 System.out.println("e=" + e); 237 } 238 } 239 240 protected void setDisplayMaster(DisplayMaster dspMaster) { 241 if (dspMaster instanceof MapProjectionDisplay) { 242 mapProjDisp = (MapProjectionDisplay)dspMaster; 243 this.mapProjDisp = mapProjDisp; 244 MapProjection mapProj = mapProjDisp.getMapProjection(); 245 java.awt.geom.Rectangle2D bounds = 246 mapProj.getDefaultMapArea(); 247 scaleX = bounds.getWidth() / 2.0; 248 scaleY = bounds.getHeight() / 2.0; 249 offsetX = bounds.getX() + scaleX; 250 offsetY = bounds.getY() + scaleY; 251 } 252 } 253 254 public float[] getExtremes() { 255 float[] extremes = new float[4]; 256 extremes[0] = eleLo; 257 extremes[1] = lineLo; 258 extremes[2] = eleHi; 259 extremes[3] = lineHi; 260 return extremes; 261 } 262 263 public void resetExtremes() { 264 lineLo = (float)99999.0; 265 lineHi = (float)0.0; 266 eleLo = (float)99999.0; 267 eleHi = (float)0.0; 268 } 269 270 public float[][] toReference(float[][] values) throws VisADException { 271 272 if (values[0][0] < eleLo) eleLo = values[0][0]; 273 if (values[0][0] > eleHi) eleHi = values[0][0]; 274 if (values[1][0] < lineLo) lineLo = values[1][0]; 275 if (values[1][0] > lineHi) lineHi = values[1][0]; 276 277 float[][] new_values = bypassToReference(values); 278 return new_values; 279 } 280 281 private float[][] bypassToReference(float[][] xyz) { 282 if ((xyz == null) || (xyz[0].length < 1)) { 283 return xyz; 284 } 285 int numpoints = xyz[0].length; 286 float x, y; 287 float[]t2ax = xyz[0]; 288 float[]t2ay = xyz[1]; 289 for (int i = 0; i < numpoints; i++) { 290 float t2x = t2ax[i]; 291 float t2y = t2ay[i]; 292 if (t2x!=t2x || t2y!=t2y) { 293 x = Float.NaN; 294 y = Float.NaN; 295 } else { 296 x = (float) ((t2x - offsetX) / scaleX); 297 y = (float) ((t2y - offsetY) / scaleY); 298 } 299 xyz[0][i] = x; 300 xyz[1][i] = y; 301 } 302 return xyz; 303 } 304 305 public float[][] fromReference(float[][] values) throws VisADException { 306 float[][] new_values = bypassFromReference(values); 307 return new_values; 308 } 309 310 /** 311 * Transform display XYZ values to latitude/longitude/altitude 312 * 313 * @param xyz array of Display.DisplaySpatialCartesianTuple XYZ values 314 * @return array of display lat/lon/alt values. 315 * 316 * @throws VisADException can't create the necessary VisAD object 317 */ 318 private float[][] bypassFromReference(float[][] xyz) throws VisADException { 319 if ((xyz == null) || (xyz[0].length < 1)) { 320 return xyz; 321 } 322 int numpoints = xyz[0].length; 323 for (int i = 0; i < numpoints; i++) { 324 if (Float.isNaN(xyz[0][i]) || Float.isNaN(xyz[0][i])) { 325 continue; 326 } 327 xyz[0][i] = (float) (xyz[0][i] * scaleX + offsetX); 328 xyz[1][i] = (float) (xyz[1][i] * scaleY + offsetY); 329 } 330 return xyz; 331 } 332 333 public double[][] toReference(double[][] values) throws VisADException { 334 //- if (isLL) values = reverseArrayOrder(values); 335 double[][] new_values = dataCS.toReference(values); 336 if (isLL) new_values = reverseArrayOrder(new_values); 337 new_values = displayCS.toReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 338 return new_values; 339 } 340 341 342 public double[][] fromReference(double[][] values) throws VisADException { 343 //- if (isLL) values = reverseArrayOrder(values); 344 double[][] new_values = displayCS.fromReference(values); 345 if (isLL) new_values = reverseArrayOrder(new_values); 346 new_values = dataCS.fromReference(new double[][] {new_values[1], new_values[0], new_values[2]}); 347 return new_values; 348 } 349 350 public boolean equals(Object obj) { 351 return true; 352 } 353 354 private double[][] reverseArrayOrder(double[][] in) { 355 if (in.length < 2) return in; 356 int len1 = 2; 357 int len2 = in[0].length; 358 double[][] out = new double[in.length][len2];; 359 for (int i=0; i<len1; i++) { 360 for (int j=0; j<len2; j++) { 361 out[len1-i-1][j] = in[i][j]; 362 } 363 } 364 if (in.length > 2) { 365 for (int i=2; i<in.length; i++) { 366 for (int j=0; j<len2; j++) { 367 out[i][j] = in[i][j]; 368 } 369 } 370 } 371 return out; 372 } 373 374 375 private float[][] reverseArrayOrder(float[][] in) { 376 if (in.length < 2) return in; 377 int len1 = 2; 378 int len2 = in[0].length; 379 float[][] out = new float[in.length][len2];; 380 for (int i=0; i<len1; i++) { 381 for (int j=0; j<len2; j++) { 382 out[len1-i-1][j] = in[i][j]; 383 } 384 } 385 if (in.length > 2) { 386 for (int i=2; i<in.length; i++) { 387 for (int j=0; j<len2; j++) { 388 out[i][j] = in[i][j]; 389 } 390 } 391 } 392 return out; 393 } 394}