GeoTessCPP  2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines
include/GeoTessUtils.h
Go to the documentation of this file.
00001 //- ****************************************************************************
00002 //- 
00003 //- Copyright 2009 Sandia Corporation. Under the terms of Contract
00004 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00005 //- retains certain rights in this software.
00006 //- 
00007 //- BSD Open Source License.
00008 //- All rights reserved.
00009 //- 
00010 //- Redistribution and use in source and binary forms, with or without
00011 //- modification, are permitted provided that the following conditions are met:
00012 //- 
00013 //-    * Redistributions of source code must retain the above copyright notice,
00014 //-      this list of conditions and the following disclaimer.
00015 //-    * Redistributions in binary form must reproduce the above copyright
00016 //-      notice, this list of conditions and the following disclaimer in the
00017 //-      documentation and/or other materials provided with the distribution.
00018 //-    * Neither the name of Sandia National Laboratories nor the names of its
00019 //-      contributors may be used to endorse or promote products derived from
00020 //-      this software without specific prior written permission.
00021 //- 
00022 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00023 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00026 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00027 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00028 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00029 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00030 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 //- POSSIBILITY OF SUCH DAMAGE.
00033 //-
00034 //- ****************************************************************************
00035 
00036 #ifndef GEOTESSUTILS_OBJECT_H
00037 #define GEOTESSUTILS_OBJECT_H
00038 
00039 // **** _SYSTEM INCLUDES_ ******************************************************
00040 
00041 #include <iostream>
00042 #include <fstream>
00043 #include <vector>
00044 #include <map>
00045 #include <string>
00046 
00047 // use standard library objects
00048 using namespace std;
00049 
00050 // **** _LOCAL INCLUDES_ *******************************************************
00051 
00052 #include "CPPUtils.h"
00053 
00054 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
00055 
00056 namespace geotess
00057 {
00058 
00059 // **** _FORWARD REFERENCES_ ***************************************************
00060 
00061 // **** _CLASS DEFINITION_ *****************************************************
00062 
00069 class GEOTESS_EXP_IMP GeoTessUtils
00070 {
00071 private:
00072 
00073         /*
00074          * Private copy constructor. Not used.
00075          */
00076         GeoTessUtils(const GeoTessUtils& gtu)
00077         {
00078         }
00079         ;
00080 
00081         /*
00082          * Private assignment operator. Not used.
00083          */
00084         GeoTessUtils& operator=(const GeoTessUtils& gtu)
00085         {
00086                 return *this;
00087         }
00088         ;
00089 
00090 public:
00091 
00102         static bool approximateLatitudes;
00103 
00107         GeoTessUtils()
00108         {
00109         }
00110 
00114         virtual ~GeoTessUtils()
00115         {
00116         }
00117 
00122         static string class_name()
00123         { return "GeoTessUtils"; }
00124 
00129         virtual int class_size() const
00130         { return (int) sizeof(GeoTessUtils); }
00131 
00136         static string getVersion() { return "2.0.4"; }
00137 
00145         static double dot(const double* const v0, const double* const v1)
00146         { return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2]; }
00147 
00157         static double scalarTripleProduct(const double* const v0,
00158                         const double* const v1, const double* const v2)
00159         {
00160                 return v0[0] * v1[1] * v2[2] + v1[0] * v2[1] * v0[2]
00161                                 + v2[0] * v0[1] * v1[2] - v2[0] * v1[1] * v0[2]
00162                                 - v0[0] * v2[1] * v1[2] - v1[0] * v0[1] * v2[2];
00163         }
00164 
00172         static double getGeoCentricLatitude(const double& lat);
00173 
00181         static double getGeoGraphicLatitude(const double& lat);
00182 
00187         static string getLatLonString(const double* const v);
00188 
00189 
00204         static double azimuthDegrees(const double* const v1, const double* const v2,
00205                         double errorValue);
00206 
00221         static double azimuth(const double* const v1, const double* const v2,
00222                         double errorValue);
00223 
00238 static void rotate(const double* const x, const double* const p, double a,
00239                         double* const z);
00240 
00263         static double** getGreatCircle(const double* const v0,
00264                         const double* const v1);
00265 
00288         static void getGreatCircle(const double* const v0, const double* const v1,
00289                         double** const gc);
00290 
00315         static double** getGreatCircle(const double* const v, double azimuth);
00316 
00341         static void getGreatCircle(const double* const v, double azimuth,
00342                         double** const gc);
00343 
00356         static int getGreatCirclePoints(double* ptA, double* ptB,
00357                         const double& delta, const bool& onCenters);
00358 
00372         static double getGreatCirclePoints(double* ptA, double* ptB,
00373                         const int& npoints, const bool& onCenters, double** points);
00374 
00391         static double getGreatCirclePoints(double* ptA, double* ptB,
00392                         const double& delta, const bool& onCenters, double** points,
00393                         int& npoints);
00394 
00401          static double length(const double* const u)
00402         {
00403                 double l = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
00404                 return l > 0 ? sqrt(l) : 0.;
00405         }
00406 
00419         static void getTransform(const double* const u, const double* const v,
00420                         double** const t);
00421 
00437         static void transform(const double* x,
00438                         double const* const * const t, double* const g)
00439         {
00440                 g[0] = x[0] * t[0][0] + x[1] * t[0][1] + x[2] * t[0][2];
00441                 g[1] = x[0] * t[1][0] + x[1] * t[1][1] + x[2] * t[1][2];
00442                 g[2] = x[0] * t[2][0] + x[1] * t[2][1] + x[2] * t[2][2];
00443         }
00444 
00450         static void readString(string& s, ifstream& ifs)
00451         {
00452                 int sze;
00453                 ifs >> sze;
00454                 char* c = new char[sze];
00455                 ifs.read(c, sze);
00456                 s = c;
00457                 delete[] c;
00458         }
00459 
00465         static void writeString(ofstream& ofs, const string& s)
00466         {
00467                 ofs << s.length();
00468                 ofs.write(s.c_str(), s.length());
00469         }
00470 
00478         static double angle(const double* const v0,
00479                         const double* const v1)
00480         {
00481                 double dot = v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
00482                 if (dot >= 1.0)
00483                         return 0.0;
00484                 if (dot <= -1.0)
00485                         return PI;
00486                 return acos(dot);
00487         }
00488 
00496         static double angleDegrees(const double* const v0,
00497                         const double* const v1)
00498         {
00499                 double dot = v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
00500                 if (dot >= 1.)
00501                         return 0.;
00502                 if (dot <= -1.)
00503                         return 180.;
00504                 return CPPUtils::toDegrees(acos(dot));
00505         }
00506 
00518         static double getDistance3D(const double* const v0, double r0,
00519                         const double* const v1, double r1)
00520         {
00521                 double v[3] = { v0[0] * r0 - v1[0] * r1, v0[1] * r0 - v1[1] * r1, v0[2] * r0
00522                                 - v1[2] * r1 };
00523                 return length(v);
00524         }
00525 
00533         static double getEarthRadius(const double* const v)
00534         {
00535                 return EARTH_A / sqrt(1. + EARTH_E / (1 - EARTH_E) * v[2] * v[2]);
00536         }
00537 
00544         static double getLat(const double* const v)
00545         {
00546                 return getGeoGraphicLatitude(asin(v[2]));
00547         }
00548 
00555         static double getLon(const double* const v)
00556         {
00557                 return atan2(v[1], v[0]);
00558         }
00559 
00566         static double getLatDegrees(const double* const v)
00567         {
00568                 // the constant 0.9933 is (1-e*e) where e is the eccentricity of the
00569                 // earth
00570                 // as defined by the GRS80 ellipsoid.
00571                 return CPPUtils::toDegrees(atan(tan(asin(v[2])) / 0.9933056199770992));
00572         }
00573 
00580         static double getLonDegrees(const double* const v)
00581         {
00582                 return CPPUtils::toDegrees(atan2(v[1], v[0]));
00583         }
00584 
00596         static double* getVectorDegrees(const double& lat,
00597                         const double& lon)
00598         {
00599                 return getVector(CPPUtils::toRadians(lat), CPPUtils::toRadians(lon));
00600         }
00601 
00612         static double* getVectorDegrees(const double& lat,
00613                         const double& lon, double* v)
00614         {
00615                 return getVector(CPPUtils::toRadians(lat), CPPUtils::toRadians(lon), v);
00616         }
00617 
00629         static double* getVector(const double& lat, const double& lon)
00630         {
00631                 double* v = new double[3];
00632                 getVector(lat, lon, v);
00633                 return v;
00634         }
00635 
00646         static double* getVector(const double& lat, const double& lon, double* v)
00647         {
00648                 // convert lat from geographic to geocentric latitude.
00649                 double temp = getGeoCentricLatitude(lat);
00650 
00651                 // z component of v is sin of geocentric latitude.
00652                 v[2] = sin(temp);
00653 
00654                 // set lat = to cos of geocentric latitude
00655                 temp = cos(temp);
00656 
00657                 // compute x and y components of v
00658                 v[0] = temp * cos(lon);
00659                 v[1] = temp * sin(lon);
00660 
00661                 return v;
00662         }
00663 
00671         static double normalize(double* const u)
00672         {
00673                 double len = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
00674                 if (len > 0.)
00675                 {
00676                         len = sqrt(len);
00677                         u[0] /= len;
00678                         u[1] /= len;
00679                         u[2] /= len;
00680                 }
00681                 else
00682                 {
00683                         len = u[0] = u[1] = u[2] = 0.0;
00684                 }
00685                 return len;
00686         }
00687 
00698         static void cross(const double* const v1, const double* const v2,
00699                         double* const rslt)
00700         {
00701                 rslt[0] = v1[1] * v2[2] - v1[2] * v2[1];
00702                 rslt[1] = v1[2] * v2[0] - v1[0] * v2[2];
00703                 rslt[2] = v1[0] * v2[1] - v1[1] * v2[0];
00704         }
00705 
00716         static double* crossNormal(const double* const u,
00717                         const double* const v)
00718         {
00719                 double* w = new double[3];
00720                 w[0] = u[1] * v[2] - u[2] * v[1];
00721                 w[1] = u[2] * v[0] - u[0] * v[2];
00722                 w[2] = u[0] * v[1] - u[1] * v[0];
00723                 normalize(w);
00724                 return w;
00725         }
00726 
00739         static double crossNormal(const double* const u,
00740                         const double* const v, double* const w)
00741         {
00742                 w[0] = u[1] * v[2] - u[2] * v[1];
00743                 w[1] = u[2] * v[0] - u[0] * v[2];
00744                 w[2] = u[0] * v[1] - u[1] * v[0];
00745                 return normalize(w);
00746         }
00747 
00760         static double crossNorth(const double* const u, double* const w)
00761         {
00762                 double len = u[0] * u[0] + u[1] * u[1];
00763                 if (len <= 0.)
00764                 {
00765                         len = w[0] = w[1] = w[2] = 0.;
00766                 }
00767                 else
00768                 {
00769                         len = sqrt(len);
00770                         w[0] = u[1] / len;
00771                         w[1] = -u[0] / len;
00772                         w[2] = 0.;
00773                 }
00774                 return len;
00775         }
00776 
00792         static bool vectorTripleProduct(const double* const v0,
00793                         const double* const v1, const double* const v2, double* const rslt)
00794         {
00795                 // set q = v0 cross v1
00796                 double q0 = v0[1] * v1[2] - v0[2] * v1[1];
00797                 double q1 = v0[2] * v1[0] - v0[0] * v1[2];
00798                 double q2 = v0[0] * v1[1] - v0[1] * v1[0];
00799 
00800                 // set w = q cross v2
00801                 double w0 = q1 * v2[2] - q2 * v2[1];
00802                 double w1 = q2 * v2[0] - q0 * v2[2];
00803                 double w2 = q0 * v2[1] - q1 * v2[0];
00804 
00805                 // set rslt = w
00806                 rslt[0] = w0;
00807                 rslt[1] = w1;
00808                 rslt[2] = w2;
00809 
00810                 // normalize rslt to unit length. if the length
00811                 // of v1 or v2 is zero or they are nearly parallel then
00812                 // rslt will = {0,0,0} and the function will return false;
00813                 return normalize(rslt) != 0.;
00814         }
00815 
00826         static bool vectorTripleProductNorthPole(const double* const u,
00827                         double* const w)
00828         {
00829                 w[0] = -u[0] * u[2];
00830                 w[1] = -u[1] * u[2];
00831                 w[2] = u[1] * u[1] + u[0] * u[0];
00832                 return normalize(w) != 0.;
00833         }
00834 
00847         static bool circumCenter(const double* const v0,
00848                         const double* const v1, const double* const v2, double* const vs)
00849         {
00850                 vs[0] = v0[1] * (v2[2] - v1[2]) + v2[1] * (v1[2] - v0[2])
00851                                 + v1[1] * (v0[2] - v2[2]);
00852                 vs[1] = v0[2] * (v2[0] - v1[0]) + v2[2] * (v1[0] - v0[0])
00853                                 + v1[2] * (v0[0] - v2[0]);
00854                 vs[2] = v0[0] * (v2[1] - v1[1]) + v2[0] * (v1[1] - v0[1])
00855                                 + v1[0] * (v0[1] - v2[1]);
00856                 return normalize(vs) > 0.;
00857         }
00858 
00870         static double* circumCenter(const double* const v0,
00871                         const double* const v1, const double* const v2)
00872         {
00873                 double* vs = new double[3];
00874                 vs[0] = v0[1] * (v2[2] - v1[2]) + v2[1] * (v1[2] - v0[2])
00875                                 + v1[1] * (v0[2] - v2[2]);
00876                 vs[1] = v0[2] * (v2[0] - v1[0]) + v2[2] * (v1[0] - v0[0])
00877                                 + v1[2] * (v0[0] - v2[0]);
00878                 vs[2] = v0[0] * (v2[1] - v1[1]) + v2[0] * (v1[1] - v0[1])
00879                                 + v1[0] * (v0[1] - v2[1]);
00880                 normalize(vs);
00881                 return vs;
00882         }
00883 
00896         static bool circumCenter(double const* const * const t,
00897                         double* const vs)
00898         {
00899                 return circumCenter(t[0], t[1], t[2], vs);
00900         }
00901 
00917         static bool moveDistAz(const double* const w, double distance,
00918                         double azimuth, double* const u)
00919         {
00920                 double n[3] = { 0.0, 0.0, 0.0 };
00921                 if (moveNorth(w, distance, n))
00922                 {
00923                         rotate(n, w, azimuth, u);
00924                         return true;
00925                 }
00926                 u[0] = w[0];
00927                 u[1] = w[1];
00928                 u[2] = w[2];
00929                 return false;
00930         }
00931 
00945         static void move(const double* const w, const double* const vtp,
00946                         double a, double* const u)
00947         {
00948                 double cosa = cos(a);
00949                 double sina = sin(a);
00950                 u[0] = cosa * w[0] + sina * vtp[0];
00951                 u[1] = cosa * w[1] + sina * vtp[1];
00952                 u[2] = cosa * w[2] + sina * vtp[2];
00953         }
00954 
00969         static bool moveNorth(const double* const x, double distance,
00970                         double* const z)
00971         {
00972                 double vtp[3] = { 0.0, 0.0, 0.0 };
00973                 if (vectorTripleProductNorthPole(x, vtp))
00974                 {
00975                         move(x, vtp, distance, z);
00976                         return true;
00977                 }
00978 
00979                 z[0] = x[0];
00980                 z[1] = x[1];
00981                 z[2] = x[2];
00982                 return false;
00983         }
00984 
00992         static bool isPole(const double* const u)
00993         {
00994                 return (u[0] * u[0] + u[1] * u[1]) < 1.0e-15;
00995         }
00996 
01006         static bool parallel(const double* const u, const double* const v)
01007         {
01008                 return 1.0 - abs(u[0] * v[0] + u[1] * v[1] + u[2] * v[2]) < 2.0e-15;
01009         }
01010 
01027         static double* getGreatCirclePoint(
01028                         double const* const * const greatCircle, double distance)
01029         {
01030                 double* v = new double[3];
01031                 getGreatCirclePoint(greatCircle, distance, v);
01032                 return v;
01033         }
01034 
01052         static void getGreatCirclePoint(
01053                         double const* const * const greatCircle, double distance,
01054                         double* const v)
01055         {
01056                 double cosa = cos(distance);
01057                 double sina = sin(distance);
01058                 v[0] = cosa * greatCircle[0][0] + sina * greatCircle[1][0];
01059                 v[1] = cosa * greatCircle[0][1] + sina * greatCircle[1][1];
01060                 v[2] = cosa * greatCircle[0][2] + sina * greatCircle[1][2];
01061         }
01062 
01069         static double getTriangleArea(const double* const v0,
01070                         const double* const v1, const double* const v2)
01071         {
01072                 double v10[3] = { v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2] };
01073                 double v20[3] = { v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2] };
01074                 double u[3] = { v10[1] * v20[2] - v10[2] * v20[1], v10[2] * v20[0]
01075                                 - v10[0] * v20[2], v10[0] * v20[1] - v10[1] * v20[0] };
01076                 return sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]) / 2.;
01077         }
01078 
01086         static double* center(double const * const * const v, int n)
01087         {
01088                 double* x = new double[3];
01089                 x[0] = x[1] = x[2] = 0.0;
01090                 if (n == 0)
01091                         return x;
01092 
01093                 for (int i = 0; i < n; ++i)
01094                 {
01095                         x[0] += v[i][0];
01096                         x[1] += v[i][1];
01097                         x[2] += v[i][2];
01098                 }
01099                 normalize(x);
01100                 return x;
01101         }
01102 
01110         static void center(vector<double*> v, double* x)
01111         {
01112                 x[0] = x[1] = x[2] = 0.0;
01113 
01114                 for (size_t i = 0; i < v.size(); ++i)
01115                 {
01116                         x[0] += v[i][0];
01117                         x[1] += v[i][1];
01118                         x[2] += v[i][2];
01119                 }
01120                 normalize(x);
01121         }
01122 };
01123 // end class GeoTessUtils
01124 
01125 // **** _INLINE FUNCTION IMPLEMENTATIONS_ **************************************
01126 
01127 
01132 static const double geocentric[] = { 0.0, 0.003047423602671013,
01133                 0.006094847970838097, 0.009142273869969656, 0.012189702065478763,
01134                 0.015237133322695492, 0.018284568406839258, 0.021332008082991166,
01135                 0.024379453116066336, 0.027426904270786288, 0.030474362311651265,
01136                 0.03352182800291262, 0.03656930210854519, 0.03961678539221966,
01137                 0.04266427861727495, 0.04571178254669065, 0.04875929794305942,
01138                 0.05180682556855937, 0.05485436618492655, 0.057901920553427404,
01139                 0.06094948943483121, 0.06399707358938257, 0.06704467377677387,
01140                 0.0700922907561179, 0.07313992528592034, 0.07618757812405218,
01141                 0.07923525002772251, 0.08228294175345101, 0.08533065405704056,
01142                 0.08837838769354987, 0.0914261434172662, 0.094473921981678,
01143                 0.09752172413944764, 0.10056955064238413, 0.1036174022414159,
01144                 0.10666527968656359, 0.1097131837269129, 0.11276111511058741,
01145                 0.11580907458472142, 0.11885706289543299, 0.12190508078779674,
01146                 0.1249531290058169, 0.1280012082924004, 0.13104931938932968,
01147                 0.13409746303723613, 0.13714563997557289, 0.140193850942588,
01148                 0.14324209667529803, 0.14629037790946073, 0.14933869537954875,
01149                 0.15238704981872267, 0.15543544195880452, 0.1584838725302512,
01150                 0.1615323422621277, 0.16458085188208085, 0.16762940211631275,
01151                 0.17067799368955427, 0.17372662732503877, 0.17677530374447592,
01152                 0.17982402366802488, 0.1828727878142688, 0.18592159690018817,
01153                 0.18897045164113468, 0.19201935275080542, 0.19506830094121663,
01154                 0.19811729692267788, 0.201166341403766, 0.20421543509129933,
01155                 0.20726457869031198, 0.21031377290402786, 0.21336301843383518,
01156                 0.21641231597926083, 0.21946166623794464, 0.22251106990561403,
01157                 0.22556052767605864, 0.2286100402411045, 0.2316596082905894,
01158                 0.23470923251233702, 0.23775891359213203, 0.24080865221369493,
01159                 0.2438584490586569, 0.24690830480653495, 0.2499582201347069,
01160                 0.25300819571838656, 0.25605823223059876, 0.25910833034215514,
01161                 0.2621584907216286, 0.26520871403532986, 0.2682590009472821,
01162                 0.27130935211919693, 0.2743597682104497, 0.27741024987805574,
01163                 0.2804607977766458, 0.28351141255844176, 0.28656209487323325,
01164                 0.2896128453683528, 0.29266366468865285, 0.29571455347648123,
01165                 0.29876551237165794, 0.3018165420114511, 0.3048676430305536,
01166                 0.30791881606105975, 0.3109700617324416, 0.314021380671526,
01167                 0.317072773502471, 0.32012424084674285, 0.3231757833230931,
01168                 0.3262274015475356, 0.3292790961333235, 0.3323308676909266,
01169                 0.3353827168280087, 0.3384346441494046, 0.34148665025709846,
01170                 0.34453873575020055, 0.34759090122492536, 0.3506431472745693,
01171                 0.35369547448948857, 0.35674788345707703, 0.3598003747617447,
01172                 0.3628529489848955, 0.36590560670490546, 0.36895834849710163,
01173                 0.3720111749337399, 0.3750640865839841, 0.3781170840138844,
01174                 0.3811701677863562, 0.384223338461159, 0.3872765965948754,
01175                 0.39032994274089, 0.393383377449369, 0.39643690126723913,
01176                 0.3994905147381674, 0.4025442184025402, 0.40559801279744334,
01177                 0.40865189845664174, 0.41170587591055896, 0.4147599456862576,
01178                 0.41781410830741905, 0.42086836429432384, 0.423922714163832,
01179                 0.4269771584293634, 0.43003169760087806, 0.43308633218485754,
01180                 0.4361410626842845, 0.43919588959862493, 0.4422508134238082,
01181                 0.44530583465220863, 0.44836095377262664, 0.4514161712702699,
01182                 0.4544714876267352, 0.45752690331998996, 0.4605824188243536,
01183                 0.46363803461047975, 0.4666937511453385, 0.4697495688921976,
01184                 0.4728054883106056, 0.47586150985637393, 0.4789176339815591,
01185                 0.4819738611344456, 0.48503019175952866, 0.4880866262974967,
01186                 0.49114316518521534, 0.49419980885570924, 0.49725655773814614,
01187                 0.5003134122578201, 0.5033703728361352, 0.5064274398905888,
01188                 0.5094846138347555, 0.5125418950782715, 0.5155992840268179,
01189                 0.5186567810821053, 0.5217143866418585, 0.5247721010998003,
01190                 0.5278299248456365, 0.5308878582650406, 0.5339459017396384,
01191                 0.5370040556469939, 0.5400623203605933, 0.5431206962498311,
01192                 0.5461791836799952, 0.5492377830122528, 0.5522964946036362,
01193                 0.5553553188070278, 0.5584142559711474, 0.5614733064405376,
01194                 0.5645324705555501, 0.5675917486523328, 0.5706511410628154,
01195                 0.5737106481146972, 0.5767702701314332, 0.5798300074322218,
01196                 0.5828898603319916, 0.5859498291413889, 0.5890099141667653,
01197                 0.5920701157101648, 0.5951304340693124, 0.598190869537602,
01198                 0.6012514224040836, 0.6043120929534528, 0.6073728814660381,
01199                 0.6104337882177904, 0.6134948134802714, 0.6165559575206421,
01200                 0.6196172206016525, 0.6226786029816302, 0.6257401049144706,
01201                 0.6288017266496251, 0.6318634684320923, 0.6349253305024066,
01202                 0.6379873130966289, 0.6410494164463364, 0.6441116407786132,
01203                 0.6471739863160405, 0.6502364532766877, 0.6532990418741025,
01204                 0.6563617523173022, 0.6594245848107654, 0.6624875395544221,
01205                 0.6655506167436465, 0.6686138165692472, 0.6716771392174603,
01206                 0.6747405848699405, 0.6778041537037534, 0.6808678458913681,
01207                 0.6839316616006491, 0.6869956009948498, 0.6900596642326039,
01208                 0.6931238514679199, 0.6961881628501729, 0.6992525985240989,
01209                 0.7023171586297877, 0.7053818433026762, 0.7084466526735433,
01210                 0.7115115868685029, 0.7145766460089984, 0.7176418302117967,
01211                 0.7207071395889835, 0.7237725742479568, 0.7268381342914229,
01212                 0.72990381981739, 0.7329696309191651, 0.7360355676853481,
01213                 0.7391016301998271, 0.7421678185417753, 0.7452341327856461,
01214                 0.7483005730011691, 0.7513671392533465, 0.7544338316024497,
01215                 0.7575006501040149, 0.7605675948088417, 0.7636346657629879,
01216                 0.7667018630077682, 0.7697691865797504, 0.7728366365107536,
01217                 0.7759042128278457, 0.7789719155533406, 0.7820397447047971,
01218                 0.7851077002950162, 0.7881757823320402, 0.7912439908191506,
01219                 0.794312325754867, 0.7973807871329465, 0.8004493749423818,
01220                 0.8035180891674011, 0.8065869297874673, 0.8096558967772779,
01221                 0.8127249901067641, 0.8157942097410916, 0.8188635556406603,
01222                 0.821933027761104, 0.8250026260532924, 0.8280723504633305,
01223                 0.83114220093256, 0.8342121773975598, 0.8372822797901482,
01224                 0.8403525080373838, 0.8434228620615665, 0.8464933417802403,
01225                 0.8495639471061945, 0.8526346779474664, 0.8557055342073429,
01226                 0.8587765157843639, 0.8618476225723242, 0.8649188544602767,
01227                 0.8679902113325356, 0.8710616930686791, 0.8741332995435535,
01228                 0.8772050306272762, 0.8802768861852399, 0.8833488660781164,
01229                 0.8864209701618606, 0.889493198287715, 0.8925655503022143,
01230                 0.8956380260471897, 0.8987106253597743, 0.9017833480724076,
01231                 0.9048561940128412, 0.9079291630041441, 0.9110022548647081,
01232                 0.9140754694082539, 0.9171488064438367, 0.9202222657758528,
01233                 0.9232958472040453, 0.9263695505235116, 0.929443375524709,
01234                 0.9325173219934624, 0.9355913897109707, 0.9386655784538146,
01235                 0.941739887993964, 0.9448143180987851, 0.9478888685310487,
01236                 0.9509635390489382, 0.9540383294060569, 0.9571132393514377,
01237                 0.9601882686295503, 0.9632634169803111, 0.9663386841390907,
01238                 0.9694140698367245, 0.9724895737995205, 0.9755651957492697,
01239                 0.9786409354032554, 0.9817167924742626, 0.9847927666705888,
01240                 0.9878688576960531, 0.9909450652500075, 0.9940213890273466,
01241                 0.9970978287185187, 1.0001743840095367, 1.0032510545819884,
01242                 1.0063278401130493, 1.0094047402754918, 1.0124817547376985,
01243                 1.0155588831636737, 1.0186361252130536, 1.0217134805411217,
01244                 1.0247909487988172, 1.0278685296327505, 1.0309462226852142,
01245                 1.0340240275941965, 1.0371019439933935, 1.0401799715122235,
01246                 1.0432581097758389, 1.0463363584051413, 1.0494147170167933,
01247                 1.0524931852232333, 1.0555717626326906, 1.0586504488491968,
01248                 1.0617292434726033, 1.0648081460985928, 1.0678871563186967,
01249                 1.0709662737203076, 1.0740454978866965, 1.0771248283970258,
01250                 1.0802042648263666, 1.0832838067457127, 1.086363453721997,
01251                 1.089443205318108, 1.092523061092904, 1.0956030206012313,
01252                 1.098683083393939, 1.1017632490178968, 1.1048435170160098,
01253                 1.1079238869272385, 1.1110043582866118, 1.1140849306252474,
01254                 1.1171656034703676, 1.120246376345317, 1.123327248769581,
01255                 1.1264082202588015, 1.129489290324798, 1.1325704584755818,
01256                 1.1356517242153787, 1.1387330870446435, 1.141814546460081,
01257                 1.1448961019546642, 1.147977753017652, 1.1510594991346106,
01258                 1.1541413397874303, 1.157223274454347, 1.1603053026099588,
01259                 1.1633874237252504, 1.1664696372676073, 1.1695519427008403,
01260                 1.1726343394852028, 1.1757168270774128, 1.1787994049306725,
01261                 1.1818820724946881, 1.1849648292156931, 1.1880476745364656,
01262                 1.1911306078963526, 1.194213628731289, 1.1972967364738196,
01263                 1.2003799305531206, 1.2034632103950214, 1.206546575422025,
01264                 1.209630025053332, 1.2127135587048612, 1.2157971757892707,
01265                 1.2188808757159835, 1.2219646578912058, 1.2250485217179534,
01266                 1.2281324665960707, 1.231216491922257, 1.2343005970900864,
01267                 1.2373847814900338, 1.2404690445094946, 1.2435533855328118,
01268                 1.2466378039412964, 1.2497222991132528, 1.2528068704240023,
01269                 1.2558915172459055, 1.2589762389483887, 1.2620610348979655,
01270                 1.265145904458263, 1.268230846990045, 1.2713158618512368,
01271                 1.27440094839695, 1.2774861059795064, 1.2805713339484646,
01272                 1.2836566316506417, 1.286741998430143, 1.2898274336283824,
01273                 1.292912936584111, 1.295998506633441, 1.299084143109872,
01274                 1.3021698453443156, 1.3052556126651222, 1.3083414443981063,
01275                 1.3114273398665721, 1.3145132983913408, 1.3175993192907758,
01276                 1.3206854018808087, 1.3237715454749663, 1.3268577493843976,
01277                 1.3299440129178983, 1.3330303353819408, 1.3361167160806975,
01278                 1.33920315431607, 1.342289649387715, 1.3453762005930718,
01279                 1.34846280722739, 1.3515494685837555, 1.3546361839531185,
01280                 1.3577229526243213, 1.3608097738841256, 1.3638966470172398,
01281                 1.366983571306347, 1.370070546032133, 1.3731575704733139,
01282                 1.3762446439066645, 1.379331765607045, 1.3824189348474314,
01283                 1.3855061508989417, 1.388593413030866, 1.3916807205106922,
01284                 1.3947680726041385, 1.3978554685751772, 1.4009429076860678,
01285                 1.4040303891973824, 1.4071179123680362, 1.4102054764553156,
01286                 1.4132930807149071, 1.4163807244009277, 1.4194684067659513,
01287                 1.4225561270610403, 1.425643884535773, 1.4287316784382749,
01288                 1.4318195080152447, 1.4349073725119876, 1.4379952711724417,
01289                 1.4410832032392094, 1.4441711679535851, 1.4472591645555866,
01290                 1.4503471922839841, 1.453435250376329, 1.4565233380689855,
01291                 1.4596114545971586, 1.4626995991949252, 1.4657877710952634,
01292                 1.468875969530083, 1.4719641937302546, 1.4750524429256404,
01293                 1.4781407163451246, 1.481229013216642, 1.4843173327672103,
01294                 1.4874056742229587, 1.490494036809159, 1.4935824197502554,
01295                 1.4966708222698952, 1.499759243590959, 1.502847682935591,
01296                 1.5059361395252298, 1.5090246125806384, 1.512113101321935,
01297                 1.5152016049686239, 1.5182901227396248, 1.5213786538533045,
01298                 1.524467197527508, 1.527555752979587, 1.5306443194264325,
01299                 1.533732896084505, 1.536821482169865, 1.539910076898203,
01300                 1.5429986794848713, 1.5460872891449153, 1.5491759050931018,
01301                 1.5522645265439523, 1.5553531527117719, 1.558441782810682,
01302                 1.561530416054649, 1.5646190516575167, 1.567707688833036,
01303                 1.5707963267948966 };
01304 
01309 static const double geographic[] = { 0.0, 0.0030886379618605825,
01310                 0.006177275137379901, 0.0092659107402475, 0.012354543984214532,
01311                 0.015443174083124565, 0.01853180025094438, 0.021620421701794772,
01312                 0.0247090376499813, 0.027797647310025125, 0.030886249896693734,
01313                 0.0339748446250317, 0.037063430710391455, 0.040152007368464,
01314                 0.043240573815309616, 0.0463291292673886, 0.049417672941591925,
01315                 0.05250620405527188, 0.05559472182627276, 0.05868322547296149,
01316                 0.0617717142142582, 0.06486018726966679, 0.06794864385930552,
01317                 0.0710370832039375, 0.07412550452500125, 0.07721390704464104,
01318                 0.08030228998573746, 0.08339065257193778, 0.08647899402768627,
01319                 0.0895673135782546, 0.0926556104497721, 0.09574388386925607,
01320                 0.09883213306464193, 0.10192035726481347, 0.10500855569963301,
01321                 0.10809672759997133, 0.11118487219773797, 0.11427298872591114,
01322                 0.11736107641856755, 0.12044913451091256, 0.1235371622393099,
01323                 0.12662515884131142, 0.12971312355568715, 0.13280105562245464,
01324                 0.13588895428290887, 0.13897681877965185, 0.14206464835662186,
01325                 0.1451524422591234, 0.14824019973385638, 0.1513279200289453,
01326                 0.15441560239396898, 0.1575032460799894, 0.16059085033958118,
01327                 0.16367841442686046, 0.16676593759751412, 0.16985341910882873,
01328                 0.17294085821971925, 0.17602825419075818, 0.17911560628420423,
01329                 0.18220291376403075, 0.18529017589595478, 0.1883773919474653,
01330                 0.19146456118785166, 0.19455168288823224, 0.1976387563215826,
01331                 0.20072578076276354, 0.20381275548854957, 0.20689967977765683,
01332                 0.209986552910771, 0.21307337417057526, 0.2161601428417781,
01333                 0.2192468582111411, 0.22233351956750647, 0.22542012620182456,
01334                 0.22850667740718159, 0.23159317247882658, 0.234679610714199,
01335                 0.23776599141295568, 0.24085231387699807, 0.24393857741049915,
01336                 0.24702478131993025, 0.250110924914088, 0.25319700750412083,
01337                 0.25628302840355577, 0.25936898692832455, 0.2624548823967905,
01338                 0.26554071412977437, 0.26862648145058093, 0.2717121836850245,
01339                 0.2747978201614555, 0.27788339021078556, 0.2809688931665142,
01340                 0.2840543283647537, 0.28713969514425475, 0.2902249928464323,
01341                 0.2933102208153901, 0.29639537839794666, 0.2994804649436597,
01342                 0.3025654798048515, 0.3056504223366336, 0.3087352918969311,
01343                 0.31182008784650794, 0.31490480954899097, 0.3179894563708943,
01344                 0.3210740276816437, 0.3241585228536002, 0.3272429412620848,
01345                 0.33032728228540187, 0.33341154530486283, 0.33649572970480984,
01346                 0.33957983487263954, 0.3426638601988257, 0.34574780507694325,
01347                 0.34883166890369055, 0.3519154510789131, 0.3549991510056258,
01348                 0.35808276809003553, 0.3611663017415644, 0.36424975137287147,
01349                 0.36733311639987526, 0.37041639624177586, 0.37349959032107694,
01350                 0.37658269806360756, 0.3796657188985439, 0.3827486522584309,
01351                 0.38583149757920354, 0.3889142543002084, 0.39199692186422425,
01352                 0.3950794997174837, 0.39816198730969365, 0.4012443840940563,
01353                 0.4043266895272892, 0.4074089030696463, 0.41049102418493755,
01354                 0.41357305234054986, 0.4166549870074662, 0.419736827660286,
01355                 0.4228185737772445, 0.42590022484023243, 0.4289817803348154,
01356                 0.43206323975025296, 0.4351446025795178, 0.4382258683193147,
01357                 0.4413070364700987, 0.44438810653609495, 0.4474690780253156,
01358                 0.45054995044957946, 0.45363072332452903, 0.45671139616964923,
01359                 0.4597919685082848, 0.4628724398676581, 0.4659528097788865,
01360                 0.4690330777769999, 0.47211324340095756, 0.4751933061936653,
01361                 0.4782732657019926, 0.4813531214767887, 0.48443287307289956,
01362                 0.48751252004918405, 0.49059206196853006, 0.49367149839787067,
01363                 0.4967508289082, 0.4998300530745889, 0.5029091704761999,
01364                 0.5059881806963037, 0.5090670833222932, 0.5121458779456998,
01365                 0.515224564162206, 0.5183031415716631, 0.5213816097781034,
01366                 0.5244599683897553, 0.5275382170190575, 0.5306163552826731,
01367                 0.533694382801503, 0.5367722992007001, 0.5398501041096824,
01368                 0.542927797162146, 0.5460053779960794, 0.549082846253775,
01369                 0.5521602015818429, 0.5552374436312231, 0.558314572057198,
01370                 0.5613915865194048, 0.5644684866818472, 0.567545272212908,
01371                 0.5706219427853598, 0.5736984980763777, 0.57677493776755,
01372                 0.5798512615448891, 0.5829274690988434, 0.5860035601243078,
01373                 0.589079534320634, 0.5921553913916412, 0.5952311310456269,
01374                 0.5983067529953761, 0.6013822569581719, 0.6044576426558057,
01375                 0.6075329098145854, 0.6106080581653462, 0.6136830874434589,
01376                 0.6167579973888396, 0.6198327877459584, 0.6229074582638479,
01377                 0.6259820086961115, 0.6290564388009326, 0.632130748341082,
01378                 0.6352049370839259, 0.6382790048014341, 0.6413529512701875,
01379                 0.644426776271385, 0.6475004795908512, 0.6505740610190438,
01380                 0.6536475203510599, 0.6567208573866427, 0.6597940719301885,
01381                 0.6628671637907525, 0.6659401327820553, 0.669012978722489,
01382                 0.6720857014351223, 0.6751583007477069, 0.6782307764926824,
01383                 0.6813031285071816, 0.684375356633036, 0.6874474607167802,
01384                 0.6905194406096566, 0.6935912961676205, 0.6966630272513432,
01385                 0.6997346337262175, 0.702806115462361, 0.7058774723346197,
01386                 0.7089487042225724, 0.7120198110105327, 0.7150907925875537,
01387                 0.7181616488474303, 0.7212323796887021, 0.7243029850146564,
01388                 0.7273734647333301, 0.7304438187575129, 0.7335140470047483,
01389                 0.7365841493973367, 0.7396541258623366, 0.7427239763315661,
01390                 0.7457937007416041, 0.7488632990337925, 0.7519327711542364,
01391                 0.7550021170538048, 0.7580713366881324, 0.7611404300176188,
01392                 0.7642093970074293, 0.7672782376274956, 0.7703469518525148,
01393                 0.7734155396619501, 0.7764840010400295, 0.779552335975746,
01394                 0.7826205444628564, 0.7856886264998802, 0.7887565820900994,
01395                 0.7918244112415559, 0.7948921139670508, 0.7979596902841429,
01396                 0.8010271402151462, 0.8040944637871283, 0.8071616610319086,
01397                 0.8102287319860549, 0.8132956766908815, 0.816362495192447,
01398                 0.8194291875415499, 0.8224957537937274, 0.8255621940092505,
01399                 0.8286285082531213, 0.8316946965950694, 0.8347607591095485,
01400                 0.8378266958757314, 0.8408925069775065, 0.8439581925034738,
01401                 0.8470237525469397, 0.8500891872059131, 0.8531544965830998,
01402                 0.8562196807858983, 0.8592847399263936, 0.8623496741213532,
01403                 0.8654144834922204, 0.8684791681651088, 0.8715437282707976,
01404                 0.8746081639447237, 0.8776724753269767, 0.8807366625622927,
01405                 0.8838007258000469, 0.8868646651942474, 0.8899284809035285,
01406                 0.8929921730911432, 0.8960557419249562, 0.8991191875774363,
01407                 0.9021825102256493, 0.9052457100512501, 0.9083087872404745,
01408                 0.9113717419841312, 0.9144345744775944, 0.9174972849207942,
01409                 0.9205598735182088, 0.923622340478856, 0.9266846860162834,
01410                 0.9297469103485603, 0.9328090136982676, 0.9358709962924899,
01411                 0.9389328583628043, 0.9419946001452715, 0.945056221880426,
01412                 0.9481177238132663, 0.9511791061932441, 0.9542403692742544,
01413                 0.9573015133146252, 0.9603625385771062, 0.9634234453288585,
01414                 0.9664842338414438, 0.969544904390813, 0.9726054572572946,
01415                 0.9756658927255841, 0.9787262110847318, 0.9817864126281313,
01416                 0.9848464976535075, 0.9879064664629048, 0.9909663193626747,
01417                 0.9940260566634633, 0.9970856786801994, 1.000145185732081,
01418                 1.0032045781425638, 1.0062638562393464, 1.0093230203543588,
01419                 1.0123820708237492, 1.0154410079878686, 1.0184998321912604,
01420                 1.0215585437826438, 1.0246171431149014, 1.0276756305450656,
01421                 1.0307340064343031, 1.0337922711479026, 1.036850425055258,
01422                 1.039908468529856, 1.04296640194926, 1.0460242256950962,
01423                 1.049081940153038, 1.0521395457127913, 1.0551970427680788,
01424                 1.0582544317166251, 1.061311712960141, 1.0643688869043078,
01425                 1.0674259539587614, 1.0704829145370764, 1.0735397690567505,
01426                 1.0765965179391872, 1.0796531616096812, 1.0827097004973996,
01427                 1.085766135035368, 1.088822465660451, 1.0918786928133375,
01428                 1.0949348169385227, 1.097990838484291, 1.101046757902699,
01429                 1.104102575649558, 1.1071582921844167, 1.1102139079705429,
01430                 1.1132694234749065, 1.1163248391681613, 1.1193801555246266,
01431                 1.12243537302227, 1.1254904921426878, 1.1285455133710884,
01432                 1.1316004371962716, 1.1346552641106122, 1.137709994610039,
01433                 1.1407646291940186, 1.143819168365533, 1.1468736126310646,
01434                 1.149927962500573, 1.1529822184874776, 1.1560363811086392,
01435                 1.1590904508843376, 1.162144428338255, 1.165198313997453,
01436                 1.1682521083923565, 1.171305812056729, 1.1743594255276575,
01437                 1.1774129493455274, 1.1804663840540066, 1.1835197302000213,
01438                 1.1865729883337375, 1.1896261590085404, 1.1926792427810122,
01439                 1.1957322402109125, 1.1987851518611565, 1.201837978297795,
01440                 1.204890720089991, 1.207943377810001, 1.2109959520331517,
01441                 1.2140484433378194, 1.217100852305408, 1.2201531795203273,
01442                 1.2232054255699714, 1.226257591044696, 1.2293096765377982,
01443                 1.232361682645492, 1.235413609966888, 1.2384654591039699,
01444                 1.241517230661573, 1.2445689252473608, 1.2476205434718035,
01445                 1.2506720859481537, 1.2537235532924256, 1.2567749461233706,
01446                 1.259826265062455, 1.2628775107338368, 1.2659286837643429,
01447                 1.2689797847834456, 1.2720308144232386, 1.2750817733184152,
01448                 1.2781326621062439, 1.2811834814265437, 1.2842342319216635,
01449                 1.2872849142364546, 1.2903355290182508, 1.2933860769168408,
01450                 1.2964365585844468, 1.2994869746756996, 1.3025373258476145,
01451                 1.3055876127595665, 1.308637836073268, 1.3116879964527417,
01452                 1.3147380945642977, 1.31778813107651, 1.3208381066601895,
01453                 1.3238880219883615, 1.3269378777362395, 1.3299876745812016,
01454                 1.3330374132027645, 1.3360870942825596, 1.339136718504307,
01455                 1.3421862865537921, 1.3452357991188382, 1.3482852568892825,
01456                 1.351334660556952, 1.3543840108156358, 1.3574333083610615,
01457                 1.3604825538908687, 1.3635317481045846, 1.366580891703597,
01458                 1.3696299853911307, 1.3726790298722187, 1.37572802585368,
01459                 1.3787769740440912, 1.381825875153762, 1.3848747298947086,
01460                 1.3879235389806277, 1.3909723031268717, 1.3940210230504206,
01461                 1.3970696994698577, 1.4001183331053422, 1.4031669246785838,
01462                 1.4062154749128157, 1.4092639845327688, 1.4123124542646455,
01463                 1.415360884836092, 1.418409276976174, 1.4214576314153478,
01464                 1.424505948885436, 1.4275542301195985, 1.4306024758523086,
01465                 1.4336506868193237, 1.4366988637576603, 1.4397470074055667,
01466                 1.442795118502496, 1.4458431977890798, 1.4488912460070997,
01467                 1.4519392638994637, 1.454987252210175, 1.4580352116843092,
01468                 1.4610831430679836, 1.464131047108333, 1.4671789245534805,
01469                 1.4702267761525125, 1.4732746026554489, 1.4763224048132186,
01470                 1.4793701833776305, 1.4824179391013466, 1.4854656727378561,
01471                 1.4885133850414456, 1.491561076767174, 1.4946087486708444,
01472                 1.4976564015089762, 1.5007040360387784, 1.5037516530181227,
01473                 1.506799253205514, 1.5098468373600653, 1.5128944062414693,
01474                 1.51594196060997, 1.5189895012263372, 1.522037028851837,
01475                 1.525084544248206, 1.5281320481776215, 1.531179541402677,
01476                 1.5342270246863512, 1.537274498791984, 1.5403219644832453,
01477                 1.5433694225241104, 1.5464168736788304, 1.5494643187119053,
01478                 1.5525117583880574, 1.555559193472201, 1.558606624729418,
01479                 1.5616540529249268, 1.5647014788240585, 1.5677489031922254,
01480                 1.5707963267948966 };
01481 
01482 inline double GeoTessUtils::getGeoCentricLatitude(const double& lat)
01483 {
01484         // convert lat from geographic to geocentric latitude.
01485 
01486         if (!approximateLatitudes)
01487                 return atan((1 - EARTH_E) * tan(lat));
01488 
01489         if (lat >= PI / 2)
01490                 return PI / 2;
01491         else if (lat <= -PI / 2)
01492                 return -PI / 2;
01493         else if (lat < 0)
01494         {
01495                 double tmp = -lat / (PI / 2 / (513 - 1));
01496                 int i = (int) tmp;
01497                 return -geocentric[i] - (tmp - i) * (geocentric[i + 1] - geocentric[i]);
01498         }
01499         else
01500         {
01501                 double tmp = lat / (PI / 2 / (513 - 1));
01502                 int i = (int) tmp;
01503                 return geocentric[i] + (tmp - i) * (geocentric[i + 1] - geocentric[i]);
01504         }
01505 }
01506 
01507 inline double GeoTessUtils::getGeoGraphicLatitude(const double& lat)
01508 {
01509         // the constant 0.9933 is (1-e*e) where e is the eccentricity of the
01510         // earth as defined by the GRS80 ellipsoid.
01511 
01512         if (!approximateLatitudes)
01513                 return atan(tan(lat) / (1 - EARTH_E));
01514 
01515         if (lat >= PI / 2)
01516                 return PI / 2;
01517         else if (lat <= -PI / 2)
01518                 return -PI / 2;
01519         else if (lat < 0)
01520         {
01521                 double tmp = -lat / (PI / 2 / (513 - 1));
01522                 int i = (int) tmp;
01523                 return -geographic[i] - (tmp - i) * (geographic[i + 1] - geographic[i]);
01524         }
01525         else
01526         {
01527                 double tmp = lat / (PI / 2 / (513 - 1));
01528                 int i = (int) tmp;
01529                 return geographic[i] + (tmp - i) * (geographic[i + 1] - geographic[i]);
01530         }
01531 }
01532 
01533 } // end namespace geotess
01534 
01535 #endif  // GEOTESSUTILS_OBJECT_H