GeoTessCPP  2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines
include/GeoTessPosition.h
Go to the documentation of this file.
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