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 
447  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model);
448 
463  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
464  const InterpolatorType& horizontalType);
465 
479  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
480  const InterpolatorType& horizontalType, const InterpolatorType& radialType);
481 
485  virtual ~GeoTessPosition();
486 
493  virtual const InterpolatorType& getInterpolatorType() const = ABSTRACT;
494 
501  virtual double getValue(int attribute);
502 
523  void setModel(GeoTessModel* newModel);
524 
529  bool noEmptyProfiles();
530 
551  void set(double lat, double lon, double depth)
552  {
553  double uVector[3] = {0.0, 0.0, 0.0};
554  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
555  double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth;
556  set(uVector, newRadius);
557  }
558 
571  void set(const double* const uVector, const double& newRadius)
572  {
573  updatePosition2D(nLayers - 1, uVector);
574 
575  int lid = getLayerId(newRadius);
576 
577  updatePosition2D(lid, uVector);
578  updateRadius(lid, newRadius);
579  }
580 
598  void set(int layid, double lat, double lon, double depth)
599  {
600  if (layid < 0)
601  set(lat, lon, depth);
602  else
603  {
604  double uVector[3];
605  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
606  updatePosition2D(layid, uVector);
607  updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth);
608  }
609  }
610 
621  void set(int layid, const double* const uVector, double rad)
622  {
623  if (layid < 0)
624  set(uVector, rad);
625  else
626  {
627  updatePosition2D(layid, uVector);
628  if (rad >= 0.0) updateRadius(layid, rad);
629  }
630  }
631 
639  void setTop(int layid, const double* const uVector)
640  {
641  updatePosition2D(layid, uVector);
642  updateRadius(layid, getRadiusTop(layid));
643  }
644 
653  void setBottom(int layid, const double* const uVector)
654  {
655  updatePosition2D(layid, uVector);
656  updateRadius(layid, getRadiusBottom(layid));
657  }
658 
666  void setRadius(int layid, double rad)
667  {
668  if (tessid < 0)
669  {
670  ostringstream os;
671  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
672  << "Geographic position has not been specified." << endl;
673  throw GeoTessException(os, __FILE__, __LINE__, 3001);
674  }
675  updateRadius(layid, rad);
676  }
677 
684  void setRadius(double rad)
685  {
686  if (tessid < 0)
687  if (tessid < 0)
688  {
689  ostringstream os;
690  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
691  << "Geographic position has not been specified." << endl;
692  throw GeoTessException(os, __FILE__, __LINE__, 3002);
693  }
694  updateRadius(getLayerId(rad), rad);
695  }
696 
708  void setDepth(int layer, double depth)
709  {
710  setRadius(layer, getEarthRadius()-depth);
711  }
712 
719  void setDepth(double depth)
720  {
721  setRadius(getEarthRadius()-depth);
722  }
723 
729  void setTop(int layid)
730  {
731  if (tessid < 0)
732  {
733  ostringstream os;
734  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
735  << "Geographic position has not been specified." << endl;
736  throw GeoTessException(os, __FILE__, __LINE__, 3003);
737  }
738  tessid = layerTessIds[layid];
739  checkTessellation(tessid);
740  updateRadius(layid, getRadiusTop(layid));
741  }
742 
749  void setBottom(int layid)
750  {
751  if (tessid < 0)
752  {
753  ostringstream os;
754  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
755  << "Geographic position has not been specified." << endl;
756  throw GeoTessException(os, __FILE__, __LINE__, 3004);
757  }
758  tessid = layerTessIds[layid];
759  checkTessellation(tessid);
760  updateRadius(layid, getRadiusBottom(layid));
761  }
762 
770  double getRadiusTop(int layid);
771 
778  double getRadiusBottom(int layid);
779 
785  double getEarthRadius()
786  {
787  if (earthRadius < 0.)
788  earthRadius = GeoTessUtils::getEarthRadius(unitVector);
789  return earthRadius;
790  }
791 
798  double* getVector() { return unitVector; };
799 
806  void copyVector(double* u)
807  { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; };
808 
814  int getTriangle() { return triangle[tessid]; };
815 
820  int getNVertices() { return vertices[tessid].size(); };
821 
829  const vector<int>& getVertices() const { return vertices[tessid]; };
830 
836  int getIndexOfClosestVertex() const;
837 
844  const double* getClosestVertex() const
845  {
846  return grid.getVertex(getIndexOfClosestVertex());
847  }
848 
855  int getVertex(int index)
856  { return vertices[tessid][index]; }
857 
863  void getCoefficients(map<int, double>& coefficients)
864  {
865  coefficients.clear();
866  vector<int>& vtx = vertices[tessid];
867  vector<double>& hc = hCoefficients[tessid];
868  for (int i = 0; i < (int) vtx.size(); ++i)
869  modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]);
870  }
871 
881  void setMaxTessLevel(int layid, int maxTess)
882  {
883  maxTessLevel[layerTessIds[layid]] = maxTess;
884  triangle[layerTessIds[layid]] = -1;
885  checkTessellation(tessid);
886  }
887 
897  int getMaxTessLevel(int layid)
898  { return maxTessLevel[layerTessIds[layid]]; }
899 
906  int getTessLevel() const { return tessLevels[tessid]; };
907 
916  int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; }
917 
923  double getRadiusTop()
924  { return getRadiusTop(layerId); };
925 
931  double getRadiusBottom()
932  { return getRadiusBottom(layerId); };
933 
939  double getDepthTop()
940  {
941  return getEarthRadius() - getRadiusTop(layerId);
942  }
943 
949  double getDepthBottom()
950  {
951  return getEarthRadius() - getRadiusBottom(layerId);
952  }
953 
960  double getDepthTop(int layid)
961  {
962  return getEarthRadius() - getRadiusTop(layid);
963  }
964 
971  double getDepthBottom(int layid)
972  {
973  return getEarthRadius() - getRadiusBottom(layid);
974  }
975 
982  double getLayerThickness(int layid)
983  {
984  return getRadiusTop(layid) - getRadiusBottom(layid);
985  }
986 
992  double getLayerThickness()
993  {
994  return getRadiusTop() - getRadiusBottom();
995  }
996 
1002  double getRadius() { return radius; };
1003 
1009  double getDepth()
1010  { return getEarthRadius() - radius; };
1011 
1015  GeoTessModel* getModel() { return model; }
1016 
1020  int getTessID() { return tessid; };
1021 
1032  int getLayerId(double rad)
1033  {
1034  for (int i=0; i<nLayers; ++i)
1035  if (rad <= getRadiusTop(i))
1036  return i;
1037 
1038  for (int i=nLayers-1; i>=0; --i)
1039  if (getLayerThickness(i) > 0)
1040  return i;
1041 
1042  return nLayers-1;
1043  };
1044 
1048  int getLayerId() { return layerId; };
1049 
1054  string toString();
1055 
1062  double getErrorValue()
1063  {
1064  return errorValue;
1065  }
1066 
1073  void setErrorValue(double errVal)
1074  {
1075  errorValue = errVal;
1076  }
1077 
1085  int getVertexIndex()
1086  {
1087  vector<int>& vtid = vertices[tessid];
1088  vector<double>& htid = hCoefficients[tessid];
1089  for (int v = 0; v < (int) vtid.size(); ++v)
1090  if (htid[v] > 0.999999999)
1091  return vtid[v];
1092  return -1;
1093  }
1094 
1119  void getWeights(map<int, double>& weights, double dkm)
1120  {
1121  vector<int>& vtx = vertices[tessid];
1122  vector<double>& htid = hCoefficients[tessid];
1123  for (int i = 0; i < (int) vtx.size(); ++i)
1124  modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]);
1125  }
1126 
1134  const vector<double>& getHorizontalCoefficients() const
1135  {
1136  return hCoefficients[tessid];
1137  }
1138 
1147  double getHorizontalCoefficient(int index) const
1148  {
1149  return hCoefficients[tessid][index];
1150  }
1151 
1167  bool isRadiusOutOfRangeAllowed()
1168  {
1169  return radiusOutOfRangeAllowed;
1170  }
1171 
1187  void setRadiusOutOfRangeAllowed(bool allowed)
1188  {
1189  if (allowed != radiusOutOfRangeAllowed)
1190  clearRadialCoefficients();
1191 
1192  radiusOutOfRangeAllowed = allowed;
1193  }
1194 
1198  void addReference() { ++refCount; }
1199 
1203  void removeReference()
1204  {
1205  if (isNotReferenced())
1206  {
1207  ostringstream os;
1208  os << endl << "ERROR in Polygon::removeReference" << endl
1209  << "Reference count (" << refCount << ") is already zero." << endl;
1210  throw GeoTessException(os, __FILE__, __LINE__, 3005);
1211  }
1212 
1213  --refCount;
1214  }
1215 
1221  int getReferenceCount()
1222  {
1223  return refCount;
1224  }
1225 
1230  bool isNotReferenced() { return refCount == 0; }
1231 
1232 }; // end class GeoTessModel
1233 
1234 } // end namespace geotess
1235 
1236 #endif // GEOTESSPOSITION_OBJECT_H