Hah! Aitoff _does_ have an inverse solution!

I tweaked MapExplainer to be a little bit better, corrected some minor issues with the Projection metadata, added real descriptions to my custom parameterised projections, and fixed a critical bug with WinkelTripel's inverse solution.
This commit is contained in:
Justin Kunimune 2017-08-28 19:43:54 -10:00
parent 5207b1999c
commit c1eb163af6
10 changed files with 24 additions and 16 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -64,7 +64,7 @@ public class MapExplainer {
Tetrahedral.TETRAGRAPH, Tetrahedral.AUTHAGRAPH, Pseudocylindrical.SINUSOIDAL,
Pseudocylindrical.MOLLWEIDE, Tobler.TOBLER, Misc.HAMMER, Misc.AITOFF,
Misc.VAN_DER_GRINTEN, Robinson.ROBINSON, WinkelTripel.WINKEL_TRIPEL,
Misc.PEIRCE_QUINCUNCIAL.transverse(), Misc.GUYOU, Misc.TWO_POINT_EQUIDISTANT,
Misc.PEIRCE_QUINCUNCIAL.transverse(), Misc.TWO_POINT_EQUIDISTANT,
Misc.HAMMER_RETROAZIMUTHAL },
{ MyProjections.PSEUDOSTEREOGRAPHIC, MyProjections.HYPERELLIPOWER,
@ -117,6 +117,7 @@ public class MapExplainer {
"title=\"TODO\">");
out.println(" </div>");
out.println("</div>");
out.println("<br>");
out.println();
}

View File

@ -45,7 +45,8 @@ public class Azimuthal {
public static final Projection POLAR =
new Projection("Polar", 1., 0b1111, Type.AZIMUTHAL, Property.EQUIDISTANT) {
new Projection(
"Azimuthal Equidistant", 1., 0b1111, Type.AZIMUTHAL, Property.EQUIDISTANT) {
public double[] project(double lat, double lon) {
final double r = .5 - lat/Math.PI;

View File

@ -39,7 +39,7 @@ public class Misc {
public static final Projection AITOFF =
new Projection("Aitoff", "A compromise projection shaped like an ellipse",
2., 0b1011, Type.PSEUDOAZIMUTHAL, Property.COMPROMISE) {
2., 0b1111, Type.PSEUDOAZIMUTHAL, Property.COMPROMISE) {
public double[] project(double lat, double lon) {
final double a = Math.acos(Math.cos(lat)*Math.cos(lon/2));

View File

@ -85,7 +85,8 @@ public class MyProjections {
public static final Projection PSEUDOSTEREOGRAPHIC =
new Projection("Pseudostereographic", "The logical next step after Aitoff and Hammer",
new Projection(
"Pseudostereographic", "The logical next step after Aitoff and Hammer",
2, 0b1111, Type.PSEUDOAZIMUTHAL, Property.COMPROMISE) {
public double[] project(double lat, double lon) {
@ -106,7 +107,8 @@ public class MyProjections {
public static final Projection HYPERELLIPOWER =
new Projection("Hyperellipower", "A parametric projection that I'm still testing",
new Projection(
"Hyperellipower", "A parametrised pseudocylindrical projection that I invented",
2., 0b1111, Type.PSEUDOCYLINDRICAL, Property.COMPROMISE,
new String[] {"k","n","a"},
new double[][] {{1,3,5},{.5,2.,1.20},{.5,2.,1.13}}) {
@ -136,7 +138,8 @@ public class MyProjections {
public static final Projection TWO_POINT_EQUALIZED =
new Projection("Two-Point Equalized", "A parametric projection that I'm still testing",
new Projection("Two-Point Equalized",
"A projection I invented specifically for viewing small elliptical regions of the Earth",
0, 0b1111, Type.OTHER, Property.EQUIDISTANT, new String[] {"Width"},
new double[][] { {0, 180, 120} }) {

View File

@ -78,7 +78,7 @@ public class Tetrahedral {
public static final Projection TETRAPOWER =
new TetrahedralProjection(
"Tetrapower", "A parametric projection that I'm still testing",
"Tetrapower", "A parameterised tetrahedral projection that I invented.",
Math.sqrt(3), 0b1111, Property.COMPROMISE, new String[] {"k1","k2","k3"},
new double[][] {{.01,2.,.98},{.01,2.,1.2},{.01,2.,.98}}) {
@ -118,7 +118,8 @@ public class Tetrahedral {
public static final Projection TETRAFILLET =
new TetrahedralProjection("TetraFillet", "A parametric projection that I'm still testing",
new TetrahedralProjection("TetraFillet",
"A parameterised tetrahedral projection I invented with the corners filleted off",
Math.sqrt(3), 0b1110, Property.COMPROMISE, new String[] {"k1","k2","k3"},
new double[][] {{.01,2.,.78},{.01,2.,.99},{.01,2.,1.3}}) {
@ -165,8 +166,9 @@ public class Tetrahedral {
public static final Projection TETRACHAMFER =
new TetrahedralProjection(
"TetraChamfer", "A parametric projection that I'm still testing", Math.sqrt(3),
0b1110, Property.COMPROMISE, new String[] {"k1","k2","k3"},
"TetraChamfer",
"A parameterised tetrahedral projection I invented with the corners chamfered off",
Math.sqrt(3), 0b1110, Property.COMPROMISE, new String[] {"k1","k2","k3"},
new double[][] {{.01,2.,.78},{.01,2.,.99},{.01,2.,1.3}}) {
private double k1, k2, k3;

View File

@ -42,7 +42,7 @@ public class Tobler {
"Tobler", "An equal-area projection shaped like a hyperellipse (in case you're wondering about gamma, it's calculated automatically)",
2., 0b1001, Type.PSEUDOCYLINDRICAL, Property.EQUAL_AREA,
new String[]{"Std. Parallel","alpha","K"},
new double[][] {{0,89,30.6}, {0,1,.5}, {1,8,3.63}}) {
new double[][] {{0,89,37}, {0,1,0}, {1,8,3.6}}) { //optimal parameters are 30.6,.50,3.63, but these defaults are more recognizably Tobler
private static final int N = 10000;
private double alpha, kappa, epsilon; //epsilon is related to gamma, but defined somewhat differently

View File

@ -55,12 +55,14 @@ public final class WinkelTripel {
}
public double[] project(double lat, double lon) {
return new double[] { f1pX(lat,lon)/aspectRatio, f2pY(lat,lon)/aspectRatio };
return new double[] {
f1pX(lat,lon)/aspectRatio/Math.PI, f2pY(lat,lon)/aspectRatio/Math.PI };
}
public double[] inverse(double x, double y) {
return NumericalAnalysis.newtonRaphsonApproximation(
x*aspectRatio, y, y/2, x*(1 + Math.cos(y*Math.PI/2))/2,
x*Math.PI*aspectRatio, y*Math.PI,
y*Math.PI/2, x*Math.PI*(1 + Math.cos(y*Math.PI/2))/2,
this::f1pX, this::f2pY,
this::df1dphi, this::df1dlam, this::df2dphi, this::df2dlam, .002);
}
@ -68,14 +70,13 @@ public final class WinkelTripel {
private double f1pX(double phi, double lam) {
final double d = D(phi,lam);
final double c = C(phi,lam);
return 2/Math.PI*d/Math.sqrt(c)*Math.cos(phi)*Math.sin(lam/2)
+ lam/Math.PI*(aspectRatio-1);
return 2*d/Math.sqrt(c)*Math.cos(phi)*Math.sin(lam/2) + lam*(aspectRatio-1);
}
private double f2pY(double phi, double lam) {
final double d = D(phi,lam);
final double c = C(phi,lam);
return d/Math.sqrt(c)*Math.sin(phi)/Math.PI + phi/Math.PI;
return d/Math.sqrt(c)*Math.sin(phi) + phi;
}
private double df1dphi(double phi, double lam) {