GeoTessCPP  2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
GeoTessUtils.h
Go to the documentation of this file.
1 //- ****************************************************************************
2 //-
3 //- Copyright 2009 Sandia Corporation. Under the terms of Contract
4 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
5 //- retains certain rights in this software.
6 //-
7 //- BSD Open Source License.
8 //- All rights reserved.
9 //-
10 //- Redistribution and use in source and binary forms, with or without
11 //- modification, are permitted provided that the following conditions are met:
12 //-
13 //- * Redistributions of source code must retain the above copyright notice,
14 //- this list of conditions and the following disclaimer.
15 //- * Redistributions in binary form must reproduce the above copyright
16 //- notice, this list of conditions and the following disclaimer in the
17 //- documentation and/or other materials provided with the distribution.
18 //- * Neither the name of Sandia National Laboratories nor the names of its
19 //- contributors may be used to endorse or promote products derived from
20 //- this software without specific prior written permission.
21 //-
22 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //- POSSIBILITY OF SUCH DAMAGE.
33 //-
34 //- ****************************************************************************
35 
36 #ifndef GEOTESSUTILS_OBJECT_H
37 #define GEOTESSUTILS_OBJECT_H
38 
39 // **** _SYSTEM INCLUDES_ ******************************************************
40 
41 #include <iostream>
42 #include <fstream>
43 #include <vector>
44 #include <map>
45 #include <string>
46 
47 // use standard library objects
48 using namespace std;
49 
50 // **** _LOCAL INCLUDES_ *******************************************************
51 
52 #include "CPPUtils.h"
53 
54 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
55 
56 namespace geotess {
57 
58 // **** _FORWARD REFERENCES_ ***************************************************
59 
60 // **** _CLASS DEFINITION_ *****************************************************
61 
69 {
70 private:
71 
72  /*
73  * Private copy constructor. Not used.
74  */
75  GeoTessUtils(const GeoTessUtils& gtu) {};
76 
77  /*
78  * Private assignment operator. Not used.
79  */
80  GeoTessUtils& operator=(const GeoTessUtils& gtu)
81  { return *this; };
82 
83 public:
84 
95  static bool approximateLatitudes;
96 
97 
102 
106  virtual ~GeoTessUtils() {};
107 
111  static string class_name() { return "GeoTessUtils"; };
112 
116  virtual int class_size() const
117  { return (int) sizeof(GeoTessUtils); };
118 
122  static string getVersion() { return "2.0.0"; };
123 
127  static void readString(string& s, ifstream& ifs);
128  static void writeString(ofstream& ofs, const string& s);
129 
133  static double angle(const double* const v0, const double* const v1);
134  static double angleDegrees(const double* const v0, const double* const v1);
135 
136  // *** TODO added 7/19/2012
142  static double getDistance3D(const double* const v0, double r0,
143  const double* const v1, double r1);
144 
148  static double dot(const double* const v0, const double* const v1);
149  static double scalarTripleProduct(const double* const v0,
150  const double* const v1,
151  const double* const v2);
152 
156  static double getEarthRadius(const double* const vector);
157 
161  static double getGeoCentricLatitude(const double& lat);
162  static double getGeoGraphicLatitude(const double& lat);
163  static double getLat(const double* const vector);
164  static double getLon(const double* const vector);
165  static double getLatDegrees(const double* const vector);
166  static double getLonDegrees(const double* const vector);
167 
171  static string getLatLonString(const double* const v);
172 
176  static double* getVectorDegrees(const double& lat, const double& lon);
177  static double* getVector(const double& lat, const double& lon);
178  static double* getVector(const double& lat, const double& lon, double* v);
179  static double* getVectorDegrees(const double& lat, const double& lon, double* v);
180 
184  static double azimuthDegrees(const double* const v1, const double* const v2,
185  double errorValue);
186  static double azimuth(const double* const v1, const double* const v2,
187  double errorValue);
188 
192  static double normalize(double* const u);
193 
197  static void cross(const double* const v1, const double* const v2, double* const rslt);
198 
202  static double* crossNormal(const double* const u, const double* const v);
203  static double crossNormal(const double* const u, const double* const v,
204  double* const w);
205 
210  static double crossNorth(const double* const u, double* const w);
211 
215  static bool vectorTripleProduct(const double* const v0, const double* const v1,
216  const double* const v2, double* const rslt);
217 
221  static bool vectorTripleProductNorthPole(const double* const u, double* const w);
222 
226  static bool circumCenter(const double* const v0, const double* const v1,
227  const double* const v2, double* const vs);
228  static double* circumCenter(const double* const v0, const double* const v1,
229  const double* const v2);
230  static bool circumCenter(double const* const* const t, double* const vs);
231 
235  static bool move(const double* const w, double distance, double azimuth,
236  double* const u);
237  static void move(const double* const w, const double* const vtp,
238  double a, double* const u);
239  static bool moveNorth(const double* const x, double distance,
240  double* const z);
241 
245  static void rotate(const double* const x, const double* const p,
246  double a, double* const z);
247 
270  static double** getGreatCircle(const double* const v0, const double* const v1);
271 
294  static void getGreatCircle(const double* const v0, const double* const v1, double** const gc);
295 
320  static double** getGreatCircle(const double* const v, double azimuth);
321 
346  static void getGreatCircle(const double* const v, double azimuth, double** const gc);
347 
348 
349  static void getGreatCirclePoint(double const* const* const greatCircle, double distance, double* const v);
350 
351  static double* getGreatCirclePoint(double const* const* const greatCircle, double distance);
352 
356  static double getTriangleArea(const double* const v0,
357  const double* const v1,
358  const double* const v2);
359  static double* center(double const* const* const v, int n);
360 
361  static void center(vector<double*> v, double* x);
362 
366  static double length(const double* const u);
367 
371  static bool isPole(const double* const u);
372 
376  static bool parallel(const double* const u, const double* const v);
377 
387  static void getTransform(const double* const u, const double* const v,
388  double** const t);
389 
402  static void transform(const double* x,
403  double const* const* const transform,
404  double* const g);
405 
406 }; // end class GeoTessUtils
407 
408 // **** _INLINE FUNCTION IMPLEMENTATIONS_ **************************************
409 
413 inline void GeoTessUtils::readString(string& s, ifstream& ifs)
414 {
415  int sze;
416  ifs >> sze;
417  char* c = new char [sze];
418  ifs.read(c, sze);
419  s = c;
420  delete [] c;
421 }
422 
426 inline void GeoTessUtils::writeString(ofstream& ofs, const string& s)
427 {
428  ofs << s.length();
429  ofs.write(s.c_str(), s.length());
430 }
431 
441 inline double GeoTessUtils::angle(const double* const v0, const double* const v1)
442 {
443  double dot = v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
444  if (dot >= 1.0) return 0.0;
445  if (dot <= -1.0) return PI;
446  return acos(dot);
447 }
448 
458 inline double GeoTessUtils::angleDegrees(const double* const v0, const double* const v1)
459 {
460  double dot = v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
461  if (dot >= 1.) return 0.;
462  if (dot <= -1.) return 180.;
463  return CPPUtils::toDegrees(acos(dot));
464 }
465 
477 inline double GeoTessUtils::getDistance3D(const double* const v0, double r0,
478  const double* const v1, double r1)
479 {
480  double v[3] = { v0[0] * r0 - v1[0] * r1,
481  v0[1] * r0 - v1[1] * r1,
482  v0[2] * r0 - v1[2] * r1 };
483  return length(v);
484 }
485 
495 inline double GeoTessUtils::dot(const double* const v0, const double* const v1)
496 {
497  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
498 }
499 
512 inline double GeoTessUtils::scalarTripleProduct(const double* const v0,
513  const double* const v1, const double* const v2)
514 {
515  return v0[0] * v1[1] * v2[2] + v1[0] * v2[1] * v0[2] + v2[0] * v0[1] * v1[2]
516  - v2[0] * v1[1] * v0[2] - v0[0] * v2[1] * v1[2] - v1[0] * v0[1] * v2[2];
517 }
518 
526 inline double GeoTessUtils::getEarthRadius(const double* const v)
527 {
528  return EARTH_A / sqrt(1. + EARTH_E/(1-EARTH_E) * v[2] * v[2]);
529 }
530 
537 inline double GeoTessUtils::getLat(const double* const v)
538 {
539  return GeoTessUtils::getGeoGraphicLatitude(asin(v[2]));
540 }
541 
548 inline double GeoTessUtils::getLon(const double* const v)
549 {
550  return atan2(v[1], v[0]);
551 }
552 
559 inline double GeoTessUtils::getLatDegrees(const double* const v)
560 {
561  // the constant 0.9933 is (1-e*e) where e is the eccentricity of the
562  // earth
563  // as defined by the GRS80 ellipsoid.
564  return CPPUtils::toDegrees(atan(tan(asin(v[2])) / 0.9933056199770992));
565 }
566 
573 inline double GeoTessUtils::getLonDegrees(const double* const v)
574 {
575  return CPPUtils::toDegrees(atan2(v[1], v[0]));
576 }
577 
589 inline double* GeoTessUtils::getVectorDegrees(const double& lat, const double& lon)
590 {
591  return getVector(CPPUtils::toRadians(lat), CPPUtils::toRadians(lon));
592 }
593 
603 inline double* GeoTessUtils::getVectorDegrees(const double& lat, const double& lon, double* v)
604 {
605  return getVector(CPPUtils::toRadians(lat), CPPUtils::toRadians(lon), v);
606 }
607 
619 inline double* GeoTessUtils::getVector(const double& lat, const double& lon)
620 {
621  double* v = new double[3];
622  getVector(lat, lon, v);
623  return v;
624 }
625 
635 inline double* GeoTessUtils::getVector(const double& lat, const double& lon, double* v)
636 {
637  // convert lat from geographic to geocentric latitude.
638  double temp = GeoTessUtils::getGeoCentricLatitude(lat);
639 
640  // z component of v is sin of geocentric latitude.
641  v[2] = sin(temp);
642 
643  // set lat = to cos of geocentric latitude
644  temp = cos(temp);
645 
646  // compute x and y components of v
647  v[0] = temp * cos(lon);
648  v[1] = temp * sin(lon);
649 
650  return v;
651 }
652 
660 inline double GeoTessUtils::normalize(double* const u)
661 {
662  double len = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
663  if (len > 0.)
664  {
665  len = sqrt(len);
666  u[0] /= len;
667  u[1] /= len;
668  u[2] /= len;
669  }
670  else
671  {
672  len = u[0] = u[1] = u[2] = 0.0;
673  }
674  return len;
675 }
676 
687 inline void GeoTessUtils::cross(const double* const v1, const double* const v2,
688  double* const rslt)
689 {
690  rslt[0] = v1[1] * v2[2] - v1[2] * v2[1];
691  rslt[1] = v1[2] * v2[0] - v1[0] * v2[2];
692  rslt[2] = v1[0] * v2[1] - v1[1] * v2[0];
693 }
694 
705 inline double* GeoTessUtils::crossNormal(const double* const u, const double* const v)
706 {
707  double* w = new double[3];
708  w[0] = u[1] * v[2] - u[2] * v[1];
709  w[1] = u[2] * v[0] - u[0] * v[2];
710  w[2] = u[0] * v[1] - u[1] * v[0];
711  normalize(w);
712  return w;
713 }
714 
727 inline double GeoTessUtils::crossNormal(const double* const u, const double* const v,
728  double* const w)
729 {
730  w[0] = u[1] * v[2] - u[2] * v[1];
731  w[1] = u[2] * v[0] - u[0] * v[2];
732  w[2] = u[0] * v[1] - u[1] * v[0];
733  return normalize(w);
734 }
735 
748 inline double GeoTessUtils::crossNorth(const double* const u, double* const w)
749 {
750  double len = u[0] * u[0] + u[1] * u[1];
751  if (len <= 0.)
752  {
753  len = w[0] = w[1] = w[2] = 0.;
754  }
755  else
756  {
757  len = sqrt(len);
758  w[0] = u[1] / len;
759  w[1] = -u[0] / len;
760  w[2] = 0.;
761  }
762  return len;
763 }
764 
780 inline bool GeoTessUtils::vectorTripleProduct(const double* const v0, const double* const v1,
781  const double* const v2, double* const rslt)
782 {
783  // set q = v0 cross v1
784  double q0 = v0[1] * v1[2] - v0[2] * v1[1];
785  double q1 = v0[2] * v1[0] - v0[0] * v1[2];
786  double q2 = v0[0] * v1[1] - v0[1] * v1[0];
787 
788  // set w = q cross v2
789  double w0 = q1 * v2[2] - q2 * v2[1];
790  double w1 = q2 * v2[0] - q0 * v2[2];
791  double w2 = q0 * v2[1] - q1 * v2[0];
792 
793  // set rslt = w
794  rslt[0] = w0;
795  rslt[1] = w1;
796  rslt[2] = w2;
797 
798  // normalize rslt to unit length. if the length
799  // of v1 or v2 is zero or they are nearly parallel then
800  // rslt will = {0,0,0} and the function will return false;
801  return normalize(rslt) != 0.;
802 }
803 
814 inline bool GeoTessUtils::vectorTripleProductNorthPole(const double* const u, double* const w)
815 {
816  w[0] = -u[0] * u[2];
817  w[1] = -u[1] * u[2];
818  w[2] = u[1] * u[1] + u[0] * u[0];
819  return normalize(w) != 0.;
820 }
821 
834 inline bool GeoTessUtils::circumCenter(const double* const v0, const double* const v1,
835  const double* const v2, double* const vs)
836 {
837  vs[0] = v0[1] * (v2[2] - v1[2]) + v2[1] * (v1[2] - v0[2]) + v1[1]
838  * (v0[2] - v2[2]);
839  vs[1] = v0[2] * (v2[0] - v1[0]) + v2[2] * (v1[0] - v0[0]) + v1[2]
840  * (v0[0] - v2[0]);
841  vs[2] = v0[0] * (v2[1] - v1[1]) + v2[0] * (v1[1] - v0[1]) + v1[0]
842  * (v0[1] - v2[1]);
843  return normalize(vs) > 0.;
844 }
845 
857 inline double* GeoTessUtils::circumCenter(const double* const v0,
858  const double* const v1,
859  const double* const v2)
860 {
861  double* vs = new double [3];
862  vs[0] = v0[1] * (v2[2] - v1[2]) + v2[1] * (v1[2] - v0[2]) + v1[1]
863  * (v0[2] - v2[2]);
864  vs[1] = v0[2] * (v2[0] - v1[0]) + v2[2] * (v1[0] - v0[0]) + v1[2]
865  * (v0[0] - v2[0]);
866  vs[2] = v0[0] * (v2[1] - v1[1]) + v2[0] * (v1[1] - v0[1]) + v1[0]
867  * (v0[1] - v2[1]);
868  normalize(vs);
869  return vs;
870 }
871 
884 inline bool GeoTessUtils::circumCenter(double const* const* const t, double* const vs)
885 {
886  return circumCenter(t[0], t[1], t[2], vs);
887 }
888 
904 inline bool GeoTessUtils::move(const double* const w, double distance, double azimuth,
905  double* const u)
906 {
907  double n[3] = { 0.0, 0.0, 0.0 };
908  if (moveNorth(w, distance, n))
909  {
910  rotate(n, w, azimuth, u);
911  return true;
912  }
913  u[0] = w[0];
914  u[1] = w[1];
915  u[2] = w[2];
916  return false;
917 }
918 
932 inline void GeoTessUtils::move(const double* const w, const double* const vtp,
933  double a, double* const u)
934 {
935  double cosa = cos(a);
936  double sina = sin(a);
937  u[0] = cosa * w[0] + sina * vtp[0];
938  u[1] = cosa * w[1] + sina * vtp[1];
939  u[2] = cosa * w[2] + sina * vtp[2];
940 }
941 
956 inline bool GeoTessUtils::moveNorth(const double* const x, double distance,
957  double* const z)
958 {
959  double vtp[3] = { 0.0, 0.0, 0.0 };
960  if (vectorTripleProductNorthPole(x, vtp))
961  {
962  move(x, vtp, distance, z);
963  return true;
964  }
965 
966  z[0] = x[0];
967  z[1] = x[1];
968  z[2] = x[2];
969  return false;
970 }
971 
979 inline bool GeoTessUtils::isPole(const double* const u)
980 {
981  return (u[0] * u[0] + u[1] * u[1]) < 1.0e-15;
982 }
983 
993 inline bool GeoTessUtils::parallel(const double* const u, const double* const v)
994 {
995  return 1.0 - abs(u[0] * v[0] + u[1] * v[1] + u[2] * v[2]) < 2.0e-15;
996 }
997 
1014 inline double* GeoTessUtils::getGreatCirclePoint(double const* const* const greatCircle,
1015  double distance)
1016 {
1017  double* v = new double[3];
1018  getGreatCirclePoint(greatCircle, distance, v);
1019  return v;
1020 }
1021 
1039 inline void GeoTessUtils::getGreatCirclePoint(double const* const* const greatCircle,
1040  double distance, double* const v)
1041 {
1042  double cosa = cos(distance);
1043  double sina = sin(distance);
1044  v[0] = cosa * greatCircle[0][0] + sina * greatCircle[1][0];
1045  v[1] = cosa * greatCircle[0][1] + sina * greatCircle[1][1];
1046  v[2] = cosa * greatCircle[0][2] + sina * greatCircle[1][2];
1047 }
1048 
1055 inline double GeoTessUtils::getTriangleArea(const double* const v0,
1056  const double* const v1,
1057  const double* const v2)
1058 {
1059  double v10[3] = { v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2] };
1060  double v20[3] = { v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2] };
1061  double u[3] = { v10[1] * v20[2] - v10[2] * v20[1],
1062  v10[2] * v20[0] - v10[0] * v20[2],
1063  v10[0] * v20[1] - v10[1] * v20[0] };
1064  return sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]) / 2.;
1065 }
1066 
1074 inline double GeoTessUtils::length(const double* const u)
1075 {
1076  double l = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
1077  if (l > 0.) return sqrt(l);
1078  return 0.;
1079 }
1080 
1088 inline double* GeoTessUtils::center(double const * const* const v, int n)
1089 {
1090  double* x = new double [3];
1091  x[0] = x[1] = x[2] = 0.0;
1092  if (n == 0) return x;
1093 
1094  for (int i = 0; i < n; ++i)
1095  {
1096  x[0] += v[i][0];
1097  x[1] += v[i][1];
1098  x[2] += v[i][2];
1099  }
1100  normalize(x);
1101  return x;
1102 }
1103 
1111 inline void GeoTessUtils::center(vector<double*> v, double* x)
1112 {
1113  x[0] = x[1] = x[2] = 0.0;
1114 
1115  for (size_t i = 0; i < v.size(); ++i)
1116  {
1117  x[0] += v[i][0];
1118  x[1] += v[i][1];
1119  x[2] += v[i][2];
1120  }
1121  normalize(x);
1122 }
1123 
1146 inline void GeoTessUtils::transform(const double* x,
1147  double const* const* const transform,
1148  double* const g)
1149 {
1150  g[0] = x[0] * transform[0][0] + x[1] * transform[0][1] +
1151  x[2] * transform[0][2];
1152  g[1] = x[0] * transform[1][0] + x[1] * transform[1][1] +
1153  x[2] * transform[1][2];
1154  g[2] = x[0] * transform[2][0] + x[1] * transform[2][1] +
1155  x[2] * transform[2][2];
1156 }
1157 
1162 static const double geocentric[] = { 0.0,
1163  0.003047423602671013, 0.006094847970838097, 0.009142273869969656,
1164  0.012189702065478763, 0.015237133322695492, 0.018284568406839258,
1165  0.021332008082991166, 0.024379453116066336, 0.027426904270786288,
1166  0.030474362311651265, 0.03352182800291262, 0.03656930210854519,
1167  0.03961678539221966, 0.04266427861727495, 0.04571178254669065,
1168  0.04875929794305942, 0.05180682556855937, 0.05485436618492655,
1169  0.057901920553427404, 0.06094948943483121, 0.06399707358938257,
1170  0.06704467377677387, 0.0700922907561179, 0.07313992528592034,
1171  0.07618757812405218, 0.07923525002772251, 0.08228294175345101,
1172  0.08533065405704056, 0.08837838769354987, 0.0914261434172662,
1173  0.094473921981678, 0.09752172413944764, 0.10056955064238413,
1174  0.1036174022414159, 0.10666527968656359, 0.1097131837269129,
1175  0.11276111511058741, 0.11580907458472142, 0.11885706289543299,
1176  0.12190508078779674, 0.1249531290058169, 0.1280012082924004,
1177  0.13104931938932968, 0.13409746303723613, 0.13714563997557289,
1178  0.140193850942588, 0.14324209667529803, 0.14629037790946073,
1179  0.14933869537954875, 0.15238704981872267, 0.15543544195880452,
1180  0.1584838725302512, 0.1615323422621277, 0.16458085188208085,
1181  0.16762940211631275, 0.17067799368955427, 0.17372662732503877,
1182  0.17677530374447592, 0.17982402366802488, 0.1828727878142688,
1183  0.18592159690018817, 0.18897045164113468, 0.19201935275080542,
1184  0.19506830094121663, 0.19811729692267788, 0.201166341403766,
1185  0.20421543509129933, 0.20726457869031198, 0.21031377290402786,
1186  0.21336301843383518, 0.21641231597926083, 0.21946166623794464,
1187  0.22251106990561403, 0.22556052767605864, 0.2286100402411045,
1188  0.2316596082905894, 0.23470923251233702, 0.23775891359213203,
1189  0.24080865221369493, 0.2438584490586569, 0.24690830480653495,
1190  0.2499582201347069, 0.25300819571838656, 0.25605823223059876,
1191  0.25910833034215514, 0.2621584907216286, 0.26520871403532986,
1192  0.2682590009472821, 0.27130935211919693, 0.2743597682104497,
1193  0.27741024987805574, 0.2804607977766458, 0.28351141255844176,
1194  0.28656209487323325, 0.2896128453683528, 0.29266366468865285,
1195  0.29571455347648123, 0.29876551237165794, 0.3018165420114511,
1196  0.3048676430305536, 0.30791881606105975, 0.3109700617324416,
1197  0.314021380671526, 0.317072773502471, 0.32012424084674285,
1198  0.3231757833230931, 0.3262274015475356, 0.3292790961333235,
1199  0.3323308676909266, 0.3353827168280087, 0.3384346441494046,
1200  0.34148665025709846, 0.34453873575020055, 0.34759090122492536,
1201  0.3506431472745693, 0.35369547448948857, 0.35674788345707703,
1202  0.3598003747617447, 0.3628529489848955, 0.36590560670490546,
1203  0.36895834849710163, 0.3720111749337399, 0.3750640865839841,
1204  0.3781170840138844, 0.3811701677863562, 0.384223338461159,
1205  0.3872765965948754, 0.39032994274089, 0.393383377449369,
1206  0.39643690126723913, 0.3994905147381674, 0.4025442184025402,
1207  0.40559801279744334, 0.40865189845664174, 0.41170587591055896,
1208  0.4147599456862576, 0.41781410830741905, 0.42086836429432384,
1209  0.423922714163832, 0.4269771584293634, 0.43003169760087806,
1210  0.43308633218485754, 0.4361410626842845, 0.43919588959862493,
1211  0.4422508134238082, 0.44530583465220863, 0.44836095377262664,
1212  0.4514161712702699, 0.4544714876267352, 0.45752690331998996,
1213  0.4605824188243536, 0.46363803461047975, 0.4666937511453385,
1214  0.4697495688921976, 0.4728054883106056, 0.47586150985637393,
1215  0.4789176339815591, 0.4819738611344456, 0.48503019175952866,
1216  0.4880866262974967, 0.49114316518521534, 0.49419980885570924,
1217  0.49725655773814614, 0.5003134122578201, 0.5033703728361352,
1218  0.5064274398905888, 0.5094846138347555, 0.5125418950782715,
1219  0.5155992840268179, 0.5186567810821053, 0.5217143866418585,
1220  0.5247721010998003, 0.5278299248456365, 0.5308878582650406,
1221  0.5339459017396384, 0.5370040556469939, 0.5400623203605933,
1222  0.5431206962498311, 0.5461791836799952, 0.5492377830122528,
1223  0.5522964946036362, 0.5553553188070278, 0.5584142559711474,
1224  0.5614733064405376, 0.5645324705555501, 0.5675917486523328,
1225  0.5706511410628154, 0.5737106481146972, 0.5767702701314332,
1226  0.5798300074322218, 0.5828898603319916, 0.5859498291413889,
1227  0.5890099141667653, 0.5920701157101648, 0.5951304340693124,
1228  0.598190869537602, 0.6012514224040836, 0.6043120929534528,
1229  0.6073728814660381, 0.6104337882177904, 0.6134948134802714,
1230  0.6165559575206421, 0.6196172206016525, 0.6226786029816302,
1231  0.6257401049144706, 0.6288017266496251, 0.6318634684320923,
1232  0.6349253305024066, 0.6379873130966289, 0.6410494164463364,
1233  0.6441116407786132, 0.6471739863160405, 0.6502364532766877,
1234  0.6532990418741025, 0.6563617523173022, 0.6594245848107654,
1235  0.6624875395544221, 0.6655506167436465, 0.6686138165692472,
1236  0.6716771392174603, 0.6747405848699405, 0.6778041537037534,
1237  0.6808678458913681, 0.6839316616006491, 0.6869956009948498,
1238  0.6900596642326039, 0.6931238514679199, 0.6961881628501729,
1239  0.6992525985240989, 0.7023171586297877, 0.7053818433026762,
1240  0.7084466526735433, 0.7115115868685029, 0.7145766460089984,
1241  0.7176418302117967, 0.7207071395889835, 0.7237725742479568,
1242  0.7268381342914229, 0.72990381981739, 0.7329696309191651,
1243  0.7360355676853481, 0.7391016301998271, 0.7421678185417753,
1244  0.7452341327856461, 0.7483005730011691, 0.7513671392533465,
1245  0.7544338316024497, 0.7575006501040149, 0.7605675948088417,
1246  0.7636346657629879, 0.7667018630077682, 0.7697691865797504,
1247  0.7728366365107536, 0.7759042128278457, 0.7789719155533406,
1248  0.7820397447047971, 0.7851077002950162, 0.7881757823320402,
1249  0.7912439908191506, 0.794312325754867, 0.7973807871329465,
1250  0.8004493749423818, 0.8035180891674011, 0.8065869297874673,
1251  0.8096558967772779, 0.8127249901067641, 0.8157942097410916,
1252  0.8188635556406603, 0.821933027761104, 0.8250026260532924,
1253  0.8280723504633305, 0.83114220093256, 0.8342121773975598,
1254  0.8372822797901482, 0.8403525080373838, 0.8434228620615665,
1255  0.8464933417802403, 0.8495639471061945, 0.8526346779474664,
1256  0.8557055342073429, 0.8587765157843639, 0.8618476225723242,
1257  0.8649188544602767, 0.8679902113325356, 0.8710616930686791,
1258  0.8741332995435535, 0.8772050306272762, 0.8802768861852399,
1259  0.8833488660781164, 0.8864209701618606, 0.889493198287715,
1260  0.8925655503022143, 0.8956380260471897, 0.8987106253597743,
1261  0.9017833480724076, 0.9048561940128412, 0.9079291630041441,
1262  0.9110022548647081, 0.9140754694082539, 0.9171488064438367,
1263  0.9202222657758528, 0.9232958472040453, 0.9263695505235116,
1264  0.929443375524709, 0.9325173219934624, 0.9355913897109707,
1265  0.9386655784538146, 0.941739887993964, 0.9448143180987851,
1266  0.9478888685310487, 0.9509635390489382, 0.9540383294060569,
1267  0.9571132393514377, 0.9601882686295503, 0.9632634169803111,
1268  0.9663386841390907, 0.9694140698367245, 0.9724895737995205,
1269  0.9755651957492697, 0.9786409354032554, 0.9817167924742626,
1270  0.9847927666705888, 0.9878688576960531, 0.9909450652500075,
1271  0.9940213890273466, 0.9970978287185187, 1.0001743840095367,
1272  1.0032510545819884, 1.0063278401130493, 1.0094047402754918,
1273  1.0124817547376985, 1.0155588831636737, 1.0186361252130536,
1274  1.0217134805411217, 1.0247909487988172, 1.0278685296327505,
1275  1.0309462226852142, 1.0340240275941965, 1.0371019439933935,
1276  1.0401799715122235, 1.0432581097758389, 1.0463363584051413,
1277  1.0494147170167933, 1.0524931852232333, 1.0555717626326906,
1278  1.0586504488491968, 1.0617292434726033, 1.0648081460985928,
1279  1.0678871563186967, 1.0709662737203076, 1.0740454978866965,
1280  1.0771248283970258, 1.0802042648263666, 1.0832838067457127,
1281  1.086363453721997, 1.089443205318108, 1.092523061092904,
1282  1.0956030206012313, 1.098683083393939, 1.1017632490178968,
1283  1.1048435170160098, 1.1079238869272385, 1.1110043582866118,
1284  1.1140849306252474, 1.1171656034703676, 1.120246376345317,
1285  1.123327248769581, 1.1264082202588015, 1.129489290324798,
1286  1.1325704584755818, 1.1356517242153787, 1.1387330870446435,
1287  1.141814546460081, 1.1448961019546642, 1.147977753017652,
1288  1.1510594991346106, 1.1541413397874303, 1.157223274454347,
1289  1.1603053026099588, 1.1633874237252504, 1.1664696372676073,
1290  1.1695519427008403, 1.1726343394852028, 1.1757168270774128,
1291  1.1787994049306725, 1.1818820724946881, 1.1849648292156931,
1292  1.1880476745364656, 1.1911306078963526, 1.194213628731289,
1293  1.1972967364738196, 1.2003799305531206, 1.2034632103950214,
1294  1.206546575422025, 1.209630025053332, 1.2127135587048612,
1295  1.2157971757892707, 1.2188808757159835, 1.2219646578912058,
1296  1.2250485217179534, 1.2281324665960707, 1.231216491922257,
1297  1.2343005970900864, 1.2373847814900338, 1.2404690445094946,
1298  1.2435533855328118, 1.2466378039412964, 1.2497222991132528,
1299  1.2528068704240023, 1.2558915172459055, 1.2589762389483887,
1300  1.2620610348979655, 1.265145904458263, 1.268230846990045,
1301  1.2713158618512368, 1.27440094839695, 1.2774861059795064,
1302  1.2805713339484646, 1.2836566316506417, 1.286741998430143,
1303  1.2898274336283824, 1.292912936584111, 1.295998506633441,
1304  1.299084143109872, 1.3021698453443156, 1.3052556126651222,
1305  1.3083414443981063, 1.3114273398665721, 1.3145132983913408,
1306  1.3175993192907758, 1.3206854018808087, 1.3237715454749663,
1307  1.3268577493843976, 1.3299440129178983, 1.3330303353819408,
1308  1.3361167160806975, 1.33920315431607, 1.342289649387715,
1309  1.3453762005930718, 1.34846280722739, 1.3515494685837555,
1310  1.3546361839531185, 1.3577229526243213, 1.3608097738841256,
1311  1.3638966470172398, 1.366983571306347, 1.370070546032133,
1312  1.3731575704733139, 1.3762446439066645, 1.379331765607045,
1313  1.3824189348474314, 1.3855061508989417, 1.388593413030866,
1314  1.3916807205106922, 1.3947680726041385, 1.3978554685751772,
1315  1.4009429076860678, 1.4040303891973824, 1.4071179123680362,
1316  1.4102054764553156, 1.4132930807149071, 1.4163807244009277,
1317  1.4194684067659513, 1.4225561270610403, 1.425643884535773,
1318  1.4287316784382749, 1.4318195080152447, 1.4349073725119876,
1319  1.4379952711724417, 1.4410832032392094, 1.4441711679535851,
1320  1.4472591645555866, 1.4503471922839841, 1.453435250376329,
1321  1.4565233380689855, 1.4596114545971586, 1.4626995991949252,
1322  1.4657877710952634, 1.468875969530083, 1.4719641937302546,
1323  1.4750524429256404, 1.4781407163451246, 1.481229013216642,
1324  1.4843173327672103, 1.4874056742229587, 1.490494036809159,
1325  1.4935824197502554, 1.4966708222698952, 1.499759243590959,
1326  1.502847682935591, 1.5059361395252298, 1.5090246125806384,
1327  1.512113101321935, 1.5152016049686239, 1.5182901227396248,
1328  1.5213786538533045, 1.524467197527508, 1.527555752979587,
1329  1.5306443194264325, 1.533732896084505, 1.536821482169865,
1330  1.539910076898203, 1.5429986794848713, 1.5460872891449153,
1331  1.5491759050931018, 1.5522645265439523, 1.5553531527117719,
1332  1.558441782810682, 1.561530416054649, 1.5646190516575167,
1333  1.567707688833036, 1.5707963267948966 };
1334 
1339 static const double geographic[] = { 0.0,
1340  0.0030886379618605825, 0.006177275137379901, 0.0092659107402475,
1341  0.012354543984214532, 0.015443174083124565, 0.01853180025094438,
1342  0.021620421701794772, 0.0247090376499813, 0.027797647310025125,
1343  0.030886249896693734, 0.0339748446250317, 0.037063430710391455,
1344  0.040152007368464, 0.043240573815309616, 0.0463291292673886,
1345  0.049417672941591925, 0.05250620405527188, 0.05559472182627276,
1346  0.05868322547296149, 0.0617717142142582, 0.06486018726966679,
1347  0.06794864385930552, 0.0710370832039375, 0.07412550452500125,
1348  0.07721390704464104, 0.08030228998573746, 0.08339065257193778,
1349  0.08647899402768627, 0.0895673135782546, 0.0926556104497721,
1350  0.09574388386925607, 0.09883213306464193, 0.10192035726481347,
1351  0.10500855569963301, 0.10809672759997133, 0.11118487219773797,
1352  0.11427298872591114, 0.11736107641856755, 0.12044913451091256,
1353  0.1235371622393099, 0.12662515884131142, 0.12971312355568715,
1354  0.13280105562245464, 0.13588895428290887, 0.13897681877965185,
1355  0.14206464835662186, 0.1451524422591234, 0.14824019973385638,
1356  0.1513279200289453, 0.15441560239396898, 0.1575032460799894,
1357  0.16059085033958118, 0.16367841442686046, 0.16676593759751412,
1358  0.16985341910882873, 0.17294085821971925, 0.17602825419075818,
1359  0.17911560628420423, 0.18220291376403075, 0.18529017589595478,
1360  0.1883773919474653, 0.19146456118785166, 0.19455168288823224,
1361  0.1976387563215826, 0.20072578076276354, 0.20381275548854957,
1362  0.20689967977765683, 0.209986552910771, 0.21307337417057526,
1363  0.2161601428417781, 0.2192468582111411, 0.22233351956750647,
1364  0.22542012620182456, 0.22850667740718159, 0.23159317247882658,
1365  0.234679610714199, 0.23776599141295568, 0.24085231387699807,
1366  0.24393857741049915, 0.24702478131993025, 0.250110924914088,
1367  0.25319700750412083, 0.25628302840355577, 0.25936898692832455,
1368  0.2624548823967905, 0.26554071412977437, 0.26862648145058093,
1369  0.2717121836850245, 0.2747978201614555, 0.27788339021078556,
1370  0.2809688931665142, 0.2840543283647537, 0.28713969514425475,
1371  0.2902249928464323, 0.2933102208153901, 0.29639537839794666,
1372  0.2994804649436597, 0.3025654798048515, 0.3056504223366336,
1373  0.3087352918969311, 0.31182008784650794, 0.31490480954899097,
1374  0.3179894563708943, 0.3210740276816437, 0.3241585228536002,
1375  0.3272429412620848, 0.33032728228540187, 0.33341154530486283,
1376  0.33649572970480984, 0.33957983487263954, 0.3426638601988257,
1377  0.34574780507694325, 0.34883166890369055, 0.3519154510789131,
1378  0.3549991510056258, 0.35808276809003553, 0.3611663017415644,
1379  0.36424975137287147, 0.36733311639987526, 0.37041639624177586,
1380  0.37349959032107694, 0.37658269806360756, 0.3796657188985439,
1381  0.3827486522584309, 0.38583149757920354, 0.3889142543002084,
1382  0.39199692186422425, 0.3950794997174837, 0.39816198730969365,
1383  0.4012443840940563, 0.4043266895272892, 0.4074089030696463,
1384  0.41049102418493755, 0.41357305234054986, 0.4166549870074662,
1385  0.419736827660286, 0.4228185737772445, 0.42590022484023243,
1386  0.4289817803348154, 0.43206323975025296, 0.4351446025795178,
1387  0.4382258683193147, 0.4413070364700987, 0.44438810653609495,
1388  0.4474690780253156, 0.45054995044957946, 0.45363072332452903,
1389  0.45671139616964923, 0.4597919685082848, 0.4628724398676581,
1390  0.4659528097788865, 0.4690330777769999, 0.47211324340095756,
1391  0.4751933061936653, 0.4782732657019926, 0.4813531214767887,
1392  0.48443287307289956, 0.48751252004918405, 0.49059206196853006,
1393  0.49367149839787067, 0.4967508289082, 0.4998300530745889,
1394  0.5029091704761999, 0.5059881806963037, 0.5090670833222932,
1395  0.5121458779456998, 0.515224564162206, 0.5183031415716631,
1396  0.5213816097781034, 0.5244599683897553, 0.5275382170190575,
1397  0.5306163552826731, 0.533694382801503, 0.5367722992007001,
1398  0.5398501041096824, 0.542927797162146, 0.5460053779960794,
1399  0.549082846253775, 0.5521602015818429, 0.5552374436312231,
1400  0.558314572057198, 0.5613915865194048, 0.5644684866818472,
1401  0.567545272212908, 0.5706219427853598, 0.5736984980763777,
1402  0.57677493776755, 0.5798512615448891, 0.5829274690988434,
1403  0.5860035601243078, 0.589079534320634, 0.5921553913916412,
1404  0.5952311310456269, 0.5983067529953761, 0.6013822569581719,
1405  0.6044576426558057, 0.6075329098145854, 0.6106080581653462,
1406  0.6136830874434589, 0.6167579973888396, 0.6198327877459584,
1407  0.6229074582638479, 0.6259820086961115, 0.6290564388009326,
1408  0.632130748341082, 0.6352049370839259, 0.6382790048014341,
1409  0.6413529512701875, 0.644426776271385, 0.6475004795908512,
1410  0.6505740610190438, 0.6536475203510599, 0.6567208573866427,
1411  0.6597940719301885, 0.6628671637907525, 0.6659401327820553,
1412  0.669012978722489, 0.6720857014351223, 0.6751583007477069,
1413  0.6782307764926824, 0.6813031285071816, 0.684375356633036,
1414  0.6874474607167802, 0.6905194406096566, 0.6935912961676205,
1415  0.6966630272513432, 0.6997346337262175, 0.702806115462361,
1416  0.7058774723346197, 0.7089487042225724, 0.7120198110105327,
1417  0.7150907925875537, 0.7181616488474303, 0.7212323796887021,
1418  0.7243029850146564, 0.7273734647333301, 0.7304438187575129,
1419  0.7335140470047483, 0.7365841493973367, 0.7396541258623366,
1420  0.7427239763315661, 0.7457937007416041, 0.7488632990337925,
1421  0.7519327711542364, 0.7550021170538048, 0.7580713366881324,
1422  0.7611404300176188, 0.7642093970074293, 0.7672782376274956,
1423  0.7703469518525148, 0.7734155396619501, 0.7764840010400295,
1424  0.779552335975746, 0.7826205444628564, 0.7856886264998802,
1425  0.7887565820900994, 0.7918244112415559, 0.7948921139670508,
1426  0.7979596902841429, 0.8010271402151462, 0.8040944637871283,
1427  0.8071616610319086, 0.8102287319860549, 0.8132956766908815,
1428  0.816362495192447, 0.8194291875415499, 0.8224957537937274,
1429  0.8255621940092505, 0.8286285082531213, 0.8316946965950694,
1430  0.8347607591095485, 0.8378266958757314, 0.8408925069775065,
1431  0.8439581925034738, 0.8470237525469397, 0.8500891872059131,
1432  0.8531544965830998, 0.8562196807858983, 0.8592847399263936,
1433  0.8623496741213532, 0.8654144834922204, 0.8684791681651088,
1434  0.8715437282707976, 0.8746081639447237, 0.8776724753269767,
1435  0.8807366625622927, 0.8838007258000469, 0.8868646651942474,
1436  0.8899284809035285, 0.8929921730911432, 0.8960557419249562,
1437  0.8991191875774363, 0.9021825102256493, 0.9052457100512501,
1438  0.9083087872404745, 0.9113717419841312, 0.9144345744775944,
1439  0.9174972849207942, 0.9205598735182088, 0.923622340478856,
1440  0.9266846860162834, 0.9297469103485603, 0.9328090136982676,
1441  0.9358709962924899, 0.9389328583628043, 0.9419946001452715,
1442  0.945056221880426, 0.9481177238132663, 0.9511791061932441,
1443  0.9542403692742544, 0.9573015133146252, 0.9603625385771062,
1444  0.9634234453288585, 0.9664842338414438, 0.969544904390813,
1445  0.9726054572572946, 0.9756658927255841, 0.9787262110847318,
1446  0.9817864126281313, 0.9848464976535075, 0.9879064664629048,
1447  0.9909663193626747, 0.9940260566634633, 0.9970856786801994,
1448  1.000145185732081, 1.0032045781425638, 1.0062638562393464,
1449  1.0093230203543588, 1.0123820708237492, 1.0154410079878686,
1450  1.0184998321912604, 1.0215585437826438, 1.0246171431149014,
1451  1.0276756305450656, 1.0307340064343031, 1.0337922711479026,
1452  1.036850425055258, 1.039908468529856, 1.04296640194926,
1453  1.0460242256950962, 1.049081940153038, 1.0521395457127913,
1454  1.0551970427680788, 1.0582544317166251, 1.061311712960141,
1455  1.0643688869043078, 1.0674259539587614, 1.0704829145370764,
1456  1.0735397690567505, 1.0765965179391872, 1.0796531616096812,
1457  1.0827097004973996, 1.085766135035368, 1.088822465660451,
1458  1.0918786928133375, 1.0949348169385227, 1.097990838484291,
1459  1.101046757902699, 1.104102575649558, 1.1071582921844167,
1460  1.1102139079705429, 1.1132694234749065, 1.1163248391681613,
1461  1.1193801555246266, 1.12243537302227, 1.1254904921426878,
1462  1.1285455133710884, 1.1316004371962716, 1.1346552641106122,
1463  1.137709994610039, 1.1407646291940186, 1.143819168365533,
1464  1.1468736126310646, 1.149927962500573, 1.1529822184874776,
1465  1.1560363811086392, 1.1590904508843376, 1.162144428338255,
1466  1.165198313997453, 1.1682521083923565, 1.171305812056729,
1467  1.1743594255276575, 1.1774129493455274, 1.1804663840540066,
1468  1.1835197302000213, 1.1865729883337375, 1.1896261590085404,
1469  1.1926792427810122, 1.1957322402109125, 1.1987851518611565,
1470  1.201837978297795, 1.204890720089991, 1.207943377810001,
1471  1.2109959520331517, 1.2140484433378194, 1.217100852305408,
1472  1.2201531795203273, 1.2232054255699714, 1.226257591044696,
1473  1.2293096765377982, 1.232361682645492, 1.235413609966888,
1474  1.2384654591039699, 1.241517230661573, 1.2445689252473608,
1475  1.2476205434718035, 1.2506720859481537, 1.2537235532924256,
1476  1.2567749461233706, 1.259826265062455, 1.2628775107338368,
1477  1.2659286837643429, 1.2689797847834456, 1.2720308144232386,
1478  1.2750817733184152, 1.2781326621062439, 1.2811834814265437,
1479  1.2842342319216635, 1.2872849142364546, 1.2903355290182508,
1480  1.2933860769168408, 1.2964365585844468, 1.2994869746756996,
1481  1.3025373258476145, 1.3055876127595665, 1.308637836073268,
1482  1.3116879964527417, 1.3147380945642977, 1.31778813107651,
1483  1.3208381066601895, 1.3238880219883615, 1.3269378777362395,
1484  1.3299876745812016, 1.3330374132027645, 1.3360870942825596,
1485  1.339136718504307, 1.3421862865537921, 1.3452357991188382,
1486  1.3482852568892825, 1.351334660556952, 1.3543840108156358,
1487  1.3574333083610615, 1.3604825538908687, 1.3635317481045846,
1488  1.366580891703597, 1.3696299853911307, 1.3726790298722187,
1489  1.37572802585368, 1.3787769740440912, 1.381825875153762,
1490  1.3848747298947086, 1.3879235389806277, 1.3909723031268717,
1491  1.3940210230504206, 1.3970696994698577, 1.4001183331053422,
1492  1.4031669246785838, 1.4062154749128157, 1.4092639845327688,
1493  1.4123124542646455, 1.415360884836092, 1.418409276976174,
1494  1.4214576314153478, 1.424505948885436, 1.4275542301195985,
1495  1.4306024758523086, 1.4336506868193237, 1.4366988637576603,
1496  1.4397470074055667, 1.442795118502496, 1.4458431977890798,
1497  1.4488912460070997, 1.4519392638994637, 1.454987252210175,
1498  1.4580352116843092, 1.4610831430679836, 1.464131047108333,
1499  1.4671789245534805, 1.4702267761525125, 1.4732746026554489,
1500  1.4763224048132186, 1.4793701833776305, 1.4824179391013466,
1501  1.4854656727378561, 1.4885133850414456, 1.491561076767174,
1502  1.4946087486708444, 1.4976564015089762, 1.5007040360387784,
1503  1.5037516530181227, 1.506799253205514, 1.5098468373600653,
1504  1.5128944062414693, 1.51594196060997, 1.5189895012263372,
1505  1.522037028851837, 1.525084544248206, 1.5281320481776215,
1506  1.531179541402677, 1.5342270246863512, 1.537274498791984,
1507  1.5403219644832453, 1.5433694225241104, 1.5464168736788304,
1508  1.5494643187119053, 1.5525117583880574, 1.555559193472201,
1509  1.558606624729418, 1.5616540529249268, 1.5647014788240585,
1510  1.5677489031922254, 1.5707963267948966 };
1511 
1512 
1520 inline double GeoTessUtils::getGeoCentricLatitude(const double& lat)
1521 {
1522  // convert lat from geographic to geocentric latitude.
1523 
1524  if (!approximateLatitudes)
1525  return atan((1-EARTH_E) * tan(lat));
1526 
1527  if (lat >= PI/2)
1528  return PI/2;
1529  else if (lat <= -PI/2)
1530  return -PI/2;
1531  else if (lat < 0)
1532  {
1533  double tmp = -lat / (PI / 2 / (513 - 1));
1534  int i = (int) tmp;
1535  return -geocentric[i] - (tmp - i)
1536  * (geocentric[i + 1] - geocentric[i]);
1537  }
1538  else
1539  {
1540  double tmp = lat / (PI / 2 / (513 - 1));
1541  int i = (int) tmp;
1542  return geocentric[i] + (tmp - i)
1543  * (geocentric[i + 1] - geocentric[i]);
1544  }
1545 }
1546 
1554 inline double GeoTessUtils::getGeoGraphicLatitude(const double& lat)
1555 {
1556  // the constant 0.9933 is (1-e*e) where e is the eccentricity of the
1557  // earth as defined by the GRS80 ellipsoid.
1558 
1559  if (!approximateLatitudes)
1560  return atan(tan(lat) / (1-EARTH_E));
1561 
1562  if (lat >= PI/2)
1563  return PI/2;
1564  else if (lat <= -PI/2)
1565  return -PI/2;
1566  else if (lat < 0)
1567  {
1568  double tmp = -lat / (PI / 2 / (513 - 1));
1569  int i = (int) tmp;
1570  return -geographic[i] - (tmp - i)
1571  * (geographic[i + 1] - geographic[i]);
1572  }
1573  else
1574  {
1575  double tmp = lat / (PI / 2 / (513 - 1));
1576  int i = (int) tmp;
1577  return geographic[i] + (tmp - i)
1578  * (geographic[i + 1] - geographic[i]);
1579  }
1580 }
1581 
1582 } // end namespace geotess
1583 
1584 #endif // GEOTESSUTILS_OBJECT_H