38 #ifndef PROFILENPOINT_OBJECT_H
39 #define PROFILENPOINT_OBJECT_H
66 class GeoTessMetaData;
122 y2(NULL), pointIndices(NULL) {};
128 double* spline(
float* x,
GeoTessData** y,
int attributeIndex,
129 double yp1,
double ypn)
const;
136 void check(
int attributeIndex)
const;
153 data(NULL), y2(NULL), pointIndices(NULL)
155 radii =
new float[size];
157 for (
int i=0; i<size; ++i)
163 if (radii[0] > radii[size - 1])
166 os << endl <<
"ERROR in ProfileNPoint::ProfileNPoint" << endl
167 <<
"Profile has negative thickness" << endl;
169 for (
int i=0; i<size; ++i)
170 os << radii[i] <<
", ";
189 data(NULL), y2(NULL), pointIndices(NULL)
191 radii =
new float[nNodes];
193 for (
int i=0; i<nNodes; ++i)
199 if (r.size() != d.size())
202 os << endl <<
"ERROR in ProfileNPoint::ProfileNPoint" << endl
203 <<
"radii.size() != data.size()" << endl;
204 os <<
"radii.size = " << r.
size() << endl;
205 os <<
"data.size = " << d.size() << endl;
209 if (radii[0] > radii[nNodes - 1])
212 os << endl <<
"ERROR in ProfileNPoint::ProfileNPoint" << endl
213 <<
"Profile has negative thickness" << endl;
215 for (
int i=0; i<nNodes; ++i)
216 os << radii[i] <<
", ";
246 sz += nNodes*(
LONG_INT)
sizeof(
float);
255 sz += nNodes * (
LONG_INT)(
sizeof(
int));
257 sz += data[0]->
size() * nNodes * (
LONG_INT)
sizeof(
double);
268 {
return GeoTessProfileType::NPOINT; };
275 if (!GeoTessProfile::operator==(p))
return false;
277 if (nNodes != p.
getNRadii())
return false;
279 for (
int i = 0; i < nNodes; ++i)
281 (!(*(data[i]) == p.
getData(i))))
294 bool isNaN(
int nodeIndex,
int attributeIndex)
295 {
return data[nodeIndex]->
isNaN(attributeIndex); };
301 virtual float getRadius(
int i)
const {
return radii[i]; };
319 float* fa =
new float [nNodes];
320 for (
int i=0; i<nNodes; ++i) fa[i] = radii[i];
332 for (
int i=0; i<nNodes; ++i) da[i] = data[i];
350 virtual void setData(
const vector<GeoTessData*>& inData);
355 virtual void setRadii(
const vector<float>& newRadii)
356 {
for (
int i=0; i<nNodes; ++i) radii[i] = newRadii[i]; }
359 {
if (index < nNodes) radii[index] = radius; }
365 {
delete data[index]; data[index] = inData; }
402 virtual double getValue(
int attributeIndex,
int radiusIndex)
const
403 {
return data[radiusIndex]->
getDouble(attributeIndex); }
412 {
return data[nNodes-1]->
getDouble(attributeIndex); }
418 virtual double getInterpolationCoefficient(
int index,
double radius)
const;
425 int attributeIndex,
double radius,
426 bool allowRadiusOutOfRange)
const;
438 bool allowOutOfRange)
const;
475 virtual int findClosestRadiusIndex(
double radius)
const
477 int i = GeoTessProfile::getRadiusIndex(radius);
478 return abs(radii[i+1] - radius) < abs(radii[i] - radius) ? i+1 : i;
488 virtual void setPointIndex(
int nodeIndex,
int pointIndex)
490 if (pointIndices == NULL)
492 if (pointIndex < 0)
return;
494 pointIndices =
new int [nNodes];
495 for (
int i = 0; i < nNodes; ++i) pointIndices[i] = -1;
497 pointIndices[nodeIndex] = pointIndex;
507 virtual void resetPointIndices()
509 if (pointIndices != NULL)
510 delete[] pointIndices;
521 virtual int getPointIndex(
int nodeIndex)
const
522 {
return pointIndices == NULL ? -1 : pointIndices[nodeIndex]; }
530 virtual void getWeights(map<int, double>& weights,
531 double dkm,
double radius,
double hcoefficient)
const
533 int node = GeoTessProfile::getRadiusIndex(radius);
539 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
541 double c = getInterpolationCoefficient(node, radius,
true);
544 map<int, double>::iterator it = weights.find(pointIndex);
545 if (it == weights.end())
546 weights[pointIndex] = dkm * hcoefficient * c;
548 it->second += dkm * hcoefficient * c;
554 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
557 map<int, double>::iterator it = weights.find(pointIndex);
558 if (it == weights.end())
559 weights[pointIndex] = dkm * hcoefficient * c;
561 it->second += dkm * hcoefficient * c;
571 virtual void getCoefficients(map<int, double>& coefficients,
double radius,
572 double horizontalCoefficient)
const
574 int node = GeoTessProfile::getRadiusIndex(radius);
577 double c = getInterpolationCoefficient(node, radius,
true);
579 int pointIndex = pointIndices == NULL ? -1 : pointIndices[node];
582 coefficients[pointIndex] = c * horizontalCoefficient;
584 pointIndex = pointIndices == NULL ? -1 : pointIndices[node+1];
587 coefficients[pointIndex] = (1.0 - c) * horizontalCoefficient;
590 virtual void setInterpolationCoefficients(
const GeoTessInterpolatorType& interpType,
591 vector<int>& nodeIndexes, vector<double>& coefficients,
592 double& radius,
bool& allowOutOfRange)
596 if (radius < radii[0])
598 nodeIndexes.push_back(0);
599 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
601 else if (radius > radii[nNodes-1])
603 nodeIndexes.push_back(nNodes-1);
604 coefficients.push_back(allowOutOfRange ? 1 : NaN_DOUBLE);
608 int index = getRadiusIndex(radius, -1);
609 double c = ((double)radii[index + 1] - radius) /
610 ((double)radii[index + 1] - (
double)radii[index]);
611 nodeIndexes.push_back(index);
612 coefficients.push_back(c);
615 nodeIndexes.push_back(index+1);
616 coefficients.push_back(1.-c);
624 virtual GeoTessProfile* copy()
626 GeoTessData** d =
new GeoTessData* [nNodes];
627 float* r =
new float [nNodes];
628 for (
int i = 0; i < nNodes; ++i)
630 d[i] = data[i]->copy();
633 return new GeoTessProfileNPoint(r, d, nNodes);
651 inline double GeoTessProfileNPoint::getInterpolationCoefficient(
int index,
double radius)
const
653 if (radius <= radii[index])
return 1.0;
654 if (radius >= radii[index + 1])
return 0.0;
655 return (radii[index + 1] - radius) / (radii[index + 1] - radii[index]);
671 int attributeIndex,
double radius,
bool allowRadiusOutOfRange)
const
673 if (!allowRadiusOutOfRange &&
674 ((radius < (
double)radii[0]) || (radius > (
double)radii[nNodes-1])))
677 int index = getRadiusIndex(radius, -1);
679 double r0 = radii[index];
680 double v0 = data[index]->
getDouble(attributeIndex);
682 if (radius <= r0)
return v0;
684 double r1 = radii[index + 1];
685 double v1 = data[index + 1]->
getDouble(attributeIndex);
687 if (radius >= r1)
return v1;
689 double a = (r1 - radius) / (r1 - r0);
692 double v = a * v0 + b * v1;
700 check(attributeIndex);
701 return v + ((a * a * a - a) * y2[attributeIndex][index]
702 + (b * b * b - b) * y2[attributeIndex][index + 1])
703 * (r1 - r0) * (r1 - r0) / 6.0;
707 os << endl <<
"ERROR in ProfileNPoint::getValue" << endl
708 <<
"InterpolatorType: " << radialType.
name()
709 <<
" cannot be applied to a Profile." << endl
710 <<
"Must specify LINEAR or SPLINE" << endl;
722 inline void GeoTessProfileNPoint::check(
int attributeIndex)
const
726 y2 =
new double* [data[0]->
size()];
727 for (
int i=0; i<data[0]->size(); ++i)
730 if (y2[attributeIndex] == NULL)
731 y2[attributeIndex] = spline(radii, data, attributeIndex, 1.0e30, 1.0e30);
738 #endif // PROFILENPOINT_OBJECT_H