// // RADRnav.java // /* This source file is part of the edu.wisc.ssec.mcidas package and is Copyright (C) 1998 - 2017 by Tom Whittaker, Tommy Jasmin, Tom Rink, Don Murray, James Kelly, Bill Hibbard, Dave Glowacki, Curtis Rueden and others. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package edu.wisc.ssec.mcidas; /** * Navigation class for Radar (RADR) type nav. This code was modified * from the original FORTRAN code (nvxradr.dlm) on the McIDAS system. It * only supports latitude/longitude to line/element transformations (LL) * and vice/versa. Transform to 'XYZ' not implemented. * @see <A HREF="http://www.ssec.wisc.edu/mcidas/doc/prog_man.html"> * McIDAS Programmer's Manual</A> * * @author Don Murray */ public final class RADRnav extends AREAnav { private boolean isEastPositive = true; final double EARTH_RADIUS=6371.23; // earth equatorial radius (km) final int MISS = McIDASUtil.MCMISSING; int itype; double xrow; double xcol; double xlat; double xlon; double xrot; double xblat; double xblon; /** * Set up for the real math work. Must pass in the int array * of the RADR nav 'codicil'. * * @param iparms the nav block from the image file * @throws IllegalArgumentException * if the nav block is not a RADR type. */ public RADRnav (int[] iparms) throws IllegalArgumentException { /* No longer needed. Kept for consistency with nvxradr.dlm if (ifunc != 1) { if (iparms[0] == XY ) itype = 1; if (iparms[0] == LL ) itype = 2; return; } */ if (iparms[0] != RADR ) throw new IllegalArgumentException("Invalid navigation type" + iparms[0]); itype = 2; xrow = iparms[1]; xcol = iparms[2]; xlat = McIDASUtil.integerLatLonToDouble(iparms[3]); xlon = McIDASUtil.integerLatLonToDouble(iparms[4]); double xspace = iparms[5]/1000.; double yspace = xspace; if (iparms[7] != 0 && iparms[7] != MISS) yspace = iparms[7]/1000.; xrot = -DEGREES_TO_RADIANS*iparms[6]/1000.; xblat = EARTH_RADIUS*DEGREES_TO_RADIANS/xspace; xblon = EARTH_RADIUS*DEGREES_TO_RADIANS/yspace; } /** converts from satellite coordinates to latitude/longitude * * @param linele array of line/element pairs. Where * linele[indexLine][] is a 'line' and * linele[indexEle][] is an element. These are in * 'file' coordinates (not "image" coordinates.) * * @return latlon[][] array of lat/long pairs. Output array is * latlon[indexLat][] of latitudes and * latlon[indexLon][] of longitudes. * */ public double[][] toLatLon(double[][] linele) { double xldif; double xedif; double xdis; double xangl; double xange; double ylat; double ylon; int number = linele[0].length; //double[][] latlon = new double[2][number]; // Convert array to Image coordinates for computations double[][] imglinele = areaCoordToImageCoord(linele); double[][] latlon = imglinele; for (int point=0; point < number; point++) { xldif = xrow - imglinele[indexLine][point]; xedif = xcol - imglinele[indexEle][point]; xdis = Math.sqrt(xldif*xldif + xedif*xedif); if (xdis > 0.001) { xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS; xange = Math.atan2(xldif, xedif) + 90.*DEGREES_TO_RADIANS; xldif = xdis*Math.cos(xrot+xangl); xedif = xdis*Math.sin(xrot+xange); } ylat = xlat + xldif/xblat; ylon = xlon + xedif/xblon/Math.cos(ylat* DEGREES_TO_RADIANS); // transform from McIDAS coordinates if (isEastPositive) ylon = -ylon; latlon[indexLat][point] = ylat; latlon[indexLon][point] = ylon; } // end point for loop return latlon; } /** * toLinEle converts lat/long to satellite line/element * * @param latlon array of lat/long pairs. Where latlon[indexLat][] * are latitudes and latlon[indexLon][] are longitudes. * * @return linele[][] array of line/element pairs. Where * linele[indexLine][] is a line and linele[indexEle][] * is an element. These are in 'file' coordinates * (not "image" coordinates); */ public double[][] toLinEle(double[][] latlon) { double zlat; double zlon; double xrlon; double xrlat; double xldif; double xedif; double xdis; double xangl; double xange; int number = latlon[0].length; double[][] linele = new double[2][number]; for (int point=0; point < number; point++) { if (Double.isNaN(latlon[indexLat][point]) || Double.isNaN(latlon[indexLon][point])) { linele[indexLine][point] = Float.NaN; linele[indexEle][point] = Float.NaN; continue; } zlat = latlon[indexLat][point]; // transform to McIDAS (west positive longitude) coordinates zlon = isEastPositive ? -latlon[indexLon][point] : latlon[indexLon][point]; if (zlon > 180) zlon -= 360; if (zlon < -180) zlon += 360; xrlon = zlon - xlon; xrlat = zlat - xlat; xldif = xblat*xrlat; xedif = xrlon*xblon*Math.cos(zlat*DEGREES_TO_RADIANS); xdis = Math.sqrt(xldif*xldif + xedif*xedif); if (xdis > .001) { xangl = Math.atan2(xldif, xedif)-90*DEGREES_TO_RADIANS; xange = Math.atan2(xldif, xedif)+90*DEGREES_TO_RADIANS; xldif = xdis*Math.cos(-xrot+xangl); xedif = xdis*Math.sin(-xrot+xange); } linele[indexLine][point] = xrow - xldif; linele[indexEle][point] = xcol - xedif; } // end point loop // Return in 'File' coordinates return imageCoordToAreaCoord(linele, linele); } /** converts from satellite coordinates to latitude/longitude * * @param linele array of line/element pairs. Where * linele[indexLine][] is a 'line' and * linele[indexEle][] is an element. These are in * 'file' coordinates (not "image" coordinates.) * * @return latlon[][] array of lat/long pairs. Output array is * latlon[indexLat][] of latitudes and * latlon[indexLon][] of longitudes. * */ public float[][] toLatLon(float[][] linele) { double xldif; double xedif; double xdis; double xangl; double xange; double ylat; double ylon; int number = linele[0].length; /* float[][] latlon = new float[2][number]; float[] lats = latlon[indexLat]; float[] lons = latlon[indexLon]; */ // Convert array to Image coordinates for computations float[][] imglinele = areaCoordToImageCoord(linele); float[][] latlon = imglinele; float[] lats = latlon[indexLat]; float[] lons = latlon[indexLon]; float[] lines = imglinele[indexLine]; float[] eles = imglinele[indexEle]; for (int point=0; point < number; point++) { xldif = xrow - lines[point]; xedif = xcol - eles[point]; xdis = Math.sqrt(xldif*xldif + xedif*xedif); if (xdis > 0.001) { xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS; xange = Math.atan2(xldif, xedif) + 90.*DEGREES_TO_RADIANS; xldif = xdis*Math.cos(xrot+xangl); xedif = xdis*Math.sin(xrot+xange); } ylat = xlat + xldif/xblat; ylon = xlon + xedif/xblon/Math.cos(ylat* DEGREES_TO_RADIANS); // transform from McIDAS coordinates if (isEastPositive) ylon = -ylon; lats[point] = (float) ylat; lons[point] = (float) ylon; } // end point for loop return latlon; } /** * toLinEle converts lat/long to satellite line/element * * @param latlon array of lat/long pairs. Where latlon[indexLat][] * are latitudes and latlon[indexLon][] are longitudes. * * @return linele[][] array of line/element pairs. Where * linele[indexLine][] is a line and linele[indexEle][] * is an element. These are in 'file' coordinates * (not "image" coordinates); */ public float[][] toLinEle(float[][] latlon) { double zlat; double zlon; double xrlon; double xrlat; double xldif; double xedif; double xdis; double xangl; double xange; int number = latlon[0].length; float[][] linele = new float[2][number]; float[] lines = linele[indexLine]; float[] eles = linele[indexEle]; float[] lats = latlon[indexLat]; float[] lons = latlon[indexLon]; for (int point=0; point < number; point++) { if (Float.isNaN(lats[point]) || Float.isNaN(lons[point])) { linele[indexLine][point] = Float.NaN; linele[indexEle][point] = Float.NaN; continue; } zlat = lats[point]; // transform to McIDAS (west positive longitude) coordinates zlon = isEastPositive ? -lons[point] : lons[point]; if (zlon > 180) zlon -= 360; if (zlon < -180) zlon += 360; xrlon = zlon - xlon; xrlat = zlat - xlat; xldif = xblat*xrlat; xedif = xrlon*xblon*Math.cos(zlat*DEGREES_TO_RADIANS); xdis = Math.sqrt(xldif*xldif + xedif*xedif); if (xdis > .001) { xangl = Math.atan2(xldif, xedif)-90*DEGREES_TO_RADIANS; xange = Math.atan2(xldif, xedif)+90*DEGREES_TO_RADIANS; xldif = xdis*Math.cos(-xrot+xangl); xedif = xdis*Math.sin(-xrot+xange); } lines[point] = (float) (xrow - xldif); eles[point] = (float) (xcol - xedif); } // end point loop // Return in 'File' coordinates return imageCoordToAreaCoord(linele, linele); } public boolean equals(Object o) { if (!(o instanceof RADRnav)) return false; RADRnav that = (RADRnav) o; return (super.equals(o) && that.xlat == xlat && that.xlon == xlon && that.xrow == xrow && that.xcol == xcol); } }