I made a new map projection which is a zoomd in single face of a cahill-keyes projection, because it was requested.
This commit is contained in:
Justin Kunimune 2022-04-18 14:49:21 -04:00
parent 9317a98505
commit 361e5d56e7
10 changed files with 81 additions and 33 deletions

6
.idea/ant.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<buildFile url="file://$PROJECT_DIR$/build.xml" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -139,8 +139,9 @@ public abstract class MapApplication extends Application {
{ Conic.ALBERS, Misc.BRAUN_CONIC, Conic.LAMBERT, Conic.EQUIDISTANT },
{ Polyhedral.AUTHAGRAPH, Polyhedral.LEE_TETRAHEDRAL_RECTANGULAR,
Polyhedral.LEE_TETRAHEDRAL_TRIANGULAR, Polyhedral.VAN_LEEUWEN },
{ Octohedral.CAHILL_CONCIALDI, Octohedral.CONFORMAL_CAHILL, Octohedral.CAHILL_KEYES,
Octohedral.KEYES_BASIC_M, Polyhedral.DYMAXION, Octohedral.WATERMAN },
{ Octohedral.CONFORMAL_CAHILL, Octohedral.CAHILL_CONCIALDI, Octohedral.KEYES_STANDARD,
Octohedral.KEYES_BASIC_M, Octohedral.KEYES_OCTANT, Polyhedral.DYMAXION,
Octohedral.WATERMAN },
{ Pseudocylindrical.ECKERT_IV, EqualEarth.EQUAL_EARTH,
Pseudocylindrical.HOMOLOSINE_INTERRUPTED, Pseudocylindrical.HOMOLOSINE,
Pseudocylindrical.KAVRAYSKIY_VII, Pseudocylindrical.MOLLWEIDE,

View File

@ -67,15 +67,13 @@ public class MapExplainer extends Application {
Pseudocylindrical.MOLLWEIDE, Tobler.TOBLER, Lenticular.AITOFF,
Lenticular.VAN_DER_GRINTEN, ArbitraryPseudocylindrical.ROBINSON,
WinkelTripel.WINKEL_TRIPEL, Polyhedral.AUTHAGRAPH,
Polyhedral.LEE_TETRAHEDRAL_RECTANGULAR, Octohedral.CAHILL_KEYES,
Polyhedral.LEE_TETRAHEDRAL_RECTANGULAR, Octohedral.KEYES_STANDARD,
Octohedral.CAHILL_CONCIALDI, Misc.PEIRCE_QUINCUNCIAL.transverse(), Snyder.GS50,
Misc.TWO_POINT_EQUIDISTANT, Misc.HAMMER_RETROAZIMUTHAL, Misc.FLAT_EARTH },
{ Meshed.DANSEIJI_N, Meshed.DANSEIJI_IV, Meshed.DANSEIJI_V, Polyhedral.TETRAGRAPH,
Polyhedral.AUTHAPOWER, Polyhedral.ACTUAUTHAGRAPH } };
private PixelMap inputSkew, inputPole, inputNone, inputEast, inputWest;
public static void main(String[] args) {
launch(args);
}
@ -83,6 +81,11 @@ public class MapExplainer extends Application {
public void start(Stage stage) throws Exception {
new File("images").mkdirs();
PixelMap inputSkew;
PixelMap inputNone;
PixelMap inputEast;
PixelMap inputPole;
PixelMap inputWest;
try {
inputSkew = new PixelMap(new File("input/Advanced/Tissot Oblique.jpg"));
inputPole = new PixelMap(new File("input/Advanced/Tissot Standard.jpg"));
@ -106,7 +109,7 @@ public class MapExplainer extends Application {
PixelMap input = inputSkew;
if (!proj.hasAspect() || proj == Polyhedral.AUTHAGRAPH)
input = inputPole;
if (proj == Octohedral.CAHILL_KEYES) //some projections only look good in standard aspect
if (proj == Octohedral.KEYES_STANDARD) //some projections only look good in standard aspect
input = inputWest;
if (proj == Octohedral.CAHILL_CONCIALDI)
input = inputEast;

View File

@ -84,7 +84,7 @@ public class MapPlotter extends Application {
Meshed.DANSEIJI_II, Gyorffy.E, Gyorffy.F };
private static final Projection[] TETRAHEDRAL = { Polyhedral.LEE_TETRAHEDRAL_RECTANGULAR,
Polyhedral.AUTHAGRAPH, Polyhedral.VAN_LEEUWEN };
private static final Projection[] CHEATY = { Pseudocylindrical.LEMONS, Octohedral.CAHILL_KEYES,
private static final Projection[] CHEATY = { Pseudocylindrical.LEMONS, Octohedral.KEYES_STANDARD,
Polyhedral.DYMAXION, Octohedral.CAHILL_CONCIALDI, Meshed.DANSEIJI_IV,
Pseudocylindrical.HOMOLOSINE_INTERRUPTED };
private static final Projection[] OTHER = { Misc.PEIRCE_QUINCUNCIAL };

View File

@ -74,7 +74,7 @@ public class MapProducer extends Application {
Polyhedral.DYMAXION, Misc.HAMMER_RETROAZIMUTHAL, Snyder.GS50,
Azimuthal.STEREOGRAPHIC.withAspect("Oblique Stereographic", .5, 2.5, -2.5),
Cylindrical.MERCATOR.withAspect("Oblique Mercator", .5, 2.5, 2.5), Misc.BONNE,
Misc.BRAUN_CONIC, Octohedral.CAHILL_CONCIALDI, Octohedral.CAHILL_KEYES,
Misc.BRAUN_CONIC, Octohedral.CAHILL_CONCIALDI, Octohedral.KEYES_STANDARD,
Lenticular.EISENLOHR, Gyorffy.E, Lenticular.LAGRANGE, Lenticular.POLYCONIC,
Polyhedral.VAN_LEEUWEN, Pseudocylindrical.WAGNER_II, Pseudocylindrical.WAGNER_V,
Lenticular.WAGNER_VIII, Pseudocylindrical.HOMOLOSINE_INTERRUPTED },

View File

@ -56,9 +56,12 @@ public class CahillKeyes {
private static final double yC = 1609.0110; //the y coordinate of the centre of arc CDV
private static final double TOLERANCE = 5; //this is a reasonable tolerance when you recall that we're operating on the order of 10,000 units
public static final double[] faceProjectD(double latD, double lonD) { //convert adjusted lat and lon in degrees to Mary Jo's coordinates
/**
* convert adjusted lat and lon in degrees to Mary Jo's coordinates
*/
public static final double[] faceProjectD(double latD, double lonD) {
final double[][] mer = meridian(lonD);
if (latD >= 75) { //zone c (frigid zone)
return new double[] { lMA + 104*(90-latD)*Math2.cosd(lonD),

View File

@ -51,7 +51,7 @@ public class Octohedral {
public static final Projection KEYES_BUTTERFLY = new OctohedralProjection(
"Cahill\u2013Keyes Butterfly", "A simple Cahill-esque octohedral map arrangement, with Antarctica left on.",
"Cahill\u2013Keyes (butterfly)", "A simple Cahill-esque octohedral map arrangement, with Antarctica left on.",
CahillKeyes.lMG, CahillKeyes.lMA, 0b1010, Property.COMPROMISE, 4,
Configuration.BUTTERFLY) {
@ -68,7 +68,7 @@ public class Octohedral {
public static final Projection KEYES_BASIC_M = new OctohedralProjection(
"Cahill\u2013Keyes Basic", "A simple M-shaped octohedral projection, with Antarctica broken into three pieces.",
"Cahill\u2013Keyes (simplified)", "A simple M-shaped octohedral projection, with Antarctica broken into three pieces.",
CahillKeyes.lMG, CahillKeyes.lMA, 0b1010, Property.COMPROMISE, 3,
Configuration.M_PROFILE) {
@ -82,36 +82,53 @@ public class Octohedral {
new double[] {Math.toRadians(coords[0]), Math.toRadians(coords[1])};
}
};
public static final Projection CAHILL_KEYES = new OctohedralProjection(
public static final Projection KEYES_STANDARD = new OctohedralProjection(
"Cahill\u2013Keyes", "An M-shaped octohedral projection with Antarctica assembled in the center.",
CahillKeyes.lMG, CahillKeyes.lMA, 0b1010, Property.COMPROMISE, 4,
Configuration.M_W_S_POLE) {
public double[] project(double lat, double lon) {
return super.project(lat, lon + Math.PI/9); // apply the central meridian manually
}
protected double[] faceProject(double lat, double lon) {
return CahillKeyes.faceProjectD(Math.toDegrees(lat), Math.toDegrees(lon));
}
public double[] inverse(double x, double y) {
double[] coords = super.inverse(x, y);
if (coords == null) return null;
coords[1] = Math2.floorMod(coords[1] - Math.PI/9 + Math.PI, 2*Math.PI) - Math.PI; // apply the central meridian manually
return coords;
}
protected double[] faceInverse(double x, double y) {
double[] coords = CahillKeyes.faceInverseD(x, y);
return (coords == null) ? null :
new double[] {Math.toRadians(coords[0]), Math.toRadians(coords[1])};
new double[] {Math.toRadians(coords[0]), Math.toRadians(coords[1])};
}
};
public static final Projection KEYES_OCTANT = new OctohedralProjection(
"Cahill\u2013Keyes (single octant)", "A single octant of the Cahill\u2013Keyes projection (for memory economization in the case of very large maps).",
CahillKeyes.lMG, CahillKeyes.lMA, 0b1010, Property.COMPROMISE, 3,
Configuration.SINGLE_OCTANT) {
protected double[] faceProject(double lat, double lon) {
return CahillKeyes.faceProjectD(Math.toDegrees(lat), Math.toDegrees(lon));
}
protected double[] faceInverse(double x, double y) {
double[] coords = CahillKeyes.faceInverseD(x, y);
return (coords == null) ? null :
new double[] {Math.toRadians(coords[0]), Math.toRadians(coords[1])};
}
};
public static final OctohedralProjection CONFORMAL_CAHILL = new OctohedralProjection(
"Cahill Conformal", "The conformal and only reproducable variant of Cahill's original map.",
Math.sqrt(3)/2, 0, 0b1000, Property.CONFORMAL, 3, Configuration.BUTTERFLY) {
@ -176,7 +193,7 @@ public class Octohedral {
public static final Projection CAHILL_CONCIALDI = new OctohedralProjection(
"Cahill\u2013Concialdi Bat", "A conformal octohedral projection with no extra cuts and a unique arrangement.",
"Cahill\u2013Concialdi", "A conformal octohedral projection with no extra cuts and a unique arrangement.",
Math.sqrt(3)/2, 0, 0b1000, Property.CONFORMAL, 4, Configuration.BAT_SHAPE) {
private final double lon0 = Math.toRadians(20);
@ -324,19 +341,37 @@ public class Octohedral {
{ 0, -0.5, Math.PI/3, Math.PI/2, -Math.PI/2, Math.PI/2 },
{ 0, -0.5, 2*Math.PI/3, Math.PI , 0, Math.PI/2, -1, Math.toRadians(-9) },
{ 3/Math.sqrt(3), 0.5, 0, Math.PI , -Math.PI/2, 0, -1, Math.toRadians( 9) },
}));
})),
SINGLE_OCTANT(1, 0, 2/Math.sqrt(3), Math.sqrt(3), true, new double[][] {
{ -0.5, 0, Math.PI/6, Math.PI/4, -Math.PI/2, Math.PI/2 },
});
public final double fullWidth, cutWidth, fullHeight, cutHeight;
public final boolean hasAspect;
public final double[][] octants; // array of {x, y (from top), rotation, \lambda_0, \phi_min, \phi_max[, \lambda_min, \lambda_max]}
// public double cutRatio; //this variable should be set by the map projection so that the configuration knows how big the cuts actually are
/**
* array of {
* x, y, rotation, λ_0, ф_min, ф_max[, λ_min, λ_max]
* } for each face of the octohedron
*/
public final double[][] octants;
/**
* @param fullWidth the size of the configuration in altitudes ignoring cuts
* @param cutWidth the change in width due to the cut-in lengths
* @param fullHeight the heit of the configuration in altitudes ignoring cuts
* @param cutHeight the change in heit due to the cut-in lengths
* @param hasAspect whether it would make any sense to change the aspect
* @param octants the array of octant specifications. each octant must
* specify the x and y of the pole, the central meridian,
* and bounding latitudes and longitudes of the face.
*/
private Configuration(double fullWidth, double cutWidth,
double fullHeight, double cutHeight, boolean hasAspect,
double[][] octants) {
this.fullWidth = fullWidth; //the size of the configuration in altitudes ignoring cuts
this.cutWidth = cutWidth; //the change in width due to the cut in cut lengths
this.fullHeight = fullHeight; //and the cut sizes
this.fullWidth = fullWidth;
this.cutWidth = cutWidth;
this.fullHeight = fullHeight;
this.cutHeight = cutHeight;
this.hasAspect = hasAspect;
this.octants = octants;