GeoTessCPP  2.1
Software to facilitate storage and retrieval of 3D information about the Earth.
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
GeoTessProfileNPoint.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 PROFILENPOINT_OBJECT_H
37 #define PROFILENPOINT_OBJECT_H
38 
39 // **** _SYSTEM INCLUDES_ ******************************************************
40 
41 #include <iostream>
42 #include <string>
43 #include <fstream>
44 #include <sstream>
45 
46 // use standard library objects
47 using namespace std;
48 
49 // **** _LOCAL INCLUDES_ *******************************************************
50 
51 #include "GeoTessUtils.h"
52 #include "GeoTessException.h"
53 #include "GeoTessData.h"
54 #include "GeoTessProfile.h"
55 #include "GeoTessProfileType.h"
57 
58 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
59 
60 namespace geotess {
61 
62 // **** _FORWARD REFERENCES_ ***************************************************
63 
64 class GeoTessMetaData;
65 class IFStreamAscii;
66 class IFStreamBinary;
67 
68 // **** _CLASS DEFINITION_ *****************************************************
69 
81 {
82 private:
83 
87  int nNodes;
88 
92  float* radii;
93 
97  GeoTessData** data;
98 
105  mutable double** y2;
106 
114  int* pointIndices;
115 
119  GeoTessProfileNPoint() : GeoTessProfile(), nNodes(0), radii(NULL), data(NULL),
120  y2(NULL), pointIndices(NULL) {};
121 
126  double* spline(float* x, GeoTessData** y, int attributeIndex,
127  double yp1, double ypn) const;
128 
134  void check(int attributeIndex) const;
135 
136 public:
137 
150  GeoTessProfileNPoint(float* r, GeoTessData** dat, int size) : GeoTessProfile(), nNodes(size), radii(NULL),
151  data(NULL), y2(NULL), pointIndices(NULL)
152  {
153  radii = new float[size];
154  data = new GeoTessData*[size];
155  for (int i=0; i<size; ++i)
156  {
157  radii[i] = r[i];
158  data[i] = dat[i];
159  }
160 
161  if (radii[0] > radii[size - 1])
162  {
163  ostringstream os;
164  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
165  << "Profile has negative thickness" << endl;
166  os << "radii = ";
167  for (int i=0; i<size; ++i)
168  os << radii[i] << ", ";
169  os << endl;
170  throw GeoTessException(os, __FILE__, __LINE__, 4301);
171  }
172  }
173 
185  GeoTessProfileNPoint(const vector<float>& r, vector<GeoTessData*>& d)
186  : GeoTessProfile(), nNodes(r.size()), radii(NULL),
187  data(NULL), y2(NULL), pointIndices(NULL)
188  {
189  radii = new float[nNodes];
190  data = new GeoTessData*[nNodes];
191  for (int i=0; i<nNodes; ++i)
192  {
193  radii[i] = r[i];
194  data[i] = d[i];
195  }
196 
197  if (r.size() != d.size())
198  {
199  ostringstream os;
200  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
201  << "radii.size() != data.size()" << endl;
202  os << "radii.size = " << r.size() << endl;
203  os << "data.size = " << d.size() << endl;
204  throw GeoTessException(os, __FILE__, __LINE__, 4302);
205  }
206 
207  if (radii[0] > radii[nNodes - 1])
208  {
209  ostringstream os;
210  os << endl << "ERROR in ProfileNPoint::ProfileNPoint" << endl
211  << "Profile has negative thickness" << endl;
212  os << "radii = ";
213  for (int i=0; i<nNodes; ++i)
214  os << radii[i] << ", ";
215  os << endl;
216  throw GeoTessException(os, __FILE__, __LINE__, 4303);
217  }
218  }
219 
225  GeoTessProfileNPoint(float* rad, const vector<GeoTessData*>& dat);
226 
230  static string class_name() { return "ProfileNPoint"; };
231 
235  virtual int class_size() const
236  { return (int) sizeof(GeoTessProfileNPoint); };
237 
243  virtual const GeoTessProfileType& getType() const
244  { return GeoTessProfileType::NPOINT; };
245 
249  virtual bool operator == (const GeoTessProfile& p) const
250  {
251  if (!GeoTessProfile::operator==(p)) return false;
252 
253  if (nNodes != p.getNRadii()) return false;
254 
255  for (int i = 0; i < nNodes; ++i)
256  if ((radii[i] != p.getRadius(i)) ||
257  (!(*(data[i]) == p.getData(i))))
258  return false;
259 
260  return true;
261  }
262 
270  bool isNaN(int nodeIndex, int attributeIndex)
271  { return data[nodeIndex]->isNaN(attributeIndex); };
272 
277  virtual float getRadius(int i) const { return radii[i]; };
278 
282  virtual int getNRadii() const { return nNodes; };
283 
287  virtual int getNData() const { return nNodes; };
288 
293  virtual float* getRadii()
294  {
295  float* fa = new float [nNodes];
296  for (int i=0; i<nNodes; ++i) fa[i] = radii[i];
297  return fa;
298  }
299 
305  virtual GeoTessData** getData()
306  {
307  GeoTessData** da = new GeoTessData*[nNodes];
308  for (int i=0; i<nNodes; ++i) da[i] = data[i];
309  return da;
310  }
311 
312 
316  virtual GeoTessData* getData(int i) { return data[i]; };
317 
321  virtual const GeoTessData& getData(int i) const { return *(data[i]); };
322 
326  virtual void setData(const vector<GeoTessData*>& inData);
327 
331  virtual void setRadii(const vector<float>& newRadii)
332  { for (int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
333 
334  virtual void setRadius(int index, float radius)
335  { if (index < nNodes) radii[index] = radius; }
336 
340  virtual void setData(int index, GeoTessData* inData)
341  { delete data[index]; data[index] = inData; }
342 
346  virtual float getRadiusTop() const { return radii[nNodes - 1]; };
347 
351  virtual const GeoTessData& getDataTop() const { return *data[nNodes - 1]; };
352 
356  virtual GeoTessData* getDataTop() { return data[nNodes - 1]; };
357 
361  virtual float getRadiusBottom() const { return radii[0]; };
362 
366  virtual const GeoTessData& getDataBottom() const { return *data[0]; };
367 
371  virtual GeoTessData* getDataBottom() { return data[0]; };
372 
373 
378  virtual double getValue(int attributeIndex, int radiusIndex) const
379  { return data[radiusIndex]->getDouble(attributeIndex); }
380 
387  virtual double getValueTop(int attributeIndex) const
388  { return data[nNodes-1]->getDouble(attributeIndex); }
389 
394  virtual double getInterpolationCoefficient(int index, double radius) const;
395 
400  virtual double getValue(const GeoTessInterpolatorType& radialType,
401  int attributeIndex, double radius,
402  bool allowRadiusOutOfRange) const;
403 
408  virtual int getRadiusIndex(double radius, int jlo) const;
409 
413  virtual double getInterpolationCoefficient(int index, double radius,
414  bool allowOutOfRange) const;
415 
417 
422 
427 
431  virtual ~GeoTessProfileNPoint();
432 
436  virtual void write(IFStreamBinary& ofs);
437 
441  virtual void write(IFStreamAscii& ofs);
442 
451  virtual int findClosestRadiusIndex(double radius) const
452  {
453  int i = GeoTessProfile::getRadiusIndex(radius);
454  return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
455  }
456 
464  virtual void setPointIndex(int nodeIndex, int pointIndex)
465  {
466  if (pointIndices == NULL)
467  {
468  if (pointIndex < 0) return;
469 
470  pointIndices = new int [nNodes];
471  for (int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
472  }
473  pointIndices[nodeIndex] = pointIndex;
474  }
475 
483  virtual void resetPointIndices()
484  {
485  if (pointIndices != NULL)
486  delete[] pointIndices;
487  pointIndices = NULL;
488  }
489 
497  virtual int getPointIndex(int nodeIndex) const
498  { return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
499 
506  virtual void getWeights(map<int, double>& weights,
507  double dkm, double radius, double hcoefficient) const
508  {
509  int node = GeoTessProfile::getRadiusIndex(radius);
510 
511  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
512 
513  // get coefficient at node influencing position radius
514 
515  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
516 
517  double c = getInterpolationCoefficient(node, radius, true);
518  if (c > 0.0)
519  {
520  map<int, double>::iterator it = weights.find(pointIndex);
521  if (it == weights.end())
522  weights[pointIndex] = dkm * hcoefficient * c;
523  else
524  it->second += dkm * hcoefficient * c;
525  }
526 
527  // now get coefficient at node+1 influencing position radius
528 
529  c = 1.0 - c;
530  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
531  if (c > 0.0)
532  {
533  map<int, double>::iterator it = weights.find(pointIndex);
534  if (it == weights.end())
535  weights[pointIndex] = dkm * hcoefficient * c;
536  else
537  it->second += dkm * hcoefficient * c;
538  }
539  }
540 
547  virtual void getCoefficients(map<int, double>& coefficients, double radius,
548  double horizontalCoefficient) const
549  {
550  int node = GeoTessProfile::getRadiusIndex(radius);
551 
552  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
553  double c = getInterpolationCoefficient(node, radius, true);
554 
555  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
556 
557  if (c > 0.0)
558  coefficients[pointIndex] = c * horizontalCoefficient;
559 
560  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
561 
562  if (c < 1.0)
563  coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
564  }
565 
566  virtual void setInterpolationCoefficients(const GeoTessInterpolatorType& interpType,
567  vector<int>& nodeIndexes, vector<double>& coefficients,
568  double& radius, bool& allowOutOfRange)
569  {
570  //TODO: need this method to work for cubic spline interpolator. It currently does not.
571 
572  if (radius < radii[0])
573  {
574  nodeIndexes.push_back(0);
575  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
576  }
577  else if (radius > radii[nNodes-1])
578  {
579  nodeIndexes.push_back(nNodes-1);
580  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
581  }
582  else
583  {
584  int index = getRadiusIndex(radius, -1);
585  double c = ((double)radii[index + 1] - radius) /
586  ((double)radii[index + 1] - (double)radii[index]);
587  nodeIndexes.push_back(index);
588  coefficients.push_back(c);
589  if (c < 1.)
590  {
591  nodeIndexes.push_back(index+1);
592  coefficients.push_back(1.-c);
593  }
594  }
595  }
596 
600  virtual GeoTessProfile* copy()
601  {
602  GeoTessData** d = new GeoTessData* [nNodes];
603  float* r = new float [nNodes];
604  for (int i = 0; i < nNodes; ++i)
605  {
606  d[i] = data[i]->copy();
607  r[i] = radii[i];
608  }
609  return new GeoTessProfileNPoint(r, d, nNodes);
610  }
611 
613 
614 }; // end class ProfileNPoint
615 
627 inline double GeoTessProfileNPoint::getInterpolationCoefficient(int index, double radius) const
628 {
629  if (radius <= radii[index]) return 1.0;
630  if (radius >= radii[index + 1]) return 0.0;
631  return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
632 }
633 
646 inline double GeoTessProfileNPoint::getValue(const GeoTessInterpolatorType& radialType,
647  int attributeIndex, double radius, bool allowRadiusOutOfRange) const
648 {
649  if (!allowRadiusOutOfRange &&
650  ((radius < (double)radii[0]) || (radius > (double)radii[nNodes-1])))
651  return NaN_DOUBLE;
652 
653  int index = getRadiusIndex(radius, -1);
654 
655  double r0 = radii[index];
656  double v0 = data[index]->getDouble(attributeIndex);
657 
658  if (radius <= r0) return v0;
659 
660  double r1 = radii[index + 1];
661  double v1 = data[index + 1]->getDouble(attributeIndex);
662 
663  if (radius >= r1) return v1;
664 
665  double a = (r1 - radius) / (r1 - r0);
666 
667  double b = 1. - a;
668  double v = a * v0 + b * v1;
669 
670  switch (radialType.ordinal())
671  {
672  case 0: // LINEAR
673  return v;
674 
675  case 2: // CUBIC_SPLINE
676  check(attributeIndex);
677  return v + ((a * a * a - a) * y2[attributeIndex][index]
678  + (b * b * b - b) * y2[attributeIndex][index + 1])
679  * (r1 - r0) * (r1 - r0) / 6.0;
680 
681  default:
682  ostringstream os;
683  os << endl << "ERROR in ProfileNPoint::getValue" << endl
684  << "InterpolatorType: " << radialType.name()
685  << " cannot be applied to a Profile." << endl
686  << "Must specify LINEAR or SPLINE" << endl;
687  throw GeoTessException(os, __FILE__, __LINE__, 4304);
688  }
689 }
690 
692 
698 inline void GeoTessProfileNPoint::check(int attributeIndex) const
699 {
700  if (y2 == NULL)
701  {
702  y2 = new double* [data[0]->size()];
703  for (int i=0; i<data[0]->size(); ++i)
704  y2[i] = NULL;
705  }
706  if (y2[attributeIndex] == NULL)
707  y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
708 }
709 
711 
712 } // end namespace geotess
713 
714 #endif // PROFILENPOINT_OBJECT_H
virtual void setRadius(int index, float radius)
Definition: GeoTessProfileNPoint.h:334
virtual int getNRadii() const
string name() const
Definition: GeoTessEnumType.h:143
Opens a file for binary read and write access.
Definition: IFStreamBinary.h:79
virtual int getNData() const
Definition: GeoTessProfileNPoint.h:287
Enumeration of the interpolation algorithms supported by GeoTess including LINEAR, NATURAL_NEIGHBOR and CUBIC_SPLINE.
Definition: GeoTessInterpolatorType.h:71
virtual int getNRadii() const
Definition: GeoTessProfileNPoint.h:282
virtual int size() const
Enumeration of the valid Profile types, including EMPTY, THIN, CONSTANT, NPOINT and SURFACE...
Definition: GeoTessProfileType.h:69
virtual GeoTessData ** getData()
virtual const GeoTessData & getData(int i) const
Definition: GeoTessProfileNPoint.h:321
virtual float getRadiusBottom() const
Definition: GeoTessProfileNPoint.h:361
virtual void setRadii(const vector< float > &newRadii)
Definition: GeoTessProfileNPoint.h:331
virtual float getRadiusTop() const
Definition: GeoTessProfileNPoint.h:346
virtual void setData(int index, GeoTessData *inData)
Definition: GeoTessProfileNPoint.h:340
GeoTessProfileNPoint(float *r, GeoTessData **dat, int size)
Definition: GeoTessProfileNPoint.h:150
virtual GeoTessData * getDataBottom()
Definition: GeoTessProfileNPoint.h:371
An exception class for all GeoTess objects.
Definition: GeoTessException.h:65
virtual const GeoTessProfileType & getType() const
Definition: GeoTessProfileNPoint.h:243
Opens ascii file for read and write access.
Definition: IFStreamAscii.h:80
static string class_name()
Definition: GeoTessProfileNPoint.h:230
virtual GeoTessData * getDataTop()
Definition: GeoTessProfileNPoint.h:356
virtual float * getRadii()
Definition: GeoTessProfileNPoint.h:293
virtual int class_size() const
Definition: GeoTessProfileNPoint.h:235
GeoTessProfileNPoint(const vector< float > &r, vector< GeoTessData * > &d)
Definition: GeoTessProfileNPoint.h:185
Abstract class that manages the radii and data values that span a single layer associated with a sing...
Definition: GeoTessProfile.h:96
Abstract base class that manages the data values attached to a single grid point. ...
Definition: GeoTessData.h:75
bool isNaN(int nodeIndex, int attributeIndex)
Definition: GeoTessProfileNPoint.h:270
virtual GeoTessData * getData(int i)
Definition: GeoTessProfileNPoint.h:316
virtual GeoTessData ** getData()
Definition: GeoTessProfileNPoint.h:305
virtual const GeoTessData & getDataTop() const
Definition: GeoTessProfileNPoint.h:351
virtual float getRadius(int i) const
Definition: GeoTessProfileNPoint.h:277
Basic metadata information about a GeoTessModel.
Definition: GeoTessMetaData.h:96
int ordinal() const
Definition: GeoTessEnumType.h:148
A Profile object consisting of N monotonically increasing radii that span the radial extent of a laye...
Definition: GeoTessProfileNPoint.h:80
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:71
virtual double getValue(int attributeIndex, int radiusIndex) const
Definition: GeoTessProfileNPoint.h:378
virtual float getRadius(int i) const
virtual double getValueTop(int attributeIndex) const
Definition: GeoTessProfileNPoint.h:387
virtual const GeoTessData & getDataBottom() const
Definition: GeoTessProfileNPoint.h:366