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