$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
align_lines.hh
1 // Copyright (C) 2009, 2010, 2011, 2013 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef SCRIBO_TABLE_INTERNAL_ALIGN_LINES_HH
28 # define SCRIBO_TABLE_INTERNAL_ALIGN_LINES_HH
29 
33 
34 
35 # include <mln/core/site_set/box.hh>
36 
37 # include <mln/accu/stat/mean.hh>
38 
39 # include <mln/util/array.hh>
40 # include <mln/util/set.hh>
41 
42 # include <mln/math/round.hh>
43 
44 # include <scribo/core/macros.hh>
45 # include <scribo/core/component_set.hh>
46 
47 
48 namespace scribo
49 {
50 
51  namespace table
52  {
53 
54  namespace internal
55  {
56 
57  using namespace mln;
58 
71  /*
72  **
73  ** 0 1 3 4 5 6
74  ** ------------ -------
75  ** 0 |- - - - - | | {0,1} |
76  ** 1 | - - | | {0,1} |
77  ** 2 | | | {1} |
78  ** 3 | | | |
79  ** 4 | | | {2} |
80  ** 5 |- - | | {2} |
81  ** 6 | | | {2} |
82  **
83  ** \p hboxes contains all the table lines bboxes. Each bbox is
84  ** associated with an id, its location in the array.
85  **
86  ** For each bbox, its id is marked in a vector. The location is defined,
87  ** according to the given parameter \p dim, either by the row or the col
88  ** value of the pmin site.
89  **
90  ** Ids are then propagated in the vector according a small delta value.
91  ** if bbox ids are at the same location in the vector, their related bboxes
92  ** are likely to be on the same line.
93  **
94  ** Finally, iterate over the vector until all bboxes have been treated.
95  ** For each iteration, the set with a specific number of elements is found
96  ** and all bboxes referenced in this set are aligned on the same row or col.
97  **
98  */
99  template <typename L>
101  align_lines(unsigned nsites,
102  int min_coord,
103  int max_coord,
104  const component_set<L>& lines,
105  component_set<L>& aligned_lines,
106  unsigned dim,
107  unsigned max_alignment_diff);
108 
109 
110 
111 # ifndef MLN_INCLUDE_ONLY
112 
113 
114  template <typename L>
116  align_lines(unsigned nsites,
117  int min_coord,
118  int max_coord,
119  const component_set<L>& lines,
120  component_set<L>& aligned_lines,
121  unsigned dim,
122  unsigned max_alignment_diff)
123  {
124  mln_trace("scribo::internal::align_lines");
125 
126  mln_precondition(nsites > 0);
127 
129  lines.resize(nsites);
130 
131  // Map components with actual lines.
132  for_all_comps(i, lines)
133  {
134  int minline = lines(i).bbox().pmin()[dim] - max_alignment_diff;
135  minline = (minline < min_coord ? min_coord : minline);
136  int maxline = lines(i).bbox().pmax()[dim] + max_alignment_diff;
137  maxline = (maxline > max_coord ? max_coord : maxline);
138 
139  for (int line = minline;
140  line <= maxline; ++line)
141  rlines[line].insert(i);
142  }
143 
144  // Init box2line
146  box2line(value::next(lines.nelements()), -1);
147 
148  // Find the line with the highest element count.
149  unsigned max_nelts = 0;
150  for_all_elements(i, rlines)
151  if (max_nelts < rlines[i].nelements())
152  max_nelts = rlines[i].nelements();
153 
154  // Aligning lines
155  // FIXME: not optimal... Make it faster!
156  // We may do too much iterations (while loop) and some of them may
157  // be done for nothing...
158  aligned_lines = duplicate(lines);
159  mln::util::array<int> newlines;
160  while (max_nelts > 0)
161  {
162  for_all_elements(i, rlines)
163  if (rlines[i].nelements() == max_nelts)
164  {
166  for_all_elements(j, rlines[i])
167  if (box2line[rlines[i][j]] == -1)
168  mean.take(lines(rlines[i][j]).bbox().pcenter()[dim]);
169 
170  if (mean.is_valid())
171  {
172  for_all_elements(j, lines[i])
173  if (box2line[rlines[i][j]] == -1)
174  {
175  lines(rlines[i][j]).bbox().pmin()[dim] = math::round<int>(mean.to_result());
176  lines(rlines[i][j]).bbox().pmax()[dim] = math::round<int>(mean.to_result());
177  box2line[rlines[i][j]] = math::round<int>(mean.to_result());
178  }
179  newlines.append(math::round<int>(mean.to_result()));
180  }
181  }
182  --max_nelts;
183  }
184 
185  return newlines;
186  }
187 
188 
189 # endif // ! MLN_INCLUDE_ONLY
190 
191 
192  } // end of namespace scribo::table::internal
193 
194  } // end of namespace scribo::table
195 
196 } // end of namespace scribo
197 
198 #endif // ! SCRIBO_TABLE_INTERNAL_ALIGN_LINES_HH