Merge branch 'gsoc2013-Visibility_doc-hemmer-old' into gsoc2013-Visibility_doc-hemmer

Conflicts:
	Documentation/biblio/cgal_manual.bib
	Documentation/biblio/geom.bib
	Installation/changes.html
This commit is contained in:
Michael Hemmer 2015-07-02 17:36:17 +02:00
commit bdd46e6978
94 changed files with 23084 additions and 0 deletions

View File

@ -2501,6 +2501,66 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
,year = {2011}
}
@article{bjrb-clvpa-87,
author = "B. Joe and R.B. Simpson",
title = "Corrections to Lee's visibility polygon algorithm",
journal = "BIT",
volume = 27,
year = 1987,
pages = "458--473"
}
@article{ta-aeafvpprh-85
,author = {T. Asano}
,title = {An Efficient Algorithm for Finding the Visibility Polygon for a Polygonal Region with Holes}
,journal = {IEICE Transactions (1976-1990)}
,year = 1985
,volume = E68
,number = 9
,pages = {557--559}
}
@article{aaghi-vpsesp-85,
author = {Takao Asano and
Tetsuo Asano and
Leonidas J. Guibas and
John Hershberger and
Hiroshi Imai},
title = {Visibility-Polygon Search and Euclidean Shortest Paths},
booktitle = {FOCS},
year = {1985},
pages = {155-164},
ee = {http://doi.ieeecomputersociety.org/10.1109/SFCS.1985.65},
crossref = {DBLP:conf/focs/FOCS26},
bibsource = {DBLP, http://dblp.uni-trier.de}
}
@article{dtl-voasp-83,
author = "D. T. Lee",
title = "Visibility of a simple polygon",
journal = "Computer Vision, Graphics, and Image Processing",
volume = 22,
year = 1983,
pages = "207--221"
}
@article{ecvp-bhhhk-14,
author = {Francisc Bungiu and
Michael Hemmer and
John Hershberger and
Kan Huang and
Alexander Kr{\"{o}}ller},
title = {Efficient Computation of Visibility Polygons},
journal = {CoRR},
year = {2014},
volume = {abs/1403.3905},
url = {http://arxiv.org/abs/1403.3905},
timestamp = {Wed, 17 Sep 2014 16:30:16 +0200},
biburl = {http://dblp.uni-trier.de/rec/bib/journals/corr/BungiuHHHK14},
bibsource = {dblp computer science bibliography, http://dblp.org}
}
% ----------------------------------------------------------------------------
% END OF BIBFILE
% ----------------------------------------------------------------------------

View File

@ -151782,6 +151782,7 @@ amplification and suppression of local contrast. Contains C code."
, year = 1999
}
@article{hh-esplp-08
, author = "I. Haran and D. Halperin"
, title = "An experimental study of point location in planar arrangements in CGAL"

View File

@ -108,6 +108,7 @@ IMAGE_PATH = ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/fig \
${CMAKE_SOURCE_DIR}/Spatial_sorting/doc/Spatial_sorting/fig \
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/fig \
${CMAKE_SOURCE_DIR}/Straight_skeleton_2/doc/Straight_skeleton_2/fig \
${CMAKE_SOURCE_DIR}/Visibility_2/doc/Visibility_2/fig \
${CMAKE_SOURCE_DIR}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/fig \

View File

@ -74,6 +74,7 @@ Spatial_searching
Spatial_sorting
Segment_Delaunay_graph_2
Straight_skeleton_2
Visibility_2
Voronoi_diagram_2
Surface_mesh_simplification
Subdivision_method_3

View File

@ -68,6 +68,7 @@ h1 {
\package_listing{Snap_rounding_2}
\package_listing{Envelope_2}
\package_listing{Envelope_3}
\package_listing{Visibility_2}
\section PartTriangulationsAndDelaunayTriangulations Triangulations and Delaunay Triangulations

View File

@ -245,6 +245,21 @@ and <code>src/</code> directories).
</a></p>
</div>
<h2 id="release4.7">Release 4.7 </h2>
<div>
<p>Release date: October 2015 </p>
<!-- Installation (and general changes) -->
<!-- New packages -->
<h3>2D Visibility (new package)</h3>
<ul>
<li>This package provides several variants to compute the visibility
area of a point within polygonal regions in two dimensions.
</li>
</ul>
<!-- end of the div for 4.6 -->
</div>
<h2 id="release4.6">Release 4.6 </h2>
<div>
<p>Release date: April 2015 </p>

View File

@ -0,0 +1,87 @@
/*!
\ingroup PkgVisibility_2Concepts
\cgalConcept
All visibility polgyon algorithms provided in \cgal are parameterized with a traits class 'Traits', which defines the extension of Arrangement_2 the output will have.
\cgalHasModel `CGAL::Arr_extension_default_traits_2<K>`
\sa `Visibility_2`
*/
class ArrExtensionTraits_2 {
public :
/// \name Types
/// @{
/*!
* The vertex handle type on which the functors will operate.
*/
typedef Hidden_type Vertex_handle;
/*!
* The halfedge handle type on which the functors will operate.
*/
typedef Hidden_type Halfedge_handle;
/*!
* The face handle type on which the functors will operate.
*/
typedef Hidden_type Face_handle;
/*!
* Add auxiliary information to vertex.
*/
typedef Hidden_type Extend_vertex;
/*!
* Add auxiliary information to halfedge.
*/
typedef Hidden_type Extend_halfedge;
/*!
* Add auxiliary information to face.
*/
typedef Hidden_type Extend_face;
/// \name Creation
/// @{
/*!
default creator
*/
ArrExtensionTraits_2 ();
/*!
copy creator
*/
ArrExtensionTraits_2 (const ArrExtensionTraits_2& Traits);
/// @}
/// \name Operations
/// The following member functions to create instances of the above predicate oject types.
/// @{
/*!
*
*/
Extend_vertex extend_vertex_object();
/*!
*
*/
Extend_halfedge extend_halfedge_object();
/*!
*
*/
Extend_face extend_face_object();
/// @}
}

View File

@ -0,0 +1,80 @@
namespace CGAL {
/*!
\ingroup PkgArrExtensionTraits
The class `Arr_extension_default_traits_2` serves as a traits class for all visibility polygon calculation function.
This class extends the vertex, halfedges and face. User also may define their own traits class to choose which to extend.
\cgalModels `ArrExtensionTraits_2`
\sa `CGAL::Arr_extended_dcel`
*/
template< typename A_ >
class Arr_extension_default_traits_2 {
public:
/// \name Types
/// @{
/*!
*
*/
typedef A_::Vertex_iterator Vertex_iterator;
/*!
*
*/
typedef A_::Halfedge_iterator Halfedge_iterator;
/*!
*
*/
typedef A_::Fayce_iterator Face_iterator;
/// @}
/// \name Functor classes
/// @{
/*!
*
*/
class Extend_vertex;
/*!
*
*/
class Extend_halfedge;
/*!
*
*/
class Extend_face;
/// @}
/// \name Operations
/// @{
/*!
*
*/
Extend_vertex extend_vertex_object();
/*!
*
*/
Extend_halfedge extend_halfedge_object();
/*!
*
*/
Extend_face extend_face_object();
/// @}
};
} /* end namespace CGAL */

View File

@ -0,0 +1,158 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
a polygon that may have holes.
\details The class template comprises the implementation of the algorithm of Takao Asano and Tetsuo Asano \cite aaghi-vpsesp-85. The algorithm, as the name of the class template suggests, requires preprocessing. The preprocessing takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space, which reduces the query time to \f$O(n)\f$.
The main preprocessing step is the dualization of all vertices of the input arrangment into an arrangment of lines.
Computing this arrangement takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space.
Using this arrangment it is possible to retrieve the angular order of all vertices around
a query point, which is one of the essential steps to achive linear query time. For more details we refer to \cite aaghi-vpsesp-85.
\tparam Arrangement_2 is the type of input polygonal environment and output visibility polygon.
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
\cgalModels `Visibility_2`
\sa `CGAL::Simple_polygon_visibility_2<Arrangement_2, RegularizationCategory>`
\sa `CGAL::Rotational_sweep_visibility_2<Arrangement_2, RegularizationCategory>`
\sa `CGAL::Triangular_expansion_visibility_2<Arrangement_2, RegularizationCategory>`
*/
template <typename Arrangement_2, typename RegularizationCategory = Tag_false>
class Preprocessed_rotational_sweep_visibility_2 {
public:
/// \name Types
/// @{
/*!
The type of the input arrangement.
*/
typedef Arrangement_2 Arrangement_2;
/*!
The type of the output arrangement.
*/
typedef Arrangement_2 Visibility_arrangement_2;
/*!
The 2D point type used for the queries.
*/
typedef Arrangement_2::Point_2 Point_2;
/*!
Face_const_handle type of the input arrangement.
*/
typedef Arrangement_2::Face_const_handle Face_const_handle;
/*!
Halfedge_const_handle type of the input arrangement.
*/
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
/// @}
/// \name Tags
/// @{
/*!
identifies whether the regularized visibility area is computed.
*/
typedef RegularizationCategory Regularization_category;
/*!
identifies that the class supports general polygons (i.e.\ with holes).
*/
typedef ::Tag_true Supports_general_polygon_category;
/*!
identifies that the class supports general simple polygons.
*/
typedef ::Tag_true Supports_simple_polygon_category;
/// @}
/// \name Constructors
/// @{
/*!
Default constructor creates an empty `Preprocessed_rotational_sweep_visibility_2` object that is not
attached to any arrangement yet.
*/
Preprocessed_rotational_sweep_visibility_2();
/*!
Constructs a `Preprocessed_rotational_sweep_visibility_2` object that is attached to `arr`.
*/
Preprocessed_rotational_sweep_visibility_2(const Arrangement_2& arr);
/// @}
/// \name functions
/// @{
/*!
Returns whether an arrangement is attached to the visibility object
*/
bool is_attached() const;
/*!
Attaches the given arrangement to the visibility object and applies preprocessing.
In case the object is already attached to another arrangement,
the visibility object gets detached before being attached to `arr`.
*/
void attach(const Arrangement_2& arr);
/*!
Detaches the arrangement from the visibility object it is currently attached to
*/
void detach();
/*!
Access to the attached arrangement
*/
const Arrangement_2& arr() const;
/*!
Computes the visibility region of `q` in the
face `f` of the arrangement that is attached to the visibility object.
The visibility region of `q` will be stored in `out_arr`.
\param q is the query point
\param f is the face of the arrangement in which the visibility region is computed
\param out_arr is the output arrangement
\pre `f` is a face of `arr()` and represents a valid polygon.
\pre `q` is in the interior of the given face `f`
\return a handle to the face in `out_arr` that represents the visibility region
*/
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Face_const_handle f, Visibility_arrangement_2& out_arr) const;
/*!
Computes the visibility region of `q` that is on `e`. If `q` is an interior point of `e`, the computed visibility region is restricted to the halfplane indicated by `e`. If `q` is an endpoint of `e`, the visibility region is restricted by `e` and its next.
The visibility region of `q` will be stored in `out_arr`.
\param q is the query point
\param e the halfedge on which `q` is located
\param out_arr is the output arrangement
\pre `e` is a halfedge of `arr()`
\pre `q` is on `e`
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
\return a handle to the face in `out_arr` that represents the visibility region
*/
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
/// @}
}; /* end Visibility_2 */
} /* namespace CGAL */

View File

@ -0,0 +1,77 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
\details The algorithm does not require preprocessing. It relies on the algorithm of T. Asano \cite ta-aeafvpprh-85 based on angular plane sweep, with a time complexity of \f$O (n \log n)\f$ in the number of vertices.
\tparam Arrangement_2_ is the type used to represent the input environment.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
\cgalModels `Visibility_2`
\sa `CGAL::Simple_polygon_visibility_2`
\sa `CGAL::Triangular_expansion_visibility_2`
*/
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
class Rotational_sweep_visibility_2 {
public:
/// \name Types
/// @{
/*!
The type of the input arrangement.
*/
typedef Arrangement_2 Arrangement_2;
/// @}
/// \name Tags
/// @{
/*!
\copydoc ::Visibility_2::Regularization_category
*/
typedef RegularizationCategory Regularization_category;
/*!
See \ref Visibility_2::Supports_general_polygon_category.
*/
typedef ::Tag_true Supports_general_polygon_category;
/*!
See \ref Visibility_2::Supports_simple_polygon_category.
*/
typedef ::Tag_true Supports_simple_polygon_category;
/// @}
/// \name Functions
/// @{
/*!
Attaches the given arrangement to the visibility object.
This operation takes \f$O(1)\f$ as the class does no pre-processing.
In case the object is already attached to another arrangement,
the visibility object gets detached before being attached to `arr`.
*/
void attach(const Arrangement_2& arr);
/// @}
}; /* end Visibility_2 */
}

View File

@ -0,0 +1,82 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
a simple polygon with no holes.
\details This class implements the algorithm of B.Joe and R.B.Simpson \cite bjrb-clvpa-87.
The algorithm is a modification and extension of the linear time algorithm of Lee \cite dtl-voasp-83.
It computes the visibility region from a viewpoint that is in the interior or on the boundary of the polygon.
While scanning the boundary the algorithm uses a stack to manipulate the vertices, and ultimately
yields the visibility region. For each scanned edge, at most 2 points are pushed onto the stack.
Overall, at most 2\f$ n \f$ points are pushed or popped. Thus, the time and space complexities of the
algorithm are \f$ O(n) \f$ even in case of degeneracies such as needles, where \f$ n \f$
is the number of the vertices of the polygon.
\tparam Arrangement_2_ is the type used to represent the input environment.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
\cgalModels `Visibility_2`
\sa `CGAL::Rotational_sweep_visibility_2`
\sa `CGAL::Triangular_expansion_visibility_2`
*/
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
class Simple_polygon_visibility_2 {
public:
/// \name Types
/// @{
/*!
The arrangement type is used for input.
*/
typedef Arrangement_2 Arrangement_2;
/// @}
/// \name Tags
/// @{
/*!
\copydoc ::Visibility_2::Regularization_category
*/
typedef RegularizationCategory Regularization_category;
/*!
See \ref Visibility_2::Supports_general_polygon_category.
*/
typedef ::Tag_false Supports_general_polygon_category;
/*!
See \ref Visibility_2::Supports_simple_polygon_category.
*/
typedef ::Tag_true Supports_simple_polygon_category;
/// @}
/// \name Functions
/// @{
/*!
Attaches the given arrangement to the visibility object.
This operation takes \f$O(1)\f$ as the class does no pre-processing.
In case the object is already attached to another arrangement,
the visibility object gets detached before being attached to `arr`.
*/
void attach(const Arrangement_2& arr);
/// @}
}; /* end Visibility_2 */
}

View File

@ -0,0 +1,80 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
\details The algorithm obtains a constrained triangulation from the input arrangement, then computes visibility by
expanding the triangle that contains the query point.
Preprocessing takes \f$ O(n)\f$ time and \f$ O(n) \f$ space, where \f$ n \f$ is the number of vertices of input polygon.
The query time is \f$ O(nh)\f$, where \f$ h \f$ is the number of holes+1 of input polygon. Thus, for simple polygons (or a polygon with a constant number of holes) the algorithm complexity is linear, but it is \f$ O(n^2)\f$ in the worst case, as the number of holes can be linear in \f$ n \f$.
\tparam Arrangement_2_ is the type used to represent the input environment.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
\cgalModels `Visibility_2`
\sa `CGAL::Simple_polygon_visibility_2`
\sa `CGAL::Rotational_sweep_visibility_2`
*/
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
class Triangular_expansion_visibility_2 {
public:
/// \name Types
/// @{
/*!
The type of the input arrangement.
*/
typedef Arrangement_2_ Arrangement_2;
/// @}
/// \name Tags
/// @{
/*!
\copydoc ::Visibility_2::Regularization_category
*/
typedef RegularizationCategory Regularization_category;
/*!
See \ref Visibility_2::Supports_general_polygon_category.
*/
typedef ::Tag_true Supports_general_polygon_category;
/*!
See \ref Visibility_2::Supports_simple_polygon_category.
*/
typedef ::Tag_true Supports_simple_polygon_category;
/// @}
/// \name Functions
/// @{
/*!
Attaches the given arrangement to the visibility object and computes the restricted triangulation.
This takes \f$ O(n) \f$ time, where \f$ n \f$ is the number of vertices.
From this moment on the class observes changes in the arrangement. If the arrangement changes
a new restricted triangulation is computed. Re-attaching forces re-computation.
In case the object is already attached to another arrangement,
the visibility object gets detached before being attached to `arr`.
*/
void attach(const Arrangement_2& arr);
/// @}
}; /* end Visibility_2 */
} /* namespace CGAL */

View File

@ -0,0 +1,158 @@
/*!
\ingroup PkgVisibility_2Concepts
\cgalConcept
A model of the `Visibility_2` concept can be attached to an `Arrangement_2` instance to
answer visibility queries within the faces of this arrangement.
\cgalHasModel `CGAL::Simple_polygon_visibility_2`
\cgalHasModel `CGAL::Rotational_sweep_visibility_2`
\cgalHasModel `CGAL::Triangular_expansion_visibility_2`
*/
class Visibility_2 {
public:
/// \name Types
/// @{
/*!
The arrangement type of the input.
*/
typedef unspecified_type Arrangement_2;
/*!
The 2D point type used for the queries.
*/
typedef Arrangement_2::Point_2 Point_2;
/*!
* The face handle type of the input arrangement.
*/
typedef Arrangement_2::Face_const_handle Face_const_handle;
/*!
* The halfedge handle type of the input arrangement.
*/
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
/// @}
/// \name Tags
/// @{
/*!
identifies whether the regularized visibility area is computed (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
*/
typedef unspecified_type Regularization_category;
/*!
identifies whether general polygons (with holes) are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
A general polygon is represented by a face \f$ f \f$ with no
isolated vertex and any edge of \f$ f \f$ separates \f$ f \f$ from another face.
Note that this allows \f$ f \f$ to touch a vertex from several sides.
*/
typedef unspecified_type Supports_general_polygon_category;
/*!
identifies whether simple polygons are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
A simple polygon is represented by a face \f$ f \f$ with no holes,
no isolated vertex and any edge of \f$ f \f$ separates \f$ f \f$ from another face.
Note that this allows \f$ f \f$ to touch a vertex from several sides.
*/
typedef unspecified_type Supports_simple_polygon_category;
/// @}
/// \name Constructors
/// @{
/*!
Default constructor creates an empty `Visibility_2` object that is not
attached to any arrangement yet.
*/
Visibility_2();
/*!
Constructs a `Visibility_2` object that is attached to `arr`.
*/
Visibility_2(const Arrangement_2& arr);
/// @}
/// \name Functions
/// @{
/*!
Returns whether an arrangement is attached to the visibility object
*/
bool is_attached() const;
/*!
Attaches the given arrangement `arr` to the visibility object.
In case the object is already attached to another arrangement,
the visibility object gets detached before being attached to `arr`.
*/
void attach(const Arrangement_2& arr);
/*!
Detaches the arrangement from the visibility object it is currently attached to
*/
void detach();
/*!
Access to the attached arrangement
*/
const Arrangement_2& arrangement_2() const;
/*!
Computes the visibility region for the given query point `q` in the
face \f$ f \f$ of the arrangement that is attached to the visibility object.
The visibility region of `q` is stored in `out_arr`, that is,
all features but the unbounded face of `out_arr` represent the visibility region.
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
must be mutual convertible to Visibility_2::Traits_2.
\param q is the query point
\param f is the face of the arrangement in which the visibility region is computed
\param out_arr is the output arrangement
\pre `f` is a face of `this->arrangement_2()`
\pre `q` is in the interior of the given face `f`
\return the face handle to the face in `out_arr` that represents interior of the visibility region
*/
template <typename VisibilityArrangement_2>
typename Visibility_arrangement_2::Face_handle
compute_visibility(const Point_2& q, const Face_const_handle f, VisibilityArrangement_2& out_arr) const;
/*!
Computes the visibility region in `e->face()` for the given query
point `q` which must be located on `e`.
If `q` is an interior point of `e`, the computed visibility
region is restricted to the side indicated by the halfedge `e`.
If `q` is an endpoint of `e`, the visibility region is restricted by `e` and `e->next()`.
The visibility region of `q` is stored in `out_arr`, that is,
all features but the unbounded face of `out_arr` represent the visibility region.
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
must be mutual convertible to Visibility_2::Traits_2.
\param q is the query point
\param e the halfedge on which `q` is located
\param out_arr is the output arrangement
\pre `e` is a halfedge of `this->arrangement_2()`
\pre `q` is on `e`
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
\return a handle to the face in `out_arr` that represents the interior of the visibility region
*/
template <typename VisibilityArrangement_2>
typename Visibility_arrangement_2::Face_handle
compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
/// @}
}; /* end Visibility_2 */

View File

@ -0,0 +1,9 @@
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
PROJECT_NAME = "CGAL ${CGAL_CREATED_VERSION_NUM} - 2D Visibility"
INPUT = ${CMAKE_SOURCE_DIR}/Visibility_2/doc/Visibility_2/

View File

@ -0,0 +1,32 @@
/// \defgroup PkgVisibility_2 Visibility_2 Reference
/// \defgroup PkgVisibility_2Concepts Concepts
/// \ingroup PkgVisibility_2
/*!
\addtogroup PkgVisibility_2
\cgalPkgDescriptionBegin{2D Visibility Computation,PkgVisibility_2Summary}
\cgalPkgPicture{visibility-teaser-thumbnail.png}
\cgalPkgSummaryBegin
\cgalPkgAuthors{Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu}
\cgalPkgDesc{This package provides several variants to compute
the visibility area of a point within polygonal regions in two dimensions.}
\cgalPkgManuals{Chapter_2D_Visibility_Computation,PkgVisibility_2}
\cgalPkgSummaryEnd
\cgalPkgShortInfoBegin
\cgalPkgSince{99.99}
\cgalPkgBib{hhb-visibility-2}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd
\cgalClassifedRefPages
## Concepts ##
- `Visibility_2`
## Classes ##
- `CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_tag>`
- `CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag>`
- `CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag>`
*/

View File

@ -0,0 +1,8 @@
Manual
Kernel_23
STL_Extension
Algebraic_foundations
Circulator
Stream_support
Arrangement_on_surface_2
Boolean_set_operations_2

View File

@ -0,0 +1,4 @@
/*!
\example Visibility_2/simple_polygon_visibility_2.cpp
\example Visibility_2/general_polygon_example.cpp
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,162 @@
namespace CGAL {
/*!
\mainpage User Manual
\anchor Chapter_2D_Visibility_Computation
\cgalAutoToc
\authors Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu
<!-- \cgalFigureBegin{example_figure,visibility-teaser.png}\cgalFigureEnd -->
\section visibility_2_introduction Introduction
This package provides functionality to compute the visibility region within polygons in two dimensions.
The package is based on the package \ref PkgArrangement2Summary and uses CGAL::Arrangement_2
as the fundamental class to specify the input as well as the output.
Hence, a polygon \f$ P \f$ is represented by a bounded arrangement face \f$ f \f$
that does not have any isolated vertices and any edge that is adjacent to \f$ f \f$ separates \f$ f \f$ from another face.
Note that \f$ f \f$ may contain holes.
Similarly, a simple polygon is represented by a face without holes.
Given two points \f$ p \f$ and \f$ q \f$ in \f$ P \f$, they are said to be
visible to each other iff the segment \f$ pq \subset P \f$, where \f$ P \f$ is
considered to be closed, that is, \f$\partial P \subset P\f$.
For a query point \f$ q \in P \f$, the set of points that are visible from
\f$ q \f$ is defined as the visibility region of \f$ q \f$, denoted by \f$ V_q \f$
\subsection visibility_2_degeneracies Degeneracies and Regularization
\cgalFigureBegin{definition-fig, example1.png}
Non-regularized visibility and regularized visibility.
\cgalFigureEnd
As illustrated in \cgalFigureRef{definition-fig} (1) the visibility
region \f$ V_q \f$ of a query point \f$ q \f$ may not be a polygon.
In the figure, all labeled points are collinear, which implies that the
point \f$ c \f$ is visible to \f$ q \f$, that is,
the segment \f$ bc \f$ is part of \f$ V_q \f$.
We call such low dimensional features that are caused by degeneracies `needles`.
However, for many applications these needles are actually irrelevant.
Moreover, for some algorithms it is even more efficient to ignore needles
in the first place.
Therefore, this package offers also
functionality to compute the regularized visibility area
\f$ \overline{V_q} = closure(interior(V_q)) = (V_q\setminus\partial V_q) \cup \partial (V_q\setminus\partial V_q)\f$,
as shown in \cgalFigureRef{definition-fig} (2).
For more information about regularization, refer to Chapter \ref PkgBooleanSetOperations2Summary.
\section visibility_2_classes Classes and Algorithms
Answering visibility queries is, in many ways, similar to answering point-location queries.
Thus, we use the same design used to implement \ref PkgArrangement2Summary point location.
Each of the various visibility class templates employs a different
algorithm or \em strategy for answering
queries\cgalFootnote{The term \em strategy is borrowed from the
design-pattern taxonomy~\cite ghjv-dpero-95.
A \em strategy provides the means to define a family of algorithms,
each implemented by a separate class. All classes that implement the various
algorithms are made interchangeable, letting the algorithm in use vary according to the user choice.}.
Similar to the point-location case, some of the strategies require preprocessing. Thus, before a visibility object is used
to answer visibility queries, it must be attached to an arrangement object.
Afterwards, the visibility object observes changes to the attached arrangement.
Hence, it is possible to modify the arrangement after attaching the visibility object.
However, this feature should be used with caution as each change to the arrangement also
requires an update of the auxiliary data structures in the attached object.
An actual query is performed by giving the view point \f$ p \f$ and its containing face \f$ f \f$
(which must represent a valid polygon) to a visibility object.
For more details see the documentation of the overloaded member function `Visibility_2::compute_visibility()`.
The following models of the `Visibility_2` concept are provided:
<CENTER>
Class | Function | Preprocessing | Query |Algorithm
-------------------------------|-----------------------------------------------------|-------------------------------|-----------------------------------|-------------------------------
`Simple_polygon_visibility_2` | simple polygons | No |\f$ O(n) \f$ time and \f$ O(n) \f$ space | B. Joe and R. B. Simpson \cite bjrb-clvpa-87
`Rotational_sweep_visibility_2` | polygons with holes | No | \f$ O(n\log n) \f$ time and \f$ O(n) \f$ space | T. Asano \cite ta-aeafvpprh-85
`Triangular_expansion_visibility_2` | polygons with holes | \f$ O(n) \f$ time and \f$ O(n) \f$ space | \f$ O(nh) \f$ time and \f$ O(n) \f$ space. | Bungiu et al. \cite ecvp-bhhhk-14
</CENTER>
Where \f$ n \f$ denotes the number of vertices of \f$ f \f$ and \f$ h \f$ the number of holes+1.
\section benchmarks Running Time in Practice
\cgalFigureBegin{cathedral-fig, cathedral_2.png}
Example representing a cathedral.
\cgalFigureEnd
The left hand side of Figure \cgalFigureRef{cathedral-fig} depicts the outer boundary of a cathedral,
which is a simple polygon with 565 vertices.
The right hand side shows the cathedral also with its inner pillars, which is a polygon (with holes)
with 1153 vertices.
The following table shows the total running time consumption of the computation of
all visibility polygons for all vertices of the cathedral.
<CENTER>
Boundary Cathedral | total preprocessing time | total query time |
-------------------------------|-----------------------------------------------------|-------------------------------|
`Simple_polygon_visibility_2` | - | 0.38 |
`Rotational_sweep_visibility_2` | - | 1.01 |
`Triangular_expansion_visibility_2` | 0.01 | 0.06 |
</CENTER>
The second table shows the same for the complete cathedral.
The table does not report the time for `Simple_polygon_visibility_2`
as this algorithm can only handle simple polygons.
<CENTER>
Complete Cathedral | total preprocessing time | total query time |
-------------------------------|-----------------------------------------------------|-------------------------------|
`Rotational_sweep_visibility_2` | - | 1.91 |
`Triangular_expansion_visibility_2` | 0.01 | 0.04 |
</CENTER>
Thus, in general we recommend to use `Triangular_expansion_visibility_2` even if the polygon is simple.
The main advantage of the algorithm is its locality.
After the triangle that contains the query point is located in the triangulation,
the algorithm explores neighboring triangles, but only those that are actually seen.
In this sense the algorithm can be considered as output sensitive.
Note that the `Triangular_expansion_visibility_2` algorithm performs better on the full
cathedral since the additional pillars block the view early in many cases.
However, if the simple polygon is rather convex (i.e., nearly all boundary is seen) or
if only one (or very little) queries are required, using one of the algorithms that
does not require preprocessing is advantageous.
\section simple_polygon_visibility_example Example of Visibility in a Simple Polygon
The following example shows how to obtain the regularized and non-regularized visibility regions.
\cgalFigureBegin{simple_example, simple_example.png}
The visibility region of \f$ q \f$ in a simple polygon: (1) non-regularized visibility; and (2) regularized visibility.
\cgalFigureEnd
\cgalExample{Visibility_2/simple_polygon_visibility_2.cpp}
\section general_polygon_example Example of Visibility in a Polygon with Holes
The following example shows how to obtain the regularized visibility region using the model
`Triangular_expansion_visibility_2`, see \cgalFigureRef{general_polygon}.
The arrangement has six bounded faces and an unbounded face.
The query point \f$ q \f$ is on a vertex.
The red arrow denotes the halfedge \f$ \overrightarrow{pq} \f$,
which also identifies the face in which the visibility region is computed.
\cgalFigureBegin{general_polygon, general_polygon_example.png}
The visibility region of \f$ q \f$ in a polygon with two holes.
\cgalFigureEnd
\cgalExample{Visibility_2/general_polygon_example.cpp}
\section implementation_history Implementation History
This package was first developed during Google Summer of Code 2013:
Francisc Bungiu developed the `CGAL::Simple_polygon_visibility_2`,
Kan Huang developed the `CGAL::Rotational_sweep_visibility_2`,
and Michael Hemmer developed the `CGAL::Triangular_expansion_visibility_2`.
During Google Summer of Code 2014 Ning Xu fixed a bug in `CGAL::Simple_polygon_visibility_2` and improved the testsuite.
*/
}
// `Preprocessed_rotational_sweep_visibility_2` | polygons with holes | \f$ O(n^2) \f$ time and \f$ O(n^2) \f$ space | \f$ O(n) \f$ time and \f$ O(n) \f$ space | Takao Asano, Tetsuo Asano etc \cite aaghi-vpsesp-85

View File

@ -0,0 +1,67 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <iostream>
#include <vector>
// Define the used kernel and arrangement
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef Arrangement_2::Face_handle Face_handle;
// Define the used visibility class
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2> TEV;
int main() {
// Defining the input geometry
Point_2 p1(1,2), p2(12, 3), p3(19,-2), p4(12,6), p5(14,14), p6( 9,5);
Point_2 h1(8,3), h2(10, 3), h3( 8, 4), h4(10,6), h5(11, 6), h6(11,7);
std::vector<Segment_2> segments;
segments.push_back(Segment_2(p1,p2));
segments.push_back(Segment_2(p2,p3));
segments.push_back(Segment_2(p3,p4));
segments.push_back(Segment_2(p4,p5));
segments.push_back(Segment_2(p5,p6));
segments.push_back(Segment_2(p6,p1));
segments.push_back(Segment_2(h1,h2));
segments.push_back(Segment_2(h2,h3));
segments.push_back(Segment_2(h3,h1));
segments.push_back(Segment_2(h4,h5));
segments.push_back(Segment_2(h5,h6));
segments.push_back(Segment_2(h6,h4));
// insert geometry into the arrangement
Arrangement_2 env;
CGAL::insert_non_intersecting_curves(env,segments.begin(),segments.end());
//Find the halfedge whose target is the query point.
//(usually you may know that already by other means)
Point_2 query_point = p4;
Halfedge_const_handle he = env.halfedges_begin();
while (he->source()->point() != p3 || he->target()->point() != p4)
he++;
//visibility query
Arrangement_2 output_arr;
TEV tev(env);
Face_handle fh = tev.compute_visibility(query_point, he, output_arr);
//print out the visibility region.
std::cout << "Regularized visibility region of q has "
<< output_arr.number_of_edges()
<< " edges." << std::endl;
std::cout << "Boundary edges of the visibility region:" << std::endl;
Arrangement_2::Ccb_halfedge_circulator curr = fh->outer_ccb();
std::cout << "[" << curr->source()->point() << " -> " << curr->target()->point() << "]" << std::endl;
while (++curr != fh->outer_ccb())
std::cout << "[" << curr->source()->point() << " -> " << curr->target()->point() << "]"<< std::endl;
return 0;
}

View File

@ -0,0 +1,74 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arr_naive_point_location.h>
#include <istream>
#include <vector>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
typedef Arrangement_2::Edge_const_iterator Edge_const_iterator;
typedef Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator;
int main() {
//create environment
Point_2 p1(0,4), p2(0,0), p3(3,2), p4(4,0), p5(4,4), p6(1,2);
std::vector<Segment_2> segments;
segments.push_back(Segment_2(p1, p2));
segments.push_back(Segment_2(p2, p3));
segments.push_back(Segment_2(p3, p4));
segments.push_back(Segment_2(p4, p5));
segments.push_back(Segment_2(p5, p6));
segments.push_back(Segment_2(p6, p1));
Arrangement_2 env;
CGAL::insert_non_intersecting_curves(env,segments.begin(),segments.end());
// find the face of the query point
// (usually you may know that by other means)
Point_2 q(0.5, 2);
Arrangement_2::Face_const_handle * face;
CGAL::Arr_naive_point_location<Arrangement_2> pl(env);
CGAL::Arr_point_location_result<Arrangement_2>::Type obj = pl.locate(q);
// The query point locates in the interior of a face
face = boost::get<Arrangement_2::Face_const_handle> (&obj);
// compute non regularized visibility area
// Define visibiliy object type that computes non-regularized visibility area
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false> NSPV;
Arrangement_2 non_regular_output;
NSPV non_regular_visibility(env);
non_regular_visibility.compute_visibility(q, *face, non_regular_output);
std::cout << "Non-regularized visibility region of q has "
<< non_regular_output.number_of_edges()
<< " edges:" << std::endl;
for (Edge_const_iterator eit = non_regular_output.edges_begin(); eit != non_regular_output.edges_end(); ++eit)
std::cout << "[" << eit->source()->point() << " -> " << eit->target()->point() << "]" << std::endl;
// compute non regularized visibility area
// Define visibiliy object type that computes regularized visibility area
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_true> RSPV;
Arrangement_2 regular_output;
RSPV regular_visibility(env);
regular_visibility.compute_visibility(q, *face, regular_output);
std::cout << "Regularized visibility region of q has "
<< regular_output.number_of_edges()
<< " edges:" << std::endl;
for (Edge_const_iterator eit = regular_output.edges_begin(); eit != regular_output.edges_end(); ++eit)
std::cout << "[" << eit->source()->point() << " -> " << eit->target()->point() << "]" << std::endl;
return 0;
}

View File

@ -0,0 +1,934 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Kan Huang <huangkandiy@gmail.com>
//
#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
#include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/bounding_box.h>
#include <boost/unordered_map.hpp>
#include <iterator>
namespace CGAL {
template<class Arrangement_2_ , class RegularizationCategory = CGAL::Tag_true >
class Rotational_sweep_visibility_2 {
public:
typedef Arrangement_2_ Arrangement_2;
typedef typename Arrangement_2::Traits_2 Traits_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::
Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
typedef typename Geometry_traits_2::Kernel K;
typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::Ray_2 Ray_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Geometry_traits_2::Line_2 Line_2;
typedef typename Geometry_traits_2::Vector_2 Vector_2;
typedef typename Geometry_traits_2::Direction_2 Direction_2;
typedef typename Geometry_traits_2::FT Number_type;
typedef typename Geometry_traits_2::Object_2 Object_2;
typedef RegularizationCategory Regularization_category;
typedef CGAL::Tag_true Supports_general_polygon_category;
typedef CGAL::Tag_true Supports_simple_polygon_category;
private:
typedef std::vector<Point_2> Points;
typedef Vertex_const_handle VH;
typedef std::vector<VH> VHs;
typedef Halfedge_const_handle EH;
typedef std::vector<EH> EHs;
class Less_edge: public std::binary_function<EH, EH, bool> {
const Geometry_traits_2* geom_traits;
public:
Less_edge() {}
Less_edge(const Geometry_traits_2* traits):geom_traits(traits) {}
bool operator() (const EH e1, const EH e2) const {
if (e1 == e2)
return false;
else {
return &(*e1)<&(*e2);
}
// if (e1->source() == e2->source())
// return Visibility_2::compare_xy_2(geom_traits,
// e1->target()->point(), e2->target()->point()) == SMALLER;
// else
// return Visibility_2::compare_xy_2(geom_traits,
// e1->source()->point(), e2->source()->point()) == SMALLER;
}
};
class Less_vertex: public std::binary_function<VH, VH, bool> {
const Geometry_traits_2* geom_traits;
public:
Less_vertex() {}
Less_vertex(const Geometry_traits_2* traits):geom_traits(traits) {}
bool operator() (const VH v1, const VH v2) const {
if (v1 == v2)
return false;
else
// I know this is dirty but it speeds up by 25%. Michael
return &(*v1)<&(*v2);
// return Visibility_2::
// compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
}
};
class Closer_edge: public std::binary_function<EH, EH, bool> {
const Geometry_traits_2* geom_traits;
Point_2 q;
public:
Closer_edge() {}
Closer_edge(const Geometry_traits_2* traits, const Point_2& q) :
geom_traits(traits), q(q) {}
int vtype(const Point_2& c, const Point_2& p) const {
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
case COLLINEAR:
if (Visibility_2::less_distance_to_point_2(geom_traits, q, c, p))
return 0;
else
return 3;
case RIGHT_TURN:
return 1;
case LEFT_TURN:
return 2;
}
return -1;
}
bool operator() (const EH& e1, const EH& e2) const {
if (e1 == e2)
return false;
const Point_2& s1=e1->source()->point(),
t1=e1->target()->point(),
s2=e2->source()->point(),
t2=e2->target()->point();
if (e1->source() == e2->source()) {
int vt1 = vtype(s1, t1),
vt2 = vtype(s1, t2);
if (vt1 != vt2)
return vt1 > vt2;
else
return (Visibility_2::orientation_2(geom_traits, s1, t2, t1)==
Visibility_2::orientation_2(geom_traits, s1, t2, q));
}
if (e1->target() == e2->source()) {
// const Point_2& p1 = s1,
// p2 = t2,
// c = s2;
int vt1 = vtype(t1, s1),
vt2 = vtype(t1, t2);
if (vt1 != vt2)
return vt1 > vt2;
else
return (Visibility_2::orientation_2(geom_traits, s2, t2, s1)==
Visibility_2::orientation_2(geom_traits, s2, t2, q));
}
if (e1->source() == e2->target()) {
// const Point_2& p1 = t1,
// p2 = s2,
// c = s1;
int vt1 = vtype(s1, t1),
vt2 = vtype(s1, s2);
if (vt1 != vt2)
return vt1 > vt2;
else return (Visibility_2::orientation_2(geom_traits, s1, s2, t1)==
Visibility_2::orientation_2(geom_traits, s1, s2, q));
}
if (e1->target() == e2->target()) {
// const Point_2& p1 = s1,
// p2 = s2,
// c = t1;
int vt1 = vtype(t1, s1),
vt2 = vtype(t1, s2);
if (vt1 != vt2)
return vt1 > vt2;
else return (Visibility_2::orientation_2(geom_traits, t1, s2, s1)==
Visibility_2::orientation_2(geom_traits, t1, s2, q));
}
Orientation e1q = Visibility_2::orientation_2(geom_traits, s1, t1, q);
switch (e1q)
{
case COLLINEAR:
if (Visibility_2::collinear(geom_traits, q, s2, t2)) {
//q is collinear with e1 and e2.
return (Visibility_2::less_distance_to_point_2(geom_traits, q, s1, s2)
|| Visibility_2::less_distance_to_point_2(geom_traits, q, t1, t2));
}
else {
//q is collinear with e1 not with e2.
if (Visibility_2::collinear(geom_traits, s2, t2, s1))
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, t1));
else
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, s1));
}
case RIGHT_TURN:
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
case COLLINEAR:
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
case RIGHT_TURN:
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
else
return false;
case LEFT_TURN:
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
else
return true;
}
case LEFT_TURN:
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
case COLLINEAR:
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
case LEFT_TURN:
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
else
return false;
case RIGHT_TURN:
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
else
return true;
}
}
return false;
}
};
const Arrangement_2 *p_arr;
const Geometry_traits_2 *geom_traits;
mutable Point_2 q; //query point
mutable Points polygon; //visibility polygon
mutable std::map<VH, EHs, Less_vertex> incident_edges;
mutable std::map<EH, int, Less_edge> edx; //index of active edges in
//the heap
mutable std::set<EH, Closer_edge> active_edges; //a set of edges that
//intersect the current
//vision ray.
mutable VHs vs; //angular sorted vertices
mutable EHs bad_edges; //edges that pass the query point
mutable VH cone_end1; //an end of visibility cone
mutable VH cone_end2; //another end of visibility cone
mutable typename Points::size_type cone_end1_idx;
//index of cone_end1->point() in
//visibility polygon
mutable typename Points::size_type cone_end2_idx;
//index of cone_end2->point() in
//visibility polygon
mutable bool is_vertex_query;
mutable bool is_edge_query;
mutable bool is_face_query;
mutable bool is_big_cone; //whether the angle of
//visibility_cone is greater than pi.
public:
Rotational_sweep_visibility_2(): p_arr(NULL), geom_traits(NULL) {}
Rotational_sweep_visibility_2(const Arrangement_2& arr): p_arr(&arr) {
geom_traits = p_arr->geometry_traits();
}
const std::string name() const { return std::string("R_visibility_2"); }
template <typename VARR>
typename VARR::Face_handle
compute_visibility(
const Point_2& q, const Halfedge_const_handle e, VARR& arr_out) const
{
arr_out.clear();
bad_edges.clear();
this->q = q;
if (Visibility_2::compare_xy_2(geom_traits, q, e->target()->point())==EQUAL)
{
is_vertex_query = true;
is_edge_query = false;
is_face_query = false;
cone_end1 = e->source();
cone_end2 = e->next()->target();
is_big_cone = CGAL::right_turn(cone_end1->point(), q, cone_end2->point());
typename Arrangement_2::
Halfedge_around_vertex_const_circulator first, curr;
first = curr = e->target()->incident_halfedges();
do {
if (curr->face() == e->face())
bad_edges.push_back(curr);
else if (curr->twin()->face() == e->face())
bad_edges.push_back(curr->twin());
} while (++curr != first);
}
else {
is_vertex_query = false;
is_edge_query = true;
is_face_query = false;
cone_end1 = e->source();
cone_end2 = e->target();
bad_edges.push_back(e);
is_big_cone = false;
}
visibility_region_impl(e->face(), q);
//decide which inside of the visibility butterfly is needed.
typename Points::size_type small_idx, big_idx;
if ( cone_end1_idx < cone_end2_idx ) {
small_idx = cone_end1_idx;
big_idx = cone_end2_idx;
}
else {
small_idx = cone_end2_idx;
big_idx = cone_end1_idx;
}
typename Points::size_type next_idx = small_idx + 1;
bool is_between;
//indicate whether the shape between small_idx and big_idx is the visibility
//region required.
if (CGAL::right_turn(cone_end1->point(), q, cone_end2->point())) {
is_between = false;
while (next_idx != big_idx) {
if (CGAL::left_turn(cone_end1->point(), q, polygon[next_idx]) ||
CGAL::left_turn(q, cone_end2->point(), polygon[next_idx]))
{
is_between = true;
break;
}
next_idx++;
}
}
else {
is_between = true;
while (next_idx != big_idx) {
if (CGAL::right_turn(cone_end1->point(), q, polygon[next_idx]) ||
CGAL::right_turn(q, cone_end2->point(), polygon[next_idx]))
{
is_between = false;
break;
}
next_idx++;
}
}
typename Points::iterator first = polygon.begin();
std::advance(first, small_idx);
typename Points::iterator last = polygon.begin();
std::advance(last, big_idx);
if (is_between) {
Points polygon_out(first, last+1);
if (is_vertex_query)
polygon_out.push_back(q);
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
(geom_traits, q, polygon_out, arr_out);
}
else {
Points polygon_out(polygon.begin(), first+1);
if (is_vertex_query) polygon_out.push_back(q);
for (typename Points::size_type i = big_idx; i != polygon.size(); i++) {
polygon_out.push_back(polygon[i]);
}
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
(geom_traits, q, polygon_out, arr_out);
}
Visibility_2::conditional_regularize(arr_out, Regularization_category());
if (arr_out.faces_begin()->is_unbounded())
return ++arr_out.faces_begin();
else
return arr_out.faces_begin();
}
template <typename VARR>
typename VARR::Face_handle
compute_visibility(
const Point_2& q, const Face_const_handle f, VARR& arr_out) const
{
arr_out.clear();
this->q = q;
is_vertex_query = false;
is_edge_query = false;
is_face_query = true;
visibility_region_impl(f, q);
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
(geom_traits, q, polygon, arr_out);
Visibility_2::conditional_regularize(arr_out, Regularization_category());
if (arr_out.faces_begin()->is_unbounded())
return ++arr_out.faces_begin();
else
return arr_out.faces_begin();
}
bool is_attached() const {
return (p_arr != NULL);
}
void attach(const Arrangement_2& arr) {
p_arr = &arr;
geom_traits = p_arr->geometry_traits();
}
void detach() {
p_arr = NULL;
geom_traits = NULL;
}
const Arrangement_2& arrangement_2() const {
return *p_arr;
}
private:
//get the neighbor of v along edge e
VH get_neighbor(const EH e, const VH v) const {
if (e->source() == v)
return e->target();
else
return e->source();
}
//check whether ray(q->dp) intersects segment(p1, p2)
bool do_intersect_ray(const Point_2& q,
const Point_2& dp,
const Point_2& p1,
const Point_2& p2) const
{
return (CGAL::orientation(q, dp, p1) != CGAL::orientation(q, dp, p2) &&
CGAL::orientation(q, p1, dp) == CGAL::orientation(q, p1, p2));
}
//arrange vertices that on a same vision ray in a 'funnel' order
void funnel(typename VHs::size_type i, typename VHs::size_type j) const {
VHs right, left;
//whether the edges incident to a vertex block the left side and right side
//of current vision ray.
bool block_left(false), block_right(false);
VH former = vs[i], nb;
for (typename VHs::size_type l=i; l<j; l++) {
bool left_v(false), right_v(false), has_predecessor(false);
EHs& edges = incident_edges[vs[l]];
for (typename EHs::size_type k=0; k<edges.size(); k++) {
nb = get_neighbor(edges[k], vs[l]);
if ( nb == former ) {
has_predecessor = true;
break;
}
if (CGAL::left_turn(q, vs[l]->point(), nb->point()))
left_v = true;
else
right_v = CGAL::right_turn(q, vs[l]->point(), nb->point());
}
if (has_predecessor) {
//if the current vertex connects to the vertex before by an edge,
//the vertex before can help it to block.
block_left = block_left || left_v;
block_right = block_right || right_v;
}
else {
block_left = left_v;
block_right = right_v;
}
if (block_left && block_right) {
//when both sides are blocked,
//there is no need to change the vertex after.
right.push_back(vs[l]);
break;
}
else {
if (block_left)
left.push_back(vs[l]);
else
right.push_back(vs[l]);
}
former = vs[l];
}
for (typename VHs::size_type l=0; l!=right.size(); l++)
vs[i+l] = right[l];
for (typename VHs::size_type l=0; l!=left.size(); l++)
vs[i+l+right.size()] = left[left.size()-1-l];
}
void visibility_region_impl(const Face_const_handle f, const Point_2& q) const
{
vs.clear();
polygon.clear();
active_edges = std::set<EH, Closer_edge>(Closer_edge(geom_traits, q));
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
EHs relevant_edges; //edges that can affect the visibility of query point.
Arrangement_2 bbox;
if (is_face_query)
input_face(f);
else
input_face(f, relevant_edges, bbox);
//the following code is the initiation of vision ray.
//the direction of the initial ray is between the direction from q to last
//vertex in vs and positive x-axis. By choosing this direction, we make sure
//that all plane is swept and there is not needle at the beginning of
//sweeping.
Vector_2 dir;
if (Direction_2(-1, 0) < Direction_2(Vector_2(q, vs.back()->point())))
dir = Vector_2(1, 0) + Vector_2(q, vs.back()->point());
else
dir = Vector_2(0, -1);
Point_2 dp = q + dir;
//initiation of active_edges. for face queries,
//all edges on the boundary can affect visibility.
//for non-face queries, only relevant_edges has to be considered.
if (is_face_query) {
Ccb_halfedge_const_circulator curr = f->outer_ccb();
Ccb_halfedge_const_circulator circ = curr;
do {
if (do_intersect_ray(
q, dp, curr->target()->point(), curr->source()->point()))
active_edges.insert(curr);
} while (++curr != circ);
typename Arrangement_2::Hole_const_iterator hi;
for (hi = f->holes_begin(); hi != f->holes_end(); ++hi) {
Ccb_halfedge_const_circulator curr = circ = *hi;
do {
if (do_intersect_ray(
q, dp, curr->target()->point(), curr->source()->point()))
active_edges.insert(curr);
} while (++curr != circ);
}
}
else {
for (typename EHs::size_type i=0; i!=relevant_edges.size(); i++)
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(),
relevant_edges[i]->target()->point()))
active_edges.insert(relevant_edges[i]);
}
//angular sweep begins
// std::cout<<active_edges.size()<<std::endl;
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
VH vh = vs[i];
EH closest_e = *active_edges.begin();
EHs& edges = incident_edges[vh];
EHs insert_ehs, remove_ehs;
for (typename EHs::size_type j=0; j!=edges.size(); j++) {
EH& e = edges[j];
if (active_edges.find(e) == active_edges.end())
insert_ehs.push_back(e);
else
remove_ehs.push_back(e);
}
typename EHs::size_type insert_cnt = insert_ehs.size();
typename EHs::size_type remove_cnt = remove_ehs.size();
if (insert_cnt == 1 && remove_cnt == 1) {
const EH& ctemp_eh = *active_edges.find(remove_ehs.front());
EH& temp_eh = const_cast<EH&>(ctemp_eh);
temp_eh = insert_ehs.front();
}
else {
for (typename EHs::size_type j=0; j!=remove_cnt; j++)
active_edges.erase(remove_ehs[j]);
for (typename EHs::size_type j=0; j!=insert_cnt; j++)
active_edges.insert(insert_ehs[j]);
}
if (closest_e != *active_edges.begin()) {
//when the closest edge changed
if (is_face_query) {
if (remove_cnt > 0 && insert_cnt > 0) {
//some edges are added and some are deleted,
//which means the vertex swept is part of visibility polygon.
update_visibility(vh->point());
}
if (remove_cnt == 0 && insert_cnt > 0) {
//only add some edges, means the view ray is blocked by new edges.
//therefore first add the intersection of view ray and
//former closet edge, then add the vertice swept.
update_visibility(ray_seg_intersection(q,
vh->point(),
closest_e->target()->point(),
closest_e->source()->point())
);
update_visibility(vh->point());
}
if (remove_cnt > 0 && insert_cnt == 0) {
//only delete some edges, means some block is moved and the view ray
//can reach the segments after the block.
update_visibility(vh->point());
update_visibility(
ray_seg_intersection(q,
vh->point(),
(*active_edges.begin())->target()->point(),
(*active_edges.begin())->source()->point()
)
);
}
}
else {
//extra work here for edge/vertex query is the index of cone_end1 and
//cone_end2 will be recorded.
if (remove_cnt > 0 && insert_cnt > 0) {
//some edges are added and some are deleted,
//which means the vertice swept is part of visibility polygon.
if (update_visibility(vh->point())) {
if (vh == cone_end1)
cone_end1_idx = polygon.size()-1;
else if (vh == cone_end2)
cone_end2_idx = polygon.size()-1;
}
}
if (remove_cnt == 0 && insert_cnt > 0) {
//only add some edges, means the view ray is blocked by new edges.
//therefore first add the intersection of view ray and former closet
//edge, then add the vertice swept.
update_visibility(ray_seg_intersection(q,
vh->point(),
closest_e->target()->point(),
closest_e->source()->point())
);
if (update_visibility(vh->point())) {
if (vh == cone_end1)
cone_end1_idx = polygon.size()-1;
else if (vh == cone_end2)
cone_end2_idx = polygon.size()-1;
}
}
if (remove_cnt > 0 && insert_cnt == 0) {
//only delete some edges, means some block is removed and the vision
//ray can reach the segments after the block.
if (update_visibility(vh->point())) {
if (vh == cone_end1)
cone_end1_idx = polygon.size()-1;
else if (vh == cone_end2)
cone_end2_idx = polygon.size()-1;
}
update_visibility(
ray_seg_intersection(q,
vh->point(),
(*active_edges.begin())->target()->point(),
(*active_edges.begin())->source()->point())
);
}
}
}
}
}
void print_edge(const EH e) const {
std::cout << e->source()->point() <<"->"<< e->target()->point() <<std::endl;
}
//compute the intersection of ray(q->dp) and segment(s, t)
//if they are collinear then return the endpoint which is closer to q.
Point_2 ray_seg_intersection(
const Point_2& q, const Point_2& dp, // the ray
const Point_2& s, const Point_2& t) // the segment
const
{
if (CGAL::collinear(q, dp, s)) {
if (CGAL::collinear(q, dp, t)) {
if (CGAL::compare_distance_to_point(q, s, t)==CGAL::SMALLER)
return s;
else
return t;
}
else
return s;
}
Ray_2 ray(q,dp);
Segment_2 seg(s,t);
CGAL::Object result = CGAL::intersection(ray, seg);
return *(CGAL::object_cast<Point_2>(&result));
}
//check if p has been discovered before, if not update the visibility polygon
bool update_visibility(const Point_2& p) const {
if (polygon.empty()) {
polygon.push_back(p);
return true;
}
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p)
!= EQUAL)
{
polygon.push_back(p);
return true;
}
return false;
}
//functor to decide which vertex is swept earlier by the rotational sweeping
//ray
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
const Point_2& q;
const Geometry_traits_2* geom_traits;
public:
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits) :
q(q), geom_traits(traits) {}
bool operator() (const VH v1, const VH v2) const {
const Point_2& p1 = v1->point();
const Point_2& p2 = v2->point();
int qua1 = quadrant(q, p1);
int qua2 = quadrant(q, p2);
if (qua1 < qua2)
return true;
if (qua1 > qua2)
return false;
if (collinear(q, p1, p2))
return (CGAL::compare_distance_to_point(q, p1, p2) == CGAL::SMALLER);
else
return CGAL::right_turn(p1, q, p2);
}
//return the quadrant of p with respect to o.
int quadrant(const Point_2& o, const Point_2& p) const {
typename Geometry_traits_2::Compare_x_2 compare_x =
geom_traits->compare_x_2_object();
typename Geometry_traits_2::Compare_y_2 compare_y =
geom_traits->compare_y_2_object();
Comparison_result dx = compare_x(p, o);
Comparison_result dy = compare_y(p, o);
if (dx==LARGER && dy!=SMALLER)
return 1;
if (dx!=LARGER && dy==LARGER)
return 2;
if (dx==SMALLER && dy!=LARGER)
return 3;
if (dx!=SMALLER && dy==SMALLER)
return 4;
return 0;
}
};
//when the query point is in face, every edge is good.
void input_neighbor_f( const Halfedge_const_handle e) const {
VH v = e->target();
if (!incident_edges.count(v))
vs.push_back(v);
incident_edges[v].push_back(e);
incident_edges[v].push_back(e->next());
}
//check if p is in the visibility cone
bool is_in_cone(const Point_2& p) const{
if (is_big_cone)
return (!CGAL::right_turn(cone_end1->point(), q, p)) ||
(!CGAL::left_turn(cone_end2->point(), q, p));
else
return (!CGAL::right_turn(cone_end1->point(), q, p)) &&
(!CGAL::left_turn(cone_end2->point(), q, p));
}
//for vertex and edge query: the visibility is limited in a cone.
void input_edge(const Halfedge_const_handle e,
EHs& good_edges) const {
for (typename EHs::size_type i = 0; i < bad_edges.size(); i++)
if (e == bad_edges[i])
return;
VH v1 = e->target();
VH v2 = e->source();
//an edge will affect visibility only if it has an endpoint in the
//visibility cone or it crosses the boundary of the cone.
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) ||
do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point()))
{
good_edges.push_back(e);
if (!incident_edges.count(v1))
vs.push_back(v1);
incident_edges[v1].push_back(e);
if (!incident_edges.count(v2))
vs.push_back(v2);
incident_edges[v2].push_back(e);
}
}
//for face query: traverse the face to get all edges
//and sort vertices in counter-clockwise order.
void input_face (Face_const_handle fh) const
{
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
Ccb_halfedge_const_circulator circ = curr;
do {
assert(curr->face() == fh);
input_neighbor_f(curr);
} while (++curr != circ);
typename Arrangement_2::Hole_const_iterator hi;
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
Ccb_halfedge_const_circulator curr = *hi, circ = *hi;
do {
assert(curr->face() == fh);
input_neighbor_f(curr);
} while (++curr != circ);
}
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
typename VHs::size_type j = i+1;
while (j != vs.size()) {
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
break;
j++;
}
if (j-i>1)
funnel(i, j);
i = j-1;
}
}
//for vertex or edge query: traverse the face to get all edges
//and sort vertices in counter-clockwise order.
void input_face (Face_const_handle fh,
EHs& good_edges,
Arrangement_2& bbox) const
{
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
Ccb_halfedge_const_circulator circ = curr;
do {
assert(curr->face() == fh);
input_edge(curr, good_edges);
} while (++curr != circ);
typename Arrangement_2::Hole_const_iterator hi;
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
Ccb_halfedge_const_circulator curr = circ = *hi;
do {
assert(curr->face() == fh);
input_edge(curr, good_edges);
} while (++curr != circ);
}
//create a box that cover all vertices such that during the sweeping,
//the vision ray will always intersect at least an edge.
//this box doesn't intersect any relevant_edge.
Points points;
for (typename VHs::size_type i=0; i<vs.size(); i++) {
points.push_back(vs[i]->point());
}
points.push_back(q);
//first get the bounding box of all relevant points.
typename Geometry_traits_2::Iso_rectangle_2 bb =
bounding_box(points.begin(), points.end());
Number_type xmin, xmax, ymin, ymax;
typename Geometry_traits_2::Compute_x_2 compute_x =
geom_traits->compute_x_2_object();
typename Geometry_traits_2::Compute_y_2 compute_y =
geom_traits->compute_y_2_object();
//make the box a little bigger than bb so that it won't intersect any
//relevant_edge.
xmin = compute_x((bb.min)())-1;
ymin = compute_y((bb.min)())-1;
xmax = compute_x((bb.max)())+1;
ymax = compute_y((bb.max)())+1;
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
Point_2(xmax, ymax), Point_2(xmin, ymax)};
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]),
bbox.unbounded_face());
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]),
e1->target());
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2],box[3]),
e2->target());
bbox.insert_at_vertices(Segment_2(box[0], box[3]),
e1->source(), e3->target());
circ = curr = e1->face()->outer_ccb();
do {
VH v = curr->target();
vs.push_back(v);
incident_edges[v].push_back(curr);
incident_edges[v].push_back(curr->next());
good_edges.push_back(curr);
} while(++curr != circ);
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
typename VHs::size_type j = i+1;
while (j != vs.size()) {
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
break;
j++;
}
if (j-i>1)
funnel(i, j);
i = j-1;
}
}
};
} // end namespace CGAL
#endif

View File

@ -0,0 +1,685 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$`
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
// Ning Xu <longyin0904@gmail.com>
#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
#define CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
#include <CGAL/tags.h>
#include <CGAL/enum.h>
#include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_walk_along_line_point_location.h>
#include <CGAL/assertions.h>
#include <stack>
// TODO:
// * fix handle needles = O(nlogn)
namespace CGAL {
template<class Arrangement_2_, class RegularizationCategory = CGAL::Tag_true>
class Simple_polygon_visibility_2 {
public:
typedef Arrangement_2_ Arrangement_2;
typedef typename Arrangement_2::Traits_2 Traits_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Geometry_traits_2::Kernel K;
typedef typename K::Intersect_2 Intersect_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_const_handle
Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::Ray_2 Ray_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Geometry_traits_2::Line_2 Line_2;
typedef typename Geometry_traits_2::Object_2 Object_2;
typedef RegularizationCategory Regularization_category;
typedef CGAL::Tag_false Supports_general_polygon_category;
typedef CGAL::Tag_true Supports_simple_polygon_category;
Simple_polygon_visibility_2() : p_arr(NULL), traits(NULL) {}
/*! Constructor given an arrangement and the Regularization tag. */
Simple_polygon_visibility_2(const Arrangement_2& arr):
p_arr(&arr) {
traits = p_arr->geometry_traits();
point_location.attach(arr);
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
}
std::string name() const { return std::string("S_visibility_2"); }
/*! Method to check if the visibility object is attached or not to
an arrangement*/
bool is_attached() const {
return (p_arr != NULL);
}
/*! Attaches the visibility object to the 'arr' arrangement */
void attach(const Arrangement_2& arr) {
if(p_arr != &arr){
detach();
p_arr = &arr;
traits = p_arr->geometry_traits();
point_location.attach(arr);
}
}
/*! Detaches the visibility object from the arrangement it is
attached to*/
void detach() {
point_location.detach();
p_arr = NULL;
traits = NULL;
vertices.clear();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
}
/*! Getter method for the input arrangement*/
const Arrangement_2& arrangement_2() const {
return *p_arr;
}
/*! Computes the visibility object from the query point 'q' in the face
'face' and constructs the output in 'out_arr'*/
template <typename VARR>
typename VARR::Face_handle
compute_visibility(const Point_2& q,
const Face_const_handle face,
VARR& out_arr) const
{
CGAL_precondition(!face->is_unbounded());
out_arr.clear();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
// Now retrieve the circulator to first visible vertex from triangulation
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
Ccb_halfedge_const_circulator curr = circ;
do {
vertices.push_back(curr->source()->point());
} while(++curr != circ);
vertices.push_back(vertices[0]);
visibility_region_impl(q);
return output(q, out_arr);
}
/*! Computes the visibility region of the query point 'q' located on the
halfedge 'he' and constructs the output in 'out_arr'*/
template <typename VARR>
typename VARR::Face_handle
compute_visibility(
const Point_2& q,
const Halfedge_const_handle he,
VARR& out_arr ) const
{
out_arr.clear();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
bool query_on_target = false;
if (q != he->source()->point()) {
if (q != he->target()->point()) {
vertices.push_back(he->target()->point());
query_pt_is_on_halfedge = true;
}
else {
query_pt_is_vertex = true;
query_on_target = true;
}
} else {
vertices.push_back( he->target()->point() );
query_pt_is_vertex = true;
}
Ccb_halfedge_const_circulator circ = he;
++circ;
Ccb_halfedge_const_circulator curr = circ;
do {
const Point_2& curr_vertex = curr->target()->point();
vertices.push_back(curr_vertex);
} while (++curr != circ);
if ( query_on_target ) {
vertices.push_back( vertices[0] );
}
visibility_region_impl(q);
return output(q, out_arr);
}
private:
typedef Arr_walk_along_line_point_location<Arrangement_2> Arr_point_location;
typedef typename Arr_point_location::result_type Location_result;
typedef std::vector<Point_2> Vertex_container;
typedef typename Vertex_container::size_type Size_type;
const Arrangement_2 *p_arr;
const Geometry_traits_2 *traits;
mutable Arr_point_location point_location;
/*! Stack of visibile points; manipulated when going through the sequence
of input vertices; contains the vertices of the visibility region after
the run of the algorithm*/
mutable std::stack<Point_2> stack;
/*! Sequence of input vertices*/
mutable Vertex_container vertices;
/*! State of visibility region algorithm*/
mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
mutable bool query_pt_is_vertex;
mutable bool query_pt_is_on_halfedge;
mutable bool inserted_artificial_starting_vertex;
template <typename VARR>
typename VARR::Face_handle
output(const Point_2& q, VARR& out_arr) const {
if(inserted_artificial_starting_vertex)
stack.pop();
std::vector<Point_2> points;
while(!stack.empty()) {
const Point_2& top = stack.top();
if (top != q || query_pt_is_vertex) {
points.push_back(top);
}
stack.pop();
}
if(inserted_artificial_starting_vertex) {
points.back() = points[0];
inserted_artificial_starting_vertex = false;
}
// Quick fix for now. Can be done faster
bool is_degenerate = false;
for(typename std::vector<Point_2>::size_type i = 0; i < points.size()-2;i++){
if(CGAL::orientation(points[i],points[i+1],points[i+2]) == CGAL::COLLINEAR){
is_degenerate = true;
break;
}
}
if(is_degenerate){
//std::cout << is_degenerate << std::endl;
std::vector<Segment_2> segments;
for(typename std::vector<Point_2>::size_type i = 0;i < points.size() - 1; ++i)
{
segments.push_back(Segment_2(points[i], points[i+1]));
}
CGAL::insert(out_arr, segments.begin(), segments.end());
}else{
points.pop_back();
//std::cout << " ordanary " << std::endl;
typename VARR::Vertex_handle v_last, v_first;
v_last = v_first =
out_arr.insert_in_face_interior(points[0],out_arr.unbounded_face());
for(unsigned int i = 0; i < points.size()-1; i++){
if(points[i] < points[(i+1)]){
v_last = out_arr.insert_from_left_vertex (
Segment_2(points[i], points[i+1]), v_last
)->target();
} else {
v_last = out_arr.insert_from_right_vertex(
Segment_2(points[i], points[i+1]), v_last
)->target();
}
}
out_arr.insert_at_vertices(
Segment_2(points.front(), points.back()),
v_last, v_first
);
}
CGAL_postcondition(out_arr.number_of_isolated_vertices() == 0);
CGAL_postcondition(stack.empty());
Visibility_2::conditional_regularize(out_arr, Regularization_category());
vertices.clear();
if (out_arr.faces_begin()->is_unbounded()) {
return ++out_arr.faces_begin();
}
else {
return out_arr.faces_begin();
}
}
/*! Finds a visible vertex from the query point 'q' in 'face'
to start the algorithm from*/
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face,
const Point_2 &q) const
{
Location_result result = point_location.ray_shoot_up(q);
if(const Halfedge_const_handle* e =
boost::get<Halfedge_const_handle>(&(result)))
{
CGAL_assertion((*e)->face() == face);
Point_2 p(q.x(),
traits->compute_y_at_x_2_object()(
Line_2((*e)->source()->point(),
(*e)->target()->point()) ,
q.x()));
vertices.push_back(p);
inserted_artificial_starting_vertex = true;
return (*e)->next()->ccb();
}
else if (const Vertex_const_handle* v =
boost::get<Vertex_const_handle>(&(result)))
{
Halfedge_around_vertex_const_circulator cir =
(*v)->incident_halfedges();
while(face != cir->face()) {
++cir;
}
return cir->next()->ccb();
}
else
{
CGAL_assertion_msg(false, "Should not be reachable.");
return Ccb_halfedge_const_circulator();
}
}
/*! Main method of the algorithm - initializes the stack and variables
and calles the corresponding methods acc. to the algorithm's state;
'q' - query point;
'i' - current vertex' index
'w' - endpoint of ray shot from query point */
void visibility_region_impl(const Point_2& q) const {
Size_type i = 0;
Point_2 w;
Orientation o = traits->orientation_2_object()(q, vertices[0], vertices[1]);
if ( o != RIGHT_TURN ) {
upcase = LEFT;
i = 1;
w = vertices[1];
stack.push(vertices[0]);
stack.push(vertices[1]);
}
else {
upcase = SCANA;
i = 1;
w = vertices[1];
stack.push(vertices[0]);
}
Ray_2 ray_origin( q, vertices[0] );
do {
switch(upcase) {
case LEFT:
left(i, w, q);
break;
case RIGHT:
right(i, w, q);
break;
case SCANA:
scana(i, w, q);
break;
case SCANB:
scanb(i, w);
break;
case SCANC:
scanc(i, w);
break;
case SCAND:
scand(i, w);
break;
case FINISH:
break;
}
if ( upcase == LEFT ) {
Point_2 s_t = stack.top();
stack.pop();
if (traits->orientation_2_object()(q, vertices[0], stack.top() )
== RIGHT_TURN
&&
traits->orientation_2_object()(q, vertices[0], s_t)
== LEFT_TURN )
{
Segment_2 seg( stack.top(), s_t );
if (Object_2 result = Intersect_2()(seg, ray_origin) )
{
const Point_2 * ipoint = object_cast<Point_2>(&result);
assert( ipoint != NULL );
s_t = *ipoint;
upcase = SCANB;
}
}
stack.push( s_t );
}
} while(upcase != FINISH);
}
/*! Method that handles the left turns in the vertex algorithm */
void left(Size_type& i, Point_2& w, const Point_2& q) const {
if (i >= vertices.size() - 1) {
upcase = FINISH;
}
else {
Point_2 s_t = stack.top();
stack.pop();
Point_2 s_t_prev = stack.top();
stack.push( s_t );
Orientation orient1 = traits->orientation_2_object()(
q,
vertices[i],
vertices[i+1] );
if ( orient1 != RIGHT_TURN ) {
// Case L2
upcase = LEFT;
stack.push( vertices[i+1] );
w = vertices[i+1];
i++;
} else {
Orientation orient2 = traits->orientation_2_object()(
s_t_prev,
vertices[i],
vertices[i+1] );
if ( orient2 == RIGHT_TURN ) {
// Case L3
upcase = SCANA;
w = vertices[i+1];
i++;
} else {
// Case L4
upcase = RIGHT;
w = vertices[i];
i++;
}
}
}
}
/*! Scans the stack such that all vertices that were pushed before to the
stack and are now not visible anymore. */
void right(Size_type& i, Point_2& w, const Point_2& q) const {
Point_2 s_j;
Point_2 s_j_prev;
Point_2 u;
int mode = 0;
Orientation orient1, orient2;
s_j_prev = stack.top();
orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i] );
while ( stack.size() > 1 ) {
s_j = s_j_prev;
orient1 = orient2;
stack.pop();
s_j_prev = stack.top();
orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i]);
if ( orient1 != LEFT_TURN && orient2 != RIGHT_TURN ) {
mode = 1;
break;
}
Segment_2 seg2( vertices[i-1], vertices[i] );
Segment_2 seg( s_j_prev, s_j );
if ( vertices[i-1] != s_j )
{
Object_2 result = Intersect_2()( seg, seg2 );
if(result) {
const Point_2 * ipoint = object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
mode = 2;
break;
}
}
}
assert( mode != 0 );
if ( mode == 1 ) {
orient1 = traits->orientation_2_object()(q, vertices[i], vertices[i+1] );
orient2 = traits->orientation_2_object()(vertices[i-1],
vertices[i],
vertices[i+1] );
if ( orient1 == RIGHT_TURN ) {
// Case R1
// Since the next action is RIGHT, we do not compute the intersection
// of (s_j,s_j_prev) and the ray (query_pt, vertices[i]),
// thus, (s_j,s_j_prev) is not shortcutted, but it is harmless
upcase = RIGHT;
stack.push( s_j );
w = vertices[i];
i++;
} else if ( orient2 == RIGHT_TURN ) {
// Case R2
Ray_2 ray( q, vertices[i] );
Segment_2 seg( s_j_prev, s_j );
Object_2 result = Intersect_2()( seg, ray );
const Point_2 * ipoint = object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
if ( stack.top() != u ) {
stack.push( u );
}
upcase = LEFT;
stack.push( vertices[i] );
stack.push( vertices[i+1] );
w = vertices[i+1];
i++;
} else {
// Case R3
Ray_2 ray( q, vertices[i] );
Segment_2 seg( s_j_prev, s_j );
Object_2 result = Intersect_2()( seg, ray );
const Point_2 * ipoint = object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
if ( stack.top() != u ) {
stack.push( u );
}
upcase = SCANC;
w = vertices[i];
i++;
}
} else if ( mode == 2 ) {
// Case R4
upcase = SCAND;
w = u;
}
}
/*! Scans the vertices starting from index 'i' for the first visible vertex
out of the back hidden window */
void scana(Size_type& i, Point_2& w, const Point_2& q) const {
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
Point_2 u;
Size_type k = scan_edges( i, q, stack.top(), u, true );
Orientation orient1 =
traits->orientation_2_object()(q, vertices[k], vertices[k+1] );
if ( orient1 == RIGHT_TURN ) {
bool fwd = traits->
collinear_are_ordered_along_line_2_object()(q, stack.top(), u );
if ( !fwd ) {
// Case A1
upcase = RIGHT;
i = k+1;
w = u;
} else {
// Case A2
upcase = SCAND;
i = k+1;
w = u;
}
} else {
// Case A3
upcase = LEFT;
i = k+1;
stack.push( u );
if ( u != vertices[k+1] ) {
stack.push( vertices[k+1] );
}
w = vertices[k+1];
}
}
/*! Find the first edge interecting the segment (v_0, s_t) */
void scanb(Size_type& i, Point_2& w) const {
if ( i == vertices.size() - 1 ) {
upcase = FINISH;
return;
}
Point_2 u;
Size_type k = scan_edges( i, stack.top(), vertices[0], u, false );
if ( (k+1 == vertices.size()-1) && (vertices[0] == u) ) {
// Case B1
upcase = FINISH;
stack.push( vertices[0] );
} else {
// Case B2
upcase = RIGHT;
i = k+1;
w = u;
}
}
/*! Finds the exit from a general front hidden window by finding the first
vertex to the right of the ray defined by the query_point and w*/
void scanc(Size_type& i, Point_2& w) const {
Point_2 u;
Size_type k = scan_edges( i, stack.top(), w, u, false );
upcase = RIGHT;
i = k+1;
w = u;
}
/*! find the first edge intersecting the given window (s_t, w) */
void scand(Size_type& i, Point_2& w) const {
Point_2 u;
Size_type k = scan_edges( i, stack.top(), w, u, false );
upcase = LEFT;
i = k+1;
stack.push( u );
if ( u != vertices[k+1] ) {
stack.push( vertices[k+1] );
}
w = vertices[k+1];
}
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
or given segment. is_ray = true -> ray, false -> segment.
The intersection point is returned by u */
Size_type scan_edges( Size_type i,
const Point_2& ray_begin,
const Point_2& ray_end,
Point_2& u,
bool is_ray ) const
{
Orientation old_orient = RIGHT_TURN;
Ray_2 ray( ray_begin, ray_end );
Segment_2 s2( ray_begin, ray_end );
Size_type k;
Object_2 result;
for ( k = i; k+1 < vertices.size(); k++ ) {
Orientation curr_orient = traits->orientation_2_object()(
ray_begin,
ray_end,
vertices[k+1] );
if ( curr_orient != old_orient ) {
// Orientation switch, an intersection may occur
Segment_2 seg( vertices[k], vertices[k+1] );
if ( is_ray ) {
result = Intersect_2()( seg, ray );
if(result)
break;
} else {
result = Intersect_2()( seg, s2 );
if(result)
break;
}
}
old_orient = curr_orient;
}
assert( k+1<vertices.size() );
const Point_2 * ipoint = object_cast<Point_2>( &result );
if ( ipoint ) {
u = *ipoint;
} else {
u = vertices[k+1];
}
return k;
}
};
} // namespace CGAL
#endif

View File

@ -0,0 +1,710 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Michael Hemmer <michael.hemmer@cgal.org>
//
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
#include <CGAL/Arrangement_2.h>
#include <boost/shared_ptr.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Arr_observer.h>
namespace CGAL {
template<class Arrangement_2_ , class RegularizationCategory = CGAL::Tag_true >
class Triangular_expansion_visibility_2 {
typedef typename Arrangement_2_::Geometry_traits_2 Geometry_traits_2;
typedef typename Geometry_traits_2::Kernel K;
typedef Triangular_expansion_visibility_2<
Arrangement_2_, RegularizationCategory> Self;
public:
typedef Arrangement_2_ Arrangement_2;
typedef typename Arrangement_2::Traits_2 Traits_2;
typedef typename Arrangement_2::Halfedge Halfedge;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Ccb_halfedge_circulator
Ccb_halfedge_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef typename K::Point_2 Point_2;
typedef typename Geometry_traits_2::Ray_2 Ray_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Geometry_traits_2::Line_2 Line_2;
typedef typename Geometry_traits_2::Vector_2 Vector_2;
typedef typename Geometry_traits_2::Direction_2 Direction_2;
typedef typename Geometry_traits_2::FT Number_type;
typedef typename Geometry_traits_2::Object_2 Object_2;
typedef RegularizationCategory Regularization_category;
typedef CGAL::Tag_true Supports_general_polygon_category;
typedef CGAL::Tag_true Supports_simple_polygon_category;
private:
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT;
typedef std::pair<Point_2,Point_2> Constraint;
// Functor to create edge constraints for the CDT out of Halfedges
struct Make_constraint
{
typedef Constraint result_type;
Constraint operator()(const Halfedge& edge) const {
return std::make_pair(edge.source()->point(),
edge.target()->point());
}
};
// Observer to track any changes of the attached arrangement.
class Observer : public Arr_observer<Arrangement_2>
{
typedef Arr_observer<Arrangement_2> Base;
typedef Observer Self;
public:
bool has_changed;
Observer() : Base(), has_changed(false)
{}
Observer(const Arrangement_2& arr)
: Base(const_cast<Arrangement_2&>(arr)), has_changed(false)
{}
// Arr_observer interface
void after_attach() { has_changed = false; }
void after_global_change() { has_changed = true; }
void after_create_vertex(Vertex_handle) { has_changed = true; }
void after_create_boundary_vertex(Vertex_handle) { has_changed = true; }
void after_create_edge(Halfedge_handle) { has_changed = true; }
void after_modify_vertex(Vertex_handle) { has_changed = true; }
void after_modify_edge(Halfedge_handle) { has_changed = true; }
void after_split_edge(Halfedge_handle, Halfedge_handle) {
has_changed = true; }
void after_split_fictitious_edge(Halfedge_handle, Halfedge_handle) {
has_changed = true; }
void after_split_face(Face_handle, Face_handle, bool) {
has_changed = true; }
void after_split_outer_ccb(Face_handle, Ccb_halfedge_circulator,
Ccb_halfedge_circulator) {
has_changed = true; }
void after_split_inner_ccb(Face_handle, Ccb_halfedge_circulator,
Ccb_halfedge_circulator) {
has_changed = true; }
void after_add_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
void after_add_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
void after_add_isolated_vertex(Vertex_handle) { has_changed = true; }
void after_merge_edge(Halfedge_handle) { has_changed = true; }
void after_merge_fictitious_edge(Halfedge_handle) { has_changed = true; }
void after_merge_face(Face_handle) { has_changed = true; }
void after_merge_outer_ccb(Face_handle, Ccb_halfedge_circulator) {
has_changed = true; }
void after_merge_inner_ccb(Face_handle, Ccb_halfedge_circulator) {
has_changed = true; }
void after_move_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
void after_move_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
void after_move_isolated_vertex(Vertex_handle) { has_changed = true; }
void after_remove_vertex() { has_changed = true; }
void after_remove_edge() { has_changed = true; }
void after_remove_outer_ccb(Face_handle) { has_changed = true; }
void after_remove_inner_ccb(Face_handle) { has_changed = true; }
};
private:
const Arrangement_2* p_arr;
// May change during visibility computation
mutable Observer observer;
mutable boost::shared_ptr<CDT> p_cdt;
mutable std::vector<Segment_2> needles;
// Copy constructor and assignment not supported
Triangular_expansion_visibility_2(const Self&);
Self& operator= (const Self& );
public:
Triangular_expansion_visibility_2() : p_arr(NULL){}
/*! Constructor given an arrangement. */
Triangular_expansion_visibility_2 (const Arrangement_2& arr)
: p_arr(&arr), observer(arr)
{
init_cdt();
}
const std::string name() const { return std::string("T_visibility_2"); }
bool is_attached() const {
//std::cout << "is_attached" << std::endl;
return (p_arr != NULL);
}
void attach(const Arrangement_2& arr) {
if(p_arr != &arr){
p_arr = &arr;
observer.detach();
observer.attach(const_cast<Arrangement_2&>(arr));
init_cdt();
}
//std::cout << "attach done" << std::endl;
}
void detach() {
//std::cout << "detach" << std::endl;
observer.detach();
p_arr = NULL;
p_cdt.reset();
}
const Arrangement_2& arrangement_2() const {
return *p_arr;
}
template <typename VARR>
typename VARR::Face_handle
compute_visibility(const Point_2& q,
const Face_const_handle face,
VARR& out_arr )
const {
//std::cout << "query in face interior" << std::endl;
if(observer.has_changed) {
init_cdt();
}
out_arr.clear();
needles.clear();
assert(!face->is_unbounded());
std::vector<Point_2> raw_output;
typename CDT::Face_handle fh = p_cdt->locate(q);
raw_output.push_back(fh->vertex(1)->point());
if(!p_cdt->is_constrained(get_edge(fh,0))){
//std::cout<< "edge 0 is not constrained" << std::endl;
expand_edge(
q,
fh->vertex(2)->point(),
fh->vertex(1)->point(),
fh,0,std::back_inserter(raw_output));
}
raw_output.push_back(fh->vertex(2)->point());
if(!p_cdt->is_constrained(get_edge(fh,1))){
//std::cout << "edge 1 is not constrained" << std::endl;
expand_edge(
q,
fh->vertex(0)->point(),
fh->vertex(2)->point(),
fh,1,std::back_inserter(raw_output));
}
raw_output.push_back(fh->vertex(0)->point());
if(!p_cdt->is_constrained(get_edge(fh,2))){
//std::cout << "edge 2 is not constrained" << std::endl;
expand_edge(
q,
fh->vertex(1)->point(),
fh->vertex(0)->point(),
fh,2,std::back_inserter(raw_output));
}
return output(raw_output,out_arr);
}
template <typename VARR>
typename VARR::Face_handle
compute_visibility(const Point_2& q,
const Halfedge_const_handle he,
VARR& out_arr)
const {
//std::cout << "visibility_region he" << std::endl;
if(observer.has_changed) {
init_cdt();
}
assert(!he->face()->is_unbounded());
out_arr.clear();
needles.clear();
std::vector<Point_2> raw_output;
typename CDT::Locate_type location;
int index;
typename CDT::Face_handle fh = p_cdt->locate(q,location,index);
assert(location == CDT::EDGE || location == CDT::VERTEX);
//the following code tries to figure out which triangle one should start in.
if(location == CDT::EDGE){
//std::cout << "query on edge" << std::endl;
// this is the easy part, there are only two possible faces
// index indicates the edge = vertex on the other side of the edge
// the next vertex in cw order should be the target of given edge
if(fh->vertex(p_cdt->cw(index))->point() != he->target()->point()){
//std::cout << "need to swap face" << std::endl;
// take face on the other side if this is not the case
typename CDT::Face_handle nfh = fh->neighbor(index);
index = nfh->index(fh);
fh = nfh;
}
assert(fh->vertex(p_cdt->cw(index))->point() == he->target()->point());
assert(!p_cdt->is_infinite(fh->vertex(index)));
// output the edge the query lies on
raw_output.push_back(he->source()->point());
raw_output.push_back(he->target()->point());
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->ccw(index)))){
expand_edge(
q,
fh->vertex(index)->point(), //left
he->target()->point() , //right
fh,
p_cdt->ccw(index),
std::back_inserter(raw_output));
}
raw_output.push_back(fh->vertex(index)->point());
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index)))){
expand_edge(
q,
he->source()->point() , //left
fh->vertex(index)->point(), //right
fh,
p_cdt->cw(index),
std::back_inserter(raw_output));
}
}
if(location == CDT::VERTEX){
//std::cout << "query on vertex" << std::endl;
//bool query_point_on_vertex_is_not_working_yet = false;
//assert(query_point_on_vertex_is_not_working_yet);
assert(q == he->target()->point());
assert(fh->vertex(index)->point() == he->target()->point());
// push points that are seen anyway
// raw_output.push_back(he->source()->point()); inserted last
raw_output.push_back(he->target()->point());
raw_output.push_back(he->next()->target()->point());
// now start in the triangle that contains he->next()
while(
p_cdt->is_infinite(fh->vertex(p_cdt->ccw(index))) ||
he->next()->target()->point() !=
fh->vertex(p_cdt->ccw(index))->point()
)
{
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
int nindex = nfh->index(fh);
index = p_cdt->ccw(nindex);
fh = nfh;
assert(he->target()->point() == fh->vertex(index)->point());
}
assert(he->next()->source()->point() == fh->vertex(index)->point());
assert(he->next()->target()->point() ==
fh->vertex(p_cdt->ccw(index))->point());
assert(!p_cdt->is_infinite(fh));
assert(p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index))));
while(he->source()->point() != fh->vertex(p_cdt->ccw(index))->point()){
if(!p_cdt->is_constrained(get_edge(fh,index))){
expand_edge(
q,
fh->vertex(p_cdt-> cw(index))->point(), //left
fh->vertex(p_cdt->ccw(index))->point(), //right
fh,
index,
std::back_inserter(raw_output));
}
// push left end point of edge into output
raw_output.push_back(fh->vertex(p_cdt-> cw(index))->point());
// take the next triangle around q in ccw order
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
int nindex = nfh->index(fh);
index = p_cdt->ccw(nindex);
fh = nfh;
assert(fh->vertex(index)->point() == he->target()->point());
}
}
return output(raw_output,out_arr);
}
private:
typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i) const {
return std::make_pair(fh,i);
}
Point_2 ray_seg_intersection(
const Point_2& q, const Point_2& b, // the ray
const Point_2& s, const Point_2& t // the segment
) const {
Ray_2 ray(q,b);
Segment_2 seg(s,t);
assert(typename K::Do_intersect_2()(ray,seg));
CGAL::Object obj = typename K::Intersect_2()(ray,seg);
Point_2 result = object_cast<Point_2>(obj);
return result;
}
void collect_needle(
const Point_2& q,
const typename CDT::Vertex_handle vh,
const typename CDT::Face_handle fh,
int index)
const {
// the expanded edge should not be constrained
assert(!p_cdt->is_constrained(get_edge(fh,index)));
assert(!p_cdt->is_infinite(fh));
// go into the new face
const typename CDT::Face_handle nfh(fh->neighbor(index));
assert(!p_cdt->is_infinite(nfh));
// get indices of neighbors
int nindex = nfh->index(fh); // index of new vertex and old face
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
// get vertices seen from entering edge
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
assert(!p_cdt->is_infinite(nvh));
assert(!p_cdt->is_infinite(lvh));
assert(!p_cdt->is_infinite(rvh));
// get edges seen from entering edge
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
// do orientation computation once for new vertex
typename K::Orientation_2 orientation =
p_cdt->geom_traits().orientation_2_object();
CGAL::Orientation orient = orientation(q,vh->point(),nvh->point());
//std::cout << "\n collect_needle" <<std::endl;
//std::cout << "q "<< q << std::endl ;
//std::cout << "vh->point() "<< vh->point() << std::endl;
//std::cout << "lvh->point() "<< lvh->point() << std::endl ;
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
switch ( orient ) {
case CGAL::COUNTERCLOCKWISE:
// looking on to the right edge
if(p_cdt->is_constrained(re)) {
if(vh != rvh) {
Point_2 p = ray_seg_intersection(q, vh->point(),
nvh->point(), rvh->point());
//std::cout << vh->point() <<" -1- "<< p <<std::endl;
needles.push_back(Segment_2(vh->point(),p));
}
} else {
collect_needle(q,vh,nfh,rindex);
}
break;
case CGAL::CLOCKWISE:
// looking on to the left edge
if(p_cdt->is_constrained(le)){
if(vh != lvh){
Point_2 p = ray_seg_intersection(q, vh->point(),
nvh->point(), lvh->point());
//std::cout << vh->point() <<" -2- "<< p <<std::endl;
needles.push_back(Segment_2(vh->point(),p));
}
} else {
collect_needle(q,vh,nfh,lindex);
}
break;
default:
assert(orient == CGAL::COLLINEAR);
// looking on nvh, so it must be reported
// if it wasn't already (triangles rotate around vh)
if(vh != nvh){
//std::cout << vh->point() <<" -3- "<< nvh->point() <<std::endl;
needles.push_back(Segment_2(vh->point(),nvh->point()));
}
// but we may also contiue looking along the vertex
if(!p_cdt->is_constrained(re)) {
collect_needle(q,nvh,nfh,rindex);
}
if(!p_cdt->is_constrained(le)) {
collect_needle(q,nvh,nfh,lindex);
}
break;
}
}
template<class OIT>
OIT expand_edge(
const Point_2& q,
const Point_2& left,
const Point_2& right,
typename CDT::Face_handle fh,
int index,
OIT oit)
const {
// the expanded edge should not be constrained
assert(!p_cdt->is_constrained(get_edge(fh,index)));
assert(!p_cdt->is_infinite(fh));
// go into the new face
const typename CDT::Face_handle nfh(fh->neighbor(index));
assert(!p_cdt->is_infinite(nfh));
// get indices of neighbors
int nindex = nfh->index(fh); // index of new vertex and old face
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
// get vertices seen from entering edge
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
assert(!p_cdt->is_infinite(nvh));
assert(!p_cdt->is_infinite(lvh));
assert(!p_cdt->is_infinite(rvh));
// get edges seen from entering edge
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
// do orientation computation once for new vertex
typename K::Orientation_2 orientation =
p_cdt->geom_traits().orientation_2_object();
CGAL::Orientation ro = orientation(q,right,nvh->point());
CGAL::Orientation lo = orientation(q,left ,nvh->point());
assert(typename K::Orientation_2()(q,left ,lvh->point())
!= CGAL::CLOCKWISE);
assert(typename K::Orientation_2()(q,right,rvh->point())
!= CGAL::COUNTERCLOCKWISE);
//std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " <<
//(lo == CGAL::CLOCKWISE) << std::endl;
//right edge is seen if new vertex is counter clockwise of right boarder
if(ro == CGAL::COUNTERCLOCKWISE){
if(p_cdt->is_constrained(re)){
// the edge is constrained
// report intersection with right boarder ray
// if it is not already the right vertex (already reported)
if(right != rvh->point()){
*oit++ = ray_seg_intersection(q,right,nvh->point(),rvh->point());
}
// then report intersection with left boarder if it exists
if(lo == CGAL::COUNTERCLOCKWISE){
*oit++ = ray_seg_intersection(q,left,nvh->point(),rvh->point());
}
}else{
// the edge is not a constrained
if(lo == CGAL::COUNTERCLOCKWISE){
// no split needed and return
//std::cout<< "h1"<< std::endl;
oit = expand_edge(q,left,right,nfh,rindex,oit);
//std::cout<< "h1 done"<< std::endl;
return oit;
}else{
// spliting at new vertex
//std::cout<< "h2"<< std::endl;
*oit++ = expand_edge(q,nvh->point(),right,nfh,rindex,oit);
//std::cout<< "h2 done"<< std::endl;
}
}
}
//std::cout << "q "<< q << std::endl ;
//std::cout << "lvh->point() "<< lvh->point() << std::endl;
//std::cout << "left "<< left << std::endl ;
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
//std::cout << "right "<< right << std::endl ;
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
// determin whether new vertex needs to be reported
if(ro != CGAL::CLOCKWISE && lo != CGAL::COUNTERCLOCKWISE){
*oit++ = nvh->point();
}
if(!Regularization_category::value){
assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR));
// we have to check whether a needle starts here.
if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re)
&& ro == CGAL::COLLINEAR)
collect_needle(q,nvh,nfh,rindex);
if(p_cdt->is_constrained(re) && !p_cdt->is_constrained(le)
&& lo == CGAL::COLLINEAR)
collect_needle(q,nvh,nfh,lindex);
}
//left edge is seen if new vertex is clockwise of left boarder
if(lo == CGAL::CLOCKWISE){
if(p_cdt->is_constrained(le)){
// the edge is constrained
// report interesection with right boarder if exists
if(ro == CGAL::CLOCKWISE){
*oit++ = ray_seg_intersection(q,right,nvh->point(),lvh->point());
}
// then report intersection with left boarder ray
// if it is not already the left vertex (already reported)
if(left != lvh->point()){
*oit++ = ray_seg_intersection(q,left,nvh->point(),lvh->point());
}
return oit;
}else{
// the edge is not a constrained
if(ro == CGAL::CLOCKWISE){
// no split needed and return
//std::cout<< "h3"<< std::endl;
oit = expand_edge(q,left,right,nfh,lindex,oit);
//std::cout<< "h3 done"<< std::endl;
return oit;
}else{
// spliting at new vertex
//std::cout<< "h4"<< std::endl;
oit = expand_edge(q,left,nvh->point(),nfh,lindex,oit);
//std::cout<< "h4 done"<< std::endl;
return oit;
}
}
}
return oit;
}
template <typename VARR>
typename VARR::Face_handle
output(std::vector<Point_2>& raw_output, VARR& out_arr) const {
if(!needles.empty()){
std::vector<Segment_2> segments(needles.begin(),needles.end());
for(unsigned int i = 0; i < raw_output.size(); i++){
// //std::cout << raw_output[i] << " -- "
// << raw_output[(i+1)%raw_output.size()] << std::endl;
segments.push_back(Segment_2(raw_output[i],
raw_output[(i+1) % raw_output.size()]));
}
CGAL::insert_non_intersecting_curves(out_arr,
segments.begin(),
segments.end());
} else {
typename VARR::Vertex_handle v_last, v_first;
v_last = v_first =
out_arr.insert_in_face_interior(raw_output[0],out_arr.unbounded_face());
for(unsigned int i = 0; i < raw_output.size()-1; i++){
// std::cout << raw_output[i] << " -- "
// << raw_output[(i+1)%raw_output.size()] << std::endl;
if(raw_output[i] < raw_output[(i+1)]){
v_last = out_arr.insert_from_left_vertex (
Segment_2(raw_output[i], raw_output[i+1]), v_last
)->target();
} else {
v_last = out_arr.insert_from_right_vertex(
Segment_2(raw_output[i], raw_output[i+1]), v_last
)->target();
}
}
out_arr.insert_at_vertices(
Segment_2(raw_output.front(), raw_output.back()),
v_last, v_first
);
}
assert(out_arr.number_of_faces() == 2);
if(out_arr.faces_begin()->is_unbounded())
return ++out_arr.faces_begin();
else
return out_arr.faces_begin();
}
void init_cdt() const {
//std::cout<< "==============" <<std::endl;
//std::cout<< "Input Polygon:" <<std::endl;
typedef typename boost::transform_iterator<Make_constraint,
Edge_const_iterator> Iter;
Iter begin = boost::make_transform_iterator(p_arr->edges_begin(),
Make_constraint());
Iter end = boost::make_transform_iterator(p_arr->edges_end(),
Make_constraint());
//std::cout << "init_cdt new CDT" << std::endl;
p_cdt = boost::shared_ptr<CDT>(new CDT(begin, end));
observer.has_changed = false;
//std::cout << "init_cdt done" << std::endl;
//std::cout << std::endl;
}
};
} // namespace CGAL
#endif // CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H

View File

@ -0,0 +1,435 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
#ifndef CGAL_VISIBILITY_UTILS_H
#define CGAL_VISIBILITY_UTILS_H
#include <vector>
#include <CGAL/tags.h>
#include <CGAL/enum.h>
namespace CGAL {
namespace Visibility_2 {
template <class Arrangement_2>
int count_edges_in_face(typename Arrangement_2::Face_const_handle fch) {
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
Ccb_halfedge_const_circulator circ = fch->outer_ccb();
Ccb_halfedge_const_circulator curr = circ;
int edge_cnt(0);
do {
edge_cnt++;
} while (++curr != circ);
return edge_cnt;
}
template <class Edge_const_iterator>
void print_edge(Edge_const_iterator eit) {
std::cout << "[" << eit->curve() << "]" << std::endl;
}
template <class Face_const_handle, class Ccb_halfedge_const_circulator>
void print_simple_face(Face_const_handle fh) {
Ccb_halfedge_const_circulator cir = fh->outer_ccb();
Ccb_halfedge_const_circulator curr = cir;
do {
std::cout << "[" << curr->curve() << "]" << std::endl;
} while (++ curr != cir);
}
template <class Arrangement_2>
void print_arrangement(const Arrangement_2& arr) {
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
Edge_const_iterator eit;
std::cout << arr.number_of_edges() << " edges:" << std::endl;
for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
print_edge(eit);
}
template <class Arrangement_2>
void print_arrangement_by_face(const Arrangement_2& arr) {
typedef typename Arrangement_2::Face_const_iterator Face_const_iterator;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
Face_const_iterator f;
for (f = arr.faces_begin() ; f != arr.faces_end() ; f++) {
if (!f->is_unbounded()) {
std::cout << "FACE\n";
print_simple_face<Face_const_iterator, Ccb_halfedge_const_circulator>(f);
std::cout << "END FACE\n";
}
}
}
template <class Geometry_traits_2>
Orientation orientation_2(const Geometry_traits_2 *geom_traits,
const typename Geometry_traits_2::Point_2& p,
const typename Geometry_traits_2::Point_2& q,
const typename Geometry_traits_2::Point_2& r) {
typename Geometry_traits_2::Orientation_2 orient =
geom_traits->orientation_2_object();
return orient(p, q, r);
}
template <class Geometry_traits_2>
bool less_distance_to_point_2(const Geometry_traits_2 *geom_traits,
const typename Geometry_traits_2::Point_2& p,
const typename Geometry_traits_2::Point_2& q,
const typename Geometry_traits_2::Point_2& r) {
typename Geometry_traits_2::Less_distance_to_point_2 less_dist =
geom_traits->less_distance_to_point_2_object();
return less_dist(p, q, r);
}
template <class Geometry_traits_2>
bool collinear(const Geometry_traits_2 *geom_traits,
const typename Geometry_traits_2::Point_2& p,
const typename Geometry_traits_2::Point_2& q,
const typename Geometry_traits_2::Point_2& r) {
typename Geometry_traits_2::Collinear_2 collinear_fnct =
geom_traits->collinear_2_object();
return collinear_fnct(p, q, r);
}
template <class Geometry_traits_2, class _Curve_first, class _Curve_second >
typename Geometry_traits_2::Object_2 intersect_2(
const Geometry_traits_2 *geom_traits,
const _Curve_first& s1,
const _Curve_second& s2)
{
typedef typename Geometry_traits_2::Kernel Kernel;
const Kernel *kernel = static_cast<const Kernel*> (geom_traits);
typename Kernel::Intersect_2 intersect_fnct = kernel->intersect_2_object();
return intersect_fnct(s1, s2);
}
template <class Geometry_traits_2>
CGAL::Comparison_result compare_xy_2(
const Geometry_traits_2 *geom_traits,
const typename Geometry_traits_2::Point_2 &p,
const typename Geometry_traits_2::Point_2 &q)
{
typename Geometry_traits_2::Compare_xy_2 cmp =
geom_traits->compare_xy_2_object();
return cmp(p, q);
}
template <class Geometry_traits_2, class Type1, class Type2>
typename Geometry_traits_2::FT compute_squared_distance_2(
const Geometry_traits_2 *geom_traits,
const Type1& p,
const Type2& seg) {
typename Geometry_traits_2::Compute_squared_distance_2 compute_dist =
geom_traits->compute_squared_distance_2_object();
return compute_dist(p, seg);
}
template <class Geometry_traits_2, class Type1, class Type2>
bool do_intersect_2(const Geometry_traits_2 *geom_traits,
const Type1& c1,
const Type2& c2) {
typename Geometry_traits_2::Do_intersect_2 intersect =
geom_traits->do_intersect_2_object();
return intersect(c1, c2);
}
template <class Geometry_traits_2>
bool collinear_are_ordered_along_line_2(
const Geometry_traits_2 *geom_traits,
const typename Geometry_traits_2::Point_2 &p,
const typename Geometry_traits_2::Point_2 &q,
const typename Geometry_traits_2::Point_2 &r)
{
typename Geometry_traits_2::Collinear_are_ordered_along_line_2 coll =
geom_traits->collinear_are_ordered_along_line_2_object();
return coll(p, q, r);
}
template <class Geometry_traits_2, class Type1, class Type2>
typename Geometry_traits_2::Point_2 construct_projected_point_2(
const Geometry_traits_2 *geom_traits,
const Type1& s,
const Type2& p) {
typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::FT Number_type;
typename Geometry_traits_2::Construct_projected_point_2 construct_proj =
geom_traits->construct_projected_point_2_object();
Point_2 proj_pt = construct_proj(s.supporting_line(), p);
if (s.has_on(proj_pt)) {
return proj_pt;
}
else {
Number_type d_to_src = compute_squared_distance_2
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.source());
Number_type d_to_trg = compute_squared_distance_2
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.target());
if (d_to_src < d_to_trg) {
return s.source();
}
else {
return s.target();
}
}
}
// construct an arrangement of visibility region from a vector of
// circular ordered vertices with respect to the query point
template <class Visibility_2, class Visibility_arrangement_2>
void report_while_handling_needles(
const typename Visibility_2::Arrangement_2::Geometry_traits_2 *traits,
const typename Visibility_2::Arrangement_2::Point_2& q,
std::vector<typename Visibility_2::Arrangement_2::Point_2>& points,
Visibility_arrangement_2& arr_out) {
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
typedef typename Arrangement_2::Point_2 Point_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Visibility_arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Visibility_arrangement_2::Vertex_handle Vertex_handle;
typename std::vector<Segment_2>::size_type i = 0;
if (points.front() == points.back()) {
points.pop_back();
}
while (collinear(traits, q, points[i], points.back())) {
points.push_back(points[i]);
i++;
}
points.push_back(points[i]);
Halfedge_handle he_handle;
//the handle of vertex where the next segment is inserted
Vertex_handle v_trg;
//the handle of vertex inserted first
Vertex_handle v_fst;
//the handle of vertex of the end of a needle
Vertex_handle v_needle_end;
v_trg = v_fst = arr_out.insert_in_face_interior(points[i],
arr_out.unbounded_face());
//find a point that is right after a needle
while (i+1 < points.size()) {
if ( collinear(traits, points[i], points[i+1], q)) {
Vertex_handle v_needle_begin = v_trg;
std::vector<Point_2> forward_needle; //vertices of the needle that are not
//between q and v_needle_begin;
//their direction is leaving q;
std::vector<Point_2> backward_needle;//vertices of the needle that are not
//between q and v_needle_begin;
//their direction is towards q;
std::vector<Point_2> part_in_q_side; //vertices of the needle that are
//between q and v_needle_begin
part_in_q_side.push_back(points[i]);
forward_needle.push_back((points[i]));
bool same_side_of_q = (compare_xy_2(traits, points[i], q) ==
compare_xy_2(traits, points[i], points[i+1]));
if (same_side_of_q)
part_in_q_side.push_back(points[i+1]);
else
forward_needle.push_back(points[i+1]);
i++;
while (i+1 < points.size() &&
orientation_2(traits, points[i], points[i+1], q ) ==
CGAL::COLLINEAR)
{
if (same_side_of_q) {
part_in_q_side.push_back(points[i+1]);
}
else {
if (compare_xy_2(traits, part_in_q_side.front(), q) ==
compare_xy_2(traits, part_in_q_side.front(), points[i+1]))
{
same_side_of_q = true;
part_in_q_side.push_back(points[i+1]);
}
else {
if (less_distance_to_point_2(traits, q, points[i], points[i+1]))
forward_needle.push_back(points[i+1]);
else
backward_needle.push_back(points[i+1]);
}
}
i++;
}
//obtain the end point of a needle
Point_2 end_of_needle;
if (same_side_of_q)
end_of_needle = part_in_q_side.back();
else {
if (backward_needle.empty()) {
end_of_needle = forward_needle.back();
}
else {
end_of_needle = backward_needle.back();
}
}
std::reverse(backward_needle.begin(), backward_needle.end());
std::vector<Point_2> merged_needle;
// merge the forward_needle and backward_needle
unsigned int itr_fst = 0, itr_snd = 0;
while (itr_fst < forward_needle.size() &&
itr_snd < backward_needle.size()) {
if (less_distance_to_point_2(traits,
q,
forward_needle[itr_fst],
backward_needle[itr_snd]))
{
merged_needle.push_back(forward_needle[itr_fst]);
itr_fst++;
}
else {
merged_needle.push_back(backward_needle[itr_snd]);
itr_snd++;
}
}
while (itr_fst < forward_needle.size()) {
merged_needle.push_back(forward_needle[itr_fst]);
itr_fst++;
}
while (itr_snd < backward_needle.size()) {
merged_needle.push_back(backward_needle[itr_snd]);
itr_snd++;
}
for (unsigned int p = 0 ; p+1 < merged_needle.size() ; p++) {
if (compare_xy_2<Geometry_traits_2>(
traits, merged_needle[p], merged_needle[p+1]) == SMALLER)
{
he_handle = arr_out.insert_from_left_vertex(
Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
}
else {
he_handle = arr_out.insert_from_right_vertex(
Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
}
v_trg = he_handle->target();
if (merged_needle[p+1] == end_of_needle) {
v_needle_end = v_trg;
}
}
if (same_side_of_q) {
//insert the part of needle between q and v_needle_begin
v_trg = v_needle_begin;
for (unsigned int p = 0 ; p+1 < part_in_q_side.size() ; p++) {
if (compare_xy_2<Geometry_traits_2>(
traits, part_in_q_side[p], part_in_q_side[p+1]) == SMALLER)
{
he_handle = arr_out.insert_from_left_vertex(
Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
}
else {
he_handle = arr_out.insert_from_right_vertex(
Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
}
v_trg = he_handle->target();
}
}
else
v_trg = v_needle_end;
}
else {
if (compare_xy_2<Geometry_traits_2>(
traits, v_trg->point(), points[i+1]) == SMALLER)
{
he_handle = arr_out.insert_from_left_vertex(
Segment_2(points[i], points[i+1]), v_trg);
}
else {
he_handle = arr_out.insert_from_right_vertex(
Segment_2(points[i], points[i+1]), v_trg);
}
v_trg = he_handle->target();
i++;
}
if (i+2 == points.size()) {
//close the boundary
v_trg = he_handle->target();
arr_out.insert_at_vertices(Segment_2(points[points.size()-2],
points[points.size()-1]),
v_trg, v_fst);
break;
}
}
}
template <typename VARR>
void regularize_output(VARR& arr_out) {
typename VARR::Edge_iterator it = arr_out.edges_begin();
while(it != arr_out.edges_end()) {
if (it->face() == it->twin()->face()) {
typename VARR::Halfedge_handle he = it;
++it;
arr_out.remove_edge(he);
}
else {
++it;
}
}
}
template <typename VARR>
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
regularize_output(arr_out);
}
template <typename VARR>
void conditional_regularize(VARR&, CGAL::Tag_false) {
//do nothing
}
} // end namespace Visibility_2
} // end namespace CGAL
#endif

View File

View File

@ -0,0 +1 @@
Braunschweig University (Germany).

View File

@ -0,0 +1 @@
GPL (v3 or later)

View File

@ -0,0 +1 @@
Michael Hemmer <michael.hemmer@cgal.org>

View File

@ -0,0 +1,18 @@
#!/bin/bash
dir="../../data/example"
nameend=".environment"
type1=S
type2=T
report_name="${type1}${type2}_report.txt"
echo "" >$report_name
for (( i=1; i<9; i=i+1)); do
file="${dir}${i}${nameend}"
for query_type in face edge vertex; do
echo "file_name: ${file}" >>$report_name
echo "query_type: ${query_type}" >>$report_name
echo "regularize: yes" >>$report_name
./simple_benchmark $file $type1 $type2 $query_type true >>$report_name
echo "regularize: no" >>$report_name
./simple_benchmark $file $type1 $type2 $query_type false >>$report_name
done
done

View File

@ -0,0 +1,17 @@
# Test case 1 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8
2 0
4 0
6 0
8 0
-10 10
10 10
10 -10
-10 -10
6
0 1
2 3
4 5
5 6
6 7
7 4

View File

@ -0,0 +1,29 @@
# Test case 2 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
16
2 2
2 0
5 1
5 0
8 1
8 0
3 -1
3 -3
6 -2
6 -3
7 0
7 -2
-10 10
10 10
10 -10
-10 -10
10
0 1
2 3
4 5
6 7
8 9
10 11
12 13
13 14
14 15
15 12

View File

@ -0,0 +1,19 @@
# Test case 2 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8
-1 4
3 0
6 4
6 0
5 0
5 -4
1 0
-1 -4
8
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 0

View File

@ -0,0 +1,40 @@
# Test case 4 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
19
-1 3
0 3
0 2
3 3
1 1
3 0
4 0
5 0
4 -1
7 0
7 -4
2 -4
1 -2
2 0
-1 -4
-10 10
10 10
10 -10
-10 -10
18
0 1
1 2
1 3
3 4
3 5
5 6
7 8
7 9
9 10
10 11
11 12
12 13
11 14
14 0
15 16
16 17
17 18
18 15

View File

@ -0,0 +1,35 @@
# Test case 5 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
17
5 2
7 2
2 1
1 0
2 0
3 0
5 0
6 0
7 0
1 -2
2 -2
3 -2
4 -2
-10 10
10 10
10 -10
-10 -10
15
0 7
1 7
2 3
4 5
6 7
7 8
9 4
10 4
11 4
12 5
12 6
13 14
14 15
15 16
16 13

View File

@ -0,0 +1,20 @@
9
2 0
4 0
6 0
8 0
10 0
10 10
-10 10
-10 -10
10 -10
9
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 4

View File

@ -0,0 +1,35 @@
# Non-regularized visibility result of Test case 2 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
16
10 10
2 2
2 0
5 0
7 0
8 0
10 0
7 -2
10 -20/7
3 -1
6 -2
10 -10/3
3 -3
10 -10
-10 -10
-10 10
16
1 0
1 2
2 3
3 4
4 5
5 6
4 7
7 8
8 11
9 10
10 11
9 12
12 13
13 14
14 15
15 0

View File

@ -0,0 +1,15 @@
# Non-regularized visibility result of Test case 3 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
6
-1 4
-1 -4
1 0
3 0
5 0
6 0
6
0 1
1 2
2 3
3 4
4 5
0 3

View File

@ -0,0 +1,31 @@
# Non-regularized visibility result of Test case 4 for arbitrary arrangement. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
14
0 2
0 3
-1 3
-1 -4
2 -4
1 -2
2 0
3 0
4 0
5 0
7 0
10 0
3 3
1 1
14
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
7 12
12 13
1 12

View File

@ -0,0 +1,26 @@
12
1 0
2 0
3 0
5 0
6 0
1 -2
5 -10
-10 -10
-10 10
10 10
10 5
2 1
12
0 1
1 2
2 3
3 4
1 5
5 6
6 7
7 8
8 9
9 10
10 11
11 0

View File

@ -0,0 +1,12 @@
# Test case 1 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
4
0 0
8 0
8 8
0 8
4
0 1
1 2
2 3
3 0
4 4

View File

@ -0,0 +1,10 @@
4
0 0
8 0
8 8
0 8
4
0 1
1 2
2 3
3 0

View File

@ -0,0 +1,23 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8 2
8 2
0
7
0 0
14 0
14 7
7 7
6 4
6 2
0 2
0
7
0 0
14 0
14 7
7 7
6 4
6 2
0 2

View File

@ -0,0 +1,12 @@
# Test case 2 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
4
0 0
4 4
8 4
0 8
4
0 1
1 2
2 3
3 0
1 3

View File

@ -0,0 +1,10 @@
4
0 0
4 4
32/5 24/5
0 8
4
0 1
1 2
2 3
3 0

View File

@ -0,0 +1,20 @@
# Test case 2 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8
0 0
13 0
13 4
11 2
9 4
7 2
4 2
0 5
8
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 0
2 2

View File

@ -0,0 +1,17 @@
# Test case 2 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
7
0 0
13 0
13 2
11 2
7 2
4 2
0 5
7
0 1
1 2
2 3
3 4
4 5
5 6
6 0

View File

@ -0,0 +1,20 @@
# Test case 4 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8
0 0
4 0
8 3
12 0
12 3
8 6
4 3
0 3
8
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 0
2 3

View File

@ -0,0 +1,15 @@
# Test case 4 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
6
0 0
4 0
8 3
12 3
4 3
0 3
6
0 1
1 2
2 3
2 4
4 5
5 0

View File

@ -0,0 +1,29 @@
# Test case 1 for non-simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
2 2
2 2
0
10
0 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 5
0 5 0 0
4 0 9 2
9 2 11 0
0
8
0 0 4 0
4 0 9 2
9 2 11 2
11 2 13 2
7 2 9 2
7 2 4 2
4 2 0 5
0 5 0 0

View File

@ -0,0 +1,30 @@
# Test case 2 for non-simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
11 2
13 4
0
10
0 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 5
0 5 0 0
4 0 9 2
9 2 11 0
0
9
11 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 2
7 2 9 2
9 2 11 0

View File

@ -0,0 +1,17 @@
# Test case 1 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
4 4
4 4
0
4
0 0 8 0
8 0 8 8
8 8 0 8
0 8 0 0
0
4
0 0 8 0
8 0 8 8
8 8 0 8
0 8 0 0

View File

@ -0,0 +1,36 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8 8
9 10
0
18
0 0 3 2
3 2 5 1
5 1 8 1
8 1 16 2
16 2 16 5
16 5 14 4
14 4 12 7
12 7 10 4
10 4 8 4
8 4 10 8
10 8 9 10
9 10 8 8
8 8 6 8
6 8 7 6
7 6 1 6
1 6 4 8
4 8 0 9
0 9 0 0
0
9
7 6 6 8
6 8 8 8
8 8 9 10
9 10 10 8
10 8 8 4
8 4 8 1
8 1 5 1
5 1 23/5 6/5
23/5 6/5 7 6

View File

@ -0,0 +1,23 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8 2
8 2
0
7
0 0 14 0
14 0 14 7
14 7 7 7
7 7 6 4
6 4 6 2
6 2 0 2
0 2 0 0
0
7
0 0 14 0
14 0 14 7
14 7 7 7
7 7 6 4
6 4 6 2
6 2 0 2
0 2 0 0

View File

@ -0,0 +1,27 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
8 2
8 2
0
9
0 0 8 0
8 0 12 4
12 4 14 0
14 0 14 7
14 7 7 7
7 7 6 4
6 4 6 2
6 2 0 2
0 2 0 0
0
9
0 0 8 0
8 0 12 4
12 4 14 5
14 5 14 7
14 7 7 7
7 7 6 4
6 4 6 2
6 2 0 2
0 2 0 0

View File

@ -0,0 +1,26 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
5 2
5 2
0
11
0 0 12 0
12 0 12 4
12 4 8 7
8 7 11 9
11 9 11 12
11 12 6 9
6 9 0 12
0 12 0 10
0 10 8 5
8 5 0 5
0 5 0 0
0
6
0 0 12 0
12 0 12 4
12 4 64/7 43/7
64/7 43/7 8 5
8 5 0 5
0 5 0 0

View File

@ -0,0 +1,26 @@
# Test case 10 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
2 3
2 3
0
10
0 0 8 0
8 0 10 3
10 3 10 6
10 6 9 4
9 4 8 6
8 6 8 2
8 2 6 3
6 3 6 7
6 7 0 7
0 7 0 0
0
7
0 0 8 0
8 0 46/5 9/5
46/5 9/5 8 2
8 2 6 3
6 3 6 7
6 7 0 7
0 7 0 0

View File

@ -0,0 +1,21 @@
# Test case 15 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
5 4
5 4
0
6
0 0 8 0
8 0 8 8
8 8 3 8
3 8 3 4
3 4 0 6
0 6 0 0
0
6
0 0 8 0
8 0 8 8
8 8 3 8
3 8 3 4
3 4 0 4
0 4 0 0

View File

@ -0,0 +1,22 @@
# Test case 16 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
3 3
3 3
0
7
0 0 12 0
12 0 12 3
12 3 9 5
9 5 6 3
6 3 3 5
3 5 0 3
0 3 0 0
0
6
0 0 12 0
12 0 12 3
12 3 6 3
6 3 3 5
3 5 0 3
0 3 0 0

View File

@ -0,0 +1,24 @@
# Test case 17 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
2 3
2 3
0
8
0 0 12 0
12 0 12 3
12 3 9 5
9 5 6 3
6 3 4 3
4 3 2 6
2 6 0 3
0 3 0 0
0
7
0 0 12 0
12 0 12 3
12 3 6 3
6 3 4 3
4 3 2 6
2 6 0 3
0 3 0 0

View File

@ -0,0 +1,51 @@
0 0
0 0
0
37
20 0 20 20
20 20 -40 20
-40 20 -40 -40
-40 -40 40 -40
40 -40 40 40
40 40 -60 40
-60 40 -60 -60
-60 -60 60 -60
60 -60 60 60
60 60 -80 60
-80 60 -80 -80
-80 -80 80 -80
80 -80 80 80
80 80 -100 80
-100 80 -100 -100
-100 -100 100 -100
100 -100 100 100
100 100 90 100
90 100 90 -90
90 -90 -90 -90
-90 -90 -90 70
-90 70 70 70
70 70 70 -70
70 -70 -70 -70
-70 -70 -70 50
-70 50 50 50
50 50 50 -50
50 -50 -50 -50
-50 -50 -50 30
-50 30 30 30
30 30 30 -30
30 -30 -30 -30
-30 -30 -30 10
-30 10 -10 10
-10 10 -10 -10
-10 -10 20 -10
20 -10 20 0
0
6
-10 -10 20 -10
20 -10 20 0
20 0 20 20
20 20 -20 20
-20 20 -10 10
-10 10 -10 -10

View File

@ -0,0 +1,51 @@
0 0
0 0
0
38
-10 -10 10 -10
10 -10 10 10
10 10 20 10
20 10 20 -20
20 -20 -20 -20
-20 -20 -20 30
-20 30 40 30
40 30 40 -40
40 -40 -40 -40
-40 -40 -40 50
-40 50 60 50
60 50 60 -60
60 -60 -60 -60
-60 -60 -60 70
-60 70 80 70
80 70 80 -80
80 -80 -80 -80
-80 -80 -80 90
-80 90 100 90
100 90 100 100
100 100 -90 100
-90 100 -90 -90
-90 -90 90 -90
90 -90 90 80
90 80 -70 80
-70 80 -70 -70
-70 -70 70 -70
70 -70 70 60
70 60 -50 60
-50 60 -50 -50
-50 -50 50 -50
50 -50 50 40
50 40 -30 40
-30 40 -30 -30
-30 -30 30 -30
30 -30 30 20
30 20 -10 20
-10 20 -10 -10
0
5
-10 20 -10 -10
-10 -10 10 -10
10 -10 10 10
10 10 20 20
20 20 -10 20

View File

@ -0,0 +1,17 @@
# Test case 2 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
1 3
1 3
0
4
0 0 4 4
4 4 8 4
8 4 0 8
0 8 0 0
0
4
0 0 4 4
4 4 32/5 24/5
32/5 24/5 0 8
0 8 0 0

View File

@ -0,0 +1,39 @@
0 0
0 0
0
24
0 -40 80 -40
80 -40 100 0
100 0 120 -50
120 -50 -60 -50
-60 -50 -60 50
-60 50 40 50
40 50 40 -10
40 -10 45 -10
45 -10 45 10
45 10 50 10
50 10 50 -10
50 -10 55 -10
55 -10 55 70
55 70 -80 70
-80 70 -80 -80
-80 -80 150 -80
150 -80 150 20
150 20 65 20
65 20 65 -15
65 -15 35 -15
35 -15 35 10
35 10 -20 10
-20 10 -20 -30
-20 -30 0 -40
0
7
35 10 -20 10
-20 10 -20 -30
-20 -30 0 -40
0 -40 80 -40
80 -40 1400/17 -600/17
1400/17 -600/17 35 -15
35 -15 35 10

View File

@ -0,0 +1,43 @@
80 0
80 0
0
23
100 0 100 20
100 20 108 23
108 23 100 50
100 50 80 60
80 60 100 70
100 70 110 70
110 70 110 -100
110 -100 80 -100
80 -100 120 -130
120 -130 120 100
120 100 -40 100
-40 100 -40 -20
-40 -20 -20 -20
-20 -20 -20 0
-20 0 -10 -30
-10 -30 -60 -30
-60 -30 -60 0
-60 0 -70 -10
-70 -10 -70 0
-70 0 -80 10
-80 10 -80 -40
-80 -40 90 -40
90 -40 100 0
0
12
-10 -30 -40 -40
-40 -40 90 -40
90 -40 100 0
100 0 100 20
100 20 748/7 188/7
748/7 188/7 100 50
100 50 80 60
80 60 80 100
80 100 -40 100
-40 100 -40 0
-40 0 -20 0
-20 0 -10 -30

View File

@ -0,0 +1,19 @@
0.5 2
0.5 2
0
6
0 4 0 0
0 0 3 2
3 2 4 0
4 0 4 4
4 4 1 2
1 2 0 4
0
5
0 4 0 0
0 0 3 2
3 2 4 2
3 2 1 2
1 2 0 4

View File

@ -0,0 +1,26 @@
# Test case 3 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
2 2
2 2
0
8
0 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 5
0 5 0 0
0
7
0 0 13 0
13 0 13 2
13 2 11 2
11 2 7 2
7 2 4 2
4 2 0 5
0 5 0 0

View File

@ -0,0 +1,42 @@
# Test case 4 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
6 4
6 4
0
18
0 0 3 2
3 2 5 1
5 1 8 1
8 1 16 2
16 2 16 5
16 5 14 4
14 4 12 7
12 7 10 4
10 4 8 4
8 4 10 8
10 8 9 10
9 10 8 8
8 8 6 8
6 8 7 6
7 6 1 6
1 6 4 8
4 8 0 9
0 9 0 0
0
15
0 0 3 2
3 2 5 1
5 1 8 1
8 1 16 2
16 2 16 4
16 4 14 4
14 4 10 4
10 4 8 4
8 4 10 8
10 8 9 10
9 10 8 8
8 8 7 6
7 6 1 6
1 6 0 32/5
0 32/5 0 0

View File

@ -0,0 +1,37 @@
# Test case 5 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
5 2
5 2
0
20
0 0 12 0
12 0 12 2
12 2 9 2
9 2 9 4
9 4 16 4
16 4 16 0
16 0 20 0
20 0 20 12
20 12 0 12
0 12 0 8
0 8 15 8
15 8 15 9
15 9 1 9
1 9 1 11
1 11 19 11
19 11 19 1
19 1 17 1
17 1 17 6
17 6 0 6
0 6 0 0
0
7
0 0 12 0
12 0 12 2
12 2 9 2
9 2 9 4
9 4 13 6
13 6 0 6
0 6 0 0

View File

@ -0,0 +1,25 @@
# Test case 6 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
1 2
1 2
0
9
0 0 0 4
0 4 2 4
2 4 3 2
3 2 4 4
4 4 5 4
5 4 5 0
5 0 4 2
4 2 3 0
3 0 0 0
0
7
0 0 0 4
0 4 2 4
2 4 3 2
3 2 4 2
4 2 5 2
4 2 3 0
3 0 0 0

View File

@ -0,0 +1,39 @@
# Test case 6 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
1 2
1 2
0
18
0 0 0 4
0 4 2 4
2 4 3 2
3 2 4 4
4 4 5 2
5 2 6 2
6 2 6 4
6 4 11 4
11 4 11 0
11 0 10 2
10 2 9 0
9 0 9 2
9 2 7 2
7 2 7 0
7 0 5 0
5 0 4 2
4 2 3 0
3 0 0 0
0
12
0 0 0 4
0 4 2 4
2 4 3 2
3 2 4 2
4 2 5 2
5 2 6 2
6 2 7 2
7 2 9 2
9 2 10 2
10 2 11 2
4 2 3 0
3 0 0 0

View File

@ -0,0 +1,26 @@
# Test case 8 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
5 2
7 2
0
8
0 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 5
0 5 0 0
0
7
0 0 13 0
13 0 13 2
13 2 11 2
11 2 7 2
7 2 4 2
4 2 0 2
0 2 0 0

View File

@ -0,0 +1,24 @@
# Test case 9 for simple polygons. See https://cgal.geometryfactory.com/CGAL/Members/wiki/Visibility/TestCases
9 4
11 2
0
8
0 0 13 0
13 0 13 4
13 4 11 2
11 2 9 4
9 4 7 2
7 2 4 2
4 2 0 5
0 5 0 0
0
5
13 0 11 2
11 2 9 4
9 4 7 2
7 2 5 0
5 0 13 0

View File

@ -0,0 +1,165 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
#ifndef CGAL_TEST_MODEL_METHODS_H
#define CGAL_TEST_MODEL_METHODS_H
#include <CGAL/basic.h>
#include <CGAL/test_utils.h>
#include <cassert>
#include <vector>
namespace CGAL {
template <class Visibility_2, class Visibility_arrangement_2>
void test_model_methods_for_arr(
typename Visibility_2::Arrangement_2 &arr) {
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
typedef typename Arrangement_2::Point_2 Point_2;
typedef typename Visibility_arrangement_2::Face_handle VFH;
Visibility_2 visibility;
assert(false == visibility.is_attached());
visibility.attach(arr);
assert(true == visibility.is_attached());
assert(true == (CGAL::test_are_equal(arr,visibility.arrangement_2())));
Visibility_arrangement_2 arr_out;
Visibility_arrangement_2 arr_out_check;
typename Arrangement_2::Face_const_iterator fit;
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) {
if (!fit->is_unbounded()) {
break;
}
}
// First consider query point in the unbounded face
const Point_2 query_pt(1, 1);
// Check returned face_handle
VFH face_check = visibility.compute_visibility(query_pt, fit, arr_out);
VFH face;
if (arr_out.faces_begin()->is_unbounded()) {
face = ++arr_out.faces_begin();
}
else {
face = arr_out.faces_begin();
}
assert(face_check == face);
assert((true == test_are_equal<Arrangement_2, Visibility_arrangement_2>
(arr, arr_out)));
visibility.detach();
assert(false == visibility.is_attached());
visibility.attach(arr);
visibility.compute_visibility(query_pt, fit, arr_out_check);
assert((true == test_are_equal<Visibility_arrangement_2, Arrangement_2>
(arr_out_check, arr)));
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
(arr_out, arr_out_check)));
arr_out.clear();
visibility.compute_visibility(query_pt, fit, arr_out);
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
(arr_out, arr_out_check)));
// Now consider the query point on a halfedge
const Point_2 query_pt2 = Point_2(0, 4);
arr_out.clear();
typename Arrangement_2::Halfedge_const_iterator hit;
VFH face_check_he;
for (hit = arr.halfedges_begin();
hit != arr.halfedges_end(); ++hit) {
if (hit->source()->point() == Point_2(0, 8) && hit->target()->point() == Point_2(0, 0)) {
face_check_he = visibility.compute_visibility(query_pt2, hit, arr_out);
break;
}
}
if (arr_out.faces_begin()->is_unbounded()) {
face = ++arr_out.faces_begin();
}
else {
face = arr_out.faces_begin();
}
assert(face_check_he == face);
assert((true == test_are_equal(arr_out, arr)));
arr_out_check.clear();
visibility.compute_visibility(query_pt2, hit, arr_out_check);
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
(arr_out, arr_out_check)));
// Now consider the query point as the target of a halfedge
typename Arrangement_2::Halfedge_const_iterator hit_snd;
for (hit_snd = arr.halfedges_begin(); hit_snd != arr.halfedges_end(); ++hit_snd) {
if(!hit_snd->face()->is_unbounded()){
arr_out.clear();
VFH face_check_he_snd = visibility.compute_visibility(hit_snd->target()->point(), hit_snd, arr_out);
assert(!face_check_he_snd->is_unbounded());
if (arr_out.faces_begin()->is_unbounded()) {
face = ++arr_out.faces_begin();
}
else {
face = arr_out.faces_begin();
}
assert(face_check_he_snd == face);
if (! test_are_equal(arr_out, arr)) {
assert(false);
}
}
}
}
template <class Visibility_2, class Visibility_arrangement_2>
void test_model_methods() {
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
typedef typename Arrangement_2::Point_2 Point_2;
typedef typename Arrangement_2::Geometry_traits_2::Segment_2 Segment_2;
Point_2 p1(0, 0), p2(8, 0), p3(8, 8), p4(0, 8);
std::vector<Segment_2> seg_sq;
seg_sq.push_back(Segment_2(p1, p2));
seg_sq.push_back(Segment_2(p2, p3));
seg_sq.push_back(Segment_2(p3, p4));
seg_sq.push_back(Segment_2(p4, p1));
Arrangement_2 arr_square;
CGAL::insert(arr_square, seg_sq.begin(), seg_sq.end());
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_square);
std::vector<Segment_2> seg_tri;
seg_tri.push_back(Segment_2(p1, p2));
seg_tri.push_back(Segment_2(p2, p4));
seg_tri.push_back(Segment_2(p4, p1));
Arrangement_2 arr_triangle;
CGAL::insert(arr_triangle, seg_tri.begin(), seg_tri.end());
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_triangle);
}
} // end CGAL namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
// Kan Huang <huangkandiy@gmail.com
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/Rotational_sweep_visibility_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <iostream>
#include <fstream>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef Traits_2::Point_2 Point_2;
typedef Traits_2::X_monotone_curve_2 Segment_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
template <class Visibility>
void deploy_pure_benchmark(const CGAL::Query_choice& qchoice, std::ifstream& input) {
Visibility v;
CGAL::pure_benchmark<Visibility>
(v, qchoice, input);
}
template <class Regularization_category>
void benchmark_one_class(std::string name, const CGAL::Query_choice& qchoice, std::string input_arr_file) {
std::ifstream input(input_arr_file.c_str());
if (name == "S")
deploy_pure_benchmark<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
if (name == "T")
deploy_pure_benchmark<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
if (name == "R")
deploy_pure_benchmark<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
}
void print_usage() {
std::cout << "Usage: ./pure_benchmark [filename] [Class type] [Query type] [Regularize]\n";
std::cout << "where [Class type] could be S(simple), R(rotational sweep), and T(triangular), indicating which class you want to test.\n";
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
std::cout << "[Regularize] can be: {true, false}.\n";
}
int main(int argc, char* argv[]) {
CGAL::Query_choice qchoice = CGAL::FACE;
std::string regularization_tag("true");
if (argc > 1) {
std::string input_arr_file(argv[1]);
if (argc == 2) {
std::cout << "NAME TAG PreProTime NQueries TimeQueries TotalTime QAVE TAVE" << std::endl;
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::FACE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::FACE, input_arr_file);
std::cout << std::endl;
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::FACE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::FACE, input_arr_file);
std::cout << std::endl;
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::FACE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::FACE, input_arr_file);
std::cout << std::endl;
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::FACE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::VERTEX, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::EDGE, input_arr_file);
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::FACE, input_arr_file);
} else if (argc == 5) {
qchoice = CGAL::FACE;
std::string query_type(argv[3]);
if (query_type == "vertex")
qchoice = CGAL::VERTEX;
else if (query_type == "edge")
qchoice = CGAL::EDGE;
else if (query_type == "face")
qchoice = CGAL::FACE;
else {
std::cout<<"query type is not matched.\n";
return 0;
}
regularization_tag = argv[4];
std::string classname(argv[2]);
if (regularization_tag == "true") {
benchmark_one_class<CGAL::Tag_true>(classname, qchoice, input_arr_file);
}
else {
benchmark_one_class<CGAL::Tag_false>(classname, qchoice, input_arr_file);
}
return 0;
}
else {
print_usage();
exit(0);
}
}
else {
print_usage();
exit(0);
}
return 0;
}

View File

@ -0,0 +1,15 @@
#!/bin/sh
# Author: Francisc Bungiu
# E-mail: fbungiu@gmail.com
for file in *
do
if ! [[ -d $file ]]
then
if [[ -x $file ]]
then
echo "Executing '$file'..."
./$file
fi
fi
done

View File

@ -0,0 +1,124 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
// Kan Huang <huangkandiy@gmail.com>
// Ning Xu <longyin0904@gmail.com>
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/Rotational_sweep_visibility_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <iostream>
#include <fstream>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef Traits_2::Point_2 Point_2;
typedef Traits_2::X_monotone_curve_2 Segment_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
template <class Visibility_fst, class Visibility_snd>
void deploy_benchmark(CGAL::Query_choice& qchoice, std::ifstream& input) {
Visibility_fst v1;
Visibility_snd v2;
CGAL::simple_benchmark<Visibility_fst, Visibility_snd>
(v1, v2, qchoice, input);
}
template <class Visibility_fst, class Regularization_category>
void define_snd_class(std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input){
if (name2 == "S")
deploy_benchmark<Visibility_fst, CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category> >
(qchoice, input);
if (name2 == "T")
deploy_benchmark<Visibility_fst, CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category> >
(qchoice, input);
if (name2 == "R")
deploy_benchmark<Visibility_fst, CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category> >
(qchoice, input);
}
template <class Regularization_category>
void benchmark_two_classes(std::string name1, std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input) {
if (name1 == "S")
define_snd_class<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
if (name1 == "T")
define_snd_class<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
if (name1 == "R")
define_snd_class<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
}
void print_usage() {
std::cout << "Usage: ./simple_benchmark [filename] [Class type 1] [Class type 2] [Query type] [Regularize]\n";
std::cout << "where [Class type] could be S(simple), R(rotational sweep) and T(triangular), indicating which classes you want to test.\n";
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
std::cout << "[Regularize] can be: {true, false}.\n";
}
int main(int argc, char* argv[]) {
CGAL::Query_choice qchoice = CGAL::FACE;
std::string regularization_tag("true");
if (argc > 1) {
std::string input_arr_file(argv[1]);
std::ifstream input(input_arr_file.c_str());
if (argc == 6) {
qchoice = CGAL::FACE;
std::string query_type(argv[4]);
if (query_type == "vertex")
qchoice = CGAL::VERTEX;
else if (query_type == "edge")
qchoice = CGAL::EDGE;
else if (query_type == "face")
qchoice = CGAL::FACE;
else {
std::cout<<"query type is not matched.\n";
return 0;
}
regularization_tag = argv[5];
std::string class1(argv[2]), class2(argv[3]);
if (regularization_tag == "true") {
benchmark_two_classes<CGAL::Tag_true>(class1, class2, qchoice, input);
}
else {
benchmark_two_classes<CGAL::Tag_false>(class1, class2, qchoice, input);
}
return 0;
}
else {
print_usage();
exit(0);
}
}
else {
print_usage();
exit(0);
}
return 0;
}

View File

@ -0,0 +1,93 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Kan Huang <huangkandiy@gmail.com>
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_rational.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <CGAL/Rotational_sweep_visibility_2.h>
#include <CGAL/Arr_extended_dcel.h>
#include <iostream>
#include <fstream>
int main() {
{
typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
{
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
RSV;
CGAL::test_model_methods<RSV,Arrangement_2>();
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
}
{
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
RSV;
CGAL::test_model_methods<RSV,Arrangement_2>();
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
}
}{
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
{
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
RSV;
CGAL::test_model_methods<RSV,Arrangement_2>();
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
}
{
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
RSV;
CGAL::test_model_methods<RSV,Arrangement_2>();
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
}
}
{
// test Visibility_arrangement_type with extended DCEL
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> ARR;
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
{
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}{
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}
}
return 0;
}

View File

@ -0,0 +1,84 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_rational.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Arr_extended_dcel.h>
#include <iostream>
#include <fstream>
int main() {
{
typedef CGAL::Exact_rational Number_type;
typedef CGAL::Cartesian<Number_type> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef CGAL::Simple_polygon_visibility_2<
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
std::cout << "Running model tests - ";
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
std::cout << GREEN << "Done!" << RESET << std::endl;
std::cout << "Running test suite with " << GREEN
<< "Cartesian" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(22, 0);
}
{
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef CGAL::Simple_polygon_visibility_2<
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
std::cout << "Running model tests - ";
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
std::cout << GREEN << "Done!" << RESET << std::endl;
std::cout << "Running test suite with " << GREEN
<< "EPECK" << RESET << " Kernel..." << std::endl;
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(22, 0);
}
{
// test Visibility_arrangement_type with extended DCEL
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> ARR;
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
{
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}{
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}
}
return 0;
}

View File

@ -0,0 +1,126 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Kan Huang <huangkandiy@gmail.com>
// Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_rational.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <iostream>
#include <fstream>
int main(int argc, char* argv[]) {
{
typedef CGAL::Exact_rational Number_type;
typedef CGAL::Cartesian<Number_type> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef CGAL::Simple_polygon_visibility_2<
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_false>
Triangular_expansion_visibility_2;
if (argc == 2) {
Simple_polygon_visibility_2 simple_visibility;
const CGAL::Query_choice qchoice = CGAL::FACE;
std::string input_arr_file(argv[1]);
std::ifstream input(input_arr_file.c_str());
CGAL::test_star_shape<Simple_polygon_visibility_2>
(simple_visibility, qchoice, input);
return 0;
}
if (argc == 3) {
const CGAL::Query_choice qchoice = CGAL::FACE;
std::string input_arr_file(argv[1]);
std::ifstream input(input_arr_file.c_str());
std::string class_name(argv[2]);
if ( class_name == "simple") {
Simple_polygon_visibility_2 simple_visibility;
CGAL::test_star_shape<Simple_polygon_visibility_2>
(simple_visibility, qchoice, input);
return 0;
}
if (class_name == "triangular") {
Triangular_expansion_visibility_2 triangular_visibility;
CGAL::test_star_shape<Triangular_expansion_visibility_2>
(triangular_visibility, qchoice, input);
return 0;
}
std::cout<<"no type is matched.\n";
return 0;
}
if (argc == 4) {
std::string input_arr_file(argv[1]);
std::ifstream input(input_arr_file.c_str());
CGAL::Query_choice qchoice;
std::string query_type(argv[3]);
if (query_type == "vertex")
qchoice = CGAL::VERTEX;
else {
if (query_type == "edge")
qchoice = CGAL::EDGE;
else {
if (query_type == "face")
qchoice = CGAL::FACE;
else {
std::cout<<"query type is not matched.\n";
return 0;
}
}
}
std::string class_name(argv[2]);
if (class_name == "simple") {
Simple_polygon_visibility_2 simple_visibility;
CGAL::test_star_shape<Simple_polygon_visibility_2>
(simple_visibility, qchoice, input);
return 0;
}
if (class_name == "triangular") {
Triangular_expansion_visibility_2 triangular_visibility;
CGAL::test_star_shape<Triangular_expansion_visibility_2>
(triangular_visibility, qchoice, input);
return 0;
}
std::cout<<"no type is matched.\n";
return 0;
}
std::cout << "Usage: ./test_star_shape [filename] [Class type] [Query type]\n";
std::cout << "where [Class type] could be simple, naive and triangular, indicating which class you want to test.\n";
std::cout << "[Query type] could be vertex, edge, face.\n";
std::cout << "The default value of [Query type] is face. The default value of [Class type] is simple.\n";
exit(0);
}
}

View File

@ -0,0 +1,91 @@
// Copyright (c) 2013 Technical University Braunschweig (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
#include <CGAL/basic.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_rational.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/test_model_methods.h>
#include <CGAL/test_utils.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/Arr_extended_dcel.h>
#include <iostream>
#include <fstream>
int main() {
{
typedef CGAL::Exact_rational Number_type;
typedef CGAL::Cartesian<Number_type> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
{
typedef CGAL::Triangular_expansion_visibility_2<
Arrangement_2 , CGAL::Tag_true> Visibility_2;
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
}
{
typedef CGAL::Triangular_expansion_visibility_2<
Arrangement_2 , CGAL::Tag_false> Visibility_2;
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
}
}
{
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
{
typedef CGAL::Triangular_expansion_visibility_2<
Arrangement_2 , CGAL::Tag_true> Visibility_2;
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
}{
typedef CGAL::Triangular_expansion_visibility_2<
Arrangement_2 , CGAL::Tag_false> Visibility_2;
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
}
}
{
// test Visibility_arrangement_type with extended DCEL
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> ARR;
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
{
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}{
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
CGAL::test_model_methods<Visibility_2,EARR>();
CGAL::run_tests<Visibility_2,EARR>(22, 2);
}
}
return 0;
}