Just call me the Master of Cone

I've got the equidistant conic and Albers down. Now all I have to do is
make Lambert's conformal conic lose its whitespace. I'm so close!
As with equidistant conic, the code for Albers looks completely hideous.
I figured I would just go ahead and continue the theme. There's a
non-negligible chance Lambert CC will soon become uglier, as well. Thank
goodness for Eclipse's ability to hide blocks of code.
This commit is contained in:
jkunimune 2017-07-20 22:33:20 -04:00
parent bf2bd735dd
commit 8c60d261aa
5 changed files with 73 additions and 21 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -65,9 +65,9 @@ public abstract class MapApplication extends Application {
private static final String[] ASPECT_NAMES = { "Standard", "Transverse", "Center of Mass", "Jerusalem", "Point Nemo",
"Longest Line", "Longest Line Transverse", "Cylindrical", "Conic", "Tetrahedral", "Quincuncial", "Antipode", "Random" };
private static final double[][] ASPECT_VALS = {
{ 90., 0., 29.98, 31.78, 48.88, -28.52,-46.4883,-35., -10., 47., 60. },
{ 0., 0., 31.13, 35.22, 56.61, 141.45, 16.5305,-13.61, 65.,-173., -6. },
{ 0., 0.,-32., -35., -45., 161.5, 137., 145., -150., 138.,-10. } };
{ 90., 0., 29.98, 31.78, 48.88, -28.52,-46.4883,-35., -17., 47., 60. },
{ 0., 0., 31.13, 35.22, 56.61, 141.45, 16.5305,-13.61, -7.,-173., -6. },
{ 0., 0.,-32., -35., -45., 161.5, 137., 145., 151., 138.,-10. } };
final private String name;

View File

@ -244,7 +244,7 @@ public class MapDesignerVector extends MapApplication {
for (int i = 1; i < closedCurve.size()+1; i ++) {
double[] p0 = convCoordsToImg(closedCurve.get(i-1));
double[] p1 = convCoordsToImg(closedCurve.get(i%closedCurve.size()));
if (Math.hypot(p1[0]-p0[0], p1[1]-p0[1]) >= c.getWidth()/10) {
if (Math.hypot(p1[0]-p0[0], p1[1]-p0[1]) >= c.getWidth()/8) {
g.stroke();
g.beginPath();
g.moveTo(p1[0], p1[1]);

View File

@ -58,7 +58,7 @@ public class MapPlotter extends Application {
private static final Projection[] COMMON = { Projection.STEREOGRAPHIC, Projection.LAMBERT_CONIC,
Projection.MERCATOR, Projection.POLAR, Projection.E_D_CONIC, Projection.PLATE_CARREE,
Projection.E_A_AZIMUTH, Projection.ALBERS, Projection.GALL_PETERS, Projection.GALL, Projection.MILLER,
Projection.E_A_AZIMUTH, Projection.ALBERS, Projection.GALL_PETERS, Projection.GALL,
Projection.VAN_DER_GRINTEN, Projection.ROBINSON, Projection.WINKEL_TRIPEL, Projection.ORTHOGRAPHIC };
private static final Projection[] UNCOMMON = { Projection.PEIRCE_QUINCUNCIAL, Projection.LEE, Projection.TOBLER,
Projection.BEHRMANN, Projection.AITOFF };

View File

@ -78,7 +78,11 @@ public enum Projection {
2, 0b1111, "cylindrical", "equidistant",
new String[]{"Std. parallel"}, new double[][]{{0, 85, 0}}) {
public double[] project(double lat, double lon, double[] params) {
return new double[] {lon, lat/Math.cos(Math.toRadians(params[0]))};
final double a = Math.cos(Math.toRadians(params[0]));
if (a >= 1)
return new double[] {lon, lat/a};
else
return new double[] {2*lon*a, 2*lat};
}
public double[] inverse(double x, double y, double[] params) {
return new double[] {y*Math.PI/2, x*Math.PI};
@ -132,7 +136,10 @@ public enum Projection {
new String[]{"Std. parallel"}, new double[][]{{0, 85, 37.5}}) {
public double[] project(double lat, double lon, double[] params) {
final double a = Math.pow(Math.cos(Math.toRadians(params[0])), 2);
return new double[] {lon, Math.sin(lat)/a};
if (a >= 1/Math.PI)
return new double[] {lon, Math.sin(lat)/a};
else
return new double[] {lon*Math.PI*a, Math.sin(lat)*Math.PI};
}
public double[] inverse(double x, double y, double[] params) {
return new double[] { Math.asin(y), x*Math.PI };
@ -278,7 +285,6 @@ public enum Projection {
private boolean reversed;
private double[] lastParams = null;
private void processParams(double[] params) {
// System.out.println(Arrays.toString(params));
double lat1 = Math.toRadians(params[0]);
double lat2 = Math.toRadians(params[1]);
reversed = lat1 + lat2 < 0;
@ -308,8 +314,7 @@ public enum Projection {
}
public double[] project(double lat, double lon, double[] params) {
if (!Arrays.equals(params, lastParams)) processParams(params);
if (m == 0)
return EQUIRECTANGULAR.project(lat, lon, params);
if (m == 0) return EQUIRECTANGULAR.project(lat, lon, params);
if (reversed) {
lat = -lat;
lon = -lon;
@ -322,14 +327,13 @@ public enum Projection {
}
public double[] inverse(double x, double y, double[] params) {
if (!Arrays.equals(params, lastParams)) processParams(params);
if (m == 0)
return EQUIRECTANGULAR.inverse(x, y, params);
if (m == 0) return EQUIRECTANGULAR.inverse(x, y, params);
if (reversed) {
x = -x;
y = -y;
}
x = x/s;
y = (y+1)/s/a - 1;
y = (y+1)/s/Math.max(a, 1) - 1;
final double r = Math.hypot(x, y);
final double phi = (1 - m/2 - r)*Math.PI/m;
final double lam = Math.atan2(x, -y)/n;
@ -345,20 +349,68 @@ public enum Projection {
},
ALBERS("Albers", 0b1111, "equal-area") {
private double n, C, a, s;
private boolean reversed;
private double[] lastParams = null;
private void processParams(double[] params) {
double lat1 = Math.toRadians(params[0]);
double lat2 = Math.toRadians(params[1]);
reversed = lat1 + lat2 < 0;
if (reversed) {
lat1 = -lat1; lat2 = -lat2;
}
if (lat1 == -lat2) //degenerates into Equirectangular; indicate with n=0
n = 0;
else //normal conic
n = (Math.sin(lat1) + Math.sin(lat2))/2;
C = Math.pow(Math.cos(lat1), 2) + 2*n*Math.sin(lat1);
if (n == 0) {
a = Math.PI*Math.pow(Math.cos(lat1), 2);
}
else if (n >= .5) {
a = 2/(1 - Math.cos(Math.PI*n)); //TODO get rid of all 1-ns
s = n/Math.sqrt(C+2*n);
}
else {
a = 2*Math.sin(Math.PI*n)/(1 - Math.sqrt(C-2*n)/Math.sqrt(C+2*n)*Math.cos(Math.PI*n));
if (a >= 1) s = n/Math.sqrt(C+2*n)/Math.sin(Math.PI*n);
else s = 2/(Math.sqrt(C+2*n)/n - Math.sqrt(C-2*n)/n*Math.cos(Math.PI*n));
}
lastParams = params.clone();
}
public double[] project(double lat, double lon, double[] params) {
final double r = 2*Math.sqrt(1.2 - Math.sin(lat));
final double tht = lon/2 - Math.PI/2;
return new double[] { r*Math.cos(tht), r*Math.sin(tht) + Math.PI/2 };
if (!Arrays.equals(params, lastParams)) processParams(params);
if (n == 0) return E_A_CYLIND.project(lat, lon, params);
if (reversed) {
lat = -lat;
lon = -lon;
}
final double r = Math.sqrt(C - 2*n*Math.sin(lat))/n;
final double x = Math.PI*s*r*Math.sin(n*lon);
final double y = Math.PI*(s*Math.sqrt(C+2*n)/n-1/Math.max(a,1)) - Math.PI*s*r*Math.cos(n*lon);
if (reversed) return new double[] { -x, -y };
else return new double[] { x, y };
}
public double[] inverse(double x, double y, double[] params) {
y = (y-1)/2;
if (!Arrays.equals(params, lastParams)) processParams(params);
if (n == 0) return E_A_CYLIND.inverse(x, y, params);
if (reversed) {
x = -x;
y = -y;
}
x = x/s;
y = (y+1)/s/Math.max(a, 1) - Math.sqrt(C+2*n)/n; //TODO I can do without these lines
final double r = Math.hypot(x, y);
if (r < Math.sqrt(1/11.) || r > 1) return null;
return new double[] {
Math.asin(1.2-2.2*Math.pow(r, 2)), 2*Math.atan2(y, x)+Math.PI };
final double phi = Math.asin((C - Math.pow(n*r,2))/(2*n));
final double lam = Math.atan2(x, -y)/n;
if (Math.abs(lam) > Math.PI || Double.isNaN(phi))
return null;
else if (reversed) return new double[] {-phi, -lam};
else return new double[] {phi, lam};
}
public double getAspectRatio(double[] params) {
return 2; //TODO: implement this
if (!Arrays.equals(params, lastParams)) processParams(params);
return a;
}
},