//
// SINUnav.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;
public final class SINUnav extends AREAnav {
double drad, decc, r;
double xrow, xcol, xlat, xlon;
double xblat, xblon, xspace, yspace;
int itype, iwest;
boolean isEastPositive = true;
public SINUnav(int[] iparms) throws IllegalArgumentException {
if (iparms[0] != SIN )
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]);
xspace = iparms[5]/1000.;
yspace = xspace;
drad = iparms[6]/1000.;
r = drad;
decc = iparms[7]/1.e6;
iwest = iparms[9];
if (iwest >= 0) iwest = 1;
xblat = r*DEGREES_TO_RADIANS/xspace;
xblon = DEGREES_TO_RADIANS*r/yspace;
/*
for (int i=0; i<10; i++) {
System.out.println("#### i="+i+" val = "+iparms[i]);
}
*/
}
public double[][] toLatLon(double[][] linele) {
double xlin, xele, xldif, xedif, xdis, ylat, ylon;
int number = linele[0].length;
double[][] latlon = new double[2][number];
double[][] imglinele = areaCoordToImageCoord(linele);
for (int point=0; point < number; point++ ){
xlin = imglinele[indexLine][point];
xele = imglinele[indexEle][point];
xldif = xrow - xlin;
xedif = xcol - xele;
xdis = Math.sqrt(xldif*xldif + xedif*xedif);
if (xdis > .001) {
double xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS;
double xange = Math.atan2(xldif,xedif) + 90.*DEGREES_TO_RADIANS;
xldif = xdis*Math.cos(xangl);
xedif = xdis*Math.sin(xange);
}
ylat = xlat + xldif/xblat;
ylon = iwest * xedif/xblon/Math.cos(ylat*DEGREES_TO_RADIANS);
if (Math.abs(ylon) > 180.0) {
latlon[indexLat][point] = Double.NaN;
latlon[indexLon][point] = Double.NaN;
} else {
ylon = xlon + ylon;
if (ylon < -180.0) {
ylon = ylon + 360.0;
} else if (ylon > 180.0) {
ylon = ylon - 360.0;
}
if (Math.abs(ylat) > 90.0 || Math.abs(ylon) > 180.0) {
latlon[indexLat][point] = Double.NaN;
latlon[indexLon][point] = Double.NaN;
}
if (isEastPositive) ylon = -ylon;
latlon[indexLat][point] = ylat;
latlon[indexLon][point] = ylon;
}
}
return latlon;
}
public double[][] toLinEle(double[][] latlon) {
double xdis, xele, xlin, zlat, zlon, xrlon, xrlat, xldif, xedif;
int number = latlon[0].length;
double[][] linele = new double[2][number];
for (int point=0; point<number; point++) {
zlat = latlon[indexLat][point];
zlon = isEastPositive
? -latlon[indexLon][point]
: latlon[indexLon][point];
if (Double.isNaN(zlat) || Double.isNaN(zlon) ||
(Math.abs(zlat) > 90.) ) {
xele = Double.NaN;
xlin = Double.NaN;
} else {
xrlon = iwest*(zlon - xlon);
if (xrlon > 180.) xrlon = xrlon - 360.;
if (xrlon < -180.) xrlon = xrlon + 360.;
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) {
double xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS;
double xange = Math.atan2(xldif, xedif) + 90.*DEGREES_TO_RADIANS;
xldif = xdis * Math.cos(xangl);
xedif = xdis * Math.sin(xange);
}
xlin = xrow - xldif;
xele = xcol - xedif;
}
linele[indexLine][point] = xlin;
linele[indexEle][point] = xele;
}
return imageCoordToAreaCoord(linele, linele);
}
public float[][] toLatLon(float[][] linele) {
double xlin, xele, xldif, xedif, xdis, ylat, ylon;
int number = linele[0].length;
float[][] latlon = new float[2][number];
float[][] imglinele = areaCoordToImageCoord(linele);
for (int point=0; point < number; point++ ){
xlin = imglinele[indexLine][point];
xele = imglinele[indexEle][point];
xldif = xrow - xlin;
xedif = xcol - xele;
xdis = Math.sqrt(xldif*xldif + xedif*xedif);
if (xdis > .001) {
double xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS;
double xange = Math.atan2(xldif,xedif) + 90.*DEGREES_TO_RADIANS;
xldif = xdis*Math.cos(xangl);
xedif = xdis*Math.sin(xange);
}
ylat = xlat + xldif/xblat;
ylon = iwest * xedif/xblon/Math.cos(ylat*DEGREES_TO_RADIANS);
if (Math.abs(ylon) > 180.0) {
latlon[indexLat][point] = Float.NaN;
latlon[indexLon][point] = Float.NaN;
} else {
ylon = xlon + ylon;
if (ylon < -180.0) {
ylon = ylon + 360.0;
} else if (ylon > 180.0) {
ylon = ylon - 360.0;
}
if (Math.abs(ylat) > 90.0 || Math.abs(ylon) > 180.0) {
latlon[indexLat][point] = Float.NaN;
latlon[indexLon][point] = Float.NaN;
}
if (isEastPositive) ylon = -ylon;
latlon[indexLat][point] = (float) ylat;
latlon[indexLon][point] = (float) ylon;
}
}
return latlon;
}
public float[][] toLinEle(float[][] latlon) {
double xdis, xele, xlin, zlat, zlon, xrlon, xrlat, xldif, xedif;
int number = latlon[0].length;
float[][] linele = new float[2][number];
for (int point=0; point<number; point++) {
zlat = latlon[indexLat][point];
zlon = isEastPositive
? -latlon[indexLon][point]
: latlon[indexLon][point];
if (Double.isNaN(zlat) || Double.isNaN(zlon) ||
(Math.abs(zlat) > 90.) ) {
xele = Double.NaN;
xlin = Float.NaN;
} else {
xrlon = iwest*(zlon - xlon);
if (xrlon > 180.) xrlon = xrlon - 360.;
if (xrlon < -180.) xrlon = xrlon + 360.;
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) {
double xangl = Math.atan2(xldif, xedif) - 90.*DEGREES_TO_RADIANS;
double xange = Math.atan2(xldif, xedif) + 90.*DEGREES_TO_RADIANS;
xldif = xdis * Math.cos(xangl);
xedif = xdis * Math.sin(xange);
}
xlin = xrow - xldif;
xele = xcol - xedif;
}
linele[indexLine][point] = (float)xlin;
linele[indexEle][point] = (float)xele;
}
return imageCoordToAreaCoord(linele, linele);
}
public static void main(String[] a) {
int[] p = {1397313056, 10000, 10000, 421353,831951,1000,6378388,81992,0,0};
SINUnav sn = new SINUnav(p);
double [][] latlon = new double[2][1];
latlon[0][0] = 43.;
latlon[1][0] = -89.;
System.out.println("#### Doing double");
System.out.println("#### Original latlon="+latlon[0][0]+" "+latlon[1][0]);
double[][] pix = sn.toLinEle(latlon);
System.out.println("#### pix="+pix[0][0]+" "+pix[1][0]);
latlon = sn.toLatLon(pix);
System.out.println("#### latlon="+latlon[0][0]+" "+latlon[1][0]);
System.out.println("#### Now doing float....");
float [][] flatlon = new float[2][1];
flatlon[0][0] = 43.f;
flatlon[1][0] = -89.f;
System.out.println("#### Original flatlon="+flatlon[0][0]+" "+flatlon[1][0]);
float[][] fpix = sn.toLinEle(flatlon);
System.out.println("#### fpix="+fpix[0][0]+" "+fpix[1][0]);
flatlon = sn.toLatLon(fpix);
System.out.println("#### flatlon="+flatlon[0][0]+" "+flatlon[1][0]);
}
}