001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2016
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.event.ActionEvent;
034import java.awt.event.ActionListener;
035import java.net.URL;
036import java.rmi.RemoteException;
037
038import javax.swing.JComponent;
039import javax.swing.JLabel;
040import javax.swing.JPanel;
041import javax.swing.JTextField;
042
043import org.slf4j.Logger;
044import org.slf4j.LoggerFactory;
045
046import ucar.unidata.data.DataChoice;
047import ucar.unidata.data.DataSelection;
048import ucar.unidata.data.DataSelectionComponent;
049import ucar.unidata.data.GeoLocationInfo;
050import ucar.unidata.data.GeoSelection;
051import ucar.unidata.geoloc.projection.LatLonProjection;
052import ucar.unidata.view.geoloc.MapProjectionDisplay;
053import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D;
054import ucar.visad.ProjectionCoordinateSystem;
055import ucar.visad.display.DisplayMaster;
056import ucar.visad.display.LineDrawing;
057import ucar.visad.display.MapLines;
058import ucar.visad.display.RubberBandBox;
059import visad.CellImpl;
060import visad.FlatField;
061import visad.Gridded2DSet;
062import visad.RealTupleType;
063import visad.RealType;
064import visad.SampledSet;
065import visad.UnionSet;
066import visad.VisADException;
067import visad.data.mcidas.BaseMapAdapter;
068import visad.georef.MapProjection;
069
070public class TrackSelection extends DataSelectionComponent {
071
072        private static final Logger logger = LoggerFactory.getLogger(TrackSelection.class);
073        
074        public static final int DEFAULT_TRACK_STRIDE = 5;
075        public static final int DEFAULT_VERTICAL_STRIDE = 2;
076        
077        DataChoice dataChoice;
078        FlatField track;
079
080        double[] x_coords = new double[2];
081        double[] y_coords = new double[2];
082        boolean hasSubset = true;
083        MapProjectionDisplayJ3D mapProjDsp;
084        DisplayMaster dspMaster;
085
086        int trackStride;
087        int verticalStride;
088
089        JTextField trkStr;
090        JTextField vrtStr;
091        MultiDimensionDataSource datSrc;
092
093        TrackSelection(DataChoice dataChoice, FlatField track,
094                        MultiDimensionDataSource datSrc) throws VisADException, RemoteException {
095                super("track");
096                this.dataChoice = dataChoice;
097                this.track = track;
098                this.datSrc = datSrc;
099                mapProjDsp = new MapProjectionDisplayJ3D(
100                                MapProjectionDisplay.MODE_2Din3D);
101                mapProjDsp.enableRubberBanding(false);
102                dspMaster = mapProjDsp;
103                mapProjDsp.setMapProjection(getDataProjection());
104                LineDrawing trackDsp = new LineDrawing("track");
105                trackDsp.setLineWidth(2f);
106                trackDsp.setData(track);
107                mapProjDsp.addDisplayable(trackDsp);
108
109                MapLines mapLines = new MapLines("maplines");
110                URL mapSource = mapProjDsp.getClass().getResource(
111                                "/auxdata/maps/OUTLSUPU");
112                try {
113                        BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
114                        mapLines.setMapLines(mapAdapter.getData());
115                        mapLines.setColor(java.awt.Color.cyan);
116                        mapProjDsp.addDisplayable(mapLines);
117                } catch (Exception excp) {
118                        logger.error("cannot open map file: " + mapSource, excp);
119                }
120
121                mapLines = new MapLines("maplines");
122                mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW");
123                try {
124                        BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
125                        mapLines.setMapLines(mapAdapter.getData());
126                        mapLines.setColor(java.awt.Color.cyan);
127                        mapProjDsp.addDisplayable(mapLines);
128                } catch (Exception excp) {
129                        logger.error("cannot open map file: " + mapSource, excp);
130                }
131
132                mapLines = new MapLines("maplines");
133                mapSource = mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL");
134                try {
135                        BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
136                        mapLines.setMapLines(mapAdapter.getData());
137                        mapLines.setColor(java.awt.Color.cyan);
138                        mapProjDsp.addDisplayable(mapLines);
139                } catch (Exception excp) {
140                        logger.error("cannot open map file: " + mapSource, excp);
141                }
142
143                final LineDrawing selectBox = new LineDrawing("select");
144                selectBox.setColor(Color.green);
145
146                final RubberBandBox rbb = new RubberBandBox(RealType.Longitude,
147                                RealType.Latitude, 1);
148                rbb.setColor(Color.green);
149                rbb.addAction(new CellImpl() {
150                        public void doAction() throws VisADException, RemoteException {
151                                Gridded2DSet set = rbb.getBounds();
152                                float[] low = set.getLow();
153                                float[] hi = set.getHi();
154                                x_coords[0] = low[0];
155                                x_coords[1] = hi[0];
156                                y_coords[0] = low[1];
157                                y_coords[1] = hi[1];
158
159                                SampledSet[] sets = new SampledSet[4];
160                                sets[0] = new Gridded2DSet(
161                                                RealTupleType.SpatialEarth2DTuple,
162                                                new float[][] { { low[0], hi[0] }, { low[1], low[1] } },
163                                                2);
164                                sets[1] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple,
165                                                new float[][] { { hi[0], hi[0] }, { low[1], hi[1] } },
166                                                2);
167                                sets[2] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple,
168                                                new float[][] { { hi[0], low[0] }, { hi[1], hi[1] } },
169                                                2);
170                                sets[3] = new Gridded2DSet(
171                                                RealTupleType.SpatialEarth2DTuple,
172                                                new float[][] { { low[0], low[0] }, { hi[1], low[1] } },
173                                                2);
174                                UnionSet uset = new UnionSet(sets);
175                                selectBox.setData(uset);
176                        }
177                });
178                dspMaster.addDisplayable(rbb);
179                dspMaster.addDisplayable(selectBox);
180                dspMaster.draw();
181        }
182
183        public MapProjection getDataProjection() {
184                MapProjection mp = null;
185                try {
186                        mp = new ProjectionCoordinateSystem(new LatLonProjection());
187                } catch (Exception e) {
188                        logger.error("error getting data projection", e);
189                }
190                return mp;
191        }
192
193        protected JComponent doMakeContents() {
194                try {
195                        JPanel panel = new JPanel(new BorderLayout());
196                        panel.add("Center", dspMaster.getDisplayComponent());
197
198                        JPanel stridePanel = new JPanel(new FlowLayout());
199                        trkStr = new JTextField(Integer.toString(TrackSelection.DEFAULT_TRACK_STRIDE), 3);
200                        vrtStr = new JTextField(Integer.toString(TrackSelection.DEFAULT_VERTICAL_STRIDE), 3);
201                        trkStr.addActionListener(new ActionListener() {
202                                public void actionPerformed(ActionEvent ae) {
203                                        setTrackStride(Integer.valueOf(trkStr.getText().trim()));
204                                }
205                        });
206                        vrtStr.addActionListener(new ActionListener() {
207                                public void actionPerformed(ActionEvent ae) {
208                                        setVerticalStride(Integer.valueOf(vrtStr.getText().trim()));
209                                }
210                        });
211
212                        stridePanel.add(new JLabel("Track Stride: "));
213                        stridePanel.add(trkStr);
214                        stridePanel.add(new JLabel("Vertical Stride: "));
215                        stridePanel.add(vrtStr);
216                        panel.add("South", stridePanel);
217
218                        return panel;
219                } catch (Exception e) {
220                        logger.error("error creating contents", e);
221                }
222                return null;
223        }
224
225        public void setTrackStride(int stride) {
226                trackStride = stride;
227        }
228
229        public void setVerticalStride(int stride) {
230                verticalStride = stride;
231        }
232
233        /**
234         * Update Track Stride if input text box holds a positive integer.
235         * 
236         * @return true if trackStride was updated
237         */
238        
239        public boolean setTrackStride() {
240                boolean setOk = false;
241                try {
242                        int newStride = Integer.valueOf(trkStr.getText().trim());
243                        trackStride = newStride;
244                        setOk = true;
245                } catch (NumberFormatException nfe) {
246                        // do nothing, will return correct result code
247                }
248                return setOk;
249        }
250
251        /**
252         * Update Vertical Stride if input text box holds a positive integer.
253         * 
254         * @return true if verticalStride was updated
255         */
256        
257        public boolean setVerticalStride() {
258                boolean setOk = false;
259                try {
260                        int newStride = Integer.valueOf(vrtStr.getText().trim());
261                        verticalStride = newStride;
262                        setOk = true;
263                } catch (NumberFormatException nfe) {
264                        // do nothing, will return correct result code
265                }
266                return setOk;
267        }
268
269        public void applyToDataSelection(DataSelection dataSelection) {
270                setTrackStride();
271                setVerticalStride();
272                if (hasSubset) {
273                        GeoSelection geoSelect = new GeoSelection(new GeoLocationInfo(
274                                        y_coords[1], x_coords[0], y_coords[0], x_coords[1]));
275                        geoSelect.setXStride(trackStride);
276                        geoSelect.setYStride(verticalStride);
277                        dataSelection.setGeoSelection(geoSelect);
278
279                        DataSelection datSel = new DataSelection();
280                        datSel.setGeoSelection(geoSelect);
281                        datSrc.setDataSelection(datSel);
282                        dataChoice.setDataSelection(dataSelection);
283                }
284        }
285}