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 */ 028package edu.wisc.ssec.mcidasv.data.hydra; 029 030import java.awt.BorderLayout; 031import java.awt.Color; 032import java.awt.FlowLayout; 033import java.awt.GridLayout; 034import java.awt.event.ActionEvent; 035import javax.swing.event.ChangeEvent; 036import java.awt.event.ActionListener; 037import javax.swing.event.ChangeListener; 038import java.net.URL; 039import java.rmi.RemoteException; 040import java.util.Map; 041import java.util.HashMap; 042import java.util.Hashtable; 043 044import javax.swing.JComponent; 045import javax.swing.JLabel; 046import javax.swing.JPanel; 047import javax.swing.JTextField; 048import javax.swing.JSlider; 049import javax.swing.DefaultBoundedRangeModel; 050 051import org.slf4j.Logger; 052import org.slf4j.LoggerFactory; 053 054import ucar.unidata.data.DataChoice; 055import ucar.unidata.data.DataSelection; 056import ucar.unidata.data.DataSelectionComponent; 057import ucar.unidata.data.GeoLocationInfo; 058import ucar.unidata.data.GeoSelection; 059import ucar.unidata.geoloc.projection.LatLonProjection; 060import ucar.unidata.view.geoloc.MapProjectionDisplay; 061import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D; 062import ucar.unidata.view.geoloc.MapProjectionDisplayJ2D; 063import ucar.unidata.geoloc.ProjectionRect; 064import ucar.visad.ProjectionCoordinateSystem; 065import ucar.visad.display.DisplayMaster; 066import ucar.visad.display.LineDrawing; 067import ucar.visad.display.MapLines; 068import ucar.visad.display.RubberBandBox; 069import visad.CellImpl; 070import visad.FlatField; 071import visad.Gridded2DSet; 072import visad.RealTupleType; 073import visad.RealType; 074import visad.SampledSet; 075import visad.UnionSet; 076import visad.VisADException; 077import visad.data.mcidas.BaseMapAdapter; 078import visad.georef.MapProjection; 079import visad.GriddedSet; 080 081public class TrackSelection extends DataSelectionComponent { 082 083 private static final Logger logger = LoggerFactory.getLogger(TrackSelection.class); 084 085 public static final int DEFAULT_TRACK_STRIDE = 5; 086 public static final int DEFAULT_VERTICAL_STRIDE = 2; 087 088 DataChoice dataChoice; 089 FlatField track; 090 091 double[] x_coords = new double[2]; 092 double[] y_coords = new double[2]; 093 MapProjectionDisplayJ2D mapProjDsp; 094 DisplayMaster dspMaster; 095 096 int trackStride; 097 int verticalStride; 098 099 JTextField trkStr; 100 JTextField vrtStr; 101 JTextField widthFld; 102 103 LineDrawing trackSelectDsp; 104 float[][] trackLocs; 105 int trackLen; 106 int trackPos; 107 int trackStart; 108 int trackStop; 109 double trackWidthPercent = 5; 110 int selectWidth; 111 Map defaultSubset; 112 113 TrackSelection(DataChoice dataChoice, FlatField track, Map defaultSubset) throws VisADException, RemoteException { 114 super("track"); 115 this.dataChoice = dataChoice; 116 this.track = track; 117 this.defaultSubset = defaultSubset; 118 119 GriddedSet gset = (GriddedSet)track.getDomainSet(); 120 float[] lo = gset.getLow(); 121 float[] hi = gset.getHi(); 122 float[][] values = gset.getSamples(); 123 124 trackLen = values[0].length; 125 selectWidth = (int) (trackLen*(trackWidthPercent/100)); 126 selectWidth /= 2; 127 trackPos = trackLen/2; 128 trackStart = trackPos - selectWidth; 129 trackStop = trackPos + selectWidth; 130 131 trackLocs = values; 132 Gridded2DSet track2D = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, new float[][] {values[0], values[1]}, values[0].length); 133 //mapProjDsp = new MapProjectionDisplayJ3D(MapProjectionDisplay.MODE_2Din3D); 134 mapProjDsp = new MapProjectionDisplayJ2D(); 135 //mapProjDsp.enableRubberBanding(false); 136 dspMaster = mapProjDsp; 137 mapProjDsp.setMapProjection(getDataProjection(new ProjectionRect(lo[0],lo[1],hi[0],hi[1]))); 138 LineDrawing trackDsp = new LineDrawing("track"); 139 trackDsp.setLineWidth(0.5f); 140 trackDsp.setData(track2D); 141 142 trackSelectDsp = new LineDrawing("trackSelect"); 143 trackSelectDsp.setLineWidth(3f); 144 trackSelectDsp.setColor(java.awt.Color.green); 145 146 updateTrackSelect(); 147 148 mapProjDsp.addDisplayable(trackDsp); 149 mapProjDsp.addDisplayable(trackSelectDsp); 150 151 MapLines mapLines = new MapLines("maplines"); 152 URL mapSource = mapProjDsp.getClass().getResource( 153 "/auxdata/maps/OUTLSUPU"); 154 try { 155 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 156 mapLines.setMapLines(mapAdapter.getData()); 157 mapLines.setColor(java.awt.Color.cyan); 158 //mapProjDsp.addDisplayable(mapLines); 159 } catch (Exception excp) { 160 logger.error("cannot open map file: " + mapSource, excp); 161 } 162 163 mapLines = new MapLines("maplines"); 164 mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW"); 165 try { 166 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 167 mapLines.setMapLines(mapAdapter.getData()); 168 mapLines.setColor(java.awt.Color.cyan); 169 mapProjDsp.addDisplayable(mapLines); 170 } catch (Exception excp) { 171 logger.error("cannot open map file: " + mapSource, excp); 172 } 173 174 mapLines = new MapLines("maplines"); 175 mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL"); 176 try { 177 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 178 mapLines.setMapLines(mapAdapter.getData()); 179 mapLines.setColor(java.awt.Color.cyan); 180 //mapProjDsp.addDisplayable(mapLines); 181 } catch (Exception excp) { 182 logger.error("cannot open map file: " + mapSource, excp); 183 } 184 185 dspMaster.draw(); 186 } 187 188 public MapProjection getDataProjection(ProjectionRect rect) { 189 MapProjection mp = null; 190 try { 191 mp = new ProjectionCoordinateSystem(new LatLonProjection("blah", rect)); 192 } catch (Exception e) { 193 logger.error("error getting data projection", e); 194 } 195 return mp; 196 } 197 198 protected JComponent doMakeContents() { 199 try { 200 JPanel panel = new JPanel(new BorderLayout()); 201 panel.add("Center", dspMaster.getDisplayComponent()); 202 203 JPanel stridePanel = new JPanel(new FlowLayout()); 204 trkStr = new JTextField(Integer.toString(TrackSelection.DEFAULT_TRACK_STRIDE), 3); 205 vrtStr = new JTextField(Integer.toString(TrackSelection.DEFAULT_VERTICAL_STRIDE), 3); 206 widthFld = new JTextField(Double.toString(trackWidthPercent), 3); 207 208 trkStr.addActionListener(new ActionListener() { 209 public void actionPerformed(ActionEvent ae) { 210 setTrackStride(Integer.valueOf(trkStr.getText().trim())); 211 } 212 }); 213 vrtStr.addActionListener(new ActionListener() { 214 public void actionPerformed(ActionEvent ae) { 215 setVerticalStride(Integer.valueOf(vrtStr.getText().trim())); 216 } 217 }); 218 widthFld.addActionListener(new ActionListener() { 219 public void actionPerformed(ActionEvent ae) { 220 setWidthPercent(Double.valueOf(widthFld.getText().trim())); 221 } 222 }); 223 224 stridePanel.add(new JLabel("Track Stride: ")); 225 stridePanel.add(trkStr); 226 stridePanel.add(new JLabel("Vertical Stride: ")); 227 stridePanel.add(vrtStr); 228 stridePanel.add(new JLabel("Width%: ")); 229 stridePanel.add(widthFld); 230 231 JPanel selectPanel = new JPanel(new GridLayout(2,0)); 232 DefaultBoundedRangeModel brm = new DefaultBoundedRangeModel(trackStart, 0, 0, trackLen); 233 JSlider trackSelect = new JSlider(brm); 234 trackSelect.addChangeListener( new ChangeListener() { 235 public void stateChanged(ChangeEvent e) { 236 trackPos = (int) ((JSlider)e.getSource()).getValue(); 237 updateTrackSelect(); 238 } 239 } 240 ); 241 selectPanel.add(trackSelect); 242 selectPanel.add(stridePanel); 243 panel.add("South", selectPanel); 244 245 return panel; 246 } catch (Exception e) { 247 logger.error("error creating contents", e); 248 } 249 return null; 250 } 251 252 public void setTrackStride(int stride) { 253 trackStride = stride; 254 } 255 256 public void setVerticalStride(int stride) { 257 verticalStride = stride; 258 } 259 260 public void setWidthPercent(double percent) { 261 trackWidthPercent = percent; 262 selectWidth = (int) (trackLen*(trackWidthPercent/100)); 263 selectWidth /= 2; 264 updateTrackSelect(); 265 } 266 267 /** 268 * Update Track Stride if input text box holds a positive integer. 269 * 270 * @return true if trackStride was updated 271 */ 272 273 public boolean setTrackStride() { 274 boolean setOk = false; 275 try { 276 int newStride = Integer.valueOf(trkStr.getText().trim()); 277 if (newStride >= 1) { 278 trackStride = newStride; 279 setOk = true; 280 } 281 else { 282 setOk = false; 283 } 284 } catch (NumberFormatException nfe) { 285 // do nothing, will return correct result code 286 } 287 return setOk; 288 } 289 290 /** 291 * Update Vertical Stride if input text box holds a positive integer. 292 * 293 * @return true if verticalStride was updated 294 */ 295 296 public boolean setVerticalStride() { 297 boolean setOk = false; 298 try { 299 int newStride = Integer.valueOf(vrtStr.getText().trim()); 300 if (newStride >= 1) { 301 verticalStride = newStride; 302 setOk = true; 303 } 304 else { 305 setOk = false; 306 } 307 } catch (NumberFormatException nfe) { 308 // do nothing, will return correct result code 309 } 310 return setOk; 311 } 312 313 /** 314 * Update Vertical Stride if input text box holds a positive integer. 315 * 316 * @return true if verticalStride was updated 317 */ 318 319 public boolean setWidthPercent() { 320 boolean setOk = false; 321 try { 322 double newWidth = Double.valueOf(widthFld.getText().trim()); 323 trackWidthPercent = newWidth; 324 setOk = true; 325 } catch (NumberFormatException nfe) { 326 // do nothing, will return correct result code 327 } 328 return setOk; 329 } 330 331 void updateTrackSelect() { 332 trackStart = trackPos - selectWidth; 333 if (trackStart < 0) trackStart = 0; 334 335 trackStop = trackPos + selectWidth; 336 if (trackStop >= trackLen) trackStop = trackLen - 1; 337 338 try { 339 Gridded2DSet trck = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 340 new float[][] {java.util.Arrays.copyOfRange(trackLocs[0], trackStart, trackStop), 341 java.util.Arrays.copyOfRange(trackLocs[1], trackStart, trackStop)}, 342 (trackStop - trackStart)); 343 trackSelectDsp.setData(trck); 344 } 345 catch (Exception exc) { 346 exc.printStackTrace(); 347 } 348 } 349 350 public void applyToDataSelection(DataSelection dataSelection) { 351 setTrackStride(); 352 setVerticalStride(); 353 setWidthPercent(); 354 355 HashMap subset = (HashMap) ((HashMap)defaultSubset).clone(); 356 double[] coords = (double[]) subset.get(ProfileAlongTrack.vertDim_name); 357 358 subset.put(ProfileAlongTrack.trackDim_name, new double[] {trackStart, trackStop, trackStride}); 359 subset.put(ProfileAlongTrack.vertDim_name, new double[] {coords[0], coords[1], verticalStride}); 360 361 362 MultiDimensionSubset select = new MultiDimensionSubset(subset); 363 364 Hashtable table = dataChoice.getProperties(); 365 table.put(MultiDimensionSubset.key, select); 366 367 table = dataSelection.getProperties(); 368 table.put(MultiDimensionSubset.key, select); 369 370 dataChoice.setDataSelection(dataSelection); 371 372 } 373}