GeoTessCPP  2.2.3
Software to facilitate storage and retrieval of 3D information about the Earth.
GeoTessProfileNPoint.h
Go to the documentation of this file.
1 //- ****************************************************************************
2 //-
3 //- Copyright 2009 National Technology & Engineering Solutions of Sandia, LLC
4 //- (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
5 //- Government 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 //- 1. Redistributions of source code must retain the above copyright notice,
14 //- this list of conditions and the following disclaimer.
15 //-
16 //- 2. Redistributions in binary form must reproduce the above copyright
17 //- notice, this list of conditions and the following disclaimer in the
18 //- documentation and/or other materials provided with the distribution.
19 //-
20 //- 3. Neither the name of the copyright holder nor the names of its
21 //- contributors may be used to endorse or promote products derived from
22 //- this software without specific prior written permission.
23 //-
24 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 //- POSSIBILITY OF SUCH DAMAGE.
35 //-
36 //- ****************************************************************************
37 
38 #ifndef PROFILENPOINT_OBJECT_H
39 #define PROFILENPOINT_OBJECT_H
40 
41 // **** _SYSTEM INCLUDES_ ******************************************************
42 
43 #include <iostream>
44 #include <string>
45 #include <fstream>
46 #include <sstream>
47 
48 // use standard library objects
49 using namespace std;
50 
51 // **** _LOCAL INCLUDES_ *******************************************************
52 
53 #include "GeoTessUtils.h"
54 #include "GeoTessException.h"
55 #include "GeoTessData.h"
56 #include "GeoTessProfile.h"
57 #include "GeoTessProfileType.h"
59 
60 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
61 
62 namespace geotess {
63 
64 // **** _FORWARD REFERENCES_ ***************************************************
65 
66 class GeoTessMetaData;
67 class IFStreamAscii;
68 class IFStreamBinary;
69 
70 // **** _CLASS DEFINITION_ *****************************************************
71 
83 {
84 private:
85 
89  int nNodes;
90 
94  float* radii;
95 
99  GeoTessData** data;
100 
107  mutable double** y2;
108 
116  int* pointIndices;
117 
121  GeoTessProfileNPoint() : GeoTessProfile(), nNodes(0), radii(NULL), data(NULL),
122  y2(NULL), pointIndices(NULL) {};
123 
128  double* spline(float* x, GeoTessData** y, int attributeIndex,
129  double yp1, double ypn) const;
130 
136  void check(int attributeIndex) const;
137 
138 public:
139 
152  GeoTessProfileNPoint(float* r, GeoTessData** dat, int size) : GeoTessProfile(), nNodes(size), radii(NULL),
153  data(NULL), y2(NULL), pointIndices(NULL)
154  {
155  radii = new float[size];
156  data = new GeoTessData*[size];
157  for (int i=0; i<size; ++i)
158  {
159  radii[i] = r[i];
160  data[i] = dat[i];
161  }
162 
163  if (radii[0] > radii[size - 1])
164  {
165  ostringstream os;
166  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
167  << "Profile has negative thickness" << endl;
168  os << "radii = ";
169  for (int i=0; i<size; ++i)
170  os << radii[i] << ", ";
171  os << endl;
172  throw GeoTessException(os, __FILE__, __LINE__, 4301);
173  }
174  }
175 
187  GeoTessProfileNPoint(const vector<float>& r, vector<GeoTessData*>& d)
188  : GeoTessProfile(), nNodes(r.size()), radii(NULL),
189  data(NULL), y2(NULL), pointIndices(NULL)
190  {
191  radii = new float[nNodes];
192  data = new GeoTessData*[nNodes];
193  for (int i=0; i<nNodes; ++i)
194  {
195  radii[i] = r[i];
196  data[i] = d[i];
197  }
198 
199  if (r.size() != d.size())
200  {
201  ostringstream os;
202  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
203  << "radii.size() != data.size()" << endl;
204  os << "radii.size = " << r.size() << endl;
205  os << "data.size = " << d.size() << endl;
206  throw GeoTessException(os, __FILE__, __LINE__, 4302);
207  }
208 
209  if (radii[0] > radii[nNodes - 1])
210  {
211  ostringstream os;
212  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
213  << "Profile has negative thickness" << endl;
214  os << "radii = ";
215  for (int i=0; i<nNodes; ++i)
216  os << radii[i] << ", ";
217  os << endl;
218  throw GeoTessException(os, __FILE__, __LINE__, 4303);
219  }
220  }
221 
227  GeoTessProfileNPoint(float* rad, const vector<GeoTessData*>& dat);
228 
232  static string class_name() { return "ProfileNPoint"; };
233 
237  virtual int class_size() const
238  { return (int) sizeof(GeoTessProfileNPoint); };
239 
240  virtual LONG_INT getMemory()
241  {
242  LONG_INT sz = (LONG_INT)sizeof(GeoTessProfileNPoint);
243  if (nNodes > 0)
244  {
245  // add memory for radii
246  sz += nNodes*(LONG_INT)sizeof(float);
247 
248  // add memory for data. assumption is made that
249  // GeoTessData objects at all nodes have the same type and
250  // number of attributes.
251  sz += nNodes*(LONG_INT)sizeof(GeoTessData*);
252  sz += nNodes*data[0]->getMemory();
253 
254  if (pointIndices)
255  sz += nNodes * (LONG_INT)(sizeof(int));
256  if (y2)
257  sz += data[0]->size() * nNodes * (LONG_INT)sizeof(double);
258  }
259  return sz;
260  }
261 
267  virtual const GeoTessProfileType& getType() const
268  { return GeoTessProfileType::NPOINT; };
269 
273  virtual bool operator == (const GeoTessProfile& p) const
274  {
275  if (!GeoTessProfile::operator==(p)) return false;
276 
277  if (nNodes != p.getNRadii()) return false;
278 
279  for (int i = 0; i < nNodes; ++i)
280  if ((radii[i] != p.getRadius(i)) ||
281  (!(*(data[i]) == p.getData(i))))
282  return false;
283 
284  return true;
285  }
286 
294  bool isNaN(int nodeIndex, int attributeIndex)
295  { return data[nodeIndex]->isNaN(attributeIndex); };
296 
301  virtual float getRadius(int i) const { return radii[i]; };
302 
306  virtual int getNRadii() const { return nNodes; };
307 
311  virtual int getNData() const { return nNodes; };
312 
317  virtual float* getRadii()
318  {
319  float* fa = new float [nNodes];
320  for (int i=0; i<nNodes; ++i) fa[i] = radii[i];
321  return fa;
322  }
323 
329  virtual GeoTessData** getData()
330  {
331  GeoTessData** da = new GeoTessData*[nNodes];
332  for (int i=0; i<nNodes; ++i) da[i] = data[i];
333  return da;
334  }
335 
336 
340  virtual GeoTessData* getData(int i) { return data[i]; };
341 
345  virtual const GeoTessData& getData(int i) const { return *(data[i]); };
346 
350  virtual void setData(const vector<GeoTessData*>& inData);
351 
355  virtual void setRadii(const vector<float>& newRadii)
356  { for (int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
357 
358  virtual void setRadius(int index, float radius)
359  { if (index < nNodes) radii[index] = radius; }
360 
364  virtual void setData(int index, GeoTessData* inData)
365  { delete data[index]; data[index] = inData; }
366 
370  virtual float getRadiusTop() const { return radii[nNodes - 1]; };
371 
375  virtual const GeoTessData& getDataTop() const { return *data[nNodes - 1]; };
376 
380  virtual GeoTessData* getDataTop() { return data[nNodes - 1]; };
381 
385  virtual float getRadiusBottom() const { return radii[0]; };
386 
390  virtual const GeoTessData& getDataBottom() const { return *data[0]; };
391 
395  virtual GeoTessData* getDataBottom() { return data[0]; };
396 
397 
402  virtual double getValue(int attributeIndex, int radiusIndex) const
403  { return data[radiusIndex]->getDouble(attributeIndex); }
404 
411  virtual double getValueTop(int attributeIndex) const
412  { return data[nNodes-1]->getDouble(attributeIndex); }
413 
418  virtual double getInterpolationCoefficient(int index, double radius) const;
419 
424  virtual double getValue(const GeoTessInterpolatorType& radialType,
425  int attributeIndex, double radius,
426  bool allowRadiusOutOfRange) const;
427 
432  virtual int getRadiusIndex(double radius, int jlo) const;
433 
437  virtual double getInterpolationCoefficient(int index, double radius,
438  bool allowOutOfRange) const;
439 
441 
446 
451 
455  virtual ~GeoTessProfileNPoint();
456 
460  virtual void write(IFStreamBinary& ofs);
461 
465  virtual void write(IFStreamAscii& ofs);
466 
475  virtual int findClosestRadiusIndex(double radius) const
476  {
477  int i = GeoTessProfile::getRadiusIndex(radius);
478  return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
479  }
480 
488  virtual void setPointIndex(int nodeIndex, int pointIndex)
489  {
490  if (pointIndices == NULL)
491  {
492  if (pointIndex < 0) return;
493 
494  pointIndices = new int [nNodes];
495  for (int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
496  }
497  pointIndices[nodeIndex] = pointIndex;
498  }
499 
507  virtual void resetPointIndices()
508  {
509  if (pointIndices != NULL)
510  delete[] pointIndices;
511  pointIndices = NULL;
512  }
513 
521  virtual int getPointIndex(int nodeIndex) const
522  { return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
523 
530  virtual void getWeights(map<int, double>& weights,
531  double dkm, double radius, double hcoefficient) const
532  {
533  int node = GeoTessProfile::getRadiusIndex(radius);
534 
535  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
536 
537  // get coefficient at node influencing position radius
538 
539  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
540 
541  double c = getInterpolationCoefficient(node, radius, true);
542  if (c > 0.0)
543  {
544  map<int, double>::iterator it = weights.find(pointIndex);
545  if (it == weights.end())
546  weights[pointIndex] = dkm * hcoefficient * c;
547  else
548  it->second += dkm * hcoefficient * c;
549  }
550 
551  // now get coefficient at node+1 influencing position radius
552 
553  c = 1.0 - c;
554  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
555  if (c > 0.0)
556  {
557  map<int, double>::iterator it = weights.find(pointIndex);
558  if (it == weights.end())
559  weights[pointIndex] = dkm * hcoefficient * c;
560  else
561  it->second += dkm * hcoefficient * c;
562  }
563  }
564 
571  virtual void getCoefficients(map<int, double>& coefficients, double radius,
572  double horizontalCoefficient) const
573  {
574  int node = GeoTessProfile::getRadiusIndex(radius);
575 
576  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
577  double c = getInterpolationCoefficient(node, radius, true);
578 
579  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
580 
581  if (c > 0.0)
582  coefficients[pointIndex] = c * horizontalCoefficient;
583 
584  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
585 
586  if (c < 1.0)
587  coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
588  }
589 
590  virtual void setInterpolationCoefficients(const GeoTessInterpolatorType& interpType,
591  vector<int>& nodeIndexes, vector<double>& coefficients,
592  double& radius, bool& allowOutOfRange)
593  {
594  //TODO: need this method to work for cubic spline interpolator. It currently does not.
595 
596  if (radius < radii[0])
597  {
598  nodeIndexes.push_back(0);
599  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
600  }
601  else if (radius > radii[nNodes-1])
602  {
603  nodeIndexes.push_back(nNodes-1);
604  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
605  }
606  else
607  {
608  int index = getRadiusIndex(radius, -1);
609  double c = ((double)radii[index + 1] - radius) /
610  ((double)radii[index + 1] - (double)radii[index]);
611  nodeIndexes.push_back(index);
612  coefficients.push_back(c);
613  if (c < 1.)
614  {
615  nodeIndexes.push_back(index+1);
616  coefficients.push_back(1.-c);
617  }
618  }
619  }
620 
624  virtual GeoTessProfile* copy()
625  {
626  GeoTessData** d = new GeoTessData* [nNodes];
627  float* r = new float [nNodes];
628  for (int i = 0; i < nNodes; ++i)
629  {
630  d[i] = data[i]->copy();
631  r[i] = radii[i];
632  }
633  return new GeoTessProfileNPoint(r, d, nNodes);
634  }
635 
637 
638 }; // end class ProfileNPoint
639 
651 inline double GeoTessProfileNPoint::getInterpolationCoefficient(int index, double radius) const
652 {
653  if (radius <= radii[index]) return 1.0;
654  if (radius >= radii[index + 1]) return 0.0;
655  return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
656 }
657 
670 inline double GeoTessProfileNPoint::getValue(const GeoTessInterpolatorType& radialType,
671  int attributeIndex, double radius, bool allowRadiusOutOfRange) const
672 {
673  if (!allowRadiusOutOfRange &&
674  ((radius < (double)radii[0]) || (radius > (double)radii[nNodes-1])))
675  return NaN_DOUBLE;
676 
677  int index = getRadiusIndex(radius, -1);
678 
679  double r0 = radii[index];
680  double v0 = data[index]->getDouble(attributeIndex);
681 
682  if (radius <= r0) return v0;
683 
684  double r1 = radii[index + 1];
685  double v1 = data[index + 1]->getDouble(attributeIndex);
686 
687  if (radius >= r1) return v1;
688 
689  double a = (r1 - radius) / (r1 - r0);
690 
691  double b = 1. - a;
692  double v = a * v0 + b * v1;
693 
694  switch (radialType.ordinal())
695  {
696  case 0: // LINEAR
697  return v;
698 
699  case 2: // CUBIC_SPLINE
700  check(attributeIndex);
701  return v + ((a * a * a - a) * y2[attributeIndex][index]
702  + (b * b * b - b) * y2[attributeIndex][index + 1])
703  * (r1 - r0) * (r1 - r0) / 6.0;
704 
705  default:
706  ostringstream os;
707  os << endl << "ERROR in ProfileNPoint::getValue" << endl
708  << "InterpolatorType: " << radialType.name()
709  << " cannot be applied to a Profile." << endl
710  << "Must specify LINEAR or SPLINE" << endl;
711  throw GeoTessException(os, __FILE__, __LINE__, 4304);
712  }
713 }
714 
716 
722 inline void GeoTessProfileNPoint::check(int attributeIndex) const
723 {
724  if (y2 == NULL)
725  {
726  y2 = new double* [data[0]->size()];
727  for (int i=0; i<data[0]->size(); ++i)
728  y2[i] = NULL;
729  }
730  if (y2[attributeIndex] == NULL)
731  y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
732 }
733 
735 
736 } // end namespace geotess
737 
738 #endif // PROFILENPOINT_OBJECT_H
geotess::GeoTessProfileNPoint::getRadii
virtual float * getRadii()
Definition: GeoTessProfileNPoint.h:317
geotess::GeoTessProfileNPoint::getValueTop
virtual double getValueTop(int attributeIndex) const
Definition: GeoTessProfileNPoint.h:411
geotess
Definition: ArrayReuse.h:57
GeoTessException.h
geotess::GeoTessProfile
Abstract class that manages the radii and data values that span a single layer associated with a sing...
Definition: GeoTessProfile.h:99
GeoTessProfileType.h
geotess::GeoTessProfileNPoint::getDataBottom
virtual GeoTessData * getDataBottom()
Definition: GeoTessProfileNPoint.h:395
GeoTessData.h
geotess::GeoTessProfileNPoint::setData
virtual void setData(const vector< GeoTessData * > &inData)
geotess::GeoTessData::getMemory
virtual LONG_INT getMemory()
GeoTessProfile.h
geotess::GeoTessProfileType
Enumeration of the valid Profile types, including EMPTY, THIN, CONSTANT, NPOINT and SURFACE.
Definition: GeoTessProfileType.h:72
geotess::GeoTessProfileNPoint::GeoTessProfileNPoint
GeoTessProfileNPoint(const vector< float > &r, vector< GeoTessData * > &d)
Definition: GeoTessProfileNPoint.h:187
geotess::GeoTessProfileNPoint::getType
virtual const GeoTessProfileType & getType() const
Definition: GeoTessProfileNPoint.h:267
geotess::GeoTessProfileNPoint::GeoTessProfileNPoint
GeoTessProfileNPoint(float *r, GeoTessData **dat, int size)
Definition: GeoTessProfileNPoint.h:152
geotess::GeoTessProfileNPoint::getDataTop
virtual GeoTessData * getDataTop()
Definition: GeoTessProfileNPoint.h:380
geotess::GeoTessProfileNPoint::class_name
static string class_name()
Definition: GeoTessProfileNPoint.h:232
geotess::GeoTessProfileNPoint::getMemory
virtual LONG_INT getMemory()
Definition: GeoTessProfileNPoint.h:240
geotess::GeoTessProfileNPoint::getNData
virtual int getNData() const
Definition: GeoTessProfileNPoint.h:311
geotess::GeoTessEnumType::name
string name() const
Definition: GeoTessEnumType.h:145
geotess::GeoTessProfile::getRadius
virtual float getRadius(int i) const
geotess::GeoTessData::size
virtual int size() const
geotess::GeoTessProfileNPoint::getDataBottom
virtual const GeoTessData & getDataBottom() const
Definition: GeoTessProfileNPoint.h:390
geotess::GeoTessProfileNPoint::getData
virtual const GeoTessData & getData(int i) const
Definition: GeoTessProfileNPoint.h:345
geotess::GeoTessProfileNPoint::getData
virtual GeoTessData * getData(int i)
Definition: GeoTessProfileNPoint.h:340
geotess::GeoTessProfileNPoint::isNaN
bool isNaN(int nodeIndex, int attributeIndex)
Definition: GeoTessProfileNPoint.h:294
geotess::GeoTessProfileNPoint::getData
virtual GeoTessData ** getData()
Definition: GeoTessProfileNPoint.h:329
geotess::GeoTessProfileNPoint::getRadius
virtual float getRadius(int i) const
Definition: GeoTessProfileNPoint.h:301
geotess::GeoTessEnumType::ordinal
int ordinal() const
Definition: GeoTessEnumType.h:150
GeoTessUtils.h
geotess::GeoTessProfile::getNRadii
virtual int getNRadii() const
geotess::IFStreamAscii
Opens ascii file for read and write access.
Definition: IFStreamAscii.h:83
geotess::GeoTessProfileNPoint::getNRadii
virtual int getNRadii() const
Definition: GeoTessProfileNPoint.h:306
LONG_INT
#define LONG_INT
Definition: CPPGlobals.h:113
geotess::GeoTessProfileNPoint::getDataTop
virtual const GeoTessData & getDataTop() const
Definition: GeoTessProfileNPoint.h:375
geotess::GeoTessProfileNPoint::setRadius
virtual void setRadius(int index, float radius)
Definition: GeoTessProfileNPoint.h:358
geotess::GeoTessProfileNPoint::getInterpolationCoefficient
virtual double getInterpolationCoefficient(int index, double radius, bool allowOutOfRange) const
geotess::GeoTessData
Abstract base class that manages the data values attached to a single grid point.
Definition: GeoTessData.h:78
GeoTessInterpolatorType.h
geotess::GeoTessProfileNPoint::getRadiusTop
virtual float getRadiusTop() const
Definition: GeoTessProfileNPoint.h:370
GEOTESS_EXP_IMP
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:73
geotess::IFStreamBinary
Opens a file for binary read and write access.
Definition: IFStreamBinary.h:82
geotess::GeoTessData::getDouble
virtual double getDouble(int attributeIndex) const
geotess::GeoTessMetaData
Basic metadata information about a GeoTessModel.
Definition: GeoTessMetaData.h:98
geotess::GeoTessProfileNPoint
A Profile object consisting of N monotonically increasing radii that span the radial extent of a laye...
Definition: GeoTessProfileNPoint.h:83
geotess::GeoTessProfileNPoint::getValue
virtual double getValue(int attributeIndex, int radiusIndex) const
Definition: GeoTessProfileNPoint.h:402
geotess::GeoTessProfileNPoint::getRadiusBottom
virtual float getRadiusBottom() const
Definition: GeoTessProfileNPoint.h:385
geotess::GeoTessProfileNPoint::GeoTessProfileNPoint
GeoTessProfileNPoint(float *rad, const vector< GeoTessData * > &dat)
geotess::GeoTessProfileNPoint::setRadii
virtual void setRadii(const vector< float > &newRadii)
Definition: GeoTessProfileNPoint.h:355
geotess::GeoTessException
An exception class for all GeoTess objects.
Definition: GeoTessException.h:68
geotess::GeoTessProfileNPoint::getRadiusIndex
virtual int getRadiusIndex(double radius, int jlo) const
geotess::GeoTessProfileNPoint::class_size
virtual int class_size() const
Definition: GeoTessProfileNPoint.h:237
geotess::GeoTessProfileNPoint::setData
virtual void setData(int index, GeoTessData *inData)
Definition: GeoTessProfileNPoint.h:364
geotess::GeoTessProfile::getData
virtual GeoTessData ** getData()
geotess::GeoTessInterpolatorType
Enumeration of the interpolation algorithms supported by GeoTess including LINEAR,...
Definition: GeoTessInterpolatorType.h:74
geotess::GeoTessData::isNaN
virtual bool isNaN(int attributeIndex) const