-
-
Save Fil/c8e32c202918bdf462b45adc01867d8d to your computer and use it in GitHub Desktop.
BertinRiviere.class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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