00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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;
00067 bool strict(const p_line2d& lhs, const p_line2d& rhs) const;
00068 };
00069
00070 }
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
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
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
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);
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
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 }
00342
00343 # endif // ! MLN_INCLUDE_ONLY
00344
00345 }
00346
00347
00348 #endif // ! MLN_CORE_SITE_SET_P_LINE2D_HH