36 #ifndef PROFILENPOINT_OBJECT_H
37 #define PROFILENPOINT_OBJECT_H
64 class GeoTessMetaData;
120 y2(NULL), pointIndices(NULL) {};
126 double* spline(
float* x,
Data** y,
int attributeIndex,
127 double yp1,
double ypn)
const;
134 void check(
int attributeIndex)
const;
151 data(NULL), y2(NULL), pointIndices(NULL)
153 radii =
new float[size];
154 data =
new Data*[size];
155 for (
int i=0; i<size; ++i)
161 if (radii[0] > radii[size - 1])
164 os << endl <<
"ERROR in ProfileNPoint::ProfileNPoint" << endl
165 <<
"Profile has negative thickness" << endl;
167 for (
int i=0; i<size; ++i)
168 os << radii[i] <<
", ";
186 :
Profile(), nNodes(r.size()), radii(NULL),
187 data(NULL), y2(NULL), pointIndices(NULL)
189 radii =
new float[nNodes];
190 data =
new Data*[nNodes];
191 for (
int i=0; i<nNodes; ++i)
197 if (r.size() != d.size())
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;
207 if (radii[0] > radii[nNodes - 1])
210 os << endl <<
"ERROR in ProfileNPoint::ProfileNPoint" << endl
211 <<
"Profile has negative thickness" << endl;
213 for (
int i=0; i<nNodes; ++i)
214 os << radii[i] <<
", ";
235 virtual int class_size()
const
244 {
return ProfileType::NPOINT; };
249 virtual bool operator == (
const Profile& p)
const
251 if (!Profile::operator==(p))
return false;
253 if (nNodes != p.
getNRadii())
return false;
255 for (
int i = 0; i < nNodes; ++i)
257 (!(*(data[i]) == p.
getData(i))))
270 bool isNaN(
int nodeIndex,
int attributeIndex)
271 {
return data[nodeIndex]->isNaN(attributeIndex); };
277 virtual float getRadius(
int i)
const {
return radii[i]; };
298 virtual void setData(
const vector<Data*>& inData);
304 virtual void setRadii(
const vector<float>& newRadii)
305 {
for (
int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
311 virtual void setData(
int index,
Data* inData)
312 {
delete data[index]; data[index] = inData; }
357 virtual float* getRadii()
359 float* fa =
new float [nNodes];
360 for (
int i=0; i<nNodes; ++i) fa[i] = radii[i];
370 virtual double getValue(
int attributeIndex,
int radiusIndex)
const
371 {
return data[radiusIndex]->getDouble(attributeIndex); }
379 virtual double getValueTop(
int attributeIndex)
const
380 {
return data[nNodes-1]->getDouble(attributeIndex); }
386 virtual double getInterpolationCoefficient(
int index,
double radius)
const;
394 int attributeIndex,
double radius,
395 bool allowRadiusOutOfRange)
const;
401 virtual int getRadiusIndex(
double radius,
int jlo)
const;
407 virtual double getInterpolationCoefficient(
int index,
double radius,
408 bool allowOutOfRange)
const;
446 virtual int findClosestRadiusIndex(
double radius)
const
448 int i = Profile::getRadiusIndex(radius);
449 return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
460 virtual void setPointIndex(
int nodeIndex,
int pointIndex)
462 if (pointIndices == NULL)
464 if (pointIndex < 0)
return;
466 pointIndices =
new int [nNodes];
467 for (
int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
469 pointIndices[nodeIndex] = pointIndex;
480 virtual void resetPointIndices()
482 if (pointIndices != NULL)
483 delete[] pointIndices;
495 virtual int getPointIndex(
int nodeIndex)
const
496 {
return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
505 virtual void getWeights(map<int, double>& weights,
506 double dkm,
double radius,
double hcoefficient)
const
508 int node = Profile::getRadiusIndex(radius);
514 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
516 double c = getInterpolationCoefficient(node, radius,
true);
519 map<int, double>::iterator it = weights.find(pointIndex);
520 if (it == weights.end())
521 weights[pointIndex] = dkm * hcoefficient * c;
523 it->second += dkm * hcoefficient * c;
529 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
532 map<int, double>::iterator it = weights.find(pointIndex);
533 if (it == weights.end())
534 weights[pointIndex] = dkm * hcoefficient * c;
536 it->second += dkm * hcoefficient * c;
547 virtual void getCoefficients(map<int, double>& coefficients,
double radius,
548 double horizontalCoefficient)
const
550 int node = Profile::getRadiusIndex(radius);
553 double c = getInterpolationCoefficient(node, radius,
true);
555 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
558 coefficients[pointIndex] = c * horizontalCoefficient;
560 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
563 coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
566 virtual void setInterpolationCoefficients(
const InterpolatorType& interpType,
567 vector<int>& nodeIndexes, vector<double>& coefficients,
568 double& radius,
bool& allowOutOfRange)
572 if (radius < radii[0])
574 nodeIndexes.push_back(0);
575 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
577 else if (radius > radii[nNodes-1])
579 nodeIndexes.push_back(nNodes-1);
580 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
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);
591 nodeIndexes.push_back(index+1);
592 coefficients.push_back(1.-c);
601 virtual Profile* copy()
603 Data** d =
new Data* [nNodes];
604 float* r =
new float [nNodes];
605 for (
int i = 0; i < nNodes; ++i)
607 d[i] = data[i]->copy();
610 return new ProfileNPoint(r, d, nNodes);
628 inline double ProfileNPoint::getInterpolationCoefficient(
int index,
double radius)
const
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]);
648 int attributeIndex,
double radius,
bool allowRadiusOutOfRange)
const
650 if (!allowRadiusOutOfRange &&
651 ((radius < (
double)radii[0]) || (radius > (
double)radii[nNodes-1])))
654 int index = getRadiusIndex(radius, -1);
656 double r0 = radii[index];
657 double v0 = data[index]->getDouble(attributeIndex);
659 if (radius <= r0)
return v0;
661 double r1 = radii[index + 1];
662 double v1 = data[index + 1]->getDouble(attributeIndex);
664 if (radius >= r1)
return v1;
666 double a = (r1 - radius) / (r1 - r0);
669 double v = a * v0 + b * v1;
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;
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;
699 inline void ProfileNPoint::check(
int attributeIndex)
const
703 y2 =
new double* [data[0]->size()];
704 for (
int i=0; i<data[0]->size(); ++i)
707 if (y2[attributeIndex] == NULL)
708 y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
715 #endif // PROFILENPOINT_OBJECT_H