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 "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