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_TOPO_COMPLEX_HH
00027 # define MLN_TOPO_COMPLEX_HH
00028
00035
00036 # include <cstddef>
00037
00038 # include <iosfwd>
00039
00040 # include <mln/metal/bool.hh>
00041
00042 # include <mln/util/tracked_ptr.hh>
00043
00044 # include <mln/topo/face_data.hh>
00045 # include <mln/topo/algebraic_face.hh>
00046 # include <mln/topo/algebraic_n_face.hh>
00047 # include <mln/topo/n_faces_set.hh>
00048
00049 # include <mln/topo/complex_iterators.hh>
00050
00051
00052 namespace mln
00053 {
00054
00055 namespace topo
00056 {
00057
00058
00059 template <unsigned N, unsigned D> class n_faces_set;
00060 template <unsigned D> class face_fwd_iter;
00061 template <unsigned D> class face_bkd_iter;
00062
00063 # if 0
00064 template <unsigned N, unsigned D> class faces_fwd_iter_;
00065 template <unsigned N, unsigned D> class faces_bkd_iter_;
00066 #endif
00067
00068
00069 namespace internal
00070 {
00071 template <unsigned D>
00072 struct complex_data;
00073
00074 template <unsigned N, unsigned D>
00075 struct faces_set_mixin;
00076 }
00077
00078
00079
00080
00081
00082
00084
00085 template <unsigned D>
00086 class complex
00087 {
00088 public:
00090 typedef face_fwd_iter<D> fwd_citer;
00092 typedef face_bkd_iter<D> bkd_citer;
00093
00094
00095 # if 0
00096
00097 template <unsigned N>
00098 struct fwd_fiter { typedef faces_fwd_iter_<N, D> ret; };
00100 template <unsigned N>
00101 struct bkd_fiter { typedef faces_bkd_iter_<N, D> ret; };
00102 #endif
00103
00107 complex();
00108
00110 n_face<0u, D> add_face();
00111
00116 template <unsigned N>
00117 n_face<N + 1, D> add_face(const n_faces_set<N, D>& adjacent_faces);
00119
00126 unsigned nfaces() const;
00127
00129 template <unsigned N>
00130 unsigned nfaces_of_static_dim() const;
00132
00143 unsigned nfaces_of_dim(unsigned n) const;
00145
00149 void print(std::ostream& ostr) const;
00151 template <unsigned N>
00152 void print_faces(std::ostream& ostr) const;
00154
00159 const void* addr() const;
00160
00161 private:
00163 util::tracked_ptr< internal::complex_data<D> > data_;
00164
00165 template <unsigned D_>
00166 friend bool operator==(const complex<D_>& lhs, const complex<D_>& rhs);
00167
00170 template <unsigned N, unsigned D_> friend class n_face;
00171 template <unsigned D_> friend class face;
00172
00173 template <unsigned N>
00174 face_data<N, D>& face_data_(unsigned face_id);
00175
00176 template <unsigned N>
00177 const face_data<N, D>& face_data_(unsigned face_id) const;
00179
00182
00183
00184
00185
00186
00187
00197 template <typename BinaryFunction, typename T>
00198 T fold_left_(const BinaryFunction& f, const T& accu) const;
00199
00201 template <typename UnaryFunction>
00202 typename UnaryFunction::result_type
00203 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
00205
00212 template <unsigned N>
00213 void connect_(const algebraic_n_face<N, D>& f1,
00214 const n_face<N + 1, D>& f2);
00215 };
00216
00217
00219 template <unsigned D>
00220 bool
00221 operator==(const complex<D>& lhs, const complex<D>& rhs);
00222
00223
00225 template <unsigned D>
00226 std::ostream&
00227 operator<<(std::ostream& ostr, const complex<D>& c);
00228
00229
00230
00231
00232
00233
00288
00289
00290
00291
00294 namespace internal
00295 {
00296
00297
00298 template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin;
00299 template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin;
00300
00301
00302
00303
00304
00307
00308 template <unsigned N, unsigned D> struct faces_set_mixin;
00309
00310
00312 template <unsigned N, unsigned D>
00313 struct faces_set_mixin : public faces_set_mixin<N - 1, D>,
00314 public lower_dim_faces_set_mixin<N, D>,
00315 public higher_dim_faces_set_mixin<N, D>
00316 {
00317 std::vector< face_data<N, D> > faces_;
00318
00322 void print(std::ostream& ostr) const;
00325 void print_rec_asc(std::ostream& ostr) const;
00327
00332 template <typename BinaryFunction, typename T>
00333 T fold_left_(const BinaryFunction& f, const T& accu) const;
00336 template <typename UnaryFunction>
00337 typename UnaryFunction::result_type
00338 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
00340 };
00341
00343 template <unsigned D>
00344 struct faces_set_mixin<D, D> : public faces_set_mixin<D - 1, D>,
00345 public lower_dim_faces_set_mixin<D, D>
00346 {
00347 std::vector< face_data<D, D> > faces_;
00348
00352 void print(std::ostream& ostr) const;
00353 void print_rec_asc(std::ostream& ostr) const;
00355
00360 template <typename BinaryFunction, typename T>
00361 T fold_left_(const BinaryFunction& f, const T& accu) const;
00364 template <typename UnaryFunction>
00365 typename UnaryFunction::result_type
00366 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
00368 };
00369
00371 template <unsigned D>
00372 struct faces_set_mixin<0u, D> : public higher_dim_faces_set_mixin<0u, D>
00373 {
00374 std::vector< face_data<0u, D> > faces_;
00375
00379 void print(std::ostream& ostr) const;
00380 void print_rec_asc(std::ostream& ostr) const;
00382
00387 template <typename BinaryFunction, typename T>
00388 T fold_left_(const BinaryFunction& f, const T& accu) const;
00391 template <typename UnaryFunction>
00392 typename UnaryFunction::result_type
00393 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
00395 };
00396
00398 template <>
00399 struct faces_set_mixin<0u, 0u>
00400 {
00401 std::vector< face_data<0u, 0u> > faces_;
00402
00406 void print(std::ostream& ostr) const;
00407 void print_rec_asc(std::ostream& ostr) const;
00409
00414 template <typename BinaryFunction, typename T>
00415 T fold_left_(const BinaryFunction& f, const T& accu) const;
00418 template <typename UnaryFunction>
00419 typename UnaryFunction::result_type
00420 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
00422 };
00424
00425
00426
00427
00428
00429
00431 template <unsigned D>
00432 struct complex_data : public faces_set_mixin<D, D>
00433 {
00434
00435 };
00436
00437
00438
00439
00440
00441
00442
00445 template <unsigned N, unsigned D>
00446 struct lower_dim_faces_set_mixin
00447 {
00448 void print(std::ostream& ostr, const face_data<N, D>& f) const;
00449 };
00450
00451 template <unsigned N, unsigned D>
00452 struct higher_dim_faces_set_mixin
00453 {
00454 void print(std::ostream& ostr, const face_data<N, D>& f) const;
00455 };
00457
00458 }
00459
00460
00461
00462 # ifndef MLN_INCLUDE_ONLY
00463
00464
00465
00466
00467
00468 template <unsigned D>
00469 inline
00470 complex<D>::complex()
00471
00472 : data_(new internal::complex_data<D>())
00473 {
00474 }
00475
00476 template <unsigned D>
00477 inline
00478 n_face<0u, D>
00479 complex<D>::add_face()
00480 {
00481
00482
00483 data_->internal::faces_set_mixin<0u, D>::faces_.push_back(face_data<0u, D>());
00484 unsigned id = nfaces_of_static_dim<0u>() - 1;
00485 return n_face<0u, D>(*this, id);
00486 }
00487
00488 template <unsigned D>
00489 template <unsigned N>
00490 inline
00491 n_face<N + 1, D>
00492 complex<D>::add_face(const n_faces_set<N, D>& adjacent_faces)
00493 {
00494 typedef typename std::vector< algebraic_n_face<N, D> >::const_iterator
00495 iter_t;
00496
00497
00498 if (!HAS_NDEBUG)
00499 for (iter_t a = adjacent_faces.faces().begin();
00500 a != adjacent_faces.faces().end(); ++a)
00501 {
00502 mln_precondition(a->cplx() == *this);
00503 mln_precondition(a->is_valid());
00504 }
00505
00506 face_data<N + 1, D> f;
00507
00508
00509 data_->internal::faces_set_mixin<N + 1, D>::faces_.push_back(f);
00510 unsigned id = nfaces_of_static_dim<N + 1>() - 1;
00511
00512 n_face<N + 1, D> fh(*this, id);
00513
00514 for (iter_t a = adjacent_faces.faces().begin();
00515 a != adjacent_faces.faces().end(); ++a)
00516
00517
00518
00519
00520 connect_(*a, fh);
00521 return fh;
00522 }
00523
00524
00525
00526
00527
00528
00529 namespace internal
00530 {
00531
00540 struct add_size
00541 {
00542 template <typename T, typename Container>
00543 T operator()(const T& x, const Container& c) const
00544 {
00545 return x + c.size();
00546 }
00547 };
00548
00557 struct get_size
00558 {
00559 typedef std::size_t result_type;
00560
00561 template <typename Container>
00562 typename Container::size_type operator()(const Container& c) const
00563 {
00564 return c.size();
00565 }
00566 };
00567
00568 }
00569
00570
00571
00572
00573
00574
00575 template <unsigned D>
00576 inline
00577 unsigned
00578 complex<D>::nfaces() const
00579 {
00580 return fold_left_(internal::add_size(), 0);
00581 }
00582
00583 template <unsigned D>
00584 template <unsigned N>
00585 inline
00586 unsigned
00587 complex<D>::nfaces_of_static_dim() const
00588 {
00589 return data_->internal::faces_set_mixin<N, D>::faces_.size();
00590 }
00591
00592
00593
00594
00595
00596
00597 template <unsigned D>
00598 inline
00599 unsigned
00600 complex<D>::nfaces_of_dim(unsigned n) const
00601 {
00602
00603 mln_precondition(n <= D);
00604 return apply_if_dim_matches_(n, internal::get_size());
00605 }
00606
00607
00608
00609
00610
00611
00612 template <unsigned D>
00613 template <unsigned N>
00614 inline
00615 face_data<N, D>&
00616 complex<D>::face_data_(unsigned face_id)
00617 {
00618 return data_->internal::faces_set_mixin<N, D>::faces_[face_id];
00619 }
00620
00621 template <unsigned D>
00622 template <unsigned N>
00623 inline
00624 const face_data<N, D>&
00625 complex<D>::face_data_(unsigned face_id) const
00626 {
00627 return data_->internal::faces_set_mixin<N, D>::faces_[face_id];
00628 }
00629
00630 template <unsigned D>
00631 template <unsigned N>
00632 inline
00633 void
00634 complex<D>::connect_(const algebraic_n_face<N, D>& f1,
00635 const n_face<N + 1, D>& f2)
00636 {
00637
00638 metal::bool_< N <= D >::check();
00639
00640
00641
00642
00643
00644 f1.data().connect_higher_dim_face(make_algebraic_n_face(f2, f1.sign()));
00645 f2.data().connect_lower_dim_face(f1);
00646 }
00647
00648
00649
00650
00651
00652
00653 template <unsigned D>
00654 inline
00655 bool
00656 operator==(const complex<D>& lhs, const complex<D>& rhs)
00657 {
00658 return lhs.data_.ptr_ == rhs.data_.ptr_;
00659 }
00660
00661
00662
00663
00664
00665
00666 template <unsigned D>
00667 inline
00668 std::ostream&
00669 operator<<(std::ostream& ostr, const complex<D>& c)
00670 {
00671 c.print(ostr);
00672 return ostr;
00673 }
00674
00675 template <unsigned D>
00676 inline
00677 void
00678 complex<D>::print(std::ostream& ostr) const
00679 {
00680 data_->internal::faces_set_mixin<D, D>::print_rec_asc(ostr);
00681 }
00682
00683 template <unsigned D>
00684 template <unsigned N>
00685 inline
00686 void
00687 complex<D>::print_faces(std::ostream& ostr) const
00688 {
00689
00690 metal::bool_< N <= D >::check();
00691
00692 data_->internal::faces_set_mixin<N, D>::print(ostr);
00693 }
00694
00695 template <unsigned D>
00696 inline
00697 const void*
00698 complex<D>::addr() const
00699 {
00700 return data_.ptr_;
00701 }
00702
00703
00704 namespace internal
00705 {
00706
00707 template <unsigned N, unsigned D>
00708 inline
00709 void
00710 faces_set_mixin<N, D>::print_rec_asc(std::ostream& ostr) const
00711 {
00712 faces_set_mixin<N - 1, D>::print_rec_asc(ostr);
00713 print(ostr);
00714 }
00715
00716 template <unsigned D>
00717 inline
00718 void
00719 faces_set_mixin<0u, D>::print_rec_asc(std::ostream& ostr) const
00720 {
00721 print(ostr);
00722 }
00723
00724 template <unsigned D>
00725 inline
00726 void
00727 faces_set_mixin<D, D>::print_rec_asc(std::ostream& ostr) const
00728 {
00729 faces_set_mixin<D - 1, D>::print_rec_asc(ostr);
00730 print(ostr);
00731 }
00732
00733 inline
00734 void
00735 faces_set_mixin<0u, 0u>::print_rec_asc(std::ostream& ostr) const
00736 {
00737 print(ostr);
00738 }
00739
00740
00741 template <unsigned N, unsigned D>
00742 inline
00743 void
00744 faces_set_mixin<N, D>::print(std::ostream& ostr) const
00745 {
00746 ostr << "Faces of dimension " << N
00747 << " and their ajacent faces of dimension "
00748 << N - 1 << " and "
00749 << N + 1 << std::endl;
00750 for (unsigned f = 0; f < faces_.size(); ++f)
00751 {
00752 ostr << " " << f << ": dim " << N - 1 << ": { ";
00753 lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
00754 ostr << "}, dim " << N + 1 << ": { ";
00755 higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
00756 ostr << "}" << std::endl;
00757 }
00758 }
00759
00760 template <unsigned D>
00761 inline
00762 void
00763 faces_set_mixin<0u, D>::print(std::ostream& ostr) const
00764 {
00765 const unsigned N = 0u;
00766 ostr << "Faces of dimension " << N
00767 << " and their ajacent faces of dimension "
00768 << N + 1 << std::endl;
00769 for (unsigned f = 0; f < faces_.size(); ++f)
00770 {
00771 ostr << " " << f << ": dim " << N + 1 << ": { ";
00772 higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
00773 ostr << "}" << std::endl;
00774 }
00775 }
00776
00777 template <unsigned D>
00778 inline
00779 void
00780 faces_set_mixin<D, D>::print(std::ostream& ostr) const
00781 {
00782 const unsigned N = D;
00783 ostr << "Faces of dimension " << N
00784 << " and their ajacent faces of dimension "
00785 << N - 1 << std::endl;
00786 for (unsigned f = 0; f < faces_.size(); ++f)
00787 {
00788 ostr << " " << f << ": dim " << N - 1 << ": { ";
00789 lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
00790 ostr << "}" << std::endl;
00791 }
00792 }
00793
00794 inline
00795 void
00796 faces_set_mixin<0u, 0u>::print(std::ostream& ostr) const
00797 {
00798 const unsigned N = 0u;
00799 ostr << "Faces of dimension " << N << std::endl;
00800 for (unsigned f = 0; f < faces_.size(); ++f)
00801 ostr << " " << f << std::endl;
00802 }
00803
00804
00805 template <unsigned N, unsigned D>
00806 inline
00807 void
00808 lower_dim_faces_set_mixin<N, D>::print(std::ostream& ostr,
00809 const face_data<N, D>& f) const
00810 {
00811 for (typename std::vector< algebraic_n_face<N - 1, D> >::const_iterator l =
00812 f.lower_dim_faces_.begin(); l != f.lower_dim_faces_.end(); ++l)
00813 ostr << l->face_id() << " ";
00814 }
00815
00816 template <unsigned N, unsigned D>
00817 inline
00818 void
00819 higher_dim_faces_set_mixin<N, D>::print(std::ostream& ostr,
00820 const face_data<N, D>& f) const
00821 {
00822 for (typename std::vector< algebraic_n_face<N + 1, D> >::const_iterator h =
00823 f.higher_dim_faces_.begin(); h != f.higher_dim_faces_.end(); ++h)
00824 ostr << h->face_id() << " ";
00825 }
00826
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 template <unsigned D>
00839 template <typename BinaryFunction, typename T>
00840 inline
00841 T
00842 complex<D>::fold_left_(const BinaryFunction& f, const T& accu) const
00843 {
00844 return data_->internal::faces_set_mixin<D, D>::fold_left_(f, accu);
00845 }
00846
00847 namespace internal
00848 {
00849
00850
00851
00852 template <unsigned D>
00853 template <typename BinaryFunction, typename T>
00854 inline
00855 T
00856 faces_set_mixin<D, D>::fold_left_(const BinaryFunction& f,
00857 const T& accu) const
00858 {
00859 return faces_set_mixin<D - 1, D>::fold_left_(f, f(accu, faces_));
00860 }
00861
00862 template <unsigned N, unsigned D>
00863 template <typename BinaryFunction, typename T>
00864 inline
00865 T
00866 faces_set_mixin<N, D>::fold_left_(const BinaryFunction& f,
00867 const T& accu) const
00868 {
00869 return faces_set_mixin<N - 1, D>::fold_left_(f, f(accu, faces_));
00870 }
00871
00872 template <unsigned D>
00873 template <typename BinaryFunction, typename T>
00874 inline
00875 T
00876 faces_set_mixin<0u, D>::fold_left_(const BinaryFunction& f,
00877 const T& accu) const
00878 {
00879 return f(accu, faces_);
00880 }
00881
00882 template <typename BinaryFunction, typename T>
00883 inline
00884 T
00885 faces_set_mixin<0u, 0u>::fold_left_(const BinaryFunction& f,
00886 const T& accu) const
00887 {
00888 return f(accu, faces_);
00889 }
00890
00891 }
00892
00893
00894
00895
00896
00897
00898 template <unsigned D>
00899 template <typename UnaryFunction>
00900 inline
00901 typename UnaryFunction::result_type
00902 complex<D>::apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const
00903 {
00904
00905 mln_precondition(n <= D);
00906 return data_->internal::faces_set_mixin<D, D>::apply_if_dim_matches_(n, f);
00907 }
00908
00909 namespace internal
00910 {
00911
00912
00913
00914 template <unsigned D>
00915 template <typename UnaryFunction>
00916 inline
00917 typename UnaryFunction::result_type
00918 faces_set_mixin<D, D>::apply_if_dim_matches_(unsigned n,
00919 const UnaryFunction& f) const
00920 {
00921
00922 mln_precondition(n <= D);
00923 return n == D ?
00924 f(faces_) :
00925 faces_set_mixin<D - 1, D>::apply_if_dim_matches_(n, f);
00926 }
00927
00928 template <unsigned N, unsigned D>
00929 template <typename UnaryFunction>
00930 inline
00931 typename UnaryFunction::result_type
00932 faces_set_mixin<N, D>::apply_if_dim_matches_(unsigned n,
00933 const UnaryFunction& f) const
00934 {
00935
00936 mln_precondition(n <= D);
00937 return n == N ?
00938 f(faces_) :
00939 faces_set_mixin<N - 1, D>::apply_if_dim_matches_(n, f);
00940 }
00941
00942 template <unsigned D>
00943 template <typename UnaryFunction>
00944 inline
00945 typename UnaryFunction::result_type
00946 faces_set_mixin<0u, D>::apply_if_dim_matches_(unsigned n,
00947 const UnaryFunction& f) const
00948 {
00949
00950 mln_precondition(n == 0);
00951
00952 (void) n;
00953 return f(faces_);
00954 }
00955
00956 template <typename UnaryFunction>
00957 inline
00958 typename UnaryFunction::result_type
00959 faces_set_mixin<0u, 0u>::apply_if_dim_matches_(unsigned n,
00960 const UnaryFunction& f) const
00961 {
00962
00963 mln_precondition(n == 0);
00964 return f(faces_);
00965 }
00966
00967 }
00968
00969 # endif // ! MLN_INCLUDE_ONLY
00970
00971 }
00972
00973 }
00974
00975 #endif // ! MLN_TOPO_COMPLEX_HH