44#ifndef _INCLUDED_Field3D_Resample_H_
45#define _INCLUDED_Field3D_Resample_H_
79template <
typename Field_T,
typename FilterOp_T>
80bool resample(
const Field_T &src, Field_T &tgt,
const V3i &newRes,
91 typedef boost::shared_ptr<Filter>
Ptr;
92 typedef boost::shared_ptr<const Filter>
CPtr;
97 virtual float eval(
const float t)
const = 0;
116 typedef boost::shared_ptr<BoxFilter>
Ptr;
117 typedef boost::shared_ptr<const BoxFilter>
CPtr;
129 virtual float eval(
const float x)
const
142 template <
typename Value_T>
143 static void op(Value_T &accumValue,
const Value_T value)
156 typedef boost::shared_ptr<MinFilter>
Ptr;
157 typedef boost::shared_ptr<const MinFilter>
CPtr;
169 virtual float eval(
const float x)
const
184 return std::numeric_limits<float>::max();
187 template <
typename T>
188 static void op(Imath::Vec3<T> &accumValue,
const Imath::Vec3<T> value)
190 accumValue.x = std::min(accumValue.x, value.x);
191 accumValue.y = std::min(accumValue.y, value.y);
192 accumValue.z = std::min(accumValue.z, value.z);
195 template <
typename Value_T>
196 static void op(Value_T &accumValue,
const Value_T value)
198 accumValue = std::min(accumValue, value);
212 typedef boost::shared_ptr<MaxFilter>
Ptr;
213 typedef boost::shared_ptr<const MaxFilter>
CPtr;
225 virtual float eval(
const float x)
const
240 return -std::numeric_limits<float>::max();
244 template <
typename T>
245 static void op(Imath::Vec3<T> &accumValue,
const Imath::Vec3<T> value)
247 accumValue.x = std::max(accumValue.x, value.x);
248 accumValue.y = std::max(accumValue.y, value.y);
249 accumValue.z = std::max(accumValue.z, value.z);
252 template <
typename Value_T>
253 static void op(Value_T &accumValue,
const Value_T value)
255 accumValue = std::max(accumValue, value);
269 typedef boost::shared_ptr<TriangleFilter>
Ptr;
270 typedef boost::shared_ptr<const TriangleFilter>
CPtr;
282 virtual float eval(
const float x)
const
294 template <
typename Value_T>
295 static void op(Value_T &,
const Value_T )
308 typedef boost::shared_ptr<GaussianFilter>
Ptr;
309 typedef boost::shared_ptr<const GaussianFilter>
CPtr;
316 m_exp(std::exp(-alpha * width * width)),
320 virtual float eval(
const float t)
const
323 return std::max(0.0f, std::exp(-
m_alpha * x * x) -
m_exp);
329 template <
typename Value_T>
330 static void op(Value_T &accumValue,
const Value_T value)
343 typedef boost::shared_ptr<MitchellFilter>
Ptr;
344 typedef boost::shared_ptr<const MitchellFilter>
CPtr;
350 const float B = 1.0 / 3.0,
const float C = 1.0 / 3.0)
354 virtual float eval(
const float x)
const
356 const float ax = std::abs(x /
m_width);
358 return ((12 - 9 *
m_B - 6 *
m_C) * ax * ax * ax +
359 (-18 + 12 *
m_B + 6 *
m_C) * ax * ax + (6 - 2 *
m_B)) / 6;
360 }
else if ((ax >= 1) && (ax < 2)) {
361 return ((-
m_B - 6 *
m_C) * ax * ax * ax +
362 (6 *
m_B + 30 *
m_C) * ax * ax + (-12 *
m_B - 48 *
m_C) *
363 ax + (8 *
m_B + 24 *
m_C)) / 6;
372 template <
typename Value_T>
373 static void op(Value_T &accumValue,
const Value_T value)
389 const V3f &srcSize,
const V3f &tgtSize);
394 srcSupportBBox(
const float &tgtP,
const float support,
const bool doUpres,
395 const float &srcSize,
const float &tgtSize);
400 const V3f &srcSize,
const V3f &tgtSize);
404 float getDist(
const bool doUpres,
const float &srcP,
const float &tgtP,
405 const float &srcSize,
const float &tgtSize);
409 template <
typename Field_T,
typename FilterOp_T,
bool IsAnalytic_T>
411 const FilterOp_T &filterOp,
const size_t dim)
413 typedef typename Field_T::value_type T;
415 const V3i srcRes = src.dataWindow().size() +
V3i(1);
416 const float srcDomain =
V3f(srcRes)[dim];
417 const float tgtDomain =
V3f(newRes)[dim];
418 const float srcSize = 1.0 / srcDomain;
419 const float tgtSize = 1.0 / tgtDomain;
422 const float support = filterOp.support();
425 const bool doUpres = newRes[dim] > srcRes[dim] ? 1 : 0;
431 for (
int k = 0; k < newRes.z; ++k) {
432 for (
int j = 0; j < newRes.y; ++j) {
433 for (
int i = 0; i < newRes.x; ++i) {
434 T accumValue(filterOp.initialValue());
439 std::pair<int, int> srcInterval =
443 std::max(srcInterval.first, src.dataWindow().min[dim]);
445 std::min(srcInterval.second, src.dataWindow().max[dim]);
447 for (
int s = srcInterval.first; s <= srcInterval.second; ++s) {
449 const int xIdx = dim == 0 ? s : i;
450 const int yIdx = dim == 1 ? s : j;
451 const int zIdx = dim == 2 ? s : k;
453 const T value = src.fastValue(xIdx, yIdx, zIdx);
456 const float dist =
getDist(doUpres, srcP, tgtP, srcSize, tgtSize);
457 const float weight = filterOp.eval(dist);
460 FilterOp_T::op(accumValue, value);
464 if (accumValue !=
static_cast<T
>(filterOp.initialValue())) {
465 tgt.fastLValue(i, j, k) = accumValue;
468 float accumWeight = 0.0f;
472 std::pair<int, int> srcInterval =
476 std::max(srcInterval.first, src.dataWindow().min[dim]);
478 std::min(srcInterval.second, src.dataWindow().max[dim]);
480 for (
int s = srcInterval.first; s <= srcInterval.second; ++s) {
482 const int xIdx = dim == 0 ? s : i;
483 const int yIdx = dim == 1 ? s : j;
484 const int zIdx = dim == 2 ? s : k;
486 const T value = src.fastValue(xIdx, yIdx, zIdx);
489 const float dist =
getDist(doUpres, srcP, tgtP, srcSize, tgtSize);
490 const float weight = filterOp.eval(dist);
492 accumWeight += weight;
493 accumValue += value * weight;
496 if (accumWeight > 0.0f && accumValue !=
static_cast<T
>(0.0)) {
497 tgt.fastLValue(i, j, k) = accumValue / accumWeight;
510 template <
typename Field_T,
typename FilterOp_T>
512 const FilterOp_T &filterOp)
516 typedef typename Field_T::value_type T;
518 if (!src.dataWindow().hasVolume()) {
522 if (src.dataWindow().min !=
V3i(0)) {
530 V3i oldRes = src.dataWindow().size() +
V3i(1);
531 V3i xRes(newRes.x, oldRes.y, oldRes.z);
532 V3i yRes(newRes.x, newRes.y, oldRes.z);
533 V3i zRes(newRes.x, newRes.y, newRes.z);
544 tgt.attribute = src.attribute;
545 tgt.setMapping(src.mapping());
546 tgt.copyMetadata(src);
559template <
typename Field_T,
typename FilterOp_T>
561 const FilterOp_T &filterOp)
Contains the DenseField class.
double discToCont(int discCoord)
Goes from discrete coordinates to continuous coordinates See Graphics Gems - What is a pixel.
static int filter(std::string &name, const char *suffix)
FIELD3D_NAMESPACE_OPEN bool resample(const Field_T &src, Field_T &tgt, const V3i &newRes, const FilterOp_T &filter)
Resamples the source field into the target field, such that the new data window is @dataWindow.
Contains the SparseField class.
Box3i srcSupportBBox(const V3f &tgtP, const float support, const V3i &doUpres, const V3f &srcSize, const V3f &tgtSize)
V3f getDist(const V3i &doUpres, const V3f &srcP, const V3f &tgtP, const V3f &srcSize, const V3f &tgtSize)
void separable(const Field_T &src, Field_T &tgt, const V3i &newRes, const FilterOp_T &filterOp, const size_t dim)
bool separableResample(const Field_T &src, Field_T &tgt, const V3i &newRes, const FilterOp_T &filterOp)
Resamples the source field into the target field, using separable execution, which is faster than res...
#define FIELD3D_NAMESPACE_HEADER_CLOSE
static const bool isAnalytic
boost::shared_ptr< BoxFilter > Ptr
virtual float support() const
Radial width of the filter (half of diameter)
boost::shared_ptr< const BoxFilter > CPtr
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
static void op(Value_T &accumValue, const Value_T value)
BoxFilter(const float width)
virtual float eval(const float t) const =0
Evaluates the filter at coordinate 't'.
boost::shared_ptr< const Filter > CPtr
boost::shared_ptr< Filter > Ptr
virtual float support() const =0
Radial width of the filter (half of diameter)
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
static const bool isAnalytic
boost::shared_ptr< GaussianFilter > Ptr
virtual float eval(const float t) const
Evaluates the filter at coordinate 't'.
GaussianFilter(const float alpha=2.0, const float width=2.0)
virtual float support() const
Radial width of the filter (half of diameter)
static void op(Value_T &accumValue, const Value_T value)
boost::shared_ptr< const GaussianFilter > CPtr
boost::shared_ptr< const MaxFilter > CPtr
static void op(Value_T &accumValue, const Value_T value)
static const bool isAnalytic
static void op(Imath::Vec3< T > &accumValue, const Imath::Vec3< T > value)
boost::shared_ptr< MaxFilter > Ptr
virtual float support() const
Radial width of the filter (half of diameter)
MaxFilter(const float width)
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
virtual float support() const
Radial width of the filter (half of diameter)
MinFilter(const float width)
boost::shared_ptr< MinFilter > Ptr
static void op(Value_T &accumValue, const Value_T value)
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
static const bool isAnalytic
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
static void op(Imath::Vec3< T > &accumValue, const Imath::Vec3< T > value)
boost::shared_ptr< const MinFilter > CPtr
virtual float support() const
Radial width of the filter (half of diameter)
MitchellFilter(const float width=1.0, const float B=1.0/3.0, const float C=1.0/3.0)
static void op(Value_T &accumValue, const Value_T value)
boost::shared_ptr< const MitchellFilter > CPtr
boost::shared_ptr< MitchellFilter > Ptr
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
static const bool isAnalytic
boost::shared_ptr< TriangleFilter > Ptr
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
static const bool isAnalytic
TriangleFilter(const float width)
boost::shared_ptr< const TriangleFilter > CPtr
static void op(Value_T &, const Value_T)
virtual float support() const
Radial width of the filter (half of diameter)