605 lines
22 KiB
C
605 lines
22 KiB
C
|
// Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany).
|
||
|
// 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
|
||
|
// 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$
|
||
|
// SPDX-License-Identifier: GPL-3.0+
|
||
|
//
|
||
|
//
|
||
|
// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
|
||
|
// Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
|
||
|
|
||
|
#ifndef CGAL_SPHERE_MAP_H
|
||
|
#define CGAL_SPHERE_MAP_H
|
||
|
|
||
|
#include <CGAL/license/Nef_S2.h>
|
||
|
|
||
|
|
||
|
#include <CGAL/basic.h>
|
||
|
#include <CGAL/Unique_hash_map.h>
|
||
|
#include <CGAL/Nef_2/Object_handle.h>
|
||
|
#include <CGAL/Nef_S2/SM_items.h>
|
||
|
#include <CGAL/Nef_S2/SM_list.h>
|
||
|
#include <CGAL/Nef_S2/SM_iteration.h>
|
||
|
#include <CGAL/Nef_S2/Generic_handle_map.h>
|
||
|
#include <CGAL/Nef_2/iterator_tools.h>
|
||
|
#include <list>
|
||
|
#undef CGAL_NEF_DEBUG
|
||
|
#define CGAL_NEF_DEBUG 109
|
||
|
#include <CGAL/Nef_2/debug.h>
|
||
|
|
||
|
#include<boost/optional.hpp>
|
||
|
#include<boost/none.hpp>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
template <typename HE>
|
||
|
class move_edge_around_svertex {
|
||
|
public:
|
||
|
void forward(HE& e) const { e = (e->sprev()->twin()); }
|
||
|
void backward(HE& e) const { e = (e->twin()->snext()); }
|
||
|
};
|
||
|
|
||
|
template <typename HE>
|
||
|
struct move_edge_around_sface {
|
||
|
void forward(HE& e) const { e = (e->snext()); }
|
||
|
void backward(HE& e) const { e = (e->sprev()); }
|
||
|
};
|
||
|
|
||
|
/*{\Manpage {Sphere_map}{Kernel}{Sphere Maps}{M}}*/
|
||
|
|
||
|
template <typename Kernel_, typename Items_, typename Mark_>
|
||
|
class Sphere_map {
|
||
|
|
||
|
/*{\Mdefinition selective sphere map container based on
|
||
|
the HDS design of Kettner.}*/
|
||
|
|
||
|
public:
|
||
|
/*{\Mtypes 7}*/
|
||
|
typedef Sphere_map<Kernel_, Items_,Mark_> Self;
|
||
|
typedef Kernel_ Sphere_kernel;
|
||
|
typedef Items_ Items;
|
||
|
typedef Mark_ Mark;
|
||
|
|
||
|
friend class SM_const_decorator<Self>;
|
||
|
friend class SM_decorator<Self>;
|
||
|
|
||
|
typedef typename Sphere_kernel::Sphere_point Sphere_point;
|
||
|
/*{\Mtypemember points on the unit sphere.}*/
|
||
|
typedef typename Sphere_kernel::Sphere_segment Sphere_segment;
|
||
|
/*{\Mtypemember segments on the unit sphere.}*/
|
||
|
typedef typename Sphere_kernel::Sphere_circle Sphere_circle;
|
||
|
/*{\Mtypemember segments on the unit sphere.}*/
|
||
|
typedef typename Sphere_kernel::Sphere_direction Sphere_direction;
|
||
|
/*{\Mtypemember directions on the unit sphere.}*/
|
||
|
// typedef bool Mark;
|
||
|
/*{\Mtypemember selective attributes of all objects.}*/
|
||
|
typedef size_t Size_type;
|
||
|
/*{\Mtypemember size type.}*/
|
||
|
|
||
|
/*{\Mtext For all objects |Vertex|, |Halfedge|, |Halfloop|, |Face|
|
||
|
there are handle and iterator types |xxx_handle|, |xxx_iterator|.
|
||
|
There's no type |SLoop_iterator|, as there is
|
||
|
at most one |SLoop| pair per sphere map.}*/
|
||
|
|
||
|
typedef typename Items::template SVertex<Self> SVertex_base;
|
||
|
typedef SNC_in_place_list_svertex<SVertex_base> SVertex;
|
||
|
typedef CGAL::In_place_list<SVertex,false> SVertex_list;
|
||
|
typedef CGAL_ALLOCATOR(SVertex) SVertex_alloc;
|
||
|
typedef typename SVertex_list::iterator SVertex_handle;
|
||
|
typedef typename SVertex_list::const_iterator SVertex_const_handle;
|
||
|
typedef typename SVertex_list::iterator SVertex_iterator;
|
||
|
typedef typename SVertex_list::const_iterator SVertex_const_iterator;
|
||
|
|
||
|
typedef typename Items::template SHalfedge<Self> SHalfedge_base;
|
||
|
typedef SNC_in_place_list_shalfedge<SHalfedge_base> SHalfedge;
|
||
|
typedef CGAL::In_place_list<SHalfedge,false> SHalfedge_list;
|
||
|
typedef CGAL_ALLOCATOR(SHalfedge) SHalfedge_alloc;
|
||
|
typedef typename SHalfedge_list::iterator SHalfedge_handle;
|
||
|
typedef typename SHalfedge_list::const_iterator SHalfedge_const_handle;
|
||
|
typedef typename SHalfedge_list::iterator SHalfedge_iterator;
|
||
|
typedef typename SHalfedge_list::const_iterator SHalfedge_const_iterator;
|
||
|
|
||
|
typedef typename Items::template SFace<Self> SFace_base;
|
||
|
typedef SNC_in_place_list_sface<SFace_base> SFace;
|
||
|
typedef CGAL::In_place_list<SFace,false> SFace_list;
|
||
|
typedef CGAL_ALLOCATOR(SFace) SFace_alloc;
|
||
|
typedef typename SFace_list::iterator SFace_handle;
|
||
|
typedef typename SFace_list::const_iterator SFace_const_handle;
|
||
|
typedef typename SFace_list::iterator SFace_iterator;
|
||
|
typedef typename SFace_list::const_iterator SFace_const_iterator;
|
||
|
|
||
|
typedef typename Items::template SHalfloop<Self> SHalfloop;
|
||
|
typedef SHalfloop* SHalfloop_handle;
|
||
|
typedef const SHalfloop* SHalfloop_const_handle;
|
||
|
typedef SHalfloop* SHalfloop_iterator;
|
||
|
typedef const SHalfloop* SHalfloop_const_iterator;
|
||
|
|
||
|
typedef CGAL::Object_handle Object_handle;
|
||
|
/*{\Mtypemember a generic handle to an object of |\Mvar|.
|
||
|
The kind of the object can be determined and the object assigned
|
||
|
by the function:\\
|
||
|
|bool assign(xxx_handle& h, Object_handle o)|\\
|
||
|
where the function returns |true| iff the assignment of |o| to
|
||
|
|h| was valid.}*/
|
||
|
|
||
|
typedef std::list<Object_handle> Object_list;
|
||
|
typedef typename Object_list::iterator Object_iterator;
|
||
|
typedef typename Object_list::const_iterator Object_const_iterator;
|
||
|
typedef boost::optional<Object_iterator> Optional_object_iterator ;
|
||
|
typedef Generic_handle_map<Optional_object_iterator> Handle_to_iterator_map;
|
||
|
|
||
|
typedef Sphere_map* Constructor_parameter;
|
||
|
typedef const Sphere_map* Constructor_const_parameter;
|
||
|
|
||
|
class SFace_cycle_iterator : public Object_iterator
|
||
|
/*{\Mtypemember a generic iterator to an object in the boundary
|
||
|
of a facet. Convertible to |Object_handle|.}*/
|
||
|
{ typedef Object_iterator Ibase;
|
||
|
public:
|
||
|
SFace_cycle_iterator() : Ibase() {}
|
||
|
SFace_cycle_iterator(const Ibase& b) : Ibase(b) {}
|
||
|
SFace_cycle_iterator(const SFace_cycle_iterator& i) : Ibase(i) {}
|
||
|
bool is_svertex() const
|
||
|
{ SVertex_handle v; return CGAL::assign(v,Ibase::operator*()); }
|
||
|
bool is_shalfedge() const
|
||
|
{ SHalfedge_handle e; return CGAL::assign(e,Ibase::operator*()); }
|
||
|
bool is_shalfloop() const
|
||
|
{ SHalfloop_handle l; return CGAL::assign(l,Ibase::operator*()); }
|
||
|
operator SVertex_handle() const
|
||
|
{ SVertex_handle v; CGAL::assign(v,Ibase::operator*()); return v; }
|
||
|
operator SHalfedge_handle() const
|
||
|
{ SHalfedge_handle e; CGAL::assign(e,Ibase::operator*()); return e; }
|
||
|
operator SHalfloop_handle() const
|
||
|
{ SHalfloop_handle l=0; CGAL::assign(l,Ibase::operator*()); return l; }
|
||
|
|
||
|
operator Object_handle() const { return Ibase::operator*(); }
|
||
|
Object_handle& operator*() const { return Ibase::operator*(); }
|
||
|
Object_handle operator->() const
|
||
|
{ CGAL_error_msg("not impl."); return Object_handle(); }
|
||
|
};
|
||
|
|
||
|
class SFace_cycle_const_iterator : public Object_const_iterator
|
||
|
/*{\Mtypemember a generic iterator to an object in the boundary
|
||
|
of a facet. Convertible to |Object_handle|.}*/
|
||
|
{ typedef Object_const_iterator Ibase;
|
||
|
public:
|
||
|
SFace_cycle_const_iterator() : Ibase() {}
|
||
|
SFace_cycle_const_iterator(const Ibase& b) : Ibase(b) {}
|
||
|
SFace_cycle_const_iterator(const SFace_cycle_const_iterator& i)
|
||
|
: Ibase(i) {}
|
||
|
bool is_svertex() const
|
||
|
{ SVertex_handle v; return CGAL::assign(v,Ibase::operator*()); }
|
||
|
bool is_shalfedge() const
|
||
|
{ SHalfedge_handle e; return CGAL::assign(e,Ibase::operator*()); }
|
||
|
bool is_shalfloop() const
|
||
|
{ SHalfloop_handle l; return CGAL::assign(l,Ibase::operator*()); }
|
||
|
operator SVertex_const_handle() const
|
||
|
{ SVertex_handle v; CGAL::assign(v,Ibase::operator*());
|
||
|
return SVertex_const_handle(v); }
|
||
|
operator SHalfedge_const_handle() const
|
||
|
{ SHalfedge_handle e; CGAL::assign(e,Ibase::operator*());
|
||
|
return SHalfedge_const_handle(e); }
|
||
|
operator SHalfloop_const_handle() const
|
||
|
{ SHalfloop_handle l=0; CGAL::assign(l,Ibase::operator*());
|
||
|
return SHalfloop_const_handle(l); }
|
||
|
|
||
|
operator Object_handle() const { return Ibase::operator*(); }
|
||
|
const Object_handle& operator*() const { return Ibase::operator*(); }
|
||
|
Object_handle operator->() const
|
||
|
{ CGAL_error_msg("not impl."); return Object_handle(); }
|
||
|
};
|
||
|
|
||
|
/*{\Mtext Local types are handles, iterators and circulators of the
|
||
|
following kind: |SVertex_handle|, |SVertex_iterator|, |SHalfedge_handle|,
|
||
|
|SHalfedge_iterator|, |SHalfloop_handle|, |SHalfloop_iterator|,
|
||
|
|SFace_handle|, |SFace_iterator|. Additionally the following
|
||
|
circulators are defined.}*/
|
||
|
|
||
|
typedef CircFromIt<
|
||
|
SHalfedge_const_iterator,
|
||
|
move_edge_around_svertex<SHalfedge_const_iterator> >
|
||
|
SHalfedge_around_svertex_const_circulator;
|
||
|
/*{\Mtypemember circulating the adjacency list of an vertex |v|.}*/
|
||
|
|
||
|
typedef CircFromIt<
|
||
|
SHalfedge_const_iterator,
|
||
|
move_edge_around_sface<SHalfedge_const_iterator> >
|
||
|
SHalfedge_around_sface_const_circulator;
|
||
|
/*{\Mtypemember circulating the face cycle of an face |f|.}*/
|
||
|
|
||
|
typedef CircFromIt<
|
||
|
SHalfedge_iterator,
|
||
|
move_edge_around_svertex<SHalfedge_iterator> >
|
||
|
SHalfedge_around_svertex_circulator;
|
||
|
/*{\Mtypemember circulating the adjacency list of an vertex |v|.}*/
|
||
|
|
||
|
typedef CircFromIt<
|
||
|
SHalfedge_iterator,
|
||
|
move_edge_around_sface<SHalfedge_iterator> >
|
||
|
SHalfedge_around_sface_circulator;
|
||
|
/*{\Mtypemember circulating the face cycle of an face |f|.}*/
|
||
|
|
||
|
/*{\Mcreation 3}*/
|
||
|
/*{\Mtext |\Mname| is default and copy constructible. Note that copy
|
||
|
construction means cloning an isomorphic structure and is thus an
|
||
|
expensive operation.}*/
|
||
|
|
||
|
Sphere_map(bool = false) : boundary_item_(boost::none),
|
||
|
svertices_(), sedges_(), sfaces_(), shalfloop_() {}
|
||
|
|
||
|
~Sphere_map() { clear(); }
|
||
|
|
||
|
Sphere_map(const Self& D) : boundary_item_(boost::none),
|
||
|
svertices_(D.svertices_),
|
||
|
sedges_(D.sedges_),
|
||
|
sfaces_(D.sfaces_),
|
||
|
shalfloop_(0)
|
||
|
{ if ( D.shalfloop_ != 0 ) new_shalfloop_pair(*(D.shalfloop_));
|
||
|
pointer_update(D);
|
||
|
}
|
||
|
|
||
|
Self& operator=(const Self& D)
|
||
|
{ if ( this == &D ) return *this;
|
||
|
clear();
|
||
|
svertices_ = D.svertices_;
|
||
|
sfaces_ = D.sfaces_;
|
||
|
sedges_ = D.sedges_;
|
||
|
if ( D.shalfloop_ != 0 ) new_shalfloop_pair(*D.shalfloop_);
|
||
|
pointer_update(D);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
void clear()
|
||
|
{
|
||
|
boundary_item_.clear(boost::none);
|
||
|
svertices_.destroy();
|
||
|
sfaces_.destroy();
|
||
|
while ( shalfedges_begin() != shalfedges_end() )
|
||
|
delete_shalfedge_pair( shalfedges_begin() );
|
||
|
if ( shalfloop_ != 0 ) { delete_shalfloop_pair(); shalfloop_=0; }
|
||
|
}
|
||
|
|
||
|
template <typename H>
|
||
|
bool is_sm_boundary_object(H h) const
|
||
|
{ return boundary_item_[h]!=boost::none; }
|
||
|
|
||
|
template <typename H>
|
||
|
Object_iterator& sm_boundary_item(H h)
|
||
|
{ return *boundary_item_[h]; }
|
||
|
|
||
|
template <typename H>
|
||
|
void store_sm_boundary_item(H h, Object_iterator o)
|
||
|
{ boundary_item_[h] = o; }
|
||
|
|
||
|
template <typename H>
|
||
|
void undef_sm_boundary_item(H h)
|
||
|
{ CGAL_assertion(boundary_item_[h]!=boost::none);
|
||
|
boundary_item_[h] = boost::none; }
|
||
|
|
||
|
void reset_sm_iterator_hash(Object_iterator it)
|
||
|
{ SVertex_handle sv;
|
||
|
SHalfedge_handle se;
|
||
|
SHalfloop_handle sl;
|
||
|
if ( CGAL::assign(se,*it) ) { undef_sm_boundary_item(se); return; }
|
||
|
if ( CGAL::assign(sl,*it) ) { undef_sm_boundary_item(sl); return; }
|
||
|
if ( CGAL::assign(sv,*it) ) { undef_sm_boundary_item(sv); return; }
|
||
|
}
|
||
|
|
||
|
void reset_sm_object_list(Object_list& L)
|
||
|
{ Object_iterator oit;
|
||
|
CGAL_forall_iterators(oit,L) reset_sm_iterator_hash(oit);
|
||
|
L.clear();
|
||
|
}
|
||
|
|
||
|
/*{\Moperations 2.5 3}*/
|
||
|
|
||
|
// The constant iterators and circulators.
|
||
|
SVertex_const_iterator svertices_begin() const { return svertices_.begin();}
|
||
|
SVertex_const_iterator svertices_end() const { return svertices_.end();}
|
||
|
SHalfedge_const_iterator shalfedges_begin() const { return sedges_.begin();}
|
||
|
SHalfedge_const_iterator shalfedges_end() const { return sedges_.end();}
|
||
|
SHalfloop_const_iterator shalfloops_begin() const { return shalfloop_; }
|
||
|
SHalfloop_const_iterator shalfloops_end() const
|
||
|
{ return shalfloop_ != 0 ? shalfloop_+2 : shalfloop_; }
|
||
|
SFace_const_iterator sfaces_begin() const { return sfaces_.begin();}
|
||
|
SFace_const_iterator sfaces_end() const { return sfaces_.end();}
|
||
|
|
||
|
SVertex_iterator svertices_begin() { return svertices_.begin();}
|
||
|
SVertex_iterator svertices_end() { return svertices_.end();}
|
||
|
SHalfedge_iterator shalfedges_begin() { return sedges_.begin();}
|
||
|
SHalfedge_iterator shalfedges_end() { return sedges_.end();}
|
||
|
SHalfloop_iterator shalfloops_begin() { return shalfloop_; }
|
||
|
SHalfloop_iterator shalfloops_end()
|
||
|
{ return shalfloop_ != 0 ? shalfloop_+2 : shalfloop_; }
|
||
|
SFace_iterator sfaces_begin() { return sfaces_.begin();}
|
||
|
SFace_iterator sfaces_end() { return sfaces_.end();}
|
||
|
|
||
|
SFace_cycle_const_iterator sface_cycles_begin(SFace_const_handle f) const
|
||
|
{ return f->sface_cycles_begin(); }
|
||
|
SFace_cycle_const_iterator sface_cycles_end(SFace_const_handle f) const
|
||
|
{ return f->sface_cycles_end(); }
|
||
|
SFace_cycle_iterator sface_cycles_begin(SFace_handle f) const
|
||
|
{ return f->sface_cycles_begin(); }
|
||
|
SFace_cycle_iterator sface_cycles_end(SFace_handle f) const
|
||
|
{ return f->sface_cycles_end(); }
|
||
|
|
||
|
/*{\Mtext The list of all objects can be accessed via iterator ranges.
|
||
|
For comfortable iteration we also provide iterations macros.
|
||
|
The iterator range access operations are of the following kind:\\
|
||
|
|SVertex_iterator vertices_begin()/vertices_end()|\\
|
||
|
|SHalfedge_iterator halfedges_begin()/halfedges_end()|\\
|
||
|
|SHalfloop_iterator halfloops_begin()/halfloops_end()|\\
|
||
|
|SFace_iterator faces_begin()/faces_end()| */
|
||
|
|
||
|
Size_type number_of_svertices() const { return svertices_.size();}
|
||
|
/*{\Mop returns the number of vertices.}*/
|
||
|
Size_type number_of_shalfedges() const { return sedges_.size();}
|
||
|
/*{\Mop returns the number of (directed edges).}*/
|
||
|
Size_type number_of_sfaces() const { return sfaces_.size();}
|
||
|
/*{\Mop returns the number of facets.}*/
|
||
|
Size_type number_of_shalfloops() const
|
||
|
{ return shalfloop_!=SHalfloop_handle() ? 2 : 0; }
|
||
|
/*{\Mop returns the number of shalfloop.}*/
|
||
|
|
||
|
bool empty() const
|
||
|
{ return number_of_svertices() == 0 &&
|
||
|
number_of_shalfedges() == 0 &&
|
||
|
number_of_shalfloops() == 0 &&
|
||
|
number_of_sfaces() == 0;
|
||
|
}
|
||
|
|
||
|
bool has_shalfloop() const {
|
||
|
return shalfloop_ != 0;
|
||
|
}
|
||
|
|
||
|
SHalfloop_handle& shalfloop() {
|
||
|
return shalfloop_;
|
||
|
}
|
||
|
|
||
|
SHalfloop_const_handle shalfloop() const {
|
||
|
return shalfloop_;
|
||
|
}
|
||
|
|
||
|
SVertex_alloc vertex_allocator;
|
||
|
SVertex* get_vertex_node( const SVertex& ) {
|
||
|
SVertex* p = vertex_allocator.allocate(1);
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SVertex_alloc>::construct(vertex_allocator, p);
|
||
|
#else
|
||
|
vertex_allocator.construct( p, SVertex());
|
||
|
#endif
|
||
|
return p;
|
||
|
}
|
||
|
void put_vertex_node( SVertex* p) {
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SVertex_alloc>::destroy(vertex_allocator, p);
|
||
|
#else
|
||
|
vertex_allocator.destroy(p);
|
||
|
#endif
|
||
|
vertex_allocator.deallocate( p, 1);
|
||
|
}
|
||
|
|
||
|
SHalfedge_alloc halfedge_allocator;
|
||
|
SHalfedge* get_halfedge_node( const SHalfedge& ) {
|
||
|
SHalfedge* p = halfedge_allocator.allocate(1);
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SHalfedge_alloc>::construct(halfedge_allocator, p);
|
||
|
#else
|
||
|
halfedge_allocator.construct( p, SHalfedge());
|
||
|
#endif
|
||
|
return p;
|
||
|
}
|
||
|
void put_halfedge_node( SHalfedge* p) {
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SHalfedge_alloc>::destroy(halfedge_allocator, p);
|
||
|
#else
|
||
|
halfedge_allocator.destroy(p);
|
||
|
#endif
|
||
|
halfedge_allocator.deallocate( p, 1);
|
||
|
}
|
||
|
|
||
|
SFace_alloc face_allocator;
|
||
|
SFace* get_face_node( const SFace& ) {
|
||
|
SFace* p = face_allocator.allocate(1);
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SFace_alloc>::construct(face_allocator, p);
|
||
|
#else
|
||
|
face_allocator.construct( p, SFace());
|
||
|
#endif
|
||
|
return p;
|
||
|
}
|
||
|
void put_face_node( SFace* p) {
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<SFace_alloc>::destroy(face_allocator, p);
|
||
|
#else
|
||
|
face_allocator.destroy(p);
|
||
|
#endif
|
||
|
face_allocator.deallocate( p, 1);
|
||
|
}
|
||
|
|
||
|
SVertex_handle new_svertex(const Sphere_point& p,
|
||
|
Mark m = Mark())
|
||
|
/*{\Mop returns a new vertex at point |p| marked by |m|.}*/
|
||
|
{ SVertex_handle vh = new_svertex(); vh->point() = p; vh->mark() = m;
|
||
|
CGAL_NEF_TRACEN("new_svertex "<<&*vh);
|
||
|
return vh;
|
||
|
}
|
||
|
|
||
|
template <typename H>
|
||
|
void make_twins(H h1, H h2) { h1->twin() = h2; h2->twin() = h1; }
|
||
|
|
||
|
SVertex_handle new_svertex() {
|
||
|
svertices_.push_back( * get_vertex_node(SVertex()));
|
||
|
return --svertices_end();
|
||
|
}
|
||
|
|
||
|
SFace_handle new_sface() {
|
||
|
sfaces_.push_back( * get_face_node(SFace()));
|
||
|
return --sfaces_end();
|
||
|
}
|
||
|
|
||
|
SHalfedge_handle new_shalfedge_pair() {
|
||
|
SHalfedge* ep2 = get_halfedge_node(SHalfedge());
|
||
|
SHalfedge* ep1 = get_halfedge_node(SHalfedge());
|
||
|
sedges_.push_back( *ep1 );
|
||
|
SHalfedge_handle e1 = --shalfedges_end();
|
||
|
sedges_.push_back( *ep2 );
|
||
|
SHalfedge_handle e2 = --shalfedges_end();
|
||
|
make_twins(e1,e2); return e1; }
|
||
|
|
||
|
SHalfloop_handle new_shalfloop_pair()
|
||
|
{ SHalfloop_handle ph = new SHalfloop[2];
|
||
|
SHalfloop* pt(ph); ++pt;
|
||
|
make_twins(ph,pt);
|
||
|
shalfloop_=ph; return ph; }
|
||
|
|
||
|
SHalfedge_handle new_shalfedge_pair(const SHalfedge& e1)
|
||
|
{ const SHalfedge& e2 = *(e1.twin());
|
||
|
SHalfedge* ep2 = new SHalfedge[2];
|
||
|
SHalfedge* ep1 = ep2++;
|
||
|
*ep1=e1; *ep2=e2;
|
||
|
sedges_.push_back( *ep1 );
|
||
|
SHalfedge_handle eh1 = --shalfedges_end();
|
||
|
sedges_.push_back( *ep2 );
|
||
|
SHalfedge_handle eh2 = --shalfedges_end();
|
||
|
make_twins(eh1,eh2); return eh1; }
|
||
|
|
||
|
SHalfloop_handle new_shalfloop_pair(const SHalfloop& l1)
|
||
|
{ const SHalfloop& l2 = *(l1.twin());
|
||
|
SHalfloop* ph = new SHalfloop[2];
|
||
|
SHalfloop* pt(ph); ++pt;
|
||
|
*ph=l1; *pt=l2; make_twins(ph,pt);
|
||
|
shalfloop_=ph; return ph; }
|
||
|
|
||
|
void delete_svertex(SVertex_handle h) {
|
||
|
svertices_.erase(h);
|
||
|
put_vertex_node(&*h);
|
||
|
}
|
||
|
|
||
|
void delete_sface(SFace_handle h) {
|
||
|
sfaces_.erase(h);
|
||
|
put_face_node(&*h);
|
||
|
}
|
||
|
|
||
|
void delete_shalfedge_pair(SHalfedge_handle h) {
|
||
|
SHalfedge_handle t = h->twin();
|
||
|
sedges_.erase(h); sedges_.erase(t);
|
||
|
put_halfedge_node(&*h);
|
||
|
put_halfedge_node(&*t);
|
||
|
}
|
||
|
|
||
|
void delete_shalfloop_pair() {
|
||
|
CGAL_assertion(has_shalfloop());
|
||
|
SHalfloop* ph = &*shalfloop_;
|
||
|
SHalfloop* pt = &*shalfloop_->twin();
|
||
|
if ( ph > pt ) std::swap(ph,pt);
|
||
|
shalfloop_ = SHalfloop_handle();
|
||
|
delete [] ph; }
|
||
|
|
||
|
protected:
|
||
|
void pointer_update(const Self& D);
|
||
|
Handle_to_iterator_map boundary_item_;
|
||
|
|
||
|
SVertex_list svertices_;
|
||
|
SHalfedge_list sedges_;
|
||
|
SFace_list sfaces_;
|
||
|
SHalfloop_iterator shalfloop_;
|
||
|
|
||
|
}; // Sphere_map
|
||
|
|
||
|
|
||
|
template <typename K, typename I, typename M>
|
||
|
void Sphere_map<K, I, M>::
|
||
|
pointer_update(const Sphere_map<K, I, M>& D)
|
||
|
{
|
||
|
CGAL::Unique_hash_map<SVertex_const_handle,SVertex_handle> VM;
|
||
|
CGAL::Unique_hash_map<SHalfedge_const_handle,SHalfedge_handle> EM;
|
||
|
CGAL::Unique_hash_map<SHalfloop_const_handle,SHalfloop_handle> LM;
|
||
|
CGAL::Unique_hash_map<SFace_const_handle,SFace_handle> FM;
|
||
|
|
||
|
SVertex_const_iterator vc = D.svertices_begin();
|
||
|
SVertex_iterator v = svertices_begin();
|
||
|
for ( ; vc != D.svertices_end(); ++vc,++v) VM[vc] = v;
|
||
|
VM[D.svertices_end()] = svertices_end();
|
||
|
|
||
|
SHalfedge_const_iterator ec = D.shalfedges_begin();
|
||
|
SHalfedge_iterator e = shalfedges_begin();
|
||
|
for ( ; ec != D.shalfedges_end(); ++ec,++e) {
|
||
|
EM[ec] = e;
|
||
|
e->mark() = ec->mark();
|
||
|
}
|
||
|
EM[D.shalfedges_end()] = shalfedges_end();
|
||
|
|
||
|
SFace_const_iterator fc = D.sfaces_begin();
|
||
|
SFace_iterator f = sfaces_begin();
|
||
|
for ( ; fc != D.sfaces_end(); ++fc,++f) FM[fc] = f;
|
||
|
FM[D.sfaces_end()] = sfaces_end();
|
||
|
|
||
|
SHalfloop_iterator l;
|
||
|
if ( D.shalfloop_ != 0 ) {
|
||
|
LM[D.shalfloop_] = shalfloop_;
|
||
|
LM[D.shalfloop_->twin()] = shalfloop_->twin();
|
||
|
l = shalfloop();
|
||
|
shalfloop_->mark() = D.shalfloop()->mark();
|
||
|
shalfloop_->twin()->mark() = D.shalfloop()->twin()->mark();
|
||
|
if( !l->is_twin() && D.shalfloop()->is_twin()) l->mark() = l->twin()->mark();
|
||
|
}
|
||
|
|
||
|
for (v = svertices_begin(); v != svertices_end(); ++v) {
|
||
|
// Local Graph update: (SVertices are postponed/updated as Edges)
|
||
|
v->out_sedge() = EM[v->out_sedge()];
|
||
|
v->incident_sface() = FM[v->incident_sface()];
|
||
|
}
|
||
|
// Edge update:
|
||
|
for (e = shalfedges_begin(); e != shalfedges_end(); ++e) {
|
||
|
e->twin() = EM[e->twin()];
|
||
|
e->sprev() = EM[e->sprev()];
|
||
|
e->snext() = EM[e->snext()];
|
||
|
e->source() = VM[e->source()];
|
||
|
e->incident_sface() = FM[e->incident_sface()];
|
||
|
}
|
||
|
for ( ec = D.shalfedges_begin(), e = shalfedges_begin();
|
||
|
ec != D.shalfedges_end(); ++ec, ++e) {
|
||
|
if( !e->is_twin() && ec->is_twin()) e->mark() = e->twin()->mark();
|
||
|
}
|
||
|
|
||
|
for (l = shalfloops_begin(); l != shalfloops_end(); ++l) {
|
||
|
// l->twin() = LM[l->twin()];
|
||
|
l->incident_sface() = FM[l->incident_sface()];
|
||
|
}
|
||
|
|
||
|
|
||
|
for (f = sfaces_begin(); f != sfaces_end(); ++f) {
|
||
|
SFace_cycle_iterator fci;
|
||
|
for(fci = f->boundary_entry_objects().begin();
|
||
|
fci != f->boundary_entry_objects().end(); ++fci) {
|
||
|
if ( fci.is_svertex() )
|
||
|
{ v = SVertex_handle(fci);
|
||
|
*fci = make_object(VM[v]); store_sm_boundary_item(v,fci); }
|
||
|
else if ( fci.is_shalfedge() )
|
||
|
{ e = SHalfedge_handle(fci);
|
||
|
*fci = make_object(EM[e]); store_sm_boundary_item(e,fci); }
|
||
|
else if ( fci.is_shalfloop() )
|
||
|
{ l = SHalfloop_handle(fci);
|
||
|
*fci = make_object(LM[l]); store_sm_boundary_item(l,fci); }
|
||
|
else CGAL_error_msg("damn wrong boundary item in face.");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
} //namespace CGAL
|
||
|
#endif // CGAL_SPHERE_MAP_H
|