GeoTessCPP  2.6.1
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 "GeoTessProfile.h"
59 #include "GeoTessData.h"
60 
61 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
62 
63 namespace geotess {
64 
65 // **** _FORWARD REFERENCES_ ***************************************************
66 
67 class GeoTessInterpolatorType;
68 class GeoTessProfile;
69 
70 // **** _CLASS DEFINITION_ *****************************************************
71 
102 {
103 private:
104 
108  int refCount;
109 
115  int* maxTessLevel;
116 
122  int* tessLevels;
123 
132  int* triangle;
133 
139  double errorValue;
140 
151  void updatePosition2D(int layerid, const double* const uVector);
152 
170  void checkTessellation(const int& tid)
171  {
172  if (triangle[tid] < 0)
173  {
174  tessLevels[tid] = 0;
175  triangle[tid] = grid.getTriangle(tid, 0, 0);
176  getContainingTriangle(tid);
177  update2D(tid);
178  }
179  }
180 
188  void updateRadius(int lid, double rad)
189  {
190  if ((radius < 0.) || (rad != radius) || (lid != layerId))
191  {
192  radius = rad;
193  layerId = lid;
194  tessid = layerTessIds[lid];
195  checkTessellation(tessid);
196  clearRadialCoefficients();
197  }
198  }
199 
200  void clearRadialCoefficients()
201  {
202  for (int i=0; i<(int)radialIndexes.size(); ++i)
203  {
204  radialIndexes[i].clear();
205  radialCoefficients[i].clear();
206  }
207  }
208 
215  void updateRadialCoefficients()
216  {
217  // make sure dimensions of radialIndexes and radialCoefficients
218  // are at least as big as the number of vertices involved in interpolation.
219  if (radialIndexes.size() < vertices[tessid].size())
220  {
221  radialIndexes.resize(vertices[tessid].size());
222  radialCoefficients.resize(vertices[tessid].size());
223  }
224 
225  // if radial interpolation coefficients have already been computed
226  // do nothing.
227  if (radialIndexes[0].size() == 0)
228  {
229  vector<int>& v = vertices[tessid];
230  for (int i = 0; i < (int)v.size(); ++i)
231  modlProfiles[v[i]][layerId]->setInterpolationCoefficients(radialInterpolatorType,
232  radialIndexes[i], radialCoefficients[i], radius, radiusOutOfRangeAllowed);
233  }
234  }
235 
240  static const double TWALK_TOLERANCE;
241 
252  void getContainingTriangle(int tid);
253 
262  int biggerTriangle(int t1, int t2)
263  {
264  const int* tv = grid.getTriangleVertexIndexes(t1);
265  double dot1 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
266  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
267  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
268 
269  tv = grid.getTriangleVertexIndexes(t2);
270  double dot2 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
271  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
272  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
273 
274  return dot2 > dot1 ? t1 : t2;
275 
276  }
277 
278 protected:
279 
281 
285  double radius;
286 
290  double earthRadius;
291 
299  vector<double> layerRadii;
300 
304  int layerId;
305 
309  int tessid;
310 
318  vector< vector< int> > vertices;
319 
325  vector< vector< double> > linearCoefficients;
326 
333  //vector< vector< double> > nnCoefficients;
334 
338  vector< vector< double> > hCoefficients;
339 
354  vector<vector<int> > radialIndexes;
355 
373  vector<vector<double> > radialCoefficients;
374 
375 
380  const GeoTessInterpolatorType& radialInterpolatorType;
381 
386  GeoTessModel* model;
387 
391  GeoTessGrid& grid;
392 
396  GeoTessProfile *** modlProfiles;
397  double const* const* gridVertices;
398  int const* const* gridTriangles;
399  int const* gridDescendants;
400  const vector<vector<Edge*> >& gridEdges;
401  const int* layerTessIds;
402  int nLayers;
403 
418  bool radiusOutOfRangeAllowed;
419 
423  double unitVector[3];
424 
428  int getTriangle(int tid)
429  { checkTessellation(tid); return triangle[tid]; };
430 
435  virtual void update2D(int tid) = ABSTRACT;
436 
440  GeoTessPosition(GeoTessModel* model, const GeoTessInterpolatorType& radialType);
441 
445  long memory()
446  {
447  long m = 0;
448 
449  // memory for int* triangle, tessLevels and maxTessLevel.
450  m += (long)(grid.getNTessellations() * 3 * sizeof(int));
451 
452  // vector<double> layerRadii;
453  m += (long)(layerRadii.capacity() * sizeof(double));
454 
455  // vector< vector< int> > vertices;
456  m += (long)(vertices.capacity()*sizeof(vector<int>));
457  for (int i=0; i<(int)vertices.size(); ++i)
458  m += (long)(vertices[i].capacity()*sizeof(int));
459 
460  // vector< vector< double> > linearCoefficients;
461  m += (long)(linearCoefficients.capacity()*sizeof(vector<double>));
462  for (int i=0; i<(int)linearCoefficients.size(); ++i)
463  m += (long)(linearCoefficients[i].capacity()*sizeof(double));
464 
465  // vector< vector< double> > hCoefficients;
466  m += (long)(hCoefficients.capacity()*sizeof(vector<double>));
467  for (int i=0; i<(int)hCoefficients.size(); ++i)
468  m += (long)(hCoefficients[i].capacity()*sizeof(double));
469 
470  // vector<vector<int> > radialIndexes;
471  m += (long)(radialIndexes.capacity()*sizeof(vector<int>));
472  for (int i=0; i<(int)radialIndexes.size(); ++i)
473  m += (long)(radialIndexes[i].capacity()*sizeof(int));
474 
475  // vector<vector<double> > radialCoefficients;
476  m += (long)(radialCoefficients.capacity()*sizeof(vector<double>));
477  for (int i=0; i<(int)radialCoefficients.size(); ++i)
478  m += (long)(radialCoefficients[i].capacity()*sizeof(double));
479 
480  return m;
481  }
482 
484 
485 public:
486 
497 
513  const GeoTessInterpolatorType& horizontalType);
514 
529  const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType);
530 
534  virtual ~GeoTessPosition();
535 
543 
548  virtual long getMemory() = ABSTRACT;
549 
556  virtual double getValue(int attribute);
557 
578  void setModel(GeoTessModel* newModel);
579 
585 
606  void set(double lat, double lon, double depth)
607  {
608  double uVector[3] = {0.0, 0.0, 0.0};
609  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
610  double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth;
611  set(uVector, newRadius);
612  }
613 
626  void set(const double* const uVector, const double& newRadius)
627  {
628  updatePosition2D(nLayers - 1, uVector);
629 
630  int lid = getLayerId(newRadius);
631 
632  updatePosition2D(lid, uVector);
633  updateRadius(lid, newRadius);
634  }
635 
653  void set(int layid, double lat, double lon, double depth)
654  {
655  if (layid < 0)
656  set(lat, lon, depth);
657  else
658  {
659  double uVector[3];
660  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
661  updatePosition2D(layid, uVector);
662  updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth);
663  }
664  }
665 
676  void set(int layid, const double* const uVector, double rad)
677  {
678  if (layid < 0)
679  set(uVector, rad);
680  else
681  {
682  updatePosition2D(layid, uVector);
683  if (rad >= 0.0) updateRadius(layid, rad);
684  }
685  }
686 
694  void setTop(int layid, const double* const uVector)
695  {
696  updatePosition2D(layid, uVector);
697  updateRadius(layid, getRadiusTop(layid));
698  }
699 
708  void setBottom(int layid, const double* const uVector)
709  {
710  updatePosition2D(layid, uVector);
711  updateRadius(layid, getRadiusBottom(layid));
712  }
713 
721  void setRadius(int layid, double rad)
722  {
723  if (tessid < 0)
724  {
725  ostringstream os;
726  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
727  << "Geographic position has not been specified." << endl;
728  throw GeoTessException(os, __FILE__, __LINE__, 3001);
729  }
730  updateRadius(layid, rad);
731  }
732 
739  void setRadius(double rad)
740  {
741  if (tessid < 0)
742  if (tessid < 0)
743  {
744  ostringstream os;
745  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
746  << "Geographic position has not been specified." << endl;
747  throw GeoTessException(os, __FILE__, __LINE__, 3002);
748  }
749  updateRadius(getLayerId(rad), rad);
750  }
751 
763  void setDepth(int layer, double depth)
764  {
765  setRadius(layer, getEarthRadius()-depth);
766  }
767 
774  void setDepth(double depth)
775  {
776  setRadius(getEarthRadius()-depth);
777  }
778 
784  void setTop(int layid)
785  {
786  if (tessid < 0)
787  {
788  ostringstream os;
789  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
790  << "Geographic position has not been specified." << endl;
791  throw GeoTessException(os, __FILE__, __LINE__, 3003);
792  }
793  tessid = layerTessIds[layid];
794  checkTessellation(tessid);
795  updateRadius(layid, getRadiusTop(layid));
796  }
797 
804  void setBottom(int layid)
805  {
806  if (tessid < 0)
807  {
808  ostringstream os;
809  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
810  << "Geographic position has not been specified." << endl;
811  throw GeoTessException(os, __FILE__, __LINE__, 3004);
812  }
813  tessid = layerTessIds[layid];
814  checkTessellation(tessid);
815  updateRadius(layid, getRadiusBottom(layid));
816  }
817 
825  double getRadiusTop(int layid);
826 
833  double getRadiusBottom(int layid);
834 
840  double getEarthRadius()
841  {
842  if (earthRadius < 0.)
843  earthRadius = GeoTessUtils::getEarthRadius(unitVector);
844  return earthRadius;
845  }
846 
853  double* getVector() { return unitVector; };
854 
861  void copyVector(double* u)
862  { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; };
863 
869  int getTriangle() { return triangle[tessid]; };
870 
875  int getNVertices() { return vertices[tessid].size(); };
876 
884  const vector<int>& getVertices() const { return vertices[tessid]; };
885 
892 
899  const double* getClosestVertex() const
900  {
901  return grid.getVertex(getIndexOfClosestVertex());
902  }
903 
910  int getVertex(int index)
911  { return vertices[tessid][index]; }
912 
918  void getCoefficients(map<int, double>& coefficients)
919  {
920  coefficients.clear();
921  vector<int>& vtx = vertices[tessid];
922  vector<double>& hc = hCoefficients[tessid];
923  for (int i = 0; i < (int) vtx.size(); ++i)
924  modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]);
925  }
926 
936  void setMaxTessLevel(int layid, int maxTess)
937  {
938  maxTessLevel[layerTessIds[layid]] = maxTess;
939  triangle[layerTessIds[layid]] = -1;
940  checkTessellation(tessid);
941  }
942 
952  int getMaxTessLevel(int layid)
953  { return maxTessLevel[layerTessIds[layid]]; }
954 
961  int getTessLevel() const { return tessLevels[tessid]; };
962 
971  int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; }
972 
978  double getRadiusTop()
979  { return getRadiusTop(layerId); };
980 
987  { return getRadiusBottom(layerId); };
988 
994  double getDepthTop()
995  {
996  return getEarthRadius() - getRadiusTop(layerId);
997  }
998 
1005  {
1006  return getEarthRadius() - getRadiusBottom(layerId);
1007  }
1008 
1015  double getDepthTop(int layid)
1016  {
1017  return getEarthRadius() - getRadiusTop(layid);
1018  }
1019 
1026  double getDepthBottom(int layid)
1027  {
1028  return getEarthRadius() - getRadiusBottom(layid);
1029  }
1030 
1037  double getLayerThickness(int layid)
1038  {
1039  return getRadiusTop(layid) - getRadiusBottom(layid);
1040  }
1041 
1048  {
1049  return getRadiusTop() - getRadiusBottom();
1050  }
1051 
1057  double getRadius() { return radius; };
1058 
1064  double getDepth()
1065  { return getEarthRadius() - radius; };
1066 
1070  GeoTessModel* getModel() { return model; }
1071 
1075  int getTessID() { return tessid; };
1076 
1087  int getLayerId(double rad)
1088  {
1089  for (int i=0; i<nLayers; ++i)
1090  if (rad <= getRadiusTop(i))
1091  return i;
1092 
1093  for (int i=nLayers-1; i>=0; --i)
1094  if (getLayerThickness(i) > 0)
1095  return i;
1096 
1097  return nLayers-1;
1098  };
1099 
1103  int getLayerId() { return layerId; };
1104 
1109  string toString();
1110 
1117  double getErrorValue()
1118  {
1119  return errorValue;
1120  }
1121 
1128  void setErrorValue(double errVal)
1129  {
1130  errorValue = errVal;
1131  }
1132 
1141  {
1142  vector<int>& vtid = vertices[tessid];
1143  vector<double>& htid = hCoefficients[tessid];
1144  for (int v = 0; v < (int) vtid.size(); ++v)
1145  if (htid[v] > 0.999999999)
1146  return vtid[v];
1147  return -1;
1148  }
1149 
1174  void getWeights(map<int, double>& weights, double dkm)
1175  {
1176  vector<int>& vtx = vertices[tessid];
1177  vector<double>& htid = hCoefficients[tessid];
1178  model->getPointMap();
1179  for (int i = 0; i < (int) vtx.size(); ++i)
1180  modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]);
1181  }
1182 
1190  const vector<double>& getHorizontalCoefficients() const
1191  {
1192  return hCoefficients[tessid];
1193  }
1194 
1203  double getHorizontalCoefficient(int index) const
1204  {
1205  return hCoefficients[tessid][index];
1206  }
1207 
1224  {
1225  return radiusOutOfRangeAllowed;
1226  }
1227 
1243  void setRadiusOutOfRangeAllowed(bool allowed)
1244  {
1245  if (allowed != radiusOutOfRangeAllowed)
1246  clearRadialCoefficients();
1247 
1248  radiusOutOfRangeAllowed = allowed;
1249  }
1250 
1254  void addReference() { ++refCount; }
1255 
1260  {
1261  if (isNotReferenced())
1262  {
1263  ostringstream os;
1264  os << endl << "ERROR in Polygon::removeReference" << endl
1265  << "Reference count (" << refCount << ") is already zero." << endl;
1266  throw GeoTessException(os, __FILE__, __LINE__, 3005);
1267  }
1268 
1269  --refCount;
1270  }
1271 
1278  {
1279  return refCount;
1280  }
1281 
1286  bool isNotReferenced() { return refCount == 0; }
1287 
1288 }; // end class GeoTessModel
1289 
1290 } // end namespace geotess
1291 
1292 #endif // GEOTESSPOSITION_OBJECT_H
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:71
#define ABSTRACT
Global constant used to make pure virtual functions readable.
Definition: CPPGlobals.h:78
An exception class for all GeoTess objects.
Manages the geometry and topology of one or more multi-level triangular tessellations of a unit spher...
Definition: GeoTessGrid.h:167
const double * getVertex(int vertex) const
Definition: GeoTessGrid.h:630
int getNTessellations() const
Definition: GeoTessGrid.h:826
Enumeration of the interpolation algorithms supported by GeoTess including LINEAR,...
Top level class that manages the GeoTessMetaData, GeoTessGrid and GeoTessData that comprise a 3D Eart...
Definition: GeoTessModel.h:120
GeoTessPointMap * getPointMap()
Information about an interpolated point at an arbitrary position in a model.
virtual double getValue(int attribute)
void set(int layid, const double *const uVector, double rad)
void setDepth(double depth)
void set(const double *const uVector, const double &newRadius)
void setBottom(int layid, const double *const uVector)
static GeoTessPosition * getGeoTessPosition(GeoTessModel *model, const GeoTessInterpolatorType &horizontalType)
void setTop(int layid, const double *const uVector)
int getTessLevel(const int &tId)
static GeoTessPosition * getGeoTessPosition(GeoTessModel *model, const GeoTessInterpolatorType &horizontalType, const GeoTessInterpolatorType &radialType)
void setRadius(double rad)
void getCoefficients(map< int, double > &coefficients)
void setRadius(int layid, double rad)
virtual const GeoTessInterpolatorType & getInterpolatorType() const
int getMaxTessLevel(int layid)
const vector< int > & getVertices() const
const vector< double > & getHorizontalCoefficients() const
double getHorizontalCoefficient(int index) const
void copyVector(double *u)
double getRadiusTop(int layid)
void setMaxTessLevel(int layid, int maxTess)
void setDepth(int layer, double depth)
void setRadiusOutOfRangeAllowed(bool allowed)
double getDepthTop(int layid)
void setModel(GeoTessModel *newModel)
double getDepthBottom(int layid)
void set(int layid, double lat, double lon, double depth)
double getRadiusBottom(int layid)
void setErrorValue(double errVal)
static GeoTessPosition * getGeoTessPosition(GeoTessModel *model)
double getLayerThickness(int layid)
const double * getClosestVertex() const
void set(double lat, double lon, double depth)
virtual long getMemory()
int getIndexOfClosestVertex() const
void getWeights(map< int, double > &weights, double dkm)
Abstract class that manages the radii and data values that span a single layer associated with a sing...