36 #ifndef PROFILENPOINT_OBJECT_H
37 #define PROFILENPOINT_OBJECT_H
64 class GeoTessMetaData;
120 y2(NULL), pointIndices(NULL) {};
126 double* spline(
float* x,
GeoTessData** 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];
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] <<
", ";
187 data(NULL), y2(NULL), pointIndices(NULL)
189 radii =
new float[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 GeoTessProfileType::NPOINT; };
251 if (!GeoTessProfile::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]; };
293 virtual float* getRadii()
295 float* fa =
new float [nNodes];
296 for (
int i=0; i<nNodes; ++i) fa[i] = radii[i];
308 for (
int i=0; i<nNodes; ++i) da[i] = data[i];
326 virtual void setData(
const vector<GeoTessData*>& inData);
331 virtual void setRadii(
const vector<float>& newRadii)
332 {
for (
int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
338 {
delete data[index]; data[index] = inData; }
375 virtual double getValue(
int attributeIndex,
int radiusIndex)
const
376 {
return data[radiusIndex]->
getDouble(attributeIndex); }
384 virtual double getValueTop(
int attributeIndex)
const
385 {
return data[nNodes-1]->getDouble(attributeIndex); }
391 virtual double getInterpolationCoefficient(
int index,
double radius)
const;
398 int attributeIndex,
double radius,
399 bool allowRadiusOutOfRange)
const;
405 virtual int getRadiusIndex(
double radius,
int jlo)
const;
410 virtual double getInterpolationCoefficient(
int index,
double radius,
411 bool allowOutOfRange)
const;
448 virtual int findClosestRadiusIndex(
double radius)
const
450 int i = GeoTessProfile::getRadiusIndex(radius);
451 return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
461 virtual void setPointIndex(
int nodeIndex,
int pointIndex)
463 if (pointIndices == NULL)
465 if (pointIndex < 0)
return;
467 pointIndices =
new int [nNodes];
468 for (
int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
470 pointIndices[nodeIndex] = pointIndex;
480 virtual void resetPointIndices()
482 if (pointIndices != NULL)
483 delete[] pointIndices;
494 virtual int getPointIndex(
int nodeIndex)
const
495 {
return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
503 virtual void getWeights(map<int, double>& weights,
504 double dkm,
double radius,
double hcoefficient)
const
506 int node = GeoTessProfile::getRadiusIndex(radius);
512 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
514 double c = getInterpolationCoefficient(node, radius,
true);
517 map<int, double>::iterator it = weights.find(pointIndex);
518 if (it == weights.end())
519 weights[pointIndex] = dkm * hcoefficient * c;
521 it->second += dkm * hcoefficient * c;
527 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
530 map<int, double>::iterator it = weights.find(pointIndex);
531 if (it == weights.end())
532 weights[pointIndex] = dkm * hcoefficient * c;
534 it->second += dkm * hcoefficient * c;
544 virtual void getCoefficients(map<int, double>& coefficients,
double radius,
545 double horizontalCoefficient)
const
547 int node = GeoTessProfile::getRadiusIndex(radius);
550 double c = getInterpolationCoefficient(node, radius,
true);
552 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
555 coefficients[pointIndex] = c * horizontalCoefficient;
557 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
560 coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
563 virtual void setInterpolationCoefficients(
const GeoTessInterpolatorType& interpType,
564 vector<int>& nodeIndexes, vector<double>& coefficients,
565 double& radius,
bool& allowOutOfRange)
569 if (radius < radii[0])
571 nodeIndexes.push_back(0);
572 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
574 else if (radius > radii[nNodes-1])
576 nodeIndexes.push_back(nNodes-1);
577 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
581 int index = getRadiusIndex(radius, -1);
582 double c = ((double)radii[index + 1] - radius) /
583 ((double)radii[index + 1] - (
double)radii[index]);
584 nodeIndexes.push_back(index);
585 coefficients.push_back(c);
588 nodeIndexes.push_back(index+1);
589 coefficients.push_back(1.-c);
597 virtual GeoTessProfile* copy()
599 GeoTessData** d =
new GeoTessData* [nNodes];
600 float* r =
new float [nNodes];
601 for (
int i = 0; i < nNodes; ++i)
603 d[i] = data[i]->copy();
606 return new GeoTessProfileNPoint(r, d, nNodes);
624 inline double GeoTessProfileNPoint::getInterpolationCoefficient(
int index,
double radius)
const
626 if (radius <= radii[index])
return 1.0;
627 if (radius >= radii[index + 1])
return 0.0;
628 return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
644 int attributeIndex,
double radius,
bool allowRadiusOutOfRange)
const
646 if (!allowRadiusOutOfRange &&
647 ((radius < (
double)radii[0]) || (radius > (
double)radii[nNodes-1])))
650 int index = getRadiusIndex(radius, -1);
652 double r0 = radii[index];
653 double v0 = data[index]->getDouble(attributeIndex);
655 if (radius <= r0)
return v0;
657 double r1 = radii[index + 1];
658 double v1 = data[index + 1]->getDouble(attributeIndex);
660 if (radius >= r1)
return v1;
662 double a = (r1 - radius) / (r1 - r0);
665 double v = a * v0 + b * v1;
673 check(attributeIndex);
674 return v + ((a * a * a - a) * y2[attributeIndex][index]
675 + (b * b * b - b) * y2[attributeIndex][index + 1])
676 * (r1 - r0) * (r1 - r0) / 6.0;
680 os << endl <<
"ERROR in ProfileNPoint::getValue" << endl
681 <<
"InterpolatorType: " << radialType.
name()
682 <<
" cannot be applied to a Profile." << endl
683 <<
"Must specify LINEAR or SPLINE" << endl;
695 inline void GeoTessProfileNPoint::check(
int attributeIndex)
const
699 y2 =
new double* [data[0]->size()];
700 for (
int i=0; i<data[0]->size(); ++i)
703 if (y2[attributeIndex] == NULL)
704 y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
711 #endif // PROFILENPOINT_OBJECT_H