001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2018
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.data.hydra;
030
031import java.rmi.RemoteException;
032import java.util.HashMap;
033import java.util.Map;
034
035import visad.Gridded2DSet;
036import visad.Gridded3DSet;
037import visad.RealTupleType;
038import visad.Set;
039import visad.VisADException;
040
041public class TrackDomain extends MultiDimensionAdapter {
042   RealTupleType domainType;
043   ArrayAdapter lonAdapter;
044   ArrayAdapter latAdapter;
045   ArrayAdapter altAdapter;
046
047   float[] trackLongitude;
048   float[] trackLatitude;
049   float[] trackAltitude;
050
051   int TrackLen;
052
053   public TrackDomain() {
054   }
055
056   public TrackDomain(ArrayAdapter lonAdapter, ArrayAdapter latAdapter) throws Exception {
057     this(lonAdapter, latAdapter, null);
058   }
059
060   public TrackDomain(ArrayAdapter lonAdapter, ArrayAdapter latAdapter, ArrayAdapter altAdapter) throws Exception {
061     this.lonAdapter = lonAdapter;
062     this.latAdapter = latAdapter;
063     this.altAdapter = altAdapter;
064
065     if (altAdapter != null) {
066       domainType = RealTupleType.SpatialEarth3DTuple;
067       trackAltitude = (altAdapter.getData(altAdapter.getDefaultSubset()).getFloats(false))[0];
068     }
069     else {
070       domainType = RealTupleType.SpatialEarth2DTuple;
071     }
072
073     trackLongitude = (lonAdapter.getData(lonAdapter.getDefaultSubset()).getFloats(false))[0];
074     trackLatitude = (latAdapter.getData(latAdapter.getDefaultSubset()).getFloats(false))[0];
075     TrackLen = trackLongitude.length;
076   }
077
078   public Set makeDomain(Map<String, double[]> subset) throws VisADException, RemoteException {
079     
080     float[] lonValues = null;
081     float[] latValues = null;
082     float[] altValues = null;
083
084     double[] coords = (double[]) ((HashMap)subset).get("TrackDim");
085     Map<String, double[]> newSubset = this.getDefaultSubset();
086     double[] newCoords = newSubset.get("TrackDim");
087     System.arraycopy(coords, 0, newCoords, 0, coords.length);
088     subset = newSubset;
089
090     try {
091       lonValues = (lonAdapter.getData(subset).getFloats())[0];
092       latValues = (latAdapter.getData(subset).getFloats())[0];
093
094       if (altAdapter != null) {
095         altValues = (altAdapter.getData(subset).getFloats())[0];
096       }
097     }
098     catch (Exception e) {
099       e.printStackTrace();
100       return null;
101     }
102
103     Set set = null;
104
105     if (altAdapter != null) {
106       set = new Gridded3DSet(domainType, new float[][] {lonValues, latValues, altValues}, lonValues.length);
107     }
108     else {
109       set = new Gridded2DSet(domainType, new float[][] {lonValues, latValues}, lonValues.length);
110     }
111     return set;
112   }
113
114   public float[] getTrackLongitude() {
115     return trackLongitude;
116   }
117
118   public float[] getTrackLatitude() {
119     return trackLatitude;
120   }
121
122   public float[] getTrackAlitude() {
123     return trackAltitude;
124   }
125
126   public int[] getTrackRangeInsideLonLatRect(double minLat, double maxLat, double minLon, double maxLon) {
127        int nn = 100;
128        int skip = TrackLen/nn;
129        double lon;
130        double lat;
131
132        int idx = 0;
133        while (idx < TrackLen) {
134          lon = (double)trackLongitude[idx];
135          lat = (double)trackLatitude[idx];
136          if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) break;
137          idx += skip;
138        }
139        if (idx > TrackLen-1) idx = TrackLen-1;
140        if (idx == TrackLen-1) return new int[] {-1,-1};
141
142        int low_idx = idx;
143        while (low_idx > 0) {
144          lon = (double)trackLongitude[low_idx];
145          lat = (double)trackLatitude[low_idx];
146          if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) {
147            low_idx -= 1;
148            continue;
149          }
150          else {
151            break;
152          }
153        }
154
155        int hi_idx = idx;
156        while (hi_idx < TrackLen-1) {
157          lon = (double)trackLongitude[hi_idx];
158          lat = (double)trackLatitude[hi_idx];
159          if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) {
160            hi_idx += 1;
161            continue;
162          }
163          else {
164            break;
165          }
166        }
167        return new int[] {low_idx, hi_idx};
168   }
169
170   public Map<String, double[]> getSubsetFromLonLatRect(Map<String, double[]> subset, double minLat, double maxLat, double minLon, double maxLon) {
171      double[] coords = subset.get("TrackDim");
172      int[] idxs = getTrackRangeInsideLonLatRect(minLat, maxLat, minLon, maxLon);
173      coords[0] = (double) idxs[0];
174      coords[1] = (double) idxs[1];
175      if ((coords[0] == -1) || (coords[1] == -1)) return null;
176      return subset;
177   }
178
179   public Map<String, double[]> getSubsetFromLonLatRect(Map<String, double[]> subset, double minLat, double maxLat, double minLon, double maxLon,
180                                          int xStride, int yStride, int zStride) {
181      double[] coords = (double[])subset.get("TrackDim");
182      int[] idxs = getTrackRangeInsideLonLatRect(minLat, maxLat, minLon, maxLon);
183      coords[0] = (double) idxs[0];
184      coords[1] = (double) idxs[1];
185      if ((coords[0] == -1) || (coords[1] == -1)) return null;
186
187      if (xStride > 0) {
188         coords[2] = xStride;
189      }
190
191      return subset;
192   }
193
194   public Map<String, double[]> getDefaultSubset() {
195     return lonAdapter.getDefaultSubset();
196   }
197}