osgEarth 2.1.1
Functions

seamless::euler Namespace Reference

Functions

bool latLonToFaceCoords (double lat_deg, double lon_deg, double &out_x, double &out_y, int &out_face, int faceHint=-1)
bool faceCoordsToLatLon (double x, double y, int face, double &out_lat_deg, double &out_lon_deg)
bool cubeToFace (double &in_out_x, double &in_out_y, int &out_face)
bool cubeToFace (double &in_out_xmin, double &in_out_ymin, double &in_out_xmax, double &in_out_ymax, int &out_face)
bool faceToCube (double &in_out_x, double &in_out_y, int face)
osg::Vec3d face2dc (int face, const osg::Vec2d &faceCoord)
double arcLength (const osg::Vec2d &coord1, const osg::Vec2d &coord2, int face)
double distanceToSegment (const osg::Vec3d &p, const osg::Vec2d &coord1, const osg::Vec2d &coord2, int face)
double distanceToSegment (const osg::Vec3d &p, const osg::Vec3d &coord1, const osg::Vec3d &coord2)
bool lineLineIntersect (const Vec3d &p1, const Vec3d &p2, const Vec3d &p3, const Vec3d &p4, Vec3d &pa, Vec3d &pb, double &mua, double &mub)
Vec3d latLon2xyz (double lat_deg, double lon_deg)
int getFace (const Vec3d &vec)
Vec3d xyz2qrs (const Vec3d &xyz, int face)
Vec3d face2qrs (const Vec2d &face)
Vec3d qrs2xyz (const Vec3d &local, int face)
Vec3d face2dc (int faceNum, const Vec2d &faceCoord)
double arcLength (const Vec2d &coord1, const Vec2d &coord2, int face)
static osg::Vec3d closestPointOnLine (const osg::Vec3d &p1, const osg::Vec3d &p2, const osg::Vec3d &p3)
double distanceToLine (const Vec3d &p1, const Vec3d &p2, const Vec3d &p3)
double distanceToSegment (const Vec3d &p, const Vec3d &geo1, const Vec3d &geo2, const Vec3d &norm)
Vec3d getNormalToSegment (const Vec2d &coord1, const Vec2d &coord2, int face)
double distanceToSegment (const Vec3d &p, const Vec2d &coord1, const Vec2d &coord2, int face)

Detailed Description

The Euler cube

The faces of a cube are projected onto the spherical globe. Within a cube face, the coordinates are specified as as angles from the fixed axes parallel to the cube face. For example, the x coordinate of equatorial faces is equivalent to longitude. The y coordinate is not latitude, because it is not measured in the longitudinal plane. The major effect of this is that the grid lines on the cube faces are great circles.

The cube is layed out like a flattened cut-out. the x,y coordinates range from (0,0) to (4, 3). In the equatorial region, x is 0-4 and y is 1-2. North Pole is (0, 2) ->(1,3); South Pole is (0,0)->(1,1).

Face 0 is centered on lat lon (0, 0). Faces 1-3 are the equatorial faces to the East. 4 is the North Pole, 5 is the South.

Within each face, the conversion formulas assume that coordinate values range from -1 to 1.


Function Documentation

double seamless::euler::arcLength ( const osg::Vec2d &  coord1,
const osg::Vec2d &  coord2,
int  face 
)

Length of great circle arc between face coordinates. This will be the length of a grid edge if the points share a coordinate.

Here is the caller graph for this function:

double seamless::euler::arcLength ( const Vec2d &  coord1,
const Vec2d &  coord2,
int  face 
)

Definition at line 336 of file Euler.cpp.

{
    if (coord1.x() != coord2.x() && coord1.y() != coord2.y())
    {
        Vec3d geo1 = face2dc(face, coord1);
        Vec3d geo2 = face2dc(face, coord2);
        Vec3d norm = geo1 ^ geo2;
        return atan2(norm.length(), geo1 * geo2) * WGS_84_RADIUS_EQUATOR;
    }
    double x1, y1, x2, y2;
    if (coord1.x() == coord2.x())
    {
        x1 = coord1.x() * PI_4;  y1 = coord1.y() * PI_4;
        x2 = coord2.x() * PI_4;  y2 = coord2.y() * PI_4;
    }
    else
    {
        x1 = coord1.y() * PI_4;  y1 = coord1.x() * PI_4;
        x2 = coord2.y() * PI_4;  y2 = coord2.x() * PI_4;
    }
    double tanPhi1 = cos(x1) * tan(y1);
    double tanPhi2 = cos(x2) * tan(y2);
    // tan(phi2 - phi1) = (tan(phi2) - tan(hi1)) / (1 + tan(phi2) * tan(phi1))
    return fabs(atan2(tanPhi2 - tanPhi1, 1 + tanPhi2 * tanPhi1))
        * WGS_84_RADIUS_EQUATOR;

}

Here is the call graph for this function:

static osg::Vec3d seamless::euler::closestPointOnLine ( const osg::Vec3d &  p1,
const osg::Vec3d &  p2,
const osg::Vec3d &  p3 
) [static]

Definition at line 366 of file Euler.cpp.

{
    Vec3d vec = p2 - p1;
    double len2 = vec.length2();
    if (equivalent(len2, 0))
        return p1;
    double u = ((p3 - p1) * vec) / len2;
    if (u <= 0.0)
        return p1;
    else if (u >= 1.0)
        return p2;
    else
        return p1 + vec * u;
}

Here is the caller graph for this function:

bool seamless::euler::cubeToFace ( double &  in_out_xmin,
double &  in_out_ymin,
double &  in_out_xmax,
double &  in_out_ymax,
int &  out_face 
)

Converts cube coordinates (0,0=>4,3) to face coordinates (-1,-1=>1,1,F). This version takes an extent, which is better than the non-extent version since it can resolve face-border ambiguity.

Definition at line 266 of file Euler.cpp.

{
    double xmin, xmax, ymin, ymax;
    if (in_out_ymin > 1.0 - 1e-11 && in_out_ymax < 2.0 + 1e-11)
    {
        double faceMin = floor(in_out_xmin + 1e-11);
        double faceMax = floor(in_out_xmax - 1e-11);
        if (faceMin != faceMax)
        {
            OE_WARN << LC << "Min face <> Max face!\n";
            return false;
        }
        xmin = in_out_xmin - faceMin;
        xmax = in_out_xmax - faceMin;
        ymin = in_out_ymin - 1.0;
        ymax = in_out_ymax - 1.0;
        out_face = static_cast<int>(faceMin);
    }
    else if (in_out_ymin > 2.0 - 1e-11 && in_out_ymax > 2.0 + 1e-11)
    {
        out_face = 4;
        ymin = in_out_ymin - 2.0;
        ymax = in_out_ymax - 2.0;
        xmin = in_out_xmin;
        xmax = in_out_xmax;
    }
    else if (in_out_ymax < 1.0 + 1e-11)
    {
        out_face = 5;
        ymin = in_out_ymin;
        ymax = in_out_ymax;
        xmin = in_out_xmin;
        xmax = in_out_xmax;
    }
    else
    {
        OE_WARN << LC << "can't determine face for ("
                << in_out_xmin << ", " << in_out_ymin << "), ("
                << in_out_xmax << ", " << in_out_ymax << ")\n";
        return false;
    }
    in_out_xmin = xmin * 2.0 - 1.0;
    in_out_xmax = xmax * 2.0 - 1.0;
    in_out_ymin = ymin * 2.0 - 1.0;
    in_out_ymax = ymax * 2.0 - 1.0;
    return true;
}
bool seamless::euler::cubeToFace ( double &  in_out_x,
double &  in_out_y,
int &  out_face 
)

Converts cube coordinates (0,0=>4,3) to face coordinates (-1,-1=>1,1,F). WARNING. If the cube coordinate lies on a face boundary, this method will always return the lower-numbered face. The "extent" version of this method (below) is better b/c it's unambiguous.

Definition at line 227 of file Euler.cpp.

{
    double x, y;
    if (in_out_x > 1.0 + 1e-11)
    {
        double face = floor(in_out_x);
        x = in_out_x - face;
        if (x < 1e-11)
        {
            face += -1.0;
            x += 1.0;
        }
        y = in_out_y - 1.0;
        out_face = static_cast<int>(face);
    }
    else
    {
        if (in_out_y > 2.0 + 1e-11)
        {
            out_face = 4;
            y = in_out_y - 2.0;
        }
        else if (in_out_y < 1.0 + 1e-11)
        {
            out_face = 5;
            y = in_out_y;
        }
        else
        {
            out_face = 0;
            y = in_out_y - 1.0;
        }
        x = in_out_x;
    }
    in_out_x = x * 2.0 - 1.0;
    in_out_y = y * 2.0 - 1.0;
    return true;
}

Here is the caller graph for this function:

double seamless::euler::distanceToLine ( const Vec3d &  p1,
const Vec3d &  p2,
const Vec3d &  p3 
)

Definition at line 383 of file Euler.cpp.

{
    Vec3d pt = closestPointOnLine(p1, p2, p3);
    return (p3 - pt).length();
}

Here is the call graph for this function:

double seamless::euler::distanceToSegment ( const osg::Vec3d &  p,
const osg::Vec2d &  coord1,
const osg::Vec2d &  coord2,
int  face 
)

Distance between a point and an arc on a face.

Parameters:
pthe point, for example the eyepoint.
coord1beginning of segment in face coordinates
coord2end of segment in face coordinates
facecube face. coord1 and coord2 lie on the same face.
Returns:
distance
double seamless::euler::distanceToSegment ( const osg::Vec3d &  p,
const osg::Vec3d &  coord1,
const osg::Vec3d &  coord2 
)

Distance between a point and an arc on the spherical earth.

Parameters:
pthe point, for example the eyepoint.
coord1beginning of the arc as a direction cosine.
coord2end of the arc as a direction cosine.
Returns:
distance
double seamless::euler::distanceToSegment ( const Vec3d &  p,
const Vec3d &  geo1,
const Vec3d &  geo2,
const Vec3d &  norm 
)

Definition at line 389 of file Euler.cpp.

{
    // Find the distance to the closet point on the circle that
    // contains the segment. If that point lies on the segment, that's
    // the shortest distance; otherwise, the distance to one of the
    // end points is the shortest.

    // Project p into plane of circle
    Vec3d q = p - norm * (norm * p);
    // If q = (0, 0, 0) -- the center of the circle -- then all points
    // on the circle are equidistant.
    // qnorm will be on unit circle
    const double r = WGS_84_RADIUS_EQUATOR;
    if (equivalent(q.length2(), 0))
    {
        return sqrt(r * r + p.length2());
    }
    Vec3d qnorm = q / q.length();

    // Vec3d x = q * r / q.length();
    const Vec3d zero;
    Vec3d end1, end2;
    double mua, mub;
    if (lineLineIntersect(zero, qnorm, geo1, geo2, end1, end2, mua, mub)
        && mub >= 0.0 && mub <= 1.0)
    {
        return (p - qnorm * r).length();
    }
    else
    {
        return minimum((p - geo1 * r).length(), (p - geo2 * r).length());
    }
}

Here is the call graph for this function:

double seamless::euler::distanceToSegment ( const Vec3d &  p,
const Vec2d &  coord1,
const Vec2d &  coord2,
int  face 
)

Definition at line 445 of file Euler.cpp.

{
    Vec3d norm = getNormalToSegment(coord1, coord2, face);
    Vec3d geo1 = face2dc(face, coord1);
    Vec3d geo2 = face2dc(face, coord2);
    return distanceToSegment(p, geo1, geo2, norm);
}

Here is the call graph for this function:

Vec3d seamless::euler::face2dc ( int  faceNum,
const Vec2d &  faceCoord 
)

Definition at line 190 of file Euler.cpp.

{
    Vec3d local = face2qrs(faceCoord);
    return qrs2xyz(local, faceNum);
}

Here is the call graph for this function:

osg::Vec3d seamless::euler::face2dc ( int  face,
const osg::Vec2d &  faceCoord 
)

Calculate the direction cosine representation (unit vector from the origin) of a face coordinate's geographic location.

Here is the caller graph for this function:

Vec3d seamless::euler::face2qrs ( const Vec2d &  face)

Definition at line 145 of file Euler.cpp.

{
    double xang = face[0] * osg::PI_4;
    double yang = face[1] * osg::PI_4;
    double sx = sin(xang), cx = cos(xang);
    double ty = tan(yang);
    // phi is a latitude measure, in the longitudinal plane
    double tanPhi = cx * ty;
    double radical = sqrt(1 + tanPhi * tanPhi);
    double c = 1.0 / radical;
    Vec3d result;
    double b = tanPhi * c;      // b gets the right sign
    result.x() = c * sx;
    result.y() = b;
    result.z() = c * cx;
    return result;
}

Here is the caller graph for this function:

bool seamless::euler::faceCoordsToLatLon ( double  x,
double  y,
int  face,
double &  out_lat_deg,
double &  out_lon_deg 
)

Converts face coordinates into lat/long.

Definition at line 196 of file Euler.cpp.

{
    double lat, lon;
    const double l = x * osg::PI_4;
    const double ty = tan(y * osg::PI_4);
    if (face < 4)
    {
        lon = face * osg::PI_2 + l;
        lon = fmod(lon + osg::PI, 2.0 * osg::PI) - osg::PI;
        lat = atan(cos(l) * ty);
    }
    else
    {
        const double tx = tan(x * osg::PI_4);
        lat = osg::PI_2 - atan(sqrt(tx * tx + ty * ty));
        if (face == 5)
        {
            lon = atan2(tx, ty);
            lat = -lat;
        }
        else
        {
            lon = atan2(tx, -ty);
        }
    }
    out_lon_deg = RadiansToDegrees(lon);
    out_lat_deg = RadiansToDegrees(lat);
    return true;
}

Here is the caller graph for this function:

bool seamless::euler::faceToCube ( double &  in_out_x,
double &  in_out_y,
int  face 
)

Converts face coordinates (-1,-1=>1,1 +F) to cube coordinates (0,0=>4,3).

Definition at line 316 of file Euler.cpp.

{
    double x = (in_out_x + 1.0) * .5;
    double y = (in_out_y + 1.0) * .5;
    if (face < 4)
    {
        in_out_x = x + face;
        in_out_y = y + 1.0;
    }
    else
    {
        in_out_x = x;
        if (face == 4)
            in_out_y = y + 2.0;
        else
            in_out_y = y;
    }
    return true;
}

Here is the caller graph for this function:

int seamless::euler::getFace ( const Vec3d &  vec) [inline]

Definition at line 68 of file Euler.cpp.

{
    double absx = fabs(vec.x());
    double absy = fabs(vec.y());
    double absz = fabs(vec.z());
    // pole faces
    if (absz > (absx + 1e-11) && absz > (absy + 1e-11))
    {
        if (vec.z() > 0.0)
            return 4;
        else
            return 5;
    }
    // One of the X faces, unless on a border
    else if (absx > absy || equivalent(absx, absy, 1e-11))
    {
        if (vec.x() > 0.0)
            return 0;
        else if (equivalent(vec.x(), -vec.y(), 1e-11))
            return 1;           // Boundary between 1 and 2
        else
            return 2;
    }
    // One of the Y faces
    else
    {
        if (vec.y() > 0.0)
            return 1;
        else
            return 3;
    }
}

Here is the caller graph for this function:

Vec3d seamless::euler::getNormalToSegment ( const Vec2d &  coord1,
const Vec2d &  coord2,
int  face 
)

Definition at line 427 of file Euler.cpp.

{
    if (coord1.x() == coord2.x())
    {
        double xang = coord1.x() * PI_4;
        double sx = sin(xang), cx = cos(xang);
        Vec3d qrsNormal(cx, 0.0, -sx);
        return qrs2xyz(qrsNormal, face);
    }
    else
    {
        double yang = coord1.y() * PI_4;
        double sy = sin(yang), cy = cos(yang);
        Vec3d qrsNormal(0.0, cy, -sy);
        return qrs2xyz(qrsNormal, face);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Vec3d seamless::euler::latLon2xyz ( double  lat_deg,
double  lon_deg 
) [inline]

Definition at line 56 of file Euler.cpp.

{
    Vec3d result;
    result.z() = sin(DegreesToRadians(lat_deg));
    double hyp = sqrt(1 - result.z() * result.z());
    double long_rad = DegreesToRadians(lon_deg);
    result.x() = hyp * cos(long_rad);
    result.y() = hyp * sin(long_rad);
    return result;
}

Here is the caller graph for this function:

bool seamless::euler::latLonToFaceCoords ( double  lat_deg,
double  lon_deg,
double &  out_x,
double &  out_y,
int &  out_face,
int  faceHint = -1 
)

Definition at line 127 of file Euler.cpp.

{
    if (lat_deg > 90.0 || lat_deg < -90.0
        || lon_deg < -180.0 || lon_deg > 180.0)
        return false;
    Vec3d xyz = latLon2xyz(lat_deg, lon_deg);
    out_face = faceHint >= 0 ? faceHint : getFace(xyz);
    Vec3d qrs = xyz2qrs(xyz, out_face);

    double xang = atan2(qrs[0], qrs[2]);
    double yang = atan2(qrs[1], qrs[2]);
    out_x = xang / osg::PI_4;
    out_y = yang / osg::PI_4;
    return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool seamless::euler::lineLineIntersect ( const Vec3d &  p1,
const Vec3d &  p2,
const Vec3d &  p3,
const Vec3d &  p4,
Vec3d &  pa,
Vec3d &  pb,
double &  mua,
double &  mub 
)

Definition at line 463 of file Euler.cpp.

{
    Vec3d p13, p43, p21;
    double d1343, d4321, d1321, d4343, d2121;
    double numer, denom;

    p13 = p1 - p3;
    p43 = p4 - p3;
    if (equivalent(p43.length2(), 0.0, 1e-11))
        return false;
    p21 = p2 - p1;
    if (equivalent(p21.length2(), 0.0, 1e-11))
        return false;

    d1343 = p13.x() * p43.x() + p13.y() * p43.y() + p13.z() * p43.z();
    d4321 = p43.x() * p21.x() + p43.y() * p21.y() + p43.z() * p21.z();
    d1321 = p13.x() * p21.x() + p13.y() * p21.y() + p13.z() * p21.z();
    d4343 = p43.x() * p43.x() + p43.y() * p43.y() + p43.z() * p43.z();
    d2121 = p21.x() * p21.x() + p21.y() * p21.y() + p21.z() * p21.z();

    denom = d2121 * d4343 - d4321 * d4321;
    if (equivalent(denom, 0.0, 1e-11))
        return false;
    numer = d1343 * d4321 - d1321 * d4343;

    mua = numer / denom;
    mub = (d1343 + d4321 * (mua)) / d4343;

    pa = p1 + p21 * mua;
    pb = p3 + p43 * mub;

    return true;
}

Here is the caller graph for this function:

Vec3d seamless::euler::qrs2xyz ( const Vec3d &  local,
int  face 
)

Definition at line 163 of file Euler.cpp.

{
    switch (face)
    {
    case 0:
        return Vec3d(local.z(), local.x(), local.y());
        break;
    case 1:
        return Vec3d(-local.x(), local.z(), local.y());
        break;
    case 2:
        return Vec3d(-local.z(), -local.x(), local.y());
    case 3:
        return Vec3d(local.x(), -local.z(), local.y());
    case 4:
        return Vec3d(-local.y(),local.x(), local.z());
    case 5:
        return Vec3d(local.y(), local.x(), -local.z());
    default:
        return Vec3d(0,0,0);
    }
}

Here is the caller graph for this function:

Vec3d seamless::euler::xyz2qrs ( const Vec3d &  xyz,
int  face 
)

Definition at line 106 of file Euler.cpp.

{
    switch (face)
    {
    case 0:
        return Vec3d(xyz.y(), xyz.z(), xyz.x());
    case 1:
        return Vec3d(-xyz.x(), xyz.z(), xyz.y());
    case 2:
        return Vec3d(-xyz.y(), xyz.z(), -xyz.x());
    case 3:
        return Vec3d(xyz.x(), xyz.z(), -xyz.y());
    case 4:
        return Vec3d(xyz.y(), -xyz.x(), xyz.z());
    case 5:
        return Vec3d(xyz.y(), xyz.x(), -xyz.z());
    default:
        return Vec3d(0, 0, 0);
    }
}

Here is the caller graph for this function:

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines