GeoTessCPP: include/ProfileNPoint.h Source File

GeoTessCPP 2.0.0 Software to facilitate storage and retrieval of 3D information about the Earth.

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Friends Macros
ProfileNPoint.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 "Data.h"
54 #include "Profile.h"
55 #include "ProfileType.h"
56 #include "InterpolatorType.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
80 class GEOTESS_EXP_IMP ProfileNPoint : virtual public Profile
81 {
82 private:
83
87 int nNodes;
88
92 float* radii;
93
97 Data** data;
98
105 mutable double** y2;
106
114 int* pointIndices;
115
119 ProfileNPoint() : Profile(), nNodes(0), radii(NULL), data(NULL),
120 y2(NULL), pointIndices(NULL) {};
121
126 double* spline(float* x, Data** y, int attributeIndex,
127 double yp1, double ypn) const;
128
134 void check(int attributeIndex) const;
135
136 public:
137
150 ProfileNPoint(float* r, Data** dat, int size) : Profile(), nNodes(size), radii(NULL),
151 data(NULL), y2(NULL), pointIndices(NULL)
152 {
153 radii = new float[size];
154 data = new Data*[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 ProfileNPoint(const vector<float>& r, vector<Data*>& d)
186 : Profile(), nNodes(r.size()), radii(NULL),
187 data(NULL), y2(NULL), pointIndices(NULL)
188 {
189 radii = new float[nNodes];
190 data = new Data*[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 ProfileNPoint(float* rad, const vector<Data*>& dat);
226
230 static string class_name() { return "ProfileNPoint"; };
231
235 virtual int class_size() const
236 { return (int) sizeof(ProfileNPoint); };
237
243 virtual const ProfileType& getType() const
244 { return ProfileType::NPOINT; };
245
249 virtual bool operator == (const Profile& p) const
250 {
251 if (!Profile::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
283 virtual Data** getData() { return data; };
284
288 virtual Data* getData(int i) { return data[i]; };
289
293 virtual const Data& getData(int i) const { return *(data[i]); };
294
298 virtual void setData(const vector<Data*>& inData);
299
300 // TODO: added by sb 9/27/2012
304 virtual void setRadii(const vector<float>& newRadii)
305 { for (int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
306
307 // *** TODO added 7/19/2012
311 virtual void setData(int index, Data* inData)
312 { delete data[index]; data[index] = inData; }
313
317 virtual float getRadiusTop() const { return radii[nNodes - 1]; };
318
322 virtual const Data& getDataTop() const { return *data[nNodes - 1]; };
323
327 virtual Data* getDataTop() { return data[nNodes - 1]; };
328
332 virtual float getRadiusBottom() const { return radii[0]; };
333
337 virtual const Data& getDataBottom() const { return *data[0]; };
338
342 virtual Data* getDataBottom() { return data[0]; };
343
347 virtual int getNRadii() const { return nNodes; };
348
352 virtual int getNData() const { return nNodes; };
353
357 virtual float* getRadii()
358 {
359 float* fa = new float [nNodes];
360 for (int i=0; i<nNodes; ++i) fa[i] = radii[i];
361 return fa;
362 }
363
364
365 // *** TODO added 7/20/2012
370 virtual double getValue(int attributeIndex, int radiusIndex) const
371 { return data[radiusIndex]->getDouble(attributeIndex); }
372
379 virtual double getValueTop(int attributeIndex) const
380 { return data[nNodes-1]->getDouble(attributeIndex); }
381
386 virtual double getInterpolationCoefficient(int index, double radius) const;
387
388 // *** TODO modified interface 7/19/2012
393 virtual double getValue(const InterpolatorType& radialType,
394 int attributeIndex, double radius,
395 bool allowRadiusOutOfRange) const;
396
401 virtual int getRadiusIndex(double radius, int jlo) const;
402
403 // *** TODO added 7/20/2012
407 virtual double getInterpolationCoefficient(int index, double radius,
408 bool allowOutOfRange) const;
409
411
415 ProfileNPoint(IFStreamBinary& ifs, GeoTessMetaData& gtmd);
416
420 ProfileNPoint(IFStreamAscii& ifs, GeoTessMetaData& gtmd);
421
425 virtual ~ProfileNPoint();
426
430 virtual void write(IFStreamBinary& ofs);
431
435 virtual void write(IFStreamAscii& ofs);
436
437 // *** TODO added 7/20/2012
446 virtual int findClosestRadiusIndex(double radius) const
447 {
448 int i = Profile::getRadiusIndex(radius);
449 return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
450 }
451
452 // *** TODO added 7/20/2012
460 virtual void setPointIndex(int nodeIndex, int pointIndex)
461 {
462 if (pointIndices == NULL)
463 {
464 if (pointIndex < 0) return;
465
466 pointIndices = new int [nNodes];
467 for (int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
468 }
469 pointIndices[nodeIndex] = pointIndex;
470 }
471
472 // *** TODO added 10/14/2012
480 virtual void resetPointIndices()
481 {
482 if (pointIndices != NULL)
483 delete[] pointIndices;
484 pointIndices = NULL;
485 }
486
487 // *** TODO added 7/20/2012
495 virtual int getPointIndex(int nodeIndex) const
496 { return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
497
498 // *** TODO added 7/20/2012
505 virtual void getWeights(map<int, double>& weights,
506 double dkm, double radius, double hcoefficient) const
507 {
508 int node = Profile::getRadiusIndex(radius);
509
510 //TODO: need getInterpolationCoefficient to work for cubic spline interpolator. It currently does not.
511
512 // get coefficient at node influencing position radius
513
514 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
515
516 double c = getInterpolationCoefficient(node, radius, true);
517 if (c > 0.0)
518 {
519 map<int, double>::iterator it = weights.find(pointIndex);
520 if (it == weights.end())
521 weights[pointIndex] = dkm * hcoefficient * c;
522 else
523 it->second += dkm * hcoefficient * c;
524 }
525
526 // now get coefficient at node+1 influencing position radius
527
528 c = 1.0 - c;
529 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
530 if (c > 0.0)
531 {
532 map<int, double>::iterator it = weights.find(pointIndex);
533 if (it == weights.end())
534 weights[pointIndex] = dkm * hcoefficient * c;
535 else
536 it->second += dkm * hcoefficient * c;
537 }
538 }
539
540 // *** TODO added 7/26/2012
547 virtual void getCoefficients(map<int, double>& coefficients, double radius,
548 double horizontalCoefficient) const
549 {
550 int node = Profile::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 InterpolatorType& 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
597 // *** TODO added 8/20/2012
601 virtual Profile* copy()
602 {
603 Data** d = new Data* [nNodes];
604 float* r = new float [nNodes];
605 for (int i = 0; i < nNodes; ++i)
606 {
607 d[i] = data[i]->copy();
608 r[i] = radii[i];
609 }
610 return new ProfileNPoint(r, d, nNodes);
611 }
612
614
615 }; // end class ProfileNPoint
616
628 inline double ProfileNPoint::getInterpolationCoefficient(int index, double radius) const
629 {
630 if (radius <= radii[index]) return 1.0;
631 if (radius >= radii[index + 1]) return 0.0;
632 return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
633 }
634
647 inline double ProfileNPoint::getValue(const InterpolatorType& radialType,
648 int attributeIndex, double radius, bool allowRadiusOutOfRange) const
649 {
650 if (!allowRadiusOutOfRange &&
651 ((radius < (double)radii[0]) || (radius > (double)radii[nNodes-1])))
652 return NaN_DOUBLE;
653
654 int index = getRadiusIndex(radius, -1);
655
656 double r0 = radii[index];
657 double v0 = data[index]->getDouble(attributeIndex);
658
659 if (radius <= r0) return v0;
660
661 double r1 = radii[index + 1];
662 double v1 = data[index + 1]->getDouble(attributeIndex);
663
664 if (radius >= r1) return v1;
665
666 double a = (r1 - radius) / (r1 - r0);
667
668 double b = 1. - a;
669 double v = a * v0 + b * v1;
670
671 switch (radialType.ordinal())
672 {
673 case 0: // LINEAR
674 return v;
675
676 case 2: // CUBIC_SPLINE
677 check(attributeIndex);
678 return v + ((a * a * a - a) * y2[attributeIndex][index]
679 + (b * b * b - b) * y2[attributeIndex][index + 1])
680 * (r1 - r0) * (r1 - r0) / 6.0;
681
682 default:
683 ostringstream os;
684 os << endl << "ERROR in ProfileNPoint::getValue" << endl
685 << "InterpolatorType: " << radialType.name()
686 << " cannot be applied to a Profile." << endl
687 << "Must specify LINEAR or SPLINE" << endl;
688 throw GeoTessException(os, __FILE__, __LINE__, 4304);
689 }
690 }
691
693
699 inline void ProfileNPoint::check(int attributeIndex) const
700 {
701 if (y2 == NULL)
702 {
703 y2 = new double* [data[0]->size()];
704 for (int i=0; i<data[0]->size(); ++i)
705 y2[i] = NULL;
706 }
707 if (y2[attributeIndex] == NULL)
708 y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
709 }
710
712
713 } // end namespace geotess
714
715 #endif // PROFILENPOINT_OBJECT_H