$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
link_single_dmax_ratio_aligned_base.hh
1 // Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_SINGLE_DMAX_RATIO_ALIGNED_BASE_HH_
27 # define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_SINGLE_DMAX_RATIO_ALIGNED_BASE_HH_
28 
33 
34 
35 # include <mln/accu/center.hh>
36 # include <mln/labeling/compute.hh>
37 # include <mln/math/abs.hh>
38 # include <mln/math/max.hh>
39 # include <mln/util/array.hh>
40 # include <mln/value/rgb8.hh>
41 # include <mln/draw/line.hh>
42 # include <mln/literal/colors.hh>
43 # include <mln/norm/l1.hh>
44 
45 # include <scribo/core/macros.hh>
46 # include <scribo/core/tag/anchor.hh>
47 # include <scribo/core/component_set.hh>
48 # include <scribo/core/object_links.hh>
49 # include <scribo/core/concept/dmax_functor.hh>
50 
51 # include <scribo/debug/logger.hh>
52 
53 # include <scribo/primitive/link/internal/link_single_dmax_ratio_base.hh>
54 # include <scribo/filter/internal/component_aligned.hh>
55 
56 
57 namespace scribo
58 {
59 
60  namespace primitive
61  {
62 
63  namespace link
64  {
65 
66  namespace internal
67  {
68  using namespace scribo::debug;
69 
70 
71  template <typename L, typename F, typename E>
73  : public link_single_dmax_ratio_base<L, F, E>
74  {
76 
77  public:
78  typedef mln_site(L) P;
79 
82  const DMax_Functor<F>& dmax_f,
83  float min_angle,
84  float max_angle,
85  anchor::Type anchor)
86  : super_(components, anchor::Horizontal, exact(dmax_f)),
87  debug_anchor_(anchor)
88  {
89  min_alpha_rad = (min_angle / 180.0f) * math::pi;
90  max_alpha_rad = (max_angle / 180.0f) * math::pi;
91 
92 # ifndef SCRIBO_NDEBUG
93  if (scribo::debug::logger().is_at_level(debug::AuxiliaryResults))
94  {
95  initialize(debug_, components.labeled_image());
96  data::fill(debug_, literal::black);
97  data::fill((debug_
98  | (pw::value(components.labeled_image()) != 0u)).rw(),
99  literal::white);
100  debug_angle_ = duplicate(debug_);
101  }
102 # endif // ! SCRIBO_NDEBUG
103  }
104 
105 
106  mln_site(L)
107  start_point_(unsigned current_object, anchor::Type anchor)
108  {
109  return link::internal::compute_anchor(this->components_,
110  current_object, anchor);
111  }
112 
113 
114  inline
115  bool
116  valid_link_(unsigned current_object,
117  const P& start_point,
118  const P& p,
119  anchor::Type anchor)
120  {
121  if (!super_::valid_link_(current_object, start_point, p, anchor))
122  return false;
123 
124  // Distance between the two components.
125  float dist;// = math::abs(p[this->direction_] - start_point[this->direction_]);
126 
127  box<P> b = this->components_(current_object).bbox();
128  if (p[this->direction_] > b.pmax()[this->direction_])
129  dist = math::abs(p[this->direction_] - b.pmax()[this->direction_]);
130  // current object is on the right.
131  else
132  dist = math::abs(p[this->direction_] - b.pmin()[this->direction_]);
133 
134 
135  unsigned ldist = this->components_(current_object).bbox().width() / 2;
136 
137 
138  // Components are really close, so the angle is more permissive.
139  if (dist < ldist * 3)
140  {
141  return
142  filter::internal::component_aligned_rad(this->components_,
143  current_object,
144  this->labeled_image_(p),
145  anchor,
146  max_alpha_rad);
147  }
148 
149 
150  // Components are really far, so the angle is less permissive.
151  return
152  filter::internal::component_aligned_rad(this->components_,
153  current_object,
154  this->labeled_image_(p),
155  anchor,
156  min_alpha_rad);
157  }
158 
159 
160  void validate_link_(unsigned current_object,
161  const P& start_point,
162  const P& p,
163  anchor::Type anchor)
164  {
165  super_::validate_link_(current_object, start_point, p, anchor);
166 
167 # ifndef SCRIBO_NDEBUG
168  if (logger().is_at_level(debug::AuxiliaryResults))
169  {
170  mln_site(L)
171  p1 = link::internal::compute_anchor(this->components_,
172  current_object, debug_anchor_),
173  p2 = link::internal::compute_anchor(this->components_,
174  this->labeled_image_(p),
175  debug_anchor_);
176  mln::draw::line(debug_, p1, p2, literal::green);
177 
178 
179  float
180  angle = filter::internal::alignment_angle(this->components_,
181  current_object,
182  this->labeled_image_(p),
183  anchor);
184  angle = (angle * 180.0f) / math::pi;
185  angle = angle * 20.0f + 1.0f;
186  mln::draw::line(debug_angle_, p1, p2,
187  value::rgb8(unsigned(angle),
188  unsigned(angle),
189  unsigned(angle)));
190  }
191 # endif // ! SCRIBO_NDEBUG
192  }
193 
194  void invalidate_link_(unsigned current_object,
195  const P& start_point,
196  const P& p,
197  anchor::Type anchor)
198  {
199  super_::invalidate_link_(current_object, start_point, p, anchor);
200 
201 # ifndef SCRIBO_NDEBUG
202  if (logger().is_at_level(debug::AuxiliaryResults))
203  {
204  if (this->labeled_image_.domain().has(p) && this->labeled_image_(p) != 0)
205  {
206  mln_site(L)
207  p1 = link::internal::compute_anchor(this->components_,
208  current_object, debug_anchor_),
209  p2 = link::internal::compute_anchor(this->components_,
210  this->labeled_image_(p),
211  debug_anchor_);
212 
213  // Arbitrary check to avoid large lines drawn over the whole page.
214  if (this->labeled_image_.domain().has(p2)
215  && norm::l1_distance(p1.to_vec(), p2.to_vec()) < 300)
216  {
217  mln::draw::line(debug_, p1, p2, literal::red);
218  }
219 
220 
221  float
222  angle = filter::internal::alignment_angle(this->components_,
223  current_object,
224  this->labeled_image_(p),
225  anchor);
226  angle = (angle * 180.0f) / math::pi;
227  angle = angle * 20.0f + 1.0f;
228  mln::draw::line(debug_angle_, p1, p2,
229  value::rgb8(unsigned(angle),
230  unsigned(angle),
231  unsigned(angle)));
232  }
233  }
234 # endif // ! SCRIBO_NDEBUG
235  }
236 
237  float min_alpha_rad;
238  float max_alpha_rad;
239 
240  // Anchor used for debug output!
241  anchor::Type debug_anchor_;
242 
243  mln_ch_value(L, value::rgb8) debug_;
244  mln_ch_value(L, value::rgb8) debug_angle_;
245  };
246 
247 
248 # ifndef MLN_INCLUDE_ONLY
249 
250 
251 # endif // ! MLN_INCLUDE_ONLY
252 
253 
254  } // end of namespace scribo::primitive::link::internal
255 
256  } // end of namespace scribo::primitive::link
257 
258  } // end of namespace scribo::primitive
259 
260 } // end of namespace scribo
261 
262 
263 #endif // SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_SINGLE_DMAX_RATIO_ALIGNED_BASE_HH_