001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2017 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 029package edu.wisc.ssec.mcidasv.control; 030 031import java.awt.Color; 032import java.rmi.RemoteException; 033import java.text.DecimalFormat; 034 035import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay; 036 037import ucar.unidata.idv.control.LineProbeControl; 038import ucar.unidata.util.LogUtil; 039import ucar.visad.display.TextDisplayable; 040import visad.CellImpl; 041import visad.Data; 042import visad.DataReference; 043import visad.DataReferenceImpl; 044import visad.FlatField; 045import visad.MathType; 046import visad.Real; 047import visad.RealTuple; 048import visad.RealTupleType; 049import visad.Text; 050import visad.TextType; 051import visad.Tuple; 052import visad.TupleType; 053import visad.VisADException; 054import visad.georef.EarthLocationTuple; 055 056public 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}