10 #ifndef OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
20 #include <type_traits>
38 template<
typename PointDataGridT,
typename SourceGridT,
39 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
41 const SourceGridT& sourceGrid,
42 const Name& targetAttribute =
"",
43 const FilterT& filter = NullFilter(),
44 InterrupterT*
const interrupter =
nullptr);
56 template<
typename PointDataGridT,
typename SourceGridT,
57 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
58 inline void boxSample( PointDataGridT& points,
59 const SourceGridT& sourceGrid,
60 const Name& targetAttribute =
"",
61 const FilterT& filter = NullFilter(),
62 InterrupterT*
const interrupter =
nullptr);
74 template<
typename PointDataGridT,
typename SourceGridT,
75 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
77 const SourceGridT& sourceGrid,
78 const Name& targetAttribute =
"",
79 const FilterT& filter = NullFilter(),
80 InterrupterT*
const interrupter =
nullptr);
89 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
90 inline ValueT sample(
const AccessorT& accessor,
const Vec3d& position)
const;
112 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT =
DummySampleType,
116 PointDataGridT& points,
117 const SourceGridT& sourceGrid,
118 const Name& targetAttribute,
121 InterrupterT*
const interrupter =
nullptr,
122 const bool threaded =
true);
128 namespace point_sample_internal {
131 template<
typename FromType,
typename ToType>
132 struct CompatibleTypes {
enum { value = std::is_constructible<ToType, FromType>::value }; };
136 T, T> {
enum { value =
true }; };
138 T, math::
Vec2<T>> {
enum { value =
true }; };
140 T, math::
Vec3<T>> {
enum { value =
true }; };
142 T, math::
Vec4<T>> {
enum { value =
true }; };
161 static const size_t Order = 0;
162 static const bool Staggered =
false;
164 template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
165 static const size_t Order = T0;
166 static const bool Staggered = T1;
171 template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
174 static inline void sample(ValueT&,
const AccessorT&,
const Vec3d&)
176 std::ostringstream ostr;
177 ostr <<
"Cannot sample a " << typeNameAsString<typename AccessorT::ValueType>()
178 <<
" grid on to a " << typeNameAsString<ValueT>() <<
" attribute";
183 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
186 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
188 value = ValueT(
math::Round(SamplerT::sample(accessor, position)));
192 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
195 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
197 value = ValueT(SamplerT::sample(accessor, position));
202 template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
207 PointDataGridT& points,
208 const SamplerT& sampler,
209 const FilterT& filter,
210 InterrupterT*
const interrupter,
216 , mInterrupter(interrupter)
217 , mThreaded(threaded) { }
221 struct AlignedTransform
223 inline Vec3d transform(
const Vec3d& position)
const {
return position; }
227 struct NonAlignedTransform
231 , mTarget(target) { }
233 inline Vec3d transform(
const Vec3d& position)
const
235 return mSource.worldToIndex(mTarget.indexToWorld(position));
239 const math::Transform& mSource;
240 const math::Transform& mTarget;
244 template <
typename ValueT,
typename SourceGr
idT,
typename Gr
idSamplerT>
245 struct SamplerWrapper
247 using ValueType = ValueT;
248 using SourceValueType =
typename SourceGridT::ValueType;
249 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
252 static const bool SourceIsBool = std::is_same<SourceValueType, bool>::value ||
253 std::is_same<SourceValueType, ValueMask>::value;
254 static const bool OrderIsZero = SamplerTraits<GridSamplerT>::Order == 0;
255 static const bool IsValid = !SourceIsBool || OrderIsZero;
257 SamplerWrapper(
const SourceGridT& sourceGrid,
const SamplerT& sampler)
258 : mAccessor(sourceGrid.getConstAccessor())
259 , mSampler(sampler) { }
263 SamplerWrapper(
const SamplerWrapper& other)
264 : mAccessor(other.mAccessor.tree())
265 , mSampler(other.mSampler) { }
267 template <
bool IsVal
idT = IsVal
id>
268 inline typename std::enable_if<IsValidT, ValueT>::type
269 sample(
const Vec3d& position)
const {
270 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
271 mAccessor, position);
274 template <
bool IsVal
idT = IsVal
id>
275 inline typename std::enable_if<!IsValidT, ValueT>::type
276 sample(
const Vec3d& )
const {
277 OPENVDB_THROW(RuntimeError,
"Cannot sample bool grid with BoxSampler or QuadraticSampler.");
281 SourceAccessorT mAccessor;
282 const SamplerT& mSampler;
285 template <
typename SamplerWrapperT,
typename TransformerT>
286 inline void doSample(
const SamplerWrapperT& sampleWrapper,
const Index targetIndex,
287 const TransformerT& transformer)
289 using PointDataTreeT =
typename PointDataGridT::TreeType;
290 using LeafT =
typename PointDataTreeT::LeafNodeType;
291 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
293 const auto& filter(mFilter);
294 const auto& interrupter(mInterrupter);
296 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &interrupter](
297 LeafT& leaf,
size_t )
299 using TargetHandleT = AttributeWriteHandle<typename SamplerWrapperT::ValueType>;
302 tbb::task::self().cancel_group_execution();
306 SamplerWrapperT newSampleWrapper(sampleWrapper);
307 auto positionHandle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray(
"P"));
308 auto targetHandle = TargetHandleT::create(leaf.attributeArray(targetIndex));
309 for (
auto iter = leaf.beginIndexOn(filter); iter; ++iter) {
310 const Vec3d position = transformer.transform(
311 positionHandle->get(*iter) + iter.getCoord().asVec3d());
312 targetHandle->set(*iter, newSampleWrapper.sample(position));
316 LeafManagerT leafManager(mPoints.tree());
318 if (mInterrupter) mInterrupter->start();
320 leafManager.foreach(sampleLambda, mThreaded);
322 if (mInterrupter) mInterrupter->end();
325 template <
typename SourceGr
idT,
typename SamplerWrapperT>
326 inline void resolveTransform(
const SourceGridT& sourceGrid,
const SamplerWrapperT& sampleWrapper,
327 const Index targetIndex)
329 const auto& sourceTransform = sourceGrid.constTransform();
330 const auto& pointsTransform = mPoints.constTransform();
332 if (sourceTransform == pointsTransform) {
333 AlignedTransform transformer;
334 doSample(sampleWrapper, targetIndex, transformer);
336 NonAlignedTransform transformer(sourceTransform, pointsTransform);
337 doSample(sampleWrapper, targetIndex, transformer);
341 template <
typename SourceGr
idT,
typename TargetValueT,
size_t Order>
342 inline void resolveStaggered(
const SourceGridT& sourceGrid,
const Index targetIndex)
344 using SamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, false>>;
345 using StaggeredSamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, true>>;
347 using SourceValueType =
typename SourceGridT::ValueType;
349 StaggeredSamplerWrapperT sampleWrapper(sourceGrid, mSampler);
350 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
352 SamplerWrapperT sampleWrapper(sourceGrid, mSampler);
353 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
358 template <
typename SourceGr
idT,
typename TargetValueT =
typename SourceGr
idT::ValueType>
359 inline void sample(
const SourceGridT& sourceGrid,
Index targetIndex)
361 using SourceValueType =
typename SourceGridT::ValueType;
362 static const bool SourceIsMask = std::is_same<SourceValueType, bool>::value ||
363 std::is_same<SourceValueType, ValueMask>::value;
365 if (SourceIsMask || mOrder == 0) {
366 resolveStaggered<SourceGridT, TargetValueT, 0>(sourceGrid, targetIndex);
367 }
else if (mOrder == 1) {
368 resolveStaggered<SourceGridT, TargetValueT, 1>(sourceGrid, targetIndex);
369 }
else if (mOrder == 2) {
370 resolveStaggered<SourceGridT, TargetValueT, 2>(sourceGrid, targetIndex);
376 PointDataGridT& mPoints;
377 const SamplerT& mSampler;
378 const FilterT& mFilter;
379 InterrupterT*
const mInterrupter;
380 const bool mThreaded;
384 template <
typename Po
intDataGr
idT,
typename ValueT>
387 static void append(PointDataGridT& points,
const Name& attribute)
389 appendAttribute<ValueT>(points.tree(), attribute);
393 template <
typename Po
intDataGr
idT>
405 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
406 ValueT SampleWithRounding::sample(
const AccessorT& accessor,
const Vec3d& position)
const
408 using namespace point_sample_internal;
409 using SourceValueT =
typename AccessorT::ValueType;
410 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
411 static const bool compatible = CompatibleTypes<SourceValueT, ValueT>::value &&
413 static const bool round = std::is_floating_point<SourceValueT>::value &&
414 std::is_integral<ValueT>::value;
416 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
417 value, accessor, position);
425 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT,
426 typename SamplerT,
typename FilterT,
typename InterrupterT>
428 PointDataGridT& points,
429 const SourceGridT& sourceGrid,
430 const Name& targetAttribute,
431 const FilterT& filter,
432 const SamplerT& sampler,
433 InterrupterT*
const interrupter,
440 Name attribute(targetAttribute);
441 if (targetAttribute.empty()) {
442 attribute = sourceGrid.getName();
446 if (attribute ==
"P") {
450 auto leaf = points.tree().cbeginLeaf();
453 PointDataSampler<PointDataGridT, SamplerT, FilterT, InterrupterT> pointDataSampler(
454 order, points, sampler, filter, interrupter, threaded);
456 const auto& descriptor = leaf->attributeSet().descriptor();
457 size_t targetIndex = descriptor.find(attribute);
458 const bool attributeExists = targetIndex != AttributeSet::INVALID_POS;
460 if (std::is_same<TargetValueT, DummySampleType>::value) {
461 if (!attributeExists) {
463 appendAttribute<typename SourceGridT::ValueType>(points.tree(), attribute);
464 targetIndex = leaf->attributeSet().descriptor().find(attribute);
465 assert(targetIndex != AttributeSet::INVALID_POS);
468 pointDataSampler.template sample<SourceGridT>(sourceGrid,
Index(targetIndex));
470 auto targetIdx =
static_cast<Index>(targetIndex);
472 const Name& targetType = descriptor.valueType(targetIndex);
474 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
476 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
478 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
480 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
482 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
484 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
486 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
488 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
490 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
492 pointDataSampler.template sample<SourceGridT, bool>(sourceGrid, targetIdx);
494 std::ostringstream ostr;
495 ostr <<
"Cannot sample attribute of type - " << targetType;
500 if (!attributeExists) {
503 AppendAttributeOp<PointDataGridT, TargetValueT>::append(points, attribute);
504 targetIndex = leaf->attributeSet().descriptor().find(attribute);
505 assert(targetIndex != AttributeSet::INVALID_POS);
508 const Name targetType = typeNameAsString<TargetValueT>();
509 const Name attributeType = descriptor.valueType(targetIndex);
510 if (targetType != attributeType) {
511 std::ostringstream ostr;
512 ostr <<
"Requested attribute type " << targetType <<
" for sampling "
513 <<
" does not match existing attribute type " << attributeType;
519 pointDataSampler.template sample<SourceGridT, TargetValueT>(
520 sourceGrid,
static_cast<Index>(targetIndex));
524 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
526 const SourceGridT& sourceGrid,
527 const Name& targetAttribute,
528 const FilterT& filter,
529 InterrupterT*
const interrupter)
532 sampleGrid(0, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
535 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
537 const SourceGridT& sourceGrid,
538 const Name& targetAttribute,
539 const FilterT& filter,
540 InterrupterT*
const interrupter)
543 sampleGrid(1, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
546 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
548 const SourceGridT& sourceGrid,
549 const Name& targetAttribute,
550 const FilterT& filter,
551 InterrupterT*
const interrupter)
554 sampleGrid(2, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
565 #endif // OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED