support for extrapolating values when doing cubic spline interpolation

metadata
Wenzel Jakob 2012-10-24 23:40:25 -04:00
parent 0cf83b5a1b
commit d7c1ab1191
4 changed files with 55 additions and 29 deletions

View File

@ -358,11 +358,14 @@ extern MTS_EXPORT_CORE bool solveQuadraticDouble(double a, double b,
* Position of the last knot * Position of the last knot
* \param size * \param size
* Denotes the size of the \c data array * Denotes the size of the \c data array
* \param extrapolate
* Extrapolate data values when \c x is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c x lies outside of [\c min, \c max] * The interpolated value or zero when <tt>extrapolate=false</tt>tt>
* and \c x lies outside of [\c min, \c max]
*/ */
extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data, extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data,
Float min, Float max, size_t size); Float min, Float max, size_t size, bool extrapolate = false);
/** /**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 1D function * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 1D function
@ -382,11 +385,14 @@ extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data,
* the entries of \c nodes. * the entries of \c nodes.
* \param size * \param size
* Denotes the size of the \c data array * Denotes the size of the \c data array
* \param extrapolate
* Extrapolate data values when \c x is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c x lies outside of \a [\c min, \c max] * The interpolated value or zero when <tt>extrapolate=false</tt>tt>
* and \c x lies outside of \a [\c min, \c max]
*/ */
extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes, extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes,
const Float *data, size_t size); const Float *data, size_t size, bool extrapolate = false);
/** /**
* \brief Evaluate a cubic spline interpolant of a regularly sampled 2D function * \brief Evaluate a cubic spline interpolant of a regularly sampled 2D function
@ -407,11 +413,14 @@ extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes,
* Position of the last knot on each dimension * Position of the last knot on each dimension
* \param size * \param size
* Denotes the size of the \c data array (along each dimension) * Denotes the size of the \c data array (along each dimension)
* \param extrapolate
* Extrapolate data values when \c p is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c p lies outside of the knot range * The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/ */
extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data, extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data,
const Point2 &min, const Point2 &max, const Size2 &size); const Point2 &min, const Point2 &max, const Size2 &size, bool extrapolate = false);
/** /**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 2D function * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 2D function
@ -435,11 +444,14 @@ extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data,
* Consecutive entries of this array correspond to increments in the 'x' coordinate. * Consecutive entries of this array correspond to increments in the 'x' coordinate.
* \param size * \param size
* Denotes the size of the \c data array (along each dimension) * Denotes the size of the \c data array (along each dimension)
* \param extrapolate
* Extrapolate data values when \c p is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c p lies outside of the knot range * The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/ */
extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float **nodes, extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float **nodes,
const Float *data, const Size2 &size); const Float *data, const Size2 &size, bool extrapolate = false);
/** /**
* \brief Evaluate a cubic spline interpolant of a regularly sampled 3D function * \brief Evaluate a cubic spline interpolant of a regularly sampled 3D function
@ -461,11 +473,14 @@ extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float
* Position of the last knot on each dimension * Position of the last knot on each dimension
* \param size * \param size
* Denotes the size of the \c data array (along each dimension) * Denotes the size of the \c data array (along each dimension)
* \param extrapolate
* Extrapolate data values when \c p is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c p lies outside of the knot range * The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/ */
extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data, extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data,
const Point3 &min, const Point3 &max, const Size3 &size); const Point3 &min, const Point3 &max, const Size3 &size, bool extrapolate = false);
/** /**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 3D function * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 3D function
@ -490,11 +505,14 @@ extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data,
* then 'y', and finally 'z' increments. * then 'y', and finally 'z' increments.
* \param size * \param size
* Denotes the size of the \c data array (along each dimension) * Denotes the size of the \c data array (along each dimension)
* \param extrapolate
* Extrapolate data values when \c p is out of range? (default: \c false)
* \return * \return
* The interpolated value or zero when \c p lies outside of the knot range * The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/ */
extern MTS_EXPORT_CORE Float interpCubic3DIrregular(const Point3 &p, const Float **nodes, extern MTS_EXPORT_CORE Float interpCubic3DIrregular(const Point3 &p, const Float **nodes,
const Float *data, const Size3 &size); const Float *data, const Size3 &size, bool extrapolate = false);
//// Convert radians to degrees //// Convert radians to degrees
inline Float radToDeg(Float value) { return value * (180.0f / M_PI); } inline Float radToDeg(Float value) { return value * (180.0f / M_PI); }

View File

@ -206,8 +206,15 @@ public:
*/ */
void computeUVTangents(); void computeUVTangents();
/// Generate surface normals /**
void computeNormals(); * \brief Generate smooth vertex normals?
*
* \param force
* When this parameter is set to true, the function
* generates normals <em>even</em> when there are
* already existing ones.
*/
void computeNormals(bool force = false);
/** /**
* \brief Rebuild the mesh so that adjacent faces * \brief Rebuild the mesh so that adjacent faces

View File

@ -469,9 +469,9 @@ bool solveLinearSystem2x2(const Float a[2][2], const Float b[2], Float x[2]) {
return true; return true;
} }
Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t size) { Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t size, bool extrapolate) {
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(x >= min && x <= max)) if (!(x >= min && x <= max) && !extrapolate)
return 0.0f; return 0.0f;
/* Transform 'x' so that knots lie at integer positions */ /* Transform 'x' so that knots lie at integer positions */
@ -508,9 +508,9 @@ Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t siz
( t3 - t2) * d1; ( t3 - t2) * d1;
} }
Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, size_t size) { Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, size_t size, bool extrapolate) {
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(x >= nodes[0] && x <= nodes[size-1])) if (!(x >= nodes[0] && x <= nodes[size-1]) && !extrapolate)
return 0.0f; return 0.0f;
size_t k = (size_t) std::max((ptrdiff_t) 0, std::min((ptrdiff_t) size - 2, size_t k = (size_t) std::max((ptrdiff_t) 0, std::min((ptrdiff_t) size - 2,
@ -545,7 +545,7 @@ Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, siz
Float interpCubic2D(const Point2 &p, const Float *data, Float interpCubic2D(const Point2 &p, const Float *data,
const Point2 &min, const Point2 &max, const Size2 &size) { const Point2 &min, const Point2 &max, const Size2 &size, bool extrapolate) {
Float knotWeights[2][4]; Float knotWeights[2][4];
Size2 knot; Size2 knot;
@ -553,7 +553,7 @@ Float interpCubic2D(const Point2 &p, const Float *data,
for (int dim=0; dim<2; ++dim) { for (int dim=0; dim<2; ++dim) {
Float *weights = knotWeights[dim]; Float *weights = knotWeights[dim];
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(p[dim] >= min[dim] && p[dim] <= max[dim])) if (!(p[dim] >= min[dim] && p[dim] <= max[dim]) && !extrapolate)
return 0.0f; return 0.0f;
/* Transform 'p' so that knots lie at integer positions */ /* Transform 'p' so that knots lie at integer positions */
@ -615,7 +615,7 @@ Float interpCubic2D(const Point2 &p, const Float *data,
} }
Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_, Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_,
const Float *data, const Size2 &size) { const Float *data, const Size2 &size, bool extrapolate) {
Float knotWeights[2][4]; Float knotWeights[2][4];
Size2 knot; Size2 knot;
@ -625,7 +625,7 @@ Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_,
Float *weights = knotWeights[dim]; Float *weights = knotWeights[dim];
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1])) if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1]) && !extrapolate)
return 0.0f; return 0.0f;
/* Find the index of the left knot in the queried subinterval, be /* Find the index of the left knot in the queried subinterval, be
@ -689,7 +689,7 @@ Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_,
} }
Float interpCubic3D(const Point3 &p, const Float *data, Float interpCubic3D(const Point3 &p, const Float *data,
const Point3 &min, const Point3 &max, const Size3 &size) { const Point3 &min, const Point3 &max, const Size3 &size, bool extrapolate) {
Float knotWeights[3][4]; Float knotWeights[3][4];
Size3 knot; Size3 knot;
@ -697,7 +697,7 @@ Float interpCubic3D(const Point3 &p, const Float *data,
for (int dim=0; dim<3; ++dim) { for (int dim=0; dim<3; ++dim) {
Float *weights = knotWeights[dim]; Float *weights = knotWeights[dim];
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(p[dim] >= min[dim] && p[dim] <= max[dim])) if (!(p[dim] >= min[dim] && p[dim] <= max[dim]) && !extrapolate)
return 0.0f; return 0.0f;
/* Transform 'p' so that knots lie at integer positions */ /* Transform 'p' so that knots lie at integer positions */
@ -763,7 +763,7 @@ Float interpCubic3D(const Point3 &p, const Float *data,
} }
Float interpCubic3DIrregular(const Point3 &p, const Float **nodes_, Float interpCubic3DIrregular(const Point3 &p, const Float **nodes_,
const Float *data, const Size3 &size) { const Float *data, const Size3 &size, bool extrapolate) {
Float knotWeights[3][4]; Float knotWeights[3][4];
Size3 knot; Size3 knot;
@ -773,7 +773,7 @@ Float interpCubic3DIrregular(const Point3 &p, const Float **nodes_,
Float *weights = knotWeights[dim]; Float *weights = knotWeights[dim];
/* Give up when given an out-of-range or NaN argument */ /* Give up when given an out-of-range or NaN argument */
if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1])) if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1]) && !extrapolate)
return 0.0f; return 0.0f;
/* Find the index of the left knot in the queried subinterval, be /* Find the index of the left knot in the queried subinterval, be

View File

@ -542,7 +542,7 @@ void TriMesh::rebuildTopology(Float maxAngle) {
configure(); configure();
} }
void TriMesh::computeNormals() { void TriMesh::computeNormals(bool force) {
int invalidNormals = 0; int invalidNormals = 0;
if (m_faceNormals) { if (m_faceNormals) {
if (m_normals) { if (m_normals) {
@ -558,7 +558,7 @@ void TriMesh::computeNormals() {
} }
} }
} else { } else {
if (m_normals) { if (m_normals && !force) {
if (m_flipNormals) { if (m_flipNormals) {
for (size_t i=0; i<m_vertexCount; i++) for (size_t i=0; i<m_vertexCount; i++)
m_normals[i] *= -1; m_normals[i] *= -1;
@ -566,7 +566,8 @@ void TriMesh::computeNormals() {
/* Do nothing */ /* Do nothing */
} }
} else { } else {
m_normals = new Normal[m_vertexCount]; if (!m_normals)
m_normals = new Normal[m_vertexCount];
memset(m_normals, 0, sizeof(Normal)*m_vertexCount); memset(m_normals, 0, sizeof(Normal)*m_vertexCount);
/* Well-behaved vertex normal computation based on /* Well-behaved vertex normal computation based on