/** * MIT License * * Copyright (c) 2017 Justin Kunimune * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package apps; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.imageio.ImageIO; import javafx.application.Application; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.embed.swing.SwingFXUtils; import javafx.geometry.Side; import javafx.scene.Scene; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.ScatterChart; import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Series; import javafx.scene.control.Label; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import maps.Azimuthal; import maps.CahillKeyes; import maps.Cylindrical; import maps.Lenticular; import maps.Misc; import maps.MyProjections; import maps.Projection; import maps.Pseudocylindrical; import maps.Arbitrary; import maps.Polyhedral; import maps.Tobler; import maps.Waterman; import maps.WinkelTripel; /** * A simple script that creates an annotated ScatterPlot of map projections * * @author jkunimune */ public class MapPlotter extends Application { private static final double DECIBEL = Math.log(10)/10; private static final double GLOBE_RES = .005; private static final Projection[] CYLINDRICAL = { Cylindrical.MERCATOR, Cylindrical.PLATE_CARREE, Cylindrical.GALL_ORTHOGRAPHIC, Cylindrical.BEHRMANN, Cylindrical.GALL_STEREOGRAPHIC }; private static final Projection[] AZIMUTHAL = { Azimuthal.POLAR }; private static final Projection[] PSEUDOCYL = { Pseudocylindrical.MOLLWEIDE, Arbitrary.ROBINSON, Arbitrary.NATURAL_EARTH, Pseudocylindrical.KAVRAYSKIY_VII, Tobler.TOBLER }; private static final Projection[] LENTICULAR = { Lenticular.AITOFF, Lenticular.VAN_DER_GRINTEN, WinkelTripel.WINKEL_TRIPEL }; private static final Projection[] TETRAHEDRAL = { Polyhedral.LEE_TETRAHEDRAL_RECTANGULAR, Polyhedral.AUTHAGRAPH, Polyhedral.ACTUAUTHAGRAPH, Polyhedral.TETRAPOWER }; private static final Projection[] CHEATY = { Pseudocylindrical.LEMONS, CahillKeyes.M_MAP, Polyhedral.DYMAXION }; private static final Projection[] OTHER = { Misc.PEIRCE_QUINCUNCIAL }; private StackPane stack; public static final void main(String[] args) { launch(args); } @Override public void start(Stage root) { final ScatterChart plot = new ScatterChart( new NumberAxis("Size distortion", 0, 4, .5), new NumberAxis("Shape distortion", 0, 3, .5)); plot.setLegendSide(Side.RIGHT); final AnchorPane overlay = new AnchorPane(); stack = new StackPane(plot, overlay); final List