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
GeoTessPosition.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 GEOTESSPOSITION_OBJECT_H
37 #define GEOTESSPOSITION_OBJECT_H
38 
39 // **** _SYSTEM INCLUDES_ ******************************************************
40 
41 #include <iostream>
42 #include <string>
43 #include <fstream>
44 #include <vector>
45 #include <sstream>
46 
47 // use standard library objects
48 using namespace std;
49 
50 // **** _LOCAL INCLUDES_ *******************************************************
51 
52 #include "CPPUtils.h"
53 #include "GeoTessUtils.h"
54 #include "GeoTessModel.h"
55 #include "GeoTessGrid.h"
56 #include "GeoTessMetaData.h"
57 #include "CpuTimer.h"
58 #include "Profile.h"
59 
60 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
61 
62 namespace geotess {
63 
64 // **** _FORWARD REFERENCES_ ***************************************************
65 
66 class InterpolatorType;
67 class Profile;
68 
69 // **** _CLASS DEFINITION_ *****************************************************
70 
101 {
102 private:
103 
107  int refCount;
108 
114  int* maxTessLevel;
115 
121  int* tessLevels;
122 
131  int* triangle;
132 
138  double errorValue;
139 
150  void updatePosition2D(int layerid, const double* const uVector);
151 
169  void checkTessellation(const int& tid)
170  {
171  if (triangle[tid] < 0)
172  {
173  tessLevels[tid] = 0;
174  triangle[tid] = grid.getTriangle(tid, 0, 0);
175  getContainingTriangle(tid);
176  update2D(tid);
177  }
178  }
179 
187  void updateRadius(int lid, double rad)
188  {
189  if ((radius < 0.) || (rad != radius) || (lid != layerId))
190  {
191  radius = rad;
192  layerId = lid;
193  tessid = layerTessIds[lid];
194  checkTessellation(tessid);
195  clearRadialCoefficients();
196  }
197  }
198 
199  void clearRadialCoefficients()
200  {
201  for (int i=0; i<(int)radialIndexes.size(); ++i)
202  {
203  radialIndexes[i].clear();
204  radialCoefficients[i].clear();
205  }
206  }
207 
214  void updateRadialCoefficients()
215  {
216  // if radial interpolation coefficients have already been computed
217  // do nothing.
218  if (radialIndexes[0].size() == 0)
219  {
220  vector<int>& v = vertices[tessid];
221  for (int i = 0; i < (int)v.size(); ++i)
222  modlProfiles[v[i]][layerId]->setInterpolationCoefficients(radialInterpolatorType,
223  radialIndexes[i], radialCoefficients[i], radius, radiusOutOfRangeAllowed);
224  }
225  }
226 
231  static const double TWALK_TOLERANCE;
232 
243  void getContainingTriangle(int tid);
244 
253  int biggerTriangle(int t1, int t2)
254  {
255  const int* tv = grid.getTriangleVertexIndexes(t1);
256  double dot1 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
257  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
258  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
259 
260  tv = grid.getTriangleVertexIndexes(t2);
261  double dot2 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
262  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
263  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
264 
265  return dot2 > dot1 ? t1 : t2;
266 
267  }
268 
269 protected:
270 
272 
276  double radius;
277 
281  double earthRadius;
282 
290  vector<double> layerRadii;
291 
295  int layerId;
296 
300  int tessid;
301 
309  vector< vector< int> > vertices;
310 
316  vector< vector< double> > linearCoefficients;
317 
324  vector< vector< double> > nnCoefficients;
325 
329  vector< vector< double> >& hCoefficients;
330 
345  vector<vector<int> > radialIndexes;
346 
364  vector<vector<double> > radialCoefficients;
365 
366 
371  const InterpolatorType& radialInterpolatorType;
372 
377  GeoTessModel* model;
378 
382  const GeoTessGrid& grid;
383 
387  Profile *** modlProfiles;
388  double const* const* gridVertices;
389  int const* const* gridTriangles;
390  int const* const* gridNeighbors;
391  double const* const* const* gridEdges;
392  const int* layerTessIds;
393  int nLayers;
394 
409  bool radiusOutOfRangeAllowed;
410 
414  double unitVector[3];
415 
419  int getTriangle(int tid)
420  { checkTessellation(tid); return triangle[tid]; };
421 
426  virtual void update2D(int tid) = ABSTRACT;
427 
431  GeoTessPosition(GeoTessModel* model, const InterpolatorType& radialType,
432  vector< vector<double> >& c);
433 
435 
436 public:
437 
446  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model);
447 
462  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
463  const InterpolatorType& horizontalType);
464 
478  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
479  const InterpolatorType& horizontalType, const InterpolatorType& radialType);
480 
484  virtual ~GeoTessPosition();
485 
492  virtual const InterpolatorType& getInterpolatorType() const = ABSTRACT;
493 
499  virtual double getValue(int attribute);
500 
519  bool setModel(GeoTessModel* newModel);
520 
525  bool noEmptyProfiles();
526 
547  void set(double lat, double lon, double depth)
548  {
549  double uVector[3] = {0.0, 0.0, 0.0};
550  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
551  double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth;
552  set(uVector, newRadius);
553  }
554 
567  void set(const double* const uVector, const double& newRadius)
568  {
569  updatePosition2D(nLayers - 1, uVector);
570 
571  int lid = getLayerId(newRadius);
572 
573  updatePosition2D(lid, uVector);
574  updateRadius(lid, newRadius);
575  }
576 
594  void set(int layid, double lat, double lon, double depth)
595  {
596  if (layid < 0)
597  set(lat, lon, depth);
598  else
599  {
600  double uVector[3];
601  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
602  updatePosition2D(layid, uVector);
603  updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth);
604  }
605  }
606 
617  void set(int layid, const double* const uVector, double rad)
618  {
619  if (layid < 0)
620  set(uVector, rad);
621  else
622  {
623  updatePosition2D(layid, uVector);
624  if (rad >= 0.0) updateRadius(layid, rad);
625  }
626  }
627 
635  void setTop(int layid, const double* const uVector)
636  {
637  updatePosition2D(layid, uVector);
638  updateRadius(layid, getRadiusTop(layid));
639  }
640 
649  void setBottom(int layid, const double* const uVector)
650  {
651  updatePosition2D(layid, uVector);
652  updateRadius(layid, getRadiusBottom(layid));
653  }
654 
662  void setRadius(int layid, double rad)
663  {
664  if (tessid < 0)
665  {
666  ostringstream os;
667  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
668  << "Geographic position has not been specified." << endl;
669  throw GeoTessException(os, __FILE__, __LINE__, 3001);
670  }
671  updateRadius(layid, rad);
672  }
673 
680  void setRadius(double rad)
681  {
682  if (tessid < 0)
683  if (tessid < 0)
684  {
685  ostringstream os;
686  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
687  << "Geographic position has not been specified." << endl;
688  throw GeoTessException(os, __FILE__, __LINE__, 3002);
689  }
690  updateRadius(getLayerId(rad), rad);
691  }
692 
704  void setDepth(int layer, double depth)
705  {
706  setRadius(layer, getEarthRadius()-depth);
707  }
708 
715  void setDepth(double depth)
716  {
717  setRadius(getEarthRadius()-depth);
718  }
719 
725  void setTop(int layid)
726  {
727  if (tessid < 0)
728  {
729  ostringstream os;
730  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
731  << "Geographic position has not been specified." << endl;
732  throw GeoTessException(os, __FILE__, __LINE__, 3003);
733  }
734  tessid = layerTessIds[layid];
735  checkTessellation(tessid);
736  updateRadius(layid, getRadiusTop(layid));
737  }
738 
745  void setBottom(int layid)
746  {
747  if (tessid < 0)
748  {
749  ostringstream os;
750  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
751  << "Geographic position has not been specified." << endl;
752  throw GeoTessException(os, __FILE__, __LINE__, 3004);
753  }
754  tessid = layerTessIds[layid];
755  checkTessellation(tessid);
756  updateRadius(layid, getRadiusBottom(layid));
757  }
758 
766  double getRadiusTop(int layid);
767 
774  double getRadiusBottom(int layid);
775 
781  double getEarthRadius()
782  {
783  if (earthRadius < 0.)
784  earthRadius = GeoTessUtils::getEarthRadius(unitVector);
785  return earthRadius;
786  }
787 
794  double* getVector() { return unitVector; };
795 
802  void copyVector(double* u)
803  { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; };
804 
810  int getTriangle() { return triangle[tessid]; };
811 
815  int getNVertices() { return vertices[tessid].size(); };
816 
824  const vector<int>& getVertices() const { return vertices[tessid]; };
825 
829  int getIndexOfClosestVertex() const;
830 
835  const double* getClosestVertex() const
836  {
837  return grid.getVertex(getIndexOfClosestVertex());
838  }
839 
846  int getVertex(int index)
847  { return vertices[tessid][index]; }
848 
854  void getCoefficients(map<int, double>& coefficients)
855  {
856  coefficients.clear();
857  vector<int>& vtx = vertices[tessid];
858  vector<double>& hc = hCoefficients[tessid];
859  for (int i = 0; i < (int) vtx.size(); ++i)
860  modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]);
861  }
862 
872  void setMaxTessLevel(int layid, int maxTess)
873  {
874  maxTessLevel[layerTessIds[layid]] = maxTess;
875  triangle[layerTessIds[layid]] = -1;
876  checkTessellation(tessid);
877  }
878 
888  int getMaxTessLevel(int layid)
889  { return maxTessLevel[layerTessIds[layid]]; }
890 
897  int getTessLevel() const { return tessLevels[tessid]; };
898 
906  int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; }
907 
913  double getRadiusTop()
914  { return getRadiusTop(layerId); };
915 
921  double getRadiusBottom()
922  { return getRadiusBottom(layerId); };
923 
929  double getDepthTop()
930  {
931  return getEarthRadius() - getRadiusTop(layerId);
932  }
933 
939  double getDepthBottom()
940  {
941  return getEarthRadius() - getRadiusBottom(layerId);
942  }
943 
950  double getDepthTop(int layid)
951  {
952  return getEarthRadius() - getRadiusTop(layid);
953  }
954 
961  double getDepthBottom(int layid)
962  {
963  return getEarthRadius() - getRadiusBottom(layid);
964  }
965 
972  double getLayerThickness(int layid)
973  {
974  return getRadiusTop(layid) - getRadiusBottom(layid);
975  }
976 
982  double getLayerThickness()
983  {
984  return getRadiusTop() - getRadiusBottom();
985  }
986 
992  double getRadius() { return radius; };
993 
999  double getDepth()
1000  { return getEarthRadius() - radius; };
1001 
1005  GeoTessModel* getModel() { return model; }
1006 
1010  int getTessID() { return tessid; };
1011 
1022  int getLayerId(double rad)
1023  {
1024  for (int i=0; i<nLayers; ++i)
1025  if (rad <= getRadiusTop(i))
1026  return i;
1027 
1028  for (int i=nLayers-1; i>=0; --i)
1029  if (getLayerThickness(i) > 0)
1030  return i;
1031 
1032  return nLayers-1;
1033  };
1034 
1038  int getLayerId() { return layerId; };
1039 
1043  string toString();
1044 
1050  double getErrorValue()
1051  {
1052  return errorValue;
1053  }
1054 
1060  void setErrorValue(double errVal)
1061  {
1062  errorValue = errVal;
1063  }
1064 
1072  int getVertexIndex()
1073  {
1074  vector<int>& vtid = vertices[tessid];
1075  vector<double>& htid = hCoefficients[tessid];
1076  for (int v = 0; v < (int) vtid.size(); ++v)
1077  if (htid[v] > 0.999999999)
1078  return vtid[v];
1079  return -1;
1080  }
1081 
1085  void getWeights(map<int, double>& weights, double dkm)
1086  {
1087  vector<int>& vtx = vertices[tessid];
1088  vector<double>& htid = hCoefficients[tessid];
1089  for (int i = 0; i < (int) vtx.size(); ++i)
1090  modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]);
1091  }
1092 
1100  const vector<double>& getHorizontalCoefficients() const
1101  {
1102  return hCoefficients[tessid];
1103  }
1104 
1113  double getHorizontalCoefficient(int index) const
1114  {
1115  return hCoefficients[tessid][index];
1116  }
1117 
1132  bool isRadiusOutOfRangeAllowed()
1133  {
1134  return radiusOutOfRangeAllowed;
1135  }
1136 
1151  void setRadiusOutOfRangeAllowed(bool allowed)
1152  {
1153  if (allowed != radiusOutOfRangeAllowed)
1154  clearRadialCoefficients();
1155 
1156  radiusOutOfRangeAllowed = allowed;
1157  }
1158 
1159  string getGridId()
1160  {
1161  return grid.getGridID();
1162  }
1163 
1167  void addReference() { ++refCount; }
1168 
1172  void removeReference()
1173  {
1174  if (isNotReferenced())
1175  {
1176  ostringstream os;
1177  os << endl << "ERROR in Polygon::removeReference" << endl
1178  << "Reference count (" << refCount << ") is already zero." << endl;
1179  throw GeoTessException(os, __FILE__, __LINE__, 3005);
1180  }
1181 
1182  --refCount;
1183  }
1184 
1185  int getReferenceCount()
1186  {
1187  return refCount;
1188  }
1189 
1193  bool isNotReferenced() { return refCount == 0; }
1194 
1195 }; // end class GeoTessModel
1196 
1197 } // end namespace geotess
1198 
1199 #endif // GEOTESSPOSITION_OBJECT_H