40 #ifndef OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
41 #define OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED
54 template<
typename GridT,
55 typename InterruptT = util::NullInterrupter>
59 typedef boost::shared_ptr<LevelSetFilter>
Ptr;
63 typedef typename TreeType::LeafNodeType
LeafType;
71 :
BaseType(grid, interrupt), mTask(0)
76 :
BaseType(other), mTask(other.mTask)
84 if (mTask) mTask(const_cast<LevelSetFilter*>(
this), r);
98 void gaussian(
int width = 1);
101 void offset(ValueType offset);
106 void median(
int width = 1);
111 void mean(
int width = 1);
114 typedef typename boost::function<void (LevelSetFilter*, const RangeType&)> FuncType;
121 const int n = BaseType::getGrainSize();
123 tbb::parallel_for(BaseType::mLeafs->getRange(n), *
this);
125 (*this)(BaseType::mLeafs->getRange());
127 if (swap) BaseType::mLeafs->swapLeafBuffer(1, n==0);
131 void doBoxX(
const RangeType&,
Int32);
132 void doBoxY(
const RangeType&,
Int32);
133 void doBoxZ(
const RangeType&,
Int32);
134 void doMedian(
const RangeType&,
int);
135 void doMeanCurvature(
const RangeType&);
136 void doLaplacian(
const RangeType&);
137 void doOffset(
const RangeType&, ValueType);
144 template<
typename Gr
idT,
typename InterruptT>
148 BaseType::startInterrupter(
"Median-value flow of level set");
150 BaseType::mLeafs->rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
152 mTask = boost::bind(&LevelSetFilter::doMedian, _1, _2,
std::max(1, width));
157 BaseType::endInterrupter();
161 template<
typename Gr
idT,
typename InterruptT>
165 BaseType::startInterrupter(
"Mean-value flow of level set");
169 BaseType::mLeafs->rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
171 mTask = boost::bind(&LevelSetFilter::doBoxX, _1, _2, width);
174 mTask = boost::bind(&LevelSetFilter::doBoxY, _1, _2, width);
177 mTask = boost::bind(&LevelSetFilter::doBoxZ, _1, _2, width);
182 BaseType::endInterrupter();
185 template<
typename Gr
idT,
typename InterruptT>
189 BaseType::startInterrupter(
"Gaussian flow of level set");
193 BaseType::mLeafs->rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
195 for (
int n=0; n<4; ++n) {
197 mTask = boost::bind(&LevelSetFilter::doBoxX, _1, _2, width);
200 mTask = boost::bind(&LevelSetFilter::doBoxY, _1, _2, width);
203 mTask = boost::bind(&LevelSetFilter::doBoxZ, _1, _2, width);
209 BaseType::endInterrupter();
214 template<
typename Gr
idT,
typename InterruptT>
218 BaseType::startInterrupter(
"Mean-curvature flow of level set");
220 BaseType::mLeafs->rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
222 mTask = boost::bind(&LevelSetFilter::doMeanCurvature, _1, _2);
227 BaseType::endInterrupter();
230 template<
typename Gr
idT,
typename InterruptT>
234 BaseType::startInterrupter(
"Laplacian flow of level set");
236 BaseType::mLeafs->rebuildAuxBuffers(1, BaseType::getGrainSize()==0);
238 mTask = boost::bind(&LevelSetFilter::doLaplacian, _1, _2);
243 BaseType::endInterrupter();
247 template<
typename Gr
idT,
typename InterruptT>
251 BaseType::startInterrupter(
"Offsetting level set");
253 BaseType::mLeafs->removeAuxBuffers();
257 while (offset-dist >
ValueType(0.001)*CFL && BaseType::checkInterrupter()) {
261 mTask = boost::bind(&LevelSetFilter::doOffset, _1, _2, copysign(delta,value));
267 BaseType::endInterrupter();
274 template<
typename Gr
idT,
typename InterruptT>
278 typedef typename LeafType::ValueOnCIter VoxelIterT;
279 BaseType::checkInterrupter();
281 const ValueType dx = BaseType::voxelSize(),dt =
math::Pow2(dx) / ValueType(3.0);
283 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
284 BufferType& buffer = BaseType::mLeafs->getBuffer(n,1);
285 for (VoxelIterT iter = BaseType::mLeafs->leaf(n).cbeginValueOn(); iter; ++iter) {
286 stencil.moveTo(iter);
287 buffer.setValue(iter.pos(), stencil.getValue() + dt * stencil.meanCurvatureNormGrad());
299 template<
typename Gr
idT,
typename InterruptT>
301 LevelSetFilter<GridT, InterruptT>::doLaplacian(
const RangeType& range)
303 typedef typename LeafType::ValueOnCIter VoxelIterT;
304 BaseType::checkInterrupter();
306 const ValueType dx = BaseType::voxelSize(), dt =
math::Pow2(dx) / ValueType(6.0);
307 math::GradStencil<GridType> stencil(BaseType::mGrid, dx);
308 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
309 BufferType& buffer = BaseType::mLeafs->getBuffer(n,1);
310 for (VoxelIterT iter = BaseType::mLeafs->leaf(n).cbeginValueOn(); iter; ++iter) {
311 stencil.moveTo(iter);
312 buffer.setValue(iter.pos(), stencil.getValue() + dt * stencil.laplacian());
318 template<
typename Gr
idT,
typename InterruptT>
320 LevelSetFilter<GridT, InterruptT>::doOffset(
const RangeType& range, ValueType value)
322 BaseType::checkInterrupter();
323 for (
size_t n=range.begin(), e=range.end(); n != e; ++n)
324 BaseType::mLeafs->leaf(n).addValue(value);
328 template<
typename Gr
idT,
typename InterruptT>
330 LevelSetFilter<GridT, InterruptT>::doMedian(
const RangeType& range,
int width)
332 typedef typename LeafType::ValueOnCIter VoxelIterT;
333 BaseType::checkInterrupter();
334 typename math::DenseStencil<GridType> stencil(BaseType::mGrid, width);
335 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
336 BufferType& buffer = BaseType::mLeafs->getBuffer(n,1);
337 for (VoxelIterT iter=BaseType::mLeafs->leaf(n).cbeginValueOn(); iter; ++iter) {
338 stencil.moveTo(iter);
339 buffer.setValue(iter.pos(), stencil.median());
345 template<
typename Gr
idT,
typename InterruptT>
347 LevelSetFilter<GridT, InterruptT>::doBoxX(
const RangeType& range,
Int32 w)
349 this->checkInterrupter();
350 const ValueType frac = ValueType(1)/ValueType(2*w+1);
351 typename GridT::ConstAccessor acc = BaseType::mGrid.getConstAccessor();
352 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
353 const LeafType& leaf = BaseType::mLeafs->leaf(n);
354 BufferType& buffer = BaseType::mLeafs->getBuffer(n, 1);
355 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
356 ValueType sum = zeroVal<ValueType>();
358 for (
Int32 x = xyz.x()-w, xLast = xyz.x()+w; x <= xLast; ++x) {
359 sum += acc.getValue(xyz.setX(x));
361 buffer.setValue(iter.pos(), sum*frac);
367 template<
typename Gr
idT,
typename InterruptT>
369 LevelSetFilter<GridT, InterruptT>::doBoxY(
const RangeType& range,
Int32 w)
371 this->checkInterrupter();
372 const ValueType frac = ValueType(1)/ValueType(2*w+1);
373 typename GridT::ConstAccessor acc = BaseType::mGrid.getConstAccessor();
374 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
375 const LeafType& leaf = BaseType::mLeafs->leaf(n);
376 BufferType& buffer = BaseType::mLeafs->getBuffer(n, 1);
377 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
378 ValueType sum = zeroVal<ValueType>();
380 for (
Int32 y = xyz.y()-w, yLast = xyz.y()+w; y <= yLast; ++y) {
381 sum += acc.getValue(xyz.setY(y));
383 buffer.setValue(iter.pos(), sum*frac);
389 template<
typename Gr
idT,
typename InterruptT>
391 LevelSetFilter<GridT, InterruptT>::doBoxZ(
const RangeType& range,
Int32 w)
393 this->checkInterrupter();
394 const ValueType frac = ValueType(1)/ValueType(2*w+1);
395 typename GridT::ConstAccessor acc = BaseType::mGrid.getConstAccessor();
396 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
397 const LeafType& leaf = BaseType::mLeafs->leaf(n);
398 BufferType& buffer = BaseType::mLeafs->getBuffer(n, 1);
399 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
400 ValueType sum = zeroVal<ValueType>();
402 for (
Int32 z = xyz.z()-w, zLast = xyz.z()+w; z <= zLast; ++z) {
403 sum += acc.getValue(xyz.setZ(z));
405 buffer.setValue(iter.pos(), sum*frac);
414 #endif // OPENVDB_TOOLS_LEVELSETFILTER_HAS_BEEN_INCLUDED