Skip to content

Instantly share code, notes, and snippets.

@Fil
Created November 24, 2019 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fil/c8e32c202918bdf462b45adc01867d8d to your computer and use it in GitHub Desktop.
Save Fil/c8e32c202918bdf462b45adc01867d8d to your computer and use it in GitHub Desktop.
BertinRiviere.class
//
// Decompiled by Procyon v0.5.36 from G.Projector's BertinRiviere.class
//
package gov.nasa.giss.map.proj;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;
import gov.nasa.giss.graphics.Bezier;
import java.awt.Graphics2D;
import gov.nasa.giss.map.MapUtils;
import gov.nasa.giss.math.PointLL;
import java.awt.geom.Point2D;
import gov.nasa.giss.map.LonLatRotator;
import org.slf4j.Logger;
public class BertinRiviere extends AbstractProjection
{
private static final Logger LOGGER;
public static final String PROJECTION_NAME = "Bertin-Rivi\u00e8re";
public static final int PROPERTIES = 0;
private static final double CSUBX = 1.68;
private static final double MAX_X_OVER_RS = 2.3758787847867997;
private static final double MIN_X_OVER_RS = -2.16976;
private static final double MAX_Y_OVER_RS = 1.419172468;
private static final double MIN_Y_OVER_RS = -1.4142135623730951;
private static final double X_OF_MAX_Y_OVER_RS = 1.04437951096;
private LonLatRotator rotMatrices_;
public BertinRiviere(final int width, final int height) {
this(width, height, 0, 0);
}
public BertinRiviere(final int width, final int height, final int xmargin, final int ymargin) {
super("Bertin-Rivi\u00e8re", 0, width, height, xmargin, ymargin, 2.3758787847867997, 1.419172468);
super.setCenter(16.5, 42.0);
this.rotMatrices_ = new LonLatRotator(16.5, 42.0);
this.autoscale();
}
public void setCenter(final double lon, final double lat) {
BertinRiviere.LOGGER.trace("Projection does not support changing center.");
}
public boolean isRecenterableLon() {
return false;
}
public boolean isRecenterableLat() {
return false;
}
public Point2D.Double transformLL2XYIgnoreMargins(final double lon, final double lat) {
if (Math.abs(lat) > 90.0) {
throw new IllegalArgumentException("Latitude must be in range [-90\u0080,90\u0080].");
}
final double[] llP = this.rotMatrices_.rotate(lon, lat);
return this.transformLpLp2XYIgnoreMargins(llP[0], llP[1]);
}
private Point2D.Double transformLpLp2XYIgnoreMargins(final double lonP, final double latP) {
double lambdaQRad = Math.toRadians(lonP);
double phiQRad = Math.toRadians(latP);
if (lambdaQRad + phiQRad < -1.4) {
final double e1 = (lambdaQRad - phiQRad + 1.6) * (lambdaQRad + phiQRad + 1.4) / 8.0;
lambdaQRad += e1;
phiQRad -= 0.8 * e1 * Math.sin(phiQRad + 1.5707963267948966);
}
final double halfLambdaQRad = 0.5 * lambdaQRad;
final double cosPhiP = Math.cos(phiQRad);
final double cosBeta = cosPhiP * Math.cos(halfLambdaQRad);
final double betaTerm = Math.sqrt(0.5 + 0.5 * cosBeta);
double x = 0.0;
double y = 0.0;
if (betaTerm > 1.0E-5) {
final double sinPhiP = Math.sin(phiQRad);
final double invBetaTerm = 1.0 / betaTerm;
x = 1.68 * cosPhiP * Math.sin(halfLambdaQRad) * invBetaTerm;
y = sinPhiP * invBetaTerm;
}
final double e2 = (1.0 - Math.cos(lambdaQRad * phiQRad)) / 12.0;
if (y < 0.0) {
x *= 1.0 + e2;
}
else if (y > 0.0) {
y *= 1.0 + e2 * x * x / 1.5;
}
x = this.outCenterX_ + x * this.rS_;
y = this.outCenterY_ - y * this.rS_;
return new Point2D.Double(x, y);
}
public PointLL transformXY2LL(final double xx, final double yy) {
final double x = xx - this.outCenterX_;
final double y = this.outCenterY_ - yy;
if (Math.abs(x) > this.dxMax_ || Math.abs(y) > this.dyMax_) {
return null;
}
if (x == 0.0 && y == 0.0) {
return new PointLL(this.lambdaC_, this.phiC_);
}
final double[] llpRad = this.iterateXY2LpLpRad(x, y);
if (llpRad == null) {
return null;
}
final double lambdaP = Math.toDegrees(llpRad[0]);
final double phiP = Math.toDegrees(llpRad[1]);
final double[] ll = this.rotMatrices_.inverse(lambdaP, phiP);
return new PointLL(ll[0], ll[1]);
}
protected void calculateInverseArray() {
synchronized (this) {
for (int iy = -this.dyMax_; iy < this.dyMax_; ++iy) {
final double y = iy + 0.5;
for (int ix = -this.dxMax_; ix < this.dxMax_; ++ix) {
final double x = ix + 0.5;
final double[] llpRad = this.iterateXY2LpLpRad(x, y);
if (llpRad == null) {
if (x * this.invRS_ > 1.04437951096) {
break;
}
}
else {
final double lambdaP = Math.toDegrees(llpRad[0]);
final double phiP = Math.toDegrees(llpRad[1]);
final double[] ll = this.rotMatrices_.inverse(lambdaP, phiP);
this.setPoint(ix, iy, ll[0], ll[1]);
}
}
}
}
}
private double[] iterateXY2LpLpRad(final double x, final double y) {
final double yOverRS = y * this.invRS_;
final double xOverRS = x * this.invRS_;
if (xOverRS < -2.16976) {
return null;
}
final double x2Over1P5 = xOverRS * xOverRS / 1.5;
double lambdaQRad = 2.9845130209103035 * xOverRS / 2.3758787847867997;
double phiQRad = 1.0524335389525807 * yOverRS / 1.419172468;
boolean found = false;
for (int iter = 0; iter < 33; ++iter) {
final double halfLambdaQRad = 0.5 * lambdaQRad;
final double cosHalfLambdaQ = Math.cos(halfLambdaQRad);
final double sinHalfLambdaQ = Math.sin(halfLambdaQRad);
final double lambdaQPhiQRad = lambdaQRad * phiQRad;
final double cosLambdaQPhiQ = Math.cos(lambdaQPhiQRad);
final double sinLambdaQPhiQ = Math.sin(lambdaQPhiQRad);
final double cosPhiQ = Math.cos(phiQRad);
final double sinPhiQ = Math.sin(phiQRad);
final double cosBeta = cosPhiQ * cosHalfLambdaQ;
final double betaTerm = Math.sqrt(0.5 + 0.5 * cosBeta);
final double invBetaTerm = 1.0 / betaTerm;
final double invBetaTerm2 = invBetaTerm * invBetaTerm * invBetaTerm;
final double e2 = (1.0 - cosLambdaQPhiQ) / 12.0;
final double dcosBetaDLambdaQ = -0.5 * cosPhiQ * sinHalfLambdaQ;
final double dcosBetaDPhiQ = -sinPhiQ * cosHalfLambdaQ;
final double dinvBetaTermDLambdaQ = -0.25 * invBetaTerm2 * dcosBetaDLambdaQ;
final double dinvBetaTermDPhiQ = -0.25 * invBetaTerm2 * dcosBetaDPhiQ;
final double deDLambdaQ = sinLambdaQPhiQ * phiQRad / 12.0;
final double deDPhiQ = sinLambdaQPhiQ * lambdaQRad / 12.0;
double f1;
double f2;
double df1dPhiQ;
double df1dLambdaQ;
double df2dPhiQ;
double df2dLambdaQ;
if (y > 0.0) {
final double e2term = 1.0 + e2 * x2Over1P5;
final double de2termDLambdaQ = x2Over1P5 * deDLambdaQ;
final double de2termDPhiQ = x2Over1P5 * deDPhiQ;
f1 = 1.68 * cosPhiQ * sinHalfLambdaQ * invBetaTerm - xOverRS;
f2 = sinPhiQ * invBetaTerm * e2term - yOverRS;
df1dPhiQ = 1.68 * sinHalfLambdaQ * (-sinPhiQ * invBetaTerm + cosPhiQ * dinvBetaTermDPhiQ);
df1dLambdaQ = 1.68 * cosPhiQ * (0.5 * cosHalfLambdaQ * invBetaTerm + sinHalfLambdaQ * dinvBetaTermDLambdaQ);
df2dPhiQ = cosPhiQ * invBetaTerm * e2term + sinPhiQ * dinvBetaTermDPhiQ * e2term + sinPhiQ * invBetaTerm * de2termDPhiQ;
df2dLambdaQ = sinPhiQ * (dinvBetaTermDLambdaQ * e2term + invBetaTerm * de2termDLambdaQ);
}
else {
final double e2term = 1.0 + e2;
final double de2termDLambdaQ = deDLambdaQ;
final double de2termDPhiQ = deDPhiQ;
f1 = 1.68 * cosPhiQ * sinHalfLambdaQ * invBetaTerm * e2term - xOverRS;
f2 = sinPhiQ * invBetaTerm - yOverRS;
df1dPhiQ = 1.68 * sinHalfLambdaQ * (-sinPhiQ * invBetaTerm * e2term + cosPhiQ * dinvBetaTermDPhiQ * e2term + cosPhiQ * invBetaTerm * de2termDPhiQ);
df1dLambdaQ = 1.68 * cosPhiQ * (0.5 * cosHalfLambdaQ * invBetaTerm * e2term + sinHalfLambdaQ * dinvBetaTermDLambdaQ * e2term + sinHalfLambdaQ * invBetaTerm * de2termDLambdaQ);
df2dPhiQ = cosPhiQ * invBetaTerm + sinPhiQ * dinvBetaTermDPhiQ;
df2dLambdaQ = sinPhiQ * dinvBetaTermDLambdaQ;
}
final double denom = df1dPhiQ * df2dLambdaQ - df2dPhiQ * df1dLambdaQ;
final double dphiQRad = (f1 * df2dLambdaQ - f2 * df1dLambdaQ) / denom;
final double dlambdaQRad = (f2 * df1dPhiQ - f1 * df2dPhiQ) / denom;
phiQRad -= dphiQRad;
lambdaQRad -= dlambdaQRad;
if (Math.abs(dphiQRad) < 1.0E-5 & Math.abs(dlambdaQRad) < 1.0E-5) {
found = true;
break;
}
}
if (!found) {
return null;
}
if (Math.abs(phiQRad) > 1.5707963267948966 || Math.abs(lambdaQRad) > 3.141592653589793) {
return null;
}
if (lambdaQRad + phiQRad >= -1.4) {
return new double[] { lambdaQRad, phiQRad };
}
double lambdaPRad = lambdaQRad;
double phiPRad = phiQRad;
found = false;
for (int iter2 = 0; iter2 < 33; ++iter2) {
final double e3 = (lambdaPRad - phiPRad + 1.6) * (lambdaPRad + phiPRad + 1.4) / 8.0;
final double de1DphiP = -(lambdaPRad + phiPRad + 1.4) / 8.0 + (lambdaPRad - phiPRad + 1.6) / 8.0;
final double de1DlambdaP = (lambdaPRad + phiPRad + 1.4) / 8.0 + (lambdaPRad - phiPRad + 1.6) / 8.0;
final double f1 = lambdaQRad - e3 - lambdaPRad;
final double f2 = phiQRad + 0.8 * e3 * Math.sin(phiPRad + 1.5707963267948966) - phiPRad;
final double df1dPhiP = -de1DphiP;
final double df1dLambdaP = -de1DlambdaP - 1.0;
final double df2dPhiP = 0.8 * Math.sin(phiPRad + 1.5707963267948966) * de1DphiP + 0.8 * e3 * Math.cos(phiPRad + 1.5707963267948966) - 1.0;
final double df2dLambdaP = 0.8 * Math.sin(phiPRad + 1.5707963267948966) * de1DlambdaP;
final double denom = df1dPhiP * df2dLambdaP - df2dPhiP * df1dLambdaP;
final double dphiPRad = (f1 * df2dLambdaP - f2 * df1dLambdaP) / denom;
final double dlambdaPRad = (f2 * df1dPhiP - f1 * df2dPhiP) / denom;
phiPRad -= dphiPRad;
lambdaPRad -= dlambdaPRad;
if (Math.abs(dphiPRad) < 1.0E-5 & Math.abs(dlambdaPRad) < 1.0E-5) {
found = true;
break;
}
}
if (!found) {
return null;
}
if (Math.abs(phiPRad) > 1.5707963267948966 || Math.abs(lambdaPRad) > 3.141592653589793) {
return null;
}
return new double[] { lambdaPRad, phiPRad };
}
private void setPoint(final int ix, final int iy, final double dlambda, final double phi) {
final int row = this.outCenterY_ - iy - 1;
final int col = this.outCenterX_ + ix;
if (row < 0 || row >= this.outHeight_ || col < 0 || col >= this.outWidth_) {
return;
}
final double lon = dlambda;
final int index = row * this.outWidth_ + col;
this.invArrayLon_[index] = MapUtils.normalize360(lon);
this.invArrayLat_[index] = phi;
final int srcY = this.getSrcPixelY(phi);
if (srcY > -1) {
final int srcX = this.getSrcPixelX(lon);
if (srcX > -1) {
this.invArray_[index] = srcY * this.srcWidth_ + srcX;
}
}
}
protected void drawBorderLines(final Graphics2D g2d) {
final Bezier[] curves = this.makeOuterBeziers();
if (curves[0] != null) {
curves[0].draw(g2d);
}
if (curves[1] != null) {
curves[1].draw(g2d);
}
}
private Bezier[] makeOuterBeziers() {
final double elon = 179.99999;
final double wlon = -179.99999;
final int np = 270;
final double fact = 0.6666666666666666;
final Point2D.Double[] dotsE = new Point2D.Double[271];
final Point2D.Double[] dotsW = new Point2D.Double[271];
for (int j = 0; j <= 270; ++j) {
final double lat = -90.0 + 0.6666666666666666 * j;
final Point2D.Double edot = this.transformLpLp2XYIgnoreMargins(179.99999, lat);
final Point2D.Double wdot = this.transformLpLp2XYIgnoreMargins(-179.99999, lat);
dotsE[j] = edot;
dotsW[j] = wdot;
}
return new Bezier[] { new Bezier(false, dotsE), new Bezier(false, dotsW) };
}
static {
LOGGER = LoggerFactory.getLogger((Class)MethodHandles.lookup().lookupClass());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment