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