• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

p_line2d.hh

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_CORE_SITE_SET_P_LINE2D_HH
00027 # define MLN_CORE_SITE_SET_P_LINE2D_HH
00028 
00033 
00034 # include <mln/core/site_set/p_array.hh>
00035 # include <mln/core/alias/box2d.hh>
00036 
00037 # include <mln/math/sign.hh>
00038 # include <mln/math/abs.hh>
00039 # include <mln/math/min.hh>
00040 # include <mln/math/max.hh>
00041 
00042 
00043 namespace mln
00044 {
00045 
00046   // Forward declaration.
00047   class p_line2d;
00048 
00049 
00050 
00051   namespace trait
00052   {
00053 
00054     template <>
00055     struct site_set_< p_line2d >
00056     {
00057       typedef trait::site_set::nsites::known   nsites;
00058       typedef trait::site_set::bbox::straight  bbox;
00059       typedef trait::site_set::contents::fixed contents;
00060       typedef trait::site_set::arity::unique   arity;
00061     };
00062 
00063     template <>
00064     struct set_precise_unary_< op::ord, p_line2d >
00065     {
00066       typedef set_precise_unary_< op::ord, p_line2d > ret; // Itself.
00067       bool strict(const p_line2d& lhs, const p_line2d& rhs) const;
00068     };
00069 
00070   } // end of namespace trait
00071 
00072 
00073 
00078   //
00079   class p_line2d : public internal::site_set_base_< point2d, p_line2d >
00080   {
00081     typedef p_line2d self_;
00082   public:
00083 
00085     typedef point2d element;
00086 
00088     typedef p_indexed_psite<self_> psite;
00089 
00091     typedef p_indexed_fwd_piter<self_> piter;
00092 
00094     typedef p_indexed_fwd_piter<self_> fwd_piter;
00095 
00097     typedef p_indexed_bkd_piter<self_> bkd_piter;
00098 
00099 
00101     p_line2d();
00102 
00104     p_line2d(const point2d& beg, const point2d& end,
00105              bool is_end_excluded = false);
00106 
00107 
00109     bool has(const psite& p) const;
00110 
00112     bool has(const util::index& i) const;
00113 
00115     bool is_valid() const;
00116 
00117 
00119     unsigned nsites() const;
00120 
00122     const point2d& begin() const;
00123 
00125     const point2d& end() const;
00126 
00128     const point2d& operator[](unsigned i) const;
00129 
00130 
00132     typedef const box2d& q_box;
00133 
00135     const box2d& bbox() const;
00136 
00137 
00139     std::size_t memory_size() const;
00140 
00142     const std::vector<point2d>& std_vector() const;
00143 
00144     // Return the corresponding algebra::vec.
00145     algebra::vec<2, float> to_vec() const;
00146 
00147   protected:
00148 
00149     p_array<point2d> arr_;
00150     box2d bb_;
00151 
00152     void compute_(const point2d& beg, const point2d& end,
00153                   bool is_end_excluded);
00154   };
00155 
00156 
00157 
00158 # ifndef MLN_INCLUDE_ONLY
00159 
00160   inline
00161   p_line2d::p_line2d()
00162   {
00163     mln_postcondition(! is_valid());
00164   }
00165 
00166   inline
00167   p_line2d::p_line2d(const point2d& beg, const point2d& end,
00168                  bool is_end_excluded)
00169   {
00170     if (is_end_excluded)
00171       mln_precondition(end != beg);
00172     compute_(beg, end, is_end_excluded);
00173     mln_postcondition(is_valid());
00174   }
00175 
00176   inline
00177   void
00178   p_line2d::compute_(const point2d& beg, const point2d& end,
00179                    bool is_end_excluded)
00180   {
00181     if (is_end_excluded)
00182       mln_precondition(end != beg);
00183 
00184     // Compute arr_.
00185     dpoint2d dp = end - beg;
00186     int
00187       srow = math::sign(dp.row()), drow = math::abs(dp.row()), ddrow = 2 * drow,
00188       scol = math::sign(dp.col()), dcol = math::abs(dp.col()), ddcol = 2 * dcol,
00189       row = beg.row(),
00190       col = beg.col();
00191     if ( dcol > drow )
00192       {
00193         int e = ddrow - dcol;
00194         for (int i = 0; i < dcol; ++i)
00195           {
00196             arr_.append(point2d(static_cast<def::coord>(row),
00197                                 static_cast<def::coord>(col)));
00198             while (e >= 0)
00199               {
00200                 row += srow;
00201                 e -= ddcol;
00202               }
00203             col += scol;
00204             e += ddrow;
00205           }
00206       }
00207     else
00208       {
00209         int e = ddcol - drow;
00210         for (int i = 0; i < drow; ++i)
00211           {
00212             arr_.append(point2d(static_cast<def::coord>(row),
00213                                 static_cast<def::coord>(col)));
00214             while (e >= 0)
00215               {
00216                 col += scol;
00217                 e -= ddrow;
00218               }
00219             row += srow;
00220             e += ddcol;
00221           }
00222       }
00223     if (! is_end_excluded)
00224       arr_.append(point2d(static_cast<def::coord>(row),
00225                           static_cast<def::coord>(col)));
00226 
00227     // Compute bb_.
00228     point2d end_ = arr_[arr_.nsites() - 1];
00229     bb_.pmin() = point2d(math::min(beg.row(), end_.row()),
00230                          math::min(beg.col(), end_.col()));
00231     bb_.pmax() = point2d(math::max(beg.row(), end_.row()),
00232                          math::max(beg.col(), end_.col()));
00233 
00234     mln_postcondition(this->begin() == beg);
00235     mln_postcondition(is_end_excluded == (this->end() != end));
00236   }
00237 
00238   inline
00239   bool
00240   p_line2d::has(const psite& p) const
00241   {
00242     mln_precondition(p.target_() == this); // FIXME: Refine.
00243     if (! has(p.index()))
00244       return false;
00245     mln_invariant(p.to_site() == (*this)[p.index()]);
00246     return true;
00247   }
00248 
00249   inline
00250   bool
00251   p_line2d::has(const util::index& i) const
00252   {
00253     return i >= 0 && unsigned(i) < nsites();
00254   }
00255 
00256   inline
00257   bool
00258   p_line2d::is_valid() const
00259   {
00260     mln_invariant(implies(bb_.is_valid(), ! arr_.is_empty()));
00261     return bb_.is_valid();
00262   }
00263 
00264   inline
00265   unsigned
00266   p_line2d::nsites() const
00267   {
00268     return arr_.nsites();
00269   }
00270 
00271   inline
00272   const box2d&
00273   p_line2d::bbox() const
00274   {
00275     mln_precondition(is_valid());
00276     return bb_;
00277   }
00278 
00279   inline
00280   const std::vector<point2d>&
00281   p_line2d::std_vector() const
00282   {
00283     return arr_.std_vector();
00284   }
00285 
00286   // FIXME: make it more generic?
00287   inline
00288   algebra::vec<2, float>
00289   p_line2d::to_vec() const
00290   {
00291     algebra::vec<2, float> res;
00292     res[0] = float(end().row() - begin().row());
00293     res[1] = float(end().col() - begin().col());
00294     return res;
00295   }
00296 
00297   inline
00298   const point2d&
00299   p_line2d::operator[](unsigned i) const
00300   {
00301     mln_precondition(i < nsites());
00302     return arr_[i];
00303   }
00304 
00305   inline
00306   const point2d&
00307   p_line2d::begin() const
00308   {
00309     mln_precondition(is_valid());
00310     return arr_[0];
00311   }
00312 
00313   inline
00314   const point2d&
00315   p_line2d::end() const
00316   {
00317     mln_precondition(is_valid());
00318     return arr_[nsites() - 1];
00319   }
00320 
00321   inline
00322   std::size_t
00323   p_line2d::memory_size() const
00324   {
00325     return arr_.memory_size() + sizeof(box2d);
00326   }
00327 
00328 
00329   namespace trait
00330   {
00331 
00332     inline
00333     bool
00334     set_precise_unary_< op::ord, p_line2d >::strict(const p_line2d& lhs,
00335                                                     const p_line2d& rhs) const
00336     {
00337       return util::ord_lexi_strict(lhs.begin(), lhs.end(),
00338                                    rhs.begin(), rhs.end());
00339     }
00340 
00341   } // end of namespace mln::trait
00342 
00343 # endif // ! MLN_INCLUDE_ONLY
00344 
00345 } // end of namespace mln
00346 
00347 
00348 #endif // ! MLN_CORE_SITE_SET_P_LINE2D_HH

Generated on Tue Oct 4 2011 15:24:16 for Milena (Olena) by  doxygen 1.7.1