osgEarth 2.1.1
Public Types | Public Member Functions | Private Attributes

osgEarth::Util::MGRSFormatter Class Reference

List of all members.

Public Types

enum  Precision {
  PRECISION_100000M = 100000, PRECISION_10000M = 10000, PRECISION_1000M = 1000, PRECISION_100M = 100,
  PRECISION_10M = 10, PRECISION_1M = 1
}
enum  Options { USE_SPACES = 1 << 0, FORCE_AA_SCHEME = 1 << 1, FORCE_AL_SCHEME = 1 << 2 }

Public Member Functions

 MGRSFormatter (Precision precision=PRECISION_1M, const SpatialReference *refSRS=0L, unsigned options=0)
std::string format (double latDeg, double lonDeg) const

Private Attributes

osg::ref_ptr< const
SpatialReference
_refSRS
bool _useAL
Precision _precision
unsigned _options

Detailed Description

Formats coordinate data as MGRS.

NOTE: This class does not yet handle the special UTM zone exceptions for southwest Norway (zone 32V) and Svalbard (31X, 33X, 35X, 37X).

See: http://en.wikipedia.org/wiki/Military_grid_reference_system

Definition at line 90 of file Formatters.


Member Enumeration Documentation

Enumerator:
USE_SPACES 
FORCE_AA_SCHEME 
FORCE_AL_SCHEME 

Definition at line 103 of file Formatters.

        {
            USE_SPACES        = 1 << 0,     // insert spaces between MGRS elements
            FORCE_AA_SCHEME   = 1 << 1,     // use the AA row lettering scheme regardless of ellipsoid
            FORCE_AL_SCHEME   = 1 << 2      // use the AL row lettering scheme regardless of ellipsoid
        };
Enumerator:
PRECISION_100000M 
PRECISION_10000M 
PRECISION_1000M 
PRECISION_100M 
PRECISION_10M 
PRECISION_1M 

Definition at line 93 of file Formatters.

        {
            PRECISION_100000M = 100000,     // i.e., omit the numerical offsets altogether
            PRECISION_10000M  = 10000,
            PRECISION_1000M   = 1000,
            PRECISION_100M    = 100,
            PRECISION_10M     = 10,
            PRECISION_1M      = 1
        };

Constructor & Destructor Documentation

MGRSFormatter::MGRSFormatter ( Precision  precision = PRECISION_1M,
const SpatialReference refSRS = 0L,
unsigned  options = 0 
)

Initialized an MGRS formatter.

Parameters:
precisionPrecision with which to print the MGRS string (see Precision above)
refSRSReference geographic SRS for MGRS encoding. Older datums (Clark and Bessel) change the row lettering scheme. Default=WGS84.
optionsFormatting options (see Options above)

Definition at line 176 of file Formatters.cpp.

                                                               :
_precision( precision ),
_options  ( options )
{
    if ( referenceSRS )
    {
        _refSRS = referenceSRS->getGeographicSRS();
    }
    else
    {
        _refSRS = SpatialReference::create( "wgs84" );
    }

    if ( options & FORCE_AA_SCHEME )
    {
        _useAL = false;
    }
    else if ( options & FORCE_AL_SCHEME )
    {
        _useAL = true;
    }
    else
    {
        // use the "AL" lettering scheme for these older datum ellipsoids.
        std::string eName = _refSRS->getEllipsoid()->getName();
        _useAL = 
            eName.find("bessel") != std::string::npos ||
            eName.find("clark")  != std::string::npos ||
            eName.find("clrk")   != std::string::npos;
    }
}

Here is the call graph for this function:


Member Function Documentation

std::string MGRSFormatter::format ( double  latDeg,
double  lonDeg 
) const

Formats a lat/lon (in degrees) as an MGRS string.

Definition at line 211 of file Formatters.cpp.

{
    unsigned    zone;
    char        gzd;
    unsigned    x=0, y=0;
    char        sqid[3];
    std::string space;

    if ( _options & USE_SPACES )
        space = " ";

    sqid[0] = '?';
    sqid[1] = '?';
    sqid[2] = 0;

    if ( latDeg >= 84.0 || latDeg <= -80.0 ) // polar projection
    {
        bool isNorth = latDeg > 0.0;
        zone = 0;
        gzd = isNorth ? (lonDeg < 0.0 ? 'Y' : 'Z') : (lonDeg < 0.0? 'A' : 'B');

        osg::ref_ptr<const SpatialReference> ups = isNorth?
            SpatialReference::create( "+proj=stere +lat_ts=90 +lat_0=90 +lon_0=0 +k_0=1 +x_0=0 +y_0=0" ) :
            SpatialReference::create( "+proj=stere +lat_ts=-90 +lat_0=-90 +lon_0=0 +k_0=1 +x_0=0 +y_0=0" );

        if ( !ups.valid() )
        {
            OE_WARN << LC << "Failed to create UPS SRS" << std::endl;
            return "";
        }

        double upsX, upsY;
        if ( _refSRS->transform2D( lonDeg, latDeg, ups.get(), upsX, upsY ) == false )
        {
            OE_WARN << LC << "Failed to transform lat/long to UPS" << std::endl;
            return "";
        }

        int sqXOffset = upsX >= 0.0 ? (int)floor(upsX/100000.0) : -(int)floor(1.0-(upsX/100000.0));
        int sqYOffset = upsY >= 0.0 ? (int)floor(upsY/100000.0) : -(int)floor(1.0-(upsY/100000.0));

        int alphaOffset = isNorth ? 7 : 12;

        sqid[0] = UPS_COL_ALPHABET[ (UPS_COL_ALPHABET_SIZE+sqXOffset) % UPS_COL_ALPHABET_SIZE ];
        sqid[1] = UPS_ROW_ALPHABET[alphaOffset + sqYOffset];

        x = upsX - (100000.0*(double)sqXOffset);
        y = upsY - (100000.0*(double)sqYOffset);
    }

    else // UTM
    {
        // figure out the grid zone designator
        unsigned gzdIndex = ((unsigned)(latDeg+80.0))/8;
        gzd = GZD_ALPHABET[gzdIndex];

        // figure out the UTM zone:
        zone = (unsigned)floor((lonDeg+180.0)/6.0);   // [0..59]
        bool north = latDeg >= 0.0;

        // convert the input coordinates to UTM:
        // yes, always use +north so we get Y relative to equator
        std::stringstream buf;
        buf << "+proj=utm +zone=" << (zone+1) << " +north +units=m";
        osg::ref_ptr<SpatialReference> utm = SpatialReference::create( buf.str() );

        double utmX, utmY;
        if ( _refSRS->transform2D( lonDeg, latDeg, utm.get(), utmX, utmY ) == false )
        {
            OE_WARN << LC << "Error transforming lat/long into UTM" << std::endl;
            return "";
        }

        // the alphabet set:
        unsigned set = zone % 6; // [0..5]

        // find the horizontal SQID offset (100KM increments) from the central meridian:
        unsigned xSetOffset = 8 * (set % 3);
        double xMeridianOffset = utmX - 500000.0;
        int sqMeridianOffset = xMeridianOffset >= 0.0 ? (int)floor(xMeridianOffset/100000.0) : -(int)floor(1.0-(xMeridianOffset/100000.0));
        unsigned indexOffset = (4 + sqMeridianOffset);
        sqid[0] = UTM_COL_ALPHABET[xSetOffset + indexOffset];
        double xWest = 500000.0 + (100000.0*(double)sqMeridianOffset);
        x = utmX - xWest;

        // find the vertical SQID offset (100KM increments) from the equator:
        unsigned ySetOffset = 5 * (zone % 2); //(set % 2);
        int sqEquatorOffset = (int)floor(utmY/100000.0);
        int absOffset = ySetOffset + sqEquatorOffset + (10 * UTM_ROW_ALPHABET_SIZE);
        if ( _useAL )
            absOffset += 10;
        sqid[1] = UTM_ROW_ALPHABET[absOffset % UTM_ROW_ALPHABET_SIZE];
        y = utmY - (100000.0*(double)sqEquatorOffset);
    }

    std::stringstream buf;

    if ( (unsigned)_precision > PRECISION_1M )
    {
        x /= (unsigned)_precision;
        y /= (unsigned)_precision;
    }

    buf << (zone+1) << gzd << space << sqid;

    if ( (unsigned)_precision < PRECISION_100000M )
    {
        int sigdigs =
            _precision == PRECISION_10000M ? 1 :
            _precision == PRECISION_1000M  ? 2 :
            _precision == PRECISION_100M   ? 3 :
            _precision == PRECISION_10M    ? 4 :
            5;

        buf << space
            << std::setfill('0')
            << std::setw(sigdigs) << x
            << space
            << std::setw(sigdigs) << y;
    }

    std::string result;
    result = buf.str();
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 133 of file Formatters.

Definition at line 132 of file Formatters.

Definition at line 130 of file Formatters.

Definition at line 131 of file Formatters.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines