00001 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) 00002 // 00003 // This file is part of Olena. 00004 // 00005 // Olena is free software: you can redistribute it and/or modify it under 00006 // the terms of the GNU General Public License as published by the Free 00007 // Software Foundation, version 2 of the License. 00008 // 00009 // Olena is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software project without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to produce 00021 // an executable, this file does not by itself cause the resulting 00022 // executable to be covered by the GNU General Public License. This 00023 // exception does not however invalidate any other reasons why the 00024 // executable file might be covered by the GNU General Public License. 00025 00026 #ifndef MLN_ACCU_SHAPE_VOLUME_HH 00027 # define MLN_ACCU_SHAPE_VOLUME_HH 00028 00032 00043 # include <mln/accu/internal/base.hh> 00044 # include <mln/core/concept/meta_accumulator.hh> 00045 # include <mln/math/diff_abs.hh> 00046 00047 # include <mln/util/pix.hh> 00048 # include <mln/literal/zero.hh> 00049 00050 namespace mln 00051 { 00052 00053 namespace accu 00054 { 00055 00056 namespace shape 00057 { 00058 00065 template <typename I> 00066 struct volume 00067 : public mln::accu::internal::base< unsigned , volume<I> > 00068 { 00076 typedef util::pix<I> argument; 00078 typedef typename argument::value value; 00079 00080 volume(); 00081 00084 void init(); 00085 void take(const argument& pixel); 00086 void take(const volume<I>& other); 00087 00089 void set_value(unsigned v); 00091 00093 unsigned to_result() const; 00094 00097 bool is_valid() const; 00098 00099 protected: 00101 value ref_level__; 00103 unsigned area__; 00105 unsigned volume_; 00106 }; 00107 00108 00109 } // end of mln::accu::shape 00110 00111 00112 namespace meta 00113 { 00114 00115 namespace shape 00116 { 00117 00119 00120 struct volume : public Meta_Accumulator< volume > 00121 { 00122 template <typename I> 00123 struct with 00124 { 00125 typedef accu::shape::volume<I> ret; 00126 }; 00127 }; 00128 00129 } // end of namespace mln::accu::meta::shape 00130 00131 } // end of namespace mln::accu::meta 00132 00133 # ifndef MLN_INCLUDE_ONLY 00134 00135 namespace shape 00136 { 00137 00138 template <typename I> 00139 inline 00140 volume<I>::volume() 00141 { 00142 init(); 00143 } 00144 00145 template <typename I> 00146 inline 00147 void 00148 volume<I>::init() 00149 { 00150 ref_level__ = literal::zero; 00151 volume_ = 0; 00152 area__ = 0; 00153 } 00154 00155 template <typename I> 00156 inline 00157 void 00158 volume<I>::take(const argument& pixel) 00159 { 00160 /* FIXME: Growing a component using this particular `take' 00161 routine won't work, since the update does not take care of 00162 the reference level to compute the new volume. Maybe we 00163 could distinguish two cases: 00164 00165 1. the empty accumulator case (which corresponds to the 00166 following code); 00167 2. the non-empty accumulator case (which sohuld act as in 00168 `take(const volume<I>& other)'). 00169 00170 Currently, the implementation is only valid if the 00171 accumulator was initialy empty before the call to 00172 `take(const argument&)'. */ 00173 ref_level__ = pixel.v(); 00174 ++area__; 00175 ++volume_; 00176 } 00177 00178 template <typename I> 00179 inline 00180 void 00181 volume<I>::take(const volume<I>& other) 00182 { 00183 area__ += other.area__; 00184 /* FIXME: Is it `t.area__' or `area__' ? Théo said it was 00185 the latter, but both the ISMM 2005 paper and Olena 0.11 use 00186 the former. */ 00187 volume_ += 00188 other.volume_ + 00189 other.area__ * mln::math::diff_abs(other.ref_level__, ref_level__); 00190 // Member ref_level__ is not touched. 00191 } 00192 00193 template <typename I> 00194 inline 00195 unsigned 00196 volume<I>::to_result() const 00197 { 00198 return volume_; 00199 } 00200 00201 template <typename I> 00202 inline 00203 void 00204 volume<I>::set_value(unsigned v) 00205 { 00206 volume_ = v; 00207 // Reset the other members. 00208 ref_level__ = literal::zero; 00209 area__ = 0; 00210 } 00211 00212 template <typename I> 00213 inline 00214 bool 00215 volume<I>::is_valid() const 00216 { 00217 return true; 00218 } 00219 00220 } // end of namespace mln::accu::shape 00221 00222 # endif // ! MLN_INCLUDE_ONLY 00223 00224 } // end of namespace mln::accu 00225 00226 } // end of namespace mln 00227 00228 00229 #endif // ! MLN_ACCU_SHAPE_VOLUME_HH