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(),
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(),
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(),
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,
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 bool Staggered =
false;
163 template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
164 static const bool Staggered = T1;
169 template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
172 static inline void sample(ValueT&,
const AccessorT&,
const Vec3d&)
174 std::ostringstream ostr;
175 ostr <<
"Cannot sample a " << typeNameAsString<typename AccessorT::ValueType>()
176 <<
" grid on to a " << typeNameAsString<ValueT>() <<
" attribute";
181 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
184 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
186 value = ValueT(
math::Round(SamplerT::sample(accessor, position)));
190 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
193 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
195 value = ValueT(SamplerT::sample(accessor, position));
200 template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
205 PointDataGridT& points,
206 const SamplerT& sampler,
207 const FilterT& filter,
215 , mThreaded(threaded) { }
219 struct AlignedTransform
221 inline Vec3d transform(
const Vec3d& position)
const {
return position; }
225 struct NonAlignedTransform
229 , mTarget(target) { }
231 inline Vec3d transform(
const Vec3d& position)
const
233 return mSource.worldToIndex(mTarget.indexToWorld(position));
237 const math::Transform& mSource;
238 const math::Transform& mTarget;
242 template <
typename ValueT,
typename SourceGr
idT,
typename Gr
idSamplerT>
243 struct SamplerWrapper
245 using ValueType = ValueT;
246 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
248 SamplerWrapper(
const SourceGridT& sourceGrid,
const SamplerT& sampler)
249 : mAccessor(sourceGrid.getConstAccessor())
250 , mSampler(sampler) { }
254 SamplerWrapper(
const SamplerWrapper& other)
255 : mAccessor(other.mAccessor.tree())
256 , mSampler(other.mSampler) { }
258 inline ValueT sample(
const Vec3d& position)
const {
259 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
260 mAccessor, position);
264 SourceAccessorT mAccessor;
265 const SamplerT& mSampler;
268 template <
typename SamplerWrapperT,
typename TransformerT>
269 inline void doSample(
const SamplerWrapperT& sampleWrapper,
const Index targetIndex,
270 const TransformerT& transformer)
272 using PointDataTreeT =
typename PointDataGridT::TreeType;
273 using LeafT =
typename PointDataTreeT::LeafNodeType;
274 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
276 const auto& filter(mFilter);
279 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &
interrupter](
280 LeafT& leaf,
size_t )
282 using TargetHandleT = AttributeWriteHandle<typename SamplerWrapperT::ValueType>;
285 tbb::task::self().cancel_group_execution();
289 SamplerWrapperT newSampleWrapper(sampleWrapper);
290 auto positionHandle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray(
"P"));
291 auto targetHandle = TargetHandleT::create(leaf.attributeArray(targetIndex));
292 for (
auto iter = leaf.beginIndexOn(filter); iter; ++iter) {
293 const Vec3d position = transformer.transform(
294 positionHandle->get(*iter) + iter.getCoord().asVec3d());
295 targetHandle->set(*iter, newSampleWrapper.sample(position));
299 LeafManagerT leafManager(mPoints.tree());
301 if (mInterrupter) mInterrupter->start();
303 leafManager.foreach(sampleLambda, mThreaded);
305 if (mInterrupter) mInterrupter->end();
308 template <
typename SourceGr
idT,
typename SamplerWrapperT>
309 inline void resolveTransform(
const SourceGridT& sourceGrid,
const SamplerWrapperT& sampleWrapper,
310 const Index targetIndex)
312 const auto& sourceTransform = sourceGrid.constTransform();
313 const auto& pointsTransform = mPoints.constTransform();
315 if (sourceTransform == pointsTransform) {
316 AlignedTransform transformer;
317 doSample(sampleWrapper, targetIndex, transformer);
319 NonAlignedTransform transformer(sourceTransform, pointsTransform);
320 doSample(sampleWrapper, targetIndex, transformer);
324 template <
typename SourceGr
idT,
typename TargetValueT,
size_t Order>
325 inline void resolveStaggered(
const SourceGridT& sourceGrid,
const Index targetIndex)
327 using SamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, false>>;
328 using StaggeredSamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, true>>;
330 using SourceValueType =
typename SourceGridT::ValueType;
332 StaggeredSamplerWrapperT sampleWrapper(sourceGrid, mSampler);
333 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
335 SamplerWrapperT sampleWrapper(sourceGrid, mSampler);
336 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
341 template <
typename SourceGr
idT,
typename TargetValueT =
typename SourceGr
idT::ValueType>
342 inline void sample(
const SourceGridT& sourceGrid,
Index targetIndex)
345 resolveStaggered<SourceGridT, TargetValueT, 0>(sourceGrid, targetIndex);
346 }
else if (mOrder == 1) {
347 resolveStaggered<SourceGridT, TargetValueT, 1>(sourceGrid, targetIndex);
348 }
else if (mOrder == 2) {
349 resolveStaggered<SourceGridT, TargetValueT, 2>(sourceGrid, targetIndex);
355 PointDataGridT& mPoints;
356 const SamplerT& mSampler;
357 const FilterT& mFilter;
358 InterrupterT*
const mInterrupter;
359 const bool mThreaded;
363 template <
typename Po
intDataGr
idT,
typename ValueT>
366 static void append(PointDataGridT& points,
const Name& attribute)
368 appendAttribute<ValueT>(points.tree(), attribute);
372 template <
typename Po
intDataGr
idT>
384 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
385 ValueT SampleWithRounding::sample(
const AccessorT& accessor,
const Vec3d& position)
const
387 using namespace point_sample_internal;
388 using SourceValueT =
typename AccessorT::ValueType;
389 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
390 static const bool compatible = CompatibleTypes<SourceValueT, ValueT>::value &&
392 static const bool round = std::is_floating_point<SourceValueT>::value &&
393 std::is_integral<ValueT>::value;
395 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
396 value, accessor, position);
404 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT,
405 typename SamplerT,
typename FilterT,
typename InterrupterT>
407 PointDataGridT& points,
408 const SourceGridT& sourceGrid,
409 const Name& targetAttribute,
410 const FilterT& filter,
411 const SamplerT& sampler,
419 Name attribute(targetAttribute);
420 if (targetAttribute.empty()) {
421 attribute = sourceGrid.getName();
425 if (attribute ==
"P") {
429 auto leaf = points.tree().cbeginLeaf();
432 PointDataSampler<PointDataGridT, SamplerT, FilterT, InterrupterT> pointDataSampler(
433 order, points, sampler, filter,
interrupter, threaded);
435 const auto& descriptor = leaf->attributeSet().descriptor();
436 size_t targetIndex = descriptor.find(attribute);
437 const bool attributeExists = targetIndex != AttributeSet::INVALID_POS;
439 if (std::is_same<TargetValueT, DummySampleType>::value) {
440 if (!attributeExists) {
442 appendAttribute<typename SourceGridT::ValueType>(points.tree(), attribute);
443 targetIndex = leaf->attributeSet().descriptor().find(attribute);
444 assert(targetIndex != AttributeSet::INVALID_POS);
447 pointDataSampler.template sample<SourceGridT>(sourceGrid,
Index(targetIndex));
449 auto targetIdx =
static_cast<Index>(targetIndex);
451 const Name& targetType = descriptor.valueType(targetIndex);
453 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
455 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
457 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
459 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
461 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
463 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
465 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
467 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
469 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
471 pointDataSampler.template sample<SourceGridT, bool>(sourceGrid, targetIdx);
473 std::ostringstream ostr;
474 ostr <<
"Cannot sample attribute of type - " << targetType;
479 if (!attributeExists) {
482 AppendAttributeOp<PointDataGridT, TargetValueT>::append(points, attribute);
483 targetIndex = leaf->attributeSet().descriptor().find(attribute);
484 assert(targetIndex != AttributeSet::INVALID_POS);
487 const Name targetType = typeNameAsString<TargetValueT>();
488 const Name attributeType = descriptor.valueType(targetIndex);
489 if (targetType != attributeType) {
490 std::ostringstream ostr;
491 ostr <<
"Requested attribute type " << targetType <<
" for sampling "
492 <<
" does not match existing attribute type " << attributeType;
498 pointDataSampler.template sample<SourceGridT, TargetValueT>(
499 sourceGrid,
static_cast<Index>(targetIndex));
503 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
505 const SourceGridT& sourceGrid,
506 const Name& targetAttribute,
507 const FilterT& filter,
514 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
516 const SourceGridT& sourceGrid,
517 const Name& targetAttribute,
518 const FilterT& filter,
525 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
527 const SourceGridT& sourceGrid,
528 const Name& targetAttribute,
529 const FilterT& filter,
544 #endif // OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED