osgEarth 2.1.1
|
Public Member Functions | |
EulerSpatialReference (void *handle) | |
virtual osgEarth::GeoLocator * | createLocator (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 |
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.
seamless::EulerSpatialReference::EulerSpatialReference | ( | void * | handle | ) |
Definition at line 588 of file Euler.cpp.
: SpatialReference(handle, "OSGEARTH", "euler-cube", "Euler Cube") { //nop }
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.
xmin,ymin,xmax,ymax | Extents of the tile for which to create a locator. These should be in degrees for a geographic/geocentric scene. |
plate_carre | Set 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; }
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; }
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; }
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; } }
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; }
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; }
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; }
friend class CacheInitializer [friend] |