diff --git a/Combinatorial_map/doc/Combinatorial_map/Concepts/CombinatorialMap.h b/Combinatorial_map/doc/Combinatorial_map/Concepts/CombinatorialMap.h index e68ed221ad6..92d535099da 100644 --- a/Combinatorial_map/doc/Combinatorial_map/Concepts/CombinatorialMap.h +++ b/Combinatorial_map/doc/Combinatorial_map/Concepts/CombinatorialMap.h @@ -19,6 +19,13 @@ public: */ CombinatorialMap(); +/*! +Construct a new combinatorial map from another one. +The new combinatorial map is created by copying the darts and the non void attributes of cmap. CMap must be a model of `CombinatorialMap` concept, which can be defined with a different dimension and/or different attributes than `*this`. In this case, only permutations that are common to `cmap` and `*this`, and only non void i-attributes of `cmap` whose info type is the same to the info of non void i-attributes of `*this`, are copied. +*/ +template +CombinatorialMap cm(const CMap& cmap); + /// @} /// \name Types @@ -521,6 +528,18 @@ Deletes all the darts and all the attributes of the combinatorial map. */ void clear(); +/*! +Assignment operator. +All darts and attributes are duplicated, and the former combinatorial map is deleted. +*/ +CombinatorialMap& operator= (const CombinatorialMap& cmap); + +/*! +Swap the current combinatorial map with `cmap`. +There is no copy of darts and attributes thus this method runs in constant time. +*/ +void swap(CombinatorialMap& cmap); + /// @} /// \name Operations diff --git a/Combinatorial_map/include/CGAL/Cell_attribute.h b/Combinatorial_map/include/CGAL/Cell_attribute.h index 153c4f643a1..269b40cc72b 100644 --- a/Combinatorial_map/include/CGAL/Cell_attribute.h +++ b/Combinatorial_map/include/CGAL/Cell_attribute.h @@ -60,26 +60,26 @@ namespace CGAL { /// Cell_attribute_without_info template class Cell_attribute_without_info; // Cell_attribute_without_info without dart support. template - class Cell_attribute_without_info { template < unsigned int d_, class Refs_, class Items_, class Alloc_ > friend class Combinatorial_map_base; - + template friend struct Dart; template < unsigned int d_, class Refs_, - class Items_, class Alloc_ > + class Items_, class Alloc_ > friend class Generalized_map_base; - + template friend struct GMap_dart; @@ -101,7 +101,7 @@ namespace CGAL { /// operator = /// We do nothing since we must not copy mrefcounting. - Cell_attribute_without_info& + Cell_attribute_without_info& operator=(const Cell_attribute_without_info& /*acell*/) { return *this; } @@ -119,7 +119,13 @@ namespace CGAL { bool is_valid() const { return true; } - protected: + bool operator==(const Cell_attribute_without_info&) const + { return true; } + + bool operator!=(const Cell_attribute_without_info& other) const + { return !operator==(other); } + + // protected: /// Contructor without parameter. Cell_attribute_without_info(): mrefcounting(0) {} @@ -129,6 +135,7 @@ namespace CGAL { mrefcounting(0) {} + protected: /// Increment the reference counting. void inc_nb_refs() { mrefcounting+=4; } // 4 because this is the 3rd bit (ie 1<<2) @@ -145,9 +152,9 @@ namespace CGAL { unsigned int get_nb_refs() const { return (mrefcounting>>2); } // >>2 to ignore the 2 least significant bits - void * for_compact_container() const + void * for_compact_container() const { return vp; } - void * & for_compact_container() + void * & for_compact_container() { return vp; } private: @@ -165,7 +172,7 @@ namespace CGAL { * The refs class must provide the type of Combinatorial_map used. */ template - class Cell_attribute_without_info { template < unsigned int d_, class Refs_, @@ -176,7 +183,7 @@ namespace CGAL { friend struct Dart; template < unsigned int d_, class Refs_, - class Items_, class Alloc_ > + class Items_, class Alloc_ > friend class Generalized_map_base; template @@ -194,17 +201,17 @@ namespace CGAL { typedef typename Refs::Dart_handle Dart_handle; typedef typename Refs::Dart_const_handle Dart_const_handle; typedef typename Refs::Alloc Alloc; - + typedef OnMerge On_merge; typedef OnSplit On_split; /// operator = /// We must not copy mrefcounting. - Cell_attribute_without_info& + Cell_attribute_without_info& operator=(const Cell_attribute_without_info& acell) { mdart = acell.mdart; - return *this; + return *this; } /// Get the dart associated with the cell. @@ -221,7 +228,13 @@ namespace CGAL { bool is_valid() const { return mdart!=NULL; } - protected: + bool operator==(const Cell_attribute_without_info&) const + { return true; } + + bool operator!=(const Cell_attribute_without_info& other) const + { return !operator==(other); } + + // protected: /// Contructor without parameter. Cell_attribute_without_info() : mdart(NULL), mrefcounting(0) @@ -233,6 +246,7 @@ namespace CGAL { mrefcounting(0) {} + protected: /// Increment the reference counting. void inc_nb_refs() { ++mrefcounting; } @@ -241,7 +255,7 @@ namespace CGAL { void dec_nb_refs() { CGAL_assertion( mrefcounting>0 ); - --mrefcounting; + --mrefcounting; } public: @@ -251,36 +265,36 @@ namespace CGAL { void * for_compact_container() const { return mdart.for_compact_container(); } - void * & for_compact_container() + void * & for_compact_container() { return mdart.for_compact_container(); } private: /// The dart handle associated with the cell. Dart_handle mdart; - + /// Reference counting: the number of darts linked to this cell. unsigned int mrefcounting; }; - /// Cell associated with an attribute, with or without info depending + /// Cell associated with an attribute, with or without info depending /// if Info==void. - template class Cell_attribute; - + /// Specialization when Info==void. - template - class Cell_attribute : - public Cell_attribute_without_info : + public Cell_attribute_without_info { template < unsigned int d_, class Refs_, class Items_, class Alloc_ > friend class Combinatorial_map_base; - + template friend class Compact_container; @@ -291,8 +305,14 @@ namespace CGAL { typedef typename Refs::Alloc Alloc; typedef OnMerge On_merge; typedef OnSplit On_split; + typedef void Info; + + // protected: + /// Default contructor. + Cell_attribute() + {} }; - + /// Specialization when Info!=void. template friend class Combinatorial_map_base; - + template friend class Compact_container; public: + typedef Cell_attribute Self; + typedef Tag_ Supports_cell_dart; typedef typename Refs::Dart_handle Dart_handle; typedef typename Refs::Dart_const_handle Dart_const_handle; @@ -318,13 +340,21 @@ namespace CGAL { typedef OnSplit On_split; typedef Info_ Info; - protected: + bool operator==(const Self& other) const + { return this->info()==other.info(); } + + bool operator!=(const Self& other) const + { return !operator==(other); } + + + // protected: /// Default contructor. Cell_attribute() {} - /// Contructor with an attribute in parameter. - Cell_attribute(const Info_& ainfo) : Info_for_cell_attribute(ainfo) + /// Contructor with an info in parameter. + Cell_attribute(const Info_& ainfo) : + Info_for_cell_attribute(ainfo) {} }; diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index a3a1cc76914..41ff65f3845 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -24,12 +24,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -60,6 +62,9 @@ namespace CGAL { friend struct CGAL::internal::Call_split_functor; public: + template < unsigned int A, class B, class I, class D > + friend class Combinatorial_map_base; + /// Types definition typedef Combinatorial_map_base Self; @@ -148,6 +153,168 @@ namespace CGAL { CGAL_assertion(number_of_darts()==0); } + /** Copy the given combinatorial map into *this. + * Note that both CMap can have different dimensions and/or non void attributes. + * @param amap the combinatorial map to copy. + * @post *this is valid. + */ + template + void copy(const CMap2& amap, const Converters& converters, + const Pointconverter& pointconverter) + { + this->clear(); + + this->mnb_used_marks = amap.mnb_used_marks; + this->mmask_marks = amap.mmask_marks; + + for (size_type i = 0; i < NB_MARKS; ++i) + { + this->mfree_marks_stack[i] = amap.mfree_marks_stack[i]; + this->mindex_marks[i] = amap.mindex_marks[i]; + this->mnb_marked_darts[i] = amap.mnb_marked_darts[i]; + this->mnb_times_reserved_marks[i] = amap.mnb_times_reserved_marks[i]; + } + + // We must do this ony once, but problem because null_dart_handle + // is static ! + if (mnull_dart_container.empty()) + { + null_dart_handle = + mnull_dart_container.emplace(amap.null_dart_handle->mmarks); + + for (unsigned int i = 0; i <= dimension; ++i) + { + null_dart_handle->unlink_beta(i); + } + } + else + null_dart_handle->mmarks = amap.null_dart_handle->mmarks; + + // Create an mapping between darts of the two maps (originals->copies). + std::map dartmap; + + for (typename CMap2::Dart_const_range::const_iterator + it=amap.darts().begin(), itend=amap.darts().end(); + it!=itend; ++it) + { + dartmap[it]=mdarts.emplace(it->mmarks); + } + + unsigned int min_dim= + (dimension + ::iterator dartmap_iter, dartmap_iter_end=dartmap.end(); + for (dartmap_iter=dartmap.begin(); dartmap_iter!=dartmap_iter_end; + ++dartmap_iter) + { + for (unsigned int i=0; i<=min_dim; i++) + { + if (dartmap_iter->first->beta(i)!=CMap2::null_dart_handle && + (dartmap_iter->first)<(dartmap_iter->first->beta(i))) + { + basic_link_beta(dartmap_iter->second, + dartmap[dartmap_iter->first->beta(i)], i); + } + } + } + + /** Copy attributes */ + for (dartmap_iter=dartmap.begin(); dartmap_iter!=dartmap_iter_end; + ++dartmap_iter) + { + Helper::template Foreach_enabled_attributes + < internal::Copy_attributes_functor >:: + run(&amap, static_cast(this), + dartmap_iter->first, dartmap_iter->second, + converters, pointconverter); + } + + CGAL_assertion (is_valid () == 1); + } + + template + void copy(const CMap2& amap) + { + CGAL::cpp11::tuple<> converters; + Default_converter_cmap_0attributes_with_point pointconverter; + return copy< CMap2, CGAL::cpp11::tuple<>, + Default_converter_cmap_0attributes_with_point > + (amap, converters, pointconverter); + } + + template + void copy(const CMap2& amap, const Converters& converters) + { + Default_converter_cmap_0attributes_with_point pointconverter; + return copy< CMap2, Converters, + Default_converter_cmap_0attributes_with_point > + (amap, converters, pointconverter); + } + + // Copy constructor from a map having exactly the same type. + Combinatorial_map_base (const Self & amap) + { copy(amap); } + + // "Copy constructor" from a map having different type. + template + Combinatorial_map_base(const CMap2& amap) + { copy(amap); } + + // "Copy constructor" from a map having different type. + template + Combinatorial_map_base(const CMap2& amap, Converters& converters) + { copy(amap, converters); } + + // "Copy constructor" from a map having different type. + template + Combinatorial_map_base(const CMap2& amap, Converters& converters, + const Pointconverter& pointconverter) + { copy + (amap, converters, pointconverter); } + + /** Affectation operation. Copies one map to the other. + * @param amap a combinatorial map. + * @return A copy of that combinatorial map. + */ + Self & operator= (const Self & amap) + { + if (this!=&amap) + { + Self tmp(amap); + this->swap(tmp); + } + return *this; + } + + /** Swap this combinatorial map with amap, a second combinatorial map. + * Note that the two maps have exactly the same type. + * @param amap a combinatorial map. + */ + void swap(Self & amap) + { + if (this!=&amap) + { + amap.mdarts.swap(mdarts); + + std::swap_ranges(mnb_times_reserved_marks, + mnb_times_reserved_marks+NB_MARKS, + amap.mnb_times_reserved_marks); + std::swap(mmask_marks,amap.mmask_marks); + std::swap(mnb_used_marks, amap.mnb_used_marks); + std::swap_ranges(mindex_marks,mindex_marks+NB_MARKS, + amap.mindex_marks); + std::swap_ranges(mfree_marks_stack, mfree_marks_stack+NB_MARKS, + amap.mfree_marks_stack); + std::swap_ranges(mused_marks_stack,mused_marks_stack+NB_MARKS, + amap.mused_marks_stack); + std::swap_ranges(mnb_marked_darts,mnb_marked_darts+NB_MARKS, + amap.mnb_marked_darts); + mattribute_containers.swap(amap.mattribute_containers); + } + } + /** Clear the combinatorial map. Remove all darts and all attributes. * Note that reserved marks are not free. */ @@ -3081,6 +3248,212 @@ namespace CGAL { return res; } + + /** Test if the connected component of cmap containing dart dh1 is + * isomorphic to the connected component of map2 containing dart dh2, + * starting from dh1 and dh2. + * @param dh1 initial dart for this map + * @param map2 the second combinatorial map + * @param dh2 initial dart for map2 + * @param testAttributes Boolean to test the equality of attributes (true) + * or not (false) + * @return true iff the cc of map is isomorphic to the cc of map2 starting + * from dh1 and dh2; by testing the equality of attributes if + * testAttributes is true + */ + template + bool are_cc_isomorphic(Dart_const_handle dh1, + const Combinatorial_map_base + & map2, + typename Combinatorial_map_base + ::Dart_const_handle dh2, + bool testAttributes=true) const + { + // CGAL_assertion(dimension==map2.dimension); + CGAL_assertion(dh1!=NULL && dh2!=NULL); + + typedef Combinatorial_map_base Map2; + + bool match = true; + + // Two stacks used to run through the two maps. + std::deque< Dart_const_handle > toTreat1; + std::deque< typename Map2::Dart_const_handle > toTreat2; + + int m1 = get_new_mark(); + int m2 = map2.get_new_mark(); + + toTreat1.push_back(dh1); + toTreat2.push_back(dh2); + + Dart_const_handle current; + typename Map2::Dart_const_handle other; + + unsigned int i = 0; + CGAL::Unique_hash_map bijection; + + while (match && !toTreat1.empty()) + { + // Next dart + current = toTreat1.front(); + toTreat1.pop_front(); + other = toTreat2.front(); + toTreat2.pop_front(); + + if (!is_marked(current, m1)) + { + if (map2.is_marked(other, m2)) + match=false; + else + { + bijection[current] = other; + + mark(current, m1); + map2.mark(other, m2); + + if (testAttributes) + { + // We need to test in both direction because + // Foreach_enabled_attributes only test non void attributes + // of Self. + Helper::template Foreach_enabled_attributes + < internal::Test_is_same_attribute_functor >:: + run(current, other); + Map2::Helper::template Foreach_enabled_attributes + < internal::Test_is_same_attribute_functor >:: + run(other, current); + if ( !internal::Test_is_same_attribute_functor:: + value || + !internal::Test_is_same_attribute_functor:: + value ) + match=false; + } + + // We test if the injection is valid with its neighboors. + // We go out as soon as it is not satisfied. + for (i = 0; match && i <= dimension; ++i) + { + if ( i>map2.dimension ) + { + if (!current->is_free(i)) match=false; + } + else + { + if (current->is_free(i)) + { + if (!other->is_free(i)) + match = false; + } + else + { + if (other->is_free(i)) + match = false; + else + { + if (is_marked(current->beta (i), m1) != + map2.is_marked(other->beta(i), m2)) + match = false; + else + { + if (!is_marked (current->beta(i), m1)) + { + toTreat1.push_back(current->beta (i)); + toTreat2.push_back(other->beta (i)); + } + else + { + if (bijection[current->beta(i)] != + other->beta(i)) + match = false; + } + } + } + } + } + } + // Now we test if the second map has more beta links than the first + for ( i=dimension+1; match && i<=map2.dimension; ++i ) + { + if (!other->is_free(i)) match=false; + } + } + } + else + { + if (!map2.is_marked(other, m2)) + match = false; + } + } + + // Here we test if both queue are empty + if ( !toTreat1.empty() || !toTreat2.empty() ) match = false; + + // Here we unmark all the marked darts. + toTreat1.clear(); + toTreat2.clear(); + + toTreat1.push_back(dh1); + toTreat2.push_back(dh2); + + while (!toTreat1.empty()) + { + current = toTreat1.front(); + toTreat1.pop_front(); + other = toTreat2.front(); + toTreat2.pop_front(); + + unmark(current, m1); + map2.unmark(other, m2); + + for (i = 0; match && i <= dimension; ++i) + { + if (!current->is_free(i) && is_marked(current->beta(i), m1)) + { + CGAL_assertion(!other->is_free(i) && + map2.is_marked(other->beta(i), m2)); + toTreat1.push_back(current->beta(i)); + toTreat2.push_back(other->beta(i)); + } + } + } + + free_mark(m1); + map2.free_mark(m2); + + return match; + } + + /** Test if this cmap is isomorphic to map2. + * @pre cmap is connected. + * @param map2 the second combinatorial map + * @param testAttributes Boolean to test the equality of attributes (true) + * or not (false) + * @return true iff this map is isomorphic to map2, testing the equality + * of attributes if testAttributes is true + */ + template + bool is_isomorphic_to(const Combinatorial_map_base + & map2, + bool testAttributes=true) + { + // if ( dimension!=map2.dimension ) return false; + + Dart_const_handle d1=darts().begin(); + + for (typename Combinatorial_map_base:: + Dart_range::const_iterator it(map2.darts().begin()), + itend(map2.darts().end()); it!=itend; ++it) + { + if (are_cc_isomorphic(d1, map2, it, testAttributes)) + { + return true; + } + } + + return false; + } + /// Void dart. A dart d is i-free if beta_i(d)=null_dart_handle. static Dart_handle null_dart_handle; @@ -3149,6 +3522,27 @@ namespace CGAL { typedef typename Base::Dart_handle Dart_handle; typedef typename Base::Dart_const_handle Dart_const_handle; typedef typename Base::Alloc Alloc; + + Combinatorial_map() : Base() + {} + + Combinatorial_map(const Self & amap) + { Base::template copy(amap); } + + template < class CMap > + Combinatorial_map(const CMap & amap) + { Base::template copy(amap); } + + template < class CMap, typename Converters > + Combinatorial_map(const CMap & amap, const Converters& converters) + { Base::template copy + (amap, converters); } + + template < class CMap, typename Converters, typename Pointconverter > + Combinatorial_map(const CMap & amap, const Converters& converters, + const Pointconverter& pointconverter) + { Base::template copy + (amap, converters, pointconverter); } }; } // namespace CGAL diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_copy_functors.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_copy_functors.h new file mode 100644 index 00000000000..97555704599 --- /dev/null +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_copy_functors.h @@ -0,0 +1,415 @@ +// Copyright (c) 2010-2013 CNRS and LIRIS' Establishments (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Guillaume Damiand +// +#ifndef CGAL_COMBINATORIAL_MAP_COPY_FUNCTORS_H +#define CGAL_COMBINATORIAL_MAP_COPY_FUNCTORS_H + +#include +#include +#include +#include +#include + +/* Definition of functors used internally to copy combinatorial maps attributes + * (we need functors as attributes are stored in tuple, thus all the access + * must be done at compiling time). + */ +namespace CGAL +{ +template< typename Map1, typename Map2, unsigned int i> +struct Default_converter_cmap_attributes; +template< typename Map1, typename Map2> +struct Default_converter_cmap_0attributes_with_point; +// **************************************************************************** +namespace internal +{ +// **************************************************************************** +// Map1 is the existing map, to convert into map2. +// Functor called only when both i-attributes have non void info. +// General cases when both info are differents. +template< typename Map1, typename Map2, unsigned int i, + typename Info1=typename Map1::template + Attribute_type::type::Info, + typename Info2=typename Map2::template + Attribute_type::type::Info > +struct Create_attribute_if_same_info_cmap +{ + static typename Map2::template Attribute_handle::type + run(Map2&, typename Map1::template Attribute_const_handle::type) + { return NULL; } +}; + +// Special case when both attributes have the same info. +template< typename Map1, typename Map2, unsigned int i, typename Info > +struct Create_attribute_if_same_info_cmap +{ + static typename Map2::template Attribute_handle::type + run(Map2& map2, typename Map1::template Attribute_const_handle::type ah) + { + CGAL_assertion( ah!=NULL ); + typename Map2::template Attribute_handle::type + res = map2.template create_attribute(); + res->info() = ah->info(); + return res; + } +}; +// **************************************************************************** +// Functor allowing to set the value of a point if point exist, have +// same dimension. For dim>3, if type of points are the same +// (because no converter). +template::type, + typename T2=typename Ambient_dimension::type> +struct Set_point_if_possible_cmap +{ + static void run(const Point1&, Point2&) + {} +}; + +template +struct Set_point_if_possible_cmap, Dimension_tag<2> > +{ + static void run(const Point1& p1, Point2& p2) + { + p2 = Cartesian_converter::Kernel, + typename Kernel_traits::Kernel>(p1); + } +}; + +template +struct Set_point_if_possible_cmap, Dimension_tag<2> > +{ + static void run(const Point1& p1, Point1& p2) + { + p2 = p1; + } +}; + +template +struct Set_point_if_possible_cmap, Dimension_tag<3> > +{ + static void run(const Point1& p1, Point2& p2) + { + p2 = Cartesian_converter::Kernel, + typename Kernel_traits::Kernel>()(p1); + } +}; + +template +struct Set_point_if_possible_cmap, Dimension_tag<3> > +{ + static void run(const Point1& p1, Point1& p2) + { + p2 = p1; + } +}; + +template +struct Set_point_if_possible_cmap +{ + static void run(const Point1& p1, Point1& p2) + { + p2 = p1; + } +}; +// **************************************************************************** +// Get the ith functor of the converters tuple if i=My_length::value)> +struct Get_convert_attribute_functor +{ + static typename Map2::template Attribute_handle::type + run( const Map1* cmap1, Map2* cmap2, typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, const Converters& converters) + { + return + CGAL::Default_converter_cmap_attributes() + (*cmap1, *cmap2, dh1, dh2); + } +}; + +template +struct Get_convert_attribute_functor +{ + static typename Map2::template Attribute_handle::type + run( const Map1* cmap1, Map2* cmap2, typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, const Converters& converters) + { + return CGAL::cpp11::get(converters) (*cmap1, *cmap2, dh1, dh2); + } +}; +// **************************************************************************** +// Call a given functor if both i-attribute have an non void info +template< typename Map1, typename Map2, unsigned int i, + typename Converters, + bool Withinfo1=CGAL::internal::template + Is_attribute_has_non_void_info + ::type>::value, + bool Withinfo2=CGAL::internal::template + Is_attribute_has_non_void_info + ::type>::value > +struct Call_functor_if_both_attributes_have_info +{ + static typename Map2::template Attribute_handle::type + run( const Map1*, + Map2*, + typename Map1::Dart_const_handle, + typename Map2::Dart_handle, + const Converters&) + { return NULL; } +}; + +template< typename Map1, typename Map2, unsigned int i, typename Converters > +struct Call_functor_if_both_attributes_have_info +{ + static typename Map2::template Attribute_handle::type + run( const Map1* cmap1, + Map2* cmap2, + typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, + const Converters& converters ) + { + return Get_convert_attribute_functor:: + run(cmap1, cmap2, dh1, dh2, converters); + } +}; +// **************************************************************************** +// Call a given functor only if both 0-attribute have a point. +// general case i!=0 or one attribute without point. +template< typename Map1, typename Map2, unsigned int i, + typename Pointconverter, + bool Withpoint1=CGAL::internal::template Is_attribute_has_point + ::type>::value, + bool Withpoint2=CGAL::internal::template Is_attribute_has_point + ::type>::value > +struct Call_functor_if_both_attributes_have_point +{ + static typename Map2::template Attribute_handle::type + run( const Map1*, + Map2*, + typename Map1::Dart_const_handle, + typename Map2::Dart_handle, + const Pointconverter&) + { return NULL; } +}; +// Specialisation with i==0 and both attributes have points. +template< typename Map1, typename Map2, typename Pointconverter > +struct Call_functor_if_both_attributes_have_point +{ + static typename Map2::template Attribute_handle<0>::type + run( const Map1* cmap1, + Map2* cmap2, + typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, + const Pointconverter& pointconverter ) + { return pointconverter(*cmap1, *cmap2, dh1, dh2); } +}; +// **************************************************************************** +// Copy attribute when if both i-attributes are non void. +// (note Attr2 could not be Void as copy functor is called only for +// non void attributes) +// General case with both attributes non void. +template::type, + typename Attr2=typename Map2::template Attribute_type::type > +struct Copy_attribute_functor_if_nonvoid +{ + static void run( const Map1* cmap1, + Map2* cmap2, + typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, + const Converters& converters, + const Pointconverter& pointconverter) + { + // If dh1 has no i-attribute, nothing to copy. + if ( dh1->template attribute()==NULL ) return; + + // If dh2 has already an i-attribute, it was already copied. + if ( dh2->template attribute()!=NULL ) return; + + // Otherwise we copy the info if both attribute have non void info. + typename Map2::template Attribute_handle::type + res=Call_functor_if_both_attributes_have_info + :: + run(cmap1, cmap2, dh1, dh2, converters); + + if ( res!=NULL ) + cmap2->template set_attribute(dh2, res); + + // And the point if both attributes have points (and only for 0-attributes) + res=Call_functor_if_both_attributes_have_point + :: + run(cmap1, cmap2, dh1, dh2, pointconverter); + + if ( res!=NULL && dh2->template attribute()==NULL ) + cmap2->template set_attribute(dh2, res); + } +}; +// Specialisation when attr1 is void, and attr2 is non void i==0. Nothing to +// copy, but if 0-attributes has point and i==0, we need to create +// vertex attributes. +template +struct Copy_attribute_functor_if_nonvoid +{ + static void run( const Map1*, + Map2* cmap2, + typename Map1::Dart_const_handle, + typename Map2::Dart_handle dh2, + const Converters&, + const Pointconverter&) + { + // If dh2 has already an 0-attribute, it was already created. + if ( dh2->template attribute<0>()!=NULL ) return; + + // Create the point if 0-attributes has Point. + if ( CGAL::internal::template Is_attribute_has_point + ::type>::value ) + cmap2->template + set_attribute<0>(dh2, cmap2->template create_attribute<0>()); + } +}; +// Specialisation when attr1 is void, and attr2 is non void i!=0. +// Nothing to do. +template +struct Copy_attribute_functor_if_nonvoid +{ + static void run( const Map1*, + Map2*, + typename Map1::Dart_const_handle, + typename Map2::Dart_handle, + const Converters&, + const Pointconverter&) + {} +}; +// **************************************************************************** +/// Copy enabled attributes from one cmap to other. General case called +/// by copy function in Combinatorial_map on all the non void attributes +/// of Map2. Map1 is the existing map, to convert into map2. +template +struct Copy_attributes_functor +{ + template + static void run( const Map1* cmap1, + Map2* cmap2, + typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2, + const Converters& converters, + const Pointconverter& pointconverter) + { Copy_attribute_functor_if_nonvoid + :: + run(cmap1, cmap2, dh1, dh2, converters, pointconverter); + } +}; +// **************************************************************************** +} // namespace internal +// **************************************************************************** +// "Converters" called during the copy of attributes, to copy Info. +// Users can replace them by their own converters. +// Info converter are called only if both i-attributes have non void info, +// if dh1 has an i-attribute and if dh2 does not already has an i-attribute. +// Map1 is the existing map, to convert into map2. +// **************************************************************************** +// Default converter copy only attributes if they have same info types. +template< typename Map1, typename Map2, unsigned int i> +struct Default_converter_cmap_attributes +{ + typename Map2::template Attribute_handle::type operator() + (const Map1&, Map2& map2, typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2) const + { + CGAL_assertion( dh1->template attribute()!=NULL ); + CGAL_assertion( dh2->template attribute()==NULL ); + return internal::Create_attribute_if_same_info_cmap + :: + run(map2, dh1->template attribute()); + } +}; +// **************************************************************************** +// Cast converter always copy attributes, doing a cast. This can work only +// if both types are convertible and this is user responsability +// to use it only in this case. +template< typename Map1, typename Map2, unsigned int i> +struct Cast_converter_cmap_attributes +{ + typename Map2::template Attribute_handle::type operator() + (const Map1&, Map2& map2, typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2) const + { + CGAL_assertion( dh1->template attribute()!=NULL ); + CGAL_assertion( dh2->template attribute()==NULL ); + typename Map2::template Attribute_handle::type + res = map2.template create_attribute(); + res->info() = (typename Map2::template Attribute_type::type::Info) + dh1->template attribute()->info(); + return res; + } +}; +// **************************************************************************** +// "Converters" called during the copy of attributes, to copy Point (for +// attributes having such type defined). +// Users can replace them by their own converters. +// Point converter is called after Info converters; thus it is possible that +// attribute<0> was already created for dh2. +// Point converter is only called if both types of 0-attributes have +// Point type defined, and if dh1 has a 0-attribute. +// Map1 is the existing map, to convert into map2. +// **************************************************************************** +// Default converter for points. Point are copied only if they have same +// types, or in 2D/3D we use Cartesian_converter. +template< typename Map1, typename Map2> +struct Default_converter_cmap_0attributes_with_point +{ + typename Map2::template Attribute_handle<0>::type operator() + (const Map1&, Map2& map2, typename Map1::Dart_const_handle dh1, + typename Map2::Dart_handle dh2) const + { + CGAL_assertion( dh1->template attribute<0>()!=NULL ); + + typename Map2::template Attribute_handle<0>::type + res = dh2->template attribute<0>(); + if ( res==NULL ) + { + res = map2.template create_attribute<0>(); + } + internal::Set_point_if_possible_cmap + ::type::Point, + typename Map2::template Attribute_type<0>::type::Point>:: + run(dh1->template attribute<0>()->point(), + res->point()); + return res; + } +}; +// **************************************************************************** +} // namespace CGAL + +#endif // CGAL_COMBINATORIAL_MAP_COPY_FUNCTORS_H diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h index bc4a38dd3d4..6f4e5b923f9 100644 --- a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h @@ -22,7 +22,10 @@ #include #include +#include +#include #include +#include /* Definition of functors used internally to manage attributes (we need * functors as attributes are stored in tuple, thus all the access must be @@ -58,6 +61,15 @@ * * internal::Set_i_attribute_of_dart_functor to set the i-attribute * of a given dart. + * + * internal::Test_is_same_attribute_functor to test if two + * i-attributes of two darts are isomorphic. + * + * internal::Is_attribute_has_non_void_info to test if the attribute + * Attr is non Void and has an non void Info as inner type + * + * internal::Is_attribute_has_point to test if the attribute + * Attr is non Void and has a Point inner type */ namespace CGAL @@ -413,6 +425,254 @@ struct Set_i_attribute_of_dart_functor {} }; // **************************************************************************** +// Functor allowing to test if two info are the same or not +template< typename Attr1, typename Attr2, + typename Info1=typename Attr1::Info, + typename Info2=typename Attr2::Info > +struct Is_same_info +{ + static bool run(const Attr1&, const Attr2&) + { return false; } +}; + +template< typename Attr1, typename Attr2, typename Info1 > +struct Is_same_info +{ + static bool run(const Attr1&, const Attr2&) + { return false; } +}; + +template< typename Attr1, typename Attr2, typename Info2 > +struct Is_same_info +{ + static bool run(const Attr1&, const Attr2&) + { return false; } +}; + +template< typename Attr1, typename Attr2 > +struct Is_same_info +{ + static bool run(const Attr1&, const Attr2&) + { return true; } +}; + +template< typename Attr1, typename Attr2, typename Info > +struct Is_same_info +{ + static bool run(const Attr1&a1, const Attr2&a2) + { return a1.info()==a2.info(); } +}; + +// Case of two non void type +template +struct Is_same_attribute_info_functor +{ + static bool run(typename Map1::Dart_const_handle dh1, + typename Map2::Dart_const_handle dh2) + { + if (dh1->template attribute()==NULL && + dh2->template attribute()==NULL) + return true; + + if (dh1->template attribute()==NULL || + dh2->template attribute()==NULL) + return false; + + return + Is_same_info::run(*(dh1->template attribute()), + *(dh2->template attribute())); + } +}; + +// Case T1==void +template +struct Is_same_attribute_info_functor +{ + static bool run(typename Map1::Dart_const_handle, + typename Map2::Dart_const_handle dh2) + { + return dh2->template attribute()==NULL || + Is_same_info:: + run(0, *(dh2->template attribute())); + } +}; + +// Case T2==void +template +struct Is_same_attribute_info_functor +{ + static bool run(typename Map1::Dart_const_handle dh1, + typename Map2::Dart_const_handle) + { + return dh1->template attribute()==NULL || + Is_same_info:: + run(*(dh1->template attribute()), 0); + } +}; + +// Case T1==T2==void +template +struct Is_same_attribute_info_functor +{ + static bool run(typename Map1::Dart_const_handle, + typename Map2::Dart_const_handle) + { return true; } +}; + +// **************************************************************************** +// Functor allowing to test if two points are the same or not. +// Here we know both attributes have points. +template< typename Attr1, typename Attr2, + typename Point1=typename Attr1::Point, + typename Point2=typename Attr2::Point, + typename T1=typename Ambient_dimension::type > +struct Is_same_point +{ + static bool run(const Attr1&, const Attr2&) + { return false; } +}; + +template< typename Attr1, typename Attr2, typename Point> +struct Is_same_point > +{ + static bool run(const Attr1& a1, const Attr2& a2) + { return typename Kernel_traits::Kernel::Equal_2() + (a1.point(),a2.point()); } +}; + +template< typename Attr1, typename Attr2, typename Point> +struct Is_same_point > +{ + static bool run(const Attr1& a1, const Attr2& a2) + { return typename Kernel_traits::Kernel::Equal_3() + (a1.point(),a2.point()); } +}; + +template< typename Attr1, typename Attr2, typename Point> +struct Is_same_point +{ + static bool run(const Attr1& a1, const Attr2& a2) + { return typename Kernel_traits::Kernel::Equal_d() + (a1.point(),a2.point()); } +}; + +// Case of two non void type, with two points +template +struct Is_same_attribute_point_functor +{ + static bool run(typename Map1::Dart_const_handle dh1, + typename Map2::Dart_const_handle dh2) + { + CGAL_static_assertion( Withpoint1==true && Withpoint2==true ); + if (dh1->template attribute()==NULL && + dh2->template attribute()==NULL) + return true; + + if (dh1->template attribute()==NULL || + dh2->template attribute()==NULL) + return false; + + return + Is_same_point::run(*(dh1->template attribute()), + *(dh2->template attribute())); + } +}; + +// Case of two non void type, first without point +template +struct Is_same_attribute_point_functor +{ + static bool run(typename Map1::Dart_const_handle, + typename Map2::Dart_const_handle) + { return false; } +}; + +// Case of two non void type, second without point +template +struct Is_same_attribute_point_functor +{ + static bool run(typename Map1::Dart_const_handle, + typename Map2::Dart_const_handle) + { return false; } +}; + +// Case of two non void type, both without point +template +struct Is_same_attribute_point_functor +{ + static bool run(typename Map1::Dart_const_handle, + typename Map2::Dart_const_handle) + { return true; } +}; +// **************************************************************************** +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_point,Point,false) + +template +struct Is_nonvoid_attribute_has_non_void_info +{ + static const bool value=true; +}; +template +struct Is_nonvoid_attribute_has_non_void_info +{ + static const bool value=false; +}; + +template +struct Is_attribute_has_non_void_info +{ + static const bool value=Is_nonvoid_attribute_has_non_void_info::value; +}; +template<> +struct Is_attribute_has_non_void_info +{ + static const bool value=false; +}; +// **************************************************************************** +template +struct Is_attribute_has_point +{ static const bool value=Has_point::value; }; +// **************************************************************************** +/// Test if the two darts are associated with the same attribute. +template +struct Test_is_same_attribute_functor +{ + template + static void run(typename Map1::Dart_const_handle dh1, + typename Map2::Dart_const_handle dh2 ) + { + if (value) + { + value = Is_same_attribute_info_functor + ::type, + typename Map2::template Attribute_type::type, + i>::run(dh1, dh2); + } + if (value) + { + value = Is_same_attribute_point_functor + ::type, + typename Map2::template Attribute_type::type, + Is_attribute_has_point::type>::value, + Is_attribute_has_point::type>::value, i>::run(dh1, dh2); + } + } + static bool value; +}; +template +bool Test_is_same_attribute_functor::value = true; +// **************************************************************************** // Beta functor, used to combine several beta. #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES template diff --git a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_copy_test.cpp b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_copy_test.cpp new file mode 100644 index 00000000000..b50490b4c57 --- /dev/null +++ b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_copy_test.cpp @@ -0,0 +1,564 @@ +#include +#include +#include +#include + +#include +#include + +using namespace std; + +struct f1 +{ + template + void operator() (Attr&, Attr&) + {} +}; +struct f2 +{ + template + void operator() (const Attr&, Attr&) + {} +}; +struct f3 +{ + template + void operator() (Attr&, const Attr&) + {} +}; +struct f4 +{ + template + void operator() (const Attr&, const Attr&) + {} +}; +struct f5 +{ + template + void operator() (const Attr&, const Attr&) + {} + template + void operator() (Attr&, const Attr&) + {} +}; +struct f6 +{ + template + void operator() (CMap*, Attr&, Attr&) + {} +}; +struct f7 +{ + template + void operator() (Attr&, const Attr&) + {} + template + void operator() (CMap*, Attr&, Attr&) + {} +}; + +struct Map_2_dart_items +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 2, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f1, f2 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f3, f4 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_2_dart_max_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 2, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f1, f2 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f3, f4 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_3_dart_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f5, f6 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f7 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_3_dart_max_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f5, f6 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f7 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +class Another_map_3_dart_items_3 +{ +public: + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_dart_items_4 +{ + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 4, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple + Attributes; + }; +}; + +struct Map_dart_max_items_4 +{ + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 4, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple + Attributes; + }; +}; + +// void, void, void +typedef CGAL::Combinatorial_map<2, CGAL::Combinatorial_map_min_items<2> > Map1; + +// double, void, double +typedef CGAL::Combinatorial_map<2, Map_2_dart_items > Map2; + +// int, int, double +typedef CGAL::Combinatorial_map<2, Map_2_dart_max_items_3> Map3; + +// void, void, void, void +typedef CGAL::Combinatorial_map<3, CGAL::Combinatorial_map_min_items<3> > Map4; + +// double, void, int, double +typedef CGAL::Combinatorial_map<3, Map_3_dart_items_3> Map5; + +// int, int, int, double +typedef CGAL::Combinatorial_map<3, Map_3_dart_max_items_3> Map6; + +// int, void, int, void +typedef CGAL::Combinatorial_map<3, Another_map_3_dart_items_3> Map7; + +// int, void, int, void, int +typedef CGAL::Combinatorial_map<4, Map_dart_items_4> Map8; + +// int, int, int, int, double +typedef CGAL::Combinatorial_map<4, Map_dart_max_items_4> Map9; + +/* +template +typename Map::Dart_handle getRandomDart(Map& map) +{ + int nb = rand()%map.number_of_darts(); + typename Map::Dart_range::iterator it=map.darts().begin(); + for ( int i=0; i::type> +struct CreateAttributes +{ + static void run(Map& map) + { + int nb=0; + for(typename Map::Dart_range::iterator it=map.darts().begin(), + itend=map.darts().end(); it!=itend; ++it) + { + if ( it->template attribute()==NULL ) + map.template set_attribute + (it, map.template create_attribute(++nb)); + } + } +}; + +template +struct CreateAttributes +{ + static void run(Map&) + { + } +}; + +template::type> +struct DisplayAttribs +{ + static void run(Map& amap) + { + std::cout<::type::iterator + it=amap.template attributes().begin(), + itend=amap.template attributes().end(); + it!=itend; ++it ) + { + std::cout<info()<<"; "; + } + std::cout< +struct DisplayAttribs +{ + static void run(Map&) + {} +}; + +template +void displayAllAttribs2D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); +} + +template +void displayAllAttribs3D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); +} + +template +void displayAllAttribs4D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); +} + +template +void create2Dmap(Map& map) +{ + for ( int i=0; i<15; ++i ) + CGAL::make_combinatorial_hexahedron(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} +template +void create3Dmap(Map& map) +{ + for ( int i=0; i<15; ++i ) + CGAL::make_combinatorial_hexahedron(map); + + for ( int i=0; i<20; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<3>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<3>(d1, d2) ) ++d2; + map.template sew<3>(d1,d2); + } + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} +template +void create4Dmap(Map& map) +{ + for ( int i=0; i<45; ++i ) + CGAL::make_combinatorial_hexahedron(map); + + for ( int i=0; i<40; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<3>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<3>(d1, d2) ) ++d2; + map.template sew<3>(d1,d2); + } + + for ( int i=0; i<20; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<4>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<4>(d1, d2) ) ++d2; + map.template sew<4>(d1,d2); + } + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} + +bool testCopy() +{ + Map1 map1; create2Dmap(map1); + Map2 map2; create2Dmap(map2); + Map3 map3; create2Dmap(map3); + + Map4 map4; create3Dmap(map4); + Map5 map5; create3Dmap(map5); + Map6 map6; create3Dmap(map6); + Map7 map7; create3Dmap(map7); + + Map8 map8; create4Dmap(map8); + Map9 map9; create4Dmap(map9); + + // First copy of same types + { + Map1 map1p(map1); + if ( !map1p.is_valid() || !map1.is_isomorphic_to(map1p) ) + { assert(false); return false; } + Map2 map2p(map2); + if ( !map2p.is_valid() || !map2.is_isomorphic_to(map2p) ) + { assert(false); return false; } + Map3 map3p(map3); + if ( !map3p.is_valid() || !map3.is_isomorphic_to(map3p) ) + { assert(false); return false; } + Map4 map4p(map4); + if ( !map4p.is_valid() || !map4.is_isomorphic_to(map4p) ) + { assert(false); return false; } + Map5 map5p(map5); + if ( !map5p.is_valid() || !map5.is_isomorphic_to(map5p) ) + { assert(false); return false; } + Map6 map6p(map6); + if ( !map6p.is_valid() || !map6.is_isomorphic_to(map6p) ) + { assert(false); return false; } + Map7 map7p(map7); + if ( !map7p.is_valid() || !map7.is_isomorphic_to(map7p) ) + { assert(false); return false; } + Map8 map8p(map8); + if ( !map8p.is_valid() || !map8.is_isomorphic_to(map8p) ) + { assert(false); return false; } + Map9 map9p(map9); + if ( !map9p.is_valid() || !map9.is_isomorphic_to(map9p) ) + { assert(false); return false; } + } + + // Second copy of same dimensions but different attributes + // Maps are still isomorphic but no same attributes + { + // 2D + Map2 map1p(map1); assert(map1p.is_valid()); + if ( !map1.is_isomorphic_to(map1p) ) { assert(false); return false; } + + Map3 map1t(map1); assert(map1t.is_valid()); + if ( !map1.is_isomorphic_to(map1t) ) { assert(false); return false; } + + if ( !map1p.is_isomorphic_to(map1t) ) { assert(false); return false; } + + Map1 map2p(map2); assert(map2p.is_valid()); + if ( map2.is_isomorphic_to(map2p) ) { assert(false); return false; } + if ( !map2.is_isomorphic_to(map2p, false) ) { assert(false); return false; } + + Map3 map2t(map2); assert(map2t.is_valid()); + if ( map2.is_isomorphic_to(map2t) ) { assert(false); return false; } + if ( !map2.is_isomorphic_to(map2t, false) ) { assert(false); return false; } + + if ( map2p.is_isomorphic_to(map2t) ) { assert(false); return false; } + if ( !map2p.is_isomorphic_to(map2t, false) ) { assert(false); return false; } + + Map1 map3p(map3); assert(map3p.is_valid()); + if ( map3.is_isomorphic_to(map3p) ) { assert(false); return false; } + if ( !map3.is_isomorphic_to(map3p, false) ) { assert(false); return false; } + + Map2 map3t(map3); assert(map3t.is_valid()); + if ( map3.is_isomorphic_to(map3t) ) { assert(false); return false; } + if ( !map3.is_isomorphic_to(map3t, false) ) { assert(false); return false; } + + if ( map3p.is_isomorphic_to(map3t) ) { assert(false); return false; } + if ( !map3p.is_isomorphic_to(map3t, false) ) { assert(false); return false; } + + assert( map1.is_isomorphic_to(map1p)==map1p.is_isomorphic_to(map1) ); + assert( map1.is_isomorphic_to(map1t)==map1t.is_isomorphic_to(map1) ); + assert( map2.is_isomorphic_to(map2p)==map2p.is_isomorphic_to(map2) ); + assert( map2.is_isomorphic_to(map2t)==map2t.is_isomorphic_to(map2) ); + assert( map3.is_isomorphic_to(map3p)==map3p.is_isomorphic_to(map3) ); + assert( map3.is_isomorphic_to(map3t)==map3t.is_isomorphic_to(map3) ); + + // 3D + Map4 map5a(map5); assert(map5a.is_valid()); + if ( map5.is_isomorphic_to(map5a) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5a, false) ) { assert(false); return false; } + + Map6 map5b(map5); assert(map5b.is_valid()); + if ( map5.is_isomorphic_to(map5b) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5b, false) ) { assert(false); return false; } + assert( map5b.number_of_attributes<0>()==0 && + map5b.number_of_attributes<1>()==0 && + map5b.number_of_attributes<2>()==map5.number_of_attributes<2>() && + map5b.number_of_attributes<3>()==map5.number_of_attributes<3>() ); + + Map7 map5c(map5); assert(map5c.is_valid()); + if ( map5.is_isomorphic_to(map5c) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5c, false) ) { assert(false); return false; } + assert( map5c.number_of_attributes<0>()==0 && + map5c.number_of_attributes<2>()==map5.number_of_attributes<2>() ); + + assert( map5.is_isomorphic_to(map5a)==map5a.is_isomorphic_to(map5) ); + assert( map5.is_isomorphic_to(map5b)==map5b.is_isomorphic_to(map5) ); + assert( map5.is_isomorphic_to(map5c)==map5c.is_isomorphic_to(map5) ); + + // 4D + Map8 map9a(map9); assert(map9a.is_valid()); + if ( map9.is_isomorphic_to(map9a) ) { assert(false); return false; } + if ( !map9.is_isomorphic_to(map9a, false) ) { assert(false); return false; } + assert( map9a.number_of_attributes<0>()==map9.number_of_attributes<0>() && + map9a.number_of_attributes<2>()==map9.number_of_attributes<2>() && + map9a.number_of_attributes<4>()==0 ); + assert( map9a.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9a) ); + + Map9 map8a(map8); assert(map8a.is_valid()); + if ( map8.is_isomorphic_to(map8a) ) { assert(false); return false; } + if ( !map8.is_isomorphic_to(map8a, false) ) { assert(false); return false; } + assert( map8a.number_of_attributes<0>()==map8.number_of_attributes<0>() && + map8a.number_of_attributes<1>()==0 && + map8a.number_of_attributes<2>()==map8.number_of_attributes<2>() && + map8a.number_of_attributes<3>()==0 && + map8a.number_of_attributes<4>()==0 ); + assert( map8a.is_isomorphic_to(map8)==map8.is_isomorphic_to(map8a) ); + + } + + // Third copy of different dimensions and different attributes + { + Map5 map2a(map2); assert(map2a.is_valid()); + if ( map2a.is_isomorphic_to(map2) ) { assert(false); return false; } + if ( !map2a.is_isomorphic_to(map2, false) ) { assert(false); return false; } + assert( map2a.number_of_attributes<0>()==map2.number_of_attributes<0>() && + map2a.number_of_attributes<2>()==0 && + map2a.number_of_attributes<3>()==0 ); + assert( map2a.is_isomorphic_to(map2)==map2.is_isomorphic_to(map2a) ); + + Map2 map5a(map5); assert(map5a.is_valid()); + if ( map5a.is_isomorphic_to(map5) ) { assert(false); return false; } + assert( map5a.number_of_attributes<0>()>=map5.number_of_attributes<0>() && + map5a.number_of_attributes<2>()==0 ); + + Map5 map9a(map9); assert(map9a.is_valid()); + if ( map9a.is_isomorphic_to(map9) ) { assert(false); return false; } + assert( map9a.number_of_attributes<0>()==0 && + map9a.number_of_attributes<2>()>=map9.number_of_attributes<2>() && + map9a.number_of_attributes<3>()==0 ); + assert( map9a.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9a) ); + + CGAL::Cast_converter_cmap_attributes c0; + CGAL::Default_converter_cmap_attributes c1; + CGAL::Default_converter_cmap_attributes c2; + CGAL::Cast_converter_cmap_attributes c3; + + CGAL::cpp11::tuple, + CGAL::Default_converter_cmap_attributes, + CGAL::Default_converter_cmap_attributes, + CGAL::Cast_converter_cmap_attributes > myconverters + (c0, c1, c2, c3); + + Map5 map9b(map9, myconverters); assert(map9a.is_valid()); + if ( map9b.is_isomorphic_to(map9) ) { assert(false); return false; } + assert( map9b.number_of_attributes<0>()>=map9.number_of_attributes<0>() && + map9b.number_of_attributes<2>()>=map9.number_of_attributes<2>() && + map9b.number_of_attributes<3>()>=map9.number_of_attributes<3>() ); + assert( map9b.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9b) ); + + CGAL::Cast_converter_cmap_attributes cb0; + CGAL::Default_converter_cmap_attributes cb1; + CGAL::Default_converter_cmap_attributes cb2; + CGAL::Cast_converter_cmap_attributes cb3; + + CGAL::cpp11::tuple, + CGAL::Default_converter_cmap_attributes, + CGAL::Default_converter_cmap_attributes, + CGAL::Cast_converter_cmap_attributes > myconverters2 + (cb0, cb1, cb2, cb3); + + Map9 map5b(map5, myconverters2); assert(map5b.is_valid()); + if ( map5b.is_isomorphic_to(map5) ) { assert(false); return false; } + if ( !map5b.is_isomorphic_to(map5, false) ) { assert(false); return false; } + assert( map5b.number_of_attributes<0>()==map5.number_of_attributes<0>() && + map5b.number_of_attributes<2>()==map5.number_of_attributes<2>() && + map5b.number_of_attributes<3>()==map5.number_of_attributes<3>() ); + assert( map5b.is_isomorphic_to(map5)==map5.is_isomorphic_to(map5b) ); + } + + /* displayAllAttribs4D(map9, "map9******************\n"); + displayAllAttribs3D(map9b, "map9b******************\n");*/ + + /* std::cout<()<<" " + <()<<" " + <()<<" " + <()<<" " + <()<<" " + <()< + struct Dart_wrapper + { + typedef CGAL::Dart< 2, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f1, f2 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f3, f4 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + struct Map_2_dart_max_items_3 { /// Dart_wrapper defines the type of darts used. @@ -63,9 +78,25 @@ struct Map_2_dart_max_items_3 typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f1, f2 > Int_attrib; typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f3, f4 > Double_attrib; - - typedef CGAL::cpp11::tuple Attributes; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_3_dart_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f5, f6 > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f7 > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; }; }; @@ -79,9 +110,9 @@ struct Map_3_dart_max_items_3 typedef CGAL::Cell_attribute< Refs, int, CGAL::Tag_true, f5, f6 > Int_attrib; typedef CGAL::Cell_attribute< Refs, double, CGAL::Tag_true, f7 > Double_attrib; - - typedef CGAL::cpp11::tuple Attributes; + + typedef CGAL::cpp11::tuple Attributes; }; }; @@ -95,8 +126,23 @@ public: typedef CGAL::Dart< 3, Refs > Dart; typedef CGAL::Cell_attribute< Refs, int > Int_attrib; - - typedef CGAL::cpp11::tuple + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_dart_items_4 +{ + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 4, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; }; }; @@ -110,76 +156,81 @@ struct Map_dart_max_items_4 typedef CGAL::Cell_attribute< Refs, int > Int_attrib; typedef CGAL::Cell_attribute< Refs, double > Double_attrib; - - typedef CGAL::cpp11::tuple + + typedef CGAL::cpp11::tuple Attributes; }; }; +typedef CGAL::Combinatorial_map<2, CGAL::Combinatorial_map_min_items<2> > Map1; +typedef CGAL::Combinatorial_map<2, Map_2_dart_items > Map2; + +typedef CGAL::Combinatorial_map<2, Map_2_dart_max_items_3> Map3; + +typedef CGAL::Combinatorial_map<3, CGAL::Combinatorial_map_min_items<3> > Map4; + +typedef CGAL::Combinatorial_map<3, Map_3_dart_items_3> Map5; + +typedef CGAL::Combinatorial_map<3, Map_3_dart_max_items_3> Map6; + +typedef CGAL::Combinatorial_map<3, Another_map_3_dart_items_3> Map7; + +typedef CGAL::Combinatorial_map<4, Map_dart_items_4> Map8; + +typedef CGAL::Combinatorial_map<4, Map_dart_max_items_4> Map9; int main() { - typedef CGAL::Combinatorial_map<2, - CGAL::Combinatorial_map_min_items<2> > Map1; if ( !test2D() ) { std::cout<<"ERROR during test2D."< Map2; if ( !test2D() ) { std::cout<<"ERROR during test2D."< Map3; if ( !test2D() ) { std::cout<<"ERROR during test2D."< > Map4; if ( !test3D() ) { std::cout<<"ERROR during test3D."< Map5; if ( !test3D() ) { std::cout<<"ERROR during test3D."< Map6; if ( !test3D() ) { std::cout<<"ERROR during test3D."< Map7; if ( !test3D() ) { std::cout<<"ERROR during test3D."< Map8; if ( !test3D() ) { std::cout<<"ERROR during test3D."< Map9; if ( !test3D() ) { std::cout<<"ERROR during test3D."<, restricted to the include/CGAL/

Combinatorial Maps

  • Two bug fixes: do not use the 2 least significant bits for cell attribute without dart support; add share a mark in CMap_cell_iterator.
  • +
  • Add a constructor taking a given combinatorial map as argument, possibly with different dimension and/or different attributes. This allows to transform a combinatorial map.
  • +
  • Add operator= and swap method.

2D Apollonius graphs

diff --git a/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt b/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt index 1a50baaf72e..ad133599d65 100644 --- a/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt +++ b/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt @@ -37,8 +37,8 @@ if ( CGAL_FOUND ) # If you want to visualize a linear cell complex, there are 2 viewers # based on qt and vtk. Just uncomment the corresponding line - # include("CMakeLCCViewerQt.inc") - # include("CMakeLCCViewerVtk.inc") + # include("CMakeLCCViewerQt.inc") + # include("CMakeLCCViewerVtk.inc") add_executable(linear_cell_complex_3_triangulation linear_cell_complex_3_triangulation.cpp) diff --git a/Linear_cell_complex/include/CGAL/Cell_attribute_with_point.h b/Linear_cell_complex/include/CGAL/Cell_attribute_with_point.h index 52bccaf3fc1..5a32980ae72 100644 --- a/Linear_cell_complex/include/CGAL/Cell_attribute_with_point.h +++ b/Linear_cell_complex/include/CGAL/Cell_attribute_with_point.h @@ -56,27 +56,45 @@ namespace CGAL { /// Attribute associated with a point and an info. template < class LCC, class Info_=void, class Tag=Tag_true, - class Functor_on_merge_=Null_functor, + class Functor_on_merge_=Null_functor, class Functor_on_split_=Null_functor > class Cell_attribute_with_point : - public Cell_attribute, public Point_for_cell { + template < unsigned int d_, class Refs_, + class Items_, class Alloc_ > + friend class Combinatorial_map_base; + + template + friend class Compact_container; + public: - typedef Cell_attribute Self; + + typedef Cell_attribute Base1; typedef Point_for_cell Base2; - + typedef typename LCC::Point Point; typedef typename LCC::Dart_handle Dart_handle; typedef typename LCC::Dart_const_handle Dart_const_handle; - + typedef Info_ Info; typedef Functor_on_merge_ Functor_on_merge; typedef Functor_on_split_ Functor_on_split; - + using Base1::info; + + bool operator==(const Self& other) const + { return Base1::operator==(other) && this->point()==other.point(); } + + bool operator!=(const Self& other) const + { return !operator==(other); } + + // protected: /// Default contructor. Cell_attribute_with_point() {} @@ -90,31 +108,47 @@ namespace CGAL { Base1(ainfo), Base2(apoint) {} - - using Base1::info; }; /// Attribute associated with a point and without info. template < class LCC, class Tag, - class Functor_on_merge_, + class Functor_on_merge_, class Functor_on_split_ > class Cell_attribute_with_point : public Cell_attribute, public Point_for_cell { + template < unsigned int d_, class Refs_, + class Items_, class Alloc_ > + friend class Combinatorial_map_base; + + template + friend class Compact_container; + public: - typedef Cell_attribute Base1; typedef Point_for_cell Base2; typedef typename LCC::Point Point; typedef typename LCC::Dart_handle Dart_handle; - typedef typename LCC::Dart_const_handle Dart_const_handle; + typedef typename LCC::Dart_const_handle Dart_const_handle; typedef Functor_on_merge_ Functor_on_merge; typedef Functor_on_split_ Functor_on_split; + bool operator==(const Cell_attribute_with_point& other) const + { return Base1::operator==(other) && this->point()==other.point(); } + + bool operator!=(const Cell_attribute_with_point& other) const + { return !operator==(other); } + + template + bool operator==(const Cellattr& other) const + { return false; } + + // protected: /// Default contructor. Cell_attribute_with_point() {} diff --git a/Linear_cell_complex/include/CGAL/Linear_cell_complex.h b/Linear_cell_complex/include/CGAL/Linear_cell_complex.h index 4f9505206ee..5790eff4b0a 100644 --- a/Linear_cell_complex/include/CGAL/Linear_cell_complex.h +++ b/Linear_cell_complex/include/CGAL/Linear_cell_complex.h @@ -81,9 +81,36 @@ namespace CGAL { typedef typename Base::template Attribute_const_range<0>::type Vertex_attribute_const_range; + typedef typename Base::size_type size_type; + /// To use previous definition of create_dart methods. using Base::create_dart; + Linear_cell_complex() : Base() + {} + + /** Copy the given linear cell complex into *this. + * Note that both LCC can have different dimensions and/or non void attributes. + * @param alcc the linear cell complex to copy. + * @post *this is valid. + */ + Linear_cell_complex(const Self & alcc) + { Base::template copy(alcc); } + + template < class LCC2 > + Linear_cell_complex(const LCC2& alcc) + { Base::template copy(alcc);} + + template < class LCC2, typename Converters > + Linear_cell_complex(const LCC2& alcc, Converters& converters) + { Base::template copy(alcc, converters);} + + template < class LCC2, typename Converters, typename Pointconverter > + Linear_cell_complex(const LCC2& alcc, Converters& converters, + const Pointconverter& pointconverter) + { Base::template copy + (alcc, converters, pointconverter);} + /** Create a vertex attribute. * @return an handle on the new attribute. */ @@ -691,7 +718,7 @@ namespace CGAL { { return insert_point_in_cell(dh, barycenter(dh)); } /** Compute the dual of a Linear_cell_complex. - * @param amap the lcc in which we build the dual of this lcc. + * @param alcc the lcc in which we build the dual of this lcc. * @param adart a dart of the initial lcc, NULL by default. * @return adart of the dual lcc, the dual of adart if adart!=NULL, * any dart otherwise. diff --git a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_copy_test.cpp b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_copy_test.cpp new file mode 100644 index 00000000000..4f2bd5f405e --- /dev/null +++ b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_copy_test.cpp @@ -0,0 +1,690 @@ +#include +#include +#include +#include + +#include +#include + +using namespace std; + +struct Map_2_dart_items +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 2, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + typedef CGAL::Cell_attribute_with_point< Refs, double > Double_attrib_wp; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_2_dart_max_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 2, Refs > Dart; + + typedef CGAL::Cell_attribute_with_point< Refs, int > Int_attrib_wp; + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_3_dart_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + typedef CGAL::Cell_attribute_with_point< Refs, double > Double_attrib_wp; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_3_dart_max_items_3 +{ + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute_with_point< Refs, int > Int_attrib_wp; + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +class Another_map_3_dart_items_3 +{ +public: + /// Dart_wrapper defines the type of darts used. + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 3, Refs > Dart; + + typedef CGAL::Cell_attribute_with_point< Refs, int > Int_attrib_wp; + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + + typedef CGAL::cpp11::tuple Attributes; + }; +}; + +struct Map_dart_items_4 +{ + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 4, Refs > Dart; + + typedef CGAL::Cell_attribute_with_point< Refs, int > Int_attrib_wp; + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple + Attributes; + }; +}; + +struct Map_dart_max_items_4 +{ + template < class Refs > + struct Dart_wrapper + { + typedef CGAL::Dart< 4, Refs > Dart; + + typedef CGAL::Cell_attribute_with_point< Refs, int > Int_attrib_wp; + typedef CGAL::Cell_attribute< Refs, int > Int_attrib; + typedef CGAL::Cell_attribute< Refs, double > Double_attrib; + + typedef CGAL::cpp11::tuple + Attributes; + }; +}; + +typedef CGAL::Linear_cell_complex_traits +<3, CGAL::Exact_predicates_inexact_constructions_kernel> Traits3_a; + +typedef CGAL::Linear_cell_complex_traits +<3, CGAL::Exact_predicates_exact_constructions_kernel> Traits3_b; + +typedef CGAL::Linear_cell_complex_traits<4> Traits4_a; + +// Point_3, void, void +typedef CGAL::Linear_cell_complex<2,3, Traits3_a, CGAL::Linear_cell_complex_min_items<2> > Map1; + +// Point_3+double, void, double +typedef CGAL::Linear_cell_complex<2,3, Traits3_a, Map_2_dart_items > Map2; + +// Point_3+int, int, double +typedef CGAL::Linear_cell_complex<2,3, Traits3_b, Map_2_dart_max_items_3> Map3; + +// Point_3, void, void, void +typedef CGAL::Linear_cell_complex<3,3, Traits3_a, CGAL::Linear_cell_complex_min_items<3> > Map4; + +// Point_3+double, void, int, double +typedef CGAL::Linear_cell_complex<3,3, Traits3_a, Map_3_dart_items_3> Map5; + +// Point_3+int, int, int, double +typedef CGAL::Linear_cell_complex<3,3, Traits3_b, Map_3_dart_max_items_3> Map6; + +// Point_3+int, void, int, void +typedef CGAL::Linear_cell_complex<3,3, Traits3_b, Another_map_3_dart_items_3> Map7; + +// Point_4+int, void, int, void, int +typedef CGAL::Linear_cell_complex<4,4, Traits4_a, Map_dart_items_4> Map8; + +// Point_4+int, int, int, int, double +typedef CGAL::Linear_cell_complex<4,4, Traits4_a, Map_dart_max_items_4> Map9; + +struct Converter_map9_points_into_map5_points +{ + Map5::Attribute_handle<0>::type operator() + (const Map9&, Map5& map2, Map9::Dart_const_handle dh1, + Map5::Dart_handle dh2) const + { + CGAL_assertion( dh1->attribute<0>()!=NULL ); + + Map5::Attribute_handle<0>::type + res = dh2->attribute<0>(); + if ( res==NULL ) + { + res = map2.create_attribute<0>(); + } + + const Map9::Point & p = dh1->attribute<0>()->point(); + res->point() = Map5::Point(p[0],p[1],p[2]); + return res; + } +}; + + +/* +template +typename Map::Dart_handle getRandomDart(Map& map) +{ + int nb = rand()%map.number_of_darts(); + typename Map::Dart_range::iterator it=map.darts().begin(); + for ( int i=0; i +struct SetInfoIfNonVoid +{ + static void run(Attr&attr, int nb) + { + attr.info()=nb; + } +}; +template +struct SetInfoIfNonVoid +{ + static void run(Attr&, int) + {} +}; + +template::type> +struct CreateAttributes +{ + static void run(Map& map) + { + int nb=0; + for(typename Map::Dart_range::iterator it=map.darts().begin(), + itend=map.darts().end(); it!=itend; ++it) + { + if ( it->template attribute()==NULL ) + { + map.template set_attribute + (it, map.template create_attribute()); + SetInfoIfNonVoid::run(*(it->template attribute()), ++nb); + } + } + } +}; + +template +struct CreateAttributes +{ + static void run(Map& amap) + { + int nb=0; + for ( typename Map::template Attribute_range<0>::type::iterator + it=amap.template attributes<0>().begin(), + itend=amap.template attributes<0>().end(); + it!=itend; ++it ) + SetInfoIfNonVoid::run(*it, ++nb); + } +}; + +template +struct CreateAttributes +{ + static void run(Map&) + {} +}; + +template +struct CreateAttributes +{ + static void run(Map&) + {} +}; + +template::type> +struct DisplayNumberOfAttribs +{ + static void run(Map& amap) + { + std::cout<()<<" "; + } +}; +template +struct DisplayNumberOfAttribs +{ + static void run(Map&) + {} +}; + +template::type> +struct DisplayAttribs +{ + static void run(Map& amap) + { + std::cout<::type::iterator + it=amap.template attributes().begin(), + itend=amap.template attributes().end(); + it!=itend; ++it ) + { + std::cout<info()<<"; "; + } + std::cout< +struct DisplayAttribs +{ + static void run(Map&) + {} +}; + +template +struct DisplayVertexAttrib +{ + static void run(Map& amap) + { + std::cout<<"0-attributes: "; + for ( typename Map::template Attribute_range<0>::type::iterator + it=amap.template attributes<0>().begin(), + itend=amap.template attributes<0>().end(); + it!=itend; ++it ) + { + std::cout<info()<<"; "; + } + std::cout< +struct DisplayVertexAttrib +{ + static void run(Map& amap) + {} +}; + +template +struct DisplayAttribs +{ + static void run(Map& amap) + { DisplayVertexAttrib::run(amap); } +}; + +template +void displayAllAttribs2D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + + std::cout<<"Points: "; + for ( typename Map::template Attribute_range<0>::type::iterator + it=amap.template attributes<0>().begin(), + itend=amap.template attributes<0>().end(); + it!=itend; ++it ) + { + std::cout<point()<<"; "; + } + std::cout< +void displayAllAttribs3D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + + std::cout<<"Points: "; + for ( typename Map::template Attribute_range<0>::type::iterator + it=amap.template attributes<0>().begin(), + itend=amap.template attributes<0>().end(); + it!=itend; ++it ) + { + std::cout<point()<<"; "; + } + std::cout< +void displayAllAttribs4D(Map& amap, const char* c) +{ + std::cout<::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + DisplayAttribs::run(amap); + + std::cout<<"Points: "; + for ( typename Map::template Attribute_range<0>::type::iterator + it=amap.template attributes<0>().begin(), + itend=amap.template attributes<0>().end(); + it!=itend; ++it ) + { + std::cout<point()<<"; "; + } + std::cout< +void create2Dmap(Map& map) +{ + for ( int i=0; i<15; ++i ) + map.make_tetrahedron(typename Map::Point(i, 0, 0),typename Map::Point(i, 2, 0), + typename Map::Point(i+1, 0, 0),typename Map::Point(i+1, 1, 2)); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} +template +void create3Dmap(Map& map) +{ + for ( int i=0; i<15; ++i ) + map.make_tetrahedron(typename Map::Point(i, 0, 0),typename Map::Point(i, 2, 0), + typename Map::Point(i+1, 0, 0),typename Map::Point(i+1, 1, 2)); + + for ( int i=0; i<20; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<3>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<3>(d1, d2) ) ++d2; + map.template sew<3>(d1,d2); + } + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} + +template +typename LCC::Point apoint(typename LCC::FT x, typename LCC::FT y, + typename LCC::FT z, typename LCC::FT t) +{ + std::vector tab; + tab.push_back(x); tab.push_back(y); + tab.push_back(z); tab.push_back(t); + typename LCC::Point p(4,tab.begin(),tab.end()); + return p; +} + +template +void create4Dmap(Map& map) +{ + for ( int i=0; i<45; ++i ) + map.make_tetrahedron(apoint(i, 0, 0, 0),apoint(i, 2, 0, 0), + apoint(i+1, 0, 0, 0),apoint(i+1, 1, 2, 0)); + + for ( int i=0; i<40; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<3>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<3>(d1, d2) ) ++d2; + map.template sew<3>(d1,d2); + } + + for ( int i=0; i<20; ++i ) + { + typename Map::Dart_handle d1=map.darts().begin(); + while ( !d1->template is_free<4>() ) ++d1; + typename Map::Dart_handle d2=map.darts().begin(); + while ( !map.template is_sewable<4>(d1, d2) ) ++d2; + map.template sew<4>(d1,d2); + } + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); + CreateAttributes::run(map); +} + +bool testCopy() +{ + Map1 map1; create2Dmap(map1); + Map2 map2; create2Dmap(map2); + Map3 map3; create2Dmap(map3); + + Map4 map4; create3Dmap(map4); + Map5 map5; create3Dmap(map5); + Map6 map6; create3Dmap(map6); + Map7 map7; create3Dmap(map7); + + Map8 map8; create4Dmap(map8); + Map9 map9; create4Dmap(map9); + + // First copy of same types + { + Map1 map1p(map1); + if ( !map1p.is_valid() || !map1.is_isomorphic_to(map1p) ) + { assert(false); return false; } + Map2 map2p(map2); + if ( !map2p.is_valid() || !map2.is_isomorphic_to(map2p) ) + { assert(false); return false; } + Map3 map3p(map3); + if ( !map3p.is_valid() || !map3.is_isomorphic_to(map3p) ) + { assert(false); return false; } + Map4 map4p(map4); + if ( !map4p.is_valid() || !map4.is_isomorphic_to(map4p) ) + { assert(false); return false; } + Map5 map5p(map5); + if ( !map5p.is_valid() || !map5.is_isomorphic_to(map5p) ) + { assert(false); return false; } + Map6 map6p(map6); + if ( !map6p.is_valid() || !map6.is_isomorphic_to(map6p) ) + { assert(false); return false; } + Map7 map7p(map7); + if ( !map7p.is_valid() || !map7.is_isomorphic_to(map7p) ) + { assert(false); return false; } + Map8 map8p(map8); + if ( !map8p.is_valid() || !map8.is_isomorphic_to(map8p) ) + { assert(false); return false; } + Map9 map9p(map9); + if ( !map9p.is_valid() || !map9.is_isomorphic_to(map9p) ) + { assert(false); return false; } + } + + // Second copy of same dimensions but different attributes + // Maps are still isomorphic but no same attributes + { + // 2D + Map2 map1p(map1); assert(map1p.is_valid()); + if ( map1.is_isomorphic_to(map1p) ) { assert(false); return false; } + if ( !map1.is_isomorphic_to(map1p, false) ) { assert(false); return false; } + + Map3 map1t(map1); assert(map1t.is_valid()); + if ( map1.is_isomorphic_to(map1t) ) { assert(false); return false; } + if ( !map1.is_isomorphic_to(map1t, false) ) { assert(false); return false; } + + if ( map1p.is_isomorphic_to(map1t) ) { assert(false); return false; } + if ( !map1p.is_isomorphic_to(map1t, false) ) { assert(false); return false; } + + Map1 map2p(map2); assert(map2p.is_valid()); + if ( map2.is_isomorphic_to(map2p) ) { assert(false); return false; } + if ( !map2.is_isomorphic_to(map2p, false) ) { assert(false); return false; } + + Map3 map2t(map2); assert(map2t.is_valid()); + if ( map2.is_isomorphic_to(map2t) ) { assert(false); return false; } + if ( !map2.is_isomorphic_to(map2t, false) ) { assert(false); return false; } + + if ( map2p.is_isomorphic_to(map2t) ) { assert(false); return false; } + if ( !map2p.is_isomorphic_to(map2t, false) ) { assert(false); return false; } + + Map1 map3p(map3); assert(map3p.is_valid()); + if ( map3.is_isomorphic_to(map3p) ) { assert(false); return false; } + if ( !map3.is_isomorphic_to(map3p, false) ) { assert(false); return false; } + + Map2 map3t(map3); assert(map3t.is_valid()); + if ( map3.is_isomorphic_to(map3t) ) { assert(false); return false; } + if ( !map3.is_isomorphic_to(map3t, false) ) { assert(false); return false; } + + if ( map3p.is_isomorphic_to(map3t) ) { assert(false); return false; } + if ( !map3p.is_isomorphic_to(map3t, false) ) { assert(false); return false; } + + assert( map1.is_isomorphic_to(map1p)==map1p.is_isomorphic_to(map1) ); + assert( map1.is_isomorphic_to(map1t)==map1t.is_isomorphic_to(map1) ); + assert( map2.is_isomorphic_to(map2p)==map2p.is_isomorphic_to(map2) ); + assert( map2.is_isomorphic_to(map2t)==map2t.is_isomorphic_to(map2) ); + assert( map3.is_isomorphic_to(map3p)==map3p.is_isomorphic_to(map3) ); + assert( map3.is_isomorphic_to(map3t)==map3t.is_isomorphic_to(map3) ); + + // 3D + Map4 map5a(map5); assert(map5a.is_valid()); + if ( map5.is_isomorphic_to(map5a) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5a, false) ) { assert(false); return false; } + + Map6 map5b(map5); assert(map5b.is_valid()); + if ( map5.is_isomorphic_to(map5b) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5b, false) ) { assert(false); return false; } + assert( map5b.number_of_attributes<0>()==map5.number_of_attributes<0>() && + map5b.number_of_attributes<1>()==0 && + map5b.number_of_attributes<2>()==map5.number_of_attributes<2>() && + map5b.number_of_attributes<3>()==map5.number_of_attributes<3>() ); + + Map7 map5c(map5); assert(map5c.is_valid()); + if ( map5.is_isomorphic_to(map5c) ) { assert(false); return false; } + if ( !map5.is_isomorphic_to(map5c, false) ) { assert(false); return false; } + assert( map5c.number_of_attributes<0>()==map5.number_of_attributes<0>() && + map5c.number_of_attributes<2>()==map5.number_of_attributes<2>() ); + + assert( map5.is_isomorphic_to(map5a)==map5a.is_isomorphic_to(map5) ); + assert( map5.is_isomorphic_to(map5b)==map5b.is_isomorphic_to(map5) ); + assert( map5.is_isomorphic_to(map5c)==map5c.is_isomorphic_to(map5) ); + + // 4D + Map8 map9a(map9); assert(map9a.is_valid()); + if ( map9.is_isomorphic_to(map9a) ) { assert(false); return false; } + if ( !map9.is_isomorphic_to(map9a, false) ) { assert(false); return false; } + assert( map9a.number_of_attributes<0>()==map9.number_of_attributes<0>() && + map9a.number_of_attributes<2>()==map9.number_of_attributes<2>() && + map9a.number_of_attributes<4>()==0 ); + assert( map9a.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9a) ); + + Map9 map8a(map8); assert(map8a.is_valid()); + if ( map8.is_isomorphic_to(map8a) ) { assert(false); return false; } + if ( !map8.is_isomorphic_to(map8a, false) ) { assert(false); return false; } + assert( map8a.number_of_attributes<0>()==map8.number_of_attributes<0>() && + map8a.number_of_attributes<1>()==0 && + map8a.number_of_attributes<2>()==map8.number_of_attributes<2>() && + map8a.number_of_attributes<3>()==0 && + map8a.number_of_attributes<4>()==0 ); + assert( map8a.is_isomorphic_to(map8)==map8.is_isomorphic_to(map8a) ); + + } + + // Third copy of different dimensions and different attributes + { + Map5 map2a(map2); assert(map2a.is_valid()); + if ( map2a.is_isomorphic_to(map2) ) { assert(false); return false; } + if ( !map2a.is_isomorphic_to(map2, false) ) { assert(false); return false; } + assert( map2a.number_of_attributes<0>()==map2.number_of_attributes<0>() && + map2a.number_of_attributes<2>()==0 && + map2a.number_of_attributes<3>()==0 ); + assert( map2a.is_isomorphic_to(map2)==map2.is_isomorphic_to(map2a) ); + + Map2 map5a(map5); assert(map5a.is_valid()); + if ( map5a.is_isomorphic_to(map5) ) { assert(false); return false; } + assert( map5a.number_of_attributes<0>()==map2.number_of_attributes<0>() && + map5a.number_of_attributes<2>()==0 ); + + Map5 map9a(map9); assert(map9a.is_valid()); + if ( map9a.is_isomorphic_to(map9) ) { assert(false); return false; } + assert( map9a.number_of_attributes<0>()>=map9.number_of_attributes<0>() && + map9a.number_of_attributes<2>()>=map9.number_of_attributes<2>() && + map9a.number_of_attributes<3>()==0 ); + assert( map9a.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9a) ); + + CGAL::Cast_converter_cmap_attributes c0; + CGAL::Default_converter_cmap_attributes c1; + CGAL::Default_converter_cmap_attributes c2; + CGAL::Cast_converter_cmap_attributes c3; + + CGAL::cpp11::tuple, + CGAL::Default_converter_cmap_attributes, + CGAL::Default_converter_cmap_attributes, + CGAL::Cast_converter_cmap_attributes > myconverters + (c0, c1, c2, c3); + + Map5 map9b(map9, myconverters); assert(map9a.is_valid()); + if ( map9b.is_isomorphic_to(map9) ) { assert(false); return false; } + assert( map9b.number_of_attributes<0>()>=map9.number_of_attributes<0>() && + map9b.number_of_attributes<2>()>=map9.number_of_attributes<2>() && + map9b.number_of_attributes<3>()>=map9.number_of_attributes<3>() ); + assert( map9b.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9b) ); + + Converter_map9_points_into_map5_points mypointconverter; + + Map5 map9c(map9, myconverters, mypointconverter); assert(map9a.is_valid()); + if ( map9c.is_isomorphic_to(map9) ) { assert(false); return false; } + assert( map9c.number_of_attributes<0>()>=map9.number_of_attributes<0>() && + map9c.number_of_attributes<2>()>=map9.number_of_attributes<2>() && + map9c.number_of_attributes<3>()>=map9.number_of_attributes<3>() ); + assert( map9c.is_isomorphic_to(map9)==map9.is_isomorphic_to(map9c) ); + + CGAL::Cast_converter_cmap_attributes cb0; + CGAL::Default_converter_cmap_attributes cb1; + CGAL::Default_converter_cmap_attributes cb2; + CGAL::Cast_converter_cmap_attributes cb3; + + CGAL::cpp11::tuple, + CGAL::Default_converter_cmap_attributes, + CGAL::Default_converter_cmap_attributes, + CGAL::Cast_converter_cmap_attributes > myconverters2 + (cb0, cb1, cb2, cb3); + + Map9 map5b(map5, myconverters2); assert(map5b.is_valid()); + if ( map5b.is_isomorphic_to(map5) ) { assert(false); return false; } + if ( !map5b.is_isomorphic_to(map5, false) ) { assert(false); return false; } + assert( map5b.number_of_attributes<0>()==map5.number_of_attributes<0>() && + map5b.number_of_attributes<2>()==map5.number_of_attributes<2>() && + map5b.number_of_attributes<3>()==map5.number_of_attributes<3>() ); + assert( map5b.is_isomorphic_to(map5)==map5.is_isomorphic_to(map5b) ); + } + + /*map2.display_characteristics(std::cout)<