37 #ifndef OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
47 #include <type_traits>
65 template<
typename PointDataGridT,
typename SourceGridT,
66 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
68 const SourceGridT& sourceGrid,
69 const Name& targetAttribute =
"",
70 const FilterT& filter = NullFilter(),
71 InterrupterT*
const interrupter =
nullptr);
83 template<
typename PointDataGridT,
typename SourceGridT,
84 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
85 inline void boxSample( PointDataGridT& points,
86 const SourceGridT& sourceGrid,
87 const Name& targetAttribute =
"",
88 const FilterT& filter = NullFilter(),
89 InterrupterT*
const interrupter =
nullptr);
101 template<
typename PointDataGridT,
typename SourceGridT,
102 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
104 const SourceGridT& sourceGrid,
105 const Name& targetAttribute =
"",
106 const FilterT& filter = NullFilter(),
107 InterrupterT*
const interrupter =
nullptr);
116 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
117 inline ValueT sample(
const AccessorT& accessor,
const Vec3d& position)
const;
139 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT =
DummySampleType,
143 PointDataGridT& points,
144 const SourceGridT& sourceGrid,
145 const Name& targetAttribute,
148 InterrupterT*
const interrupter =
nullptr,
149 const bool threaded =
true);
155 namespace point_sample_internal {
158 template<
typename FromType,
typename ToType>
159 struct CompatibleTypes {
enum { value = std::is_constructible<ToType, FromType>::value }; };
163 T, T> {
enum { value =
true }; };
165 T, math::
Vec2<T>> {
enum { value =
true }; };
167 T, math::
Vec3<T>> {
enum { value =
true }; };
169 T, math::
Vec4<T>> {
enum { value =
true }; };
188 static const bool Staggered =
false;
190 template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
191 static const bool Staggered = T1;
196 template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
199 static inline void sample(ValueT&,
const AccessorT&,
const Vec3d&)
201 std::ostringstream ostr;
202 ostr <<
"Cannot sample a " << typeNameAsString<typename AccessorT::ValueType>()
203 <<
" grid on to a " << typeNameAsString<ValueT>() <<
" attribute";
208 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
211 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
213 value = ValueT(
math::Round(SamplerT::sample(accessor, position)));
217 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
220 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
222 value = ValueT(SamplerT::sample(accessor, position));
227 template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
232 PointDataGridT& points,
233 const SamplerT& sampler,
234 const FilterT& filter,
235 InterrupterT*
const interrupter,
241 , mInterrupter(interrupter)
242 , mThreaded(threaded) { }
246 struct AlignedTransform
248 inline Vec3d transform(
const Vec3d& position)
const {
return position; }
252 struct NonAlignedTransform
256 , mTarget(target) { }
258 inline Vec3d transform(
const Vec3d& position)
const
260 return mSource.worldToIndex(mTarget.indexToWorld(position));
264 const math::Transform& mSource;
265 const math::Transform& mTarget;
269 template <
typename ValueT,
typename SourceGr
idT,
typename Gr
idSamplerT>
270 struct SamplerWrapper
272 using ValueType = ValueT;
273 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
275 SamplerWrapper(
const SourceGridT& sourceGrid,
const SamplerT& sampler)
276 : mAccessor(sourceGrid.getConstAccessor())
277 , mSampler(sampler) { }
281 SamplerWrapper(
const SamplerWrapper& other)
282 : mAccessor(other.mAccessor.tree())
283 , mSampler(other.mSampler) { }
285 inline ValueT sample(
const Vec3d& position)
const {
286 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
287 mAccessor, position);
291 SourceAccessorT mAccessor;
292 const SamplerT& mSampler;
295 template <
typename SamplerWrapperT,
typename TransformerT>
296 inline void doSample(
const SamplerWrapperT& sampleWrapper,
const Index targetIndex,
297 const TransformerT& transformer)
299 using PointDataTreeT =
typename PointDataGridT::TreeType;
300 using LeafT =
typename PointDataTreeT::LeafNodeType;
301 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
303 const auto& filter(mFilter);
304 const auto& interrupter(mInterrupter);
306 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &interrupter](
307 LeafT& leaf,
size_t )
309 using TargetHandleT = AttributeWriteHandle<typename SamplerWrapperT::ValueType>;
312 tbb::task::self().cancel_group_execution();
316 SamplerWrapperT newSampleWrapper(sampleWrapper);
317 auto positionHandle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray(
"P"));
318 auto targetHandle = TargetHandleT::create(leaf.attributeArray(targetIndex));
319 for (
auto iter = leaf.beginIndexOn(filter); iter; ++iter) {
320 const Vec3d position = transformer.transform(
321 positionHandle->get(*iter) + iter.getCoord().asVec3d());
322 targetHandle->set(*iter, newSampleWrapper.sample(position));
326 LeafManagerT leafManager(mPoints.tree());
328 if (mInterrupter) mInterrupter->start();
330 leafManager.foreach(sampleLambda, mThreaded);
332 if (mInterrupter) mInterrupter->end();
335 template <
typename SourceGr
idT,
typename SamplerWrapperT>
336 inline void resolveTransform(
const SourceGridT& sourceGrid,
const SamplerWrapperT& sampleWrapper,
337 const Index targetIndex)
339 const auto& sourceTransform = sourceGrid.constTransform();
340 const auto& pointsTransform = mPoints.constTransform();
342 if (sourceTransform == pointsTransform) {
343 AlignedTransform transformer;
344 doSample(sampleWrapper, targetIndex, transformer);
346 NonAlignedTransform transformer(sourceTransform, pointsTransform);
347 doSample(sampleWrapper, targetIndex, transformer);
351 template <
typename SourceGr
idT,
typename TargetValueT,
size_t Order>
352 inline void resolveStaggered(
const SourceGridT& sourceGrid,
const Index targetIndex)
354 using SamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, false>>;
355 using StaggeredSamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, true>>;
357 using SourceValueType =
typename SourceGridT::ValueType;
358 if (VecTraits<SourceValueType>::Size == 3 && sourceGrid.getGridClass() ==
GRID_STAGGERED) {
359 StaggeredSamplerWrapperT sampleWrapper(sourceGrid, mSampler);
360 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
362 SamplerWrapperT sampleWrapper(sourceGrid, mSampler);
363 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
368 template <
typename SourceGr
idT,
typename TargetValueT =
typename SourceGr
idT::ValueType>
369 inline void sample(
const SourceGridT& sourceGrid,
Index targetIndex)
372 resolveStaggered<SourceGridT, TargetValueT, 0>(sourceGrid, targetIndex);
373 }
else if (mOrder == 1) {
374 resolveStaggered<SourceGridT, TargetValueT, 1>(sourceGrid, targetIndex);
375 }
else if (mOrder == 2) {
376 resolveStaggered<SourceGridT, TargetValueT, 2>(sourceGrid, targetIndex);
382 PointDataGridT& mPoints;
383 const SamplerT& mSampler;
384 const FilterT& mFilter;
385 InterrupterT*
const mInterrupter;
386 const bool mThreaded;
390 template <
typename Po
intDataGr
idT,
typename ValueT>
393 static void append(PointDataGridT& points,
const Name& attribute)
395 appendAttribute<ValueT>(points.tree(), attribute);
399 template <
typename Po
intDataGr
idT>
411 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
412 ValueT SampleWithRounding::sample(
const AccessorT& accessor,
const Vec3d& position)
const
414 using namespace point_sample_internal;
415 using SourceValueT =
typename AccessorT::ValueType;
416 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
417 static const bool compatible = CompatibleTypes<SourceValueT, ValueT>::value &&
419 static const bool round = std::is_floating_point<SourceValueT>::value &&
420 std::is_integral<ValueT>::value;
422 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
423 value, accessor, position);
431 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT,
432 typename SamplerT,
typename FilterT,
typename InterrupterT>
434 PointDataGridT& points,
435 const SourceGridT& sourceGrid,
436 const Name& targetAttribute,
437 const FilterT& filter,
438 const SamplerT& sampler,
439 InterrupterT*
const interrupter,
446 Name attribute(targetAttribute);
447 if (targetAttribute.empty()) {
448 attribute = sourceGrid.getName();
452 if (attribute ==
"P") {
456 auto leaf = points.tree().cbeginLeaf();
459 PointDataSampler<PointDataGridT, SamplerT, FilterT, InterrupterT> pointDataSampler(
460 order, points, sampler, filter, interrupter, threaded);
462 const auto& descriptor = leaf->attributeSet().descriptor();
463 size_t targetIndex = descriptor.find(attribute);
464 const bool attributeExists = targetIndex != AttributeSet::INVALID_POS;
466 if (std::is_same<TargetValueT, DummySampleType>::value) {
467 if (!attributeExists) {
469 appendAttribute<typename SourceGridT::ValueType>(points.tree(), attribute);
470 targetIndex = leaf->attributeSet().descriptor().find(attribute);
471 assert(targetIndex != AttributeSet::INVALID_POS);
474 pointDataSampler.template sample<SourceGridT>(sourceGrid,
Index(targetIndex));
476 auto targetIdx =
static_cast<Index>(targetIndex);
478 const Name& targetType = descriptor.valueType(targetIndex);
480 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
482 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
484 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
486 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
488 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
490 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
492 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
494 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
496 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
498 pointDataSampler.template sample<SourceGridT, bool>(sourceGrid, targetIdx);
500 std::ostringstream ostr;
501 ostr <<
"Cannot sample attribute of type - " << targetType;
506 if (!attributeExists) {
509 AppendAttributeOp<PointDataGridT, TargetValueT>::append(points, attribute);
510 targetIndex = leaf->attributeSet().descriptor().find(attribute);
511 assert(targetIndex != AttributeSet::INVALID_POS);
514 const Name targetType = typeNameAsString<TargetValueT>();
515 const Name attributeType = descriptor.valueType(targetIndex);
516 if (targetType != attributeType) {
517 std::ostringstream ostr;
518 ostr <<
"Requested attribute type " << targetType <<
" for sampling "
519 <<
" does not match existing attribute type " << attributeType;
525 pointDataSampler.template sample<SourceGridT, TargetValueT>(
526 sourceGrid,
static_cast<Index>(targetIndex));
530 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
532 const SourceGridT& sourceGrid,
533 const Name& targetAttribute,
534 const FilterT& filter,
535 InterrupterT*
const interrupter)
538 sampleGrid(0, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
541 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
543 const SourceGridT& sourceGrid,
544 const Name& targetAttribute,
545 const FilterT& filter,
546 InterrupterT*
const interrupter)
549 sampleGrid(1, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
552 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
554 const SourceGridT& sourceGrid,
555 const Name& targetAttribute,
556 const FilterT& filter,
557 InterrupterT*
const interrupter)
560 sampleGrid(2, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
571 #endif // OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED