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"
55 #include "GeoTessException.h"
56 #include "GeoTessPointMap.h"
57 #include "GeoTessProfileSurface.h"
58 #include "GeoTessProfileEmpty.h"
60 
61 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
62 
63 namespace geotess
64 {
65 
66 // **** _FORWARD REFERENCES_ ***************************************************
67 
68 class GeoTessPosition;
69 class GeoTessGrid;
70 class GeoTessMetaData;
71 class GeoTessOptimizationType;
72 class GeoTessProfile;
73 class IFStreamAscii;
74 class IFStreamBinary;
75 
76 // **** _CLASS DEFINITION_ *****************************************************
77 
118 {
120 
121 protected:
122 
134  static map<string, GeoTessGrid*> reuseGridMap;
135 
139  GeoTessGrid* grid;
140 
145  GeoTessProfile*** profiles;
146 
163  GeoTessMetaData* metaData;
164 
170  GeoTessPointMap* pointMap;
171 
175  void deleteProfiles();
176 
187  void loadModelAscii(const string& inputFile, const string& relGridFilePath);
188 
205  virtual void loadModelAscii(IFStreamAscii& input, const string& inputDirectory,
206  const string& relGridFilePath);
207 
221  void loadModelBinary(const string& inputFile, const string& relGridFilePath);
222 
238  virtual void loadModelBinary(IFStreamBinary& input, const string& inputDirectory,
239  const string& relGridFilePath);
240 
250  void writeModelAscii(const string& outputFile, const string& gridFileName);
251 
261  virtual void writeModelAscii(IFStreamAscii& output, const string& gridFileName);
262 
272  void writeModelBinary(const string& outputFile, const string& gridFileName);
273 
283  virtual void writeModelBinary(IFStreamBinary& output, const string& gridFileName);
284 
297  template<class T>
298  void loadGrid(T& input, const string& inputDirectory,
299  const string& relGridFilePath, const string& gridFileName,
300  const string& gridID, const string& funcName)
301  {
302  // process grid
303 
304  grid = NULL;
305  map<string, GeoTessGrid*>::iterator it = reuseGridMap.find(gridID);
306  if (it != reuseGridMap.end())
307  grid = it->second;
308 
309  if (gridFileName == "*")
310  {
311  // load the grid from this input file. The grid has to be read from the
312  // file, even a reference was retrieved from the reuseGridMap, so that the
313  // file is positioned where classes that extend GeoTessModel can read
314  // additional data.
315  GeoTessGrid* g = new GeoTessGrid(input,
316  &metaData->getOptimizationType());
317  if (!grid)
318  {
319  grid = g;
320 
321  grid->setGridInputFile(metaData->getInputModelFile());
322 
323  if (metaData->isGridReuseOn())
324  reuseGridMap[gridID] = grid;
325  }
326  else
327  delete g;
328  }
329  else if (!grid)
330  {
331  // build the name of the grid file using the input directory and
332  // the relative path to the grid file. Assume that both
333  // inputDirectory and relGridFilePath may be null or empty.
334  string gridFil = gridFileName;
335  if (relGridFilePath != "")
336  gridFil = CPPUtils::insertPathSeparator(relGridFilePath, gridFileName);
337  if (inputDirectory != "")
338  gridFil = CPPUtils::insertPathSeparator(inputDirectory, gridFil);
339 
340  grid = new GeoTessGrid(&metaData->getOptimizationType());
341  grid->loadGrid(gridFil);
342  if (metaData->isGridReuseOn())
343  reuseGridMap[gridID] = grid;
344 
345  // throw an error if the grid ID's are not equal
346 
347  if (grid->getGridID() != gridID)
348  {
349  ostringstream os;
350  os << endl << "ERROR in GeoTessModel::" + funcName << endl
351  << "gridIDs in model file and existingGrid are not equal: "
352  << endl << " Model File gridID = " << gridID << endl
353  << " Grid File gridID = " << grid->getGridID() << endl;
354  throw GeoTessException(os, __FILE__, __LINE__, 1002);
355  }
356  }
357 
358  // add a reference to the grid and build the point map
359 
360  grid->addReference();
361  }
362 
363 private:
364 
365  void constructor(const string& gridFileName, GeoTessGrid* grid, GeoTessMetaData* metaData);
366 
368 
369 public:
370 
379  GeoTessModel(const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
380 
406  GeoTessModel(const string& inputFile, const string& relativeGridPath,
407  const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
408 
425  GeoTessModel(const string& modelInputFile,
426  const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
427 
438  GeoTessModel(vector<int>& attributeFilter, const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
439 
467  GeoTessModel(const string& inputFile, const string& relativeGridPath,
468  vector<int>& attributeFilter,
469  const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
470 
489  GeoTessModel(const string& modelInputFile, vector<int>& attributeFilter,
490  const GeoTessOptimizationType* optimization = &GeoTessOptimizationType::SPEED);
491 
522  GeoTessModel(const string& gridFileName, GeoTessMetaData* metaData);
523 
559  GeoTessModel(GeoTessGrid* grid, GeoTessMetaData* metaData);
560 
564  virtual ~GeoTessModel();
565 
570  static string class_name() { return "GeoTessModel"; };
571 
583  GeoTessModel* loadModel(const string& inputFile, const string& relGridFilePath = "");
584 
591  static bool isGeoTessModel(const string& fileName);
592 
598  static void clearReuseGrid()
599  {
600  reuseGridMap.clear();
601  }
602 
609  static int getReuseGridMapSize()
610  {
611  return reuseGridMap.size();
612  }
613 
618  const GeoTessGrid& getGrid() const
619  {
620  return *grid;
621  };
622 
627  GeoTessGrid& getGrid()
628  {
629  return *grid;
630  };
631 
639  GeoTessMetaData& getMetaData()
640  {
641  return *metaData;
642  };
643 
652  GeoTessPosition* getPosition();
653 
667  GeoTessPosition* getPosition(const GeoTessInterpolatorType& horizontalType);
668 
682  GeoTessPosition* getPosition(const GeoTessInterpolatorType& horizontalType,
683  const GeoTessInterpolatorType& radialType);
684 
689  int getNVertices() const { return grid->getNVertices(); }
690 
695  int getNLayers() const { return metaData->getNLayers(); }
696 
704  int getNRadii(int vertexId, int layerId) { return profiles[vertexId][layerId]->getNRadii(); }
705 
713  int getNData(int vertexId, int layerId) { return profiles[vertexId][layerId]->getNData(); }
714 
719  int getNAttributes() { return metaData->getNAttributes(); }
720 
728  double getRadius(int vertexId, int layerId, int nodeId)
729  { return profiles[vertexId][layerId]->getRadius(nodeId); }
730 
739  double getDepth(int vertexId, int layerId, int nodeId)
740  { return GeoTessUtils::getEarthRadius(grid->getVertex(vertexId))
741  - profiles[vertexId][layerId]->getRadius(nodeId); }
742 
752  double getValueDouble(int vertexId, int layerId, int nodeId, int attributeIndex)
753  {
754  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
755  return data == NULL ? NaN_DOUBLE : data->getDouble(attributeIndex);
756  }
757 
767  float getValueFloat(int vertexId, int layerId, int nodeId, int attributeIndex)
768  {
769  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
770  return data == NULL ? NaN_FLOAT : data->getFloat(attributeIndex);
771  }
772 
782  LONG_INT getValueLong(int vertexId, int layerId, int nodeId, int attributeIndex)
783  {
784  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
785  return data == NULL ? LONG_MIN : data->getLong(attributeIndex);
786  }
787 
797  int getValueInt(int vertexId, int layerId, int nodeId, int attributeIndex)
798  {
799  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
800  return data == NULL ? INT_MIN : data->getInt(attributeIndex);
801  }
802 
812  short getValueShort(int vertexId, int layerId, int nodeId, int attributeIndex)
813  {
814  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
815  return data == NULL ? SHRT_MIN : data->getShort(attributeIndex);
816  }
817 
827  byte getValueByte(int vertexId, int layerId, int nodeId, int attributeIndex)
828  {
829  GeoTessData* data = profiles[vertexId][layerId]->getData(nodeId);
830  return data == NULL ? CHAR_MIN : data->getByte(attributeIndex);
831  }
832 
842  template<typename T>
843  void setValue(int vertexId, int layerId, int nodeId, int attributeIndex, T value)
844  { profiles[vertexId][layerId]->getData(nodeId)->setValue(attributeIndex, value); }
845 
851  double getRadius(int pointIndex)
852  { return getPointMap()->getPointRadius(pointIndex); }
853 
860  double getDepth(int pointIndex)
861  { return getPointMap()->getPointDepth(pointIndex); }
862 
870  double getValueDouble(int pointIndex, int attributeIndex)
871  {
872  GeoTessData* data = getPointMap()->getPointData(pointIndex);
873  return data == NULL ? NaN_DOUBLE : data->getDouble(attributeIndex);
874  }
875 
883  float getValueFloat(int pointIndex, int attributeIndex)
884  {
885  GeoTessData* data = getPointMap()->getPointData(pointIndex);
886  return data == NULL ? NaN_FLOAT : data->getFloat(attributeIndex);
887  }
888 
896  LONG_INT getValueLong(int pointIndex, int attributeIndex)
897  {
898  GeoTessData* data = getPointMap()->getPointData(pointIndex);
899  return data == NULL ? LONG_MIN : data->getLong(attributeIndex);
900  }
901 
909  int getValueInt(int pointIndex, int attributeIndex)
910  {
911  GeoTessData* data = getPointMap()->getPointData(pointIndex);
912  return data == NULL ? INT_MIN : data->getInt(attributeIndex);
913  }
914 
922  short getValueShort(int pointIndex, int attributeIndex)
923  {
924  GeoTessData* data = getPointMap()->getPointData(pointIndex);
925  return data == NULL ? SHRT_MIN : data->getShort(attributeIndex);
926  }
927 
935  byte getValueByte(int pointIndex, int attributeIndex)
936  {
937  GeoTessData* data = getPointMap()->getPointData(pointIndex);
938  return data == NULL ? CHAR_MIN : data->getByte(attributeIndex);
939  }
940 
948  template<typename T>
949  void setValue(int pointIndex, int attributeIndex, T value)
950  {
951  GeoTessData* data = getPointMap()->getPointData(pointIndex);
952  if (data != NULL) data->setValue(attributeIndex, value);
953  }
954 
960  int getNPoints() { return getPointMap()->size(); }
961 
970  virtual bool operator == (const GeoTessModel& other) const;
971 
980  virtual bool operator != (const GeoTessModel& other) const { return !(*this == other); } ;
981 
999  GeoTessPointMap* getPointMap()
1000  {
1001  if (!pointMap->isPopulated())
1002  pointMap->setActiveRegion();
1003  return pointMap;
1004  }
1005 
1014  const set<int>& getConnectedVertices(int layerIndex)
1015  {
1016  return grid->getVertexIndicesTopLevel(metaData->getTessellation(layerIndex));
1017  }
1018 
1024  void setActiveRegion()
1025  {
1026  pointMap->setActiveRegion();
1027  }
1028 
1041  void setActiveRegion(const string& polygon)
1042  {
1043  pointMap->setActiveRegion(polygon);
1044  }
1045 
1057  void setActiveRegion(GeoTessPolygon* polygon)
1058  {
1059  pointMap->setActiveRegion(polygon);
1060  }
1061 
1070  void getLayerCount(bool activeOnly, int* layerCount)
1071  {
1072  for (int layer=0; layer<getNLayers(); ++layer)
1073  layerCount[layer] = 0;
1074 
1075  GeoTessProfile** pp;
1076  GeoTessProfile* p;
1077  for (int v=0; v<getNVertices(); ++v)
1078  {
1079  pp = profiles[v];
1080  for (int layer=0; layer<getNLayers(); ++layer)
1081  {
1082  if (activeOnly)
1083  {
1084  p = pp[layer];
1085  for (int n=0; n<p->getNData(); ++n)
1086  if (p->getPointIndex(n) >= 0)
1087  ++layerCount[layer];
1088  }
1089  else
1090  layerCount[layer] += pp[layer]->getNData();
1091  }
1092  }
1093  }
1094 
1102  GeoTessProfile* getProfile(int vertex, int layer)
1103  {
1104  return profiles[vertex][layer];
1105  }
1106 
1113  GeoTessProfile** getProfiles(int vertex)
1114  {
1115  return profiles[vertex];
1116  }
1117 
1122  GeoTessProfile*** getProfiles() const { return profiles; }
1123 
1134  void setProfile(int vertex, int layer, GeoTessProfile* profile);
1135 
1149  template<typename T>
1150  void setProfile(int vertex, int layer, vector<float>& radii, vector<vector<T> >& values)
1151  {
1152  if (getConnectedVertices(layer).count(vertex) == 1)
1153  setProfile(vertex, layer, GeoTessProfile::newProfile(radii, values));
1154  else setProfile(vertex, layer, new GeoTessProfileEmpty(radii[0], radii[radii.size()-1]));
1155  }
1156 
1172  template<typename T>
1173  void setProfile(const int& vertex, const int& layer,
1174  float* radii, const int& nRadii,
1175  T** values, const int& nNodes, const int& nAttributes)
1176  {
1177  if (getConnectedVertices(layer).count(vertex) == 1)
1178  setProfile(vertex, layer, GeoTessProfile::newProfile(radii, nRadii, values, nNodes, nAttributes));
1179  else setProfile(vertex, layer, new GeoTessProfileEmpty(radii[0], radii[nRadii-1]));
1180  }
1181 
1190  void setProfile(int vertex, int layer, vector<float>& radii)
1191  { setProfile(vertex, layer, new GeoTessProfileEmpty(radii[0], radii[radii.size()-1])); }
1192 
1202  template<typename T>
1203  void setProfile(const int& vertex, const int& layer, float* radii, const int& nRadii)
1204  { setProfile(vertex, layer, new GeoTessProfileEmpty(radii[0], radii[nRadii-1])); }
1205 
1214  template<typename T>
1215  void setProfile(const int& vertex, vector<T>& values)
1216  { setProfile(vertex, 0, new GeoTessProfileSurface(GeoTessData::getData(values))); }
1217 
1227  template<typename T>
1228  void setProfile(const int& vertex, T* values, const int& nAttributes)
1229  { setProfile(vertex, 0, new GeoTessProfileSurface(GeoTessData::getData(values, nAttributes))); }
1230 
1236  void setProfile(const int& vertex)
1237  { setProfile(vertex, 0, new GeoTessProfileSurfaceEmpty()); }
1238 
1253  void writeModel(const string& outputFile, const string& gridFileName);
1254 
1259  string toString();
1260 
1268  void getLayerCount(vector<int>& layerCount, const bool& activeOnly)
1269  {
1270  layerCount.resize(metaData->getNLayers(), 0);
1271 
1272  GeoTessProfile** pp;
1273  GeoTessProfile* p;
1274  for (int vtx=0; vtx<getNVertices(); ++vtx)
1275  {
1276  pp = profiles[vtx];
1277  for (int layer = 0; layer < metaData->getNLayers(); ++layer)
1278  if (activeOnly)
1279  {
1280  p = pp[layer];
1281  for (int n = 0; n < p->getNData(); ++n)
1282  if (p->getPointIndex(n) >= 0)
1283  ++layerCount[layer];
1284  }
1285  else
1286  layerCount[layer] += pp[layer]->getNData();
1287  }
1288  }
1289 
1297  void profileCount(vector< vector<int> >& count)
1298  {
1299  count.clear();
1300 
1301  getPointMap();
1302 
1303  // this is total number of profiles of each type, independent of layer index.
1304  vector<int> totalCount;
1305  for (int profileType=0; profileType<GeoTessProfileType::size(); ++profileType)
1306  totalCount.push_back(0);
1307 
1308  for (int layer = 0; layer < getNLayers(); ++layer)
1309  {
1310  vector<int> typeCount;
1311 
1312  for (int profileType=0; profileType<GeoTessProfileType::size(); ++profileType)
1313  typeCount.push_back(0);
1314 
1315  count.push_back(typeCount);
1316  }
1317 
1318  for (int layer = 0; layer < getNLayers(); ++layer)
1319  {
1320  for (int vertex = 0; vertex < metaData->getNVertices(); ++vertex)
1321  {
1322  int pType = profiles[vertex][layer]->getType().ordinal();
1323  count[layer][pType] += 1;
1324  totalCount[pType] += 1;
1325  }
1326  }
1327 
1328  count.push_back(totalCount);
1329  }
1330 
1364  template<typename T>
1365  void initializeData(const vector<string>& attributeNames,
1366  const vector<string>& attributeUnits, T fillValue)
1367  {
1368  if (profiles == NULL)
1369  {
1370  ostringstream os;
1371  os << endl << "ERROR in GeoTessModel::initializeData" << endl
1372  << "Attempting to initialize the model data before Profiles" << endl
1373  << "have been specified (profiles == NULL)" << endl;
1374  throw GeoTessException(os, __FILE__, __LINE__, 1001);
1375  }
1376 
1377  const GeoTessDataType& newDataType = GeoTessDataType::getDataType(fillValue);
1378  int nAttributesNew = attributeNames.size();
1379 
1380  int newDataTypeOrdinal = newDataType.ordinal();
1381  int oldDataTypeOrdinal = metaData->getDataType().ordinal();
1382 
1383  // if neither the dataType or the number of attributes has changed, there is no need to
1384  // copy the data. The only thing that happens is that the attributeNames or attributeUnits might change.
1385  if (newDataTypeOrdinal != oldDataTypeOrdinal || nAttributesNew != metaData->getNAttributes())
1386  {
1387  // initialize an array of the new dataType with number of elements
1388  // equal to the number of new attributes and populate it with fillValue.
1389  T* newValues = new T[nAttributesNew];
1390  for (int i=0; i<nAttributesNew; ++i)
1391  newValues[i] = fillValue;
1392 
1393  GeoTessProfile* profile;
1394  vector<GeoTessData*> data;
1395  for (int v = 0; v < getNVertices(); ++v)
1396  for (int lid = 0; lid < getNLayers(); ++lid)
1397  {
1398  profile = profiles[v][lid];
1399  data.reserve(profile->getNData());
1400  data.clear();
1401  for (int n = 0; n < profile->getNData(); ++n)
1402  {
1403  profile->getData(n)->getValues(newValues, nAttributesNew);
1404  data.push_back(GeoTessData::getData(newValues, nAttributesNew));
1405  }
1406  // set new entries into profile and continue
1407  profile->setData(data);
1408  }
1409  delete[] newValues;
1410  }
1411 
1412  metaData->setDataType(newDataType);
1413 
1414  metaData->setAttributes(attributeNames, attributeUnits);
1415  }
1416 
1429  template<typename T>
1430  void initializeData(const string& attributeNames,
1431  const string& attributeUnits, T fillValue)
1432  {
1433  vector<string> names;
1434  CPPUtils::tokenizeString(attributeNames, ";", names);
1435  vector<string> units;
1436  CPPUtils::tokenizeString(attributeUnits, ";", units);
1437  initializeData(names, units, fillValue);
1438  }
1439 
1459  void getWeights(const vector<double*>& rayPath, const vector<double>& radii,
1460  const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType,
1461  map<int, double>& weights);
1462 
1483  void getWeights(double** rayPath, double* radii, const int& numPoints,
1484  const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType,
1485  map<int, double>& weights);
1486 
1516  double getPathIntegral(const int& attribute, const bool& reciprocal,
1517  double** rayPath, double* radii, const int& numPoints,
1518  const GeoTessInterpolatorType& horizontalType, const GeoTessInterpolatorType& radialType);
1519 
1557  double getPathIntegral(const int& attribute, const bool& reciprocal,
1558  double** rayPath, double* radii, const int& numPoints,
1559  const GeoTessInterpolatorType& horizontalType,
1560  const GeoTessInterpolatorType& radialType,
1561  map<int, double>& weights);
1562 
1564 
1565 
1569  bool isSupportedFormatVersion(int frmtVrsn)
1570  { return (frmtVrsn == 1) ? true : false; }
1571 
1577  bool testLayerRadii();
1578 
1592  void writeModel(const string& outputFile)
1593  { writeModel(outputFile, getGridFileReference()); }
1594 
1604  string getGridFileReference() const
1605  {
1606  if (grid->getGridInputFile() == metaData->getInputModelFile())
1607  return "*";
1608 
1609  return grid->getGridInputFile();
1610  }
1611 
1613 
1614 };
1615 // end class GeoTessModel
1616 
1617 }// end namespace geotess
1618 
1619 #endif // GEOTESSMODEL_OBJECT_H