001/* 002 * $Id: HydraImageProbe.java,v 1.12 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.control; 032 033import java.awt.Color; 034import java.rmi.RemoteException; 035import java.text.DecimalFormat; 036 037import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay; 038 039import ucar.unidata.idv.control.LineProbeControl; 040import ucar.unidata.util.LogUtil; 041import ucar.visad.display.TextDisplayable; 042import visad.CellImpl; 043import visad.Data; 044import visad.DataReference; 045import visad.DataReferenceImpl; 046import visad.FlatField; 047import visad.MathType; 048import visad.Real; 049import visad.RealTuple; 050import visad.RealTupleType; 051import visad.Text; 052import visad.TextType; 053import visad.Tuple; 054import visad.TupleType; 055import visad.VisADException; 056import visad.georef.EarthLocationTuple; 057 058public 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}