3029 lines
110 KiB
C
3029 lines
110 KiB
C
|
// Copyright (c) 2005,2006,2007,2008,2009,2010,2011 Tel-Aviv University (Israel).
|
||
|
// 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): Ron Wein <wein@post.tau.ac.il>
|
||
|
// Efi Fogel <efif@post.tau.ac.il>
|
||
|
// Eric Berberich <ericb@post.tau.ac.il>
|
||
|
// (based on old version by: Iddo Hanniel,
|
||
|
// Eyal Flato,
|
||
|
// Oren Nechushtan,
|
||
|
// Ester Ezra,
|
||
|
// Shai Hirsch,
|
||
|
// and Eugene Lipovetsky)
|
||
|
#ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||
|
#define CGAL_ARRANGEMENT_ON_SURFACE_2_H
|
||
|
|
||
|
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||
|
|
||
|
#include <CGAL/disable_warnings.h>
|
||
|
|
||
|
/*! \file
|
||
|
* The header file for the Arrangement_on_surface_2<Traits,Dcel> class.
|
||
|
*/
|
||
|
|
||
|
#include <map>
|
||
|
#include <vector>
|
||
|
#include <algorithm>
|
||
|
#include <boost/mpl/assert.hpp>
|
||
|
|
||
|
#include <CGAL/Arr_tags.h>
|
||
|
#include <CGAL/Arr_enums.h>
|
||
|
#include <CGAL/HalfedgeDS_iterator.h>
|
||
|
#include <CGAL/Arrangement_2/Arrangement_2_iterators.h>
|
||
|
#include <CGAL/In_place_list.h>
|
||
|
#include <CGAL/Arr_default_dcel.h>
|
||
|
#include <CGAL/Arr_observer.h>
|
||
|
#include <CGAL/Arr_accessor.h>
|
||
|
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
|
||
|
#include <CGAL/function_objects.h>
|
||
|
#include <CGAL/Iterator_project.h>
|
||
|
#include <CGAL/Iterator_transform.h>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
/*! \class Arrangement_on_surface_2
|
||
|
* The arrangement class, representing 2-dimensional subdivisions induced on
|
||
|
* an arbitrary surface by a set of arbitrary planar curves.
|
||
|
* The GeomTraits parameter corresponds to a geometry-traits class that
|
||
|
* defines the Point_2 and X_monotone_curve_2 types and implements the
|
||
|
* geometric predicates and constructions for the family of curves it defines.
|
||
|
* The TopTraits parameter corresponds to a topology-traits class that defines
|
||
|
* the topological structure of the surface. Note that the geometry traits
|
||
|
* class should also be aware of the kind of surface on which its curves and
|
||
|
* points are defined.
|
||
|
*/
|
||
|
template <typename GeomTraits_, typename TopTraits_>
|
||
|
class Arrangement_on_surface_2 {
|
||
|
public:
|
||
|
typedef GeomTraits_ Geometry_traits_2;
|
||
|
typedef TopTraits_ Topology_traits;
|
||
|
typedef CGAL_ALLOCATOR(int) Allocator;
|
||
|
|
||
|
// first define adaptor ...
|
||
|
typedef Arr_traits_basic_adaptor_2<Geometry_traits_2> Traits_adaptor_2;
|
||
|
|
||
|
// .. as it completes (potentially) missing side tags
|
||
|
typedef typename Traits_adaptor_2::Left_side_category Left_side_category;
|
||
|
typedef typename Traits_adaptor_2::Bottom_side_category Bottom_side_category;
|
||
|
typedef typename Traits_adaptor_2::Top_side_category Top_side_category;
|
||
|
typedef typename Traits_adaptor_2::Right_side_category Right_side_category;
|
||
|
|
||
|
BOOST_MPL_ASSERT(
|
||
|
(typename
|
||
|
Arr_sane_identified_tagging<Left_side_category,
|
||
|
Bottom_side_category,
|
||
|
Top_side_category,
|
||
|
Right_side_category>::result)
|
||
|
);
|
||
|
|
||
|
public:
|
||
|
typedef Arrangement_on_surface_2<Geometry_traits_2, Topology_traits>
|
||
|
Self;
|
||
|
|
||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||
|
typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||
|
|
||
|
// maybe remove this in a future version (that supports complete handling
|
||
|
// of all sides)
|
||
|
typedef typename Arr_are_all_sides_oblivious_tag<Left_side_category,
|
||
|
Bottom_side_category,
|
||
|
Top_side_category,
|
||
|
Right_side_category>::result
|
||
|
Are_all_sides_oblivious_category;
|
||
|
|
||
|
typedef typename Arr_has_identified_sides<Left_side_category,
|
||
|
Bottom_side_category>::result
|
||
|
Has_identified_sides_category;
|
||
|
|
||
|
typedef typename Arr_two_sides_category<Bottom_side_category,
|
||
|
Top_side_category>::result
|
||
|
Top_or_bottom_sides_category;
|
||
|
|
||
|
public:
|
||
|
typedef typename Topology_traits::Dcel Dcel;
|
||
|
typedef typename Dcel::Size Size;
|
||
|
|
||
|
protected:
|
||
|
friend class Arr_observer<Self>;
|
||
|
friend class Arr_accessor<Self>;
|
||
|
|
||
|
// Internal DCEL types:
|
||
|
typedef typename Dcel::Vertex DVertex;
|
||
|
typedef typename Dcel::Halfedge DHalfedge;
|
||
|
typedef typename Dcel::Face DFace;
|
||
|
typedef typename Dcel::Outer_ccb DOuter_ccb;
|
||
|
typedef typename Dcel::Inner_ccb DInner_ccb;
|
||
|
typedef typename Dcel::Isolated_vertex DIso_vertex;
|
||
|
|
||
|
typedef typename Dcel::difference_type DDifference;
|
||
|
typedef typename Dcel::iterator_category DIterator_category;
|
||
|
|
||
|
typedef typename Dcel::Vertex_iterator DVertex_iter;
|
||
|
typedef typename Dcel::Vertex_const_iterator DVertex_const_iter;
|
||
|
|
||
|
typedef typename Dcel::Halfedge_iterator DHalfedge_iter;
|
||
|
typedef typename Dcel::Halfedge_const_iterator DHalfedge_const_iter;
|
||
|
|
||
|
typedef typename Dcel::Edge_iterator DEdge_iter;
|
||
|
typedef typename Dcel::Edge_const_iterator DEdge_const_iter;
|
||
|
|
||
|
typedef typename Dcel::Face_iterator DFace_iter;
|
||
|
typedef typename Dcel::Face_const_iterator DFace_const_iter;
|
||
|
|
||
|
typedef typename DFace::Outer_ccb_iterator DOuter_ccb_iter;
|
||
|
typedef typename DFace::Outer_ccb_const_iterator DOuter_ccb_const_iter;
|
||
|
|
||
|
typedef typename DFace::Inner_ccb_iterator DInner_ccb_iter;
|
||
|
typedef typename DFace::Inner_ccb_const_iterator DInner_ccb_const_iter;
|
||
|
|
||
|
typedef typename DFace::Isolated_vertex_iterator DIso_vertex_iter;
|
||
|
typedef typename DFace::Isolated_vertex_const_iterator
|
||
|
DIso_vertex_const_iter;
|
||
|
|
||
|
protected:
|
||
|
/*! \class
|
||
|
* A functor for filtering DCEL vertices at infinity.
|
||
|
*/
|
||
|
class _Is_concrete_vertex {
|
||
|
private:
|
||
|
const Topology_traits* m_topol_traits;
|
||
|
|
||
|
public:
|
||
|
_Is_concrete_vertex() : m_topol_traits(NULL) {}
|
||
|
|
||
|
_Is_concrete_vertex(const Topology_traits* topol_traits) :
|
||
|
m_topol_traits(topol_traits)
|
||
|
{}
|
||
|
|
||
|
bool operator()(const DVertex& v) const
|
||
|
{
|
||
|
if (m_topol_traits == NULL)
|
||
|
return true;
|
||
|
|
||
|
return (m_topol_traits->is_concrete_vertex(&v));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*! \class
|
||
|
* A functor for filtering fictitious DCEL vertices.
|
||
|
*/
|
||
|
class _Is_valid_vertex {
|
||
|
private:
|
||
|
const Topology_traits* m_topol_traits;
|
||
|
|
||
|
public:
|
||
|
_Is_valid_vertex() : m_topol_traits(NULL) {}
|
||
|
|
||
|
_Is_valid_vertex(const Topology_traits* topol_traits) :
|
||
|
m_topol_traits(topol_traits)
|
||
|
{}
|
||
|
|
||
|
bool operator()(const DVertex& v) const
|
||
|
{
|
||
|
if (m_topol_traits == NULL)
|
||
|
return true;
|
||
|
|
||
|
return (m_topol_traits->is_valid_vertex(&v));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*! \struct
|
||
|
* A functor for filtering fictitious DCEL halfedges.
|
||
|
*/
|
||
|
class _Is_valid_halfedge {
|
||
|
private:
|
||
|
const Topology_traits* m_topol_traits;
|
||
|
|
||
|
public:
|
||
|
_Is_valid_halfedge() : m_topol_traits(NULL) {}
|
||
|
|
||
|
_Is_valid_halfedge(const Topology_traits* topol_traits) :
|
||
|
m_topol_traits(topol_traits)
|
||
|
{}
|
||
|
|
||
|
bool operator()(const DHalfedge& he) const
|
||
|
{
|
||
|
if (m_topol_traits == NULL)
|
||
|
return true;
|
||
|
|
||
|
return (m_topol_traits->is_valid_halfedge(&he));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*! \struct
|
||
|
* A functor for filtering the fictitious faces.
|
||
|
*/
|
||
|
class _Is_valid_face {
|
||
|
private:
|
||
|
const Topology_traits* m_topol_traits;
|
||
|
|
||
|
public:
|
||
|
_Is_valid_face() : m_topol_traits(NULL) {}
|
||
|
|
||
|
_Is_valid_face(const Topology_traits* topol_traits) :
|
||
|
m_topol_traits(topol_traits)
|
||
|
{}
|
||
|
|
||
|
bool operator()(const DFace& f) const
|
||
|
{
|
||
|
if (m_topol_traits == NULL)
|
||
|
return true;
|
||
|
|
||
|
return (m_topol_traits->is_valid_face(&f));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*! \struct
|
||
|
* A functor for filtering bounded faces.
|
||
|
*/
|
||
|
class _Is_unbounded_face {
|
||
|
private:
|
||
|
const Topology_traits* m_topol_traits;
|
||
|
|
||
|
public:
|
||
|
_Is_unbounded_face() : m_topol_traits(NULL) {}
|
||
|
|
||
|
_Is_unbounded_face(const Topology_traits* topol_traits) :
|
||
|
m_topol_traits(topol_traits)
|
||
|
{}
|
||
|
|
||
|
const Topology_traits* topology_traits() const { return m_topol_traits; }
|
||
|
|
||
|
bool operator()(const DFace& f) const
|
||
|
{
|
||
|
return (m_topol_traits->is_valid_face(&f) &&
|
||
|
m_topol_traits->is_unbounded(&f));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
// Forward declerations:
|
||
|
class Vertex;
|
||
|
class Halfedge;
|
||
|
class Face;
|
||
|
|
||
|
// Definition of the halfedge data-structure itereators and circulators:
|
||
|
typedef I_Filtered_iterator<DVertex_iter, _Is_concrete_vertex,
|
||
|
Vertex, DDifference, DIterator_category>
|
||
|
Vertex_iterator;
|
||
|
|
||
|
typedef I_Filtered_const_iterator<DVertex_const_iter, _Is_concrete_vertex,
|
||
|
DVertex_iter, Vertex, DDifference,
|
||
|
DIterator_category>
|
||
|
Vertex_const_iterator;
|
||
|
|
||
|
typedef I_Filtered_iterator<DHalfedge_iter, _Is_valid_halfedge,
|
||
|
Halfedge, DDifference, DIterator_category>
|
||
|
Halfedge_iterator;
|
||
|
|
||
|
typedef I_Filtered_const_iterator<DHalfedge_const_iter, _Is_valid_halfedge,
|
||
|
DHalfedge_iter, Halfedge, DDifference,
|
||
|
DIterator_category>
|
||
|
Halfedge_const_iterator;
|
||
|
|
||
|
/*! \class
|
||
|
* Edges iterator - defined as a derived class to make it assignable
|
||
|
* to the halfedge iterator type.
|
||
|
*/
|
||
|
class Edge_iterator :
|
||
|
public I_Filtered_iterator<DEdge_iter, _Is_valid_halfedge,
|
||
|
Halfedge, DDifference, DIterator_category>
|
||
|
{
|
||
|
typedef I_Filtered_iterator<DEdge_iter, _Is_valid_halfedge,
|
||
|
Halfedge, DDifference, DIterator_category>
|
||
|
Base;
|
||
|
|
||
|
public:
|
||
|
Edge_iterator() {}
|
||
|
|
||
|
Edge_iterator(DEdge_iter iter, DEdge_iter iend,
|
||
|
const _Is_valid_halfedge& pred) :
|
||
|
Base(iter, iend, pred)
|
||
|
{}
|
||
|
|
||
|
// Casting to a halfedge iterator.
|
||
|
operator Halfedge_iterator() const
|
||
|
{
|
||
|
return (Halfedge_iterator(DHalfedge_iter(this->current_iterator())));
|
||
|
}
|
||
|
|
||
|
operator Halfedge_const_iterator() const
|
||
|
{
|
||
|
return (Halfedge_const_iterator
|
||
|
(DHalfedge_const_iter(this->current_iterator())));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class Edge_const_iterator :
|
||
|
public I_Filtered_const_iterator<DEdge_const_iter, _Is_valid_halfedge,
|
||
|
DEdge_iter, Halfedge, DDifference,
|
||
|
DIterator_category>
|
||
|
{
|
||
|
typedef I_Filtered_const_iterator<DEdge_const_iter, _Is_valid_halfedge,
|
||
|
DEdge_iter, Halfedge, DDifference,
|
||
|
DIterator_category> Base;
|
||
|
|
||
|
public:
|
||
|
Edge_const_iterator() {}
|
||
|
|
||
|
Edge_const_iterator(Edge_iterator iter) :
|
||
|
Base(iter.current_iterator(), iter.past_the_end(), iter.filter())
|
||
|
{}
|
||
|
|
||
|
Edge_const_iterator(DEdge_const_iter iter, DEdge_const_iter iend,
|
||
|
const _Is_valid_halfedge& pred) :
|
||
|
Base(iter, iend, pred)
|
||
|
{}
|
||
|
|
||
|
// Casting to a halfedge iterator.
|
||
|
operator Halfedge_const_iterator() const
|
||
|
{
|
||
|
return (Halfedge_const_iterator
|
||
|
(DHalfedge_const_iter(this->current_iterator())));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef I_Filtered_iterator<DFace_iter, _Is_valid_face,
|
||
|
Face, DDifference,
|
||
|
DIterator_category> Face_iterator;
|
||
|
|
||
|
typedef I_Filtered_const_iterator<DFace_const_iter, _Is_valid_face,
|
||
|
DFace_iter, Face,
|
||
|
DDifference, DIterator_category>
|
||
|
Face_const_iterator;
|
||
|
|
||
|
typedef _HalfedgeDS_vertex_circ<Halfedge, Halfedge_iterator,
|
||
|
Bidirectional_circulator_tag>
|
||
|
Halfedge_around_vertex_circulator;
|
||
|
|
||
|
typedef _HalfedgeDS_vertex_const_circ<Halfedge, Halfedge_const_iterator,
|
||
|
Bidirectional_circulator_tag>
|
||
|
Halfedge_around_vertex_const_circulator;
|
||
|
|
||
|
typedef _HalfedgeDS_facet_circ<Halfedge, Halfedge_iterator,
|
||
|
Bidirectional_circulator_tag>
|
||
|
Ccb_halfedge_circulator;
|
||
|
|
||
|
typedef _HalfedgeDS_facet_const_circ<Halfedge, Halfedge_const_iterator,
|
||
|
Bidirectional_circulator_tag>
|
||
|
Ccb_halfedge_const_circulator;
|
||
|
|
||
|
/*! \class
|
||
|
* Unbounded faces iterator - defined as a derived class to make it
|
||
|
* assignable to the face iterator type.
|
||
|
*/
|
||
|
class Unbounded_face_iterator :
|
||
|
public I_Filtered_iterator<DFace_iter, _Is_unbounded_face,
|
||
|
Face, DDifference, DIterator_category>
|
||
|
{
|
||
|
typedef I_Filtered_iterator<DFace_iter, _Is_unbounded_face,
|
||
|
Face, DDifference, DIterator_category>
|
||
|
Base;
|
||
|
|
||
|
public:
|
||
|
Unbounded_face_iterator() {}
|
||
|
|
||
|
Unbounded_face_iterator(DFace_iter iter, DFace_iter iend,
|
||
|
const _Is_unbounded_face& is_unbounded) :
|
||
|
Base(iter, iend, is_unbounded)
|
||
|
{}
|
||
|
|
||
|
// Casting to a face iterator.
|
||
|
operator Face_iterator() const
|
||
|
{
|
||
|
return (Face_iterator(DFace_iter(this->current_iterator()),
|
||
|
DFace_iter(this->past_the_end()),
|
||
|
_Is_valid_face(this->filter().topology_traits())));
|
||
|
}
|
||
|
|
||
|
operator Face_const_iterator() const
|
||
|
{
|
||
|
return (Face_const_iterator
|
||
|
(DFace_const_iter(this->current_iterator()),
|
||
|
DFace_const_iter(this->past_the_end()),
|
||
|
_Is_valid_face(this->filter().topology_traits())));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class Unbounded_face_const_iterator :
|
||
|
public I_Filtered_const_iterator<DFace_const_iter, _Is_unbounded_face,
|
||
|
DFace_iter, Face, DDifference,
|
||
|
DIterator_category>
|
||
|
{
|
||
|
typedef I_Filtered_const_iterator<DFace_const_iter, _Is_unbounded_face,
|
||
|
DFace_iter, Face, DDifference,
|
||
|
DIterator_category> Base;
|
||
|
|
||
|
public:
|
||
|
Unbounded_face_const_iterator() {}
|
||
|
|
||
|
Unbounded_face_const_iterator(Unbounded_face_iterator iter) : Base(iter) {}
|
||
|
|
||
|
Unbounded_face_const_iterator(DFace_const_iter iter,
|
||
|
DFace_const_iter iend,
|
||
|
const _Is_unbounded_face& is_unbounded) :
|
||
|
Base(iter, iend, is_unbounded)
|
||
|
{}
|
||
|
|
||
|
// Casting to a face iterator.
|
||
|
operator Face_const_iterator() const
|
||
|
{
|
||
|
return (Face_const_iterator(DFace_const_iter(this->current_iterator()),
|
||
|
DFace_const_iter(this->past_the_end())));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
protected:
|
||
|
struct _Halfedge_to_ccb_circulator {
|
||
|
typedef DHalfedge* argument_type;
|
||
|
typedef Ccb_halfedge_circulator result_type;
|
||
|
|
||
|
result_type operator()(argument_type s) const
|
||
|
{ return Ccb_halfedge_circulator(Halfedge_iterator(s)); }
|
||
|
};
|
||
|
|
||
|
struct _Const_halfedge_to_ccb_circulator {
|
||
|
typedef const DHalfedge* argument_type;
|
||
|
typedef Ccb_halfedge_const_circulator result_type;
|
||
|
|
||
|
result_type operator()(argument_type s) const
|
||
|
{ return Ccb_halfedge_const_circulator(Halfedge_const_iterator(s)); }
|
||
|
};
|
||
|
|
||
|
typedef Cast_function_object<DVertex, Vertex> _Vertex_to_vertex;
|
||
|
|
||
|
public:
|
||
|
typedef Iterator_transform<DOuter_ccb_iter, _Halfedge_to_ccb_circulator>
|
||
|
Outer_ccb_iterator;
|
||
|
|
||
|
typedef Iterator_transform<DOuter_ccb_const_iter,
|
||
|
_Const_halfedge_to_ccb_circulator>
|
||
|
Outer_ccb_const_iterator;
|
||
|
|
||
|
typedef Iterator_transform<DInner_ccb_iter, _Halfedge_to_ccb_circulator>
|
||
|
Inner_ccb_iterator;
|
||
|
|
||
|
typedef Iterator_transform<DInner_ccb_const_iter,
|
||
|
_Const_halfedge_to_ccb_circulator>
|
||
|
Inner_ccb_const_iterator;
|
||
|
|
||
|
/*! \class
|
||
|
* Isolated vertices iterator - defined as a class to make it assignable
|
||
|
* to the vertex iterator type.
|
||
|
*/
|
||
|
class Isolated_vertex_iterator :
|
||
|
public Iterator_project<DIso_vertex_iter, _Vertex_to_vertex>
|
||
|
{
|
||
|
typedef Iterator_project<DIso_vertex_iter, _Vertex_to_vertex> Base;
|
||
|
|
||
|
public:
|
||
|
Isolated_vertex_iterator() {}
|
||
|
|
||
|
Isolated_vertex_iterator(DIso_vertex_iter iter) : Base(iter) {}
|
||
|
|
||
|
// Casting to a vertex iterator.
|
||
|
operator Vertex_iterator() const
|
||
|
{ return (Vertex_iterator(DVertex_iter(this->ptr()))); }
|
||
|
|
||
|
operator Vertex_const_iterator() const
|
||
|
{ return (Vertex_const_iterator(DVertex_const_iter(this->ptr()))); }
|
||
|
};
|
||
|
|
||
|
class Isolated_vertex_const_iterator :
|
||
|
public Iterator_project<DIso_vertex_const_iter, _Vertex_to_vertex>
|
||
|
{
|
||
|
typedef Iterator_project<DIso_vertex_const_iter, _Vertex_to_vertex> Base;
|
||
|
|
||
|
public:
|
||
|
Isolated_vertex_const_iterator() {}
|
||
|
|
||
|
Isolated_vertex_const_iterator(Isolated_vertex_iterator iter) :
|
||
|
Base(iter)
|
||
|
{}
|
||
|
|
||
|
Isolated_vertex_const_iterator(DIso_vertex_const_iter iter) :
|
||
|
Base(iter)
|
||
|
{}
|
||
|
|
||
|
// Casting to a vertex iterator.
|
||
|
operator Vertex_const_iterator() const
|
||
|
{ return (Vertex_const_iterator(DVertex_const_iter(this->ptr()))); }
|
||
|
};
|
||
|
|
||
|
protected:
|
||
|
class _Valid_vertex_iterator :
|
||
|
public I_Filtered_iterator<DVertex_iter, _Is_valid_vertex, Vertex,
|
||
|
DDifference, DIterator_category>
|
||
|
{
|
||
|
typedef I_Filtered_iterator<DVertex_iter, _Is_valid_vertex, Vertex,
|
||
|
DDifference, DIterator_category> Base;
|
||
|
|
||
|
public:
|
||
|
_Valid_vertex_iterator() {}
|
||
|
|
||
|
_Valid_vertex_iterator(DVertex_iter iter, DVertex_iter iend,
|
||
|
const _Is_valid_vertex& pred) :
|
||
|
Base(iter, iend, pred)
|
||
|
{}
|
||
|
|
||
|
// Casting to a vertex iterator.
|
||
|
operator Vertex_iterator() const
|
||
|
{ return (Vertex_iterator(DVertex_iter(this->current_iterator()))); }
|
||
|
|
||
|
operator Vertex_const_iterator() const
|
||
|
{
|
||
|
return (Vertex_const_iterator(DVertex_const_iter
|
||
|
(this->current_iterator())));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
// Definition of handles (equivalent to iterators):
|
||
|
typedef Vertex_iterator Vertex_handle;
|
||
|
typedef Halfedge_iterator Halfedge_handle;
|
||
|
typedef Face_iterator Face_handle;
|
||
|
|
||
|
typedef Vertex_const_iterator Vertex_const_handle;
|
||
|
typedef Halfedge_const_iterator Halfedge_const_handle;
|
||
|
typedef Face_const_iterator Face_const_handle;
|
||
|
|
||
|
/*! \class
|
||
|
* The arrangement vertex class.
|
||
|
*/
|
||
|
class Vertex : public DVertex {
|
||
|
typedef DVertex Base;
|
||
|
|
||
|
public:
|
||
|
/*! Default constrcutor. */
|
||
|
Vertex() {}
|
||
|
|
||
|
/*! Check whether the vertex lies on an open boundary. */
|
||
|
bool is_at_open_boundary() const { return (Base::has_null_point()); }
|
||
|
|
||
|
/*! Get the vertex degree (number of incident edges). */
|
||
|
Size degree() const
|
||
|
{
|
||
|
if (this->is_isolated())
|
||
|
return (0);
|
||
|
|
||
|
// Go around the vertex and count the incident halfedges.
|
||
|
const DHalfedge* he_first = Base::halfedge();
|
||
|
const DHalfedge* he_curr = he_first;
|
||
|
Size n = 0;
|
||
|
|
||
|
if (he_curr != NULL) {
|
||
|
do {
|
||
|
++n;
|
||
|
he_curr = he_curr->next()->opposite();
|
||
|
} while (he_curr != he_first);
|
||
|
}
|
||
|
return (n);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get the incident halfedges (non-const version).
|
||
|
* \pre The vertex is not isolated.
|
||
|
*/
|
||
|
Halfedge_around_vertex_circulator incident_halfedges()
|
||
|
{
|
||
|
CGAL_precondition(! this->is_isolated());
|
||
|
return Halfedge_around_vertex_circulator
|
||
|
(DHalfedge_iter(Base::halfedge()));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get the incident halfedges (const version).
|
||
|
* \pre The vertex is not isolated.
|
||
|
*/
|
||
|
Halfedge_around_vertex_const_circulator incident_halfedges() const
|
||
|
{
|
||
|
CGAL_precondition(! this->is_isolated());
|
||
|
return Halfedge_around_vertex_const_circulator
|
||
|
(DHalfedge_const_iter(Base::halfedge()));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get the face that contains the vertex (non-const version).
|
||
|
* \pre The vertex is isolated.
|
||
|
*/
|
||
|
Face_handle face()
|
||
|
{
|
||
|
CGAL_precondition(this->is_isolated());
|
||
|
return (DFace_iter(Base::isolated_vertex()->face()));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get the face that contains the vertex (const version).
|
||
|
* \pre The vertex is isolated.
|
||
|
*/
|
||
|
Face_const_handle face() const
|
||
|
{
|
||
|
CGAL_precondition(this->is_isolated());
|
||
|
return (DFace_const_iter(Base::isolated_vertex()->face()));
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
// Blocking access to inherited functions from the Dcel::Vertex.
|
||
|
bool has_null_point() const;
|
||
|
void set_point(Point_2* );
|
||
|
void set_boundary(Arr_parameter_space , Arr_parameter_space );
|
||
|
const DHalfedge* halfedge() const;
|
||
|
DHalfedge* halfedge();
|
||
|
void set_halfedge(DHalfedge* );
|
||
|
const DIso_vertex* isolated_vertex() const;
|
||
|
DIso_vertex* isolated_vertex();
|
||
|
void set_isolated_vertex(DIso_vertex* );
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
* \class The arrangement halfedge class.
|
||
|
*/
|
||
|
class Halfedge : public DHalfedge {
|
||
|
typedef DHalfedge Base;
|
||
|
|
||
|
public:
|
||
|
/*! Default constrcutor. */
|
||
|
Halfedge() {}
|
||
|
|
||
|
/*! Check whether the halfedge is fictitious. */
|
||
|
bool is_fictitious() const
|
||
|
{ return (Base::has_null_curve()); }
|
||
|
|
||
|
/*! Get the source vertex (non-const version). */
|
||
|
Vertex_handle source()
|
||
|
{ return (DVertex_iter(Base::opposite()->vertex())); }
|
||
|
|
||
|
/*! Get the source vertex (const version). */
|
||
|
Vertex_const_handle source() const
|
||
|
{ return (DVertex_const_iter(Base::opposite()->vertex())); }
|
||
|
|
||
|
/*! Get the target vertex (non-const version). */
|
||
|
Vertex_handle target()
|
||
|
{ return (DVertex_iter(Base::vertex())); }
|
||
|
|
||
|
/*! Get the target vertex (const version). */
|
||
|
Vertex_const_handle target() const
|
||
|
{ return (DVertex_const_iter(Base::vertex())); }
|
||
|
|
||
|
/*! Get the incident face (non-const version). */
|
||
|
Face_handle face()
|
||
|
{
|
||
|
return (! Base::is_on_inner_ccb()) ?
|
||
|
DFace_iter(Base::outer_ccb()->face()) :
|
||
|
DFace_iter(Base::inner_ccb()->face());
|
||
|
}
|
||
|
|
||
|
/*! Get the incident face (const version). */
|
||
|
Face_const_handle face() const
|
||
|
{
|
||
|
return (! Base::is_on_inner_ccb()) ?
|
||
|
DFace_const_iter(Base::outer_ccb()->face()) :
|
||
|
DFace_const_iter(Base::inner_ccb()->face());
|
||
|
}
|
||
|
|
||
|
/*! Get the twin halfedge (non-const version). */
|
||
|
Halfedge_handle twin()
|
||
|
{ return (DHalfedge_iter(Base::opposite())); }
|
||
|
|
||
|
/*! Get the twin halfedge (const version). */
|
||
|
Halfedge_const_handle twin() const
|
||
|
{ return (DHalfedge_const_iter(Base::opposite())); }
|
||
|
|
||
|
/*! Get the previous halfegde in the chain (non-const version). */
|
||
|
Halfedge_handle prev()
|
||
|
{ return (DHalfedge_iter(Base::prev())); }
|
||
|
|
||
|
/*! Get the previous halfegde in the chain (const version). */
|
||
|
Halfedge_const_handle prev() const
|
||
|
{ return (DHalfedge_const_iter(Base::prev())); }
|
||
|
|
||
|
/*! Get the next halfegde in the chain (non-const version). */
|
||
|
Halfedge_handle next()
|
||
|
{ return (DHalfedge_iter(Base::next())); }
|
||
|
|
||
|
/*! Get the next halfegde in the chain (const version). */
|
||
|
Halfedge_const_handle next() const
|
||
|
{ return (DHalfedge_const_iter(Base::next())); }
|
||
|
|
||
|
/*! Get the connected component of the halfedge (non-const version). */
|
||
|
Ccb_halfedge_circulator ccb()
|
||
|
{ return Ccb_halfedge_circulator(DHalfedge_iter(this)); }
|
||
|
|
||
|
/*! Get the connected component of the halfedge (const version). */
|
||
|
Ccb_halfedge_const_circulator ccb() const
|
||
|
{ return Ccb_halfedge_const_circulator(DHalfedge_const_iter(this)); }
|
||
|
|
||
|
private:
|
||
|
|
||
|
// Blocking access to inherited functions from the Dcel::Halfedge.
|
||
|
bool has_null_curve() const;
|
||
|
void set_curve(X_monotone_curve_2* );
|
||
|
const DHalfedge* opposite() const;
|
||
|
DHalfedge* opposite();
|
||
|
void set_opposite(DHalfedge* );
|
||
|
void set_direction(Arr_halfedge_direction );
|
||
|
void set_prev(DHalfedge* );
|
||
|
void set_next(DHalfedge* );
|
||
|
const DVertex* vertex() const ;
|
||
|
DVertex* vertex();
|
||
|
void set_vertex(DVertex* );
|
||
|
const DOuter_ccb* outer_ccb() const;
|
||
|
DOuter_ccb* outer_ccb();
|
||
|
void set_outer_ccb(DOuter_ccb* );
|
||
|
const DInner_ccb* inner_ccb() const;
|
||
|
DInner_ccb* inner_ccb();
|
||
|
void set_inner_ccb(DInner_ccb* );
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
* \class The arrangement face class.
|
||
|
*/
|
||
|
class Face : public DFace {
|
||
|
typedef DFace Base;
|
||
|
|
||
|
public:
|
||
|
/*! Default constrcutor. */
|
||
|
Face() {}
|
||
|
|
||
|
/*! Get an iterator for the outer CCBs of the face (non-const version). */
|
||
|
Outer_ccb_iterator outer_ccbs_begin()
|
||
|
{ return (DOuter_ccb_iter(Base::outer_ccbs_begin())); }
|
||
|
|
||
|
/*! Get an iterator for the outer CCBs the face (const version). */
|
||
|
Outer_ccb_const_iterator outer_ccbs_begin() const
|
||
|
{ return (DOuter_ccb_const_iter(Base::outer_ccbs_begin())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the outer CCBs (non-const version). */
|
||
|
Outer_ccb_iterator outer_ccbs_end()
|
||
|
{ return (DOuter_ccb_iter(Base::outer_ccbs_end())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the outer CCBs (const version). */
|
||
|
Outer_ccb_const_iterator outer_ccbs_end() const
|
||
|
{ return (DOuter_ccb_const_iter(Base::outer_ccbs_end())); }
|
||
|
|
||
|
/*! Get an iterator for the inner CCBs of the face (non-const version). */
|
||
|
Inner_ccb_iterator inner_ccbs_begin()
|
||
|
{ return (DInner_ccb_iter(Base::inner_ccbs_begin())); }
|
||
|
|
||
|
/*! Get an iterator for the inner CCBs the face (const version). */
|
||
|
Inner_ccb_const_iterator inner_ccbs_begin() const
|
||
|
{ return (DInner_ccb_const_iter(Base::inner_ccbs_begin())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the inner CCBs (non-const version). */
|
||
|
Inner_ccb_iterator inner_ccbs_end()
|
||
|
{ return (DInner_ccb_iter(Base::inner_ccbs_end())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the inner CCBs (const version). */
|
||
|
Inner_ccb_const_iterator inner_ccbs_end() const
|
||
|
{ return (DInner_ccb_const_iter(Base::inner_ccbs_end())); }
|
||
|
|
||
|
/*! Get an iterator for the isolated_vertices inside the face
|
||
|
* (non-const version).
|
||
|
*/
|
||
|
Isolated_vertex_iterator isolated_vertices_begin()
|
||
|
{ return (DIso_vertex_iter(Base::isolated_vertices_begin())); }
|
||
|
|
||
|
/*! Get an iterator for the isolated_vertices inside the face
|
||
|
* (const version).
|
||
|
*/
|
||
|
Isolated_vertex_const_iterator isolated_vertices_begin() const
|
||
|
{ return (DIso_vertex_const_iter(Base::isolated_vertices_begin())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the isolated_vertices
|
||
|
* (non-const version).
|
||
|
*/
|
||
|
Isolated_vertex_iterator isolated_vertices_end()
|
||
|
{ return (DIso_vertex_iter(Base::isolated_vertices_end())); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the isolated_vertices
|
||
|
* (const version).
|
||
|
*/
|
||
|
Isolated_vertex_const_iterator isolated_vertices_end() const
|
||
|
{ return (DIso_vertex_const_iter(Base::isolated_vertices_end())); }
|
||
|
|
||
|
/// \name These functions are kept for Arrangement_2 compatibility:
|
||
|
//@{
|
||
|
|
||
|
/*!
|
||
|
* Check whether the face has an outer CCB.
|
||
|
*/
|
||
|
bool has_outer_ccb() const
|
||
|
{ return (Base::number_of_outer_ccbs() > 0); }
|
||
|
|
||
|
/*!
|
||
|
* Get a circulator for the outer boundary (non-const version).
|
||
|
* \pre The face has a single outer CCB.
|
||
|
*/
|
||
|
Ccb_halfedge_circulator outer_ccb()
|
||
|
{
|
||
|
CGAL_precondition(Base::number_of_outer_ccbs() == 1);
|
||
|
|
||
|
DOuter_ccb_iter iter = Base::outer_ccbs_begin();
|
||
|
DHalfedge* he = *iter;
|
||
|
return Ccb_halfedge_circulator(DHalfedge_iter(he));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get a circulator for the outer boundary (const version).
|
||
|
* \pre The face has a single outer CCB.
|
||
|
*/
|
||
|
Ccb_halfedge_const_circulator outer_ccb() const
|
||
|
{
|
||
|
CGAL_precondition(Base::number_of_outer_ccbs() == 1);
|
||
|
|
||
|
DOuter_ccb_const_iter iter = Base::outer_ccbs_begin();
|
||
|
const DHalfedge* he = *iter;
|
||
|
return Ccb_halfedge_const_circulator(DHalfedge_const_iter(he));
|
||
|
}
|
||
|
|
||
|
/*! Get the number of holes (inner CCBs) inside the face. */
|
||
|
Size number_of_holes() const
|
||
|
{ return (Base::number_of_inner_ccbs()); }
|
||
|
|
||
|
/*! Get an iterator for the holes inside the face (non-const version). */
|
||
|
Inner_ccb_iterator holes_begin()
|
||
|
{ return (this->inner_ccbs_begin()); }
|
||
|
|
||
|
/*! Get an iterator for the holes inside the face (const version). */
|
||
|
Inner_ccb_const_iterator holes_begin() const
|
||
|
{ return (this->inner_ccbs_begin()); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the holes (non-const version). */
|
||
|
Inner_ccb_iterator holes_end()
|
||
|
{ return (this->inner_ccbs_end()); }
|
||
|
|
||
|
/*! Get a past-the-end iterator for the holes (const version). */
|
||
|
Inner_ccb_const_iterator holes_end() const
|
||
|
{ return (this->inner_ccbs_end()); }
|
||
|
//@}
|
||
|
|
||
|
private:
|
||
|
// Blocking access to inherited functions from the Dcel::Face.
|
||
|
void set_unbounded(bool);
|
||
|
void set_fictitious(bool);
|
||
|
void add_outer_ccb(DOuter_ccb*, Halfedge*);
|
||
|
void erase_outer_ccb(DOuter_ccb*);
|
||
|
void add_inner_ccb(DInner_ccb*, Halfedge*);
|
||
|
void erase_inner_ccb(DInner_ccb*);
|
||
|
void add_isolated_vertex(DIso_vertex*, DVertex*);
|
||
|
void erase_isolated_vertex(DIso_vertex*);
|
||
|
};
|
||
|
|
||
|
protected:
|
||
|
typedef CGAL_ALLOCATOR(Point_2) Points_alloc;
|
||
|
typedef CGAL_ALLOCATOR(X_monotone_curve_2) Curves_alloc;
|
||
|
|
||
|
typedef Arr_observer<Self> Observer;
|
||
|
typedef std::list<Observer*> Observers_container;
|
||
|
typedef typename Observers_container::iterator Observers_iterator;
|
||
|
|
||
|
typedef typename Observers_container::reverse_iterator
|
||
|
Observers_rev_iterator;
|
||
|
|
||
|
// Data members:
|
||
|
Topology_traits m_topol_traits; // the topology traits.
|
||
|
Points_alloc m_points_alloc; // allocator for the points.
|
||
|
Curves_alloc m_curves_alloc; // allocator for the curves.
|
||
|
Observers_container m_observers; // pointers to existing observers.
|
||
|
const Traits_adaptor_2* m_geom_traits; // the geometry-traits adaptor.
|
||
|
bool m_own_traits; // inidicates whether the geometry
|
||
|
// traits should be freed up.
|
||
|
|
||
|
public:
|
||
|
/// \name Constructors.
|
||
|
//@{
|
||
|
|
||
|
/*! Default constructor. */
|
||
|
Arrangement_on_surface_2();
|
||
|
|
||
|
/*! Copy constructor. */
|
||
|
Arrangement_on_surface_2(const Self & arr);
|
||
|
|
||
|
/*! Constructor given a traits object. */
|
||
|
Arrangement_on_surface_2(const Geometry_traits_2* geom_traits);
|
||
|
//@}
|
||
|
|
||
|
/// \name Assignment functions.
|
||
|
//@{
|
||
|
|
||
|
/*! Assignment operator. */
|
||
|
Self& operator=(const Self& arr);
|
||
|
|
||
|
/*! Assign an arrangement. */
|
||
|
void assign(const Self& arr);
|
||
|
//@}
|
||
|
|
||
|
/// \name Destruction functions.
|
||
|
//@{
|
||
|
|
||
|
/*! Destructor. */
|
||
|
virtual ~Arrangement_on_surface_2();
|
||
|
|
||
|
/*! Clear the arrangement. */
|
||
|
virtual void clear();
|
||
|
//@}
|
||
|
|
||
|
/// \name Access the traits-class objects.
|
||
|
//@{
|
||
|
|
||
|
/*! Access the geometry-traits object (const version). */
|
||
|
inline const Traits_adaptor_2* traits_adaptor() const
|
||
|
{ return (m_geom_traits); }
|
||
|
|
||
|
/*! Access the geometry-traits object (const version). */
|
||
|
inline const Geometry_traits_2* geometry_traits() const
|
||
|
{ return (m_geom_traits); }
|
||
|
|
||
|
/*! Access the topology-traits object (non-const version). */
|
||
|
inline Topology_traits* topology_traits()
|
||
|
{ return (&m_topol_traits); }
|
||
|
|
||
|
/*! Access the topology-traits object (const version). */
|
||
|
inline const Topology_traits* topology_traits() const
|
||
|
{ return (&m_topol_traits); }
|
||
|
//@}
|
||
|
|
||
|
/// \name Access the arrangement dimensions.
|
||
|
//@{
|
||
|
|
||
|
/*! Check whether the arrangement is empty. */
|
||
|
bool is_empty() const
|
||
|
{ return (m_topol_traits.is_empty_dcel()); }
|
||
|
|
||
|
/*!
|
||
|
* Check whether the arrangement is valid. In particular, check the
|
||
|
* validity of each vertex, halfedge and face, their incidence relations
|
||
|
* and the geometric properties of the arrangement.
|
||
|
*/
|
||
|
bool is_valid() const;
|
||
|
|
||
|
/*! Get the number of arrangement vertices. */
|
||
|
Size number_of_vertices() const
|
||
|
{ return (m_topol_traits.number_of_concrete_vertices()); }
|
||
|
|
||
|
/*! Get the number of isolated arrangement vertices. */
|
||
|
Size number_of_isolated_vertices() const
|
||
|
{ return (_dcel().size_of_isolated_vertices()); }
|
||
|
|
||
|
/*! Get the number of arrangement halfedges (the result is always even). */
|
||
|
Size number_of_halfedges() const
|
||
|
{ return (m_topol_traits.number_of_valid_halfedges()); }
|
||
|
|
||
|
/*! Get the number of arrangement edges. */
|
||
|
Size number_of_edges() const
|
||
|
{ return (m_topol_traits.number_of_valid_halfedges() / 2); }
|
||
|
|
||
|
/*! Get the number of arrangement faces. */
|
||
|
Size number_of_faces() const
|
||
|
{ return (m_topol_traits.number_of_valid_faces()); }
|
||
|
|
||
|
/*! Get the number of unbounded faces in the arrangement. */
|
||
|
Size number_of_unbounded_faces() const
|
||
|
{
|
||
|
Unbounded_face_const_iterator iter = unbounded_faces_begin();
|
||
|
Unbounded_face_const_iterator end = unbounded_faces_end();
|
||
|
Size n_unb = 0;
|
||
|
|
||
|
while (iter != end) {
|
||
|
++n_unb;
|
||
|
++iter;
|
||
|
}
|
||
|
|
||
|
return (n_unb);
|
||
|
}
|
||
|
//@}
|
||
|
|
||
|
/// \name Traversal functions for the arrangement vertices.
|
||
|
//@{
|
||
|
|
||
|
/*! Get an iterator for the first vertex in the arrangement. */
|
||
|
Vertex_iterator vertices_begin()
|
||
|
{
|
||
|
return (Vertex_iterator(_dcel().vertices_begin(), _dcel().vertices_end(),
|
||
|
_Is_concrete_vertex(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end iterator for the arrangement vertices. */
|
||
|
Vertex_iterator vertices_end()
|
||
|
{
|
||
|
return (Vertex_iterator(_dcel().vertices_end(), _dcel().vertices_end(),
|
||
|
_Is_concrete_vertex(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a range over handles of the arrangement vertices .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Vertex_iterator> >
|
||
|
vertex_handles()
|
||
|
{
|
||
|
return make_prevent_deref_range(vertices_begin(), vertices_end());
|
||
|
}
|
||
|
|
||
|
/*! Get a const iterator for the first vertex in the arrangement. */
|
||
|
Vertex_const_iterator vertices_begin() const
|
||
|
{
|
||
|
return (Vertex_const_iterator(_dcel().vertices_begin(),
|
||
|
_dcel().vertices_end(),
|
||
|
_Is_concrete_vertex(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end const iterator for the arrangement vertices. */
|
||
|
Vertex_const_iterator vertices_end() const
|
||
|
{
|
||
|
return (Vertex_const_iterator(_dcel().vertices_end(),
|
||
|
_dcel().vertices_end(),
|
||
|
_Is_concrete_vertex(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a const range (model of `ConstRange`) over handles of the arrangement vertices .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Vertex_iterator> >
|
||
|
vertex_handles() const
|
||
|
{
|
||
|
return make_prevent_deref_range(vertices_begin(), vertices_end());
|
||
|
}
|
||
|
|
||
|
//@}
|
||
|
|
||
|
/// \name Traversal functions for the arrangement halfedges.
|
||
|
//@{
|
||
|
|
||
|
/*! Get an iterator for the first halfedge in the arrangement. */
|
||
|
Halfedge_iterator halfedges_begin()
|
||
|
{
|
||
|
return (Halfedge_iterator(_dcel().halfedges_begin(),
|
||
|
_dcel().halfedges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end iterator for the arrangement halfedges. */
|
||
|
Halfedge_iterator halfedges_end()
|
||
|
{
|
||
|
return (Halfedge_iterator(_dcel().halfedges_end(),
|
||
|
_dcel().halfedges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a range over handles of the arrangement halfedges .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Halfedge_iterator> >
|
||
|
halfedge_handles()
|
||
|
{
|
||
|
return make_prevent_deref_range(halfedges_begin(), halfedges_end());
|
||
|
}
|
||
|
|
||
|
/*! Get a const iterator for the first halfedge in the arrangement. */
|
||
|
Halfedge_const_iterator halfedges_begin() const
|
||
|
{
|
||
|
return (Halfedge_const_iterator(_dcel().halfedges_begin(),
|
||
|
_dcel().halfedges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end const iterator for the arrangement halfedges. */
|
||
|
Halfedge_const_iterator halfedges_end() const
|
||
|
{
|
||
|
return (Halfedge_const_iterator(_dcel().halfedges_end(),
|
||
|
_dcel().halfedges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
/*!
|
||
|
returns a const range (model of `ConstRange`) over handles of the arrangement halfedges .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Halfedge_iterator> >
|
||
|
halfedge_handles() const
|
||
|
{
|
||
|
return make_prevent_deref_range(halfedges_begin(), halfedges_end());
|
||
|
}
|
||
|
//@}
|
||
|
|
||
|
/// \name Traversal functions for the arrangement edges.
|
||
|
//@{
|
||
|
|
||
|
/*! Get an iterator for the first edge in the arrangement. */
|
||
|
Edge_iterator edges_begin()
|
||
|
{
|
||
|
return (Edge_iterator(_dcel().edges_begin(), _dcel().edges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end iterator for the arrangement edges. */
|
||
|
Edge_iterator edges_end()
|
||
|
{
|
||
|
return (Edge_iterator(_dcel().edges_end(), _dcel().edges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a range over handles of the arrangement edges .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Edge_iterator> >
|
||
|
edge_handles()
|
||
|
{
|
||
|
return make_prevent_deref_range(edges_begin(), edges_end());
|
||
|
}
|
||
|
|
||
|
/*! Get a const iterator for the first edge in the arrangement. */
|
||
|
Edge_const_iterator edges_begin() const
|
||
|
{
|
||
|
return (Edge_const_iterator(_dcel().edges_begin(), _dcel().edges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end const iterator for the arrangement edges. */
|
||
|
Edge_const_iterator edges_end() const
|
||
|
{
|
||
|
return (Edge_const_iterator(_dcel().edges_end(), _dcel().edges_end(),
|
||
|
_Is_valid_halfedge(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a const range (model of `ConstRange`) over handles of the arrangement edges .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Edge_iterator> >
|
||
|
edge_handles() const
|
||
|
{
|
||
|
return make_prevent_deref_range(edges_begin(), edges_end());
|
||
|
}
|
||
|
//@}
|
||
|
|
||
|
/// \name Traversal functions for the arrangement faces.
|
||
|
//@{
|
||
|
|
||
|
/*! Get an iterator for the first face in the arrangement. */
|
||
|
Face_iterator faces_begin()
|
||
|
{
|
||
|
return (Face_iterator(_dcel().faces_begin(), _dcel().faces_end(),
|
||
|
_Is_valid_face(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end iterator for the arrangement faces. */
|
||
|
Face_iterator faces_end()
|
||
|
{
|
||
|
return (Face_iterator(_dcel().faces_end(), _dcel().faces_end(),
|
||
|
_Is_valid_face(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a range over handles of the arrangement faces .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Face_iterator> >
|
||
|
face_handles()
|
||
|
{
|
||
|
return make_prevent_deref_range(faces_begin(), faces_end());
|
||
|
}
|
||
|
/*! Get a const iterator for the first face in the arrangement. */
|
||
|
Face_const_iterator faces_begin() const
|
||
|
{
|
||
|
return (Face_const_iterator(_dcel().faces_begin(), _dcel().faces_end(),
|
||
|
_Is_valid_face(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end const iterator for the arrangement faces. */
|
||
|
Face_const_iterator faces_end() const
|
||
|
{
|
||
|
return (Face_const_iterator(_dcel().faces_end(), _dcel().faces_end(),
|
||
|
_Is_valid_face(&m_topol_traits)));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
returns a const range (model of `ConstRange`) over handles of the arrangement faces .
|
||
|
*/
|
||
|
Iterator_range<Prevent_deref<Face_iterator> >
|
||
|
face_handles() const
|
||
|
{
|
||
|
return make_prevent_deref_range(faces_begin(), faces_end());
|
||
|
}
|
||
|
//! reference_face (const version).
|
||
|
/*! The function returns a reference face of the arrangement.
|
||
|
* All reference faces of arrangements of the same type have a common
|
||
|
* point.
|
||
|
* \return A const handle to the reference face.
|
||
|
*/
|
||
|
Face_const_handle reference_face() const
|
||
|
{
|
||
|
return _const_handle_for(this->topology_traits()->reference_face());
|
||
|
}
|
||
|
|
||
|
//! reference_face (non-const version).
|
||
|
/*! The function returns a reference face of the arrangement.
|
||
|
All reference faces of arrangements of the same type have a common
|
||
|
point.
|
||
|
\return A handle to the reference face.
|
||
|
*/
|
||
|
Face_handle reference_face()
|
||
|
{ return _handle_for(this->topology_traits()->reference_face()); }
|
||
|
|
||
|
//@}
|
||
|
|
||
|
/// \name Traversal functions for the unbounded faces of the arrangement.
|
||
|
//@{
|
||
|
|
||
|
/*! Get an iterator for the first unbounded face in the arrangement. */
|
||
|
Unbounded_face_iterator unbounded_faces_begin()
|
||
|
{
|
||
|
return Unbounded_face_iterator(_dcel().faces_begin(), _dcel().faces_end(),
|
||
|
_Is_unbounded_face(&m_topol_traits));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end iterator for the unbounded arrangement faces. */
|
||
|
Unbounded_face_iterator unbounded_faces_end()
|
||
|
{
|
||
|
return Unbounded_face_iterator(_dcel().faces_end(), _dcel().faces_end(),
|
||
|
_Is_unbounded_face(&m_topol_traits));
|
||
|
}
|
||
|
|
||
|
/*! Get a const iterator for the first unbounded face in the arrangement. */
|
||
|
Unbounded_face_const_iterator unbounded_faces_begin() const
|
||
|
{
|
||
|
return Unbounded_face_const_iterator(_dcel().faces_begin(),
|
||
|
_dcel().faces_end(),
|
||
|
_Is_unbounded_face(&m_topol_traits));
|
||
|
}
|
||
|
|
||
|
/*! Get a past-the-end const iterator for the unbounded arrangement faces. */
|
||
|
Unbounded_face_const_iterator unbounded_faces_end() const
|
||
|
{
|
||
|
return Unbounded_face_const_iterator(_dcel().faces_end(),
|
||
|
_dcel().faces_end(),
|
||
|
_Is_unbounded_face(&m_topol_traits));
|
||
|
}
|
||
|
|
||
|
/*! Get the fictitious face (non-const version). */
|
||
|
Face_handle fictitious_face()
|
||
|
{
|
||
|
// The fictitious contains all other faces in a single hole inside it.
|
||
|
return
|
||
|
Face_handle(const_cast<DFace*>(this->topology_traits()->initial_face()));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* Get the unbounded face (const version).
|
||
|
* The fictitious contains all other faces in a single hole inside it.
|
||
|
*/
|
||
|
Face_const_handle fictitious_face() const
|
||
|
{ return DFace_const_iter(this->topology_traits()->initial_face()); }
|
||
|
//@}
|
||
|
|
||
|
/// \name Casting away constness for handle types.
|
||
|
//@{
|
||
|
Vertex_handle non_const_handle(Vertex_const_handle vh)
|
||
|
{
|
||
|
DVertex* p_v = (DVertex*)&(*vh);
|
||
|
return (Vertex_handle(p_v));
|
||
|
}
|
||
|
|
||
|
Halfedge_handle non_const_handle(Halfedge_const_handle hh)
|
||
|
{
|
||
|
DHalfedge* p_he = (DHalfedge*)&(*hh);
|
||
|
return (Halfedge_handle(p_he));
|
||
|
}
|
||
|
|
||
|
Face_handle non_const_handle(Face_const_handle fh)
|
||
|
{
|
||
|
DFace* p_f = (DFace*) &(*fh);
|
||
|
return (Face_handle(p_f));
|
||
|
}
|
||
|
//@}
|
||
|
|
||
|
/// \name Specilaized insertion functions.
|
||
|
//@{
|
||
|
|
||
|
/*!
|
||
|
* Insert a point that forms an isolated vertex in the interior of a given
|
||
|
* face.
|
||
|
* \param p The given point.
|
||
|
* \param f The face into which we insert the new isolated vertex.
|
||
|
* \return A handle for the isolated vertex that has been created.
|
||
|
*/
|
||
|
Vertex_handle insert_in_face_interior(const Point_2& p, Face_handle f);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement as a new hole (inner
|
||
|
* component) inside the given face.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param f The face into which we insert the new hole.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve, directed (lexicographically) from left to right.
|
||
|
*/
|
||
|
Halfedge_handle insert_in_face_interior(const X_monotone_curve_2& cv,
|
||
|
Face_handle f);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that its left
|
||
|
* endpoint corresponds to a given arrangement vertex.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param v The given vertex.
|
||
|
* \param f The face that contains v (in case it has no incident edges).
|
||
|
* \pre The left endpoint of cv is incident to the vertex v.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve, whose target is the new vertex.
|
||
|
*/
|
||
|
Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||
|
Vertex_handle v,
|
||
|
Face_handle f = Face_handle());
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that its left
|
||
|
* endpoints corresponds to a given arrangement vertex, given the exact
|
||
|
* place for the curve in the circular list around this vertex.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param prev The reference halfedge. We should represent cv as a pair
|
||
|
* of edges, one of them should become prev's successor.
|
||
|
* \pre The target vertex of prev is cv's left endpoint.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve, whose target is the new vertex that was created.
|
||
|
*/
|
||
|
Halfedge_handle insert_from_left_vertex(const X_monotone_curve_2& cv,
|
||
|
Halfedge_handle prev);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that its right
|
||
|
* endpoint corresponds to a given arrangement vertex.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param v The given vertex.
|
||
|
* \param f The face that contains v (in case it has no incident edges).
|
||
|
* \pre The right endpoint of cv is incident to the vertex v.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve, whose target is the new vertex.
|
||
|
*/
|
||
|
Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||
|
Vertex_handle v,
|
||
|
Face_handle f = Face_handle());
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that its right
|
||
|
* endpoints corresponds to a given arrangement vertex, given the exact
|
||
|
* place for the curve in the circular list around this vertex.
|
||
|
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param prev The reference halfedge. We should represent cv as a pair
|
||
|
* of edges, one of them should become prev's successor.
|
||
|
* \pre The target vertex of prev is cv's right endpoint.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve, whose target is the new vertex that was created.
|
||
|
*/
|
||
|
Halfedge_handle insert_from_right_vertex(const X_monotone_curve_2& cv,
|
||
|
Halfedge_handle prev);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that both its
|
||
|
* endpoints correspond to given arrangement vertices.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param v1 The first vertex.
|
||
|
* \param v2 The second vertex.
|
||
|
* \param f The face that contains v1 and v2
|
||
|
* (in case both have no incident edges).
|
||
|
* \pre v1 and v2 corresponds to cv's endpoints.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve directed from v1 to v2.
|
||
|
*/
|
||
|
Halfedge_handle insert_at_vertices(const X_monotone_curve_2& cv,
|
||
|
Vertex_handle v1,
|
||
|
Vertex_handle v2,
|
||
|
Face_handle f = Face_handle());
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that both its
|
||
|
* endpoints correspond to given arrangement vertices, given the exact
|
||
|
* place for the curve in one of the circular lists around a vertex.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param prev1 The reference halfedge for the first vertex.
|
||
|
* \param v2 The second vertex.
|
||
|
* \pre The target vertex of prev1 and v2 corresponds to cv's endpoints.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve directed from prev1 to v2.
|
||
|
*/
|
||
|
Halfedge_handle insert_at_vertices(const X_monotone_curve_2& cv,
|
||
|
Halfedge_handle prev1,
|
||
|
Vertex_handle v2);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that both its
|
||
|
* endpoints correspond to given arrangement vertices, given the exact
|
||
|
* place for the curve in both circular lists around these two vertices.
|
||
|
* \param cv the given curve.
|
||
|
* \param prev1 The reference halfedge for the first vertex.
|
||
|
* \param prev2 The reference halfedge for the second vertex.
|
||
|
* \pre The target vertices of prev1 and prev2 are cv's endpoints.
|
||
|
* \return A handle for one of the halfedges corresponding to the inserted
|
||
|
* curve directed from prev1's target to prev2's target.
|
||
|
*/
|
||
|
Halfedge_handle insert_at_vertices(const X_monotone_curve_2 & cv,
|
||
|
Halfedge_handle prev1,
|
||
|
Halfedge_handle prev2);
|
||
|
|
||
|
//@}
|
||
|
|
||
|
/// \name Vertex manipulation functions.
|
||
|
//@{
|
||
|
|
||
|
/*!
|
||
|
* Replace the point associated with the given vertex.
|
||
|
* \param v The vertex to modify.
|
||
|
* \param p The point that should be associated with the edge.
|
||
|
* \pre p is geometrically equivalent to the current point
|
||
|
* associated with v.
|
||
|
* \return A handle for a the modified vertex (same as v).
|
||
|
*/
|
||
|
Vertex_handle modify_vertex(Vertex_handle v, const Point_2& p);
|
||
|
|
||
|
/*!
|
||
|
* Remove an isolated vertex from the interior of a given face.
|
||
|
* \param v The vertex to remove.
|
||
|
* \pre v is an isolated vertex (it has no incident halfedges).
|
||
|
* \return A handle for the face containing v.
|
||
|
*/
|
||
|
Face_handle remove_isolated_vertex(Vertex_handle v);
|
||
|
|
||
|
///@}
|
||
|
|
||
|
/// \name Halfedge manipulation functions.
|
||
|
//@{
|
||
|
|
||
|
/*!
|
||
|
* Replace the x-monotone curve associated with the given edge.
|
||
|
* \param e The edge to modify.
|
||
|
* \param cv The curve that should be associated with the edge.
|
||
|
* \pre cv is geometrically equivalent to the current curve
|
||
|
* associated with e.
|
||
|
* \return A handle for a the modified halfedge (same as e).
|
||
|
*/
|
||
|
Halfedge_handle modify_edge(Halfedge_handle e, const X_monotone_curve_2& cv);
|
||
|
|
||
|
/*!
|
||
|
* Split a given edge into two, and associate the given x-monotone
|
||
|
* curves with the split edges.
|
||
|
* \param e The edge to split (one of the pair of twin halfegdes).
|
||
|
* \param cv1 The curve that should be associated with the first split edge.
|
||
|
* \param cv2 The curve that should be associated with the second split edge.
|
||
|
|
||
|
* \pre cv1's source and cv2's target equal the endpoints of the curve
|
||
|
* currently assoicated with e (respectively), and cv1's target equals
|
||
|
* cv2's target, and this is the split point (ot vice versa).
|
||
|
* \return A handle for the halfedge whose source is the source of the the
|
||
|
* original halfedge e, and whose target is the split point.
|
||
|
*/
|
||
|
Halfedge_handle split_edge(Halfedge_handle e,
|
||
|
const X_monotone_curve_2& cv1,
|
||
|
const X_monotone_curve_2& cv2);
|
||
|
|
||
|
/*!
|
||
|
* Merge two edges to form a single edge, and associate the given x-monotone
|
||
|
* curve with the merged edge.
|
||
|
* \param e1 The first edge to merge (one of the pair of twin halfegdes).
|
||
|
* \param e2 The second edge to merge (one of the pair of twin halfegdes).
|
||
|
* \param cv The curve that should be associated with merged edge.
|
||
|
* \return A handle for the merged halfedge.
|
||
|
*/
|
||
|
Halfedge_handle merge_edge(Halfedge_handle e1, Halfedge_handle e2,
|
||
|
const X_monotone_curve_2& cv);
|
||
|
|
||
|
/*!
|
||
|
* Remove an edge from the arrangement.
|
||
|
* \param e The edge to remove (one of the pair of twin halfegdes).
|
||
|
* \param remove_source Should the source vertex of e be removed if it
|
||
|
* becomes isolated (true by default).
|
||
|
* \param remove_target Should the target vertex of e be removed if it
|
||
|
* becomes isolated (true by default).
|
||
|
* \return A handle for the remaining face.
|
||
|
*/
|
||
|
Face_handle remove_edge(Halfedge_handle e,
|
||
|
bool remove_source = true,
|
||
|
bool remove_target = true);
|
||
|
|
||
|
//@}
|
||
|
|
||
|
protected:
|
||
|
/// \name Determining the boundary-side conditions.
|
||
|
//@{
|
||
|
|
||
|
/*! Determines whether a boundary-side categoty indicates an open side.
|
||
|
*/
|
||
|
inline bool is_open(Arr_boundary_side_tag) const { return false; }
|
||
|
inline bool is_open(Arr_open_side_tag) const { return true; }
|
||
|
|
||
|
/*! Determines whether the given x and y parameter spaces are open.
|
||
|
* These parameter spaces are typically associated with a particular curve
|
||
|
* end.
|
||
|
* \param ps_x The parameter space in x.
|
||
|
* \param ps_y The parameter space in y.
|
||
|
*/
|
||
|
inline bool is_open(Arr_parameter_space ps_x, Arr_parameter_space ps_y) const
|
||
|
{
|
||
|
return
|
||
|
(((ps_x == ARR_LEFT_BOUNDARY) && is_open(Left_side_category())) ||
|
||
|
((ps_x == ARR_RIGHT_BOUNDARY) && is_open(Right_side_category())) ||
|
||
|
((ps_y == ARR_BOTTOM_BOUNDARY) && is_open(Bottom_side_category())) ||
|
||
|
((ps_y == ARR_TOP_BOUNDARY) && is_open(Top_side_category())));
|
||
|
|
||
|
}
|
||
|
|
||
|
/*! Determines whether a boundary-side categoty indicates a constracted side.
|
||
|
*/
|
||
|
inline bool is_contracted(Arr_boundary_side_tag) const { return false; }
|
||
|
inline bool is_contracted(Arr_contracted_side_tag) const { return true; }
|
||
|
|
||
|
/*! Determines whether a boundary-side categoty indicates a constracted side.
|
||
|
*/
|
||
|
inline bool is_identified(Arr_boundary_side_tag) const { return false; }
|
||
|
inline bool is_identified(Arr_identified_side_tag) const { return true; }
|
||
|
//@}
|
||
|
|
||
|
/// \name Allocating and de-allocating points and curves.
|
||
|
//@{
|
||
|
|
||
|
/*! Allocate a new point. */
|
||
|
Point_2*_new_point(const Point_2& pt)
|
||
|
{
|
||
|
Point_2* p_pt = m_points_alloc.allocate(1);
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<Points_alloc>::construct(m_points_alloc, p_pt, pt);
|
||
|
#else
|
||
|
m_points_alloc.construct(p_pt, pt);
|
||
|
#endif
|
||
|
return (p_pt);
|
||
|
}
|
||
|
|
||
|
/*! De-allocate a point. */
|
||
|
void _delete_point(Point_2& pt)
|
||
|
{
|
||
|
Point_2* p_pt = &pt;
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<Points_alloc>::destroy(m_points_alloc, p_pt);
|
||
|
#else
|
||
|
m_points_alloc.destroy(p_pt);
|
||
|
#endif
|
||
|
m_points_alloc.deallocate(p_pt, 1);
|
||
|
}
|
||
|
|
||
|
/*! Allocate a new curve. */
|
||
|
X_monotone_curve_2* _new_curve(const X_monotone_curve_2& cv)
|
||
|
{
|
||
|
X_monotone_curve_2* p_cv = m_curves_alloc.allocate(1);
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<Curves_alloc>::construct(m_curves_alloc, p_cv, cv);
|
||
|
#else
|
||
|
m_curves_alloc.construct(p_cv, cv);
|
||
|
#endif
|
||
|
return (p_cv);
|
||
|
}
|
||
|
|
||
|
/*! De-allocate a curve. */
|
||
|
void _delete_curve(X_monotone_curve_2& cv)
|
||
|
{
|
||
|
X_monotone_curve_2* p_cv = &cv;
|
||
|
#ifdef CGAL_CXX11
|
||
|
std::allocator_traits<Curves_alloc>::destroy(m_curves_alloc, p_cv);
|
||
|
#else
|
||
|
m_curves_alloc.destroy(p_cv);
|
||
|
#endif
|
||
|
m_curves_alloc.deallocate(p_cv, 1);
|
||
|
}
|
||
|
//@}
|
||
|
|
||
|
/// \name Converting handles to pointers (for the arrangement accessor).
|
||
|
//@{
|
||
|
/*! Access the DCEL (non-const version). */
|
||
|
inline Dcel& _dcel() { return (m_topol_traits.dcel()); }
|
||
|
/*! Access the DCEL (const version). */
|
||
|
inline const Dcel& _dcel() const
|
||
|
{ return (m_topol_traits.dcel()); }
|
||
|
|
||
|
/*! Convert a vertex handle to a pointer to a DCEL vertex. */
|
||
|
inline DVertex* _vertex(Vertex_handle vh) const
|
||
|
{ return (&(*vh)); }
|
||
|
|
||
|
/*! Convert a constant vertex handle to a pointer to a DCEL vertex. */
|
||
|
inline const DVertex* _vertex(Vertex_const_handle vh) const
|
||
|
{ return (&(*vh)); }
|
||
|
|
||
|
/*! Convert a halfedge handle to a pointer to a DCEL halfedge. */
|
||
|
inline DHalfedge* _halfedge(Halfedge_handle hh) const
|
||
|
{ return (&(*hh)); }
|
||
|
|
||
|
/*! Convert a constant halfedge handle to a pointer to a DCEL halfedge. */
|
||
|
inline const DHalfedge* _halfedge(Halfedge_const_handle hh) const
|
||
|
{ return (&(*hh)); }
|
||
|
|
||
|
/*! Convert a face handle to a pointer to a DCEL face. */
|
||
|
inline DFace* _face(Face_handle fh) const
|
||
|
{ return (&(*fh)); }
|
||
|
|
||
|
/*! Convert a constant face handle to a pointer to a DCEL face. */
|
||
|
inline const DFace* _face(Face_const_handle fh) const
|
||
|
{ return (&(*fh)); }
|
||
|
//@}
|
||
|
|
||
|
/// \name Converting pointers to handles (for the arrangement accessor).
|
||
|
//@{
|
||
|
|
||
|
/*! Convert a pointer to a DCEL vertex to a vertex handle. */
|
||
|
Vertex_handle _handle_for(DVertex* v)
|
||
|
{ return (Vertex_handle(v)); }
|
||
|
|
||
|
/*! Convert a pointer to a DCEL vertex to a constant vertex handle. */
|
||
|
Vertex_const_handle _const_handle_for(const DVertex* v) const
|
||
|
{ return (Vertex_const_handle(v)); }
|
||
|
|
||
|
/*! Convert a pointer to a DCEL halfedge to a halfedge handle. */
|
||
|
Halfedge_handle _handle_for(DHalfedge* he)
|
||
|
{ return (Halfedge_handle(he)); }
|
||
|
|
||
|
|
||
|
/*! Convert a pointer to a DCEL halfedge to a constant halfedge handle. */
|
||
|
Halfedge_const_handle _const_handle_for(const DHalfedge* he) const
|
||
|
{ return (Halfedge_const_handle(he)); }
|
||
|
|
||
|
/*! Convert a pointer to a DCEL face to a face handle. */
|
||
|
Face_handle _handle_for(DFace* f)
|
||
|
{ return (Face_handle(f)); }
|
||
|
|
||
|
/*! Convert a pointer to a DCEL face to a constant face handle. */
|
||
|
Face_const_handle _const_handle_for(const DFace* f) const
|
||
|
{ return (Face_const_handle(f)); }
|
||
|
//@}
|
||
|
|
||
|
/// \name Auxiliary (protected) functions.
|
||
|
//@{
|
||
|
|
||
|
/*! Is the vertex incident to a given halfedge lexicographically smaller than
|
||
|
* the vertex incident to another given halfedge. Recall that the incident
|
||
|
* vertex is the target vertex. This function is used, for example, in the
|
||
|
* search for lexicographically smallest vertex in a CCB, when an edge is
|
||
|
* about to be removed from the DCEL.
|
||
|
*
|
||
|
* This is the implementation for the case where all 4 boundary sides are
|
||
|
* oblivious.
|
||
|
*
|
||
|
* \param he1 the given first halfedge
|
||
|
* \param ps_x1 the parameter space in x of the vertex incident to he1
|
||
|
* \param ps_y1 the parameter space in y of the vertex incident to he1
|
||
|
* \param he2 the given second halfedge
|
||
|
* \param ps_x2 the parameter space in x of the vertex incident to he2
|
||
|
* \param ps_y2 the parameter space in y of the vertex incident to he2
|
||
|
* \precondition he1 is directed from right to left
|
||
|
* \precondition he2 is directed from right to left
|
||
|
* \precondition the vertex incident to he1 (he1->vertex()) is different
|
||
|
* than the vertex incident to he1 (he2->vertex()), and thus their
|
||
|
* geometric mappings (he1->vertex()->point() and
|
||
|
* he2->vertex()->point()) are not equal.
|
||
|
*/
|
||
|
bool _is_smaller(const DHalfedge* he1,
|
||
|
Arr_parameter_space ps_x1, Arr_parameter_space ps_y1,
|
||
|
const DHalfedge* he2,
|
||
|
Arr_parameter_space ps_x2, Arr_parameter_space ps_y2,
|
||
|
Arr_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*! This is a wrapper for the case where any boundary side is not
|
||
|
* necessarily oblivious.
|
||
|
*/
|
||
|
bool _is_smaller(const DHalfedge* he1,
|
||
|
Arr_parameter_space ps_x1, Arr_parameter_space ps_y1,
|
||
|
const DHalfedge* he2,
|
||
|
Arr_parameter_space ps_x2, Arr_parameter_space ps_y2,
|
||
|
Arr_not_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*! Is the lexicographically minimal vertex of a given x-monotone curve
|
||
|
* lexicographically smaller than the lexicographically minimal vertex of
|
||
|
* another given x-monotone curve. This function is used, for example, when
|
||
|
* a new curve is to be inserted into the arrangement. In this case the
|
||
|
* search is conducted over the curves that will comprise a new CCB.
|
||
|
*
|
||
|
* This is the implementation for the case where all 4 boundary sides are
|
||
|
* oblivious.
|
||
|
*
|
||
|
* \param cv1 the given first x-monotone curve
|
||
|
* \param ps_x1 the parameter space in x of the minimal point of cv1
|
||
|
* \param ps_y1 the parameter space in y of the minimal point of cv1
|
||
|
* \param cv2 the given second x-monotone curve
|
||
|
* \param ps_x2 the parameter space in x of the minimal point of cv2
|
||
|
* \param ps_y2 the parameter space in y of the minimal point of cv2
|
||
|
* \precondition the minimal points of cv1 and cv2 are not equal.
|
||
|
*/
|
||
|
bool _is_smaller(const X_monotone_curve_2& cv1, const Point_2& p1,
|
||
|
Arr_parameter_space ps_x1, Arr_parameter_space ps_y1,
|
||
|
const X_monotone_curve_2& cv2, const Point_2& p2,
|
||
|
Arr_parameter_space ps_x2, Arr_parameter_space ps_y2,
|
||
|
Arr_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*! This is the implementation for the case where any one of the 4 boundary
|
||
|
* sides can be of any type.
|
||
|
*/
|
||
|
bool _is_smaller(const X_monotone_curve_2& cv1, const Point_2& p1,
|
||
|
Arr_parameter_space ps_x1, Arr_parameter_space ps_y1,
|
||
|
const X_monotone_curve_2& cv2, const Point_2& p2,
|
||
|
Arr_parameter_space ps_x2, Arr_parameter_space ps_y2,
|
||
|
Arr_not_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*! Given two x-monotone curves that share their minimal end point.
|
||
|
* The function return true if the y-coordinate of the first curve curve
|
||
|
* near its minimal end smaller than the y-coordinate of the second curve
|
||
|
* (near its minimal end). This function is used, for example, when
|
||
|
* a new curve is to be inserted into the arrangement. In this case the
|
||
|
* search is conducted over the curves that will comprise a new CCB.
|
||
|
*
|
||
|
* This is the implementation for the case where all 4 boundary sides are
|
||
|
* oblivious.
|
||
|
*
|
||
|
* \param cv1 the given first x-monotone curve
|
||
|
* \param cv2 the given second x-monotone curve
|
||
|
* \param p the shared minimal point of cv1 and cv2
|
||
|
* \param ps_x the parameter space in x of the minimal point of cv1
|
||
|
* \param ps_y the parameter space in y of the minimal point of cv1
|
||
|
* \precondition the minimal points of cv1 and cv2 are equal.
|
||
|
*/
|
||
|
bool _is_smaller_near_right(const X_monotone_curve_2& cv1,
|
||
|
const X_monotone_curve_2& cv2,
|
||
|
const Point_2& p,
|
||
|
Arr_parameter_space ps_x,
|
||
|
Arr_parameter_space ps_y,
|
||
|
Arr_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*! This is the implementation for the case where any one of the 4 boundary
|
||
|
* sides can be of any type.
|
||
|
*/
|
||
|
bool _is_smaller_near_right(const X_monotone_curve_2& cv1,
|
||
|
const X_monotone_curve_2& cv2,
|
||
|
const Point_2& p,
|
||
|
Arr_parameter_space ps_x,
|
||
|
Arr_parameter_space ps_y,
|
||
|
Arr_not_all_sides_oblivious_tag) const;
|
||
|
|
||
|
/*!
|
||
|
* Locate the place for the given curve around the given vertex.
|
||
|
* \param v The given arrangement vertex.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param ind Whether we refer to the minimal or maximal end of cv.
|
||
|
* \return A pointer to a halfedge whose target is v, where cv should be
|
||
|
* inserted between this halfedge and the next halfedge around this
|
||
|
* vertex (in a clockwise order).
|
||
|
* A NULL return value indicates a precondition violation.
|
||
|
*/
|
||
|
DHalfedge* _locate_around_vertex(DVertex* v, const X_monotone_curve_2& cv,
|
||
|
Arr_curve_end ind) const;
|
||
|
|
||
|
/*!
|
||
|
* Compute the distance (in halfedges) between two halfedges.
|
||
|
* \param e1 The source halfedge.
|
||
|
* \param e2 The destination halfedge.
|
||
|
* \pre e1 and e2 belong to the same connected component
|
||
|
* \return The number of halfedges along the component boundary between the
|
||
|
* two halfedges.
|
||
|
*/
|
||
|
unsigned int _halfedge_distance(const DHalfedge* e1,
|
||
|
const DHalfedge* e2) const;
|
||
|
|
||
|
/*!
|
||
|
* Compare the length of the induced paths from e1 to e2 and
|
||
|
* from e2 to e1.
|
||
|
* \pre e1 and e2 belong to the same connected component
|
||
|
* \return The comparison result
|
||
|
*/
|
||
|
Comparison_result _compare_induced_path_length(const DHalfedge* e1,
|
||
|
const DHalfedge* e2) const;
|
||
|
|
||
|
/*!
|
||
|
* Update the indices according to boundary locations
|
||
|
*/
|
||
|
void
|
||
|
_compute_indices(Arr_parameter_space ps_x_curr, Arr_parameter_space ps_y_curr,
|
||
|
Arr_parameter_space ps_x_next, Arr_parameter_space ps_y_next,
|
||
|
int& x_index, int& y_index, boost::mpl::bool_<true>) const;
|
||
|
|
||
|
/*!
|
||
|
* Update the indices according to boundary locations (i.e. does nothing)
|
||
|
*/
|
||
|
void
|
||
|
_compute_indices(Arr_parameter_space ps_x_curr, Arr_parameter_space ps_y_curr,
|
||
|
Arr_parameter_space ps_x_next, Arr_parameter_space ps_y_next,
|
||
|
int& x_index, int& y_index, boost::mpl::bool_<false>) const;
|
||
|
|
||
|
/*!
|
||
|
* Is the first given x-monotone curve above the second given?
|
||
|
* \param xcv1 the first given curve
|
||
|
* \param ps_y1 the parameter space in y of xcv1
|
||
|
* \param xcv2 the second given curve
|
||
|
* \param Arr_identified_side_tag used for dispatching to ensure that this
|
||
|
* function is invoked when the bottom and top boundaries are
|
||
|
* identified
|
||
|
*/
|
||
|
bool _is_above(const X_monotone_curve_2& xcv1,
|
||
|
const X_monotone_curve_2& xcv2,
|
||
|
const Point_2& point,
|
||
|
Arr_parameter_space ps_y1,
|
||
|
Arr_has_identified_side_tag) const;
|
||
|
|
||
|
/*!
|
||
|
* Is the first given x-monotone curve above the second given?
|
||
|
* \param xcv1 the first given curve
|
||
|
* \param ps_y1 the parameter space in y of xcv1
|
||
|
* \param xcv2 the second given curve
|
||
|
* \param Arr_contracted_side_tag used for dispatching to ensure that this
|
||
|
* function is invoked when the bottom or top boundaries are
|
||
|
* contracted
|
||
|
*/
|
||
|
bool _is_above(const X_monotone_curve_2& xcv1,
|
||
|
const X_monotone_curve_2& xcv2,
|
||
|
const Point_2& point,
|
||
|
Arr_parameter_space ps_y1,
|
||
|
Arr_has_contracted_side_tag) const;
|
||
|
|
||
|
/*!
|
||
|
* Is the first given x-monotone curve above the second given?
|
||
|
* \param xcv1 the first given curve
|
||
|
* \param ps_y1 the parameter space in y of xcv1
|
||
|
* \param xcv2 the second given curve
|
||
|
* \param Arr_oblivious_side_tag used for dispatching to ensure that this
|
||
|
* function is invoked when the bottom and top boundaries are neither
|
||
|
* identified nor contracted
|
||
|
*/
|
||
|
bool _is_above(const X_monotone_curve_2& xcv1,
|
||
|
const X_monotone_curve_2& xcv2,
|
||
|
const Point_2& point,
|
||
|
Arr_parameter_space ps_y1,
|
||
|
Arr_boundary_cond_tag) const;
|
||
|
|
||
|
/*!
|
||
|
* Compute the signs (in left/right and bottom/top) of a path
|
||
|
* induced by the sequence he_to=>cv,cv_dir=>he_away, and reports
|
||
|
* as side-effect the halfedges pointing to local minima copied
|
||
|
* to an outputiterator.
|
||
|
* \param he_to The predecessor halfedge.
|
||
|
* \param cv The x-monotone curve we use to connect he_to's target and
|
||
|
* he_away's source vertex.
|
||
|
* \param cv_dir the direction of the curve between he_to and he_away
|
||
|
* \param he_away The succcessor halfedge.
|
||
|
* \param local_mins_it the outputiterator
|
||
|
* (value_type = std::pair< DHalfedge*, int >, where the int denotes the
|
||
|
* index) to report the halfedges pointing to local minima (<-shaped
|
||
|
* situation)
|
||
|
* \return A pair of signs for the induced path (ZERO if non-perimetric,
|
||
|
* POSITIVE if perimetric ccb is oriented in positive direction,
|
||
|
* NEGATIVE if perimetric ccb is oriented in negative direction).
|
||
|
*/
|
||
|
template <typename OutputIterator>
|
||
|
std::pair<Sign, Sign>
|
||
|
_compute_signs_and_local_minima(const DHalfedge* he_to,
|
||
|
const X_monotone_curve_2& cv,
|
||
|
Arr_halfedge_direction cv_dir,
|
||
|
const DHalfedge* he_away,
|
||
|
OutputIterator local_mins_it) const;
|
||
|
|
||
|
/*!
|
||
|
* Compute the signs (in left/right and bottom/top) of a closed ccb (loop)
|
||
|
* represented by a given halfedge, and the halfedge pointing to the smallest
|
||
|
* vertex on the ccb.
|
||
|
* \param he The representative halfedge on the ccb.
|
||
|
* \param ps_x_min The parameter space in x of the smallest vertex.
|
||
|
* \param ps_y_min The parameter space in y of the smallest vertex.
|
||
|
* \param index_min The index of the smallest vertex.
|
||
|
* \return A pair of, a pair of signs for the induced path, and the halfedge
|
||
|
* pointing to the smallest vertex.
|
||
|
* A sign ZERO is if the ccb is non-perimetric,
|
||
|
* POSITIVE if the ccb is perimetric and oriented in positive direction,
|
||
|
* NEGATIVE if the ccb is perimetric and oriented in negative direction).
|
||
|
*/
|
||
|
std::pair<std::pair<Sign, Sign>, const DHalfedge*>
|
||
|
_compute_signs_and_min(const DHalfedge* he,
|
||
|
Arr_parameter_space& ps_x_min,
|
||
|
Arr_parameter_space& ps_y_min,
|
||
|
int& index_min) const;
|
||
|
|
||
|
/*!
|
||
|
* Compute the signs (in left/right and bottom/top) of a closed ccb (loop)
|
||
|
* represented by a given halfedge.
|
||
|
* \param he The representative halfedge on the ccb.
|
||
|
* \return A pair of signs for the induced path.
|
||
|
* A sign ZERO is if the ccb is non-perimetric,
|
||
|
* POSITIVE if the ccb is perimetric and oriented in positive direction,
|
||
|
* NEGATIVE if the ccb is perimetric and oriented in negative direction).
|
||
|
*/
|
||
|
std::pair<Sign, Sign> _compute_signs(const DHalfedge* he,
|
||
|
boost::mpl::bool_<true>) const;
|
||
|
|
||
|
/*! Compute the signs (in left/right and bottom/top) of a closed ccb (loop)
|
||
|
* represented by a given halfedge for the case where non of the boundaries
|
||
|
* is identified.
|
||
|
* \return the pair (ZERO, ZERO)
|
||
|
*/
|
||
|
std::pair<Sign, Sign> _compute_signs(const DHalfedge* he,
|
||
|
boost::mpl::bool_<false>) const;
|
||
|
|
||
|
/*!
|
||
|
* Given two predecessor halfedges that will be used for inserting a
|
||
|
* new halfedge pair (he_to is the predecessor of the directed curve
|
||
|
* cv, cv_dir and he_away will be the successor), such that the
|
||
|
* insertion will create a new face that forms a hole inside an existing
|
||
|
* face, determine whether he_to=>cv,cv_dir=>he_away will be part
|
||
|
* of the new outer ccb of the new face.
|
||
|
* \param he_to The predecessor halfedge.
|
||
|
* \param cv The x-monotone curve we use to connect he_to's target and
|
||
|
* he_away's source vertex.
|
||
|
* \param cv_dir the direction of the curve between he_to and he_away
|
||
|
* \param he_away The succcessor halfedge.
|
||
|
* \pre he_to and he_away belong to the same inner CCB.
|
||
|
* \return true if he_to=>cv,cv_dir=>he_away lie in the interior of the face we
|
||
|
* are about to create (i.e.~are part of the new outer ccb),
|
||
|
* false otherwise - in which case the subsequence
|
||
|
* he_away->next()=>cv,opposite(cv_dir)=>he_to->next()
|
||
|
* must be incident to this new face (i.e.~are part
|
||
|
* of the new outer ccb).
|
||
|
*/
|
||
|
template <typename InputIterator>
|
||
|
bool _defines_outer_ccb_of_new_face(const DHalfedge* he_to,
|
||
|
const X_monotone_curve_2& cv,
|
||
|
const DHalfedge* he_away,
|
||
|
InputIterator lm_begin,
|
||
|
InputIterator lm_end) const;
|
||
|
|
||
|
/*!
|
||
|
* Move a given outer CCB from one face to another.
|
||
|
* \param from_face The face currently containing the component.
|
||
|
* \param to_face The face into which we should move the component.
|
||
|
* \param he A halfedge lying on the outer component.
|
||
|
*/
|
||
|
void _move_outer_ccb(DFace* from_face, DFace* to_face, DHalfedge* he);
|
||
|
|
||
|
/*!
|
||
|
* Move a given inner CCB (hole) from one face to another.
|
||
|
* \param from_face The face currently containing the component.
|
||
|
* \param to_face The face into which we should move the component.
|
||
|
* \param he A halfedge lying on the inner component.
|
||
|
*/
|
||
|
void _move_inner_ccb(DFace* from_face, DFace* to_face, DHalfedge* he);
|
||
|
|
||
|
/*!
|
||
|
* Move all inner CCBs (holes) from one face to another.
|
||
|
* \param from_face The face currently containing the components.
|
||
|
* \param to_face The face into which we should move the components.
|
||
|
*/
|
||
|
void _move_all_inner_ccb(DFace* from_face, DFace* to_face);
|
||
|
|
||
|
/*!
|
||
|
* Insert the given vertex as an isolated vertex inside the given face.
|
||
|
* \param f The face that should contain the isolated vertex.
|
||
|
* \param v The isolated vertex.
|
||
|
*/
|
||
|
void _insert_isolated_vertex(DFace* f, DVertex* v);
|
||
|
|
||
|
/*!
|
||
|
* Move a given isolated vertex from one face to another.
|
||
|
* \param from_face The face currently containing the isolated vertex.
|
||
|
* \param to_face The face into which we should move the isolated vertex.
|
||
|
* \param v The isolated vertex.
|
||
|
*/
|
||
|
void _move_isolated_vertex(DFace* from_face, DFace* to_face, DVertex* v);
|
||
|
|
||
|
/*!
|
||
|
* Move all isolated vertices from one face to another.
|
||
|
* \param from_face The face currently containing the isolated vertices.
|
||
|
* \param to_face The face into which we should move the isolated vertices.
|
||
|
*/
|
||
|
void _move_all_isolated_vertices(DFace* from_face, DFace* to_face);
|
||
|
|
||
|
/*!
|
||
|
* Create a new vertex and associate it with the given point.
|
||
|
* \param p The point.
|
||
|
* \return A pointer to the newly created vertex.
|
||
|
*/
|
||
|
DVertex* _create_vertex(const Point_2& p);
|
||
|
|
||
|
/*!
|
||
|
* Create a new boundary vertex.
|
||
|
* \param cv The curve incident to the boundary.
|
||
|
* \param ind The relevant curve-end.
|
||
|
* \param bx The boundary condition in x.
|
||
|
* \param by The boundary condition in y.
|
||
|
* \pre Either bx or by does not equal ARR_INTERIOR.
|
||
|
* \return A pointer to the newly created vertex.
|
||
|
*/
|
||
|
DVertex* _create_boundary_vertex(const X_monotone_curve_2& cv,
|
||
|
Arr_curve_end ind,
|
||
|
Arr_parameter_space bx,
|
||
|
Arr_parameter_space by);
|
||
|
|
||
|
/*!
|
||
|
* Locate the DCEL features that will be used for inserting the given curve
|
||
|
* end, which has a boundary condition, and set a proper vertex there.
|
||
|
* \param f The face that contains the curve end.
|
||
|
* \param cv The x-monotone curve.
|
||
|
* \param ind The curve end.
|
||
|
* \param bx The boundary condition at the x-coordinate.
|
||
|
* \param by The boundary condition at the y-coordinate.
|
||
|
* \param p_pred Output: The predecessor halfedge around this vertex
|
||
|
* (may be NULL, if no such halfedge exists).
|
||
|
* \return The vertex that corresponds to the curve end.
|
||
|
*/
|
||
|
DVertex* _place_and_set_curve_end(DFace* f,
|
||
|
const X_monotone_curve_2& cv,
|
||
|
Arr_curve_end ind,
|
||
|
Arr_parameter_space bx,
|
||
|
Arr_parameter_space by,
|
||
|
DHalfedge** p_pred);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that both its
|
||
|
* endpoints correspond to free arrangement vertices (newly created vertices
|
||
|
* or existing isolated vertices), so a new inner CCB is formed in the face
|
||
|
* that contains the two vertices.
|
||
|
* \param f The face containing the two end vertices.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param cv_dir The direction of the curve
|
||
|
* \param v1 The free vertex that corresponds to the left endpoint of cv.
|
||
|
* \param v2 The free vertex that corresponds to the right endpoint of cv.
|
||
|
* \return A pointer to one of the halfedges corresponding to the inserted
|
||
|
* curve, directed from v1 to v2.
|
||
|
*/
|
||
|
DHalfedge* _insert_in_face_interior(DFace* f,
|
||
|
const X_monotone_curve_2& cv,
|
||
|
Arr_halfedge_direction cv_dir,
|
||
|
DVertex* v1, DVertex* v2);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that one of its
|
||
|
* endpoints corresponds to a given arrangement vertex, given the exact
|
||
|
* place for the curve in the circular list around this vertex. The other
|
||
|
* endpoint corrsponds to a free vertex (a newly created vertex or an
|
||
|
* isolated vertex).
|
||
|
* \param he_to The reference halfedge. We should represent cv as a pair
|
||
|
* of edges, one of them should become he_to's successor.
|
||
|
* \param cv The given x-monotone curve.
|
||
|
* \param cv_dir The direction of cv.
|
||
|
* \param v The free vertex that corresponds to the other endpoint.
|
||
|
* \return A pointer to one of the halfedges corresponding to the inserted
|
||
|
* curve, whose target is the vertex v.
|
||
|
*/
|
||
|
DHalfedge* _insert_from_vertex(DHalfedge* he_to, const X_monotone_curve_2& cv,
|
||
|
Arr_halfedge_direction cv_dir,
|
||
|
DVertex* v);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, where the end vertices
|
||
|
* are given by the target points of two given halfedges.
|
||
|
* The two halfedges should be given such that in case a new face is formed,
|
||
|
* it will be the incident face of the halfedge directed from the first
|
||
|
* vertex to the second vertex.
|
||
|
* \param he_to The reference halfedge pointing to the insertion vertex
|
||
|
* \param cv the given curve.
|
||
|
* \param cv_dir the direction of the curve
|
||
|
* \param he_away the reference halfedge for the second vertex.
|
||
|
* \param res the comparison result of the points associated with prev1's
|
||
|
* target vertex and prev2's target vertex.
|
||
|
* \param new_face (Output) indicates whether a new face has been created.
|
||
|
* \param swapped_predecessors (Output) indicates whether roles of prev1 and
|
||
|
* prev2 have been switched
|
||
|
* \param allow_swap_of_predecessors set to false if no swapping should
|
||
|
* take place at all
|
||
|
* \return A pointer to one of the halfedges corresponding to the inserted
|
||
|
* curve directed from prev1's target to prev2's target.
|
||
|
* In case a new face has been created, it is given as the incident
|
||
|
* face of this halfedge.
|
||
|
*/
|
||
|
DHalfedge* _insert_at_vertices(DHalfedge* he_to,
|
||
|
const X_monotone_curve_2& cv,
|
||
|
Arr_halfedge_direction cv_dir,
|
||
|
DHalfedge* he_away,
|
||
|
bool& new_face,
|
||
|
bool& swapped_predecessors,
|
||
|
bool allow_swap_of_predecessors = true);
|
||
|
|
||
|
/*!
|
||
|
* Relocate all inner CCBs and isolated vertices to their proper position,
|
||
|
* immediately after a face has split due to the insertion of a new halfedge.
|
||
|
* \param new_he The new halfedge that caused the split, such that the new
|
||
|
* face lies to its left and the old face to its right.
|
||
|
*/
|
||
|
void _relocate_in_new_face(DHalfedge* new_he);
|
||
|
|
||
|
/*!
|
||
|
* Relocate all inner CCBs to their proper position,
|
||
|
* immediately after a face has split due to the insertion of a new halfedge.
|
||
|
* \param new_he The new halfedge that caused the split, such that the new
|
||
|
* face lies to its left and the old face to its right.
|
||
|
*/
|
||
|
void _relocate_inner_ccbs_in_new_face(DHalfedge* new_he);
|
||
|
|
||
|
/*!
|
||
|
* Relocate all vertices to their proper position,
|
||
|
* immediately after a face has split due to the insertion of a new halfedge.
|
||
|
* \param new_he The new halfedge that caused the split, such that the new
|
||
|
* face lies to its left and the old face to its right.
|
||
|
*/
|
||
|
void _relocate_isolated_vertices_in_new_face(DHalfedge* new_he);
|
||
|
|
||
|
/*!
|
||
|
* Replace the point associated with the given vertex.
|
||
|
* \param v The vertex to modify.
|
||
|
* \param p The point that should be associated with the edge.
|
||
|
*/
|
||
|
void _modify_vertex(DVertex* v, const Point_2& p);
|
||
|
|
||
|
/*!
|
||
|
* Replace the x-monotone curve associated with the given edge.
|
||
|
* \param e The edge to modify.
|
||
|
* \param cv The curve that should be associated with the edge.
|
||
|
*/
|
||
|
void _modify_edge(DHalfedge* he, const X_monotone_curve_2& cv);
|
||
|
|
||
|
/*!
|
||
|
* Check if the given vertex represents one of the ends of a given curve.
|
||
|
* \param v The vertex.
|
||
|
* \param cv The curve.
|
||
|
* \param ind Indicates whether the minimal or the maximal end of cv is
|
||
|
* refereed to.
|
||
|
* \return Whether v represents the left (or right) end of cv.
|
||
|
*/
|
||
|
bool _are_equal(const DVertex* v,
|
||
|
const X_monotone_curve_2& cv, Arr_curve_end ind) const;
|
||
|
|
||
|
/*!
|
||
|
* Split a given edge into two at a given point, and associate the given
|
||
|
* x-monotone curves with the split edges.
|
||
|
* \param e The edge to split (one of the pair of twin halfegdes).
|
||
|
* \param p The split point.
|
||
|
* \param cv1 The curve that should be associated with the first split edge,
|
||
|
* whose source equals e's source and its target is p.
|
||
|
* \param cv2 The curve that should be associated with the second split edge,
|
||
|
* whose source is p and its target equals e's target.
|
||
|
* \return A pointer to the first split halfedge, whose source equals the
|
||
|
* source of e, and whose target is the split point.
|
||
|
*/
|
||
|
DHalfedge* _split_edge(DHalfedge* e, const Point_2& p,
|
||
|
const X_monotone_curve_2& cv1,
|
||
|
const X_monotone_curve_2& cv2);
|
||
|
|
||
|
/*!
|
||
|
* Split a given edge into two at a given vertex, and associate the given
|
||
|
* x-monotone curves with the split edges.
|
||
|
* \param e The edge to split (one of the pair of twin halfegdes).
|
||
|
* \param v The split vertex.
|
||
|
* \param cv1 The curve that should be associated with the first split edge,
|
||
|
* whose source equals e's source and its target is v.
|
||
|
* \param cv2 The curve that should be associated with the second split edge,
|
||
|
* whose source is v and its target equals e's target.
|
||
|
* \return A pointer to the first split halfedge, whose source equals the
|
||
|
* source of e, and whose target is v.
|
||
|
*/
|
||
|
DHalfedge* _split_edge(DHalfedge* e, DVertex* v,
|
||
|
const X_monotone_curve_2& cv1,
|
||
|
const X_monotone_curve_2& cv2);
|
||
|
|
||
|
/*!
|
||
|
* Remove a pair of twin halfedges from the arrangement.
|
||
|
* \param e One of the halfedges to be removed.
|
||
|
* \param remove_source Should the source vertex of e be removed if it
|
||
|
* becomes isolated.
|
||
|
* \param remove_target Should the target vertex of e be removed if it
|
||
|
* becomes isolated.
|
||
|
* \pre In case the removal causes the creation of a new inner CCB (hole),
|
||
|
* e should point at this hole.
|
||
|
* \return A pointer to the remaining face.
|
||
|
*/
|
||
|
DFace* _remove_edge(DHalfedge* e, bool remove_source, bool remove_target);
|
||
|
|
||
|
/*!
|
||
|
* Decide whether a hole is created when an edge is removed.
|
||
|
*
|
||
|
* \param signs1 signs of future ccb1
|
||
|
* \param signs2 signs of future ccb2
|
||
|
* \param same_face to he and he->opposite() belong to same face
|
||
|
* return true, in case a new hole is created, false otherwise
|
||
|
*/
|
||
|
bool _hole_creation_on_edge_removal(std::pair< CGAL::Sign, CGAL::Sign > signs1,
|
||
|
std::pair< CGAL::Sign, CGAL::Sign > signs2,
|
||
|
bool same_face);
|
||
|
|
||
|
/*!
|
||
|
* Remove a vertex in case it becomes redundant after the deletion of an
|
||
|
* incident edge.
|
||
|
* \param v The vertex.
|
||
|
* \param f The face that contains v (in case it becomes isolated).
|
||
|
*/
|
||
|
void _remove_vertex_if_redundant(DVertex* v, DFace* f);
|
||
|
|
||
|
/*!
|
||
|
* Remove an isolated vertex from the interior of its face (but not from
|
||
|
* the DCEL).
|
||
|
* \param v The isolated vertex to remove.
|
||
|
*/
|
||
|
void _remove_isolated_vertex(DVertex* v);
|
||
|
//@}
|
||
|
|
||
|
/// \name Auxiliary (protected) functions for validity checking.
|
||
|
//@{
|
||
|
|
||
|
/*! Check the validity of a given vertex. */
|
||
|
bool _is_valid(Vertex_const_handle v) const;
|
||
|
|
||
|
/*! Check the validity of a given halfedge. */
|
||
|
bool _is_valid(Halfedge_const_handle he) const;
|
||
|
|
||
|
/*! Check the validity of a given face. */
|
||
|
bool _is_valid(Face_const_handle f) const;
|
||
|
|
||
|
/*! Check the validity of an outer CCB. */
|
||
|
bool _is_outer_ccb_valid(const DOuter_ccb* oc, const DHalfedge* first) const;
|
||
|
|
||
|
/*! Check the validity of an inner CCB. */
|
||
|
bool _is_inner_ccb_valid(const DInner_ccb* ic, const DHalfedge* first) const;
|
||
|
|
||
|
/*!
|
||
|
* Check that all vertices are unique (no two vertices with the same
|
||
|
* geometric point.
|
||
|
*/
|
||
|
bool _are_vertices_unique() const;
|
||
|
|
||
|
/*! Check that the curves around a given vertex are ordered clockwise. */
|
||
|
bool _are_curves_ordered_cw_around_vertrex(Vertex_const_handle v) const;
|
||
|
|
||
|
//@}
|
||
|
|
||
|
protected:
|
||
|
/// \name Managing and notifying the arrangement observers.
|
||
|
//@{
|
||
|
|
||
|
/*!
|
||
|
* Register a new observer (so it starts receiving notifications).
|
||
|
* \param p_obs A pointer to the observer object.
|
||
|
*/
|
||
|
void _register_observer(Observer* p_obs) { m_observers.push_back(p_obs); }
|
||
|
|
||
|
/*!
|
||
|
* Unregister a new observer (so it stops receiving notifications).
|
||
|
* \param p_obs A pointer to the observer object.
|
||
|
* \return Whether the observer was successfully unregistered.
|
||
|
*/
|
||
|
bool _unregister_observer(Observer* p_obs)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter) {
|
||
|
if ((*iter) == p_obs) {
|
||
|
// Remove the p_ob pointer from the list of observers.
|
||
|
m_observers.erase (iter);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we reached here, the observer was not registered.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
/* Notify the observers on global arrangement operations: */
|
||
|
|
||
|
void _notify_before_assign(const Self& arr)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_assign(arr);
|
||
|
}
|
||
|
|
||
|
void _notify_after_assign()
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_assign();
|
||
|
}
|
||
|
|
||
|
void _notify_before_clear()
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_clear();
|
||
|
}
|
||
|
|
||
|
void _notify_after_clear()
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_clear();
|
||
|
}
|
||
|
|
||
|
void _notify_before_global_change()
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_global_change();
|
||
|
}
|
||
|
|
||
|
void _notify_after_global_change()
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_global_change();
|
||
|
}
|
||
|
|
||
|
/* Notify the observers on local changes in the arrangement: */
|
||
|
|
||
|
void _notify_before_create_vertex(const Point_2& p)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_create_vertex(p);
|
||
|
}
|
||
|
|
||
|
void _notify_after_create_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_create_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_before_create_boundary_vertex(const X_monotone_curve_2& cv,
|
||
|
Arr_curve_end ind,
|
||
|
Arr_parameter_space bx,
|
||
|
Arr_parameter_space by)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_create_boundary_vertex(cv, ind, bx, by);
|
||
|
}
|
||
|
|
||
|
void _notify_after_create_boundary_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_create_boundary_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_before_create_edge(const X_monotone_curve_2& c,
|
||
|
Vertex_handle v1, Vertex_handle v2)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_create_edge(c, v1, v2);
|
||
|
}
|
||
|
|
||
|
void _notify_after_create_edge(Halfedge_handle e)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_create_edge(e);
|
||
|
}
|
||
|
|
||
|
void _notify_before_modify_vertex(Vertex_handle v, const Point_2& p)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_modify_vertex(v, p);
|
||
|
}
|
||
|
|
||
|
void _notify_after_modify_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_modify_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_before_modify_edge(Halfedge_handle e,
|
||
|
const X_monotone_curve_2& c)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_modify_edge(e, c);
|
||
|
}
|
||
|
|
||
|
void _notify_after_modify_edge(Halfedge_handle e)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_modify_edge(e);
|
||
|
}
|
||
|
|
||
|
void _notify_before_split_edge(Halfedge_handle e, Vertex_handle v,
|
||
|
const X_monotone_curve_2& c1,
|
||
|
const X_monotone_curve_2& c2)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_split_edge(e, v, c1, c2);
|
||
|
}
|
||
|
|
||
|
void _notify_after_split_edge(Halfedge_handle e1, Halfedge_handle e2)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_split_edge(e1, e2);
|
||
|
}
|
||
|
|
||
|
void _notify_before_split_fictitious_edge(Halfedge_handle e, Vertex_handle v)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_split_fictitious_edge(e, v);
|
||
|
}
|
||
|
|
||
|
void _notify_after_split_fictitious_edge(Halfedge_handle e1,
|
||
|
Halfedge_handle e2)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_split_fictitious_edge(e1, e2);
|
||
|
}
|
||
|
|
||
|
void _notify_before_split_face(Face_handle f, Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_split_face(f, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_split_face(Face_handle f, Face_handle new_f, bool is_hole)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_split_face(f, new_f, is_hole);
|
||
|
}
|
||
|
|
||
|
void _notify_before_split_outer_ccb(Face_handle f, Ccb_halfedge_circulator h,
|
||
|
Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_split_outer_ccb(f, h, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_split_outer_ccb(Face_handle f, Ccb_halfedge_circulator h1,
|
||
|
Ccb_halfedge_circulator h2)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_split_outer_ccb(f, h1, h2);
|
||
|
}
|
||
|
|
||
|
void _notify_before_split_inner_ccb(Face_handle f, Ccb_halfedge_circulator h,
|
||
|
Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_split_inner_ccb(f, h, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_split_inner_ccb(Face_handle f,
|
||
|
Ccb_halfedge_circulator h1,
|
||
|
Ccb_halfedge_circulator h2)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_split_inner_ccb(f, h1, h2);
|
||
|
}
|
||
|
|
||
|
void _notify_before_add_outer_ccb(Face_handle f, Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_add_outer_ccb(f, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_add_outer_ccb(Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_add_outer_ccb(h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_add_inner_ccb(Face_handle f, Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_add_inner_ccb(f, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_add_inner_ccb(Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_add_inner_ccb(h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_add_isolated_vertex(Face_handle f, Vertex_handle v)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_add_isolated_vertex(f, v);
|
||
|
}
|
||
|
|
||
|
void _notify_after_add_isolated_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_add_isolated_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_before_merge_edge(Halfedge_handle e1, Halfedge_handle e2,
|
||
|
const X_monotone_curve_2& c)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_merge_edge(e1, e2, c);
|
||
|
}
|
||
|
|
||
|
void _notify_after_merge_edge(Halfedge_handle e)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_merge_edge(e);
|
||
|
}
|
||
|
|
||
|
void _notify_before_merge_fictitious_edge(Halfedge_handle e1,
|
||
|
Halfedge_handle e2)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_merge_fictitious_edge(e1, e2);
|
||
|
}
|
||
|
|
||
|
void _notify_after_merge_fictitious_edge(Halfedge_handle e)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_merge_fictitious_edge(e);
|
||
|
}
|
||
|
|
||
|
void _notify_before_merge_face(Face_handle f1, Face_handle f2,
|
||
|
Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_merge_face(f1, f2, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_merge_face(Face_handle f)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_merge_face(f);
|
||
|
}
|
||
|
|
||
|
void _notify_before_merge_outer_ccb(Face_handle f,
|
||
|
Ccb_halfedge_circulator h1,
|
||
|
Ccb_halfedge_circulator h2,
|
||
|
Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_merge_outer_ccb(f, h1, h2, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_merge_outer_ccb(Face_handle f,
|
||
|
Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_merge_outer_ccb(f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_merge_inner_ccb(Face_handle f,
|
||
|
Ccb_halfedge_circulator h1,
|
||
|
Ccb_halfedge_circulator h2,
|
||
|
Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_merge_inner_ccb(f, h1, h2, e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_merge_inner_ccb(Face_handle f,
|
||
|
Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_merge_inner_ccb(f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_move_outer_ccb(Face_handle from_f,
|
||
|
Face_handle to_f,
|
||
|
Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_move_outer_ccb(from_f, to_f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_after_move_outer_ccb(Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_move_outer_ccb(h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_move_inner_ccb(Face_handle from_f,
|
||
|
Face_handle to_f,
|
||
|
Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_move_inner_ccb(from_f, to_f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_after_move_inner_ccb(Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_move_inner_ccb(h);
|
||
|
}
|
||
|
|
||
|
void _notify_before_move_isolated_vertex(Face_handle from_f,
|
||
|
Face_handle to_f,
|
||
|
Vertex_handle v)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_move_isolated_vertex(from_f, to_f, v);
|
||
|
}
|
||
|
|
||
|
|
||
|
void _notify_after_move_isolated_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_move_isolated_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_before_remove_vertex(Vertex_handle v)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_remove_vertex(v);
|
||
|
}
|
||
|
|
||
|
void _notify_after_remove_vertex()
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_remove_vertex();
|
||
|
}
|
||
|
|
||
|
void _notify_before_remove_edge(Halfedge_handle e)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_remove_edge(e);
|
||
|
}
|
||
|
|
||
|
void _notify_after_remove_edge()
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_remove_edge();
|
||
|
}
|
||
|
|
||
|
void _notify_before_remove_outer_ccb(Face_handle f, Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_remove_outer_ccb(f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_after_remove_outer_ccb(Face_handle f)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_remove_outer_ccb(f);
|
||
|
}
|
||
|
|
||
|
void _notify_before_remove_inner_ccb(Face_handle f, Ccb_halfedge_circulator h)
|
||
|
{
|
||
|
Observers_iterator iter;
|
||
|
Observers_iterator end = m_observers.end();
|
||
|
for (iter = m_observers.begin(); iter != end; ++iter)
|
||
|
(*iter)->before_remove_inner_ccb(f, h);
|
||
|
}
|
||
|
|
||
|
void _notify_after_remove_inner_ccb(Face_handle f)
|
||
|
{
|
||
|
Observers_rev_iterator iter;
|
||
|
Observers_rev_iterator end = m_observers.rend();
|
||
|
for (iter = m_observers.rbegin(); iter != end; ++iter)
|
||
|
(*iter)->after_remove_inner_ccb(f);
|
||
|
}
|
||
|
//@}
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Declarations of the various global insertion and removal functions.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
// In some compilers there is a template deduction disambiguity between this
|
||
|
// function and the following function receiving two InputIterator.
|
||
|
// For now the solution is to add a dummy variable at the end (referring
|
||
|
// to point-location). Maybe the proper solution is to use boost::enable_if
|
||
|
// together with appropriate tag.
|
||
|
/*!
|
||
|
* Insert a curve or x-monotone curve into the arrangement (incremental
|
||
|
* insertion).
|
||
|
* The inserted curve can be x-monotone (or not) and may intersect the
|
||
|
* existing arrangement.
|
||
|
* \param arr The arrangement.
|
||
|
* \param cv The curve to be inserted.
|
||
|
* \param pl A point-location object associated with the arrangement.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename Curve,
|
||
|
typename PointLocation>
|
||
|
void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const Curve& c, const PointLocation& pl,
|
||
|
typename PointLocation::Point_2* = 0);
|
||
|
|
||
|
/*!
|
||
|
* Insert a curve or x-monotone curve into the arrangement (incremental
|
||
|
* insertion).
|
||
|
* The inserted curve can be x-monotone (or not) and may intersect the
|
||
|
* existing arrangement. The default "walk" point-location strategy is used
|
||
|
* for the curve insertion.
|
||
|
* \param arr The arrangement.
|
||
|
* \param cv The curve to be inserted.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename Curve>
|
||
|
void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const Curve& c);
|
||
|
|
||
|
/*!
|
||
|
* Insert a range of curves or x-monotone curves into the arrangement
|
||
|
* (aggregated insertion).
|
||
|
* The inserted curves may intersect one another and may also intersect the
|
||
|
* existing arrangement.
|
||
|
* \param arr The arrangement.
|
||
|
* \param begin An iterator for the first curve in the range.
|
||
|
* \param end A past-the-end iterator for the curve range.
|
||
|
* \pre The value type of the iterators must be Curve_2.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename InputIterator>
|
||
|
void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
InputIterator begin, InputIterator end);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement (incremental insertion)
|
||
|
* when the location of the left endpoint of the curve is known and is
|
||
|
* given as an isertion hint.
|
||
|
* The inserted x-monotone curve may intersect the existing arrangement.
|
||
|
* \param arr The arrangement.
|
||
|
* \param cv The x-monotone curve to be inserted.
|
||
|
* \param obj An object that represents the location of cv's left endpoint
|
||
|
* in the arrangement.
|
||
|
*/
|
||
|
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::X_monotone_curve_2& c,
|
||
|
const Object& obj);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that the curve
|
||
|
* interior does not intersect with any existing edge or vertex in the
|
||
|
* arragement (incremental insertion).
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The x-monotone curve to be inserted.
|
||
|
* \param pl A point-location object associated with the arrangement.
|
||
|
* \pre The interior of c does not intersect any existing edge or vertex.
|
||
|
* \return A handle for one of the new halfedges corresponding to the
|
||
|
* inserted curve, directed (lexicographically) from left to right.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename PointLocation>
|
||
|
typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
|
||
|
insert_non_intersecting_curve
|
||
|
(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::X_monotone_curve_2& c,
|
||
|
const PointLocation& pl);
|
||
|
|
||
|
/*!
|
||
|
* Insert an x-monotone curve into the arrangement, such that the curve
|
||
|
* interior does not intersect with any existing edge or vertex in the
|
||
|
* arragement (incremental insertion). The default point-location strategy
|
||
|
* is used for the curve insertion.
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The x-monotone curve to be inserted.
|
||
|
* \pre The interior of c does not intersect any existing edge or vertex.
|
||
|
* \return A handle for one of the new halfedges corresponding to the inserted
|
||
|
* curve, directed (lexicographically) from left to right.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
|
||
|
insert_non_intersecting_curve
|
||
|
(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::X_monotone_curve_2& c);
|
||
|
|
||
|
/*!
|
||
|
* Insert a range of pairwise interior-disjoint x-monotone curves into
|
||
|
* the arrangement, such that the curve interiors do not intersect with
|
||
|
* any existing edge or vertex in the arragement (aggregated insertion).
|
||
|
* \param arr The arrangement.
|
||
|
* \param begin An iterator for the first x-monotone curve in the range.
|
||
|
* \param end A past-the-end iterator for the x-monotone curve range.
|
||
|
* \pre The value type of the iterators must be X_monotone_curve_2.
|
||
|
* The curves in the range are pairwise interior-disjoint, and their
|
||
|
* interiors do not intersect any existing edge or vertex.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename InputIterator>
|
||
|
void insert_non_intersecting_curves
|
||
|
(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
InputIterator begin, InputIterator end);
|
||
|
|
||
|
/*!
|
||
|
* Remove an edge from the arrangement. In case it is possible to merge
|
||
|
* the edges incident to the end-vertices of the removed edge after its
|
||
|
* deletion, the function performs these merges as well.
|
||
|
* \param arr The arrangement.
|
||
|
* \param e The edge to remove (one of the pair of twin halfegdes).
|
||
|
* \return A handle for the remaining face.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle
|
||
|
remove_edge(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
typename Arrangement_on_surface_2<GeomTraits,
|
||
|
TopTraits>::Halfedge_handle e);
|
||
|
|
||
|
/*!
|
||
|
* Insert a vertex that corresponds to a given point into the arrangement.
|
||
|
* The inserted point may lie on any existing arrangement feature.
|
||
|
* \param arr The arrangement.
|
||
|
* \param p The point to be inserted.
|
||
|
* \param pl A point-location object associated with the arrangement.
|
||
|
* \return A handle to the vertex that corresponds to the given point.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename PointLocation>
|
||
|
typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle
|
||
|
insert_point(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::Point_2& p,
|
||
|
const PointLocation& pl);
|
||
|
|
||
|
/*!
|
||
|
* Insert a vertex that corresponds to a given point into the arrangement.
|
||
|
* The inserted point may lie on any existing arrangement feature.
|
||
|
* \param arr The arrangement.
|
||
|
* \param p The point to be inserted.
|
||
|
* \return A handle to the vertex that corresponds to the given point.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle
|
||
|
insert_point(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::Point_2& p);
|
||
|
|
||
|
/*!
|
||
|
* Remove a vertex from the arrangement.
|
||
|
* \param arr The arrangement.
|
||
|
* \param v The vertex to remove.
|
||
|
* \return Whether the vertex has been removed or not.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
bool
|
||
|
remove_vertex(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
typename Arrangement_on_surface_2<GeomTraits,
|
||
|
TopTraits>::Vertex_handle v);
|
||
|
|
||
|
|
||
|
/*!
|
||
|
* Check the validity of the arrangement. In particular, check that the
|
||
|
* edegs are disjoint-interior, and the holes are located in their proper
|
||
|
* position.
|
||
|
* \param arr The arrangement.
|
||
|
* \return Whether the arrangement is valid.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits>
|
||
|
bool is_valid(const Arrangement_on_surface_2<GeomTraits, TopTraits>& arr);
|
||
|
|
||
|
/*!
|
||
|
* Compute the zone of the given x-monotone curve in the existing arrangement.
|
||
|
* Meaning, it output the arrangment's vertices, edges and faces that the
|
||
|
* x-monotone curve intersects.
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The x-monotone curve that its zone was computed.
|
||
|
* \param oi Output iterator of CGAL::Object to insert the zone elements to.
|
||
|
* \param pi The point location strategy that is used to locate the starting
|
||
|
* point.
|
||
|
* \return The output iterator that the curves were inserted to.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits,
|
||
|
typename OutputIterator, typename PointLocation>
|
||
|
OutputIterator zone(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::X_monotone_curve_2& c,
|
||
|
OutputIterator oi,
|
||
|
const PointLocation& pl);
|
||
|
|
||
|
/*!
|
||
|
* Compute the zone of the given x-monotone curve in the existing arrangement.
|
||
|
* Overloaded version with no point location object - the walk point-location
|
||
|
* strategy is used as default.
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The x-monotone curve that its zone was computed.
|
||
|
* \param oi Output iterator of CGAL::Object to insert the zone elements to.
|
||
|
* \return The output iterator that the curves were inserted to.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename OutputIterator>
|
||
|
OutputIterator zone(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const typename GeomTraits::X_monotone_curve_2& c,
|
||
|
OutputIterator oi);
|
||
|
|
||
|
/*!
|
||
|
* Checks if the given curve/x-monotone curve intersects the existing
|
||
|
* arrangement.
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The curve/x-monotone curve.
|
||
|
* \param pi The point location strategy that is used to locate the starting
|
||
|
* point.
|
||
|
* \return True if the curve intersect the arrangement, false otherwise.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename Curve,
|
||
|
typename PointLocation>
|
||
|
bool do_intersect(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const Curve& c, const PointLocation& pl);
|
||
|
|
||
|
/*!
|
||
|
* Checks if the given curve/x-monotone curve intersects the existing
|
||
|
* arrangement.
|
||
|
* Overloaded version with no point location object - the walk point-location
|
||
|
* strategy is used as default.
|
||
|
* \param arr The arrangement.
|
||
|
* \param c The x-monotone curve/curve.
|
||
|
* \return True if the curve intersect the arrangement, false otherwise.
|
||
|
*/
|
||
|
template <typename GeomTraits, typename TopTraits, typename Curve>
|
||
|
bool do_intersect(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr,
|
||
|
const Curve& c);
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
// The function definitions can be found under:
|
||
|
#include <CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h>
|
||
|
#include <CGAL/Arrangement_2/Arrangement_on_surface_2_global.h>
|
||
|
|
||
|
#include <CGAL/enable_warnings.h>
|
||
|
#endif
|