GeoTessCPP: include/GeoTessModel.h Source File

GeoTessCPP 2.0.0 Software to facilitate storage and retrieval of 3D information about the Earth.

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Friends Macros
GeoTessModel.h
Go to the documentation of this file.
1 //- ****************************************************************************
2 //-
3 //- Copyright 2009 Sandia Corporation. Under the terms of Contract
4 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
5 //- retains certain rights in this software.
6 //-
7 //- BSD Open Source License.
8 //- All rights reserved.
9 //-
10 //- Redistribution and use in source and binary forms, with or without
11 //- modification, are permitted provided that the following conditions are met:
12 //-
13 //- * Redistributions of source code must retain the above copyright notice,
14 //- this list of conditions and the following disclaimer.
15 //- * Redistributions in binary form must reproduce the above copyright
16 //- notice, this list of conditions and the following disclaimer in the
17 //- documentation and/or other materials provided with the distribution.
18 //- * Neither the name of Sandia National Laboratories nor the names of its
19 //- contributors may be used to endorse or promote products derived from
20 //- this software without specific prior written permission.
21 //-
22 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //- POSSIBILITY OF SUCH DAMAGE.
33 //-
34 //- ****************************************************************************
35
36 #ifndef GEOTESSMODEL_OBJECT_H
37 #define GEOTESSMODEL_OBJECT_H
38
39 // **** _SYSTEM INCLUDES_ ******************************************************
40
41 #include <iostream>
42 #include <string>
43 #include <fstream>
44 #include <vector>
45 #include <map>
46
47 // use standard library objects
48 using namespace std;
49
50 // **** _LOCAL INCLUDES_ *******************************************************
51
52 #include "CPPUtils.h"
53 #include "GeoTessUtils.h"
54 #include "InterpolatorType.h"
55 #include "GeoTessException.h"
56 #include "PointMap.h"
57 #include "ProfileSurface.h"
58 #include "ProfileEmpty.h"
59
60 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
61
62 namespace geotess
63 {
64
65 // **** _FORWARD REFERENCES_ ***************************************************
66
67 class GeoTessPosition;
68 class GeoTessGrid;
69 class GeoTessMetaData;
70 class OptimizationType;
71 class Profile;
72 class IFStreamAscii;
73 class IFStreamBinary;
74
75 // **** _CLASS DEFINITION_ *****************************************************
76
116 class GEOTESS_EXP_IMP GeoTessModel
117 {
119
120 protected:
121
133 static map<string, GeoTessGrid*> reuseGridMap;
134
138 GeoTessGrid* grid;
139
144 Profile*** profiles;
145
162 GeoTessMetaData* metaData;
163
169 PointMap* pointMap;
170
174 void deleteProfiles();
175
186 void loadModelAscii(const string& inputFile, const string& relGridFilePath);
187
204 virtual void loadModelAscii(IFStreamAscii& input, const string& inputDirectory,
205 const string& relGridFilePath);
206
220 void loadModelBinary(const string& inputFile, const string& relGridFilePath);
221
237 virtual void loadModelBinary(IFStreamBinary& input, const string& inputDirectory,
238 const string& relGridFilePath);
239
249 void writeModelAscii(const string& outputFile, const string& gridFileName);
250
260 virtual void writeModelAscii(IFStreamAscii& output, const string& gridFileName);
261
271 void writeModelBinary(const string& outputFile, const string& gridFileName);
272
282 virtual void writeModelBinary(IFStreamBinary& output, const string& gridFileName);
283
296 template<class T>
297 void loadGrid(T& input, const string& inputDirectory,
298 const string& relGridFilePath, const string& gridFileName,
299 const string& gridID, const string& funcName)
300 {
301 // process grid
302
303 grid = NULL;
304 map<string, GeoTessGrid*>::iterator it = reuseGridMap.find(gridID);
305 if (it != reuseGridMap.end())
306 grid = it->second;
307
308 if (gridFileName == "*")
309 {
310 // load the grid from this input file. The grid has to be read from the
311 // file, even a reference was retrieved from the reuseGridMap, so that the
312 // file is positioned where classes that extend GeoTessModel can read
313 // additional data.
314 GeoTessGrid* g = new GeoTessGrid(input,
315 &metaData->getOptimizationType());
316 if (!grid)
317 {
318 grid = g;
319
320 grid->setGridInputFile(metaData->getInputModelFile());
321
322 if (metaData->isGridReuseOn())
323 reuseGridMap[gridID] = grid;
324 }
325 else
326 delete g;
327 }
328 else if (!grid)
329 {
330 // build the name of the grid file using the input directory and
331 // the relative path to the grid file. Assume that both
332 // inputDirectory and relGridFilePath may be null or empty.
333 string gridFil = gridFileName;
334 if (relGridFilePath != "")
335 gridFil = CPPUtils::insertPathSeparator(relGridFilePath, gridFileName);
336 if (inputDirectory != "")
337 gridFil = CPPUtils::insertPathSeparator(inputDirectory, gridFil);
338
339 grid = new GeoTessGrid(&metaData->getOptimizationType());
340 grid->loadGrid(gridFil);
341 if (metaData->isGridReuseOn())
342 reuseGridMap[gridID] = grid;
343
344 // throw an error if the grid ID's are not equal
345
346 if (grid->getGridID() != gridID)
347 {
348 ostringstream os;
349 os << endl << "ERROR in GeoTessModel::" + funcName << endl
350 << "gridIDs in model file and existingGrid are not equal: "
351 << endl << " Model File gridID = " << gridID << endl
352 << " Grid File gridID = " << grid->getGridID() << endl;
353 throw GeoTessException(os, __FILE__, __LINE__, 1002);
354 }
355 }
356
357 // add a reference to the grid and build the point map
358
359 grid->addReference();
360 }
361
362 private:
363
364 void constructor(const string& gridFileName, GeoTessGrid* grid, GeoTessMetaData* metaData);
365
367
368 public:
369
378 GeoTessModel(const OptimizationType* optimization = &OptimizationType::SPEED);
379
405 GeoTessModel(const string& inputFile, const string& relativeGridPath,
406 const OptimizationType* optimization = &OptimizationType::SPEED);
407
424 GeoTessModel(const string& modelInputFile,
425 const OptimizationType* optimization = &OptimizationType::SPEED);
426
437 GeoTessModel(vector<int>& attributeFilter, const OptimizationType* optimization = &OptimizationType::SPEED);
438
466 GeoTessModel(const string& inputFile, const string& relativeGridPath,
467 vector<int>& attributeFilter,
468 const OptimizationType* optimization = &OptimizationType::SPEED);
469
488 GeoTessModel(const string& modelInputFile, vector<int>& attributeFilter,
489 const OptimizationType* optimization = &OptimizationType::SPEED);
490
521 GeoTessModel(const string& gridFileName, GeoTessMetaData* metaData);
522
558 GeoTessModel(GeoTessGrid* grid, GeoTessMetaData* metaData);
559
563 virtual ~GeoTessModel();
564
576 GeoTessModel* loadModel(const string& inputFile, const string& relGridFilePath = "");
577
584 static bool isGeoTessModel(const string& fileName);
585
591 static void clearReuseGrid()
592 {
593 reuseGridMap.clear();
594 }
595
602 static int getReuseGridMapSize()
603 {
604 return reuseGridMap.size();
605 }
606
610 const GeoTessGrid& getGrid() const
611 {
612 return *grid;
613 };
614
618 GeoTessGrid& getGrid()
619 {
620 return *grid;
621 };
622
629 GeoTessMetaData& getMetaData()
630 {
631 return *metaData;
632 };
633
642 GeoTessPosition* getPosition();
643
657 GeoTessPosition* getPosition(const InterpolatorType& horizontalType);
658
672 GeoTessPosition* getPosition(const InterpolatorType& horizontalType,
673 const InterpolatorType& radialType);
674
679 int getNVertices() const;
680
685 int getNLayers() const;
686
691 int getNPoints()
692 {
693 return getPointMap()->size();
694 }
695
704 bool operator == (const GeoTessModel& other) const;
705
714 bool operator != (const GeoTessModel& other) const { return !(*this == other); } ;
715
732 PointMap* getPointMap()
733 {
734 if (!pointMap->isPopulated())
735 pointMap->setActiveRegion();
736 return pointMap;
737 }
738
747 const set<int>& getConnectedVertices(int layerIndex)
748 {
749 return grid->getVertexIndicesTopLevel(metaData->getTessellation(layerIndex));
750 }
751
757 void setActiveRegion()
758 {
759 pointMap->setActiveRegion();
760 }
761
774 void setActiveRegion(const string& polygon)
775 {
776 pointMap->setActiveRegion(polygon);
777 }
778
787 void setActiveRegion(Polygon* polygon)
788 {
789 pointMap->setActiveRegion(polygon);
790 }
791
800 void getLayerCount(bool activeOnly, int* layerCount)
801 {
802 for (int layer=0; layer<getNLayers(); ++layer)
803 layerCount[layer] = 0;
804
805 Profile** pp;
806 Profile* p;
807 for (int v=0; v<getNVertices(); ++v)
808 {
809 pp = profiles[v];
810 for (int layer=0; layer<getNLayers(); ++layer)
811 {
812 if (activeOnly)
813 {
814 p = pp[layer];
815 for (int n=0; n<p->getNData(); ++n)
816 if (p->getPointIndex(n) >= 0)
817 ++layerCount[layer];
818 }
819 else
820 layerCount[layer] += pp[layer]->getNData();
821 }
822 }
823 }
824
832 Profile* getProfile(int vertex, int layer)
833 {
834 return profiles[vertex][layer];
835 }
836
843 Profile** getProfiles(int vertex)
844 {
845 return profiles[vertex];
846 }
847
851 Profile*** getProfiles() const { return profiles; }
852
863 void setProfile(int vertex, int layer, Profile* profile);
864
878 template<typename T>
879 void setProfile(int vertex, int layer, vector<float>& radii, vector<vector<T> >& values)
880 {
881 if (getConnectedVertices(layer).count(vertex) == 1)
882 setProfile(vertex, layer, Profile::newProfile(radii, values));
883 else setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[radii.size()-1]));
884 }
885
901 template<typename T>
902 void setProfile(const int& vertex, const int& layer,
903 float* radii, const int& nRadii,
904 T** values, const int& nNodes, const int& nAttributes)
905 {
906 if (getConnectedVertices(layer).count(vertex) == 1)
907 setProfile(vertex, layer, Profile::newProfile(radii, nRadii, values, nNodes, nAttributes));
908 else setProfile(vertex, layer, new ProfileEmpty(radii[0], radii[nRadii-1]));
909 }
910
919 template<typename T>
920 void setProfile(const int& vertex, vector<T>& values)
921 { setProfile(vertex, 0, new ProfileSurface(Data::getData(values))); }
922
932 template<typename T>
933 void setProfile(const int& vertex, T* values, const int& nAttributes)
934 { setProfile(vertex, 0, new ProfileSurface(Data::getData(values, nAttributes))); }
935
950 void writeModel(const string& outputFile, const string& gridFileName);
951
955 string toString();
956
964 void getLayerCount(vector<int>& layerCount, const bool& activeOnly)
965 {
966 layerCount.resize(metaData->getNLayers(), 0);
967
968 Profile** pp;
969 Profile* p;
970 for (int vtx=0; vtx<getNVertices(); ++vtx)
971 {
972 pp = profiles[vtx];
973 for (int layer = 0; layer < metaData->getNLayers(); ++layer)
974 if (activeOnly)
975 {
976 p = pp[layer];
977 for (int n = 0; n < p->getNData(); ++n)
978 if (p->getPointIndex(n) >= 0)
979 ++layerCount[layer];
980 }
981 else
982 layerCount[layer] += pp[layer]->getNData();
983 }
984 }
985
993 void profileCount(vector< vector<int> >& count)
994 {
995 count.clear();
996
997 getPointMap();
998
999 // this is total number of profiles of each type, independent of layer index.
1000 vector<int> totalCount;
1001 for (int profileType=0; profileType<ProfileType::size(); ++profileType)
1002 totalCount.push_back(0);
1003
1004 for (int layer = 0; layer < getNLayers(); ++layer)
1005 {
1006 vector<int> typeCount;
1007
1008 for (int profileType=0; profileType<ProfileType::size(); ++profileType)
1009 typeCount.push_back(0);
1010
1011 count.push_back(typeCount);
1012 }
1013
1014 for (int layer = 0; layer < getNLayers(); ++layer)
1015 {
1016 for (int vertex = 0; vertex < metaData->getNVertices(); ++vertex)
1017 {
1018 int pType = profiles[vertex][layer]->getType().ordinal();
1019 count[layer][pType] += 1;
1020 totalCount[pType] += 1;
1021 }
1022 }
1023
1024 count.push_back(totalCount);
1025 }
1026
1060 template<typename T>
1061 void initializeData(const vector<string>& attributeNames,
1062 const vector<string>& attributeUnits, T fillValue)
1063 {
1064 if (profiles == NULL)
1065 {
1066 ostringstream os;
1067 os << endl << "ERROR in GeoTessModel::initializeData" << endl
1068 << "Attempting to initialize the model data before Profiles" << endl
1069 << "have been specified (profiles == NULL)" << endl;
1070 throw GeoTessException(os, __FILE__, __LINE__, 1001);
1071 }
1072
1073 const DataType& newDataType = DataType::getDataType(fillValue);
1074 int nAttributesNew = attributeNames.size();
1075
1076 int newDataTypeOrdinal = newDataType.ordinal();
1077 int oldDataTypeOrdinal = metaData->getDataType().ordinal();
1078
1079 // if neither the dataType or the number of attributes has changed, there is no need to
1080 // copy the data. The only thing that happens is that the attributeNames or attributeUnits might change.
1081 if (newDataTypeOrdinal != oldDataTypeOrdinal || nAttributesNew != metaData->getNAttributes())
1082 {
1083 // initialize an array of the new dataType with number of elements
1084 // equal to the number of new attributes and populate it with fillValue.
1085 T* newValues = new T[nAttributesNew];
1086 for (int i=0; i<nAttributesNew; ++i)
1087 newValues[i] = fillValue;
1088
1089 Profile* profile;
1090 vector<Data*> data;
1091 for (int v = 0; v < getNVertices(); ++v)
1092 for (int lid = 0; lid < getNLayers(); ++lid)
1093 {
1094 profile = profiles[v][lid];
1095 data.reserve(profile->getNData());
1096 data.clear();
1097 for (int n = 0; n < profile->getNData(); ++n)
1098 {
1099 profile->getData(n)->getValues(newValues, nAttributesNew);
1100 data.push_back(Data::getData(newValues, nAttributesNew));
1101 }
1102 // set new entries into profile and continue
1103 profile->setData(data);
1104 }
1105 delete[] newValues;
1106 }
1107
1108 metaData->setDataType(newDataType);
1109
1110 metaData->setAttributes(attributeNames, attributeUnits);
1111 }
1112
1125 template<typename T>
1126 void initializeData(const string& attributeNames,
1127 const string& attributeUnits, T fillValue)
1128 {
1129 vector<string> names;
1130 CPPUtils::tokenizeString(attributeNames, ";", names);
1131 vector<string> units;
1132 CPPUtils::tokenizeString(attributeUnits, ";", units);
1133 initializeData(names, units, fillValue);
1134 }
1135
1136
1137
1151 void getWeights(const vector<double*>& vectors,
1152 const vector<double>& radii, const InterpolatorType& horizontalType,
1153 const InterpolatorType& radialType,
1154 map<int, double>& weights);
1155
1156
1157
1158
1160
1161
1162
1163
1167 bool isSupportedFormatVersion(int frmtVrsn)
1168 { return (frmtVrsn == 1) ? true : false; }
1169
1175 bool testLayerRadii();
1176
1190 void writeModel(const string& outputFile)
1191 { writeModel(outputFile, getGridFileReference()); }
1192
1202 string getGridFileReference() const
1203 {
1204 if (grid->getGridInputFile() == metaData->getInputModelFile())
1205 return "*";
1206
1207 return grid->getGridInputFile();
1208 }
1209
1211
1212 };
1213 // end class GeoTessModel
1214
1215 }// end namespace geotess
1216
1217 #endif // GEOTESSMODEL_OBJECT_H