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 "GeoTessProfile.h"
59 
60 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
61 
62 namespace geotess {
63 
64 // **** _FORWARD REFERENCES_ ***************************************************
65 
66 class GeoTessInterpolatorType;
67 class GeoTessProfile;
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  // make sure dimensions of radialIndexes and radialCoefficients
217  // are at least as big as the number of vertices involved in interpolation.
218  if (radialIndexes.size() < vertices[tessid].size())
219  {
220  radialIndexes.resize(vertices[tessid].size());
221  radialCoefficients.resize(vertices[tessid].size());
222  }
223 
224  // if radial interpolation coefficients have already been computed
225  // do nothing.
226  if (radialIndexes[0].size() == 0)
227  {
228  vector<int>& v = vertices[tessid];
229  for (int i = 0; i < (int)v.size(); ++i)
230  modlProfiles[v[i]][layerId]->setInterpolationCoefficients(radialInterpolatorType,
231  radialIndexes[i], radialCoefficients[i], radius, radiusOutOfRangeAllowed);
232  }
233  }
234 
239  static const double TWALK_TOLERANCE;
240 
251  void getContainingTriangle(int tid);
252 
261  int biggerTriangle(int t1, int t2)
262  {
263  const int* tv = grid.getTriangleVertexIndexes(t1);
264  double dot1 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
265  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
266  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
267 
268  tv = grid.getTriangleVertexIndexes(t2);
269  double dot2 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1]))
270  + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2]))
271  + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0]));
272 
273  return dot2 > dot1 ? t1 : t2;
274 
275  }
276 
277 protected:
278 
280 
284  double radius;
285 
289  double earthRadius;
290 
298  vector<double> layerRadii;
299 
303  int layerId;
304 
308  int tessid;
309 
317  vector< vector< int> > vertices;
318 
324  vector< vector< double> > linearCoefficients;
325 
332  //vector< vector< double> > nnCoefficients;
333 
337  vector< vector< double> > hCoefficients;
338 
353  vector<vector<int> > radialIndexes;
354 
372  vector<vector<double> > radialCoefficients;
373 
374 
379  const GeoTessInterpolatorType& radialInterpolatorType;
380 
385  GeoTessModel* model;
386 
390  const GeoTessGrid& grid;
391 
395  GeoTessProfile *** modlProfiles;
396  double const* const* gridVertices;
397  int const* const* gridTriangles;
398  int const* const* gridNeighbors;
399  double const* const* const* gridEdges;
400  const int* layerTessIds;
401  int nLayers;
402 
417  bool radiusOutOfRangeAllowed;
418 
422  double unitVector[3];
423 
427  int getTriangle(int tid)
428  { checkTessellation(tid); return triangle[tid]; };
429 
434  virtual void update2D(int tid) = ABSTRACT;
435 
439  GeoTessPosition(GeoTessModel* model, const GeoTessInterpolatorType& radialType);
440 
442 
443 public:
444 
454  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model);
455 
470  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
471  const GeoTessInterpolatorType& horizontalType);
472 
486  static GeoTessPosition* getGeoTessPosition(GeoTessModel* model,
487  const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType);
488 
492  virtual ~GeoTessPosition();
493 
500  virtual const GeoTessInterpolatorType& getInterpolatorType() const = ABSTRACT;
501 
508  virtual double getValue(int attribute);
509 
530  void setModel(GeoTessModel* newModel);
531 
536  bool noEmptyProfiles();
537 
558  void set(double lat, double lon, double depth)
559  {
560  double uVector[3] = {0.0, 0.0, 0.0};
561  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
562  double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth;
563  set(uVector, newRadius);
564  }
565 
578  void set(const double* const uVector, const double& newRadius)
579  {
580  updatePosition2D(nLayers - 1, uVector);
581 
582  int lid = getLayerId(newRadius);
583 
584  updatePosition2D(lid, uVector);
585  updateRadius(lid, newRadius);
586  }
587 
605  void set(int layid, double lat, double lon, double depth)
606  {
607  if (layid < 0)
608  set(lat, lon, depth);
609  else
610  {
611  double uVector[3];
612  GeoTessUtils::getVectorDegrees(lat, lon, uVector);
613  updatePosition2D(layid, uVector);
614  updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth);
615  }
616  }
617 
628  void set(int layid, const double* const uVector, double rad)
629  {
630  if (layid < 0)
631  set(uVector, rad);
632  else
633  {
634  updatePosition2D(layid, uVector);
635  if (rad >= 0.0) updateRadius(layid, rad);
636  }
637  }
638 
646  void setTop(int layid, const double* const uVector)
647  {
648  updatePosition2D(layid, uVector);
649  updateRadius(layid, getRadiusTop(layid));
650  }
651 
660  void setBottom(int layid, const double* const uVector)
661  {
662  updatePosition2D(layid, uVector);
663  updateRadius(layid, getRadiusBottom(layid));
664  }
665 
673  void setRadius(int layid, double rad)
674  {
675  if (tessid < 0)
676  {
677  ostringstream os;
678  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
679  << "Geographic position has not been specified." << endl;
680  throw GeoTessException(os, __FILE__, __LINE__, 3001);
681  }
682  updateRadius(layid, rad);
683  }
684 
691  void setRadius(double rad)
692  {
693  if (tessid < 0)
694  if (tessid < 0)
695  {
696  ostringstream os;
697  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
698  << "Geographic position has not been specified." << endl;
699  throw GeoTessException(os, __FILE__, __LINE__, 3002);
700  }
701  updateRadius(getLayerId(rad), rad);
702  }
703 
715  void setDepth(int layer, double depth)
716  {
717  setRadius(layer, getEarthRadius()-depth);
718  }
719 
726  void setDepth(double depth)
727  {
728  setRadius(getEarthRadius()-depth);
729  }
730 
736  void setTop(int layid)
737  {
738  if (tessid < 0)
739  {
740  ostringstream os;
741  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
742  << "Geographic position has not been specified." << endl;
743  throw GeoTessException(os, __FILE__, __LINE__, 3003);
744  }
745  tessid = layerTessIds[layid];
746  checkTessellation(tessid);
747  updateRadius(layid, getRadiusTop(layid));
748  }
749 
756  void setBottom(int layid)
757  {
758  if (tessid < 0)
759  {
760  ostringstream os;
761  os << endl << "ERROR in GeoTessPosition::setRadius" << endl
762  << "Geographic position has not been specified." << endl;
763  throw GeoTessException(os, __FILE__, __LINE__, 3004);
764  }
765  tessid = layerTessIds[layid];
766  checkTessellation(tessid);
767  updateRadius(layid, getRadiusBottom(layid));
768  }
769 
777  double getRadiusTop(int layid);
778 
785  double getRadiusBottom(int layid);
786 
792  double getEarthRadius()
793  {
794  if (earthRadius < 0.)
795  earthRadius = GeoTessUtils::getEarthRadius(unitVector);
796  return earthRadius;
797  }
798 
805  double* getVector() { return unitVector; };
806 
813  void copyVector(double* u)
814  { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; };
815 
821  int getTriangle() { return triangle[tessid]; };
822 
827  int getNVertices() { return vertices[tessid].size(); };
828 
836  const vector<int>& getVertices() const { return vertices[tessid]; };
837 
843  int getIndexOfClosestVertex() const;
844 
851  const double* getClosestVertex() const
852  {
853  return grid.getVertex(getIndexOfClosestVertex());
854  }
855 
862  int getVertex(int index)
863  { return vertices[tessid][index]; }
864 
870  void getCoefficients(map<int, double>& coefficients)
871  {
872  coefficients.clear();
873  vector<int>& vtx = vertices[tessid];
874  vector<double>& hc = hCoefficients[tessid];
875  for (int i = 0; i < (int) vtx.size(); ++i)
876  modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]);
877  }
878 
888  void setMaxTessLevel(int layid, int maxTess)
889  {
890  maxTessLevel[layerTessIds[layid]] = maxTess;
891  triangle[layerTessIds[layid]] = -1;
892  checkTessellation(tessid);
893  }
894 
904  int getMaxTessLevel(int layid)
905  { return maxTessLevel[layerTessIds[layid]]; }
906 
913  int getTessLevel() const { return tessLevels[tessid]; };
914 
923  int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; }
924 
930  double getRadiusTop()
931  { return getRadiusTop(layerId); };
932 
938  double getRadiusBottom()
939  { return getRadiusBottom(layerId); };
940 
946  double getDepthTop()
947  {
948  return getEarthRadius() - getRadiusTop(layerId);
949  }
950 
956  double getDepthBottom()
957  {
958  return getEarthRadius() - getRadiusBottom(layerId);
959  }
960 
967  double getDepthTop(int layid)
968  {
969  return getEarthRadius() - getRadiusTop(layid);
970  }
971 
978  double getDepthBottom(int layid)
979  {
980  return getEarthRadius() - getRadiusBottom(layid);
981  }
982 
989  double getLayerThickness(int layid)
990  {
991  return getRadiusTop(layid) - getRadiusBottom(layid);
992  }
993 
999  double getLayerThickness()
1000  {
1001  return getRadiusTop() - getRadiusBottom();
1002  }
1003 
1009  double getRadius() { return radius; };
1010 
1016  double getDepth()
1017  { return getEarthRadius() - radius; };
1018 
1022  GeoTessModel* getModel() { return model; }
1023 
1027  int getTessID() { return tessid; };
1028 
1039  int getLayerId(double rad)
1040  {
1041  for (int i=0; i<nLayers; ++i)
1042  if (rad <= getRadiusTop(i))
1043  return i;
1044 
1045  for (int i=nLayers-1; i>=0; --i)
1046  if (getLayerThickness(i) > 0)
1047  return i;
1048 
1049  return nLayers-1;
1050  };
1051 
1055  int getLayerId() { return layerId; };
1056 
1061  string toString();
1062 
1069  double getErrorValue()
1070  {
1071  return errorValue;
1072  }
1073 
1080  void setErrorValue(double errVal)
1081  {
1082  errorValue = errVal;
1083  }
1084 
1092  int getVertexIndex()
1093  {
1094  vector<int>& vtid = vertices[tessid];
1095  vector<double>& htid = hCoefficients[tessid];
1096  for (int v = 0; v < (int) vtid.size(); ++v)
1097  if (htid[v] > 0.999999999)
1098  return vtid[v];
1099  return -1;
1100  }
1101 
1126  void getWeights(map<int, double>& weights, double dkm)
1127  {
1128  vector<int>& vtx = vertices[tessid];
1129  vector<double>& htid = hCoefficients[tessid];
1130  for (int i = 0; i < (int) vtx.size(); ++i)
1131  modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]);
1132  }
1133 
1141  const vector<double>& getHorizontalCoefficients() const
1142  {
1143  return hCoefficients[tessid];
1144  }
1145 
1154  double getHorizontalCoefficient(int index) const
1155  {
1156  return hCoefficients[tessid][index];
1157  }
1158 
1174  bool isRadiusOutOfRangeAllowed()
1175  {
1176  return radiusOutOfRangeAllowed;
1177  }
1178 
1194  void setRadiusOutOfRangeAllowed(bool allowed)
1195  {
1196  if (allowed != radiusOutOfRangeAllowed)
1197  clearRadialCoefficients();
1198 
1199  radiusOutOfRangeAllowed = allowed;
1200  }
1201 
1205  void addReference() { ++refCount; }
1206 
1210  void removeReference()
1211  {
1212  if (isNotReferenced())
1213  {
1214  ostringstream os;
1215  os << endl << "ERROR in Polygon::removeReference" << endl
1216  << "Reference count (" << refCount << ") is already zero." << endl;
1217  throw GeoTessException(os, __FILE__, __LINE__, 3005);
1218  }
1219 
1220  --refCount;
1221  }
1222 
1228  int getReferenceCount()
1229  {
1230  return refCount;
1231  }
1232 
1237  bool isNotReferenced() { return refCount == 0; }
1238 
1239 }; // end class GeoTessModel
1240 
1241 } // end namespace geotess
1242 
1243 #endif // GEOTESSPOSITION_OBJECT_H