001 /*
002 * $Id: HydraImageProbe.java,v 1.13 2012/02/19 17:35:38 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.control;
032
033 import java.awt.Color;
034 import java.rmi.RemoteException;
035 import java.text.DecimalFormat;
036
037 import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay;
038
039 import ucar.unidata.idv.control.LineProbeControl;
040 import ucar.unidata.util.LogUtil;
041 import ucar.visad.display.TextDisplayable;
042 import visad.CellImpl;
043 import visad.Data;
044 import visad.DataReference;
045 import visad.DataReferenceImpl;
046 import visad.FlatField;
047 import visad.MathType;
048 import visad.Real;
049 import visad.RealTuple;
050 import visad.RealTupleType;
051 import visad.Text;
052 import visad.TextType;
053 import visad.Tuple;
054 import visad.TupleType;
055 import visad.VisADException;
056 import visad.georef.EarthLocationTuple;
057
058 public class HydraImageProbe extends LineProbeControl {
059
060 private static final TupleType TUPTYPE = makeTupleType();
061
062 private DataReference positionRef = null;
063
064 private DataReference spectrumRef = null;
065
066 private Color currentColor = Color.MAGENTA;
067
068 private RealTuple currentPosition = null;
069
070 private Tuple locationValue = null;
071
072 private MultiSpectralDisplay display = null;
073
074 private TextDisplayable valueDisplay = null;
075
076 public HydraImageProbe() throws VisADException, RemoteException {
077 super();
078
079 currentPosition = new RealTuple(RealTupleType.Generic2D);
080
081 spectrumRef = new DataReferenceImpl(hashCode() + "_spectrumRef");
082 positionRef = new DataReferenceImpl(hashCode() + "_positionRef");
083
084 valueDisplay = createValueDisplayer(currentColor);
085
086 new Updater();
087 }
088
089 public void setDisplay(final MultiSpectralDisplay disp) throws VisADException, RemoteException {
090 display = disp;
091 display.addRef(spectrumRef, currentColor);
092 }
093
094 // triggered for both position and color changes.
095 protected void probePositionChanged(final RealTuple newPos) {
096 if (display == null)
097 return;
098
099 if (!currentPosition.equals(newPos)) {
100 updatePosition(newPos);
101 updateLocationValue();
102 updateSpectrum();
103 currentPosition = newPos;
104 }
105
106 Color tmp = getColor();
107 if (!currentColor.equals(tmp)) {
108 updateSpectrumColor(tmp);
109 currentColor = tmp;
110 }
111 }
112
113 public RealTuple getCurrentPosition() {
114 return currentPosition;
115 }
116
117 public Color getCurrentColor() {
118 return currentColor;
119 }
120
121 public TextDisplayable getValueDisplay() {
122 return valueDisplay;
123 }
124
125 public DataReference getSpectrumRef() {
126 return spectrumRef;
127 }
128
129 public DataReference getPositionRef() {
130 return positionRef;
131 }
132
133 public Tuple getLocationValue() {
134 return locationValue;
135 }
136
137 private void updateLocationValue() {
138 Tuple tup = null;
139
140 try {
141 RealTuple location = (RealTuple)positionRef.getData();
142 if (location == null)
143 return;
144
145 FlatField image = (FlatField)display.getImageDisplay().getData();
146 if (image == null)
147 return;
148
149 double[] vals = location.getValues();
150 if (vals[1] < -180)
151 vals[1] += 360f;
152
153 if (vals[1] > 180)
154 vals[1] -= 360f;
155
156 RealTuple lonLat = new RealTuple(RealTupleType.SpatialEarth2DTuple, new double[] { vals[1], vals[0] });
157 Real val = (Real)image.evaluate(lonLat, Data.NEAREST_NEIGHBOR, Data.NO_ERRORS);
158 float fval = (float)val.getValue();
159 tup = new Tuple(TUPTYPE, new Data[] { lonLat, new Text(TextType.Generic, Float.toString(fval)) });
160 valueDisplay.setData(tup);
161 } catch (Exception e) {
162 LogUtil.logException("HydraImageProbe.updateLocationValue", e);
163 }
164
165 if (tup != null)
166 locationValue = tup;
167 }
168
169 public void forceUpdateSpectrum() {
170 updateLocationValue();
171 updateSpectrum();
172 updatePosition(currentPosition);
173 }
174
175 private void updateSpectrum() {
176 try {
177 RealTuple tmp = (RealTuple)positionRef.getData();
178 FlatField spectrum = display.getMultiSpectralData().getSpectrum(tmp);
179 spectrumRef.setData(spectrum);
180 } catch (Exception e) {
181 LogUtil.logException("HydraImageProbe.updateSpectrum", e);
182 }
183 }
184
185 protected void updatePosition(final RealTuple position) {
186 double[] vals = position.getValues();
187 try {
188 EarthLocationTuple elt = (EarthLocationTuple)boxToEarth(
189 new double[] { vals[0], vals[1], 1.0 });
190
191 positionRef.setData(elt.getLatLonPoint());
192 } catch (Exception e) {
193 LogUtil.logException("HydraImageProbe.updatePosition", e);
194 }
195 }
196
197 private void updateSpectrumColor(final Color color) {
198 try {
199 display.updateRef(spectrumRef, color);
200 valueDisplay.setColor(color);
201 } catch (Exception e) {
202 LogUtil.logException("HydraImageProbe.updateColor", e);
203 }
204 }
205
206 private static TextDisplayable createValueDisplayer(final Color color)
207 throws VisADException, RemoteException
208 {
209 DecimalFormat fmt = new DecimalFormat();
210 fmt.setMaximumIntegerDigits(3);
211 fmt.setMaximumFractionDigits(1);
212
213 TextDisplayable td = new TextDisplayable(TextType.Generic);
214 td.setLineWidth(2f);
215 td.setColor(color);
216 td.setNumberFormat(fmt);
217
218 return td;
219 }
220
221 private static TupleType makeTupleType() {
222 TupleType t = null;
223 try {
224 t = new TupleType(new MathType[] {RealTupleType.SpatialEarth2DTuple,
225 TextType.Generic});
226 } catch (Exception e) {
227 LogUtil.logException("HydraImageProbe.makeTupleType", e);
228 }
229 return t;
230 }
231
232 private class Updater extends CellImpl {
233 public Updater() throws VisADException, RemoteException {
234 this.addReference(positionRef);
235 }
236
237 public void doAction() {
238
239 }
240 }
241 }