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