- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# Y:/msp/devkits/temp_geotrans/master/geotrans3.1/CCS/src/dtcc/CoordinateSystems/bng/BritishNationalGrid.cpp

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /***************************************************************************/
    00004 /* RSC IDENTIFIER: BRITISH NATIONAL GRID
    00005  *
    00006  * ABSTRACT
    00007  *
    00008  *    This component provides conversions between Geodetic coordinates
    00009  *    (latitude and longitude) and British National Grid coordinates.
    00010  *
    00011  * ERROR HANDLING
    00012  *
    00013  *    This component checks parameters for valid values.  If an invalid value
    00014  *    is found the error code is combined with the current error code using
    00015  *    the bitwise or.  This combining allows multiple error codes to be
    00016  *    returned. The possible error codes are:
    00017  *
    00018  *       BNG_NO_ERROR               : No errors occurred in function
    00019  *       BNG_LAT_ERROR              : Latitude outside of valid range
    00020  *                                      (49.5 to 61.5 degrees)
    00021  *       BNG_LON_ERROR              : Longitude outside of valid range
    00022  *                                      (-10.0 to 3.5 degrees)
    00023  *       BNG_EASTING_ERROR          : Easting outside of valid range
    00024  *                                      (depending on ellipsoid and
    00025  *                                       projection parameters)
    00026  *       BNG_NORTHING_ERROR         : Northing outside of valid range
    00027  *                                      (depending on ellipsoid and
    00028  *                                       projection parameters)
    00029  *       BNG_STRING_ERROR           : A BNG string error: string too long,
    00030  *                                      too short, or badly formed
    00031  *       BNG_INVALID_AREA_ERROR     : Coordinate is outside of valid area
    00032  *       BNG_ELLIPSOID_ERROR        : Invalid ellipsoid - must be Airy
    00033  *
    00034  * REUSE NOTES
    00035  *
    00036  *    BRITISH NATIONAL GRID is intended for reuse by any application that
    00037  *    performs a British National Grid projection or its inverse.
    00038  *
    00039  * REFERENCES
    00040  *
    00041  *    Further information on BRITISH NATIONAL GRID can be found in the
    00042  *    Reuse Manual.
    00043  *
    00044  *    BRITISH NATIONAL GRID originated from :
    00045  *                      U.S. Army Topographic Engineering Center
    00046  *                      Geospatial Information Division
    00047  *                      7701 Telegraph Road
    00048  *                      Alexandria, VA  22310-3864
    00049  *
    00050  * LICENSES
    00051  *
    00052  *    None apply to this component.
    00053  *
    00054  * RESTRICTIONS
    00055  *
    00056  *    BRITISH NATIONAL GRID has no restrictions.
    00057  *
    00058  * ENVIRONMENT
    00059  *
    00060  *    BRITISH NATIONAL GRID was tested and certified in the following
    00061  *    environments:
    00062  *
    00063  *    1. Solaris 2.5 with GCC, version 2.8.1
    00064  *    2. Windows 95 with MS Visual C++, version 6
    00065  *
    00066  * MODIFICATIONS
    00067  *
    00068  *    Date              Description
    00069  *    ----              -----------
    00070  *    09-06-00          Original Code
    00071  *    03-02-07          Original C++ Code
    00072  *
    00073  *
    00074  */
    00075
    00076
    00077 /***************************************************************************/
    00078 /*
    00079  *                               INCLUDES
    00080  */
    00081
    00082 #include <ctype.h>
    00083 #include <math.h>
    00084 #include <stdio.h>
    00085 #include <string.h>
    00086 #include "TransverseMercator.h"
    00087 #include "BritishNationalGrid.h"
    00088 #include "BNGCoordinates.h"
    00089 #include "EllipsoidParameters.h"
    00090 #include "MapProjectionCoordinates.h"
    00091 #include "GeodeticCoordinates.h"
    00092 #include "CoordinateConversionException.h"
    00093 #include "ErrorMessages.h"
    00094
    00095 /*
    00096  *    ctype.h     - Standard C character handling library
    00097  *    math.h      - Standard C math library
    00098  *    stdio.h     - Standard C input/output library
    00099  *    string.h    - Standard C string handling library
    00100  *    TransverseMercator.h  - Is used to convert transverse mercator coordinates
    00101  *    BritishNationalGrid.h       - Is for prototype error checking
    00102  *    BNGCoordinates.h   - defines bng coordinates
    00103  *    MapProjectionCoordinates.h   - defines map projection coordinates
    00104  *    GeodeticCoordinates.h   - defines geodetic coordinates
    00105  *    CoordinateConversionException.h - Exception handler
    00106  *    ErrorMessages.h  - Contains exception messages
    00107  */
    00108
    00109
    00110 using namespace MSP::CCS;
    00111
    00112
    00113 /***************************************************************************/
    00114 /*                               DEFINES
    00115  *
    00116  */
    00117
    00118 const double PI = 3.14159265358979323e0;              /* PI     */
    00119 const double PI_OVER_2 = (PI / 2.0e0);                /* PI over 2 */
    00120 const double TWO_PI = (2.0e0 * PI);                   /* 2 * PI */
    00121 const double MAX_LAT = (61.5 * PI / 180.0);           /* 61.5 degrees */
    00122 const double MIN_LAT = (49.5 * PI / 180.0);           /* 49.5 degrees */
    00123 const double MAX_LON = (3.5 * PI / 180.0);            /* 3.5 degrees */
    00124 const double MIN_LON = (-10.0 * PI / 180.0);          /* -10 degrees */
    00125 const char* BNG500GRID = "STNOHJ";                    /* 500,000 unit square identifications */
    00126 const char* BNG100GRID = "VWXYZQRSTULMNOPFGHJKABCDE"; /* 100,000 unit square identifications */
    00127
    00128 /* BNG projection Parameters */
    00129 const double BNG_Origin_Lat = (49.0 * PI / 180.0);  /* Latitude of origin, in radians */
    00130 const double BNG_Origin_Long = (-2.0 * PI / 180.0); /* Longitude of origin, in radians */
    00131 const double BNG_False_Northing = -100000.0;        /* False northing, in meters */
    00132 const double BNG_False_Easting = 400000.0;          /* False easting, in meters */
    00133 const double BNG_Scale_Factor = .9996012717;        /* Scale factor                      */
    00134
    00135 /* Maximum variance for easting and northing values for Airy. */
    00136 const double BNG_Max_Easting = 759961.0;
    00137 const double BNG_Max_Northing = 1257875.0;
    00138 const double BNG_Min_Easting = -133134.0;
    00139 const double BNG_Min_Northing = -14829.0;
    00140
    00141 static const char* Airy = "AA";
    00142
    00143
    00144 /************************************************************************/
    00145 /*                              LOCAL FUNCTIONS
    00146  *
    00147  */
    00148
    00149 void findIndex( char letter, const char* letterArray, long *index )
    00150 {
    00151 /*
    00152  * The function findIndex searches for a given letter in an array.
    00153  * It returns the index of the letter in the array if the letter is found.
    00154  * If the letter is not found, an error code is returned, otherwise
    00155  * BNG_NO_ERROR is returned.
    00156  *
    00157  *    letter              : Letter being searched for
    00158  *    letter_Array        : Array being searched
    00159  *    index               : Index of letter in array
    00160  */
    00161   long i = 0;
    00162   long not_Found = 1;
    00163   long length = strlen(letterArray);
    00164
    00165   while ((i < length) && (not_Found))
    00166   {
    00167     if (letter == letterArray[i])
    00168     {
    00169       *index = i;
    00170       not_Found = 0;
    00171     }
    00172     i++;
    00173   }
    00174   if (not_Found)
    00175     throw CoordinateConversionException( ErrorMessages::bngString );
    00176 }
    00177
    00178
    00179 long roundBNG( double value )
    00180 {
    00181 /* Round value to nearest integer, using standard engineering rule */
    00182   double ivalue;
    00183   long ival;
    00184   double fraction = modf (value, &ivalue);
    00185   ival = (long)(ivalue);
    00186   if ((fraction > 0.5) || ((fraction == 0.5) && (ival%2 == 1)))
    00187     ival++;
    00188
    00189   return (ival);
    00190 }
    00191
    00192
    00193 void makeBNGString( char ltrnum[4], long easting, long northing, char* BNGString, long precision )
    00194 /* Construct a BNG string from its component parts */
    00195 {
    00196
    00197   double divisor;
    00198   long east;
    00199   long north;
    00200   long i;
    00201   long j;
    00202   double unitInterval;
    00203
    00204   i = 0;
    00205   for (j = 0; j < 3; j++)
    00206     BNGString[i++] = ltrnum[j];
    00207   divisor = pow (10.0, (5.0 - precision));
    00208   unitInterval = pow (10.0, (double)precision);
    00209
    00210   east = roundBNG (easting/divisor);
    00211   if (east == unitInterval)
    00212     east -= 1;
    00213   if ((precision == 0) && (east == 1))
    00214     east = 0;
    00215   i += sprintf (BNGString + i, "%*.*ld", precision, precision, east);
    00216
    00217   north = roundBNG (northing/divisor);
    00218   if (north == unitInterval)
    00219     north -= 1;
    00220   if ((precision == 0) && (north == 1))
    00221     north = 0;
    00222   i += sprintf (BNGString + i, "%*.*ld",  precision, precision, north);
    00223 }
    00224
    00225
    00226 bool checkOutOfArea( char BNG500, char BNG100 )
    00227
    00228 {
    00229 /*
    00230  * The function checkOutOfArea checks if the 500,000 and
    00231  * 100,000 unit square identifications are within the valid area. If
    00232  * they are not, an error code is returned, otherwise BNG_NO_ERROR
    00233  * is returned.
    00234  *
    00235  *    BNG500        : 500,000 square unit identification
    00236  *    BNG100        : 100,000 square unit identification
    00237  */
    00238
    00239   bool outOfArea = false;
    00240
    00241   switch (BNG500)
    00242   {
    00243     case 'S':
    00244       switch (BNG100)
    00245       {
    00246         case 'A':
    00247         case 'F':
    00248         case 'L':
    00249           outOfArea = true;
    00250           break;
    00251         default:
    00252           break;
    00253       }
    00254       break;
    00255     case 'N':
    00256       switch (BNG100)
    00257       {
    00258         case 'V':
    00259           outOfArea = true;
    00260           break;
    00261         default:
    00262           break;
    00263       }
    00264       break;
    00265
    00266     case 'H':
    00267       if (BNG100 < 'L')
    00268         outOfArea = true;
    00269       break;
    00270     case 'T':
    00271       switch (BNG100)
    00272       {
    00273         case 'D':
    00274         case 'E':
    00275         case 'J':
    00276         case 'K':
    00277         case 'O':
    00278         case 'P':
    00279         case 'T':
    00280         case 'U':
    00281         case 'X':
    00282         case 'Y':
    00283         case 'Z':
    00284           outOfArea = true;
    00285           break;
    00286         default:
    00287           break;
    00288       }
    00289       break;
    00290     case 'O':
    00291       switch (BNG100)
    00292       {
    00293         case 'C':
    00294         case 'D':
    00295         case 'E':
    00296         case 'J':
    00297         case 'K':
    00298         case 'O':
    00299         case 'P':
    00300         case 'T':
    00301         case 'U':
    00302         case 'Y':
    00303         case 'Z':
    00304           outOfArea = true;
    00305           break;
    00306         default:
    00307           break;
    00308       }
    00309       break;
    00310     case 'J':
    00311       switch (BNG100)
    00312       {
    00313         case 'L':
    00314         case 'M':
    00315         case 'Q':
    00316         case 'R':
    00317         case 'V':
    00318         case 'W':
    00320           break;
    00321         default:
    00322           outOfArea = true;
    00323           break;
    00324       }
    00325       break;
    00326     default:
    00327       outOfArea = true;
    00328       break;
    00329   }
    00330
    00331   return outOfArea;
    00332 }
    00333
    00334
    00335 void breakBNGString( char* BNGString, char letters[3], double* easting, double* northing, long* precision )
    00336 {
    00337 /* Break down a BNG string into its component parts */
    00338
    00339   long i = 0;
    00340   long j;
    00341   long num_digits = 0;
    00342   long num_letters;
    00343   long length = strlen(BNGString);
    00344
    00345   while (BNGString[i] == ' ')
    00346     i++;  /* skip any leading blanks */
    00347   j = i;
    00348   while (isalpha(BNGString[i]))
    00349     i++;
    00350   num_letters = i - j;
    00351   if (num_letters == 2)
    00352   {
    00353     /* get letters */
    00354     letters[0] = (char)toupper(BNGString[j]);
    00355     letters[1] = (char)toupper(BNGString[j+1]);
    00356     letters[2] = 0;
    00357   }
    00358   else
    00359     throw CoordinateConversionException( ErrorMessages::bngString );
    00360
    00361   checkOutOfArea(letters[0], letters[1]);
    00362   while (BNGString[i] == ' ')
    00363     i++;
    00364   j = i;
    00365   if (BNGString[length-1] == ' ')
    00366     length --;
    00367   while (i < length)
    00368   {
    00369     if (isdigit(BNGString[i]))
    00370       i++;
    00371     else
    00372       throw CoordinateConversionException( ErrorMessages::bngString );
    00373   }
    00374
    00375   num_digits = i - j;
    00376   if ((num_digits <= 10) && (num_digits%2 == 0))
    00377   {
    00378     long n;
    00379     char east_string[6];
    00380     char north_string[6];
    00381     long east;
    00382     long north;
    00383     double multiplier;
    00384
    00385     /* get easting & northing */
    00386     n = num_digits / 2;
    00387     *precision = n;
    00388     if (n > 0)
    00389     {
    00390       strncpy (east_string, BNGString+j, n);
    00391       east_string[n] = 0;
    00392       sscanf (east_string, "%ld", &east);
    00393       strncpy (north_string, BNGString+j+n, n);
    00394       north_string[n] = 0;
    00395       sscanf (north_string, "%ld", &north);
    00396       multiplier = pow (10.0, 5.0 - n);
    00397       *easting = east * multiplier;
    00398       *northing = north * multiplier;
    00399     }
    00400     else
    00401     {
    00402       *easting = 0.0;
    00403       *northing = 0.0;
    00404     }
    00405   }
    00406   else
    00407     throw CoordinateConversionException( ErrorMessages::bngString );
    00408 }
    00409
    00410
    00411 /************************************************************************/
    00412 /*                              FUNCTIONS
    00413  *
    00414  */
    00415
    00416 BritishNationalGrid::BritishNationalGrid( char *ellipsoidCode ) :
    00417   CoordinateSystem( 6377563.396, 1 / 299.324964600 ),
    00418   transverseMercator( 0 ),
    00419   BNG_Easting( 0.0 ),
    00420   BNG_Northing( 0.0 )
    00421 {
    00422 /*
    00423  * The constructor receives the ellipsoid code and sets
    00424  * the corresponding state variables. If any errors occur, an exception is thrown
    00425  * with a description of the error.
    00426  *
    00427  *   ellipsoidCode : 2-letter code for ellipsoid           (input)
    00428  */
    00429
    00430   strcpy( BNG_Letters, "SV" );
    00431   strcpy( BNG_Ellipsoid_Code, "AA");
    00432
    00433   if ( strcmp( ellipsoidCode, Airy ) != 0 )
    00434   { /* Ellipsoid must be Airy */
    00435     throw CoordinateConversionException( ErrorMessages::bngEllipsoid );
    00436   }
    00437
    00438   strcpy( BNG_Ellipsoid_Code, ellipsoidCode );
    00439
    00440   transverseMercator = new TransverseMercator( semiMajorAxis, flattening, BNG_Origin_Long, BNG_Origin_Lat,
    00441                                      BNG_False_Easting, BNG_False_Northing, BNG_Scale_Factor );
    00442 }
    00443
    00444
    00445 BritishNationalGrid::BritishNationalGrid( const BritishNationalGrid &bng )
    00446 {
    00447   transverseMercator = new TransverseMercator( *( bng.transverseMercator ) );
    00448   semiMajorAxis = bng.semiMajorAxis;
    00449   flattening = bng.flattening;
    00450   BNG_Easting = bng.BNG_Easting;
    00451   BNG_Northing = bng.BNG_Northing;
    00452 }
    00453
    00454
    00455 BritishNationalGrid::~BritishNationalGrid()
    00456 {
    00457   delete transverseMercator;
    00458   transverseMercator = 0;
    00459 }
    00460
    00461
    00462 BritishNationalGrid& BritishNationalGrid::operator=( const BritishNationalGrid &bng )
    00463 {
    00464   if( this != &bng )
    00465   {
    00466     transverseMercator->operator=( *bng.transverseMercator );
    00467     semiMajorAxis = bng.semiMajorAxis;
    00468     flattening = bng.flattening;
    00469     BNG_Easting = bng.BNG_Easting;
    00470     BNG_Northing = bng.BNG_Northing;
    00471   }
    00472
    00473   return *this;
    00474 }
    00475
    00476
    00477 EllipsoidParameters* BritishNationalGrid::getParameters() const
    00478 {
    00479 /*
    00480  * The function getParameters returns the current ellipsoid
    00481  * code.
    00482  *
    00483  *   ellipsoidCode : 2-letter code for ellipsoid          (output)
    00484  */
    00485
    00486   return new EllipsoidParameters( semiMajorAxis, flattening, (char*)BNG_Ellipsoid_Code );
    00487 }
    00488
    00489
    00490 MSP::CCS::BNGCoordinates* BritishNationalGrid::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates, long precision )
    00491 {
    00492 /*
    00493  * The function convertFromGeodetic converts geodetic (latitude and
    00494  * longitude) coordinates to a BNG coordinate string, according to the
    00495  * current ellipsoid parameters.  If any errors occur, an exception is thrown
    00496  * with a description of the error.
    00497  *
    00498  *    longitude  : Longitude, in radians                   (input)
    00499  *    latitude   : Latitude, in radians                    (input)
    00500  *    precision  : Precision level of BNG string           (input)
    00501  *    BNGString  : British National Grid coordinate string (output)
    00502  *
    00503  */
    00504
    00505   double TMEasting, TMNorthing;
    00506   char errorStatus[50] = "";
    00507
    00508   double longitude = geodeticCoordinates->longitude();
    00509   double latitude = geodeticCoordinates->latitude();
    00510
    00511   if ((latitude < MIN_LAT) || (latitude > MAX_LAT))
    00512   {  /* Latitude out of range */
    00513     strcat( errorStatus, MSP::CCS::ErrorMessages::latitude );
    00514   }
    00515   if ((longitude < MIN_LON) || (longitude > MAX_LON))
    00516   {  /* Longitude out of range */
    00517     strcat( errorStatus, MSP::CCS::ErrorMessages::longitude );
    00518   }
    00519
    00520   if( strlen( errorStatus ) > 0)
    00521     throw CoordinateConversionException( errorStatus );
    00522
    00523   MapProjectionCoordinates* transverseMercatorCoordinates = transverseMercator->convertFromGeodetic( geodeticCoordinates );
    00524
    00525   TMEasting = transverseMercatorCoordinates->easting();
    00526   TMNorthing = transverseMercatorCoordinates->northing();
    00527
    00528   if ((TMEasting < 0.0) && (TMEasting > -2.0))
    00529     transverseMercatorCoordinates->setEasting( 0.0 );
    00530   if ((TMNorthing < 0.0) && (TMNorthing > -2.0))
    00531     transverseMercatorCoordinates->setNorthing( 0.0 );
    00532
    00533   TMEasting = transverseMercatorCoordinates->easting();
    00534   TMNorthing = transverseMercatorCoordinates->northing();
    00535
    00536   if ((TMEasting < BNG_Min_Easting) || (TMEasting > BNG_Max_Easting))
    00537   {
    00538     delete transverseMercatorCoordinates;
    00539     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00540   }
    00541   if ((TMNorthing < BNG_Min_Northing) || (TMNorthing > BNG_Max_Northing))
    00542   {
    00543     delete transverseMercatorCoordinates;
    00544     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00545   }
    00546
    00547   BNGCoordinates* bngCoordinates = convertFromTransverseMercator( transverseMercatorCoordinates, precision );
    00548   delete transverseMercatorCoordinates;
    00549
    00550   return bngCoordinates;
    00551 }
    00552
    00553
    00554 MSP::CCS::GeodeticCoordinates* BritishNationalGrid::convertToGeodetic( MSP::CCS::BNGCoordinates* bngCoordinates )
    00555 {
    00556 /*
    00557  * The function convertToGeodetic converts a BNG coordinate string
    00558  * to geodetic (latitude and longitude) coordinates, according to the current
    00559  * ellipsoid parameters. If any errors occur, an exception is thrown
    00560  * with a description of the error.
    00561  *
    00562  *    BNGString  : British National Grid coordinate string (input)
    00563  *    longitude  : Longitude, in radians                   (output)
    00564  *    latitude   : Latitude, in radians                    (output)
    00565  *
    00566  */
    00567
    00568   double TMEasting, TMNorthing;
    00569   long in_Precision;
    00570
    00571   char* BNGString = bngCoordinates->BNGString();
    00572
    00573   breakBNGString( BNGString, BNG_Letters, &BNG_Easting, &BNG_Northing, &in_Precision );
    00574
    00575   MapProjectionCoordinates* transverseMercatorCoordinates = convertToTransverseMercator( bngCoordinates );
    00576   TMEasting = transverseMercatorCoordinates->easting();
    00577   TMNorthing = transverseMercatorCoordinates->northing();
    00578
    00579   if ((TMEasting < BNG_Min_Easting) || (TMEasting > BNG_Max_Easting))
    00580   {
    00581     delete transverseMercatorCoordinates;
    00582     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00583   }
    00584   if ((TMNorthing < BNG_Min_Northing) || (TMNorthing > BNG_Max_Northing))
    00585   {
    00586     delete transverseMercatorCoordinates;
    00587     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00588   }
    00589
    00590   GeodeticCoordinates* geodeticCoordinates = transverseMercator->convertToGeodetic( transverseMercatorCoordinates );
    00591   double latitude = geodeticCoordinates->latitude();
    00592   double longitude = geodeticCoordinates->longitude();
    00593   delete transverseMercatorCoordinates;
    00594
    00595   if ((latitude < MIN_LAT) || (latitude > MAX_LAT))
    00596   {
    00597     delete geodeticCoordinates;
    00598     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00599   }
    00600   if ((longitude < MIN_LON) || (longitude > MAX_LON))
    00601   {
    00602     delete geodeticCoordinates;
    00603     throw CoordinateConversionException( ErrorMessages::invalidArea );
    00604   }
    00605
    00606   return geodeticCoordinates;
    00607 }
    00608
    00609
    00610 MSP::CCS::BNGCoordinates* BritishNationalGrid::convertFromTransverseMercator( MapProjectionCoordinates* mapProjectionCoordinates, long precision )
    00611 {
    00612 /*
    00613  * The function convertFromTransverseMercator converts Transverse Mercator
    00614  * (easting and northing) coordinates to a BNG coordinate string, according
    00615  * to the current ellipsoid parameters.  If any errors occur, an exception is thrown
    00616  * with a description of the error.
    00617  *
    00618  *    easting    : Easting (X), in meters                  (input)
    00619  *    northing   : Northing (Y), in meters                 (input)
    00620  *    precision  : Precision level of BNG string           (input)
    00621  *    BNGString  : British National Grid coordinate string (output)
    00622  */
    00623
    00624   char letters[4];
    00625   long x, y;
    00626   long index;
    00627   long temp_Easting, temp_Northing;
    00628   char BNGString[21];
    00629   char errorStatus[50] = "";
    00630
    00631   double easting = mapProjectionCoordinates->easting();
    00632   double northing = mapProjectionCoordinates->northing();
    00633
    00634   if ((easting < BNG_Min_Easting) || (easting > BNG_Max_Easting))
    00635   { /* Easting out of range  */
    00636     strcat( errorStatus, ErrorMessages::easting );
    00637   }
    00638   if ((northing < BNG_Min_Northing) || (northing > BNG_Max_Northing))
    00639   { /* Northing out of range */
    00640     strcat( errorStatus, ErrorMessages::northing );
    00641   }
    00642
    00643   if( strlen( errorStatus ) > 0)
    00644     throw CoordinateConversionException( errorStatus );
    00645
    00646   temp_Easting = roundBNG(easting);
    00647   temp_Northing = roundBNG(northing);
    00648
    00649   temp_Easting += 1000000;
    00650   temp_Northing += 500000;
    00651
    00652   x = temp_Easting / 500000;
    00653   y = temp_Northing / 500000;
    00654
    00655   index = y * 5 + x;
    00656   if ((index >= 0) && (index < 25))
    00657   {
    00658     letters[0] = BNG100GRID[index];
    00659     temp_Easting %= 500000;
    00660     temp_Northing %= 500000;
    00661     x = temp_Easting / 100000;
    00662     y = temp_Northing / 100000;
    00663     index = y * 5 + x;
    00664     if ((index >= 0) && (index < 25))
    00665     {
    00666       letters[1] = BNG100GRID[index];
    00667
    00668       if( checkOutOfArea(letters[0], letters[1]) )
    00669         throw CoordinateConversionException( ErrorMessages::invalidArea );
    00670
    00671       letters[2] = ' ';
    00672       letters[3] = 0;
    00673       temp_Easting %= 100000;
    00674       temp_Northing %= 100000;
    00675       makeBNGString(letters, temp_Easting, temp_Northing, BNGString, precision);
    00676     }
    00677     else
    00678     {
    00679       long five_y = 5 * y;
    00680       if ((x >= (25 - five_y)) || (x < -five_y))
    00681         throw CoordinateConversionException( ErrorMessages::easting );
    00682       if ((five_y >= (25 - x)) || (five_y < -x))
    00683         throw CoordinateConversionException( ErrorMessages::northing );
    00684     }
    00685   }
    00686   else
    00687   {
    00688     long five_y = 5 * y;
    00689     if ((x >= (25 - five_y)) || (x < -five_y))
    00690       throw CoordinateConversionException( ErrorMessages::easting );
    00691     if ((five_y >= (25 - x)) || (five_y < -x))
    00692       throw CoordinateConversionException( ErrorMessages::northing );
    00693   }
    00694
    00695   return new BNGCoordinates( CoordinateType::britishNationalGrid, BNGString );
    00696 }
    00697
    00698
    00699 MSP::CCS::MapProjectionCoordinates* BritishNationalGrid::convertToTransverseMercator( MSP::CCS::BNGCoordinates* bngCoordinates )
    00700 {
    00701 /*
    00702  * The function convertToTransverseMercator converts a BNG coordinate string
    00703  * to Transverse Mercator projection (easting and northing) coordinates
    00704  * according to the current ellipsoid parameters.  If any errors occur, an exception is thrown
    00705  * with a description of the error.
    00706  * is returned.
    00707  *
    00708  *    BNGString  : British National Grid coordinate string (input)
    00709  *    easting    : Easting (X), in meters                  (output)
    00710  *    northing   : Northing (Y), in meters                 (output)
    00711  */
    00712
    00713   long northing_Offset, easting_Offset;
    00714   long i = 0;
    00715   long j = 0;
    00716   long in_Precision;
    00717
    00718   char* BNGString = bngCoordinates->BNGString();
    00719
    00720   breakBNGString( BNGString, BNG_Letters, &BNG_Easting, &BNG_Northing, &in_Precision );
    00721
    00722   findIndex(BNG_Letters[0], BNG500GRID, &i);
    00723
    00724   northing_Offset = 500000 * (i / 2);
    00725   easting_Offset = 500000 * (i % 2);
    00726
    00727   findIndex(BNG_Letters[1], BNG100GRID, &j);
    00728
    00729   northing_Offset += 100000 * (j / 5);
    00730   easting_Offset += 100000 * (j % 5);
    00731
    00732   double easting = BNG_Easting + easting_Offset;
    00733   double northing = BNG_Northing + northing_Offset;
    00734
    00735   return new MapProjectionCoordinates( CoordinateType::transverseMercator, easting, northing );
    00736 }
    00737
    00738
    00739
    00740
    00741 // CLASSIFICATION: UNCLASSIFIED