wein: fixed vertical-decomposition

This commit is contained in:
Efi Fogel 2007-08-23 13:53:07 +00:00
parent 39ab15f6d6
commit f46a4b71aa
4 changed files with 725 additions and 0 deletions

View File

@ -0,0 +1,106 @@
// Copyright (c) 2007 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Ron Wein <wein@post.tau.ac.il>
#ifndef CGAL_ARR_BOUNDED_PLANAR_VERT_DEOCMP_HELPER_H
#define CGAL_ARR_BOUNDED_PLANAR_VERT_DEOCMP_HELPER_H
/*! \file
* Definition of the Arr_bounded_planar_vert_decomp_helper class-template.
*/
CGAL_BEGIN_NAMESPACE
#include <CGAL/Sweep_line_empty_visitor.h>
/*! \class Arr_bounded_planar_vert_decomp_helper
* A helper class for the vertical decomposition sweep-line visitor, suitable
* for an Arrangement_on_surface_2 instantiated with a topology-traits class
* for bounded curves in the plane.
*/
template <class Traits_, class Arrangement_>
class Arr_bounded_planar_vert_decomp_helper
{
public:
typedef Traits_ Traits_2;
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef Sweep_line_empty_visitor<Traits_2> Base_visitor;
typedef typename Base_visitor::Event Event;
typedef typename Base_visitor::Subcurve Subcurve;
protected:
typedef typename Arrangement_2::Topology_traits Topology_traits;
// Data members:
const Topology_traits *m_top_traits; // The topology-traits class.
Face_const_handle m_unb_face; // The unbounded arrangement face.
public:
/*!
* Constructor.
* \param arr The arrangement.
*/
Arr_bounded_planar_vert_decomp_helper (const Arrangement_2 *arr) :
m_top_traits (arr->topology_traits())
{}
/// \name Notification functions.
//@{
/* A notification issued before the sweep process starts. */
void before_sweep ()
{
// Get the unbounded face.
m_unb_face = Face_const_handle (m_top_traits->unbounded_face());
}
/*!
* A notification invoked after the sweep-line finishes handling the given
* event.
*/
void after_handle_event (Event* event)
{
return;
}
//@}
/*! Get the current top object. */
CGAL::Object top_object () const
{
// Wrap the unbounded face by a CGAL object.
return (CGAL::make_object (m_unb_face));
}
/*! Get the current bottom object. */
CGAL::Object bottom_object () const
{
// Wrap the unbounded face by a CGAL object.
return (CGAL::make_object (m_unb_face));
}
};
CGAL_END_NAMESPACE
#endif

View File

@ -0,0 +1,105 @@
// Copyright (c) 2007 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
// Author(s) : Ron Wein <wein@post.tau.ac.il>
// Efi Fogel <efif@post.tau.ac.il>
//
#ifndef CGAL_ARR_SPHERICAL_VERT_DECOMP_HELPER_H
#define CGAL_ARR_SPHERICAL_VERT_DECOMP_HELPER_H
/*! \file
* Definition of the Arr_spherical_vert_decomp_helper class-template.
*/
CGAL_BEGIN_NAMESPACE
#include <CGAL/Sweep_line_empty_visitor.h>
/*! \class Arr_spherical_vert_decomp_helper
* A helper class for the vertical decomposition sweep-line visitor, suitable
* for an Arrangement_on_surface_2 instantiated with a topology-traits class
* for bounded curves in the plane.
*/
template <class Traits_, class Arrangement_>
class Arr_spherical_vert_decomp_helper
{
public:
typedef Traits_ Traits_2;
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef Sweep_line_empty_visitor<Traits_2> Base_visitor;
typedef typename Base_visitor::Event Event;
typedef typename Base_visitor::Subcurve Subcurve;
protected:
typedef typename Arrangement_2::Topology_traits Topology_traits;
const Topology_traits *m_top_traits; // The topology traits.
Face_const_handle m_north_face; // Current north face.
public:
/*! Constructor.
* \param arr The arrangement.
*/
Arr_spherical_batched_pl_helper(const Arrangement_2 *arr) :
m_top_traits(arr->topology_traits())
{}
/// \name Notification functions.
//@{
/*! A notification issued before the sweep process starts. */
void before_sweep()
{
// Get the spherical face of the arrangement.
m_north_face = Face_handle_red(m_top_traits->spherical_face());
return;
}
/*!
* A notification invoked after the sweep-line finishes handling the given
* event.
*/
void after_handle_event(Event * event)
{
return;
}
//@}
/*! Get the current top object. */
CGAL::Object top_object () const
{
// Wrap the north face with a CGAL object.
return (m_north_face);
}
/*! Get the current bottom object. */
CGAL::Object bottom_object () const
{
// Wrap the north face with a CGAL object.
return (m_north_face);
}
};
CGAL_END_NAMESPACE
#endif

View File

@ -0,0 +1,186 @@
// Copyright (c) 2007 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Ron Wein <wein@post.tau.ac.il>
#ifndef CGAL_ARR_UNB_PLANAR_VERT_DECOMP_HELPER_H
#define CGAL_ARR_UNB_PLANAR_VERT_DECOMP_HELPER_H
/*! \file
* Definition of the Arr_unb_planar_vert_decomp_helper class-template.
*/
CGAL_BEGIN_NAMESPACE
#include <CGAL/Sweep_line_empty_visitor.h>
/*! \class Arr_unb_planar_vert_decomp_helper
* A helper class for the vertical decomposition sweep-line visitor, suitable
* for an Arrangement_on_surface_2 instantiated with a topology-traits class
* for unbounded curves in the plane.
*/
template <class Traits_, class Arrangement_>
class Arr_unb_planar_vert_decomp_helper
{
public:
typedef Traits_ Traits_2;
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef Sweep_line_empty_visitor<Traits_2> Base_visitor;
typedef typename Base_visitor::Event Event;
typedef typename Base_visitor::Subcurve Subcurve;
protected:
typedef typename Arrangement_2::Topology_traits Topology_traits;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
// Data members:
const Topology_traits *m_top_traits; // The topology-traits class.
Halfedge_const_handle m_top_fict; // The current top fictitious halfedge.
Halfedge_const_handle m_bottom_fict; // The current bottom fictitious
// halfedge.
public:
/*!
* Constructor.
* \param arr The arrangement.
*/
Arr_unb_planar_vert_decomp_helper (const Arrangement_2 *arr) :
m_top_traits (arr->topology_traits())
{}
/// \name Notification functions.
//@{
/* A notification issued before the sweep process starts. */
void before_sweep ();
/*!
* A notification invoked after the sweep-line finishes handling the given
* event.
*/
void after_handle_event (Event* event);
//@}
/*! Get the current top object. */
CGAL::Object top_object () const
{
// Wrap the top fictitious halfedge by a CGAL object.
return (CGAL::make_object (m_top_fict));
}
/*! Get the current bottom object. */
CGAL::Object bottom_object () const
{
// Wrap the bottom fictitious halfedge by a CGAL object.
return (CGAL::make_object (m_bottom_fict));
}
};
//-----------------------------------------------------------------------------
// Memeber-function definitions:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// A notification issued before the sweep process starts.
//
template <class Tr, class Arr>
void Arr_unb_planar_vert_decomp_helper<Tr, Arr>::before_sweep ()
{
// Initialize the fictitious halfedge lying on the top edge of the
// bounding rectangle. We start from the leftmost halfedge, which is
// incident to the top-left vertex and directed from right to left.
Vertex_const_handle v_tl =
Vertex_const_handle (m_top_traits->top_left_vertex());
m_top_fict = v_tl->incident_halfedges();
if (m_top_fict->direction() == LEFT_TO_RIGHT)
m_top_fict = m_top_fict->next()->twin();
CGAL_assertion_code (
Vertex_const_handle v_tr =
Vertex_const_handle (m_top_traits->top_right_vertex());
);
CGAL_assertion ((m_top_fict->source() == v_tr) ||
(m_top_fict->source()->boundary_in_x() == NO_BOUNDARY &&
m_top_fict->source()->boundary_in_y() == PLUS_INFINITY));
// Initialize the fictitious halfedge lying on the bottom edge of the
// bounding rectangle. We start from the leftmost halfedge, which is
// incident to the bottom-left vertex and whose source is not at -oo.
Vertex_const_handle v_bl =
Vertex_const_handle (m_top_traits->bottom_left_vertex());
m_bottom_fict = v_bl->incident_halfedges();
if (m_bottom_fict->source()->boundary_in_x() == MINUS_INFINITY)
m_bottom_fict = m_bottom_fict->next()->twin();
CGAL_assertion_code (
Vertex_const_handle v_br =
Vertex_const_handle (m_top_traits->bottom_right_vertex());
);
CGAL_assertion ((m_bottom_fict->source() == v_br) ||
(m_bottom_fict->source()->boundary_in_x() == NO_BOUNDARY &&
m_bottom_fict->source()->boundary_in_y() == MINUS_INFINITY));
return;
}
//-----------------------------------------------------------------------------
// A notification invoked after the sweep-line finishes handling the given
// event.
//
template <class Tr, class Arr>
void Arr_unb_planar_vert_decomp_helper<Tr, Arr>::after_handle_event
(Event* event)
{
// If the event is at infinity and occurs on the top edge of the fictitious
// face (namely x is finite and y = +oo), we have to update the fictitious
// halfedges we keep.
if (event->is_finite())
return;
if (event->boundary_in_x() != NO_BOUNDARY)
return;
Boundary_type by = event->boundary_in_y();
if (by == PLUS_INFINITY)
{
// Update the fictitious top halfedge.
m_top_fict = m_top_fict->twin()->next()->twin();
}
else
{
CGAL_assertion (by == PLUS_INFINITY);
// Update the fictitious bottom halfedge.
m_bottom_fict = m_bottom_fict->prev();
}
return;
}
CGAL_END_NAMESPACE
#endif

View File

@ -0,0 +1,328 @@
// Copyright (c) 2007 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Ron Wein <wein@post.tau.ac.il>
#ifndef CGAL_ARR_VERT_DECOMP_SL_VISITOR_H
#define CGAL_ARR_VERT_DECOMP_SL_VISITOR_H
/*!
* Definition of the Arr_vert_decomp_sl_visitor class-template.
*/
CGAL_BEGIN_NAMESPACE
#include <CGAL/Object.h>
/*! \class Arr_vert_decomp_sl_visitor
* A sweep-line visitor for performing vertical decomposition on an
* arrangement embedded on a surface.
*/
template <class Helper_, class OutputIterator_>
class Arr_vert_decomp_sl_visitor :
public Helper_::Base_visitor
{
public:
typedef Helper_ Helper;
typedef OutputIterator_ OutputIterator;
typedef typename Helper::Traits_2 Traits_2;
typedef typename Helper::Arrangement_2 Arrangement_2;
typedef typename Helper::Base_visitor Base;
typedef typename Helper::Event Event;
typedef typename Helper::Subcurve Subcurve;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef std::pair<CGAL::Object, CGAL::Object> Vert_pair;
typedef std::pair<Vertex_const_handle, Vert_pair> Vert_entry;
protected:
typedef typename Base::Status_line_iterator Status_line_iterator;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
// Data members:
Helper m_helper; // The helper class.
const typename Arrangement_2::Geometry_traits_2 *m_traits;
// The traits class.
const Vertex_const_handle invalid_vh;
// An invalid vertex handle.
Vertex_const_handle m_prev_vh; // The previous vertex.
CGAL::Object m_prev_obj_below; // The object this vertex sees below it.
CGAL::Object m_prev_obj_above; // The object this vertex sees above it.
OutputIterator *m_out; // An output iterator for the result.
public:
/*!
* Constructor.
* \param arr The arrangement.
* \param oi A pointer to the output iterator that will store the result.
*/
Arr_vert_decomp_sl_visitor (const Arrangement_2 *arr,
OutputIterator *oi) :
m_helper (arr),
m_traits (arr->geometry_traits()),
invalid_vh(),
m_out (oi)
{}
/* A notification issued before the sweep process starts. */
void before_sweep ();
/*!
* A notification invoked after the sweep-line finishes handling the given
* event.
* \param event The event.
* \param above An iterator to the sweep-line subcurves lying right above
* (or on) the event point.
* \param on_above Whether the event is locates on the subcurve above it.
*/
bool after_handle_event (Event* event,
Status_line_iterator above,
bool on_above);
/*!
* A notification issued when the sweep process is over.
*/
void after_sweep ();
};
//-----------------------------------------------------------------------------
// Memeber-function definitions:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// A notification issued before the sweep process starts.
//
template <class Hlpr, class OutIt>
void Arr_vert_decomp_sl_visitor<Hlpr, OutIt>::before_sweep ()
{
// Notify the helper that the sweep process now starts.
m_helper.before_sweep();
// Set an invalid previous vertex.
m_prev_vh = Vertex_const_handle();
return;
}
//-----------------------------------------------------------------------------
// A notification invoked after the sweep-line finishes handling the given
// event.
//
template <class Hlpr, class OutIt>
bool Arr_vert_decomp_sl_visitor<Hlpr, OutIt>::after_handle_event
(Event* event,
Status_line_iterator above, bool /* on_above */)
{
// Notify the helper on the event.
m_helper.after_handle_event (event);
// We are only interested in events associated with finite points:
if (! event->is_finite())
return (true);
// Get the vertex handle associated with the current event (stored with
// the point).
Vertex_const_handle vh = event->point().vertex_handle();
CGAL::Object obj_above, obj_below;
// Check the feature from above.
if (above == this->status_line_end())
{
// There is no concrete subcurve above the current event point, so we use
// the helper class to obtain the object above.
obj_above = m_helper.top_object();
}
else
{
// We have a valid subcurve above the event: get its halfedge handle
// and associate it with the vertex.
obj_above =
CGAL::make_object((*above)->last_curve().halfedge_handle());
}
// Check if the previous vertex we handled has the same x-coordinate
// as the current one (it lies vertically below the current vertex).
const bool prev_same_x =
(m_prev_vh != invalid_vh &&
m_traits->compare_x_2_object() (vh->point(),
m_prev_vh->point()) == EQUAL);
// Decrement the status-line iterator to reach the subcurve below the
// event point. If the number of right subcurves associated with the
// event is n_right, we decrement the iterator n_right times, then
// check if it is possible to further decrement it.
Status_line_iterator below = above;
const int n_right = event->number_of_right_curves();
int k;
for (k = 0; k < n_right; k++)
--below;
if (below == this->status_line_begin())
{
if (prev_same_x)
{
// The previous vertex is vertically below the current vertex,
// so we update their respective entries in the output map.
// We first check if the two vertices are connected (by a vertical
// segment) - if so, they "see" empty features.
bool vert_connected = false;
if (! vh->is_isolated())
{
Halfedge_around_vertex_const_circulator circ, first;
first = circ = vh->incident_halfedges();
do
{
if (circ->source() == m_prev_vh)
vert_connected = true;
++circ;
} while (! vert_connected && circ != first);
}
if (! vert_connected)
{
obj_below = CGAL::make_object(m_prev_vh);
m_prev_obj_above = CGAL::make_object(vh);
}
else
{
obj_below = CGAL::Object();
m_prev_obj_above = CGAL::Object();
}
}
else
{
// There is no concrete subcurve below the current event point, so we
// use the helper class to obtain the object below.
obj_below = m_helper.bottom_object();
}
}
else
{
// Decrement the iterator once more in order to reach the subcurve below
// the current event.
--below;
// If the previous event has the same x-coordinate as the current one,
// we check whether it lies below or above the subcurve below. We do this
// to distinguish between the following scenarios:
//
//
// * *
//
// -------- x
//
// x ---------
//
if (prev_same_x &&
(m_traits->compare_y_at_x_2_object()
(m_prev_vh->point(),
(*below)->last_curve().base()) != SMALLER))
{
// The previous vertex is vertically below the current vertex,
// and above the subcurve that lies below vh. We therefore update
// the respective entries in the output map accordingly.
// We first check if the two vertices are connected (by a vertical
// segment) - if so, they "see" empty features.
bool vert_connected = false;
if (! vh->is_isolated())
{
Halfedge_around_vertex_const_circulator circ, first;
first = circ = vh->incident_halfedges();
do
{
if (circ->source() == m_prev_vh)
vert_connected = true;
++circ;
} while (! vert_connected && circ != first);
}
if (! vert_connected)
{
obj_below = CGAL::make_object(m_prev_vh);
m_prev_obj_above = CGAL::make_object(vh);
}
else
{
obj_below = CGAL::Object();
m_prev_obj_above = CGAL::Object();
}
}
else
{
// Get the halfedge handle of the subcurve below the current event and
// associate it with its vertex.
obj_below =
CGAL::make_object((*below)->last_curve().halfedge_handle());
}
}
// We can now create the entry for the previous vertex, as we are not
// going to change the identity of the features below or above it.
if (m_prev_vh != Vertex_const_handle())
{
*(*m_out) = Vert_entry (m_prev_vh, Vert_pair (m_prev_obj_below,
m_prev_obj_above));
++(*m_out);
}
// We are done with the current vertex, but we cannot create the entry
// yet - so we store it for the next event.
m_prev_vh = vh;
m_prev_obj_below = obj_below;
m_prev_obj_above = obj_above;
// It is safe to deallocate the event.
return (true);
}
//-----------------------------------------------------------------------------
// A notification issued when the sweep process is over.
//
template <class Hlpr, class OutIt>
void Arr_vert_decomp_sl_visitor<Hlpr, OutIt>::after_sweep ()
{
// Create an entry for the last vertex (the xy-largest one).
if (m_prev_vh != invalid_vh)
{
*(*m_out) = Vert_entry (m_prev_vh, Vert_pair (m_prev_obj_below,
m_prev_obj_above));
++(*m_out);
}
return;
}
CGAL_END_NAMESPACE
#endif