osgEarth 2.1.1
Public Member Functions | Protected Member Functions | Friends

seamless::EulerSpatialReference Class Reference

Inheritance diagram for seamless::EulerSpatialReference:
Collaboration diagram for seamless::EulerSpatialReference:

List of all members.

Public Member Functions

 EulerSpatialReference (void *handle)
virtual osgEarth::GeoLocatorcreateLocator (double xmin, double ymin, double xmax, double ymax, bool plate_carre=false) const
virtual bool isGeographic () const
virtual bool isProjected () const
virtual bool preTransform (double &x, double &y, void *context) const
virtual bool postTransform (double &x, double &y, void *context) const
virtual bool transform (double x, double y, const SpatialReference *to_srs, double &out_x, double &out_y, void *context=0L) const
virtual bool transformPoints (const SpatialReference *to_srs, double *x, double *y, unsigned int numPoints, void *context=0L, bool ignore_errors=false) const
virtual bool transformExtent (const SpatialReference *to_srs, double &in_out_xmin, double &in_out_ymin, double &in_out_xmax, double &in_out_ymax, void *context) const
virtual bool transformExtentPoints (const SpatialReference *to_srs, double in_xmin, double in_ymin, double in_xmax, double in_ymax, double *x, double *y, unsigned int numx, unsigned int numy, void *context=0L, bool ignore_errors=false) const

Protected Member Functions

void _init ()

Friends

class CacheInitializer

Detailed Description

The EULER SRS represents a 6-face cube, each face being in unit coordinates (-1,-1=>1,1). The cube lays out the 4 equatorial faces in a row. The North Pole face is above face 0 and the South Pole face is below face 0. This results in a space measuring (0,0=>4,3).

Note: The cube faces have coordinates (0,0=>4,3), but the profile is defined as having a range of (0,0=>4,4) and one key at the top level. This key and its subkeys are not valid, but the cube faces will have an LOD of 2. This betters corresponds to the LODs in a geographic profile.

Definition at line 162 of file Euler.


Constructor & Destructor Documentation

seamless::EulerSpatialReference::EulerSpatialReference ( void *  handle)

Definition at line 588 of file Euler.cpp.

    : SpatialReference(handle, "OSGEARTH", "euler-cube",
                       "Euler Cube")
{
    //nop
}

Member Function Documentation

void seamless::EulerSpatialReference::_init ( ) [protected, virtual]

Reimplemented from osgEarth::SpatialReference.

Definition at line 596 of file Euler.cpp.

{
    SpatialReference::_init();

    _is_user_defined = true;
    _is_cube = true;
    _is_contiguous = false;
    _is_geographic = false;
    _name = "Euler Cube";
}
GeoLocator * seamless::EulerSpatialReference::createLocator ( double  xmin,
double  ymin,
double  xmax,
double  ymax,
bool  plate_carre = false 
) const [virtual]

Creates a new Locator object based on this spatial reference.

Parameters:
xmin,ymin,xmax,ymaxExtents of the tile for which to create a locator. These should be in degrees for a geographic/geocentric scene.
plate_carreSet this to true for the special case in which you are using a geographic SRS with a PROJECTED map (like flat-earth lat/long).

Reimplemented from osgEarth::SpatialReference.

Definition at line 608 of file Euler.cpp.

{
    int face;
    cubeToFace(xmin, ymin, xmax, ymax, face);

    GeoLocator* result = new EulerFaceLocator( face );

    osg::Matrixd transform;
    transform.set(
        xmax-xmin, 0.0,       0.0, 0.0,
        0.0,       ymax-ymin, 0.0, 0.0,
        0.0,       0.0,       1.0, 0.0,
        xmin,      ymin,      0.0, 1.0);
    result->setTransform( transform );

    return result;
}

Here is the call graph for this function:

virtual bool seamless::EulerSpatialReference::isGeographic ( ) const [inline, virtual]

True is this is a geographic SRS (i.e. unprojected lat/long)

Reimplemented from osgEarth::SpatialReference.

Definition at line 172 of file Euler.

{ return false; }
virtual bool seamless::EulerSpatialReference::isProjected ( ) const [inline, virtual]

True if this is a projected SRS (i.e. local coordinate system)

Reimplemented from osgEarth::SpatialReference.

Definition at line 173 of file Euler.

{ return true; }
bool seamless::EulerSpatialReference::postTransform ( double &  x,
double &  y,
void *  context 
) const [virtual]

Definition at line 652 of file Euler.cpp.

{
    //Convert the incoming points from lat/lon back to face coordinates
    int face;
    double out_x, out_y;

    // convert from lat/long to x/y/face
    bool success = latLonToFaceCoords(y, x, out_x, out_y, face);
    if (!success)
    {
        OE_WARN << LC << "Could not transform face coordinates to lat lon" << std::endl;
        return false;
    }

    //TODO: what to do about boundary points?

    if ( !faceToCube(out_x, out_y, face))
    {
        OE_WARN << LC << "fromFace(" << out_x << "," << out_y << "," << face << ") failed" << std::endl;
        return false;
    }

    x = out_x;
    y = out_y;

    return true;
}

Here is the call graph for this function:

bool seamless::EulerSpatialReference::preTransform ( double &  x,
double &  y,
void *  context 
) const [virtual]

Definition at line 629 of file Euler.cpp.

{
    // Convert the incoming points from cube => face => lat/long.
    int face;
    if ( !cubeToFace(x, y, face) )
    {
        OE_WARN << LC << "Failed to convert (" << x << "," << y << ") into face coordinates." << std::endl;
        return false;
    }

    double lat_deg, lon_deg;
    bool success = faceCoordsToLatLon( x, y, face, lat_deg, lon_deg );
    if (!success)
    {
        OE_WARN << LC << "Could not transform face coordinates to lat lon" << std::endl;
        return false;
    }
    x = lon_deg;
    y = lat_deg;
    return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool seamless::EulerSpatialReference::transform ( double  x,
double  y,
const SpatialReference to_srs,
double &  out_x,
double &  out_y,
void *  context = 0L 
) const [virtual]

Definition at line 681 of file Euler.cpp.

{
    if ( !_initialized )
        const_cast<EulerSpatialReference*>(this)->init();
    if (!to_srs->isEquivalentTo(getGeographicSRS()))
        return SpatialReference::transform(x, y, to_srs, out_x, out_y, context);
    if (EulerSpatialReference::preTransform(x, y, context))
    {
        out_x = x;
        out_y = y;
        return true;
    }
    else
    {
        return false;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool seamless::EulerSpatialReference::transformExtent ( const SpatialReference to_srs,
double &  in_out_xmin,
double &  in_out_ymin,
double &  in_out_xmax,
double &  in_out_ymax,
void *  context 
) const [virtual]

Transforms a spatial extent to another SRS.

TODO: Update this method to work for: a) Geographic extents that cross the date line; and b) Polar extents.

Reimplemented from osgEarth::SpatialReference.

Definition at line 724 of file Euler.cpp.

{
    // note: this method only works when the extent is isolated to one
    // face of the cube. If you want to transform an arbitrary extent,
    // you need to break it up into separate extents for each cube face.
    bool ok = true;

    double face_xmin = in_out_xmin, face_ymin = in_out_ymin;
    double face_xmax = in_out_xmax, face_ymax = in_out_ymax;

    int face;
    if (!cubeToFace(face_xmin, face_ymin, face_xmax, face_ymax, face))
    {
        OE_WARN << LC << "extent (" << in_out_xmin << ", " << in_out_ymin
                << ")=>(" << in_out_xmax << ", " << in_out_ymax <<
            ") crosses faces\n";
        return false;
    }
    // The polar and equatorial faces behave the same way, except if
    // an extent crosses the pole.

    double lonmin, lonmax, latmin, latmax;
    // if the extent crosses the center axes of the face, then,
    // due to the curvy nature of the projection, the maximim /
    // minimum will be at the crossing. So we may need to sample
    // up to 8 points.
    double lats[8], lons[8];
    int numSamples = 4;
    faceCoordsToLatLon(face_xmin, face_ymin, face, lats[0], lons[0]);
    faceCoordsToLatLon(face_xmax, face_ymin, face, lats[1], lons[1]);
    faceCoordsToLatLon(face_xmin, face_ymax, face, lats[2], lons[2]);
    faceCoordsToLatLon(face_xmax, face_ymax, face, lats[3], lons[3]);

    if ((face_xmin < 0 && face_xmax > 0))
    {
        faceCoordsToLatLon(0.0, face_ymin, face,
                           lats[numSamples], lons[numSamples]);
        faceCoordsToLatLon(0.0, face_ymax, face,
                           lats[numSamples + 1], lons[numSamples + 1]);
        numSamples += 2;

    }
    if ((face_ymin < 0 && face_ymax > 0))
    {
        faceCoordsToLatLon(face_xmin, 0.0, face,
                           lats[numSamples], lons[numSamples]);
        faceCoordsToLatLon(face_xmax, 0.0, face,
                           lats[numSamples + 1], lons[numSamples + 1]);
        numSamples += 2;

    }
    // keep extent longitudes consistent. If the max latitude lies on
    // the date line, its value should be 180, not -180. The poles are
    // especially interesting...
    if (face == 2 && face_xmax == 0.0)
    {
        lons[1] = 180.0;
        lons[3] = 180.0;
    }
    else if ((face == 4 && face_ymax > 0.0)
             || (face == 5 && face_ymax <= 0.0))
    {
        if (face_xmin == 0.0)
        {
            lons[0] = 180.0;
            lons[2] = 180.0;
        }
        else if (face_xmax == 0.0)
        {
            lons[1] = -180.0;
            lons[3] = -180.0;
        }
    }
    if ((face == 4 || face == 5) && face_ymax == 0.0)
    {
        if  (face_xmax == 0.0)
            lons[3] = -90;
        else if (face_xmin == 0.0)
            lons[2] = 90;
            
    }
    lonmin = *min_element(&lons[0], &lons[numSamples]);
    latmin = *min_element(&lats[0], &lats[numSamples]);
    lonmax = *max_element(&lons[0], &lons[numSamples]);
    latmax = *max_element(&lats[0], &lats[numSamples]);
    // Does the extent cross one of the poles?
    if ((face == 4 || face == 5) && numSamples == 8)
    {
        lonmin = -180.0;
        lonmax = 180.0;
        if (face == 4)
            latmax = 90.0;
        else
            latmin = -90.0;
    }
    // Check for Date Line crossing
    else if (face_xmin < 0 && face_xmax > 0
             && (face == 2 || (face == 4 && face_ymin >= 0)
                 || (face == 5 && face_ymax <= 0)))
    {
        std::swap(lonmin, lonmax);
    }
    if (to_srs->isGeographic())
    {
        in_out_xmin = lonmin;
        in_out_xmax = lonmax;
        in_out_ymin = latmin;
        in_out_ymax = latmax;
    }
    else
    {
        bool ok1 = transform(lonmin, latmin, to_srs, in_out_xmin, in_out_ymin,
                             context);
        bool ok2 = transform(lonmax, latmax, to_srs, in_out_xmax, in_out_ymax,
                             context);
        ok = ok1 && ok2;
    }
    return ok;
}

Here is the call graph for this function:

bool seamless::EulerSpatialReference::transformExtentPoints ( const SpatialReference to_srs,
double  in_xmin,
double  in_ymin,
double  in_xmax,
double  in_ymax,
double *  x,
double *  y,
unsigned int  numx,
unsigned int  numy,
void *  context = 0L,
bool  ignore_errors = false 
) const [virtual]

Reimplemented from osgEarth::SpatialReference.

Definition at line 852 of file Euler.cpp.

{
    if ( !_initialized )
        const_cast<EulerSpatialReference*>(this)->init();
    int face;

    // Punt if the extent covers more than one face (doesn't happen
    // normally).
    if (!(to_srs->isEquivalentTo(getGeographicSRS())
          && cubeToFace(in_xmin, in_ymin, in_xmax, in_ymax, face)))
        return SpatialReference::transformExtentPoints(
            to_srs, in_xmin, in_ymin, in_xmax, in_ymax, x, y,
            numx, numy, context, ignore_errors);
    const double dx = (in_xmax - in_xmin) / (numx - 1);
    const double dy = (in_ymax - in_ymin) / (numy - 1);
    unsigned pixel = 0;
    // Cache values for and tan(y)
    AutoBuffer<double, 256> tany(numy);
    // induction variables for column and row counters
    double fc = 0.0, fr = 0.0;
    for (unsigned r = 0; r < numy; ++r, ++fr)
        tany[r] = tan((in_ymin + fr * dy) * osg::PI_4);
    if (face < 4)
    {
        double lonBase = face * osg::PI_2;
        for (unsigned c = 0; c < numx; ++c, ++fc)
        {
            const double l = (in_xmin + fc * dx) * osg::PI_4;
            double lon = lonBase + l;
            lon = fmod(lon + osg::PI, 2.0 * osg::PI) - osg::PI;
            const double rlon = RadiansToDegrees(lon);
            const double cosl = cos(l);
            for (unsigned r = 0; r < numy; ++r)
            {
                const double lat = atan(cosl * tany[r]);
                x[pixel] = rlon;
                y[pixel] = RadiansToDegrees(lat);
                pixel++;
            }
        }
    }
    else
    {
        // The pole faces are the same, except for a change of sign in
        // the latitude and longitude calculations.
        const double sgn = face == 4 ? -1.0 : 1.0;
        for (unsigned c = 0; c < numx; ++c, ++fc)
        {
            const double l = (in_xmin + fc * dx) * osg::PI_4;
            const double tx = tan(l);
            const double tx2 = tx * tx;
            for (unsigned r = 0; r < numy; ++r)
            {
                const double ty = tany[r];
                const double lon = atan2(tx, sgn * ty);
                const double lat = (atan(sqrt(tx2 + ty * ty)) - osg::PI_2)
                    * sgn;
                x[pixel] = RadiansToDegrees(lon);
                y[pixel] = RadiansToDegrees(lat);
                pixel++;
            }
        }
    }
    const int numPixels = numx * numy;
    // Fixups for boundary lieing on date line
    if (face == 2 && in_xmax == 0.0)
    {
        for (int pixel = numx - 1; pixel < numPixels; pixel += numx)
            x[pixel] = 180;
    }
    else if ((face == 4 && in_ymax > 0.0)
             || (face == 5 && in_ymax <= 0.0))
    {
        double val;
        int startPix = -1;
        if (in_xmin == 0.0)
        {
            val = 180.0;
            startPix = 0;
        }
        else if (in_xmax == 0.0)
        {
            val = -180.0;
            startPix = numx - 1;
        }
        if (startPix > 0)
            for (int pixel = startPix; pixel < numPixels; pixel += numx)
                x[pixel] = val;
    }
    // pole case
    if ((face == 4 || face == 5) && in_ymax == 0.0)
    {
        if (in_xmax == 0.0)
            x[numPixels - 1] = -90.0;
        else if (in_xmin == 0.0)
            x[numx * (numy - 1)] = 90;
    }
    return true;
}

Here is the call graph for this function:

bool seamless::EulerSpatialReference::transformPoints ( const SpatialReference to_srs,
double *  x,
double *  y,
unsigned int  numPoints,
void *  context = 0L,
bool  ignore_errors = false 
) const [virtual]

Definition at line 702 of file Euler.cpp.

{
        if ( !_initialized )
            const_cast<EulerSpatialReference*>(this)->init();
        if (!to_srs->isEquivalentTo(getGeographicSRS()))
            return SpatialReference::transformPoints(to_srs, x, y, numPoints,
                                                     context, ignore_errors);
        bool success = true;
        for (unsigned int i = 0; i < numPoints; ++i)
        {
            bool result
                = EulerSpatialReference::preTransform(x[i], y[i], context);
            success = success && result;
        }
        return success;
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class CacheInitializer [friend]

Definition at line 212 of file Euler.


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