GeoTessCPP  2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
 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 
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