44 #ifndef _INCLUDED_Field3D_Resample_H_ 45 #define _INCLUDED_Field3D_Resample_H_ 79 template <
typename Field_T,
typename FilterOp_T>
80 bool 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;
99 virtual float support()
const = 0;
116 typedef boost::shared_ptr<BoxFilter>
Ptr;
117 typedef boost::shared_ptr<const BoxFilter>
CPtr;
119 static const bool isAnalytic =
false;
129 virtual float eval(
const float x)
const 131 const float t = x / m_width;
140 return 0.5f * m_width;
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;
159 static const bool isAnalytic =
true;
169 virtual float eval(
const float x)
const 171 const float t = x / m_width;
180 return 0.5f * m_width;
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;
215 static const bool isAnalytic =
true;
225 virtual float eval(
const float x)
const 227 const float t = x / m_width;
236 return 0.5f * m_width;
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;
272 static const bool isAnalytic =
false;
282 virtual float eval(
const float x)
const 284 const float t = x / m_width;
292 return 1.0f * m_width;
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;
311 static const bool isAnalytic =
false;
316 m_exp(
std::exp(-alpha * width * width)),
320 virtual float eval(
const float t)
const 322 const float x = t / m_width;
323 return std::max(0.0f, std::exp(-m_alpha * x * x) - m_exp);
327 return 2.0f * m_width;
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;
346 static const bool isAnalytic =
false;
350 const float B = 1.0 / 3.0,
const float C = 1.0 / 3.0)
351 : m_B(B), m_C(C), m_width(width)
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;
370 return 2.0f * m_width;
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);
536 separable<Field_T, FilterOp_T, FilterOp_T::isAnalytic>(src, tgt, xRes, filterOp, 0);
538 separable<Field_T, FilterOp_T, FilterOp_T::isAnalytic>(tgt, tmp, yRes, filterOp, 1);
540 separable<Field_T, FilterOp_T, FilterOp_T::isAnalytic>(tmp, tgt, zRes, filterOp, 2);
544 tgt.attribute = src.attribute;
545 tgt.setMapping(src.mapping());
546 tgt.copyMetadata(src);
559 template <
typename Field_T,
typename FilterOp_T>
560 bool resample(
const Field_T &src, Field_T &tgt,
const V3i &newRes,
561 const FilterOp_T &filterOp)
572 #endif // Include guard MinFilter(const float width)
#define FIELD3D_NAMESPACE_HEADER_CLOSE
boost::shared_ptr< const MaxFilter > CPtr
static void op(Value_T &accumValue, const Value_T value)
Contains the DenseField class.
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
virtual float support() const
Radial width of the filter (half of diameter)
static void op(Value_T &, const Value_T)
boost::shared_ptr< const BoxFilter > CPtr
virtual float support() const
Radial width of the filter (half of diameter)
void separable(const Field_T &src, Field_T &tgt, const V3i &newRes, const FilterOp_T &filterOp, const size_t dim)
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
boost::shared_ptr< GaussianFilter > Ptr
virtual float support() const =0
Radial width of the filter (half of diameter)
GaussianFilter(const float alpha=2.0, const float width=2.0)
MaxFilter(const float width)
static void op(Value_T &accumValue, const Value_T value)
boost::shared_ptr< TriangleFilter > Ptr
boost::shared_ptr< const GaussianFilter > CPtr
boost::shared_ptr< const MitchellFilter > CPtr
TriangleFilter(const float width)
boost::shared_ptr< Filter > Ptr
std::pair< int, int > srcSupportBBox(const float &tgtP, const float support, const bool doUpres, const float &srcSize, const float &tgtSize)
float getDist(const bool doUpres, const float &srcP, const float &tgtP, const float &srcSize, const float &tgtSize)
T max(const T a, const T2 b)
Max operation on mixed types.
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
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...
virtual float eval(const float t) const =0
Evaluates the filter at coordinate 't'.
virtual float eval(const float t) const
Evaluates the filter at coordinate 't'.
MitchellFilter(const float width=1.0, const float B=1.0/3.0, const float C=1.0/3.0)
boost::shared_ptr< const Filter > CPtr
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
boost::shared_ptr< MinFilter > Ptr
static int filter(std::string &name, const char *suffix)
boost::shared_ptr< const MinFilter > CPtr
static void op(Imath::Vec3< T > &accumValue, const Imath::Vec3< T > value)
static void op(Value_T &accumValue, const Value_T value)
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 ...
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)
boost::shared_ptr< MaxFilter > Ptr
BoxFilter(const float width)
boost::shared_ptr< MitchellFilter > Ptr
virtual float support() const
Radial width of the filter (half of diameter)
virtual float eval(const float x) const
Evaluates the filter at coordinate 't'.
virtual float initialValue() const
Initial value (zero by default, but need to be different for min/max)
Contains the SparseField class.
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)
static void op(Value_T &accumValue, const Value_T value)
static void op(Imath::Vec3< T > &accumValue, const Imath::Vec3< T > value)
T min(const T a, const T2 b)
Min operation on mixed types.
boost::shared_ptr< const TriangleFilter > CPtr
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< BoxFilter > Ptr
double discToCont(int discCoord)
Goes from discrete coordinates to continuous coordinates See Graphics Gems - What is a pixel...