26 #ifndef MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH
27 # define MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH
43 # include <mln/core/site_set/p_set.hh>
44 # include <mln/core/site_set/p_priority.hh>
45 # include <mln/core/site_set/p_queue_fast.hh>
47 # include <mln/util/ord.hh>
49 # include <mln/data/sort_psites.hh>
50 # include <mln/data/fill.hh>
65 mln_site(I) min (const Image<I> &ima_, p_set<mln_site(I)>& components)
67 const I& ima = exact(ima_);
69 if (components.nsites() == 0)
70 return mln_site(I)(-1, -1);
72 typename p_set<mln_site(I)>::fwd_piter it(components);
73 mln_site(I) min = components[0];
76 if (ima(it) < ima(min))
83 mln_site(I) max (p_set<mln_site(I)>& components)
85 if (components.nsites() == 0)
86 return mln_site(I)(-1, -1);
88 typename p_set<mln_site(I)>::fwd_piter it(components);
89 mln_site(I) max = components[0];
92 if (ima(it) > ima(max))
100 template <class I, class N>
105 typedef mln_site(I) site;
107 typedef N neighborhood_t;
116 typedef mln_site(I) site;
119 std::vector<site> children;
121 void addChildren(const node& n)
128 for (
unsigned i=0; i < n.children.size(); ++i)
129 children.push_back(n.children[i]);
132 void addChild(
const site p)
135 children.push_back(p);
141 mln_ch_value(I, site) Par_node;
142 mln_ch_value(I, site) Par_tree;
144 mln_ch_value(I,
int) Rnk_tree;
145 mln_ch_value(I,
int) Rnk_node;
146 mln_ch_value(I, site) subtreeRoot;
147 mln_ch_value(I, node) nodes;
152 void MakeSet_tree(site x);
153 void MakeSet_node(site x);
154 site Find_tree(site x);
155 site Find_node(site x);
156 void BuildComponentTree();
157 site MergeNode(site& node1, site& node2);
158 site Link_tree(site x, site y);
159 site Link_node(site x, site y);
160 node MakeNode(
int level);
163 mln_ch_value(I,
bool) isproc;
167 topo_wst(const Image<I>& i,
168 const Neighborhood<N>& n);
178 site min (p_set<site>& components);
179 site max (p_set<site>& components);
180 bool highest_fork (p_set<site>& components);
181 bool highest_fork (p_set<site>& components, site &r);
186 site lca (site a, site b);
192 std::map<site,
int, mln::util::ord<site> > pos;
198 void compute_ctree_size (site p);
199 void build_euler_tour_rec(site p,
int &position,
int d);
200 void build_euler_tour();
202 void removeOneSonNodes(site *p, mln_ch_value(I, site) &newPar_node);
213 # ifndef MLN_INCLUDE_ONLY
216 template <
class I,
class N>
217 topo_wst<I, N>::topo_wst(
const Image<I>& i,
218 const Neighborhood<N>& n)
219 : ima(exact(i)), nbh(exact(n))
230 template <
class I,
class N>
231 void topo_wst<I, N>::MakeSet_tree(site x)
237 template <
class I,
class N>
238 void topo_wst<I, N>::MakeSet_node(site x)
244 template <
class I,
class N>
245 typename topo_wst<I, N>::site topo_wst<I, N>::Find_tree(site x)
247 if (Par_tree(x) != x)
248 Par_tree(x) = Find_tree(Par_tree(x));
252 template <
class I,
class N>
253 typename topo_wst<I, N>::site topo_wst<I, N>::Find_node(site x)
255 if (Par_node(x) != x)
256 Par_node(x) = Find_node(Par_node(x));
260 template <
class I,
class N>
261 void topo_wst<I, N>::go()
263 BuildComponentTree();
270 template <
class I,
class N>
271 void topo_wst<I, N>::BuildComponentTree()
276 p_array<mln_site(I)> S;
281 for (
int ip = 0; ip < int(S.nsites()); ++ip)
289 nodes(p) = MakeNode(ima(p));
294 typename p_array<mln_site(I)>::fwd_piter ip(S);
297 site p = ip.to_site();
299 site curCanonicalElt = Find_tree(p);
300 site curNode = Find_node(subtreeRoot(curCanonicalElt));
303 mln_niter(N) q(nbh, ip);
305 if (ima.has(q) and isproc(q) and ima(q) <= ima(p))
307 site adjCanonicalElt = Find_tree(q);
308 site adjNode = Find_node(subtreeRoot(adjCanonicalElt));
309 if (curNode != adjNode)
311 if (nodes(curNode).level == nodes(adjNode).level)
312 curNode = MergeNode(adjNode, curNode);
315 nodes(curNode).addChild(adjNode);
316 nodes(curNode).area += nodes(adjNode).area;
317 nodes(curNode).highest += nodes(adjNode).highest;
321 curCanonicalElt = Link_tree(adjCanonicalElt, curCanonicalElt);
322 subtreeRoot(curCanonicalElt) = curNode;
333 mln_piter(I) r(Par_node.domain());
335 Par_node(r) = Find_node(r);
339 mln_fwd_piter(I) rp(Par_node.domain());;
342 Root = subtreeRoot(Find_tree(Find_node(rp)));
346 template <class I, class N>
347 typename topo_wst<I, N>::site topo_wst<I, N>::MergeNode(site& node1,
350 site tmpNode = Link_node(node1, node2);
352 if (tmpNode == node2)
354 nodes(node2).addChildren(nodes(node1));
359 nodes(node1).addChildren(nodes(node2));
362 nodes(tmpNode).area += nodes(tmpNode2).area;
363 nodes(tmpNode).highest += nodes(tmpNode2).highest;
367 template <
class I,
class N>
368 typename topo_wst<I, N>::site topo_wst<I, N>::Link_tree(site x, site y)
370 if (Rnk_tree(x) > Rnk_tree(y))
373 if (Rnk_tree(x) == Rnk_tree(y))
379 template <
class I,
class N>
380 typename topo_wst<I, N>::site topo_wst<I, N>::Link_node(site x, site y)
382 if (Rnk_node(x) > Rnk_node(y))
385 if (Rnk_node(x) == Rnk_node(y))
391 template <
class I,
class N>
392 typename topo_wst<I, N>::node topo_wst<I, N>::MakeNode(
int level)
402 template <
class I,
class N>
403 bool topo_wst<I, N>::highest_fork (p_set<site>& components, site &r)
405 if (components.nsites() == 0)
407 std::cerr <<
"highest fork : empty set" << std::endl;
415 typename p_set<site>::fwd_piter it(components);
419 if (it.to_site() == m)
422 site c = lca(hfork, it.to_site());
423 if (c != it.to_site())
427 if (nodes(m).level == nodes(hfork).level)
434 template <
class I,
class N>
435 bool topo_wst<I, N>::highest_fork (p_set<site>& components) {
437 return highest_fork(components, i);
440 template <
class I,
class N>
441 void topo_wst<I, N>::compute_ctree_size (site p)
450 for (
unsigned i=0; i < n.children.size(); ++i)
451 compute_ctree_size(n.children[i]);
455 template <
class I,
class N>
456 void topo_wst<I, N>::build_euler_tour_rec(site p,
int &position,
int d)
458 if (pos.find(p) == pos.end())
463 euler[position] = pos[p];
477 for (
unsigned i=0; i < n.children.size(); ++i)
479 build_euler_tour_rec(n.children[i], position, d+1);
481 euler[position] = pos[p];
488 template <
class I,
class N>
489 void topo_wst<I, N>::build_euler_tour ()
492 compute_ctree_size(Root);
494 int size = 2 * ctree_size - 1;
497 euler =
new int[size];
498 depth =
new int[size];
499 repr =
new site[size];
502 build_euler_tour_rec(Root, position, 0);
506 template <
class I,
class N>
507 void topo_wst<I, N>::build_minim ()
510 int size = 2 * ctree_size - 1;
511 int logn = (int)(ceil(log((
double)(size))/log(2.0)));
513 minim =
new int [logn * size];
514 Minim =
new int* [logn];
519 for (
int i = 0; i < size - 1; ++i)
520 if (depth[euler[i]] < depth[euler[i+1]]) {
529 for (
int j = 1; j < logn; j++) {
531 Minim[j] = &minim[j * size];
532 for (
int i = 0; i < size; i++) {
533 if ((i + (k << 1)) >= size) {
537 if (depth[euler[Minim[j - 1][i]]]
538 <= depth[euler[Minim[j - 1][i + k]]])
539 Minim[j][i] = Minim[j - 1][i];
541 Minim[j][i] = Minim[j - 1][i + k];
549 template <
class I,
class N>
550 typename topo_wst<I, N>::site topo_wst<I, N>::lca (site a, site b)
567 k = (int)(log((
double)(n - m))/log(2.));
569 if (depth[euler[Minim[k][m]]] < depth[euler[Minim[k][n - (1 << k)]]]) {
570 return repr[euler[Minim[k][m]]];
572 return repr[euler[Minim[k][n - (1 << k)]]];
577 template <
class I,
class N>
578 void topo_wst<I, N>::removeOneSonNodes(site *p,
579 mln_ch_value(I, site) &newPar_node)
583 if (n.children.size() == 1)
586 newPar_node(*p) = n.children[0];
588 removeOneSonNodes(p, newPar_node);
592 for (
unsigned i = 0; i < n.children.size(); ++i)
593 removeOneSonNodes(&(n.children[i]), newPar_node);
598 template <
class I,
class N>
599 void topo_wst<I, N>::compressTree()
601 mln_ch_value(I, site) newPar_node;
605 removeOneSonNodes(&Root, newPar_node);
608 mln_piter(I) p(Par_node.domain());
610 while (nodes(Par_node(p)).area == -1)
611 Par_node(p) = newPar_node(Par_node(p));
615 bool w_constructible(T &tree, typename T::site p, typename T::site &r)
618 typedef typename T::image_t I;
619 typedef typename T::neighborhood_t N;
621 const I &ima = exact(tree.ima);
622 const N &nbh = exact(tree.nbh);
625 mln_niter(N) q(nbh, p);
626 p_set<mln_site(I)> v;
631 if (ima.domain().has(q) && ima(q) < ima(p))
632 v.insert(tree.Par_node(q));
643 mln_site(I) c = min(ima, v);
644 mln_site(I) cmin = c;
646 typename p_set<mln_site(I)>::fwd_piter it(v);
650 if (it.to_site() == cmin)
653 mln_site(I) c1 = tree.lca(c, it);
659 if (tree.nodes(c).level >= ima(p))
667 bool w_constructible(T &tree, typename T::site p) {
669 return w_constructible(tree, p, r);
678 typedef typename T::image_t I;
679 typedef typename T::neighborhood_t N;
681 I ima = exact(tree.ima);
682 const N &nbh = exact(tree.nbh);
685 mln_ch_value(I,
bool) cmax;
689 mln_ch_value(I,
bool) enqueued;
694 std::queue<mln_site(I)> m;
695 mln_value(I) min = mln_min(mln_value(I));
697 std::cout <<
"Init" << std::endl;
703 mln_piter(I) it(tree.Par_node.domain());
706 if (tree.nodes(tree.Par_node(it)).children.size() == 0)
715 mln_niter(N) q(nbh, m.front());
719 if (cmax.domain().has(q) && !cmax(q) && !enqueued(q))
722 l.
push(mln_max(mln_value(I)) - ima(q), q);
728 std::cout <<
"end" << std::endl;
731 while (!l.is_empty())
733 mln_site(I) x = l.
front();
738 bool is_w = w_constructible(tree, x, c);
742 ima(x) = tree.nodes(c).level;
743 tree.Par_node(x) = c;
746 if (tree.nodes(c).children.size() == 0)
750 if (tree.nodes(c).children.size() == 1)
751 std::cerr <<
"ERREUR COMPOSANTE BRANCHE "
752 << tree.nodes(c).children.size() << std::endl;
756 mln_niter(N) q(nbh, x);
760 if (ima.domain().has(q) && !cmax(q) && !enqueued(q))
763 l.
push(mln_max(mln_value(I)) - ima(q), q);
773 ima(it) = tree.nodes(tree.Par_node(it)).level;
778 # endif // MLN_INCLUDE_ONLY
787 #endif // ! MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH