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 java.awt.BorderLayout; 032import java.awt.Color; 033import java.awt.geom.Rectangle2D; 034import java.awt.event.ComponentEvent; 035import java.awt.event.ComponentListener; 036 037import java.net.URL; 038 039import java.rmi.RemoteException; 040 041import javax.swing.JComponent; 042import javax.swing.JPanel; 043 044import visad.BaseColorControl; 045import visad.CellImpl; 046import visad.FlatField; 047import visad.FunctionType; 048import visad.Gridded2DSet; 049import visad.RealTupleType; 050import visad.RealType; 051import visad.ScalarMap; 052import visad.VisADException; 053import visad.data.mcidas.BaseMapAdapter; 054import visad.georef.MapProjection; 055 056import ucar.visad.display.Displayable; 057import ucar.visad.display.DisplayMaster; 058import ucar.visad.display.LineDrawing; 059import ucar.visad.display.MapLines; 060 061import ucar.unidata.data.DataChoice; 062import ucar.unidata.data.DataSelection; 063import ucar.unidata.data.DataSourceImpl; 064import ucar.unidata.data.DataSelectionComponent; 065import ucar.unidata.data.GeoSelection; 066import ucar.unidata.data.grid.GridUtil; 067import ucar.unidata.idv.IdvObjectStore; 068import ucar.unidata.idv.MapViewManager; 069import ucar.unidata.util.Range; 070import ucar.unidata.view.geoloc.MapProjectionDisplay; 071import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D; 072 073import org.slf4j.Logger; 074import org.slf4j.LoggerFactory; 075 076import edu.wisc.ssec.mcidasv.data.hydra.HydraRGBDisplayable; 077import edu.wisc.ssec.mcidasv.data.hydra.MultiSpectralData; 078import edu.wisc.ssec.mcidasv.control.LambertAEA; 079 080public class GeoPreviewSelection extends DataSelectionComponent { 081 082 private static final Logger logger = LoggerFactory.getLogger(GeoPreviewSelection.class); 083 DataChoice dataChoice; 084 FlatField image; 085 boolean isLL; 086 MapProjection sampleProjection; 087 088 double[] x_coords = new double[2]; 089 double[] y_coords = new double[2]; 090 MapProjectionDisplayJ3D mapProjDsp; 091 DisplayMaster dspMaster; 092 MapViewManager mvm; 093 IdvObjectStore store; 094 095 final private GeoSubsetRubberBandBox rbb; 096 private int lineMag; 097 private int elementMag; 098 099 private GeoLatLonSelection laloSel; 100 101 private LineDrawing box; 102 103 public GeoPreviewSelection(DataSourceImpl dataSource, 104 DataChoice dataChoice, FlatField image, 105 GeoLatLonSelection laLoSel, 106 MapProjection sample, int lMag, int eMag, boolean showPreview) 107 throws VisADException, RemoteException { 108 super("Region"); 109 110 this.dataChoice = dataChoice; 111 this.image = image; 112 this.laloSel = laLoSel; 113 this.sampleProjection = sample; 114 115 if (lMag == 0) lMag = 1; 116 if (eMag == 0) eMag = 1; 117 this.lineMag = lMag; 118 this.elementMag = eMag; 119 sample = getDataProjection(); 120 121 if (this.sampleProjection == null) { 122 this.sampleProjection = sample; 123 } 124 125 isLL = sampleProjection.isLatLonOrder(); 126 mapProjDsp = new MapProjectionDisplayJ3D(MapProjectionDisplay.MODE_2Din3D); 127 mapProjDsp.enableRubberBanding(false); 128 dspMaster = mapProjDsp; 129 mapProjDsp.setMapProjection(sampleProjection); 130 RealType imageRangeType = (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 131 HydraRGBDisplayable imageDsp = new HydraRGBDisplayable("image", imageRangeType, null, true, null); 132 133 String name = this.dataChoice.getName(); 134 135 if (showPreview) { 136 if (name.startsWith("186_")) { 137 filterMissingValueABI(); 138 } 139 imageDsp.setData(image); 140 } 141 142 MapLines mapLines = new MapLines("maplines"); 143 URL mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPU"); 144 try { 145 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 146 mapLines.setMapLines(mapAdapter.getData()); 147 mapLines.setColor(java.awt.Color.cyan); 148 mapProjDsp.addDisplayable(mapLines); 149 } catch (Exception excp) { 150 logger.error("can't open map file="+mapSource, excp); 151 } 152 153 mapLines = new MapLines("maplines"); 154 mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW"); 155 try { 156 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 157 mapLines.setMapLines(mapAdapter.getData()); 158 mapLines.setColor(java.awt.Color.cyan); 159 mapProjDsp.addDisplayable(mapLines); 160 } catch (Exception excp) { 161 logger.error("can't open map file="+mapSource, excp); 162 } 163 164 mapLines = new MapLines("maplines"); 165 mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL"); 166 try { 167 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 168 mapLines.setMapLines(mapAdapter.getData()); 169 mapLines.setColor(java.awt.Color.cyan); 170 mapProjDsp.addDisplayable(mapLines); 171 } catch (Exception excp) { 172 logger.error("can't open map file="+mapSource, excp); 173 } 174 175 if (showPreview) { 176 dspMaster.addDisplayable(imageDsp); 177 } 178 rbb = new GeoSubsetRubberBandBox(isLL, image, ((MapProjectionDisplay)mapProjDsp).getDisplayCoordinateSystem(), 1); 179 mvm = new MapViewManager(dataSource.getDataContext().getIdv()); 180 store = dataSource.getDataContext().getIdv().getStore(); 181 rbb.setColor((Color)store.get(mvm.PREF_FGCOLOR, Color.GREEN)); 182 rbb.addAction(new CellImpl() { 183 public void doAction() throws VisADException, RemoteException { 184 eraseBox(); 185 forceCoords(); 186 } 187 }); 188 addRBB(); 189 makeBox(); 190 191 dspMaster.draw(); 192 ScalarMap colorMap = imageDsp.getColorMap(); 193 if (showPreview) { 194 Range[] range = GridUtil.fieldMinMax(this.image); 195 Range imageRange = range[0]; 196 int max; 197 int min; 198 double dMax = imageRange.getMax(); 199 double dMin = imageRange.getMin(); 200 DataSelection ds = this.dataChoice.getDataSelection(); 201 if (ds != null) { 202 GeoSelection gs = ds.getGeoSelection(); 203 } 204 if (name.endsWith("TEMP")) { 205 min = (int)(dMax); 206 max = (int)(dMin); 207 } else { 208 max = (int)(dMin); 209 min = (int)(dMax); 210 } 211 colorMap.setRange(min, max); 212 BaseColorControl clrCntrl = (BaseColorControl) colorMap.getControl(); 213 clrCntrl.setTable(BaseColorControl.initTableGreyWedge(new float[4][256], true)); 214 } 215 } 216 217 private void filterMissingValueABI() throws VisADException, RemoteException { 218 float missingValue = getMissingValueABI(); 219 float[][] values = image.getFloats(); 220 for (int i = 0; i < values[0].length; i++) { 221 if (values[0][i] == missingValue) { 222 values[0][i] = Float.NaN; 223 } 224 } 225 image.setSamples(values); 226 } 227 228 private float getMissingValueABI() { 229 String name = this.dataChoice.getName(); 230 if (!name.startsWith("186_")) { 231 throw new AssertionError("This method is only applicable to ABI"); 232 } 233 if (name.contains("_Band1_")) { 234 return 1023.0f; 235 } else if (name.contains("_Band2_")) { 236 return 4095.0f; 237 } else if (name.contains("_Band3_")) { 238 return 1023.0f; 239 } else if (name.contains("_Band4_")) { 240 return 2047.0f; 241 } else if (name.contains("_Band5_")) { 242 return 1023.0f; 243 } else if (name.contains("_Band6_")) { 244 return 1023.0f; 245 } else if (name.contains("_Band7_")) { 246 return 16383.0f; 247 } else if (name.contains("_Band8_")) { 248 return 4095.0f; 249 } else if (name.contains("_Band9_")) { 250 return 2047.0f; 251 } else if (name.contains("_Band10_")) { 252 return 4095.0f; 253 } else if (name.contains("_Band11_")) { 254 return 4095.0f; 255 } else if (name.contains("_Band12_")) { 256 return 2047.0f; 257 } else if (name.contains("_Band13_")) { 258 return 4095.0f; 259 } else if (name.contains("_Band14_")) { 260 return 4095.0f; 261 } else if (name.contains("_Band15_")) { 262 return 4095.0f; 263 } else if (name.contains("_Band16_")) { 264 return 1023.0f; 265 } else { 266 throw new AssertionError("Could not infer band from '"+name+'\''); 267 } 268 } 269 270 public MapProjection getDataProjection() { 271 MapProjection mp = null; 272 Rectangle2D rect = MultiSpectralData.getLonLatBoundingBox(image); 273 try { 274 mp = new LambertAEA(rect); 275 } catch (Exception e) { 276 logger.error("error while attempting to create new LambertAEA", e); 277 } 278 return mp; 279 } 280 281 public void initBox() { 282 this.drawBox(); 283 } 284 285 protected JComponent doMakeContents() { 286 try { 287 JPanel panel = new JPanel(new BorderLayout()); 288 panel.add("Center", dspMaster.getDisplayComponent()); 289 panel.addComponentListener (new ComponentListener() { 290 public void componentHidden(ComponentEvent ce) { 291 dspMaster.getDisplayComponent().setVisible(false); 292 } 293 public void componentShown(ComponentEvent ce) { 294 dspMaster.getDisplayComponent().setVisible(true); 295 drawBox(); 296 rbb.resetExtremes(); 297 } 298 public void componentMoved(ComponentEvent ce) { 299 } 300 public void componentResized(ComponentEvent ce) { 301 } 302 }); 303 return panel; 304 } 305 catch (Exception e) { 306 logger.error("error building preview panel", e); 307 } 308 return null; 309 } 310 311 public void setDataChoice(DataChoice choice) { 312 logger.trace("oldChoice={} newChoice={}", this.dataChoice, choice); 313 this.dataChoice = choice; 314 } 315 public DataChoice getDataChoice() { 316 return this.dataChoice; 317 } 318 319 private void forceCoords() { 320 float[] extrms = rbb.getRanges(); 321 x_coords[0] = (double)extrms[0]; 322 y_coords[0] = (double)extrms[1]; 323 x_coords[1] = (double)extrms[2]; 324 y_coords[1] = (double)extrms[3]; 325 326 int height = (int)(y_coords[1] - y_coords[0]); 327 int width = (int)(x_coords[1] - x_coords[0]); 328 if ((height < 1) || (width < 1)) return; 329 330 if (laloSel != null) { 331 int lineMid = (int)((y_coords[0] + y_coords[1])/2.0 + 0.5); 332 int eleMid = (int)((x_coords[0] + x_coords[1])/2.0 + 0.5); 333 double uLLine = y_coords[1]; 334 double uLEle = x_coords[0]; 335 if (height < 0) { 336 height *= -1; 337 uLLine = y_coords[0]; 338 } 339 if (width < 0) { 340 width *= -1; 341 uLEle = x_coords[1]; 342 } 343 344 int line = lineMid; 345 int ele = eleMid; 346 if (laloSel.getPlace().equals(laloSel.PLACE_ULEFT)) { 347 line = (int)Math.floor(uLLine + 0.5); 348 ele = (int)Math.floor(uLEle + 0.5); 349 } 350 351 int linRes = laloSel.getPreviewLineRes(); 352 int eleRes = laloSel.getPreviewEleRes(); 353 354 height *= linRes; 355 width *= eleRes; 356 laloSel.setBaseNumLines(height); 357 laloSel.setBaseNumElements(width); 358 359 this.lineMag = laloSel.getLineMag(); 360 this.elementMag = laloSel.getElementMag(); 361 if (lineMag > 0) { 362 height *= lineMag; 363 } else if (lineMag < 0) { 364 height /= -lineMag; 365 } 366 if (elementMag > 0) { 367 width *= elementMag; 368 } else if (elementMag < 0) { 369 width /= -elementMag; 370 } 371 372 Rectangle2D mapArea = sampleProjection.getDefaultMapArea(); 373 double previewXDim = mapArea.getWidth(); 374 double previewYDim = mapArea.getHeight(); 375 double dLin = (double)line; 376 double dEle = (double)ele; 377 if ((line < 0) || (dLin > previewYDim) || 378 (ele < 0) || (dEle > previewXDim)) { 379 line = -1; 380 ele = -1; 381 } 382 383// boolean lock = laloSel.getLockOn(); 384// laloSel.setLockOn(true); 385// int lineMag = 1; 386// int eleMag = 1; 387 laloSel.setNumLines(height); 388 laloSel.setNumEles(width); 389// laloSel.setBaseNumLines(height); 390// laloSel.setBaseNumElements(width); 391// laloSel.setLineMag(lineMag); 392// laloSel.setElementMag(eleMag); 393// laloSel.lineMagSlider.setValue(lineMag); 394// laloSel.setLRes(-1.0); 395// laloSel.elementMagSlider.setValue(eleMag); 396// laloSel.setERes(-1.0); 397// laloSel.amUpdating = true; 398// laloSel.lineMagSliderChanged(false); 399// laloSel.elementMagSliderChanged(false); 400// laloSel.amUpdating = false; 401// laloSel.setLockOn(lock); 402 403 laloSel.getGeoLocationInfo(line, ele); 404 String type = laloSel.getCoordinateType(); 405 int pos = 0; 406 if (laloSel.getPlace().equals(laloSel.PLACE_ULEFT)) pos = 1; 407 if (type.equals(laloSel.TYPE_LATLON)) { 408 double[][] pts = laloSel.getLatLonPoints(); 409 laloSel.setLatitude(pts[0][pos]); 410 laloSel.setLongitude(pts[1][pos]); 411 laloSel.convertToLineEle(); 412 } else { 413 double[][] pts = laloSel.getImagePoints(); 414 if (type.equals(laloSel.TYPE_AREA)) 415 pts = laloSel.getAreaPoints(); 416 laloSel.setElement((int)Math.floor(pts[0][pos] + 0.5)); 417 laloSel.setLine((int)Math.floor(pts[1][pos] + 0.5)); 418 laloSel.setLineElement(); 419 laloSel.convertToLatLon(); 420 } 421 } 422 } 423 424 @Override public void applyToDataSelection(DataSelection dataSelection) { 425 } 426 427 @Override public boolean getShowInControlProperties() { 428 return false; 429 } 430 431 public void drawBox() { 432 if (box == null) makeBox(); 433 removeRBB(); 434 435 double[][] elelin = laloSel.getDisplayELPoints(); 436 if (elelin == null) return; 437 438 for (int i=0; i<2; i++) { 439 for (int j=0; j<5; j++) { 440 Double val = new Double(elelin[i][j]); 441 if (val.isNaN()) { 442 eraseBox(); 443 return; 444 } 445 } 446 } 447 448 float[][] floatVals = new float[][] { 449 { (float)elelin[0][0], (float)elelin[0][1], (float)elelin[0][2], 450 (float)elelin[0][3], (float)elelin[0][4] }, 451 { (float)elelin[1][0], (float)elelin[1][1], (float)elelin[1][2], 452 (float)elelin[1][3], (float)elelin[1][4] }}; 453 454 float[][] dispVals = new float[][] { 455 { floatVals[0][1], floatVals[0][2], floatVals[0][4], 456 floatVals[0][3], floatVals[0][1] }, 457 { floatVals[1][1], floatVals[1][2], floatVals[1][4], 458 floatVals[1][3], floatVals[1][1] } 459 }; 460 461 try { 462 float[][] refVals = rbb.getDisplayCoordSystem().toReference(dispVals); 463 Gridded2DSet set = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, 464 refVals, 5); 465 box.setData(set); 466 } catch (Exception e) { 467 logger.error("error drawing box", e); 468 } 469 } 470 471 private void makeBox() { 472 if (box == null) { 473 try { 474 box = new LineDrawing("box"); 475 box.setColor((Color)store.get(mvm.PREF_FGCOLOR, Color.GREEN)); 476 dspMaster.addDisplayable(box); 477 } catch (Exception e) { 478 logger.error("error making box", e); 479 } 480 } 481 } 482 483 private void eraseBox() { 484 Gridded2DSet set = null; 485 if (box == null) makeBox(); 486 try { 487 set = new Gridded2DSet(RealTupleType.LatitudeLongitudeTuple, 488 new float[][] { 489 { (float)0.0, (float)0.0 }, 490 { (float)0.0, (float)0.0 }, 491 }, 2); 492 box.setData(set); 493 } catch (Exception e) { 494 logger.error("error erasing box", e); 495 } 496 addRBB(); 497 } 498 499 private boolean rBBPresent() { 500 Displayable[] dsps = dspMaster.getDisplayables(); 501 if (dsps.length > 0) { 502 for (int i = 0; i < dsps.length; i++) { 503 Displayable disp = dsps[i]; 504 if (disp == (Displayable)rbb) { 505 return true; 506 } 507 } 508 } 509 return false; 510 } 511 512 private void removeRBB() { 513 if (rBBPresent()) { 514 try { 515 dspMaster.removeDisplayable(rbb); 516 } catch (Exception e) { 517 logger.error("error removing rubberband box", e); 518 } 519 } 520 addRBB(); 521 } 522 523 private void addRBB() { 524 if (!rBBPresent()) { 525 try { 526 dspMaster.addDisplayable(rbb); 527 } catch (Exception e) { 528 logger.error("error adding rubberband box", e); 529 } 530 } 531 } 532}