Commit 9b05847c authored by Étienne Folio's avatar Étienne Folio
Browse files

New fast front propagation.

	* sandbox/folio/distance_front_new.hh: New fast front propagation
	(not tested).

git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@3475 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent cf9b21ec
2009-03-04 Etienne FOLIO <folio@lrde.epita.fr>
New fast front propagation.
* sandbox/folio/distance_front_new.hh: New fast front propagation
(not tested).
2009-03-03 Guillaume Lazzara <lazzara@lrde.epita.fr>
 
Fix compilation issues.
// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef MLN_CANVAS_DISTANCE_FRONT_HH
# define MLN_CANVAS_DISTANCE_FRONT_HH
/// \file mln/canvas/distance_front.hh
///
/// Discrete distance canvas by front propagation.
# include <vector>
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/core/concept/weighted_window.hh>
# include <mln/data/fill.hh>
# include <mln/accu/max.hh>
//# include <mln/core/routine/duplicate.hh>
//# include <mln/core/site_set/p_queue_fast.hh>
//# include <queue>
//# include <mln/extension/adjust_fill.hh>
namespace mln
{
namespace canvas
{
/// Discrete front distance canvas.
template <typename I,
typename N, typename W, typename D,
typename F>
mln_ch_value(I, D)
distance_front(const Image<I>& input,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win, D max,
F& functor);
# ifndef MLN_INCLUDE_ONLY
// Tests.
namespace internal
{
template <typename I,
typename N, typename W, typename D,
typename F>
void
distance_front_tests(const Image<I>& input_,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win, D max,
F& functor)
{
const I& input = exact(input_);
const N& nbh = exact(nbh_);
mln_precondition(input.is_valid());
mln_precondition(nbh.is_valid());
(void) input;
(void) nbh;
(void) max;
(void) functor;
}
} // of namespace mln::canvas::internal
// Implementations.
namespace impl
{
namespace generic
{
template <typename I,
typename N, typename W, typename D,
typename F>
mln_ch_value(I, D)
distance_front(const Image<I>& input_,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win, D max,
F& functor)
{
trace::entering("canvas::impl::generic::distance_front");
const I& input = exact(input_);
const N& nbh = exact(nbh_);
const W& w_win = exact(w_win_);
mln_precondition(input.is_valid());
mln_precondition(w_win.is_valid());
typedef mln_site(I) P;
typedef std::vector<P> bucket_t;
// Distance map.
mln_ch_value(I, D) dmap;
initialize(dmap, input);
data::fill(dmap, max);
// Mod determination.
unsigned mod;
{
accu::max<unsigned> m;
for (unsigned i = 0; i < w_win.size(); ++i)
m.take(w_win.w(i));
mod = unsigned(m) + 1;
}
// Aux data.
std::vector<bucket_t> bucket(mod);
unsigned bucket_size = 0;
// Initialization.
{
functor.init(input); // <-- init
mln_piter(I) p(input.domain());
mln_niter(N) n(nbh, p);
for_all(p)
if (functor.inqueue_p_wrt_input_p(input(p))) // <-- inqueue_p_wrt_input_p
{
dmap(p) = 0;
for_all(n)
if (input.domain().has(n) &&
functor.inqueue_p_wrt_input_n(input(n))) // <-- inqueue_p_wrt_input_n
{
bucket[0].push_back(p);
++bucket_size;
break;
}
}
}
// Propagation.
{
P p;
mln_qiter(W) q(w_win, p);
for (unsigned d = 0; bucket_size != 0; ++d)
{
bucket_t& bucket_d = bucket[d % mod];
for (unsigned i = 0; i < bucket_d.size(); ++i)
{
p = bucket_d[i];
if (dmap(p) == max)
{
// Saturation so stop.
bucket_size = bucket_d.size(); // So at end bucket_size == 0.
break;
}
if (dmap(p) < d)
// p has already been processed, having a distance less than d.
continue;
for_all(q)
if (dmap.domain().has(q) && dmap(q) > d)
{
unsigned d_ = d + q.w();
if (d_ < dmap(q))
{
dmap(q) = d_;
functor.process(p, q); // <- process
bucket[d_ % mod].push_back(q);
++bucket_size;
}
}
}
bucket_size -= bucket_d.size();
bucket_d.clear();
}
trace::exiting("canvas::impl::generic::distance_front");
return dmap;
}
}
} // of namespace mln::canvas::impl::generic
// Fastest version.
template <typename I,
typename N, typename W, typename D,
typename F>
mln_ch_value(I, D)
distance_front_fastest(const Image<I>& input_,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
D max, F& functor)
{
trace::entering("canvas::impl::distance_front_fastest");
const I& input = exact(input_);
const N& nbh = exact(nbh_);
const W& w_win = exact(w_win_);
// mln_precondition(input.is_valid()); // ?x
// mln_precondition(w_win.is_valid()); // ?x
extension::adjust(input, w_win); // ?
// typedef mln_site(I) P;
typedef std::vector<unsigned> bucket_t;
// Distance map.
mln_ch_value(I, D) dmap;
initialize(dmap, input);
data::fill(dmap, max);
// Mod determination.
unsigned mod;
{
accu::max<unsigned> m;
for (unsigned i = 0; i < w_win.size(); ++i)
m.take(w_win.w(i));
mod = unsigned(m) + 1;
}
// Aux data.
std::vector<bucket_t> bucket(mod);
unsigned bucket_size = 0;
// Initialization.
{
functor.init_(input); // <-- init
// For the extension to be ignored: // ?
extension::fill(input, true); // ?
extension::fill(dmap, D(0)); // ?
mln_pixter(const I) p(input);
mln_nixter(const I, N) n(p, nbh);
for_all(p)
if (functor.inqueue_p_wrt_input_p_(input(p))) // <-- inqueue_p_wrt_input_p
{
dmap.element(p.offset()) = 0;
for_all(n)
if (functor.inqueue_p_wrt_input_n_(n.val())) // <-- inqueue_p_wrt_input_n
{
bucket[0].push_back(p.offset());
++bucket_size;
break;
}
}
}
// Propagation.
{
unsigned p;
mln_qiter(W) q(w_win, p); // ?x-
for (unsigned d = 0; bucket_size != 0; ++d)
{
bucket_t& bucket_d = bucket[d % mod];
for (unsigned i = 0; i < bucket_d.size(); ++i)
{
p = bucket_d[i];
if (dmap.element(p) == max)
{
// Saturation so stop.
bucket_size = bucket_d.size(); // So at end bucket_size == 0.
break;
}
if (dmap.element(p) < d)
// p has already been processed, having a distance less than d.
continue;
for_all(q)
{
if (dmap.domain().has(q) && dmap(q) > d)
{
unsigned d_ = d + q.w();
if (d_ < dmap(q))
{
dmap(q) = d_;
functor.process_(dmap.element(p), q); // <- process
bucket[d_ % mod].push_back(q);
++bucket_size;
}
}
}
bucket_size -= bucket_d.size();
bucket_d.clear();
}
trace::exiting("canvas::impl::distance_front_fastest");
return dmap;
}
}
} // of namespace mln::canvas::impl
// Dispatch.
namespace internal
{
template <typename I,
typename N, typename W, typename D,
typename F>
inline
mln_ch_value(I, D)
distance_front_dispatch(metal::false_,
const Image<I>& input,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
D max, F& functor)
{
return impl::generic::distance_front(input, nbh, max, w_win, functor);
}
template <typename I,
typename N, typename W, typename D,
typename F>
inline
mln_ch_value(I, D)
distance_front_dispatch(metal::true_,
const Image<I>& input,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
D max, F& functor)
{
return impl::distance_front_fastest(input, nbh, w_win, max, functor);
// return impl::generic::distance_front(input, nbh, w_win, max, functor);
}
template <typename I,
typename N, typename W, typename D,
typename F>
inline
mln_ch_value(I, D)
distance_front_dispatch(const Image<I>& input,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
D max, F& functor)
{
enum {
test = mlc_equal(mln_trait_image_speed(I),
trait::image::speed::fastest)::value
&&
mln_is_simple_neighborhood(N)::value
};
return distance_front_dispatch(metal::bool_<test>(),
input, nbh, w_win, max, functor);
}
} // of namespace mln::canvas::internal
// Facade.
template <typename I,
typename N, typename W, typename D,
typename F>
inline
mln_ch_value(I, D)
distance_front(const Image<I>& input,
const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
D max, F& functor)
{
trace::entering("canvas::distance_front");
internal::distance_front_tests(input, nbh, w_win, max, functor);
mln_ch_value(I,D) output;
output = internal::distance_front_dispatch(input, nbh, w_win, max, functor);
trace::exiting("canvas::distance_front");
return output;
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::canvas
} // end of namespace mln
#endif // ! MLN_CANVAS_DISTANCE_FRONT_HH
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment