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 "GeoTessProfile.h" 00059 00060 // **** _BEGIN GEOTESS NAMESPACE_ ********************************************** 00061 00062 namespace geotess { 00063 00064 // **** _FORWARD REFERENCES_ *************************************************** 00065 00066 class GeoTessInterpolatorType; 00067 class GeoTessProfile; 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 // make sure dimensions of radialIndexes and radialCoefficients 00217 // are at least as big as the number of vertices involved in interpolation. 00218 if (radialIndexes.size() < vertices[tessid].size()) 00219 { 00220 radialIndexes.resize(vertices[tessid].size()); 00221 radialCoefficients.resize(vertices[tessid].size()); 00222 } 00223 00224 // if radial interpolation coefficients have already been computed 00225 // do nothing. 00226 if (radialIndexes[0].size() == 0) 00227 { 00228 vector<int>& v = vertices[tessid]; 00229 for (int i = 0; i < (int)v.size(); ++i) 00230 modlProfiles[v[i]][layerId]->setInterpolationCoefficients(radialInterpolatorType, 00231 radialIndexes[i], radialCoefficients[i], radius, radiusOutOfRangeAllowed); 00232 } 00233 } 00234 00239 static const double TWALK_TOLERANCE; 00240 00251 void getContainingTriangle(int tid); 00252 00261 int biggerTriangle(int t1, int t2) 00262 { 00263 const int* tv = grid.getTriangleVertexIndexes(t1); 00264 double dot1 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1])) 00265 + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2])) 00266 + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0])); 00267 00268 tv = grid.getTriangleVertexIndexes(t2); 00269 double dot2 = GeoTessUtils::dot(grid.getVertex(tv[0]), grid.getVertex(tv[1])) 00270 + GeoTessUtils::dot(grid.getVertex(tv[1]), grid.getVertex(tv[2])) 00271 + GeoTessUtils::dot(grid.getVertex(tv[2]), grid.getVertex(tv[0])); 00272 00273 return dot2 > dot1 ? t1 : t2; 00274 00275 } 00276 00277 protected: 00278 00280 00284 double radius; 00285 00289 double earthRadius; 00290 00298 vector<double> layerRadii; 00299 00303 int layerId; 00304 00308 int tessid; 00309 00317 vector< vector< int> > vertices; 00318 00324 vector< vector< double> > linearCoefficients; 00325 00332 //vector< vector< double> > nnCoefficients; 00333 00337 vector< vector< double> > hCoefficients; 00338 00353 vector<vector<int> > radialIndexes; 00354 00372 vector<vector<double> > radialCoefficients; 00373 00374 00379 const GeoTessInterpolatorType& radialInterpolatorType; 00380 00385 GeoTessModel* model; 00386 00390 const GeoTessGrid& grid; 00391 00395 GeoTessProfile *** modlProfiles; 00396 double const* const* gridVertices; 00397 int const* const* gridTriangles; 00398 int const* const* gridNeighbors; 00399 double const* const* const* gridEdges; 00400 const int* layerTessIds; 00401 int nLayers; 00402 00417 bool radiusOutOfRangeAllowed; 00418 00422 double unitVector[3]; 00423 00427 int getTriangle(int tid) 00428 { checkTessellation(tid); return triangle[tid]; }; 00429 00434 virtual void update2D(int tid) = ABSTRACT; 00435 00439 GeoTessPosition(GeoTessModel* model, const GeoTessInterpolatorType& radialType); 00440 00442 00443 public: 00444 00454 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model); 00455 00470 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model, 00471 const GeoTessInterpolatorType& horizontalType); 00472 00486 static GeoTessPosition* getGeoTessPosition(GeoTessModel* model, 00487 const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType); 00488 00492 virtual ~GeoTessPosition(); 00493 00500 virtual const GeoTessInterpolatorType& getInterpolatorType() const = ABSTRACT; 00501 00508 virtual double getValue(int attribute); 00509 00530 void setModel(GeoTessModel* newModel); 00531 00536 bool noEmptyProfiles(); 00537 00558 void set(double lat, double lon, double depth) 00559 { 00560 double uVector[3] = {0.0, 0.0, 0.0}; 00561 GeoTessUtils::getVectorDegrees(lat, lon, uVector); 00562 double newRadius = GeoTessUtils::getEarthRadius(uVector) - depth; 00563 set(uVector, newRadius); 00564 } 00565 00578 void set(const double* const uVector, const double& newRadius) 00579 { 00580 updatePosition2D(nLayers - 1, uVector); 00581 00582 int lid = getLayerId(newRadius); 00583 00584 updatePosition2D(lid, uVector); 00585 updateRadius(lid, newRadius); 00586 } 00587 00605 void set(int layid, double lat, double lon, double depth) 00606 { 00607 if (layid < 0) 00608 set(lat, lon, depth); 00609 else 00610 { 00611 double uVector[3]; 00612 GeoTessUtils::getVectorDegrees(lat, lon, uVector); 00613 updatePosition2D(layid, uVector); 00614 updateRadius(layid, GeoTessUtils::getEarthRadius(uVector) - depth); 00615 } 00616 } 00617 00628 void set(int layid, const double* const uVector, double rad) 00629 { 00630 if (layid < 0) 00631 set(uVector, rad); 00632 else 00633 { 00634 updatePosition2D(layid, uVector); 00635 if (rad >= 0.0) updateRadius(layid, rad); 00636 } 00637 } 00638 00646 void setTop(int layid, const double* const uVector) 00647 { 00648 updatePosition2D(layid, uVector); 00649 updateRadius(layid, getRadiusTop(layid)); 00650 } 00651 00660 void setBottom(int layid, const double* const uVector) 00661 { 00662 updatePosition2D(layid, uVector); 00663 updateRadius(layid, getRadiusBottom(layid)); 00664 } 00665 00673 void setRadius(int layid, double rad) 00674 { 00675 if (tessid < 0) 00676 { 00677 ostringstream os; 00678 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00679 << "Geographic position has not been specified." << endl; 00680 throw GeoTessException(os, __FILE__, __LINE__, 3001); 00681 } 00682 updateRadius(layid, rad); 00683 } 00684 00691 void setRadius(double rad) 00692 { 00693 if (tessid < 0) 00694 if (tessid < 0) 00695 { 00696 ostringstream os; 00697 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00698 << "Geographic position has not been specified." << endl; 00699 throw GeoTessException(os, __FILE__, __LINE__, 3002); 00700 } 00701 updateRadius(getLayerId(rad), rad); 00702 } 00703 00715 void setDepth(int layer, double depth) 00716 { 00717 setRadius(layer, getEarthRadius()-depth); 00718 } 00719 00726 void setDepth(double depth) 00727 { 00728 setRadius(getEarthRadius()-depth); 00729 } 00730 00736 void setTop(int layid) 00737 { 00738 if (tessid < 0) 00739 { 00740 ostringstream os; 00741 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00742 << "Geographic position has not been specified." << endl; 00743 throw GeoTessException(os, __FILE__, __LINE__, 3003); 00744 } 00745 tessid = layerTessIds[layid]; 00746 checkTessellation(tessid); 00747 updateRadius(layid, getRadiusTop(layid)); 00748 } 00749 00756 void setBottom(int layid) 00757 { 00758 if (tessid < 0) 00759 { 00760 ostringstream os; 00761 os << endl << "ERROR in GeoTessPosition::setRadius" << endl 00762 << "Geographic position has not been specified." << endl; 00763 throw GeoTessException(os, __FILE__, __LINE__, 3004); 00764 } 00765 tessid = layerTessIds[layid]; 00766 checkTessellation(tessid); 00767 updateRadius(layid, getRadiusBottom(layid)); 00768 } 00769 00777 double getRadiusTop(int layid); 00778 00785 double getRadiusBottom(int layid); 00786 00792 double getEarthRadius() 00793 { 00794 if (earthRadius < 0.) 00795 earthRadius = GeoTessUtils::getEarthRadius(unitVector); 00796 return earthRadius; 00797 } 00798 00805 double* getVector() { return unitVector; }; 00806 00813 void copyVector(double* u) 00814 { u[0] = unitVector[0]; u[1] = unitVector[1]; u[2] = unitVector[2]; }; 00815 00821 int getTriangle() { return triangle[tessid]; }; 00822 00827 int getNVertices() { return vertices[tessid].size(); }; 00828 00836 const vector<int>& getVertices() const { return vertices[tessid]; }; 00837 00843 int getIndexOfClosestVertex() const; 00844 00851 const double* getClosestVertex() const 00852 { 00853 return grid.getVertex(getIndexOfClosestVertex()); 00854 } 00855 00862 int getVertex(int index) 00863 { return vertices[tessid][index]; } 00864 00870 void getCoefficients(map<int, double>& coefficients) 00871 { 00872 coefficients.clear(); 00873 vector<int>& vtx = vertices[tessid]; 00874 vector<double>& hc = hCoefficients[tessid]; 00875 for (int i = 0; i < (int) vtx.size(); ++i) 00876 modlProfiles[vtx[i]][layerId]->getCoefficients(coefficients, radius, hc[i]); 00877 } 00878 00888 void setMaxTessLevel(int layid, int maxTess) 00889 { 00890 maxTessLevel[layerTessIds[layid]] = maxTess; 00891 triangle[layerTessIds[layid]] = -1; 00892 checkTessellation(tessid); 00893 } 00894 00904 int getMaxTessLevel(int layid) 00905 { return maxTessLevel[layerTessIds[layid]]; } 00906 00913 int getTessLevel() const { return tessLevels[tessid]; }; 00914 00923 int getTessLevel(const int& tId) { checkTessellation(tId); return tessLevels[tId]; } 00924 00930 double getRadiusTop() 00931 { return getRadiusTop(layerId); }; 00932 00938 double getRadiusBottom() 00939 { return getRadiusBottom(layerId); }; 00940 00946 double getDepthTop() 00947 { 00948 return getEarthRadius() - getRadiusTop(layerId); 00949 } 00950 00956 double getDepthBottom() 00957 { 00958 return getEarthRadius() - getRadiusBottom(layerId); 00959 } 00960 00967 double getDepthTop(int layid) 00968 { 00969 return getEarthRadius() - getRadiusTop(layid); 00970 } 00971 00978 double getDepthBottom(int layid) 00979 { 00980 return getEarthRadius() - getRadiusBottom(layid); 00981 } 00982 00989 double getLayerThickness(int layid) 00990 { 00991 return getRadiusTop(layid) - getRadiusBottom(layid); 00992 } 00993 00999 double getLayerThickness() 01000 { 01001 return getRadiusTop() - getRadiusBottom(); 01002 } 01003 01009 double getRadius() { return radius; }; 01010 01016 double getDepth() 01017 { return getEarthRadius() - radius; }; 01018 01022 GeoTessModel* getModel() { return model; } 01023 01027 int getTessID() { return tessid; }; 01028 01039 int getLayerId(double rad) 01040 { 01041 for (int i=0; i<nLayers; ++i) 01042 if (rad <= getRadiusTop(i)) 01043 return i; 01044 01045 for (int i=nLayers-1; i>=0; --i) 01046 if (getLayerThickness(i) > 0) 01047 return i; 01048 01049 return nLayers-1; 01050 }; 01051 01055 int getLayerId() { return layerId; }; 01056 01061 string toString(); 01062 01069 double getErrorValue() 01070 { 01071 return errorValue; 01072 } 01073 01080 void setErrorValue(double errVal) 01081 { 01082 errorValue = errVal; 01083 } 01084 01092 int getVertexIndex() 01093 { 01094 vector<int>& vtid = vertices[tessid]; 01095 vector<double>& htid = hCoefficients[tessid]; 01096 for (int v = 0; v < (int) vtid.size(); ++v) 01097 if (htid[v] > 0.999999999) 01098 return vtid[v]; 01099 return -1; 01100 } 01101 01126 void getWeights(map<int, double>& weights, double dkm) 01127 { 01128 vector<int>& vtx = vertices[tessid]; 01129 vector<double>& htid = hCoefficients[tessid]; 01130 for (int i = 0; i < (int) vtx.size(); ++i) 01131 modlProfiles[vtx[i]][layerId]->getWeights(weights, dkm, radius, htid[i]); 01132 } 01133 01141 const vector<double>& getHorizontalCoefficients() const 01142 { 01143 return hCoefficients[tessid]; 01144 } 01145 01154 double getHorizontalCoefficient(int index) const 01155 { 01156 return hCoefficients[tessid][index]; 01157 } 01158 01174 bool isRadiusOutOfRangeAllowed() 01175 { 01176 return radiusOutOfRangeAllowed; 01177 } 01178 01194 void setRadiusOutOfRangeAllowed(bool allowed) 01195 { 01196 if (allowed != radiusOutOfRangeAllowed) 01197 clearRadialCoefficients(); 01198 01199 radiusOutOfRangeAllowed = allowed; 01200 } 01201 01205 void addReference() { ++refCount; } 01206 01210 void removeReference() 01211 { 01212 if (isNotReferenced()) 01213 { 01214 ostringstream os; 01215 os << endl << "ERROR in Polygon::removeReference" << endl 01216 << "Reference count (" << refCount << ") is already zero." << endl; 01217 throw GeoTessException(os, __FILE__, __LINE__, 3005); 01218 } 01219 01220 --refCount; 01221 } 01222 01228 int getReferenceCount() 01229 { 01230 return refCount; 01231 } 01232 01237 bool isNotReferenced() { return refCount == 0; } 01238 01239 }; // end class GeoTessModel 01240 01241 } // end namespace geotess 01242 01243 #endif // GEOTESSPOSITION_OBJECT_H