Ticket #5551: projection-patch.diff

File projection-patch.diff, 29.2 KB (added by extropy, 14 years ago)

the patch

  • src/org/openstreetmap/josm/data/projection/Projection.java

     
    1818    public static Projection[] allProjections = new Projection[]{
    1919        new Epsg4326(),
    2020        new Mercator(),
     21        new TransverseMercatorLV(),
    2122        new LambertEST(), // Still needs proper default zoom
    2223        new Lambert(),    // Still needs proper default zoom
    2324        new Puwg(),
  • src/org/openstreetmap/josm/data/projection/TransverseMercator.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.projection;
     3
     4/**
     5 * This is a base class to do projections based on Transverse Mercator projection.
     6 *
     7 * @author Dirk Stöcker
     8 * code based on JavaScript from Chuck Taylor
     9 *
     10 * NOTE: Uses polygon approximation to translate to WGS84.
     11 */
     12import org.openstreetmap.josm.data.coor.EastNorth;
     13import org.openstreetmap.josm.data.coor.LatLon;
     14
     15public abstract class TransverseMercator implements Projection {
     16
     17    private final static double UTMScaleFactor = 0.9996;
     18
     19    private double UTMCentralMeridianRad = 0;
     20    private double offsetEastMeters = 500000;
     21    private double offsetNorthMeters = 0;
     22
     23
     24    protected void setProjectionParameters(double centralMeridianDegress, double offsetEast, double offsetNorth)
     25    {
     26        UTMCentralMeridianRad = Math.toRadians(centralMeridianDegress);
     27        offsetEastMeters = offsetEast;
     28        offsetNorthMeters = offsetNorth;
     29    }
     30
     31    /*
     32     * ArcLengthOfMeridian
     33     *
     34     * Computes the ellipsoidal distance from the equator to a point at a
     35     * given latitude.
     36     *
     37     * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
     38     * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
     39     *
     40     * Inputs:
     41     *     phi - Latitude of the point, in radians.
     42     *
     43     * Globals:
     44     *     Ellipsoid.GRS80.a - Ellipsoid model major axis.
     45     *     Ellipsoid.GRS80.b - Ellipsoid model minor axis.
     46     *
     47     * Returns:
     48     *     The ellipsoidal distance of the point from the equator, in meters.
     49     *
     50     */
     51    private double ArcLengthOfMeridian(double phi)
     52    {
     53        /* Precalculate n */
     54        double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
     55
     56        /* Precalculate alpha */
     57        double alpha = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
     58        * (1.0 + (Math.pow (n, 2.0) / 4.0) + (Math.pow (n, 4.0) / 64.0));
     59
     60        /* Precalculate beta */
     61        double beta = (-3.0 * n / 2.0) + (9.0 * Math.pow (n, 3.0) / 16.0)
     62        + (-3.0 * Math.pow (n, 5.0) / 32.0);
     63
     64        /* Precalculate gamma */
     65        double gamma = (15.0 * Math.pow (n, 2.0) / 16.0)
     66        + (-15.0 * Math.pow (n, 4.0) / 32.0);
     67
     68        /* Precalculate delta */
     69        double delta = (-35.0 * Math.pow (n, 3.0) / 48.0)
     70        + (105.0 * Math.pow (n, 5.0) / 256.0);
     71
     72        /* Precalculate epsilon */
     73        double epsilon = (315.0 * Math.pow (n, 4.0) / 512.0);
     74
     75        /* Now calculate the sum of the series and return */
     76        return alpha
     77        * (phi + (beta * Math.sin (2.0 * phi))
     78                + (gamma * Math.sin (4.0 * phi))
     79                + (delta * Math.sin (6.0 * phi))
     80                + (epsilon * Math.sin (8.0 * phi)));
     81    }
     82
     83
     84    /*
     85     * FootpointLatitude
     86     *
     87     * Computes the footpoint latitude for use in converting transverse
     88     * Mercator coordinates to ellipsoidal coordinates.
     89     *
     90     * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
     91     *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
     92     *
     93     * Inputs:
     94     *   y - The UTM northing coordinate, in meters.
     95     *
     96     * Returns:
     97     *   The footpoint latitude, in radians.
     98     *
     99     */
     100    private double FootpointLatitude(double y)
     101    {
     102        /* Precalculate n (Eq. 10.18) */
     103        double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
     104
     105        /* Precalculate alpha_ (Eq. 10.22) */
     106        /* (Same as alpha in Eq. 10.17) */
     107        double alpha_ = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
     108        * (1 + (Math.pow (n, 2.0) / 4) + (Math.pow (n, 4.0) / 64));
     109
     110        /* Precalculate y_ (Eq. 10.23) */
     111        double y_ = y / alpha_;
     112
     113        /* Precalculate beta_ (Eq. 10.22) */
     114        double beta_ = (3.0 * n / 2.0) + (-27.0 * Math.pow (n, 3.0) / 32.0)
     115        + (269.0 * Math.pow (n, 5.0) / 512.0);
     116
     117        /* Precalculate gamma_ (Eq. 10.22) */
     118        double gamma_ = (21.0 * Math.pow (n, 2.0) / 16.0)
     119        + (-55.0 * Math.pow (n, 4.0) / 32.0);
     120
     121        /* Precalculate delta_ (Eq. 10.22) */
     122        double delta_ = (151.0 * Math.pow (n, 3.0) / 96.0)
     123        + (-417.0 * Math.pow (n, 5.0) / 128.0);
     124
     125        /* Precalculate epsilon_ (Eq. 10.22) */
     126        double epsilon_ = (1097.0 * Math.pow (n, 4.0) / 512.0);
     127
     128        /* Now calculate the sum of the series (Eq. 10.21) */
     129        return y_ + (beta_ * Math.sin (2.0 * y_))
     130        + (gamma_ * Math.sin (4.0 * y_))
     131        + (delta_ * Math.sin (6.0 * y_))
     132        + (epsilon_ * Math.sin (8.0 * y_));
     133    }
     134
     135    /*
     136     * MapLatLonToXY
     137     *
     138     * Converts a latitude/longitude pair to x and y coordinates in the
     139     * Transverse Mercator projection.  Note that Transverse Mercator is not
     140     * the same as UTM; a scale factor is required to convert between them.
     141     *
     142     * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
     143     * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
     144     *
     145     * Inputs:
     146     *    phi - Latitude of the point, in radians.
     147     *    lambda - Longitude of the point, in radians.
     148     *    lambda0 - Longitude of the central meridian to be used, in radians.
     149     *
     150     * Outputs:
     151     *    xy - A 2-element array containing the x and y coordinates
     152     *         of the computed point.
     153     *
     154     * Returns:
     155     *    The function does not return a value.
     156     *
     157     */
     158    public EastNorth mapLatLonToXY(double phi, double lambda, double lambda0)
     159    {
     160        /* Precalculate ep2 */
     161        double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0)) / Math.pow (Ellipsoid.GRS80.b, 2.0);
     162
     163        /* Precalculate nu2 */
     164        double nu2 = ep2 * Math.pow (Math.cos (phi), 2.0);
     165
     166        /* Precalculate N */
     167        double N = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nu2));
     168
     169        /* Precalculate t */
     170        double t = Math.tan (phi);
     171        double t2 = t * t;
     172
     173        /* Precalculate l */
     174        double l = lambda - lambda0;
     175
     176        /* Precalculate coefficients for l**n in the equations below
     177           so a normal human being can read the expressions for easting
     178           and northing
     179           -- l**1 and l**2 have coefficients of 1.0 */
     180        double l3coef = 1.0 - t2 + nu2;
     181
     182        double l4coef = 5.0 - t2 + 9 * nu2 + 4.0 * (nu2 * nu2);
     183
     184        double l5coef = 5.0 - 18.0 * t2 + (t2 * t2) + 14.0 * nu2
     185        - 58.0 * t2 * nu2;
     186
     187        double l6coef = 61.0 - 58.0 * t2 + (t2 * t2) + 270.0 * nu2
     188        - 330.0 * t2 * nu2;
     189
     190        double l7coef = 61.0 - 479.0 * t2 + 179.0 * (t2 * t2) - (t2 * t2 * t2);
     191
     192        double l8coef = 1385.0 - 3111.0 * t2 + 543.0 * (t2 * t2) - (t2 * t2 * t2);
     193
     194        return new EastNorth(
     195                /* Calculate easting (x) */
     196                N * Math.cos (phi) * l
     197                + (N / 6.0 * Math.pow (Math.cos (phi), 3.0) * l3coef * Math.pow (l, 3.0))
     198                + (N / 120.0 * Math.pow (Math.cos (phi), 5.0) * l5coef * Math.pow (l, 5.0))
     199                + (N / 5040.0 * Math.pow (Math.cos (phi), 7.0) * l7coef * Math.pow (l, 7.0)),
     200                /* Calculate northing (y) */
     201                ArcLengthOfMeridian (phi)
     202                + (t / 2.0 * N * Math.pow (Math.cos (phi), 2.0) * Math.pow (l, 2.0))
     203                + (t / 24.0 * N * Math.pow (Math.cos (phi), 4.0) * l4coef * Math.pow (l, 4.0))
     204                + (t / 720.0 * N * Math.pow (Math.cos (phi), 6.0) * l6coef * Math.pow (l, 6.0))
     205                + (t / 40320.0 * N * Math.pow (Math.cos (phi), 8.0) * l8coef * Math.pow (l, 8.0)));
     206    }
     207
     208    /*
     209     * MapXYToLatLon
     210     *
     211     * Converts x and y coordinates in the Transverse Mercator projection to
     212     * a latitude/longitude pair.  Note that Transverse Mercator is not
     213     * the same as UTM; a scale factor is required to convert between them.
     214     *
     215     * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
     216     *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
     217     *
     218     * Inputs:
     219     *   x - The easting of the point, in meters.
     220     *   y - The northing of the point, in meters.
     221     *   lambda0 - Longitude of the central meridian to be used, in radians.
     222     *
     223     * Outputs:
     224     *   philambda - A 2-element containing the latitude and longitude
     225     *               in radians.
     226     *
     227     * Returns:
     228     *   The function does not return a value.
     229     *
     230     * Remarks:
     231     *   The local variables Nf, nuf2, tf, and tf2 serve the same purpose as
     232     *   N, nu2, t, and t2 in MapLatLonToXY, but they are computed with respect
     233     *   to the footpoint latitude phif.
     234     *
     235     *   x1frac, x2frac, x2poly, x3poly, etc. are to enhance readability and
     236     *   to optimize computations.
     237     *
     238     */
     239    public LatLon mapXYToLatLon(double x, double y, double lambda0)
     240    {
     241        /* Get the value of phif, the footpoint latitude. */
     242        double phif = FootpointLatitude (y);
     243
     244        /* Precalculate ep2 */
     245        double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0))
     246        / Math.pow (Ellipsoid.GRS80.b, 2.0);
     247
     248        /* Precalculate cos (phif) */
     249        double cf = Math.cos (phif);
     250
     251        /* Precalculate nuf2 */
     252        double nuf2 = ep2 * Math.pow (cf, 2.0);
     253
     254        /* Precalculate Nf and initialize Nfpow */
     255        double Nf = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nuf2));
     256        double Nfpow = Nf;
     257
     258        /* Precalculate tf */
     259        double tf = Math.tan (phif);
     260        double tf2 = tf * tf;
     261        double tf4 = tf2 * tf2;
     262
     263        /* Precalculate fractional coefficients for x**n in the equations
     264           below to simplify the expressions for latitude and longitude. */
     265        double x1frac = 1.0 / (Nfpow * cf);
     266
     267        Nfpow *= Nf;   /* now equals Nf**2) */
     268        double x2frac = tf / (2.0 * Nfpow);
     269
     270        Nfpow *= Nf;   /* now equals Nf**3) */
     271        double x3frac = 1.0 / (6.0 * Nfpow * cf);
     272
     273        Nfpow *= Nf;   /* now equals Nf**4) */
     274        double x4frac = tf / (24.0 * Nfpow);
     275
     276        Nfpow *= Nf;   /* now equals Nf**5) */
     277        double x5frac = 1.0 / (120.0 * Nfpow * cf);
     278
     279        Nfpow *= Nf;   /* now equals Nf**6) */
     280        double x6frac = tf / (720.0 * Nfpow);
     281
     282        Nfpow *= Nf;   /* now equals Nf**7) */
     283        double x7frac = 1.0 / (5040.0 * Nfpow * cf);
     284
     285        Nfpow *= Nf;   /* now equals Nf**8) */
     286        double x8frac = tf / (40320.0 * Nfpow);
     287
     288        /* Precalculate polynomial coefficients for x**n.
     289           -- x**1 does not have a polynomial coefficient. */
     290        double x2poly = -1.0 - nuf2;
     291        double x3poly = -1.0 - 2 * tf2 - nuf2;
     292        double x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 *nuf2) - 9.0 * tf2 * (nuf2 * nuf2);
     293        double x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2;
     294        double x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2;
     295        double x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2);
     296        double x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2);
     297
     298        return new LatLon(
     299                /* Calculate latitude */
     300                Math.toDegrees(
     301                        phif + x2frac * x2poly * (x * x)
     302                        + x4frac * x4poly * Math.pow (x, 4.0)
     303                        + x6frac * x6poly * Math.pow (x, 6.0)
     304                        + x8frac * x8poly * Math.pow (x, 8.0)),
     305                        Math.toDegrees(
     306                                /* Calculate longitude */
     307                                lambda0 + x1frac * x
     308                                + x3frac * x3poly * Math.pow (x, 3.0)
     309                                + x5frac * x5poly * Math.pow (x, 5.0)
     310                                + x7frac * x7poly * Math.pow (x, 7.0)));
     311    }
     312
     313    @Override
     314    public EastNorth latlon2eastNorth(LatLon p) {
     315        EastNorth a = mapLatLonToXY(Math.toRadians(p.lat()), Math.toRadians(p.lon()), UTMCentralMeridianRad);
     316        return new EastNorth(a.east() * UTMScaleFactor + offsetEastMeters, a.north() * UTMScaleFactor + offsetNorthMeters);
     317    }
     318
     319    @Override
     320    public LatLon eastNorth2latlon(EastNorth p) {
     321        return mapXYToLatLon((p.east() - offsetEastMeters)/UTMScaleFactor, (p.north() - offsetNorthMeters)/UTMScaleFactor, UTMCentralMeridianRad);
     322    }
     323
     324    @Override
     325    public double getDefaultZoomInPPD() {
     326        // this will set the map scaler to about 1000 m
     327        return 10;
     328    }
     329}
  • src/org/openstreetmap/josm/data/projection/TransverseMercatorLV.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.projection;
     3
     4/**
     5 * LKS-92/ Latvia TM projection. Based on data from spatialreference.org.
     6 * http://spatialreference.org/ref/epsg/3059/
     7 *
     8 * @author Viesturs Zarins
     9 */
     10import static org.openstreetmap.josm.tools.I18n.tr;
     11
     12import org.openstreetmap.josm.data.Bounds;
     13import org.openstreetmap.josm.data.coor.LatLon;
     14
     15public class TransverseMercatorLV extends TransverseMercator {
     16
     17    public TransverseMercatorLV()
     18    {
     19        setProjectionParameters(24, 500000, -6000000);
     20    }
     21
     22    @Override public String toString() {
     23        return tr("LKS-92/ Latvia TM");
     24    }
     25
     26    private int epsgCode() {
     27        return 3059;
     28    }
     29
     30    @Override
     31    public String toCode() {
     32        return "EPSG:"+ epsgCode();
     33    }
     34
     35    @Override
     36    public int hashCode() {
     37        return toCode().hashCode();
     38    }
     39
     40    public String getCacheDirectoryName() {
     41        return "epsg"+ epsgCode();
     42    }
     43
     44
     45    @Override
     46    public Bounds getWorldBoundsLatLon() {
     47        return new Bounds(
     48                new LatLon(-90.0, -180.0),
     49                new LatLon(90.0, 180.0));
     50    }
     51
     52}
  • src/org/openstreetmap/josm/data/projection/UTM.java

     
    1515import javax.swing.JRadioButton;
    1616
    1717import org.openstreetmap.josm.data.Bounds;
    18 import org.openstreetmap.josm.data.coor.EastNorth;
    1918import org.openstreetmap.josm.data.coor.LatLon;
    2019import org.openstreetmap.josm.tools.GBC;
    2120
    2221/**
    23  * Directly use latitude / longitude values as x/y.
    2422 *
    2523 * @author Dirk Stöcker
    2624 * code based on JavaScript from Chuck Taylor
    2725 */
    28 public class UTM implements Projection, ProjectionSubPrefs {
     26public class UTM extends TransverseMercator implements ProjectionSubPrefs {
    2927
    3028    private static final int DEFAULT_ZONE = 30;
    3129    private int zone = DEFAULT_ZONE;
     
    3634
    3735    private boolean offset = false;
    3836
    39     private final static double UTMScaleFactor = 0.9996;
    40 
    41     /* Ellipsoid model constants (WGS84) - TODO Use Elliposid class here too */
    42     //final private double sm_EccSquared = 6.69437999013e-03;
    43 
    44     /*
    45      * ArcLengthOfMeridian
    46      *
    47      * Computes the ellipsoidal distance from the equator to a point at a
    48      * given latitude.
    49      *
    50      * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
    51      * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
    52      *
    53      * Inputs:
    54      *     phi - Latitude of the point, in radians.
    55      *
    56      * Globals:
    57      *     Ellipsoid.GRS80.a - Ellipsoid model major axis.
    58      *     Ellipsoid.GRS80.b - Ellipsoid model minor axis.
    59      *
    60      * Returns:
    61      *     The ellipsoidal distance of the point from the equator, in meters.
    62      *
    63      */
    64     private double ArcLengthOfMeridian(double phi)
     37    public UTM()
    6538    {
    66         /* Precalculate n */
    67         double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
    68 
    69         /* Precalculate alpha */
    70         double alpha = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
    71         * (1.0 + (Math.pow (n, 2.0) / 4.0) + (Math.pow (n, 4.0) / 64.0));
    72 
    73         /* Precalculate beta */
    74         double beta = (-3.0 * n / 2.0) + (9.0 * Math.pow (n, 3.0) / 16.0)
    75         + (-3.0 * Math.pow (n, 5.0) / 32.0);
    76 
    77         /* Precalculate gamma */
    78         double gamma = (15.0 * Math.pow (n, 2.0) / 16.0)
    79         + (-15.0 * Math.pow (n, 4.0) / 32.0);
    80 
    81         /* Precalculate delta */
    82         double delta = (-35.0 * Math.pow (n, 3.0) / 48.0)
    83         + (105.0 * Math.pow (n, 5.0) / 256.0);
    84 
    85         /* Precalculate epsilon */
    86         double epsilon = (315.0 * Math.pow (n, 4.0) / 512.0);
    87 
    88         /* Now calculate the sum of the series and return */
    89         return alpha
    90         * (phi + (beta * Math.sin (2.0 * phi))
    91                 + (gamma * Math.sin (4.0 * phi))
    92                 + (delta * Math.sin (6.0 * phi))
    93                 + (epsilon * Math.sin (8.0 * phi)));
     39        updateParameters();
    9440    }
    9541
     42
    9643    /*
    9744     * UTMCentralMeridian
    9845     *
     
    10754     *   Range of the central meridian is the radian equivalent of [-177,+177].
    10855     *
    10956     */
    110     private double UTMCentralMeridian(int zone)
    111     {
    112         return Math.toRadians(-183.0 + (zone * 6.0));
    113     }
    11457    private double UTMCentralMeridianDeg(int zone)
    11558    {
    11659        return -183.0 + (zone * 6.0);
    11760    }
    11861
    119     /*
    120      * FootpointLatitude
    121      *
    122      * Computes the footpoint latitude for use in converting transverse
    123      * Mercator coordinates to ellipsoidal coordinates.
    124      *
    125      * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
    126      *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
    127      *
    128      * Inputs:
    129      *   y - The UTM northing coordinate, in meters.
    130      *
    131      * Returns:
    132      *   The footpoint latitude, in radians.
    133      *
    134      */
    135     private double FootpointLatitude(double y)
    136     {
    137         /* Precalculate n (Eq. 10.18) */
    138         double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
    139 
    140         /* Precalculate alpha_ (Eq. 10.22) */
    141         /* (Same as alpha in Eq. 10.17) */
    142         double alpha_ = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
    143         * (1 + (Math.pow (n, 2.0) / 4) + (Math.pow (n, 4.0) / 64));
    144 
    145         /* Precalculate y_ (Eq. 10.23) */
    146         double y_ = y / alpha_;
    147 
    148         /* Precalculate beta_ (Eq. 10.22) */
    149         double beta_ = (3.0 * n / 2.0) + (-27.0 * Math.pow (n, 3.0) / 32.0)
    150         + (269.0 * Math.pow (n, 5.0) / 512.0);
    151 
    152         /* Precalculate gamma_ (Eq. 10.22) */
    153         double gamma_ = (21.0 * Math.pow (n, 2.0) / 16.0)
    154         + (-55.0 * Math.pow (n, 4.0) / 32.0);
    155 
    156         /* Precalculate delta_ (Eq. 10.22) */
    157         double delta_ = (151.0 * Math.pow (n, 3.0) / 96.0)
    158         + (-417.0 * Math.pow (n, 5.0) / 128.0);
    159 
    160         /* Precalculate epsilon_ (Eq. 10.22) */
    161         double epsilon_ = (1097.0 * Math.pow (n, 4.0) / 512.0);
    162 
    163         /* Now calculate the sum of the series (Eq. 10.21) */
    164         return y_ + (beta_ * Math.sin (2.0 * y_))
    165         + (gamma_ * Math.sin (4.0 * y_))
    166         + (delta_ * Math.sin (6.0 * y_))
    167         + (epsilon_ * Math.sin (8.0 * y_));
    168     }
    169 
    170     /*
    171      * MapLatLonToXY
    172      *
    173      * Converts a latitude/longitude pair to x and y coordinates in the
    174      * Transverse Mercator projection.  Note that Transverse Mercator is not
    175      * the same as UTM; a scale factor is required to convert between them.
    176      *
    177      * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
    178      * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
    179      *
    180      * Inputs:
    181      *    phi - Latitude of the point, in radians.
    182      *    lambda - Longitude of the point, in radians.
    183      *    lambda0 - Longitude of the central meridian to be used, in radians.
    184      *
    185      * Outputs:
    186      *    xy - A 2-element array containing the x and y coordinates
    187      *         of the computed point.
    188      *
    189      * Returns:
    190      *    The function does not return a value.
    191      *
    192      */
    193     public EastNorth mapLatLonToXY(double phi, double lambda, double lambda0)
    194     {
    195         /* Precalculate ep2 */
    196         double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0)) / Math.pow (Ellipsoid.GRS80.b, 2.0);
    197 
    198         /* Precalculate nu2 */
    199         double nu2 = ep2 * Math.pow (Math.cos (phi), 2.0);
    200 
    201         /* Precalculate N */
    202         double N = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nu2));
    203 
    204         /* Precalculate t */
    205         double t = Math.tan (phi);
    206         double t2 = t * t;
    207 
    208         /* Precalculate l */
    209         double l = lambda - lambda0;
    210 
    211         /* Precalculate coefficients for l**n in the equations below
    212            so a normal human being can read the expressions for easting
    213            and northing
    214            -- l**1 and l**2 have coefficients of 1.0 */
    215         double l3coef = 1.0 - t2 + nu2;
    216 
    217         double l4coef = 5.0 - t2 + 9 * nu2 + 4.0 * (nu2 * nu2);
    218 
    219         double l5coef = 5.0 - 18.0 * t2 + (t2 * t2) + 14.0 * nu2
    220         - 58.0 * t2 * nu2;
    221 
    222         double l6coef = 61.0 - 58.0 * t2 + (t2 * t2) + 270.0 * nu2
    223         - 330.0 * t2 * nu2;
    224 
    225         double l7coef = 61.0 - 479.0 * t2 + 179.0 * (t2 * t2) - (t2 * t2 * t2);
    226 
    227         double l8coef = 1385.0 - 3111.0 * t2 + 543.0 * (t2 * t2) - (t2 * t2 * t2);
    228 
    229         return new EastNorth(
    230                 /* Calculate easting (x) */
    231                 N * Math.cos (phi) * l
    232                 + (N / 6.0 * Math.pow (Math.cos (phi), 3.0) * l3coef * Math.pow (l, 3.0))
    233                 + (N / 120.0 * Math.pow (Math.cos (phi), 5.0) * l5coef * Math.pow (l, 5.0))
    234                 + (N / 5040.0 * Math.pow (Math.cos (phi), 7.0) * l7coef * Math.pow (l, 7.0)),
    235                 /* Calculate northing (y) */
    236                 ArcLengthOfMeridian (phi)
    237                 + (t / 2.0 * N * Math.pow (Math.cos (phi), 2.0) * Math.pow (l, 2.0))
    238                 + (t / 24.0 * N * Math.pow (Math.cos (phi), 4.0) * l4coef * Math.pow (l, 4.0))
    239                 + (t / 720.0 * N * Math.pow (Math.cos (phi), 6.0) * l6coef * Math.pow (l, 6.0))
    240                 + (t / 40320.0 * N * Math.pow (Math.cos (phi), 8.0) * l8coef * Math.pow (l, 8.0)));
    241     }
    242 
    243     /*
    244      * MapXYToLatLon
    245      *
    246      * Converts x and y coordinates in the Transverse Mercator projection to
    247      * a latitude/longitude pair.  Note that Transverse Mercator is not
    248      * the same as UTM; a scale factor is required to convert between them.
    249      *
    250      * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
    251      *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
    252      *
    253      * Inputs:
    254      *   x - The easting of the point, in meters.
    255      *   y - The northing of the point, in meters.
    256      *   lambda0 - Longitude of the central meridian to be used, in radians.
    257      *
    258      * Outputs:
    259      *   philambda - A 2-element containing the latitude and longitude
    260      *               in radians.
    261      *
    262      * Returns:
    263      *   The function does not return a value.
    264      *
    265      * Remarks:
    266      *   The local variables Nf, nuf2, tf, and tf2 serve the same purpose as
    267      *   N, nu2, t, and t2 in MapLatLonToXY, but they are computed with respect
    268      *   to the footpoint latitude phif.
    269      *
    270      *   x1frac, x2frac, x2poly, x3poly, etc. are to enhance readability and
    271      *   to optimize computations.
    272      *
    273      */
    274     public LatLon mapXYToLatLon(double x, double y, double lambda0)
    275     {
    276         /* Get the value of phif, the footpoint latitude. */
    277         double phif = FootpointLatitude (y);
    278 
    279         /* Precalculate ep2 */
    280         double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0))
    281         / Math.pow (Ellipsoid.GRS80.b, 2.0);
    282 
    283         /* Precalculate cos (phif) */
    284         double cf = Math.cos (phif);
    285 
    286         /* Precalculate nuf2 */
    287         double nuf2 = ep2 * Math.pow (cf, 2.0);
    288 
    289         /* Precalculate Nf and initialize Nfpow */
    290         double Nf = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nuf2));
    291         double Nfpow = Nf;
    292 
    293         /* Precalculate tf */
    294         double tf = Math.tan (phif);
    295         double tf2 = tf * tf;
    296         double tf4 = tf2 * tf2;
    297 
    298         /* Precalculate fractional coefficients for x**n in the equations
    299            below to simplify the expressions for latitude and longitude. */
    300         double x1frac = 1.0 / (Nfpow * cf);
    301 
    302         Nfpow *= Nf;   /* now equals Nf**2) */
    303         double x2frac = tf / (2.0 * Nfpow);
    304 
    305         Nfpow *= Nf;   /* now equals Nf**3) */
    306         double x3frac = 1.0 / (6.0 * Nfpow * cf);
    307 
    308         Nfpow *= Nf;   /* now equals Nf**4) */
    309         double x4frac = tf / (24.0 * Nfpow);
    310 
    311         Nfpow *= Nf;   /* now equals Nf**5) */
    312         double x5frac = 1.0 / (120.0 * Nfpow * cf);
    313 
    314         Nfpow *= Nf;   /* now equals Nf**6) */
    315         double x6frac = tf / (720.0 * Nfpow);
    316 
    317         Nfpow *= Nf;   /* now equals Nf**7) */
    318         double x7frac = 1.0 / (5040.0 * Nfpow * cf);
    319 
    320         Nfpow *= Nf;   /* now equals Nf**8) */
    321         double x8frac = tf / (40320.0 * Nfpow);
    322 
    323         /* Precalculate polynomial coefficients for x**n.
    324            -- x**1 does not have a polynomial coefficient. */
    325         double x2poly = -1.0 - nuf2;
    326         double x3poly = -1.0 - 2 * tf2 - nuf2;
    327         double x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 *nuf2) - 9.0 * tf2 * (nuf2 * nuf2);
    328         double x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2;
    329         double x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2;
    330         double x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2);
    331         double x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2);
    332 
    333         return new LatLon(
    334                 /* Calculate latitude */
    335                 Math.toDegrees(
    336                         phif + x2frac * x2poly * (x * x)
    337                         + x4frac * x4poly * Math.pow (x, 4.0)
    338                         + x6frac * x6poly * Math.pow (x, 6.0)
    339                         + x8frac * x8poly * Math.pow (x, 8.0)),
    340                         Math.toDegrees(
    341                                 /* Calculate longitude */
    342                                 lambda0 + x1frac * x
    343                                 + x3frac * x3poly * Math.pow (x, 3.0)
    344                                 + x5frac * x5poly * Math.pow (x, 5.0)
    345                                 + x7frac * x7poly * Math.pow (x, 7.0)));
    346     }
    347 
    348     public EastNorth latlon2eastNorth(LatLon p) {
    349         EastNorth a = mapLatLonToXY(Math.toRadians(p.lat()), Math.toRadians(p.lon()), UTMCentralMeridian(getzone()));
    350         return new EastNorth(a.east() * UTMScaleFactor + getEastOffset(), a.north() * UTMScaleFactor + getNorthOffset());
    351     }
    352 
    353     public LatLon eastNorth2latlon(EastNorth p) {
    354         return mapXYToLatLon((p.east()-getEastOffset())/UTMScaleFactor, (p.north()-getNorthOffset())/UTMScaleFactor, UTMCentralMeridian(getzone()));
    355     }
    356 
    35762    @Override public String toString() {
    35863        return tr("UTM");
    35964    }
    36065
     66    private void updateParameters() {
     67        setProjectionParameters(this.UTMCentralMeridianDeg(getzone()), getEastOffset(), getNorthOffset());
     68    }
     69
    36170    public int getzone()
    36271    {
    36372        return zone;
     
    403112                    new LatLon(5.0, UTMCentralMeridianDeg(getzone())+5.0));
    404113    }
    405114
    406     public double getDefaultZoomInPPD() {
    407         // this will set the map scaler to about 1000 m
    408         return 10;
    409     }
    410 
    411115    public void setupPreferencePanel(JPanel p) {
    412116        //Zone
    413117        JComboBox zonecb = new JComboBox();
     
    509213                offset = array[2].equals("offset");
    510214            }
    511215        }
     216
     217        updateParameters();
    512218    }
    513219
     220
     221
    514222    public Collection<String> getPreferencesFromCode(String code)
    515223    {
    516224        boolean offset = code.startsWith("EPSG:3258") || code.startsWith("EPSG:3259");