GeoTessCPP  2.6.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 
238  virtual LONG_INT getMemory()
239  {
240  LONG_INT sz = (LONG_INT)sizeof(GeoTessProfileNPoint);
241  if (nNodes > 0)
242  {
243  // add memory for radii
244  sz += nNodes*(LONG_INT)sizeof(float);
245 
246  // add memory for data. assumption is made that
247  // GeoTessData objects at all nodes have the same type and
248  // number of attributes.
249  sz += nNodes*(LONG_INT)sizeof(GeoTessData*);
250  sz += nNodes*data[0]->getMemory();
251 
252  if (pointIndices)
253  sz += nNodes * (LONG_INT)(sizeof(int));
254  if (y2)
255  sz += data[0]->size() * nNodes * (LONG_INT)sizeof(double);
256  }
257  return sz;
258  }
259 
265  virtual const GeoTessProfileType& getType() const
266  { return GeoTessProfileType::NPOINT; };
267 
271  virtual bool operator == (const GeoTessProfile& p) const
272  {
273  if (!GeoTessProfile::operator==(p)) return false;
274 
275  if (nNodes != p.getNRadii()) return false;
276 
277  for (int i = 0; i < nNodes; ++i)
278  if ((radii[i] != p.getRadius(i)) ||
279  (!(*(data[i]) == p.getData(i))))
280  return false;
281 
282  return true;
283  }
284 
292  bool isNaN(int nodeIndex, int attributeIndex)
293  { return data[nodeIndex]->isNaN(attributeIndex); };
294 
299  virtual float getRadius(int i) const { return radii[i]; };
300 
304  virtual int getNRadii() const { return nNodes; };
305 
309  virtual int getNData() const { return nNodes; };
310 
315  virtual float* getRadii()
316  {
317  float* fa = new float [nNodes];
318  for (int i=0; i<nNodes; ++i) fa[i] = radii[i];
319  return fa;
320  }
321 
327  virtual GeoTessData** getData()
328  {
329  GeoTessData** da = new GeoTessData*[nNodes];
330  for (int i=0; i<nNodes; ++i) da[i] = data[i];
331  return da;
332  }
333 
334 
338  virtual GeoTessData* getData(int i) { return data[i]; };
339 
343  virtual const GeoTessData& getData(int i) const { return *(data[i]); };
344 
348  virtual void setData(const vector<GeoTessData*>& inData);
349 
353  virtual void setRadii(const vector<float>& newRadii)
354  { for (int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
355 
356  virtual void setRadius(int index, float radius)
357  { if (index < nNodes) radii[index] = radius; }
358 
362  virtual void setData(int index, GeoTessData* inData)
363  { delete data[index]; data[index] = inData; }
364 
368  virtual float getRadiusTop() const { return radii[nNodes - 1]; };
369 
373  virtual const GeoTessData& getDataTop() const { return *data[nNodes - 1]; };
374 
378  virtual GeoTessData* getDataTop() { return data[nNodes - 1]; };
379 
383  virtual float getRadiusBottom() const { return radii[0]; };
384 
388  virtual const GeoTessData& getDataBottom() const { return *data[0]; };
389 
393  virtual GeoTessData* getDataBottom() { return data[0]; };
394 
395 
400  virtual double getValue(int attributeIndex, int radiusIndex) const
401  { return data[radiusIndex]->getDouble(attributeIndex); }
402 
409  virtual double getValueTop(int attributeIndex) const
410  { return data[nNodes-1]->getDouble(attributeIndex); }
411 
416  virtual double getInterpolationCoefficient(int index, double radius) const;
417 
422  virtual double getValue(const GeoTessInterpolatorType& radialType,
423  int attributeIndex, double radius,
424  bool allowRadiusOutOfRange) const;
425 
430  virtual int getRadiusIndex(double radius, int jlo) const;
431 
435  virtual double getInterpolationCoefficient(int index, double radius,
436  bool allowOutOfRange) const;
437 
439 
444 
449 
453  virtual ~GeoTessProfileNPoint();
454 
458  virtual void write(IFStreamBinary& ofs);
459 
463  virtual void write(IFStreamAscii& ofs);
464 
473  virtual int findClosestRadiusIndex(double radius) const
474  {
475  int i = GeoTessProfile::getRadiusIndex(radius);
476  return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
477  }
478 
486  virtual void setPointIndex(int nodeIndex, int pointIndex)
487  {
488  if (pointIndices == NULL)
489  {
490  if (pointIndex < 0) return;
491 
492  pointIndices = new int [nNodes];
493  for (int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
494  }
495  pointIndices[nodeIndex] = pointIndex;
496  }
497 
505  virtual void resetPointIndices()
506  {
507  if (pointIndices != NULL)
508  delete[] pointIndices;
509  pointIndices = NULL;
510  }
511 
519  virtual int getPointIndex(int nodeIndex) const
520  { return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
521 
528  virtual void getWeights(map<int, double>& weights,
529  double dkm, double radius, double hcoefficient) const
530  {
531  int node = GeoTessProfile::getRadiusIndex(radius);
532 
533  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
534 
535  // get coefficient at node influencing position radius
536 
537  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
538 
539  double c = getInterpolationCoefficient(node, radius, true);
540  if (c > 0.0)
541  {
542  map<int, double>::iterator it = weights.find(pointIndex);
543  if (it == weights.end())
544  weights[pointIndex] = dkm * hcoefficient * c;
545  else
546  it->second += dkm * hcoefficient * c;
547  }
548 
549  // now get coefficient at node+1 influencing position radius
550 
551  c = 1.0 - c;
552  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
553  if (c > 0.0)
554  {
555  map<int, double>::iterator it = weights.find(pointIndex);
556  if (it == weights.end())
557  weights[pointIndex] = dkm * hcoefficient * c;
558  else
559  it->second += dkm * hcoefficient * c;
560  }
561  }
562 
569  virtual void getCoefficients(map<int, double>& coefficients, double radius,
570  double horizontalCoefficient) const
571  {
572  int node = GeoTessProfile::getRadiusIndex(radius);
573 
574  //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
575  double c = getInterpolationCoefficient(node, radius, true);
576 
577  int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
578 
579  if (c > 0.0)
580  coefficients[pointIndex] = c * horizontalCoefficient;
581 
582  pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
583 
584  if (c < 1.0)
585  coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
586  }
587 
588  virtual void setInterpolationCoefficients(const GeoTessInterpolatorType& interpType,
589  vector<int>& nodeIndexes, vector<double>& coefficients,
590  double& radius, bool& allowOutOfRange)
591  {
592  //TODO: need this method to work for cubic spline interpolator. It currently does not.
593 
594  if (radius < radii[0])
595  {
596  nodeIndexes.push_back(0);
597  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
598  }
599  else if (radius > radii[nNodes-1])
600  {
601  nodeIndexes.push_back(nNodes-1);
602  coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
603  }
604  else
605  {
606  int index = getRadiusIndex(radius, -1);
607  double c = ((double)radii[index + 1] - radius) /
608  ((double)radii[index + 1] - (double)radii[index]);
609  nodeIndexes.push_back(index);
610  coefficients.push_back(c);
611  if (c < 1.)
612  {
613  nodeIndexes.push_back(index+1);
614  coefficients.push_back(1.-c);
615  }
616  }
617  }
618 
622  virtual GeoTessProfile* copy()
623  {
624  GeoTessData** d = new GeoTessData* [nNodes];
625  float* r = new float [nNodes];
626  for (int i = 0; i < nNodes; ++i)
627  {
628  d[i] = data[i]->copy();
629  r[i] = radii[i];
630  }
631  return new GeoTessProfileNPoint(r, d, nNodes);
632  }
633 
635 
636 }; // end class ProfileNPoint
637 
649 inline double GeoTessProfileNPoint::getInterpolationCoefficient(int index, double radius) const
650 {
651  if (radius <= radii[index]) return 1.0;
652  if (radius >= radii[index + 1]) return 0.0;
653  return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
654 }
655 
668 inline double GeoTessProfileNPoint::getValue(const GeoTessInterpolatorType& radialType,
669  int attributeIndex, double radius, bool allowRadiusOutOfRange) const
670 {
671  if (!allowRadiusOutOfRange &&
672  ((radius < (double)radii[0]) || (radius > (double)radii[nNodes-1])))
673  return NaN_DOUBLE;
674 
675  int index = getRadiusIndex(radius, -1);
676 
677  double r0 = radii[index];
678  double v0 = data[index]->getDouble(attributeIndex);
679 
680  if (radius <= r0) return v0;
681 
682  double r1 = radii[index + 1];
683  double v1 = data[index + 1]->getDouble(attributeIndex);
684 
685  if (radius >= r1) return v1;
686 
687  double a = (r1 - radius) / (r1 - r0);
688 
689  double b = 1. - a;
690  double v = a * v0 + b * v1;
691 
692  switch (radialType.ordinal())
693  {
694  case 0: // LINEAR
695  return v;
696 
697  case 2: // CUBIC_SPLINE
698  check(attributeIndex);
699  return v + ((a * a * a - a) * y2[attributeIndex][index]
700  + (b * b * b - b) * y2[attributeIndex][index + 1])
701  * (r1 - r0) * (r1 - r0) / 6.0;
702 
703  default:
704  ostringstream os;
705  os << endl << "ERROR in ProfileNPoint::getValue" << endl
706  << "InterpolatorType: " << radialType.name()
707  << " cannot be applied to a Profile." << endl
708  << "Must specify LINEAR or SPLINE" << endl;
709  throw GeoTessException(os, __FILE__, __LINE__, 4304);
710  }
711 }
712 
714 
720 inline void GeoTessProfileNPoint::check(int attributeIndex) const
721 {
722  if (y2 == NULL)
723  {
724  y2 = new double* [data[0]->size()];
725  for (int i=0; i<data[0]->size(); ++i)
726  y2[i] = NULL;
727  }
728  if (y2[attributeIndex] == NULL)
729  y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
730 }
731 
733 
734 } // end namespace geotess
735 
736 #endif // PROFILENPOINT_OBJECT_H
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:71
#define LONG_INT
Definition: CPPGlobals.h:111
Abstract base class that manages the data values attached to a single grid point.
Definition: GeoTessData.h:76
virtual LONG_INT getMemory()
virtual int size() const
virtual double getDouble(int attributeIndex) const
virtual bool isNaN(int attributeIndex) const
An exception class for all GeoTess objects.
Enumeration of the interpolation algorithms supported by GeoTess including LINEAR,...
Basic metadata information about a GeoTessModel.
Abstract class that manages the radii and data values that span a single layer associated with a sing...
virtual int getNRadii() const
virtual float getRadius(int i) const
virtual GeoTessData ** getData()
A Profile object consisting of N monotonically increasing radii that span the radial extent of a laye...
virtual const GeoTessData & getDataTop() const
virtual GeoTessData * getDataTop()
GeoTessProfileNPoint(const vector< float > &r, vector< GeoTessData * > &d)
GeoTessProfileNPoint(float *r, GeoTessData **dat, int size)
virtual int getRadiusIndex(double radius, int jlo) const
virtual void setRadius(int index, float radius)
virtual void setData(int index, GeoTessData *inData)
bool isNaN(int nodeIndex, int attributeIndex)
virtual void setRadii(const vector< float > &newRadii)
virtual float getRadiusBottom() const
virtual float getRadius(int i) const
virtual GeoTessData * getData(int i)
virtual const GeoTessData & getData(int i) const
virtual double getValue(int attributeIndex, int radiusIndex) const
virtual const GeoTessData & getDataBottom() const
virtual const GeoTessProfileType & getType() const
virtual double getInterpolationCoefficient(int index, double radius, bool allowOutOfRange) const
GeoTessProfileNPoint(float *rad, const vector< GeoTessData * > &dat)
virtual double getValueTop(int attributeIndex) const
virtual GeoTessData * getDataBottom()
virtual GeoTessData ** getData()
virtual void setData(const vector< GeoTessData * > &inData)
virtual float getRadiusTop() const
Enumeration of the valid Profile types, including EMPTY, THIN, CONSTANT, NPOINT and SURFACE.
Opens ascii file for read and write access.
Definition: IFStreamAscii.h:81
Opens a file for binary read and write access.