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 GEOTESSMODEL_OBJECT_H 00037 #define GEOTESSMODEL_OBJECT_H 00038 00039 // **** _SYSTEM INCLUDES_ ****************************************************** 00040 00041 #include <iostream> 00042 #include <string> 00043 #include <fstream> 00044 #include <vector> 00045 #include <map> 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 "InterpolatorType.h" 00055 #include "GeoTessException.h" 00056 #include "PointMap.h" 00057 #include "ProfileSurface.h" 00058 #include "ProfileEmpty.h" 00059 #include "ProfileSurfaceEmpty.h" 00060 00061 // **** _BEGIN GEOTESS NAMESPACE_ ********************************************** 00062 00063 namespace geotess 00064 { 00065 00066 // **** _FORWARD REFERENCES_ *************************************************** 00067 00068 class GeoTessPosition; 00069 class GeoTessGrid; 00070 class GeoTessMetaData; 00071 class OptimizationType; 00072 class Profile; 00073 class IFStreamAscii; 00074 class IFStreamBinary; 00075 00076 // **** _CLASS DEFINITION_ ***************************************************** 00077 00117 class GEOTESS_EXP_IMP GeoTessModel 00118 { 00120 00121 protected: 00122 00134 static map<string, GeoTessGrid*> reuseGridMap; 00135 00139 GeoTessGrid* grid; 00140 00145 Profile*** profiles; 00146 00163 GeoTessMetaData* metaData; 00164 00170 PointMap* pointMap; 00171 00175 void deleteProfiles(); 00176 00187 void loadModelAscii(const string& inputFile, const string& relGridFilePath); 00188 00205 virtual void loadModelAscii(IFStreamAscii& input, const string& inputDirectory, 00206 const string& relGridFilePath); 00207 00221 void loadModelBinary(const string& inputFile, const string& relGridFilePath); 00222 00238 virtual void loadModelBinary(IFStreamBinary& input, const string& inputDirectory, 00239 const string& relGridFilePath); 00240 00250 void writeModelAscii(const string& outputFile, const string& gridFileName); 00251 00261 virtual void writeModelAscii(IFStreamAscii& output, const string& gridFileName); 00262 00272 void writeModelBinary(const string& outputFile, const string& gridFileName); 00273 00283 virtual void writeModelBinary(IFStreamBinary& output, const string& gridFileName); 00284 00297 template<class T> 00298 void loadGrid(T& input, const string& inputDirectory, 00299 const string& relGridFilePath, const string& gridFileName, 00300 const string& gridID, const string& funcName) 00301 { 00302 // process grid 00303 00304 grid = NULL; 00305 map<string, GeoTessGrid*>::iterator it = reuseGridMap.find(gridID); 00306 if (it != reuseGridMap.end()) 00307 grid = it->second; 00308 00309 if (gridFileName == "*") 00310 { 00311 // load the grid from this input file. The grid has to be read from the 00312 // file, even a reference was retrieved from the reuseGridMap, so that the 00313 // file is positioned where classes that extend GeoTessModel can read 00314 // additional data. 00315 GeoTessGrid* g = new GeoTessGrid(input, 00316 &metaData->getOptimizationType()); 00317 if (!grid) 00318 { 00319 grid = g; 00320 00321 grid->setGridInputFile(metaData->getInputModelFile()); 00322 00323 if (metaData->isGridReuseOn()) 00324 reuseGridMap[gridID] = grid; 00325 } 00326 else 00327 delete g; 00328 } 00329 else if (!grid) 00330 { 00331 // build the name of the grid file using the input directory and 00332 // the relative path to the grid file. Assume that both 00333 // inputDirectory and relGridFilePath may be null or empty. 00334 string gridFil = gridFileName; 00335 if (relGridFilePath != "") 00336 gridFil = CPPUtils::insertPathSeparator(relGridFilePath, gridFileName); 00337 if (inputDirectory != "") 00338 gridFil = CPPUtils::insertPathSeparator(inputDirectory, gridFil); 00339 00340 grid = new GeoTessGrid(&metaData->getOptimizationType()); 00341 grid->loadGrid(gridFil); 00342 if (metaData->isGridReuseOn()) 00343 reuseGridMap[gridID] = grid; 00344 00345 // throw an error if the grid ID's are not equal 00346 00347 if (grid->getGridID() != gridID) 00348 { 00349 ostringstream os; 00350 os << endl << "ERROR in GeoTessModel::" + funcName << endl 00351 << "gridIDs in model file and existingGrid are not equal: " 00352 << endl << " Model File gridID = " << gridID << endl 00353 << " Grid File gridID = " << grid->getGridID() << endl; 00354 throw GeoTessException(os, __FILE__, __LINE__, 1002); 00355 } 00356 } 00357 00358 // add a reference to the grid and build the point map 00359 00360 grid->addReference(); 00361 } 00362 00363 private: 00364 00365 void constructor(const string& gridFileName, GeoTessGrid* grid, GeoTessMetaData* metaData); 00366 00368 00369 public: 00370 00379 GeoTessModel(const OptimizationType* optimization = &OptimizationType::SPEED); 00380 00406 GeoTessModel(const string& inputFile, const string& relativeGridPath, 00407 const OptimizationType* optimization = &OptimizationType::SPEED); 00408 00425 GeoTessModel(const string& modelInputFile, 00426 const OptimizationType* optimization = &OptimizationType::SPEED); 00427 00438 GeoTessModel(vector<int>& attributeFilter, const OptimizationType* optimization = &OptimizationType::SPEED); 00439 00467 GeoTessModel(const string& inputFile, const string& relativeGridPath, 00468 vector<int>& attributeFilter, 00469 const OptimizationType* optimization = &OptimizationType::SPEED); 00470 00489 GeoTessModel(const string& modelInputFile, vector<int>& attributeFilter, 00490 const OptimizationType* optimization = &OptimizationType::SPEED); 00491 00522 GeoTessModel(const string& gridFileName, GeoTessMetaData* metaData); 00523 00559 GeoTessModel(GeoTessGrid* grid, GeoTessMetaData* metaData); 00560 00564 virtual ~GeoTessModel(); 00565 00570 static string class_name() { return "GeoTessModel"; }; 00571 00583 GeoTessModel* loadModel(const string& inputFile, const string& relGridFilePath = ""); 00584 00591 static bool isGeoTessModel(const string& fileName); 00592 00598 static void clearReuseGrid() 00599 { 00600 reuseGridMap.clear(); 00601 } 00602 00609 static int getReuseGridMapSize() 00610 { 00611 return reuseGridMap.size(); 00612 } 00613 00618 const GeoTessGrid& getGrid() const 00619 { 00620 return *grid; 00621 }; 00622 00627 GeoTessGrid& getGrid() 00628 { 00629 return *grid; 00630 }; 00631 00639 GeoTessMetaData& getMetaData() 00640 { 00641 return *metaData; 00642 }; 00643 00652 GeoTessPosition* getPosition(); 00653 00667 GeoTessPosition* getPosition(const InterpolatorType& horizontalType); 00668 00682 GeoTessPosition* getPosition(const InterpolatorType& horizontalType, 00683 const InterpolatorType& radialType); 00684 00689 int getNVertices() const { return grid->getNVertices(); } 00690 00695 int getNLayers() const { return metaData->getNLayers(); } 00696 00704 int getNRadii(int vertexId, int layerId) { return profiles[vertexId][layerId]->getNRadii(); } 00705 00713 int getNData(int vertexId, int layerId) { return profiles[vertexId][layerId]->getNData(); } 00714 00719 int getNAttributes() { return metaData->getNAttributes(); } 00720 00728 double getRadius(int vertexId, int layerId, int nodeId) 00729 { return profiles[vertexId][layerId]->getRadius(nodeId); } 00730 00739 double getDepth(int vertexId, int layerId, int nodeId) 00740 { return GeoTessUtils::getEarthRadius(grid->getVertex(vertexId)) 00741 - profiles[vertexId][layerId]->getRadius(nodeId); } 00742 00752 double getValueDouble(int vertexId, int layerId, int nodeId, int attributeIndex) 00753 { 00754 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00755 return data == NULL ? NaN_DOUBLE : data->getDouble(attributeIndex); 00756 } 00757 00767 float getValueFloat(int vertexId, int layerId, int nodeId, int attributeIndex) 00768 { 00769 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00770 return data == NULL ? NaN_FLOAT : data->getFloat(attributeIndex); 00771 } 00772 00782 LONG_INT getValueLong(int vertexId, int layerId, int nodeId, int attributeIndex) 00783 { 00784 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00785 return data == NULL ? LONG_MIN : data->getLong(attributeIndex); 00786 } 00787 00797 int getValueInt(int vertexId, int layerId, int nodeId, int attributeIndex) 00798 { 00799 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00800 return data == NULL ? INT_MIN : data->getInt(attributeIndex); 00801 } 00802 00812 short getValueShort(int vertexId, int layerId, int nodeId, int attributeIndex) 00813 { 00814 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00815 return data == NULL ? SHRT_MIN : data->getShort(attributeIndex); 00816 } 00817 00827 byte getValueByte(int vertexId, int layerId, int nodeId, int attributeIndex) 00828 { 00829 Data* data = profiles[vertexId][layerId]->getData(nodeId); 00830 return data == NULL ? CHAR_MIN : data->getByte(attributeIndex); 00831 } 00832 00842 template<typename T> 00843 void setValue(int vertexId, int layerId, int nodeId, int attributeIndex, T value) 00844 { profiles[vertexId][layerId]->getData(nodeId)->setValue(attributeIndex, value); } 00845 00851 double getRadius(int pointIndex) 00852 { return getPointMap()->getPointRadius(pointIndex); } 00853 00860 double getDepth(int pointIndex) 00861 { return getPointMap()->getPointDepth(pointIndex); } 00862 00870 double getValueDouble(int pointIndex, int attributeIndex) 00871 { 00872 Data* data = getPointMap()->getPointData(pointIndex); 00873 return data == NULL ? NaN_DOUBLE : data->getDouble(attributeIndex); 00874 } 00875 00883 float getValueFloat(int pointIndex, int attributeIndex) 00884 { 00885 Data* data = getPointMap()->getPointData(pointIndex); 00886 return data == NULL ? NaN_FLOAT : data->getFloat(attributeIndex); 00887 } 00888 00896 LONG_INT getValueLong(int pointIndex, int attributeIndex) 00897 { 00898 Data* data = getPointMap()->getPointData(pointIndex); 00899 return data == NULL ? LONG_MIN : data->getLong(attributeIndex); 00900 } 00901 00909 int getValueInt(int pointIndex, int attributeIndex) 00910 { 00911 Data* data = getPointMap()->getPointData(pointIndex); 00912 return data == NULL ? INT_MIN : data->getInt(attributeIndex); 00913 } 00914 00922 short getValueShort(int pointIndex, int attributeIndex) 00923 { 00924 Data* data = getPointMap()->getPointData(pointIndex); 00925 return data == NULL ? SHRT_MIN : data->getShort(attributeIndex); 00926 } 00927 00935 byte getValueByte(int pointIndex, int attributeIndex) 00936 { 00937 Data* data = getPointMap()->getPointData(pointIndex); 00938 return data == NULL ? CHAR_MIN : data->getByte(attributeIndex); 00939 } 00940 00948 template<typename T> 00949 void setValue(int pointIndex, int attributeIndex, T value) 00950 { 00951 Data* data = getPointMap()->getPointData(pointIndex); 00952 if (data != NULL) data->setValue(attributeIndex, value); 00953 } 00954 00960 int getNPoints() { return getPointMap()->size(); } 00961 00970 virtual bool operator == (const GeoTessModel& other) const; 00971 00980 virtual bool operator != (const GeoTessModel& other) const { return !(*this == other); } ; 00981 00999 PointMap* getPointMap() 01000 { 01001 if (!pointMap->isPopulated()) 01002 pointMap->setActiveRegion(); 01003 return pointMap; 01004 } 01005 01014 const set<int>& getConnectedVertices(int layerIndex) 01015 { 01016 return grid->getVertexIndicesTopLevel(metaData->getTessellation(layerIndex)); 01017 } 01018 01024 void setActiveRegion() 01025 { 01026 pointMap->setActiveRegion(); 01027 } 01028 01041 void setActiveRegion(const string& polygon) 01042 { 01043 pointMap->setActiveRegion(polygon); 01044 } 01045 01057 void setActiveRegion(Polygon* polygon) 01058 { 01059 pointMap->setActiveRegion(polygon); 01060 } 01061 01070 void getLayerCount(bool activeOnly, int* layerCount) 01071 { 01072 for (int layer=0; layer<getNLayers(); ++layer) 01073 layerCount[layer] = 0; 01074 01075 Profile** pp; 01076 Profile* p; 01077 for (int v=0; v<getNVertices(); ++v) 01078 { 01079 pp = profiles[v]; 01080 for (int layer=0; layer<getNLayers(); ++layer) 01081 { 01082 if (activeOnly) 01083 { 01084 p = pp[layer]; 01085 for (int n=0; n<p->getNData(); ++n) 01086 if (p->getPointIndex(n) >= 0) 01087 ++layerCount[layer]; 01088 } 01089 else 01090 layerCount[layer] += pp[layer]->getNData(); 01091 } 01092 } 01093 } 01094 01102 Profile* getProfile(int vertex, int layer) 01103 { 01104 return profiles[vertex][layer]; 01105 } 01106 01113 Profile** getProfiles(int vertex) 01114 { 01115 return profiles[vertex]; 01116 } 01117 01122 Profile*** getProfiles() const { return profiles; } 01123 01134 void setProfile(int vertex, int layer, Profile* profile); 01135 01149 template<typename T> 01150 void setProfile(int vertex, int layer, vector<float>& radii, vector<vector<T> >& values) 01151 { 01152 if (getConnectedVertices(layer).count(vertex) == 1) 01153 setProfile(vertex, layer, Profile::newProfile(radii, values)); 01154 else setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[radii.size()-1])); 01155 } 01156 01172 template<typename T> 01173 void setProfile(const int& vertex, const int& layer, 01174 float* radii, const int& nRadii, 01175 T** values, const int& nNodes, const int& nAttributes) 01176 { 01177 if (getConnectedVertices(layer).count(vertex) == 1) 01178 setProfile(vertex, layer, Profile::newProfile(radii, nRadii, values, nNodes, nAttributes)); 01179 else setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[nRadii-1])); 01180 } 01181 01190 void setProfile(int vertex, int layer, vector<float>& radii) 01191 { setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[radii.size()-1])); } 01192 01202 template<typename T> 01203 void setProfile(const int& vertex, const int& layer, float* radii, const int& nRadii) 01204 { setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[nRadii-1])); } 01205 01214 template<typename T> 01215 void setProfile(const int& vertex, vector<T>& values) 01216 { setProfile(vertex, 0, new ProfileSurface(Data::getData(values))); } 01217 01227 template<typename T> 01228 void setProfile(const int& vertex, T* values, const int& nAttributes) 01229 { setProfile(vertex, 0, new ProfileSurface(Data::getData(values, nAttributes))); } 01230 01236 void setProfile(const int& vertex) 01237 { setProfile(vertex, 0, new ProfileSurfaceEmpty()); } 01238 01253 void writeModel(const string& outputFile, const string& gridFileName); 01254 01259 string toString(); 01260 01268 void getLayerCount(vector<int>& layerCount, const bool& activeOnly) 01269 { 01270 layerCount.resize(metaData->getNLayers(), 0); 01271 01272 Profile** pp; 01273 Profile* p; 01274 for (int vtx=0; vtx<getNVertices(); ++vtx) 01275 { 01276 pp = profiles[vtx]; 01277 for (int layer = 0; layer < metaData->getNLayers(); ++layer) 01278 if (activeOnly) 01279 { 01280 p = pp[layer]; 01281 for (int n = 0; n < p->getNData(); ++n) 01282 if (p->getPointIndex(n) >= 0) 01283 ++layerCount[layer]; 01284 } 01285 else 01286 layerCount[layer] += pp[layer]->getNData(); 01287 } 01288 } 01289 01297 void profileCount(vector< vector<int> >& count) 01298 { 01299 count.clear(); 01300 01301 getPointMap(); 01302 01303 // this is total number of profiles of each type, independent of layer index. 01304 vector<int> totalCount; 01305 for (int profileType=0; profileType<ProfileType::size(); ++profileType) 01306 totalCount.push_back(0); 01307 01308 for (int layer = 0; layer < getNLayers(); ++layer) 01309 { 01310 vector<int> typeCount; 01311 01312 for (int profileType=0; profileType<ProfileType::size(); ++profileType) 01313 typeCount.push_back(0); 01314 01315 count.push_back(typeCount); 01316 } 01317 01318 for (int layer = 0; layer < getNLayers(); ++layer) 01319 { 01320 for (int vertex = 0; vertex < metaData->getNVertices(); ++vertex) 01321 { 01322 int pType = profiles[vertex][layer]->getType().ordinal(); 01323 count[layer][pType] += 1; 01324 totalCount[pType] += 1; 01325 } 01326 } 01327 01328 count.push_back(totalCount); 01329 } 01330 01364 template<typename T> 01365 void initializeData(const vector<string>& attributeNames, 01366 const vector<string>& attributeUnits, T fillValue) 01367 { 01368 if (profiles == NULL) 01369 { 01370 ostringstream os; 01371 os << endl << "ERROR in GeoTessModel::initializeData" << endl 01372 << "Attempting to initialize the model data before Profiles" << endl 01373 << "have been specified (profiles == NULL)" << endl; 01374 throw GeoTessException(os, __FILE__, __LINE__, 1001); 01375 } 01376 01377 const DataType& newDataType = DataType::getDataType(fillValue); 01378 int nAttributesNew = attributeNames.size(); 01379 01380 int newDataTypeOrdinal = newDataType.ordinal(); 01381 int oldDataTypeOrdinal = metaData->getDataType().ordinal(); 01382 01383 // if neither the dataType or the number of attributes has changed, there is no need to 01384 // copy the data. The only thing that happens is that the attributeNames or attributeUnits might change. 01385 if (newDataTypeOrdinal != oldDataTypeOrdinal || nAttributesNew != metaData->getNAttributes()) 01386 { 01387 // initialize an array of the new dataType with number of elements 01388 // equal to the number of new attributes and populate it with fillValue. 01389 T* newValues = new T[nAttributesNew]; 01390 for (int i=0; i<nAttributesNew; ++i) 01391 newValues[i] = fillValue; 01392 01393 Profile* profile; 01394 vector<Data*> data; 01395 for (int v = 0; v < getNVertices(); ++v) 01396 for (int lid = 0; lid < getNLayers(); ++lid) 01397 { 01398 profile = profiles[v][lid]; 01399 data.reserve(profile->getNData()); 01400 data.clear(); 01401 for (int n = 0; n < profile->getNData(); ++n) 01402 { 01403 profile->getData(n)->getValues(newValues, nAttributesNew); 01404 data.push_back(Data::getData(newValues, nAttributesNew)); 01405 } 01406 // set new entries into profile and continue 01407 profile->setData(data); 01408 } 01409 delete[] newValues; 01410 } 01411 01412 metaData->setDataType(newDataType); 01413 01414 metaData->setAttributes(attributeNames, attributeUnits); 01415 } 01416 01429 template<typename T> 01430 void initializeData(const string& attributeNames, 01431 const string& attributeUnits, T fillValue) 01432 { 01433 vector<string> names; 01434 CPPUtils::tokenizeString(attributeNames, ";", names); 01435 vector<string> units; 01436 CPPUtils::tokenizeString(attributeUnits, ";", units); 01437 initializeData(names, units, fillValue); 01438 } 01439 01459 void getWeights(const vector<double*>& rayPath, const vector<double>& radii, 01460 const InterpolatorType& horizontalType, const InterpolatorType& radialType, 01461 map<int, double>& weights); 01462 01483 void getWeights(double** rayPath, double* radii, const int& numPoints, 01484 const InterpolatorType& horizontalType, const InterpolatorType& radialType, 01485 map<int, double>& weights); 01486 01516 double getPathIntegral(const int& attribute, const bool& reciprocal, 01517 double** rayPath, double* radii, const int& numPoints, 01518 const InterpolatorType& horizontalType, const InterpolatorType& radialType); 01519 01557 double getPathIntegral(const int& attribute, const bool& reciprocal, 01558 double** rayPath, double* radii, const int& numPoints, 01559 const InterpolatorType& horizontalType, 01560 const InterpolatorType& radialType, 01561 map<int, double>& weights); 01562 01564 01565 01569 bool isSupportedFormatVersion(int frmtVrsn) 01570 { return (frmtVrsn == 1) ? true : false; } 01571 01577 bool testLayerRadii(); 01578 01592 void writeModel(const string& outputFile) 01593 { writeModel(outputFile, getGridFileReference()); } 01594 01604 string getGridFileReference() const 01605 { 01606 if (grid->getGridInputFile() == metaData->getInputModelFile()) 01607 return "*"; 01608 01609 return grid->getGridInputFile(); 01610 } 01611 01613 01614 }; 01615 // end class GeoTessModel 01616 01617 }// end namespace geotess 01618 01619 #endif // GEOTESSMODEL_OBJECT_H