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