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