line_set.hh 9.29 KB
Newer Older
1
2
// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
// (LRDE)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//
// This file is part of Olena.
//
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free
// software project 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 SCRIBO_CORE_LINE_SET_HH
# define SCRIBO_CORE_LINE_SET_HH

/// \file
///
/// \brief Definition of a line set.

# include <mln/util/array.hh>

# include <mln/accu/pair.hh>
# include <mln/accu/center.hh>
# include <mln/accu/shape/bbox.hh>

# include <mln/labeling/compute.hh>
# include <mln/make/relabelfun.hh>

# include <mln/fun/i2v/array.hh>

# include <mln/convert/from_to.hh>


# include <scribo/core/macros.hh>
# include <scribo/core/line_info.hh>
50
51
52

# include <scribo/core/object_links.hh>
# include <scribo/core/object_groups.hh>
53
54
55
56
57
58
59


namespace scribo
{

  // Forward declaration.
  template <typename L> struct line_set;
60
  template <typename L> struct line_info;
61
62


63
64
  typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t;

65
66
67
68
69
70
71
  namespace internal
  {
    /// Data structure for \c scribo::line_set<I>.
    template <typename L>
    struct line_set_data
    {
      line_set_data();
72
      line_set_data(const object_groups<L>& comp_set);
Guillaume Lazzara's avatar
Guillaume Lazzara committed
73
      line_set_data(const mln::util::array<scribo::line_info<L> >& infos,
74
		    const object_groups<L>& comp_set);
75

Guillaume Lazzara's avatar
Guillaume Lazzara committed
76
      mln::util::array<scribo::line_info<L> > infos_;
77
78
79
      component_set<L> components_;
      object_links<L> links_;
      object_groups<L> groups_;
80
81
82
83
84
    };

  } // end of namespace scribo::internal


85
86
87
  /*! \brief Lines container.

    Line ids start from 1.
88

89
   */
90
91
92
93
94
95
96
97
98
99
100
  template <typename L>
  class line_set
  {
  public:

    /// Constructors
    /// @{
    /// Constructor without argument.
    line_set();

    /// Constructor from object groups.
101
    line_set(const object_groups<L>& groups);
102
103
104
    /// @}

    /// Compute line stats and fill the underlying information.
105
    void compute_lines(const object_groups<L>& groups);
106
107
108
109
110

    /// Return the line count.
    mln_value(L) nelements() const;

    /// Return line information for a given line id \p id.
Guillaume Lazzara's avatar
Guillaume Lazzara committed
111
    const line_info<L>& info(const mln_value(L)& id) const;
112
113

    /// Return line information for a given line id \p id.
Guillaume Lazzara's avatar
Guillaume Lazzara committed
114
    line_info<L>& info(const mln_value(L)& id);
115
116

    /// Return line information for a given line id \p id.
Guillaume Lazzara's avatar
Guillaume Lazzara committed
117
    line_info<L>& operator()(const line_id_t& id);
118
119

    /// Return line information for a given line id \p id.
Guillaume Lazzara's avatar
Guillaume Lazzara committed
120
    const line_info<L>& operator()(const line_id_t& id) const;
121
122
123
124
125
126
127
128
129

    /// Update tag of lines set to 'false' in \p f with \p tag.
    template <typename F>
    void update_tags(const mln::Function_v2b<F>& f, line::Tag tag);

    /// Create a copy of this line_set<L>
    line_set<L> duplicate() const;

    /// Return the underlying component set.
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    const component_set<L>& components() const;

    /// Return the underlying component set (non-const version).
    component_set<L>& components_();

    /// Return the underlying component group.
    const object_groups<L>& groups() const;

    /// Return the underlying links.
    const object_links<L>& links() const;


    /// Massive line computation
    /// @{

    void force_stats_update();

    /// @}
148
149
150
151
152

    /// Internal methods
    /// @{

    /// Return all the line infos.
Guillaume Lazzara's avatar
Guillaume Lazzara committed
153
    const mln::util::array<scribo::line_info<L> >& infos_() const;
154
155
156

    /// @}

157
158
159

    bool is_valid() const;

160
161
162
163
164
165
166
167
168
169
170
171
172
  private:
    /// Duplicate the underlying image and create a new line_set.
    void init_(const line_set<L>& model);

    mln::util::tracked_ptr< internal::line_set_data<L> > data_;
  };


  namespace make
  {

    template <typename L>
    scribo::line_set<L>
173
    line_set(const object_groups<L>& groups);
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

  } // End of namespace scribo::make



# ifndef MLN_INCLUDE_ONLY


  // line_set_data<L> >

  namespace internal
  {

    // data< line_set<L> >


    template <typename L>
    inline
    line_set_data<L>::line_set_data()
    {
    }


197
198
199
200
201
202
203
204
205
    template <typename L>
    inline
    line_set_data<L>::line_set_data(const object_groups<L>& groups)
      : components_(groups.components()), links_(groups.links()),
	groups_(groups)
    {
    }


206
207
    template <typename L>
    inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
208
    line_set_data<L>::line_set_data(const mln::util::array<scribo::line_info<L> >& infos,
209
210
211
				    const object_groups<L>& groups)
      : infos_(infos), components_(groups.components()),
	links_(groups.links()), groups_(groups)
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    {
    }

  } // end of namespace mln::internal




  template <typename L>
  inline
  line_set<L>::line_set()
  {
  }

226

227
228
  template <typename L>
  inline
229
  line_set<L>::line_set(const object_groups<L>& groups)
230
  {
231
    compute_lines(groups);
232
233
234
235
  }


  template <typename L>
Guillaume Lazzara's avatar
Guillaume Lazzara committed
236
  void
237
  line_set<L>::compute_lines(const object_groups<L>& groups)
238
  {
239
    data_ = new internal::line_set_data<L>(groups);
240
241
242
243
244
245
246
247
248

    typedef mln_site(L) P;

    mln_value(L) n_groups = groups.nelements() - 1;
    mln::fun::i2v::array<mln_value(L)>
      packed_groups = mln::make::relabelfun(groups.comp_to_group(),
					    n_groups, n_groups);

    // FIXME: object_groups should store the relation 'group -> comp'.
249
    mln::util::array< mln::util::array<component_id_t> >
250
      group_to_comps(value::next(n_groups));
251
252
253


    // 1st pass - Compute data.
254
255
    for_all_comps(i, data_->components_)
      if (data_->components_(i).is_valid())
256
257
258
259
260
      {
	unsigned group_id = packed_groups(i);
	if (group_id != 0) // Is this component part of a group?
	{
	  // Component id.
261
	  group_to_comps(group_id).append(i);
262
263
264
265
	}
      }

    // 2nd pass - Store data.
266
    data_->infos_.reserve(group_to_comps.size());
Guillaume Lazzara's avatar
Guillaume Lazzara committed
267
    data_->infos_.append(line_info<L>()); // line with id 0 is invalid.
268

269
    for_all_groups(i, group_to_comps)
270
271
    {
      // Add line info.
272
      line_info<L> info(*this, i, group_to_comps(i));
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
      data_->infos_.append(info);
    }
  }



  template <typename L>
  inline
  mln_value(L)
  line_set<L>::nelements() const
  {
    return data_->infos_.nelements() - 1;
  }

  template <typename L>
  inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
289
  const line_info<L>&
290
291
292
293
294
295
296
  line_set<L>::info(const mln_value(L)& id) const
  {
    return this->data_->infos_[id];
  }

  template <typename L>
  inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
297
  line_info<L>&
298
299
300
301
302
303
304
  line_set<L>::info(const mln_value(L)& id)
  {
    return this->data_->infos_[id];
  }

  template <typename L>
  inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
305
  const line_info<L>&
306
307
308
309
310
311
312
  line_set<L>::operator()(const line_id_t& id) const
  {
    return this->data_->infos_[id];
  }

  template <typename L>
  inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
313
  line_info<L>&
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  line_set<L>::operator()(const line_id_t& id)
  {
    return this->data_->infos_[id];
  }

  template <typename L>
  template <typename F>
  inline
  void
  line_set<L>::update_tags(const mln::Function_v2b<F>& f_,
				line::Tag tag)
  {
    const F& f = exact(f_);

328
    for_all_lines_info(i, data_->infos_)
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
      if (!f(i))
	data_->infos_[i].update_tag(tag);
  }


  template <typename L>
  inline
  line_set<L>
  line_set<L>::duplicate() const
  {
    line_set<L> output;
    output.init_(*this);
    return output;
  }

  template <typename L>
  inline
  const component_set<L>&
347
348
349
350
351
352
353
354
355
  line_set<L>::components() const
  {
    return data_->components_;
  }

  template <typename L>
  inline
  component_set<L>&
  line_set<L>::components_()
356
  {
357
    return data_->components_;
358
359
  }

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  template <typename L>
  inline
  const object_groups<L>&
  line_set<L>::groups() const
  {
    return data_->groups_;
  }

  template <typename L>
  inline
  const object_links<L>&
  line_set<L>::links() const
  {
    return data_->links_;
  }

  template <typename L>
  inline
  void
  line_set<L>::force_stats_update()
  {
    for_all_lines_info(i, data_->infos_)
      if (data_->infos_(i).tag() == line::Needs_Precise_Stats_Update)
	data_->infos_(i).force_stats_update();
  }
385
386
387

  template <typename L>
  inline
Guillaume Lazzara's avatar
Guillaume Lazzara committed
388
  const mln::util::array<scribo::line_info<L> >&
389
390
391
392
393
  line_set<L>::infos_() const
  {
    return data_->infos_;
  }

394
395
396
397
398
399
400
401
  template <typename L>
  inline
  bool
  line_set<L>::is_valid() const
  {
    return data_->links_.is_valid() && data_->groups_.is_valid();
  }

402
403
404
405
406
  template <typename L>
  inline
  void
  line_set<L>::init_(const line_set<L>& set)
  {
407
    data_ = new internal::line_set_data<L>(set.infos_(), set.groups());
408
409
410
411
412
413
414
415
416
417
  }


  // Make routines.

  namespace make
  {

    template <typename L>
    scribo::line_set<L>
418
    line_set(const object_groups<L>& groups)
419
    {
420
421
      mln_precondition(groups.is_valid());
      scribo::line_set<L> tmp(groups);
422
423
424
425
426
427
428
429
430
431
432
      return tmp;
    }

  } // end of namespace scribo::make


# endif // ! MLN_INCLUDE_ONLY

} // end of namespace scribo

#endif // ! SCRIBO_CORE_LINE_SET_HH