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