GeoTessCPP: include/GeoTessPosition.h Source File

GeoTessCPP 2.0.0 Software to facilitate storage and retrieval of 3D information about the Earth.

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
100 class GEOTESS_EXP_IMP GeoTessPosition
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