Logo Search packages:      
Sourcecode: josm-plugins version File versions  Download package

OSRef.java

package uk.me.jstott.jcoord;

/**
 * Class to represent an Ordnance Survey grid reference
 * 
 * (c) 2006 Jonathan Stott
 * 
 * Created on 11-02-2006
 * 
 * @author Jonathan Stott
 * @version 1.0
 * @since 1.0
 */
00014 public class OSRef {

  /**
   * Easting
   */
00019   private double easting;

  /**
   * Northing
   */
00024   private double northing;


  /**
   * Create a new Ordnance Survey grid reference.
   * 
   * @param easting
   *          the easting in metres
   * @param northing
   *          the northing in metres
   * @since 1.0
   */
00036   public OSRef(double easting, double northing) {
    this.easting = easting;
    this.northing = northing;
  }


  /**
   * Take a string formatted as a six-figure OS grid reference (e.g. "TG514131")
   * and create a new OSRef object that represents that grid reference. The
   * first character must be H, N, S, O or T. The second character can be any
   * uppercase character from A through Z excluding I.
   * 
   * @param ref
   *          a String representing a six-figure Ordnance Survey grid reference
   *          in the form XY123456
   * @throws IllegalArgumentException
   *           if ref is not of the form XY123456
   * @since 1.0
   */
00055   public OSRef(String ref) throws IllegalArgumentException {
    // if (ref.matches(""))
    char char1 = ref.charAt(0);
    char char2 = ref.charAt(1);
    // Thanks to Nick Holloway for pointing out the radix bug here
    int east = Integer.parseInt(ref.substring(2, 5)) * 100;
    int north = Integer.parseInt(ref.substring(5, 8)) * 100;
    if (char1 == 'H') {
      north += 1000000;
    } else if (char1 == 'N') {
      north += 500000;
    } else if (char1 == 'O') {
      north += 500000;
      east += 500000;
    } else if (char1 == 'T') {
      east += 500000;
    }
    int char2ord = char2;
    if (char2ord > 73)
      char2ord--; // Adjust for no I
    double nx = ((char2ord - 65) % 5) * 100000;
    double ny = (4 - Math.floor((char2ord - 65) / 5)) * 100000;
    easting = east + nx;
    northing = north + ny;
  }


  /**
   * Return a String representation of this OSGB grid reference showing the
   * easting and northing.
   * 
   * @return a String represenation of this OSGB grid reference
   * @since 1.0
   */
00089   public String toString() {
    return "(" + easting + ", " + northing + ")";
  }


  /**
   * Return a String representation of this OSGB grid reference using the
   * six-figure notation in the form XY123456
   * 
   * @return a String representing this OSGB grid reference in six-figure
   *         notation
   * @since 1.0
   */
00102   public String toSixFigureString() {
    int hundredkmE = (int) Math.floor(easting / 100000);
    int hundredkmN = (int) Math.floor(northing / 100000);
    String firstLetter;
    if (hundredkmN < 5) {
      if (hundredkmE < 5) {
        firstLetter = "S";
      } else {
        firstLetter = "T";
      }
    } else if (hundredkmN < 10) {
      if (hundredkmE < 5) {
        firstLetter = "N";
      } else {
        firstLetter = "O";
      }
    } else {
      firstLetter = "H";
    }

    int index = 65 + ((4 - (hundredkmN % 5)) * 5) + (hundredkmE % 5);
    // int ti = index;
    if (index >= 73)
      index++;
    String secondLetter = Character.toString((char) index);

    int e = (int) Math.floor((easting - (100000 * hundredkmE)) / 100);
    int n = (int) Math.floor((northing - (100000 * hundredkmN)) / 100);
    String es = "" + e;
    if (e < 100)
      es = "0" + es;
    if (e < 10)
      es = "0" + es;
    String ns = "" + n;
    if (n < 100)
      ns = "0" + ns;
    if (n < 10)
      ns = "0" + ns;

    return firstLetter + secondLetter + es + ns;
  }


  /**
   * Convert this OSGB grid reference to a latitude/longitude pair using the
   * OSGB36 datum. Note that, the LatLng object may need to be converted to the
   * WGS84 datum depending on the application.
   * 
   * @return a LatLng object representing this OSGB grid reference using the
   *         OSGB36 datum
   * @since 1.0
   */
00154   public LatLng toLatLng() {
    double OSGB_F0 = 0.9996012717;
    double N0 = -100000.0;
    double E0 = 400000.0;
    double phi0 = Math.toRadians(49.0);
    double lambda0 = Math.toRadians(-2.0);
    double a = RefEll.AIRY_1830.getMaj();
    double b = RefEll.AIRY_1830.getMin();
    double eSquared = RefEll.AIRY_1830.getEcc();
    double phi = 0.0;
    double lambda = 0.0;
    double E = this.easting;
    double N = this.northing;
    double n = (a - b) / (a + b);
    double M = 0.0;
    double phiPrime = ((N - N0) / (a * OSGB_F0)) + phi0;
    do {
      M =
          (b * OSGB_F0)
              * (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n)) * (phiPrime - phi0))
                  - (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))
                      * Math.sin(phiPrime - phi0) * Math.cos(phiPrime + phi0))
                  + ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))
                      * Math.sin(2.0 * (phiPrime - phi0)) * Math
                      .cos(2.0 * (phiPrime + phi0))) - (((35.0 / 24.0) * n * n * n)
                  * Math.sin(3.0 * (phiPrime - phi0)) * Math
                  .cos(3.0 * (phiPrime + phi0))));
      phiPrime += (N - N0 - M) / (a * OSGB_F0);
    } while ((N - N0 - M) >= 0.001);
    double v =
        a * OSGB_F0
            * Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -0.5);
    double rho =
        a * OSGB_F0 * (1.0 - eSquared)
            * Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -1.5);
    double etaSquared = (v / rho) - 1.0;
    double VII = Math.tan(phiPrime) / (2 * rho * v);
    double VIII =
        (Math.tan(phiPrime) / (24.0 * rho * Math.pow(v, 3.0)))
            * (5.0 + (3.0 * Util.tanSquared(phiPrime)) + etaSquared - (9.0 * Util
                .tanSquared(phiPrime) * etaSquared));
    double IX =
        (Math.tan(phiPrime) / (720.0 * rho * Math.pow(v, 5.0)))
            * (61.0 + (90.0 * Util.tanSquared(phiPrime)) + (45.0 * Util
                .tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
    double X = Util.sec(phiPrime) / v;
    double XI =
        (Util.sec(phiPrime) / (6.0 * v * v * v))
            * ((v / rho) + (2 * Util.tanSquared(phiPrime)));
    double XII =
        (Util.sec(phiPrime) / (120.0 * Math.pow(v, 5.0)))
            * (5.0 + (28.0 * Util.tanSquared(phiPrime)) + (24.0 * Util
                .tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
    double XIIA =
        (Util.sec(phiPrime) / (5040.0 * Math.pow(v, 7.0)))
            * (61.0
                + (662.0 * Util.tanSquared(phiPrime))
                + (1320.0 * Util.tanSquared(phiPrime) * Util
                    .tanSquared(phiPrime)) + (720.0 * Util.tanSquared(phiPrime)
                * Util.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
    phi =
        phiPrime - (VII * Math.pow(E - E0, 2.0))
            + (VIII * Math.pow(E - E0, 4.0)) - (IX * Math.pow(E - E0, 6.0));
    lambda =
        lambda0 + (X * (E - E0)) - (XI * Math.pow(E - E0, 3.0))
            + (XII * Math.pow(E - E0, 5.0)) - (XIIA * Math.pow(E - E0, 7.0));

    return new LatLng(Math.toDegrees(phi), Math.toDegrees(lambda));
  }


  /**
   * Get the easting.
   * 
   * @return the easting in metres
   * @since 1.0
   */
00231   public double getEasting() {
    return easting;
  }


  /**
   * Get the northing.
   * 
   * @return the northing in metres
   * @since 1.0
   */
00242   public double getNorthing() {
    return northing;
  }
}

Generated by  Doxygen 1.6.0   Back to index