Merge branch 'Combinatorial_map_copy2-gdamiand'

Approved by the release manager
This commit is contained in:
Guillaume Damiand 2013-06-14 13:33:46 +02:00
commit 98a4e30f34
12 changed files with 2554 additions and 68 deletions

View File

@ -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<typename CMap>
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

View File

@ -60,26 +60,26 @@ namespace CGAL {
/// Cell_attribute_without_info
template <class Refs, class Tag=Tag_true,
class OnMerge=Null_functor,
class OnMerge=Null_functor,
class OnSplit=Null_functor>
class Cell_attribute_without_info;
// Cell_attribute_without_info without dart support.
template <class Refs, class OnMerge, class OnSplit>
class Cell_attribute_without_info<Refs, Tag_false,
class Cell_attribute_without_info<Refs, Tag_false,
OnMerge, OnSplit>
{
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
friend class Combinatorial_map_base;
template <int d, typename Refs_>
friend struct Dart;
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
class Items_, class Alloc_ >
friend class Generalized_map_base;
template <int d, typename Refs_>
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 Refs, class OnMerge, class OnSplit>
class Cell_attribute_without_info<Refs, Tag_true,
class Cell_attribute_without_info<Refs, Tag_true,
OnMerge, OnSplit>
{
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 <int d, typename Refs_>
@ -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 Refs, class Info_=void, class Tag_=Tag_true,
class OnMerge=Null_functor,
template <class Refs, class Info_=void, class Tag_=Tag_true,
class OnMerge=Null_functor,
class OnSplit=Null_functor>
class Cell_attribute;
/// Specialization when Info==void.
template <class Refs, class Tag_,
template <class Refs, class Tag_,
class OnMerge, class OnSplit>
class Cell_attribute<Refs, void, Tag_,
OnSplit, OnMerge> :
public Cell_attribute_without_info<Refs, Tag_,
class Cell_attribute<Refs, void, Tag_,
OnSplit, OnMerge> :
public Cell_attribute_without_info<Refs, Tag_,
OnSplit, OnMerge>
{
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
friend class Combinatorial_map_base;
template <class T, class Alloc_>
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 <class Refs, class Info_, class Tag_,
@ -305,11 +325,13 @@ namespace CGAL {
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
friend class Combinatorial_map_base;
template <class T, class Alloc_>
friend class Compact_container;
public:
typedef Cell_attribute<Refs, Info_, Tag_, OnMerge, OnSplit> 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<Info_>(ainfo)
/// Contructor with an info in parameter.
Cell_attribute(const Info_& ainfo) :
Info_for_cell_attribute<Info_>(ainfo)
{}
};

View File

@ -24,12 +24,14 @@
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/internal/Combinatorial_map_group_functors.h>
#include <CGAL/internal/Combinatorial_map_copy_functors.h>
#include <CGAL/internal/Combinatorial_map_sewable.h>
#include <CGAL/Combinatorial_map_functors.h>
#include <CGAL/Combinatorial_map_min_items.h>
#include <CGAL/Dart_const_iterators.h>
#include <CGAL/Cell_const_iterators.h>
#include <CGAL/Combinatorial_map_basic_operations.h>
#include <CGAL/Unique_hash_map.h>
#include <bitset>
#include <vector>
#include <deque>
@ -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<d_, Refs, Items_,Alloc_> 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 <typename CMap2, typename Converters, typename Pointconverter>
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<typename CMap2::Dart_const_handle, Dart_handle> 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<amap.dimension?dimension:amap.dimension);
typename std::map<typename CMap2::Dart_const_handle,Dart_handle>
::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 <CMap2, Refs, Converters,
Pointconverter> >::
run(&amap, static_cast<Refs*>(this),
dartmap_iter->first, dartmap_iter->second,
converters, pointconverter);
}
CGAL_assertion (is_valid () == 1);
}
template <typename CMap2>
void copy(const CMap2& amap)
{
CGAL::cpp11::tuple<> converters;
Default_converter_cmap_0attributes_with_point<CMap2, Refs> pointconverter;
return copy< CMap2, CGAL::cpp11::tuple<>,
Default_converter_cmap_0attributes_with_point<CMap2, Refs> >
(amap, converters, pointconverter);
}
template <typename CMap2, typename Converters>
void copy(const CMap2& amap, const Converters& converters)
{
Default_converter_cmap_0attributes_with_point<CMap2, Refs> pointconverter;
return copy< CMap2, Converters,
Default_converter_cmap_0attributes_with_point<CMap2, Refs> >
(amap, converters, pointconverter);
}
// Copy constructor from a map having exactly the same type.
Combinatorial_map_base (const Self & amap)
{ copy<Self>(amap); }
// "Copy constructor" from a map having different type.
template <typename CMap2>
Combinatorial_map_base(const CMap2& amap)
{ copy<CMap2>(amap); }
// "Copy constructor" from a map having different type.
template <typename CMap2, typename Converters>
Combinatorial_map_base(const CMap2& amap, Converters& converters)
{ copy<CMap2,Converters>(amap, converters); }
// "Copy constructor" from a map having different type.
template <typename CMap2, typename Converters, typename Pointconverter>
Combinatorial_map_base(const CMap2& amap, Converters& converters,
const Pointconverter& pointconverter)
{ copy<CMap2,Converters, Pointconverter>
(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 <unsigned int d2, typename Refs2, typename Items2, class Alloc2>
bool are_cc_isomorphic(Dart_const_handle dh1,
const Combinatorial_map_base
<d2,Refs2,Items2,Alloc2>& map2,
typename Combinatorial_map_base
<d2,Refs2,Items2,Alloc2>::Dart_const_handle dh2,
bool testAttributes=true) const
{
// CGAL_assertion(dimension==map2.dimension);
CGAL_assertion(dh1!=NULL && dh2!=NULL);
typedef Combinatorial_map_base<d2,Refs2,Items2,Alloc2> 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<Dart_const_handle,
typename Map2::Dart_const_handle> 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<Self, Map2> >::
run(current, other);
Map2::Helper::template Foreach_enabled_attributes
< internal::Test_is_same_attribute_functor<Map2, Self> >::
run(other, current);
if ( !internal::Test_is_same_attribute_functor<Self, Map2>::
value ||
!internal::Test_is_same_attribute_functor<Map2, Self>::
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 <unsigned int d2, typename Refs2, typename Items2, class Alloc2>
bool is_isomorphic_to(const Combinatorial_map_base
<d2,Refs2,Items2,Alloc2>& map2,
bool testAttributes=true)
{
// if ( dimension!=map2.dimension ) return false;
Dart_const_handle d1=darts().begin();
for (typename Combinatorial_map_base<d2,Refs2,Items2,Alloc2>::
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<Self>(amap); }
template < class CMap >
Combinatorial_map(const CMap & amap)
{ Base::template copy<CMap>(amap); }
template < class CMap, typename Converters >
Combinatorial_map(const CMap & amap, const Converters& converters)
{ Base::template copy<CMap, Converters>
(amap, converters); }
template < class CMap, typename Converters, typename Pointconverter >
Combinatorial_map(const CMap & amap, const Converters& converters,
const Pointconverter& pointconverter)
{ Base::template copy<CMap, Converters, Pointconverter>
(amap, converters, pointconverter); }
};
} // namespace CGAL

View File

@ -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 <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_COMBINATORIAL_MAP_COPY_FUNCTORS_H
#define CGAL_COMBINATORIAL_MAP_COPY_FUNCTORS_H
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/Dimension.h>
#include <CGAL/Kernel_traits.h>
#include <CGAL/Cartesian_converter.h>
/* 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<i>::type::Info,
typename Info2=typename Map2::template
Attribute_type<i>::type::Info >
struct Create_attribute_if_same_info_cmap
{
static typename Map2::template Attribute_handle<i>::type
run(Map2&, typename Map1::template Attribute_const_handle<i>::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<Map1, Map2, i, Info, Info>
{
static typename Map2::template Attribute_handle<i>::type
run(Map2& map2, typename Map1::template Attribute_const_handle<i>::type ah)
{
CGAL_assertion( ah!=NULL );
typename Map2::template Attribute_handle<i>::type
res = map2.template create_attribute<i>();
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<typename Point1, typename Point2,
typename T1=typename Ambient_dimension<Point1>::type,
typename T2=typename Ambient_dimension<Point2>::type>
struct Set_point_if_possible_cmap
{
static void run(const Point1&, Point2&)
{}
};
template<typename Point1, typename Point2>
struct Set_point_if_possible_cmap<Point1, Point2,
Dimension_tag<2>, Dimension_tag<2> >
{
static void run(const Point1& p1, Point2& p2)
{
p2 = Cartesian_converter<typename Kernel_traits<Point1>::Kernel,
typename Kernel_traits<Point2>::Kernel>(p1);
}
};
template<typename Point1>
struct Set_point_if_possible_cmap<Point1, Point1,
Dimension_tag<2>, Dimension_tag<2> >
{
static void run(const Point1& p1, Point1& p2)
{
p2 = p1;
}
};
template<typename Point1, typename Point2>
struct Set_point_if_possible_cmap<Point1, Point2,
Dimension_tag<3>, Dimension_tag<3> >
{
static void run(const Point1& p1, Point2& p2)
{
p2 = Cartesian_converter<typename Kernel_traits<Point1>::Kernel,
typename Kernel_traits<Point2>::Kernel>()(p1);
}
};
template<typename Point1>
struct Set_point_if_possible_cmap<Point1, Point1,
Dimension_tag<3>, Dimension_tag<3> >
{
static void run(const Point1& p1, Point1& p2)
{
p2 = p1;
}
};
template<typename Point1>
struct Set_point_if_possible_cmap<Point1, Point1,
Dynamic_dimension_tag, Dynamic_dimension_tag >
{
static void run(const Point1& p1, Point1& p2)
{
p2 = p1;
}
};
// ****************************************************************************
// Get the ith functor of the converters tuple if i<length of the tuple,
// otherwise get the default converter.
template<typename Map1, typename Map2, unsigned int i, typename Converters,
bool t=((int)i>=My_length<Converters>::value)>
struct Get_convert_attribute_functor
{
static typename Map2::template Attribute_handle<i>::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<Map1, Map2, i>()
(*cmap1, *cmap2, dh1, dh2);
}
};
template<typename Map1, typename Map2, unsigned int i, typename Converters>
struct Get_convert_attribute_functor<Map1,Map2,i,Converters,false>
{
static typename Map2::template Attribute_handle<i>::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<i>(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
<typename Map1::template Attribute_type<i>::type>::value,
bool Withinfo2=CGAL::internal::template
Is_attribute_has_non_void_info
<typename Map2::template Attribute_type<i>::type>::value >
struct Call_functor_if_both_attributes_have_info
{
static typename Map2::template Attribute_handle<i>::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<Map1, Map2, i,
Converters, true, true>
{
static typename Map2::template Attribute_handle<i>::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<Map1,Map2,i,Converters>::
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
<typename Map1::template Attribute_type<i>::type>::value,
bool Withpoint2=CGAL::internal::template Is_attribute_has_point
<typename Map2::template Attribute_type<i>::type>::value >
struct Call_functor_if_both_attributes_have_point
{
static typename Map2::template Attribute_handle<i>::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<Map1, Map2, 0,
Pointconverter, true, true>
{
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<typename Map1, typename Map2, typename Converters,
typename Pointconverter, unsigned int i,
typename Attr1=typename Map1::template Attribute_type<i>::type,
typename Attr2=typename Map2::template Attribute_type<i>::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<i>()==NULL ) return;
// If dh2 has already an i-attribute, it was already copied.
if ( dh2->template attribute<i>()!=NULL ) return;
// Otherwise we copy the info if both attribute have non void info.
typename Map2::template Attribute_handle<i>::type
res=Call_functor_if_both_attributes_have_info
<Map1, Map2, i, Converters>::
run(cmap1, cmap2, dh1, dh2, converters);
if ( res!=NULL )
cmap2->template set_attribute<i>(dh2, res);
// And the point if both attributes have points (and only for 0-attributes)
res=Call_functor_if_both_attributes_have_point
<Map1, Map2, i, Pointconverter>::
run(cmap1, cmap2, dh1, dh2, pointconverter);
if ( res!=NULL && dh2->template attribute<i>()==NULL )
cmap2->template set_attribute<i>(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<typename Map1, typename Map2, typename Converters,
typename Pointconverter, typename Attr2>
struct Copy_attribute_functor_if_nonvoid<Map1, Map2, Converters,
Pointconverter, 0, CGAL::Void, Attr2>
{
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
<typename Map2::template Attribute_type<0>::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<typename Map1, typename Map2, typename Converters, unsigned int i,
typename Pointconverter, typename Attr2>
struct Copy_attribute_functor_if_nonvoid<Map1, Map2, Converters,
Pointconverter, i, CGAL::Void, Attr2>
{
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<typename Map1, typename Map2, typename Converters,
typename Pointconverter>
struct Copy_attributes_functor
{
template<unsigned int i>
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
<Map1, Map2, Converters, Pointconverter, i>::
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<i>::type operator()
(const Map1&, Map2& map2, typename Map1::Dart_const_handle dh1,
typename Map2::Dart_handle dh2) const
{
CGAL_assertion( dh1->template attribute<i>()!=NULL );
CGAL_assertion( dh2->template attribute<i>()==NULL );
return internal::Create_attribute_if_same_info_cmap
<Map1,Map2,i>::
run(map2, dh1->template attribute<i>());
}
};
// ****************************************************************************
// 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<i>::type operator()
(const Map1&, Map2& map2, typename Map1::Dart_const_handle dh1,
typename Map2::Dart_handle dh2) const
{
CGAL_assertion( dh1->template attribute<i>()!=NULL );
CGAL_assertion( dh2->template attribute<i>()==NULL );
typename Map2::template Attribute_handle<i>::type
res = map2.template create_attribute<i>();
res->info() = (typename Map2::template Attribute_type<i>::type::Info)
dh1->template attribute<i>()->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
<typename Map1::template Attribute_type<0>::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

View File

@ -22,7 +22,10 @@
#include <CGAL/Dart_const_iterators.h>
#include <CGAL/Combinatorial_map_basic_operations.h>
#include <CGAL/Dimension.h>
#include <CGAL/Kernel_traits.h>
#include <vector>
#include <boost/mpl/has_xxx.hpp>
/* 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<CMap, i> to set the i-attribute
* of a given dart.
*
* internal::Test_is_same_attribute_functor<Map1, Map2> to test if two
* i-attributes of two darts are isomorphic.
*
* internal::Is_attribute_has_non_void_info<Attr> to test if the attribute
* Attr is non Void and has an non void Info as inner type
*
* internal::Is_attribute_has_point<Attr> 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<CMap, i, CGAL::Void>
{}
};
// ****************************************************************************
// 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<Attr1, Attr2, Info1, void>
{
static bool run(const Attr1&, const Attr2&)
{ return false; }
};
template< typename Attr1, typename Attr2, typename Info2 >
struct Is_same_info<Attr1, Attr2, void, Info2>
{
static bool run(const Attr1&, const Attr2&)
{ return false; }
};
template< typename Attr1, typename Attr2 >
struct Is_same_info<Attr1, Attr2, void, void>
{
static bool run(const Attr1&, const Attr2&)
{ return true; }
};
template< typename Attr1, typename Attr2, typename Info >
struct Is_same_info<Attr1, Attr2, Info, Info>
{
static bool run(const Attr1&a1, const Attr2&a2)
{ return a1.info()==a2.info(); }
};
// Case of two non void type
template<typename Map1, typename Map2,
typename T1, typename T2, int i>
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<i>()==NULL &&
dh2->template attribute<i>()==NULL)
return true;
if (dh1->template attribute<i>()==NULL ||
dh2->template attribute<i>()==NULL)
return false;
return
Is_same_info<T1,T2>::run(*(dh1->template attribute<i>()),
*(dh2->template attribute<i>()));
}
};
// Case T1==void
template <typename Map1, typename Map2,
typename T2, int i>
struct Is_same_attribute_info_functor<Map1, Map2, Void, T2, i>
{
static bool run(typename Map1::Dart_const_handle,
typename Map2::Dart_const_handle dh2)
{
return dh2->template attribute<i>()==NULL ||
Is_same_info<int,T2,void,typename T2::Info>::
run(0, *(dh2->template attribute<i>()));
}
};
// Case T2==void
template <typename Map1, typename Map2,
typename T1, int i>
struct Is_same_attribute_info_functor<Map1, Map2, T1, Void, i>
{
static bool run(typename Map1::Dart_const_handle dh1,
typename Map2::Dart_const_handle)
{
return dh1->template attribute<i>()==NULL ||
Is_same_info<T1, int, typename T1::Info, void>::
run(*(dh1->template attribute<i>()), 0);
}
};
// Case T1==T2==void
template <typename Map1, typename Map2, int i>
struct Is_same_attribute_info_functor<Map1, Map2, Void, Void, i>
{
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<Point1>::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<Attr1, Attr2, Point, Point, Dimension_tag<2> >
{
static bool run(const Attr1& a1, const Attr2& a2)
{ return typename Kernel_traits<Point>::Kernel::Equal_2()
(a1.point(),a2.point()); }
};
template< typename Attr1, typename Attr2, typename Point>
struct Is_same_point<Attr1, Attr2, Point, Point, Dimension_tag<3> >
{
static bool run(const Attr1& a1, const Attr2& a2)
{ return typename Kernel_traits<Point>::Kernel::Equal_3()
(a1.point(),a2.point()); }
};
template< typename Attr1, typename Attr2, typename Point>
struct Is_same_point<Attr1, Attr2, Point, Point, Dynamic_dimension_tag >
{
static bool run(const Attr1& a1, const Attr2& a2)
{ return typename Kernel_traits<Point>::Kernel::Equal_d()
(a1.point(),a2.point()); }
};
// Case of two non void type, with two points
template<typename Map1, typename Map2,
typename T1, typename T2, bool Withpoint1, bool Withpoint2, int i>
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<i>()==NULL &&
dh2->template attribute<i>()==NULL)
return true;
if (dh1->template attribute<i>()==NULL ||
dh2->template attribute<i>()==NULL)
return false;
return
Is_same_point<T1,T2>::run(*(dh1->template attribute<i>()),
*(dh2->template attribute<i>()));
}
};
// Case of two non void type, first without point
template<typename Map1, typename Map2,
typename T1, typename T2, int i>
struct Is_same_attribute_point_functor<Map1, Map2, T1, T2, false, true, i>
{
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<typename Map1, typename Map2,
typename T1, typename T2, int i>
struct Is_same_attribute_point_functor<Map1, Map2, T1, T2, true, false, i>
{
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<typename Map1, typename Map2,
typename T1, typename T2, int i>
struct Is_same_attribute_point_functor<Map1, Map2, T1, T2, false, false, i>
{
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<typename Attr, typename Info=typename Attr::Info>
struct Is_nonvoid_attribute_has_non_void_info
{
static const bool value=true;
};
template<typename Attr>
struct Is_nonvoid_attribute_has_non_void_info<Attr, void>
{
static const bool value=false;
};
template<typename Attr>
struct Is_attribute_has_non_void_info
{
static const bool value=Is_nonvoid_attribute_has_non_void_info<Attr>::value;
};
template<>
struct Is_attribute_has_non_void_info<CGAL::Void>
{
static const bool value=false;
};
// ****************************************************************************
template<typename Attr>
struct Is_attribute_has_point
{ static const bool value=Has_point<Attr>::value; };
// ****************************************************************************
/// Test if the two darts are associated with the same attribute.
template<typename Map1, typename Map2>
struct Test_is_same_attribute_functor
{
template<unsigned int i>
static void run(typename Map1::Dart_const_handle dh1,
typename Map2::Dart_const_handle dh2 )
{
if (value)
{
value = Is_same_attribute_info_functor
<Map1, Map2,
typename Map1::template Attribute_type<i>::type,
typename Map2::template Attribute_type<i>::type,
i>::run(dh1, dh2);
}
if (value)
{
value = Is_same_attribute_point_functor
<Map1, Map2,
typename Map1::template Attribute_type<i>::type,
typename Map2::template Attribute_type<i>::type,
Is_attribute_has_point<typename Map1::template
Attribute_type<i>::type>::value,
Is_attribute_has_point<typename Map2::template
Attribute_type<i>::type>::value, i>::run(dh1, dh2);
}
}
static bool value;
};
template<typename Map1, typename Map2>
bool Test_is_same_attribute_functor<Map1, Map2>::value = true;
// ****************************************************************************
// Beta functor, used to combine several beta.
#ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
template<typename Dart_handle, typename ... Betas>

View File

@ -0,0 +1,564 @@
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Cell_attribute.h>
#include <CGAL/Combinatorial_map_constructors.h>
#include <CGAL/Combinatorial_map_operations.h>
#include <iostream>
#include <fstream>
using namespace std;
struct f1
{
template<typename Attr>
void operator() (Attr&, Attr&)
{}
};
struct f2
{
template<typename Attr>
void operator() (const Attr&, Attr&)
{}
};
struct f3
{
template<typename Attr>
void operator() (Attr&, const Attr&)
{}
};
struct f4
{
template<typename Attr>
void operator() (const Attr&, const Attr&)
{}
};
struct f5
{
template<typename Attr>
void operator() (const Attr&, const Attr&)
{}
template<typename Attr>
void operator() (Attr&, const Attr&)
{}
};
struct f6
{
template<typename CMap, typename Attr>
void operator() (CMap*, Attr&, Attr&)
{}
};
struct f7
{
template<typename Attr>
void operator() (Attr&, const Attr&)
{}
template<typename CMap, typename Attr>
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<Double_attrib, void, Double_attrib> 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<Int_attrib, Int_attrib,
Double_attrib> 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<Double_attrib, void,
Int_attrib, Double_attrib> 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<Int_attrib, Int_attrib,
Int_attrib, Double_attrib> 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<Int_attrib, void, Int_attrib> 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<Int_attrib, void,
Int_attrib, void, Int_attrib>
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<Int_attrib, Int_attrib,
Int_attrib, Int_attrib, Double_attrib>
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>
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<nb; ++i, ++it )
{}
return it;
}
*/
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<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<i>()==NULL )
map.template set_attribute<i>
(it, map.template create_attribute<i>(++nb));
}
}
};
template<typename Map, unsigned int i>
struct CreateAttributes<Map, i, CGAL::Void>
{
static void run(Map&)
{
}
};
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<i>::type>
struct DisplayAttribs
{
static void run(Map& amap)
{
std::cout<<i<<"-attributes: ";
for ( typename Map::template Attribute_range<i>::type::iterator
it=amap.template attributes<i>().begin(),
itend=amap.template attributes<i>().end();
it!=itend; ++it )
{
std::cout<<it->info()<<"; ";
}
std::cout<<std::endl;
}
};
template<typename Map, unsigned int i>
struct DisplayAttribs<Map,i,CGAL::Void>
{
static void run(Map&)
{}
};
template<typename Map>
void displayAllAttribs2D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::run(amap);
}
template<typename Map>
void displayAllAttribs3D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::run(amap);
DisplayAttribs<Map,3>::run(amap);
}
template<typename Map>
void displayAllAttribs4D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::run(amap);
DisplayAttribs<Map,3>::run(amap);
DisplayAttribs<Map,4>::run(amap);
}
template<typename Map>
void create2Dmap(Map& map)
{
for ( int i=0; i<15; ++i )
CGAL::make_combinatorial_hexahedron(map);
CreateAttributes<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
}
template<typename Map>
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<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
CreateAttributes<Map,3>::run(map);
}
template<typename Map>
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<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
CreateAttributes<Map,3>::run(map);
CreateAttributes<Map,4>::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<Map9,Map5,0> c0;
CGAL::Default_converter_cmap_attributes<Map9,Map5,1> c1;
CGAL::Default_converter_cmap_attributes<Map9,Map5,2> c2;
CGAL::Cast_converter_cmap_attributes<Map9,Map5,3> c3;
CGAL::cpp11::tuple<CGAL::Cast_converter_cmap_attributes<Map9,Map5,0>,
CGAL::Default_converter_cmap_attributes<Map9,Map5,1>,
CGAL::Default_converter_cmap_attributes<Map9,Map5,2>,
CGAL::Cast_converter_cmap_attributes<Map9,Map5,3> > 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<Map5,Map9,0> cb0;
CGAL::Default_converter_cmap_attributes<Map5,Map9,1> cb1;
CGAL::Default_converter_cmap_attributes<Map5,Map9,2> cb2;
CGAL::Cast_converter_cmap_attributes<Map5,Map9,3> cb3;
CGAL::cpp11::tuple<CGAL::Cast_converter_cmap_attributes<Map5,Map9,0>,
CGAL::Default_converter_cmap_attributes<Map5,Map9,1>,
CGAL::Default_converter_cmap_attributes<Map5,Map9,2>,
CGAL::Cast_converter_cmap_attributes<Map5,Map9,3> > 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<<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>()<<std::endl;*/
//map5.display_characteristics(std::cout)<<std::endl;
//map5a.display_characteristics(std::cout)<<std::endl;
return true;
}
int main()
{
std::cout<<"Combinatorial map copy test (v1)."<<std::flush;
if ( !testCopy() )
{
std::cout<<" Failed."<<std::endl;
return EXIT_FAILURE;
}
std::cout<<" Success."<<std::endl;
return EXIT_SUCCESS;
}

View File

@ -53,6 +53,21 @@ struct f7
{}
};
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<Double_attrib, void, Double_attrib> 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<Int_attrib, Int_attrib,
Double_attrib> Attributes;
typedef CGAL::cpp11::tuple<Int_attrib, Int_attrib,
Double_attrib> 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<Double_attrib, void,
Int_attrib, Double_attrib> 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<Int_attrib, Int_attrib,
Int_attrib, Double_attrib> Attributes;
typedef CGAL::cpp11::tuple<Int_attrib, Int_attrib,
Int_attrib, Double_attrib> Attributes;
};
};
@ -95,8 +126,23 @@ public:
typedef CGAL::Dart< 3, Refs > Dart;
typedef CGAL::Cell_attribute< Refs, int > Int_attrib;
typedef CGAL::cpp11::tuple<Int_attrib, void, Int_attrib>
typedef CGAL::cpp11::tuple<Int_attrib, void, Int_attrib> 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<Int_attrib, void,
Int_attrib, void, Int_attrib>
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<Int_attrib, Int_attrib,
Int_attrib, Double_attrib, Double_attrib>
typedef CGAL::cpp11::tuple<Int_attrib, Int_attrib,
Int_attrib, Double_attrib, Double_attrib>
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<Map1>() )
{
std::cout<<"ERROR during test2D<Map1>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<2, Map_2_dart_max_items_3 > Map2;
if ( !test2D<Map2>() )
{
std::cout<<"ERROR during test2D<Map2>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<2, Map_2_dart_max_items_3> Map3;
if ( !test2D<Map3>() )
{
std::cout<<"ERROR during test2D<Map3>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<3,
CGAL::Combinatorial_map_min_items<3> > Map4;
if ( !test3D<Map4>() )
{
std::cout<<"ERROR during test3D<Map4>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<3, Map_3_dart_max_items_3> Map5;
if ( !test3D<Map5>() )
{
std::cout<<"ERROR during test3D<Map5>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<3, Map_3_dart_max_items_3> Map6;
if ( !test3D<Map6>() )
{
std::cout<<"ERROR during test3D<Map6>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<3, Another_map_3_dart_items_3> Map7;
if ( !test3D<Map7>() )
{
std::cout<<"ERROR during test3D<Map7>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<3, Another_map_3_dart_items_3> Map8;
if ( !test3D<Map8>() )
{
std::cout<<"ERROR during test3D<Map8>."<<std::endl;
return EXIT_FAILURE;
}
typedef CGAL::Combinatorial_map<4, Map_dart_max_items_4> Map9;
if ( !test3D<Map9>() )
{
std::cout<<"ERROR during test3D<Map9>."<<std::endl;

View File

@ -134,6 +134,8 @@ David A. Wheeler's 'SLOCCount'</a>, restricted to the <code>include/CGAL/</code>
<h3>Combinatorial Maps</h3>
<ul>
<li>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.</li>
<li>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. </li>
<li>Add operator= and swap method.</li>
</ul>
<h3>2D Apollonius graphs</h3>

View File

@ -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)

View File

@ -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<LCC, Info_, Tag,
public Cell_attribute<LCC, Info_, Tag,
Functor_on_merge_, Functor_on_split_>,
public Point_for_cell<typename LCC::Point>
{
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
friend class Combinatorial_map_base;
template <class T, class Alloc_>
friend class Compact_container;
public:
typedef Cell_attribute<LCC, Info_, Tag,
typedef Cell_attribute_with_point<LCC, Info_, Tag, Functor_on_merge_,
Functor_on_split_> Self;
typedef Cell_attribute<LCC, Info_, Tag,
Functor_on_merge_, Functor_on_split_> Base1;
typedef Point_for_cell<typename LCC::Point> 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<LCC, void, Tag,
Functor_on_merge_, Functor_on_split_> :
public Cell_attribute<LCC, void, Tag, Functor_on_merge_, Functor_on_split_>,
public Point_for_cell<typename LCC::Point>
{
template < unsigned int d_, class Refs_,
class Items_, class Alloc_ >
friend class Combinatorial_map_base;
template <class T, class Alloc_>
friend class Compact_container;
public:
typedef Cell_attribute<LCC, void, Tag,
typedef Cell_attribute<LCC, void, Tag,
Functor_on_merge_, Functor_on_split_> Base1;
typedef Point_for_cell<typename LCC::Point> 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<typename Cellattr>
bool operator==(const Cellattr& other) const
{ return false; }
// protected:
/// Default contructor.
Cell_attribute_with_point()
{}

View File

@ -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<Self>(alcc); }
template < class LCC2 >
Linear_cell_complex(const LCC2& alcc)
{ Base::template copy<LCC2>(alcc);}
template < class LCC2, typename Converters >
Linear_cell_complex(const LCC2& alcc, Converters& converters)
{ Base::template copy<LCC2, Converters>(alcc, converters);}
template < class LCC2, typename Converters, typename Pointconverter >
Linear_cell_complex(const LCC2& alcc, Converters& converters,
const Pointconverter& pointconverter)
{ Base::template copy<LCC2, Converters, Pointconverter>
(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<i>(dh, barycenter<i>(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.

View File

@ -0,0 +1,690 @@
#include <CGAL/Linear_cell_complex.h>
#include <CGAL/Cell_attribute_with_point.h>
#include <CGAL/Linear_cell_complex_constructors.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <iostream>
#include <fstream>
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<Double_attrib_wp, void, Double_attrib> 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<Int_attrib_wp, Int_attrib,
Double_attrib> 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<Double_attrib_wp, void,
Int_attrib, Double_attrib> 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<Int_attrib_wp, Int_attrib,
Int_attrib, Double_attrib> 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<Int_attrib_wp, void, Int_attrib> 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<Int_attrib_wp, void,
Int_attrib, void, Int_attrib>
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<Int_attrib_wp, Int_attrib,
Int_attrib, Int_attrib, Double_attrib>
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>
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<nb; ++i, ++it )
{}
return it;
}
*/
template<typename Attr, typename Info=typename Attr::Info>
struct SetInfoIfNonVoid
{
static void run(Attr&attr, int nb)
{
attr.info()=nb;
}
};
template<typename Attr>
struct SetInfoIfNonVoid<Attr, void>
{
static void run(Attr&, int)
{}
};
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<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<i>()==NULL )
{
map.template set_attribute<i>
(it, map.template create_attribute<i>());
SetInfoIfNonVoid<Attr>::run(*(it->template attribute<i>()), ++nb);
}
}
}
};
template<typename Map, typename Attr>
struct CreateAttributes<Map, 0, Attr>
{
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<Attr>::run(*it, ++nb);
}
};
template<typename Map, unsigned int i>
struct CreateAttributes<Map, i, CGAL::Void>
{
static void run(Map&)
{}
};
template<typename Map>
struct CreateAttributes<Map, 0, CGAL::Void>
{
static void run(Map&)
{}
};
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<i>::type>
struct DisplayNumberOfAttribs
{
static void run(Map& amap)
{
std::cout<<i<<"-attributes="<<amap.template number_of_attributes<i>()<<" ";
}
};
template<typename Map, unsigned int i>
struct DisplayNumberOfAttribs<Map,i,CGAL::Void>
{
static void run(Map&)
{}
};
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<i>::type>
struct DisplayAttribs
{
static void run(Map& amap)
{
std::cout<<i<<"-attributes: ";
for ( typename Map::template Attribute_range<i>::type::iterator
it=amap.template attributes<i>().begin(),
itend=amap.template attributes<i>().end();
it!=itend; ++it )
{
std::cout<<it->info()<<"; ";
}
std::cout<<std::endl;
}
};
template<typename Map, unsigned int i>
struct DisplayAttribs<Map,i,CGAL::Void>
{
static void run(Map&)
{}
};
template<typename Map,typename Attr,typename Info=typename Attr::Info>
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<<it->info()<<"; ";
}
std::cout<<std::endl;
}
};
template<typename Map,typename Attr>
struct DisplayVertexAttrib<Map,Attr,void>
{
static void run(Map& amap)
{}
};
template<typename Map, typename Attr>
struct DisplayAttribs<Map,0,Attr>
{
static void run(Map& amap)
{ DisplayVertexAttrib<Map,Attr>::run(amap); }
};
template<typename Map>
void displayAllAttribs2D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::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<<it->point()<<"; ";
}
std::cout<<std::endl;
}
template<typename Map>
void displayAllAttribs3D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::run(amap);
DisplayAttribs<Map,3>::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<<it->point()<<"; ";
}
std::cout<<std::endl;
}
template<typename Map>
void displayAllAttribs4D(Map& amap, const char* c)
{
std::cout<<c;
DisplayAttribs<Map,0>::run(amap);
DisplayAttribs<Map,1>::run(amap);
DisplayAttribs<Map,2>::run(amap);
DisplayAttribs<Map,3>::run(amap);
DisplayAttribs<Map,4>::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<<it->point()<<"; ";
}
std::cout<<std::endl;
}
template<typename Map>
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<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
}
template<typename Map>
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<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
CreateAttributes<Map,3>::run(map);
}
template<typename LCC>
typename LCC::Point apoint(typename LCC::FT x, typename LCC::FT y,
typename LCC::FT z, typename LCC::FT t)
{
std::vector<typename LCC::FT> 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<typename Map>
void create4Dmap(Map& map)
{
for ( int i=0; i<45; ++i )
map.make_tetrahedron(apoint<Map>(i, 0, 0, 0),apoint<Map>(i, 2, 0, 0),
apoint<Map>(i+1, 0, 0, 0),apoint<Map>(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<Map,0>::run(map);
CreateAttributes<Map,1>::run(map);
CreateAttributes<Map,2>::run(map);
CreateAttributes<Map,3>::run(map);
CreateAttributes<Map,4>::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<Map9,Map5,0> c0;
CGAL::Default_converter_cmap_attributes<Map9,Map5,1> c1;
CGAL::Default_converter_cmap_attributes<Map9,Map5,2> c2;
CGAL::Cast_converter_cmap_attributes<Map9,Map5,3> c3;
CGAL::cpp11::tuple<CGAL::Cast_converter_cmap_attributes<Map9,Map5,0>,
CGAL::Default_converter_cmap_attributes<Map9,Map5,1>,
CGAL::Default_converter_cmap_attributes<Map9,Map5,2>,
CGAL::Cast_converter_cmap_attributes<Map9,Map5,3> > 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<Map5,Map9,0> cb0;
CGAL::Default_converter_cmap_attributes<Map5,Map9,1> cb1;
CGAL::Default_converter_cmap_attributes<Map5,Map9,2> cb2;
CGAL::Cast_converter_cmap_attributes<Map5,Map9,3> cb3;
CGAL::cpp11::tuple<CGAL::Cast_converter_cmap_attributes<Map5,Map9,0>,
CGAL::Default_converter_cmap_attributes<Map5,Map9,1>,
CGAL::Default_converter_cmap_attributes<Map5,Map9,2>,
CGAL::Cast_converter_cmap_attributes<Map5,Map9,3> > 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)<<std::endl;
map2a.display_characteristics(std::cout)<<std::endl;
displayAllAttribs2D(mapXX, "mapXX******************\n");
displayAllAttribs2D(mapYY, "mapYY******************\n");*/
/*map5.display_characteristics(std::cout)<<std::endl;
map5b.display_characteristics(std::cout)<<std::endl;
displayAllAttribs3D(map5, "map5******************\n");
displayAllAttribs3D(map5b, "map5b******************\n");*/
return true;
}
int main()
{
std::cout<<"Linear cell complex copy test (v1)."<<std::flush;
if ( !testCopy() )
{
std::cout<<" Failed."<<std::endl;
return EXIT_FAILURE;
}
std::cout<<" Success."<<std::endl;
return EXIT_SUCCESS;
}