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 sz += nNodes*(
LONG_INT)
sizeof(
float);
250 sz += nNodes*data[0]->getMemory();
253 sz += nNodes * (
LONG_INT)(
sizeof(
int));
255 sz += data[0]->size() * nNodes * (
LONG_INT)
sizeof(
double);
266 {
return GeoTessProfileType::NPOINT; };
273 if (!GeoTessProfile::operator==(p))
return false;
275 if (nNodes != p.
getNRadii())
return false;
277 for (
int i = 0; i < nNodes; ++i)
279 (!(*(data[i]) == p.
getData(i))))
292 bool isNaN(
int nodeIndex,
int attributeIndex)
293 {
return data[nodeIndex]->isNaN(attributeIndex); };
299 virtual float getRadius(
int i)
const {
return radii[i]; };
315 virtual float* getRadii()
317 float* fa =
new float [nNodes];
318 for (
int i=0; i<nNodes; ++i) fa[i] = radii[i];
330 for (
int i=0; i<nNodes; ++i) da[i] = data[i];
348 virtual void setData(
const vector<GeoTessData*>& inData);
353 virtual void setRadii(
const vector<float>& newRadii)
354 {
for (
int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
356 virtual void setRadius(
int index,
float radius)
357 {
if (index < nNodes) radii[index] = radius; }
363 {
delete data[index]; data[index] = inData; }
400 virtual double getValue(
int attributeIndex,
int radiusIndex)
const
401 {
return data[radiusIndex]->
getDouble(attributeIndex); }
409 virtual double getValueTop(
int attributeIndex)
const
410 {
return data[nNodes-1]->getDouble(attributeIndex); }
416 virtual double getInterpolationCoefficient(
int index,
double radius)
const;
423 int attributeIndex,
double radius,
424 bool allowRadiusOutOfRange)
const;
430 virtual int getRadiusIndex(
double radius,
int jlo)
const;
435 virtual double getInterpolationCoefficient(
int index,
double radius,
436 bool allowOutOfRange)
const;
473 virtual int findClosestRadiusIndex(
double radius)
const
475 int i = GeoTessProfile::getRadiusIndex(radius);
476 return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
486 virtual void setPointIndex(
int nodeIndex,
int pointIndex)
488 if (pointIndices == NULL)
490 if (pointIndex < 0)
return;
492 pointIndices =
new int [nNodes];
493 for (
int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
495 pointIndices[nodeIndex] = pointIndex;
505 virtual void resetPointIndices()
507 if (pointIndices != NULL)
508 delete[] pointIndices;
519 virtual int getPointIndex(
int nodeIndex)
const
520 {
return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
528 virtual void getWeights(map<int, double>& weights,
529 double dkm,
double radius,
double hcoefficient)
const
531 int node = GeoTessProfile::getRadiusIndex(radius);
537 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
539 double c = getInterpolationCoefficient(node, radius,
true);
542 map<int, double>::iterator it = weights.find(pointIndex);
543 if (it == weights.end())
544 weights[pointIndex] = dkm * hcoefficient * c;
546 it->second += dkm * hcoefficient * c;
552 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
555 map<int, double>::iterator it = weights.find(pointIndex);
556 if (it == weights.end())
557 weights[pointIndex] = dkm * hcoefficient * c;
559 it->second += dkm * hcoefficient * c;
569 virtual void getCoefficients(map<int, double>& coefficients,
double radius,
570 double horizontalCoefficient)
const
572 int node = GeoTessProfile::getRadiusIndex(radius);
575 double c = getInterpolationCoefficient(node, radius,
true);
577 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
580 coefficients[pointIndex] = c * horizontalCoefficient;
582 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
585 coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
588 virtual void setInterpolationCoefficients(
const GeoTessInterpolatorType& interpType,
589 vector<int>& nodeIndexes, vector<double>& coefficients,
590 double& radius,
bool& allowOutOfRange)
594 if (radius < radii[0])
596 nodeIndexes.push_back(0);
597 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
599 else if (radius > radii[nNodes-1])
601 nodeIndexes.push_back(nNodes-1);
602 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
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);
613 nodeIndexes.push_back(index+1);
614 coefficients.push_back(1.-c);
622 virtual GeoTessProfile* copy()
624 GeoTessData** d =
new GeoTessData* [nNodes];
625 float* r =
new float [nNodes];
626 for (
int i = 0; i < nNodes; ++i)
628 d[i] = data[i]->copy();
631 return new GeoTessProfileNPoint(r, d, nNodes);
649 inline double GeoTessProfileNPoint::getInterpolationCoefficient(
int index,
double radius)
const
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]);
669 int attributeIndex,
double radius,
bool allowRadiusOutOfRange)
const
671 if (!allowRadiusOutOfRange &&
672 ((radius < (
double)radii[0]) || (radius > (
double)radii[nNodes-1])))
675 int index = getRadiusIndex(radius, -1);
677 double r0 = radii[index];
678 double v0 = data[index]->getDouble(attributeIndex);
680 if (radius <= r0)
return v0;
682 double r1 = radii[index + 1];
683 double v1 = data[index + 1]->getDouble(attributeIndex);
685 if (radius >= r1)
return v1;
687 double a = (r1 - radius) / (r1 - r0);
690 double v = a * v0 + b * v1;
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;
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;
720 inline void GeoTessProfileNPoint::check(
int attributeIndex)
const
724 y2 =
new double* [data[0]->size()];
725 for (
int i=0; i<data[0]->size(); ++i)
728 if (y2[attributeIndex] == NULL)
729 y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
736 #endif // PROFILENPOINT_OBJECT_H