GeoTessCPP
2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
|
00001 //- **************************************************************************** 00002 //- 00003 //- Copyright 2009 Sandia Corporation. Under the terms of Contract 00004 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00005 //- retains certain rights in this software. 00006 //- 00007 //- BSD Open Source License. 00008 //- All rights reserved. 00009 //- 00010 //- Redistribution and use in source and binary forms, with or without 00011 //- modification, are permitted provided that the following conditions are met: 00012 //- 00013 //- * Redistributions of source code must retain the above copyright notice, 00014 //- this list of conditions and the following disclaimer. 00015 //- * Redistributions in binary form must reproduce the above copyright 00016 //- notice, this list of conditions and the following disclaimer in the 00017 //- documentation and/or other materials provided with the distribution. 00018 //- * Neither the name of Sandia National Laboratories nor the names of its 00019 //- contributors may be used to endorse or promote products derived from 00020 //- this software without specific prior written permission. 00021 //- 00022 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00026 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00027 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00028 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00031 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 //- POSSIBILITY OF SUCH DAMAGE. 00033 //- 00034 //- **************************************************************************** 00035 00036 #ifndef GEOTESSPOSITION_OBJECT_H 00037 #define GEOTESSPOSITION_OBJECT_H 00038 00039 // **** _SYSTEM INCLUDES_ ****************************************************** 00040 00041 #include <iostream> 00042 #include <string> 00043 #include <fstream> 00044 #include <vector> 00045 #include <sstream> 00046 00047 // use standard library objects 00048 using namespace std; 00049 00050 // **** _LOCAL INCLUDES_ ******************************************************* 00051 00052 #include "CPPUtils.h" 00053 #include "GeoTessUtils.h" 00054 #include "GeoTessModel.h" 00055 #include "GeoTessGrid.h" 00056 #include "GeoTessMetaData.h" 00057 #include "CpuTimer.h" 00058 #include "Profile.h" 00059 00060 // **** _BEGIN GEOTESS NAMESPACE_ ********************************************** 00061 00062 namespace geotess { 00063 00064 // **** _FORWARD REFERENCES_ *************************************************** 00065 00066 class InterpolatorType; 00067 class Profile; 00068 00069 // **** _CLASS DEFINITION_ ***************************************************** 00070 00100 class GEOTESS_EXP_IMP GeoTessPosition 00101 { 00102 private: 00103 00107 int refCount; 00108 00114 int* maxTessLevel; 00115 00121 int* tessLevels; 00122 00131 int* triangle; 00132 00138 double errorValue; 00139 00150 void updatePosition2D(int layerid, const double* const uVector); 00151 00169 void checkTessellation(const int& tid) 00170 { 00171 if (triangle[tid] < 0) 00172 { 00173 tessLevels[tid] = 0; 00174 triangle[tid] = grid.getTriangle(tid, 0, 0); 00175 getContainingTriangle(tid); 00176 update2D(tid); 00177 } 00178 } 00179 00187 void updateRadius(int lid, double rad) 00188 { 00189 if ((radius < 0.) || (rad != radius) || (lid != layerId)) 00190 { 00191 radius = rad; 00192 layerId = lid; 00193 tessid = layerTessIds[lid]; 00194 checkTessellation(tessid); 00195 clearRadialCoefficients(); 00196 } 00197 } 00198 00199 void clearRadialCoefficients() 00200 { 00201 for (int i=0; i<(int)radialIndexes.size(); ++i) 00202 { 00203 radialIndexes[i].clear(); 00204 radialCoefficients[i].clear(); 00205 } 00206 } 00207 00214 void updateRadialCoefficients() 00215 { 00216 // if radial interpolation coefficients have already been computed 00217 // do nothing. 00218 if (radialIndexes[0].size() == 0) 00219 { 00220 vector<int>& v = vertices[tessid]; 00221 for (int i = 0; i < (int)v.size(); ++i) 00222 modlProfiles[v[i]][layerId]->setInterpolationCoefficients(radialInterpolatorType, 00223 radialIndexes[i], radialCoefficients[i], radius, radiusOutOfRangeAllowed); 00224 } 00225 } 00226 00231 static const double TWALK_TOLERANCE; 00232 00243 void getContainingTriangle(int tid); 00244 00253 int biggerTriangle(int t1, int t2) 00254 { 00255 const int* tv = grid.getTriangleVertexIndexes(t1); 00256 double dot1 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1])) 00257 + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2])) 00258 + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0])); 00259 00260 tv = grid.getTriangleVertexIndexes(t2); 00261 double dot2 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1])) 00262 + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2])) 00263 + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0])); 00264 00265 return dot2 > dot1 ? t1 : t2; 00266 00267 } 00268 00269 protected: 00270 00272 00276 double radius; 00277 00281 double earthRadius; 00282 00290 vector<double> layerRadii; 00291 00295 int layerId; 00296 00300 int tessid; 00301 00309 vector< vector< int> > vertices; 00310 00316 vector< vector< double> > linearCoefficients; 00317 00324 vector< vector< double> > nnCoefficients; 00325 00329 vector< vector< double> >& hCoefficients; 00330 00345 vector<vector<int> > radialIndexes; 00346 00364 vector<vector<double> > radialCoefficients; 00365 00366 00371 const InterpolatorType& radialInterpolatorType; 00372 00377 GeoTessModel* model; 00378 00382 const GeoTessGrid& grid; 00383 00387 Profile *** modlProfiles; 00388 double const* const* gridVertices; 00389 int const* const* gridTriangles; 00390 int const* const* gridNeighbors; 00391 double const* const* const* gridEdges; 00392 const int* layerTessIds; 00393 int nLayers; 00394 00409 bool radiusOutOfRangeAllowed; 00410 00414 double unitVector[3]; 00415 00419 int getTriangle(int tid) 00420 { checkTessellation(tid); return triangle[tid]; }; 00421 00426 virtual void update2D(int tid) = ABSTRACT; 00427 00431 GeoTessPosition(GeoTessModel* model, const InterpolatorType& radialType, 00432 vector< vector<double> >& c); 00433 00435 00436 public: 00437 00447 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model); 00448 00463 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model, 00464 const InterpolatorType& horizontalType); 00465 00479 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model, 00480 const InterpolatorType& horizontalType, const InterpolatorType& radialType); 00481 00485 virtual ~GeoTessPosition(); 00486 00493 virtual const InterpolatorType& getInterpolatorType() const = ABSTRACT; 00494 00501 virtual double getValue(int attribute); 00502 00523 void setModel(GeoTessModel* newModel); 00524 00529 bool noEmptyProfiles(); 00530 00551 void set(double lat, double lon, double depth) 00552 { 00553 double uVector[3] = {0.0, 0.0, 0.0}; 00554 GeoTessUtils::getVectorDegrees(lat, lon, uVector); 00555 double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth; 00556 set(uVector, newRadius); 00557 } 00558 00571 void set(const double* const uVector, const double& newRadius) 00572 { 00573 updatePosition2D(nLayers - 1, uVector); 00574 00575 int lid = getLayerId(newRadius); 00576 00577 updatePosition2D(lid, uVector); 00578 updateRadius(lid, newRadius); 00579 } 00580 00598 void set(int layid, double lat, double lon, double depth) 00599 { 00600 if (layid < 0) 00601 set(lat, lon, depth); 00602 else 00603 { 00604 double uVector[3]; 00605 GeoTessUtils::getVectorDegrees(lat, lon, uVector); 00606 updatePosition2D(layid, uVector); 00607 updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth); 00608 } 00609 } 00610 00621 void set(int layid, const double* const uVector, double rad) 00622 { 00623 if (layid < 0) 00624 set(uVector, rad); 00625 else 00626 { 00627 updatePosition2D(layid, uVector); 00628 if (rad >= 0.0) updateRadius(layid, rad); 00629 } 00630 } 00631 00639 void setTop(int layid, const double* const uVector) 00640 { 00641 updatePosition2D(layid, uVector); 00642 updateRadius(layid, getRadiusTop(layid)); 00643 } 00644 00653 void setBottom(int layid, const double* const uVector) 00654 { 00655 updatePosition2D(layid, uVector); 00656 updateRadius(layid, getRadiusBottom(layid)); 00657 } 00658 00666 void setRadius(int layid, double rad) 00667 { 00668 if (tessid < 0) 00669 { 00670 ostringstream os; 00671 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00672 << "Geographic position has not been specified." << endl; 00673 throw GeoTessException(os, __FILE__, __LINE__, 3001); 00674 } 00675 updateRadius(layid, rad); 00676 } 00677 00684 void setRadius(double rad) 00685 { 00686 if (tessid < 0) 00687 if (tessid < 0) 00688 { 00689 ostringstream os; 00690 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00691 << "Geographic position has not been specified." << endl; 00692 throw GeoTessException(os, __FILE__, __LINE__, 3002); 00693 } 00694 updateRadius(getLayerId(rad), rad); 00695 } 00696 00708 void setDepth(int layer, double depth) 00709 { 00710 setRadius(layer, getEarthRadius()-depth); 00711 } 00712 00719 void setDepth(double depth) 00720 { 00721 setRadius(getEarthRadius()-depth); 00722 } 00723 00729 void setTop(int layid) 00730 { 00731 if (tessid < 0) 00732 { 00733 ostringstream os; 00734 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00735 << "Geographic position has not been specified." << endl; 00736 throw GeoTessException(os, __FILE__, __LINE__, 3003); 00737 } 00738 tessid = layerTessIds[layid]; 00739 checkTessellation(tessid); 00740 updateRadius(layid, getRadiusTop(layid)); 00741 } 00742 00749 void setBottom(int layid) 00750 { 00751 if (tessid < 0) 00752 { 00753 ostringstream os; 00754 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00755 << "Geographic position has not been specified." << endl; 00756 throw GeoTessException(os, __FILE__, __LINE__, 3004); 00757 } 00758 tessid = layerTessIds[layid]; 00759 checkTessellation(tessid); 00760 updateRadius(layid, getRadiusBottom(layid)); 00761 } 00762 00770 double getRadiusTop(int layid); 00771 00778 double getRadiusBottom(int layid); 00779 00785 double getEarthRadius() 00786 { 00787 if (earthRadius < 0.) 00788 earthRadius = GeoTessUtils::getEarthRadius(unitVector); 00789 return earthRadius; 00790 } 00791 00798 double* getVector() { return unitVector; }; 00799 00806 void copyVector(double* u) 00807 { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; }; 00808 00814 int getTriangle() { return triangle[tessid]; }; 00815 00820 int getNVertices() { return vertices[tessid].size(); }; 00821 00829 const vector<int>& getVertices() const { return vertices[tessid]; }; 00830 00836 int getIndexOfClosestVertex() const; 00837 00844 const double* getClosestVertex() const 00845 { 00846 return grid.getVertex(getIndexOfClosestVertex()); 00847 } 00848 00855 int getVertex(int index) 00856 { return vertices[tessid][index]; } 00857 00863 void getCoefficients(map<int, double>& coefficients) 00864 { 00865 coefficients.clear(); 00866 vector<int>& vtx = vertices[tessid]; 00867 vector<double>& hc = hCoefficients[tessid]; 00868 for (int i = 0; i < (int) vtx.size(); ++i) 00869 modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]); 00870 } 00871 00881 void setMaxTessLevel(int layid, int maxTess) 00882 { 00883 maxTessLevel[layerTessIds[layid]] = maxTess; 00884 triangle[layerTessIds[layid]] = -1; 00885 checkTessellation(tessid); 00886 } 00887 00897 int getMaxTessLevel(int layid) 00898 { return maxTessLevel[layerTessIds[layid]]; } 00899 00906 int getTessLevel() const { return tessLevels[tessid]; }; 00907 00916 int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; } 00917 00923 double getRadiusTop() 00924 { return getRadiusTop(layerId); }; 00925 00931 double getRadiusBottom() 00932 { return getRadiusBottom(layerId); }; 00933 00939 double getDepthTop() 00940 { 00941 return getEarthRadius() - getRadiusTop(layerId); 00942 } 00943 00949 double getDepthBottom() 00950 { 00951 return getEarthRadius() - getRadiusBottom(layerId); 00952 } 00953 00960 double getDepthTop(int layid) 00961 { 00962 return getEarthRadius() - getRadiusTop(layid); 00963 } 00964 00971 double getDepthBottom(int layid) 00972 { 00973 return getEarthRadius() - getRadiusBottom(layid); 00974 } 00975 00982 double getLayerThickness(int layid) 00983 { 00984 return getRadiusTop(layid) - getRadiusBottom(layid); 00985 } 00986 00992 double getLayerThickness() 00993 { 00994 return getRadiusTop() - getRadiusBottom(); 00995 } 00996 01002 double getRadius() { return radius; }; 01003 01009 double getDepth() 01010 { return getEarthRadius() - radius; }; 01011 01015 GeoTessModel* getModel() { return model; } 01016 01020 int getTessID() { return tessid; }; 01021 01032 int getLayerId(double rad) 01033 { 01034 for (int i=0; i<nLayers; ++i) 01035 if (rad <= getRadiusTop(i)) 01036 return i; 01037 01038 for (int i=nLayers-1; i>=0; --i) 01039 if (getLayerThickness(i) > 0) 01040 return i; 01041 01042 return nLayers-1; 01043 }; 01044 01048 int getLayerId() { return layerId; }; 01049 01054 string toString(); 01055 01062 double getErrorValue() 01063 { 01064 return errorValue; 01065 } 01066 01073 void setErrorValue(double errVal) 01074 { 01075 errorValue = errVal; 01076 } 01077 01085 int getVertexIndex() 01086 { 01087 vector<int>& vtid = vertices[tessid]; 01088 vector<double>& htid = hCoefficients[tessid]; 01089 for (int v = 0; v < (int) vtid.size(); ++v) 01090 if (htid[v] > 0.999999999) 01091 return vtid[v]; 01092 return -1; 01093 } 01094 01119 void getWeights(map<int, double>& weights, double dkm) 01120 { 01121 vector<int>& vtx = vertices[tessid]; 01122 vector<double>& htid = hCoefficients[tessid]; 01123 for (int i = 0; i < (int) vtx.size(); ++i) 01124 modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]); 01125 } 01126 01134 const vector<double>& getHorizontalCoefficients() const 01135 { 01136 return hCoefficients[tessid]; 01137 } 01138 01147 double getHorizontalCoefficient(int index) const 01148 { 01149 return hCoefficients[tessid][index]; 01150 } 01151 01167 bool isRadiusOutOfRangeAllowed() 01168 { 01169 return radiusOutOfRangeAllowed; 01170 } 01171 01187 void setRadiusOutOfRangeAllowed(bool allowed) 01188 { 01189 if (allowed != radiusOutOfRangeAllowed) 01190 clearRadialCoefficients(); 01191 01192 radiusOutOfRangeAllowed = allowed; 01193 } 01194 01198 void addReference() { ++refCount; } 01199 01203 void removeReference() 01204 { 01205 if (isNotReferenced()) 01206 { 01207 ostringstream os; 01208 os << endl << "ERROR in Polygon::removeReference" << endl 01209 << "Reference count (" << refCount << ") is already zero." << endl; 01210 throw GeoTessException(os, __FILE__, __LINE__, 3005); 01211 } 01212 01213 --refCount; 01214 } 01215 01221 int getReferenceCount() 01222 { 01223 return refCount; 01224 } 01225 01230 bool isNotReferenced() { return refCount == 0; } 01231 01232 }; // end class GeoTessModel 01233 01234 } // end namespace geotess 01235 01236 #endif // GEOTESSPOSITION_OBJECT_H