diff --git a/Documentation/biblio/cgal_manual.bib b/Documentation/biblio/cgal_manual.bib
index 279aa623f6e..8202e049b5f 100644
--- a/Documentation/biblio/cgal_manual.bib
+++ b/Documentation/biblio/cgal_manual.bib
@@ -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
% ----------------------------------------------------------------------------
diff --git a/Documentation/biblio/geom.bib b/Documentation/biblio/geom.bib
index 49ae3a088f5..8cf6f98f004 100644
--- a/Documentation/biblio/geom.bib
+++ b/Documentation/biblio/geom.bib
@@ -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"
diff --git a/Documentation/doc/Documentation/Doxyfile.in b/Documentation/doc/Documentation/Doxyfile.in
index 643393a4c6c..66760ff79b8 100644
--- a/Documentation/doc/Documentation/Doxyfile.in
+++ b/Documentation/doc/Documentation/Doxyfile.in
@@ -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 \
diff --git a/Documentation/doc/Documentation/dependencies b/Documentation/doc/Documentation/dependencies
index 79184ef9136..253d1770edd 100644
--- a/Documentation/doc/Documentation/dependencies
+++ b/Documentation/doc/Documentation/dependencies
@@ -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
diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt
index 8d54a9ba957..0288a085228 100644
--- a/Documentation/doc/Documentation/packages.txt
+++ b/Documentation/doc/Documentation/packages.txt
@@ -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
diff --git a/Installation/changes.html b/Installation/changes.html
index b6da5cd32f0..f0d18f07171 100644
--- a/Installation/changes.html
+++ b/Installation/changes.html
@@ -245,6 +245,21 @@ and src/ directories).
+
Release 4.7
+
+
Release date: October 2015
+
+
+
+
2D Visibility (new package)
+
+
This package provides several variants to compute the visibility
+ area of a point within polygonal regions in two dimensions.
+
+
+
+
+
Release 4.6
Release date: April 2015
diff --git a/Visibility_2/doc/OLD/ArrExtensionTraits_2.h b/Visibility_2/doc/OLD/ArrExtensionTraits_2.h
new file mode 100644
index 00000000000..333689eeab5
--- /dev/null
+++ b/Visibility_2/doc/OLD/ArrExtensionTraits_2.h
@@ -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`
+
+\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();
+
+/// @}
+
+
+}
+
diff --git a/Visibility_2/doc/OLD/Arr_extension_default_traits_2.h b/Visibility_2/doc/OLD/Arr_extension_default_traits_2.h
new file mode 100644
index 00000000000..40d8baa9328
--- /dev/null
+++ b/Visibility_2/doc/OLD/Arr_extension_default_traits_2.h
@@ -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 */
diff --git a/Visibility_2/doc/OLD/Preprocessed_rotational_sweep_visibility_2.h b/Visibility_2/doc/OLD/Preprocessed_rotational_sweep_visibility_2.h
new file mode 100644
index 00000000000..3f80ec8e27c
--- /dev/null
+++ b/Visibility_2/doc/OLD/Preprocessed_rotational_sweep_visibility_2.h
@@ -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`
+\sa `CGAL::Rotational_sweep_visibility_2`
+\sa `CGAL::Triangular_expansion_visibility_2`
+
+
+*/
+template
+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 */
diff --git a/Visibility_2/doc/Visibility_2/CGAL/Rotational_sweep_visibility_2.h b/Visibility_2/doc/Visibility_2/CGAL/Rotational_sweep_visibility_2.h
new file mode 100644
index 00000000000..8a384730b7d
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/CGAL/Rotational_sweep_visibility_2.h
@@ -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
+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 */
+}
diff --git a/Visibility_2/doc/Visibility_2/CGAL/Simple_polygon_visibility_2.h b/Visibility_2/doc/Visibility_2/CGAL/Simple_polygon_visibility_2.h
new file mode 100644
index 00000000000..22095c24516
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/CGAL/Simple_polygon_visibility_2.h
@@ -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
+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 */
+}
diff --git a/Visibility_2/doc/Visibility_2/CGAL/Triangular_expansion_visibility_2.h b/Visibility_2/doc/Visibility_2/CGAL/Triangular_expansion_visibility_2.h
new file mode 100644
index 00000000000..6a8b5fcccf8
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/CGAL/Triangular_expansion_visibility_2.h
@@ -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
+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 */
diff --git a/Visibility_2/doc/Visibility_2/Concepts/Visibility_2.h b/Visibility_2/doc/Visibility_2/Concepts/Visibility_2.h
new file mode 100644
index 00000000000..cc7f935ee2f
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/Concepts/Visibility_2.h
@@ -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 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 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 */
+
diff --git a/Visibility_2/doc/Visibility_2/Doxyfile.in b/Visibility_2/doc/Visibility_2/Doxyfile.in
new file mode 100644
index 00000000000..963b8c7f059
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/Doxyfile.in
@@ -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/
+
+
+
diff --git a/Visibility_2/doc/Visibility_2/PackageDescription.txt b/Visibility_2/doc/Visibility_2/PackageDescription.txt
new file mode 100644
index 00000000000..f45f3bc7291
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/PackageDescription.txt
@@ -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`
+- `CGAL::Rotational_sweep_visibility_2`
+- `CGAL::Triangular_expansion_visibility_2`
+*/
diff --git a/Visibility_2/doc/Visibility_2/dependencies b/Visibility_2/doc/Visibility_2/dependencies
new file mode 100644
index 00000000000..9f04c30e0c4
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/dependencies
@@ -0,0 +1,8 @@
+Manual
+Kernel_23
+STL_Extension
+Algebraic_foundations
+Circulator
+Stream_support
+Arrangement_on_surface_2
+Boolean_set_operations_2
diff --git a/Visibility_2/doc/Visibility_2/examples.txt b/Visibility_2/doc/Visibility_2/examples.txt
new file mode 100644
index 00000000000..72d4164844c
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/examples.txt
@@ -0,0 +1,4 @@
+/*!
+\example Visibility_2/simple_polygon_visibility_2.cpp
+\example Visibility_2/general_polygon_example.cpp
+*/
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral-simple.png b/Visibility_2/doc/Visibility_2/fig/cathedral-simple.png
new file mode 100644
index 00000000000..b4802ebd24e
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/cathedral-simple.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral-simple.svg b/Visibility_2/doc/Visibility_2/fig/cathedral-simple.svg
new file mode 100644
index 00000000000..0e2617f1652
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/fig/cathedral-simple.svg
@@ -0,0 +1,2354 @@
+
+
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral.png b/Visibility_2/doc/Visibility_2/fig/cathedral.png
new file mode 100644
index 00000000000..349af7a7447
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/cathedral.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral.svg b/Visibility_2/doc/Visibility_2/fig/cathedral.svg
new file mode 100644
index 00000000000..263029df7e6
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/fig/cathedral.svg
@@ -0,0 +1,4705 @@
+
+
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral_2.png b/Visibility_2/doc/Visibility_2/fig/cathedral_2.png
new file mode 100644
index 00000000000..e1bcaa9852b
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/cathedral_2.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/cathedral_2.svg b/Visibility_2/doc/Visibility_2/fig/cathedral_2.svg
new file mode 100644
index 00000000000..531568c6ecc
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/fig/cathedral_2.svg
@@ -0,0 +1,8690 @@
+
+
diff --git a/Visibility_2/doc/Visibility_2/fig/definition.png b/Visibility_2/doc/Visibility_2/fig/definition.png
new file mode 100644
index 00000000000..99f6af6a37c
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/definition.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/example1.png b/Visibility_2/doc/Visibility_2/fig/example1.png
new file mode 100644
index 00000000000..e5eeb1f1775
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/example1.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/general_polygon_example.png b/Visibility_2/doc/Visibility_2/fig/general_polygon_example.png
new file mode 100644
index 00000000000..2f06e9a7b74
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/general_polygon_example.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/simple_example.png b/Visibility_2/doc/Visibility_2/fig/simple_example.png
new file mode 100644
index 00000000000..90e1348363b
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/simple_example.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/visibility-teaser-thumbnail.png b/Visibility_2/doc/Visibility_2/fig/visibility-teaser-thumbnail.png
new file mode 100644
index 00000000000..1efe7bd5b24
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/visibility-teaser-thumbnail.png differ
diff --git a/Visibility_2/doc/Visibility_2/fig/visibility-teaser.png b/Visibility_2/doc/Visibility_2/fig/visibility-teaser.png
new file mode 100644
index 00000000000..fff644acee3
Binary files /dev/null and b/Visibility_2/doc/Visibility_2/fig/visibility-teaser.png differ
diff --git a/Visibility_2/doc/Visibility_2/visibility_2.txt b/Visibility_2/doc/Visibility_2/visibility_2.txt
new file mode 100644
index 00000000000..3e6ba84946c
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/visibility_2.txt
@@ -0,0 +1,162 @@
+namespace CGAL {
+
+/*!
+\mainpage User Manual
+\anchor Chapter_2D_Visibility_Computation
+\cgalAutoToc
+
+\authors Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu
+
+
+
+\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:
+
+
+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
+
+
+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.
+
+
+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 |
+
+
+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.
+
+
+Complete Cathedral | total preprocessing time | total query time |
+-------------------------------|-----------------------------------------------------|-------------------------------|
+ `Rotational_sweep_visibility_2` | - | 1.91 |
+ `Triangular_expansion_visibility_2` | 0.01 | 0.04 |
+
+
+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
diff --git a/Visibility_2/examples/Visibility_2/general_polygon_example.cpp b/Visibility_2/examples/Visibility_2/general_polygon_example.cpp
new file mode 100644
index 00000000000..d1e231a8422
--- /dev/null
+++ b/Visibility_2/examples/Visibility_2/general_polygon_example.cpp
@@ -0,0 +1,67 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+// 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 Traits_2;
+typedef CGAL::Arrangement_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 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 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;
+}
diff --git a/Visibility_2/examples/Visibility_2/simple_polygon_visibility_2.cpp b/Visibility_2/examples/Visibility_2/simple_polygon_visibility_2.cpp
new file mode 100644
index 00000000000..e0aa3cf9683
--- /dev/null
+++ b/Visibility_2/examples/Visibility_2/simple_polygon_visibility_2.cpp
@@ -0,0 +1,74 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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 Traits_2;
+typedef CGAL::Arrangement_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 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 pl(env);
+ CGAL::Arr_point_location_result::Type obj = pl.locate(q);
+ // The query point locates in the interior of a face
+ face = boost::get (&obj);
+
+ // compute non regularized visibility area
+ // Define visibiliy object type that computes non-regularized visibility area
+ typedef CGAL::Simple_polygon_visibility_2 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 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;
+}
+
diff --git a/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h
new file mode 100644
index 00000000000..b73060ab28c
--- /dev/null
+++ b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h
@@ -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
+//
+
+#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
+#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
+
+#include
+#include
+#include
+#include
+#include
+
+
+namespace CGAL {
+
+template
+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 Points;
+ typedef Vertex_const_handle VH;
+ typedef std::vector VHs;
+ typedef Halfedge_const_handle EH;
+ typedef std::vector EHs;
+
+ class Less_edge: public std::binary_function {
+ 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 {
+ 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 {
+ 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 incident_edges;
+
+ mutable std::map edx; //index of active edges in
+ //the heap
+
+ mutable std::set 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::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
+ (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
+ (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::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
+ (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; lpoint(), 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(Closer_edge(geom_traits, q));
+ incident_edges = std::map(Less_vertex(geom_traits));
+ edx = std::map(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<(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() <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(&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 {
+ 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; ipoint());
+ }
+ 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
+
+
diff --git a/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h b/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h
new file mode 100644
index 00000000000..ddd229f67bb
--- /dev/null
+++ b/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h
@@ -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
+// Michael Hemmer
+// Ning Xu
+
+#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
+#define CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// TODO:
+// * fix handle needles = O(nlogn)
+
+namespace CGAL {
+
+ template
+ 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::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::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 Arr_point_location;
+ typedef typename Arr_point_location::result_type Location_result;
+
+ typedef std::vector 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 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::Face_handle
+ output(const Point_2& q, VARR& out_arr) const {
+
+ if(inserted_artificial_starting_vertex)
+ stack.pop();
+
+ std::vector 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::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 segments;
+
+ for(typename std::vector::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(&(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(&(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(&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(&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(&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(&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( &result );
+ if ( ipoint ) {
+ u = *ipoint;
+ } else {
+ u = vertices[k+1];
+ }
+ return k;
+ }
+ };
+
+} // namespace CGAL
+#endif
diff --git a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h
new file mode 100644
index 00000000000..4a7ba9a9ca3
--- /dev/null
+++ b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h
@@ -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
+//
+
+#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
+#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
+
+#include
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+template
+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 Vb;
+ typedef CGAL::Constrained_triangulation_face_base_2 Fb;
+ typedef CGAL::Triangulation_data_structure_2 TDS;
+ typedef CGAL::No_intersection_tag Itag;
+ typedef CGAL::Constrained_Delaunay_triangulation_2 CDT;
+
+ typedef std::pair 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
+ {
+
+ typedef Arr_observer Base;
+ typedef Observer Self;
+
+
+ public:
+ bool has_changed;
+
+ Observer() : Base(), has_changed(false)
+ {}
+
+ Observer(const Arrangement_2& arr)
+ : Base(const_cast(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 p_cdt;
+ mutable std::vector 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(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::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 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::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 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(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" <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 <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 <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() <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
+ 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::Face_handle
+ output(std::vector& raw_output, VARR& out_arr) const {
+
+ if(!needles.empty()){
+ std::vector 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<< "==============" < 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(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
diff --git a/Visibility_2/include/CGAL/Visibility_2/visibility_utils.h b/Visibility_2/include/CGAL/Visibility_2/visibility_utils.h
new file mode 100644
index 00000000000..e787cc551b2
--- /dev/null
+++ b/Visibility_2/include/CGAL/Visibility_2/visibility_utils.h
@@ -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
+// Michael Hemmer
+
+#ifndef CGAL_VISIBILITY_UTILS_H
+#define CGAL_VISIBILITY_UTILS_H
+
+#include
+#include
+#include
+
+namespace CGAL {
+namespace Visibility_2 {
+
+ template
+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
+void print_edge(Edge_const_iterator eit) {
+ std::cout << "[" << eit->curve() << "]" << std::endl;
+}
+template
+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
+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
+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(f);
+ std::cout << "END FACE\n";
+ }
+ }
+}
+
+template
+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
+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
+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
+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 (geom_traits);
+ typename Kernel::Intersect_2 intersect_fnct = kernel->intersect_2_object();
+ return intersect_fnct(s1, s2);
+}
+
+template
+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
+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
+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
+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
+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
+ (geom_traits, proj_pt, s.source());
+ Number_type d_to_trg = compute_squared_distance_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
+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& 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::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 forward_needle; //vertices of the needle that are not
+ //between q and v_needle_begin;
+ //their direction is leaving q;
+
+ std::vector backward_needle;//vertices of the needle that are not
+ //between q and v_needle_begin;
+ //their direction is towards q;
+
+ std::vector 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 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(
+ 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(
+ 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(
+ 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
+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
+void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
+ regularize_output(arr_out);
+}
+
+template
+void conditional_regularize(VARR&, CGAL::Tag_false) {
+ //do nothing
+}
+
+
+
+} // end namespace Visibility_2
+} // end namespace CGAL
+
+#endif
diff --git a/Visibility_2/package_info/README b/Visibility_2/package_info/README
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/Visibility_2/package_info/Visibility_2/copyright b/Visibility_2/package_info/Visibility_2/copyright
new file mode 100644
index 00000000000..ef4df740e24
--- /dev/null
+++ b/Visibility_2/package_info/Visibility_2/copyright
@@ -0,0 +1 @@
+Braunschweig University (Germany).
diff --git a/Visibility_2/package_info/Visibility_2/description.txt b/Visibility_2/package_info/Visibility_2/description.txt
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/Visibility_2/package_info/Visibility_2/license.txt b/Visibility_2/package_info/Visibility_2/license.txt
new file mode 100644
index 00000000000..8bb8efcb72b
--- /dev/null
+++ b/Visibility_2/package_info/Visibility_2/license.txt
@@ -0,0 +1 @@
+GPL (v3 or later)
diff --git a/Visibility_2/package_info/Visibility_2/maintainer b/Visibility_2/package_info/Visibility_2/maintainer
new file mode 100644
index 00000000000..42bbe33488e
--- /dev/null
+++ b/Visibility_2/package_info/Visibility_2/maintainer
@@ -0,0 +1 @@
+Michael Hemmer
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/create_benchmark_report.sh b/Visibility_2/test/Visibility_2/create_benchmark_report.sh
new file mode 100755
index 00000000000..f3ae0e812da
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/create_benchmark_report.sh
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/in1 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in1
new file mode 100644
index 00000000000..2700fe53598
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in1
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/in2 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in2
new file mode 100644
index 00000000000..69304687bd6
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in2
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/in3 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in3
new file mode 100644
index 00000000000..39dd279c79b
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in3
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/in4 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in4
new file mode 100644
index 00000000000..6b68c501674
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in4
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/in5 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in5
new file mode 100644
index 00000000000..5e26ca7b6a7
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/in5
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out1 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out1
new file mode 100644
index 00000000000..9652c0f85ea
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out1
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out2 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out2
new file mode 100644
index 00000000000..1e99dfa0792
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out2
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out3 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out3
new file mode 100644
index 00000000000..cdd4288c369
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out3
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out4 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out4
new file mode 100644
index 00000000000..0eb09835e36
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out4
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out5 b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out5
new file mode 100644
index 00000000000..2d97d1a932b
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/Arrangement_Test/non_regular_out5
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.in b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.in
new file mode 100644
index 00000000000..26f74cedc8d
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.in
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.out b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.out
new file mode 100644
index 00000000000..068e55863cf
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_1.out
@@ -0,0 +1,10 @@
+4
+0 0
+8 0
+8 8
+0 8
+4
+0 1
+1 2
+2 3
+3 0
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_11.dat b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_11.dat
new file mode 100644
index 00000000000..230ab1db98c
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_11.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.in b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.in
new file mode 100644
index 00000000000..726d765637a
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.in
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.out b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.out
new file mode 100644
index 00000000000..f725e56ccff
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_2.out
@@ -0,0 +1,10 @@
+4
+0 0
+4 4
+32/5 24/5
+0 8
+4
+0 1
+1 2
+2 3
+3 0
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.in b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.in
new file mode 100644
index 00000000000..af54c28320a
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.in
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.out b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.out
new file mode 100644
index 00000000000..b297b5aa35b
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_3.out
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.in b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.in
new file mode 100644
index 00000000000..0a6d3b4e5e0
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.in
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.out b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.out
new file mode 100644
index 00000000000..eb97ed629ba
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/simple_polygon_test_case_4.out
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_1.dat b/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_1.dat
new file mode 100644
index 00000000000..4642e7f61e8
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_1.dat
@@ -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
+
+
diff --git a/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_2.dat b/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_2.dat
new file mode 100644
index 00000000000..7a0c8b5c867
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_non_simple_polygon_2.dat
@@ -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
+
+
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_1.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_1.dat
new file mode 100644
index 00000000000..1c1831df549
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_1.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_10.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_10.dat
new file mode 100644
index 00000000000..45f82bd5756
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_10.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_11.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_11.dat
new file mode 100644
index 00000000000..d541a8e3189
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_11.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_12.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_12.dat
new file mode 100644
index 00000000000..50293f02a44
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_12.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_13.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_13.dat
new file mode 100644
index 00000000000..89a50356237
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_13.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_14.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_14.dat
new file mode 100644
index 00000000000..1f3f06be81f
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_14.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_15.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_15.dat
new file mode 100644
index 00000000000..f5e0a064fa7
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_15.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_16.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_16.dat
new file mode 100644
index 00000000000..1a22709c2e5
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_16.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_17.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_17.dat
new file mode 100644
index 00000000000..5f58092bdda
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_17.dat
@@ -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
\ No newline at end of file
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_18.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_18.dat
new file mode 100644
index 00000000000..53977df93c6
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_18.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_19.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_19.dat
new file mode 100644
index 00000000000..1a30a031e63
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_19.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_2.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_2.dat
new file mode 100644
index 00000000000..c4113a8b559
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_2.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_20.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_20.dat
new file mode 100644
index 00000000000..6b1d08de06e
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_20.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_21.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_21.dat
new file mode 100644
index 00000000000..f379cb855f7
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_21.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_22.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_22.dat
new file mode 100644
index 00000000000..e75d1320752
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_22.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_3.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_3.dat
new file mode 100644
index 00000000000..932b304cb08
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_3.dat
@@ -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
+
+
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_4.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_4.dat
new file mode 100644
index 00000000000..5499e797fc4
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_4.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_5.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_5.dat
new file mode 100644
index 00000000000..114390d664d
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_5.dat
@@ -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
+
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_6.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_6.dat
new file mode 100644
index 00000000000..4ced7944242
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_6.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_7.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_7.dat
new file mode 100644
index 00000000000..536d64a2cfd
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_7.dat
@@ -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
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_8.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_8.dat
new file mode 100644
index 00000000000..4f52bbb694d
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_8.dat
@@ -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
+
+
diff --git a/Visibility_2/test/Visibility_2/data/test_simple_polygon_9.dat b/Visibility_2/test/Visibility_2/data/test_simple_polygon_9.dat
new file mode 100644
index 00000000000..56b7193c623
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/data/test_simple_polygon_9.dat
@@ -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
+
+
diff --git a/Visibility_2/test/Visibility_2/include/CGAL/test_model_methods.h b/Visibility_2/test/Visibility_2/include/CGAL/test_model_methods.h
new file mode 100644
index 00000000000..32d6dbfda16
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/include/CGAL/test_model_methods.h
@@ -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
+// Michael Hemmer
+
+#ifndef CGAL_TEST_MODEL_METHODS_H
+#define CGAL_TEST_MODEL_METHODS_H
+
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+template
+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
+ (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
+ (arr_out_check, arr)));
+ assert((true == test_are_equal
+ (arr_out, arr_out_check)));
+ arr_out.clear();
+ visibility.compute_visibility(query_pt, fit, arr_out);
+ assert((true == test_are_equal
+ (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
+ (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
+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 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(arr_square);
+
+ std::vector 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(arr_triangle);
+}
+
+} // end CGAL namespace
+#endif
diff --git a/Visibility_2/test/Visibility_2/include/CGAL/test_utils.h b/Visibility_2/test/Visibility_2/include/CGAL/test_utils.h
new file mode 100644
index 00000000000..26c335e5afe
--- /dev/null
+++ b/Visibility_2/test/Visibility_2/include/CGAL/test_utils.h
@@ -0,0 +1,1429 @@
+// 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
+// Francisc Bungiu
+// Michael Hemmer
+
+#ifndef CGAL_TEST_UTILS_H
+#define CGAL_TEST_UTILS_H
+
+//#define RESET "\033[0m"
+//#define RED "\033[31m"
+//#define GREEN "\033[32m"
+
+#define RESET ""
+#define RED ""
+#define GREEN ""
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+enum Query_choice {VERTEX, EDGE, FACE};
+
+template
+typename Arrangement_2::Halfedge_handle get_initial_halfedge(const Arrangement_2 &arr) {
+
+ typedef typename Arrangement_2::Vertex Vertex;
+ typedef typename Arrangement_2::Vertex_const_iterator Vertex_const_iterator;
+ typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
+
+ // find the min vertex
+ Vertex v = *arr.vertices_begin();
+ for(Vertex_const_iterator vit = arr.vertices_begin(); vit != arr.vertices_end(); vit++){
+ if(arr.traits()->compare_xy_2_object()((*vit).point(),v.point()) == CGAL::SMALLER){
+ v = *vit;
+ }
+ }
+
+ // take the edge with the smallest source
+ Halfedge_handle he_final = v.incident_halfedges();
+ Halfedge_handle he1 = v.incident_halfedges();
+ he1=he1->next()->twin();
+
+ while(he1 != v.incident_halfedges()){
+ if(arr.traits()->compare_xy_2_object()(
+ he1->source()->point(),
+ he_final->source()->point()) == CGAL::SMALLER){
+ he_final = he1;
+ }
+ he1=he1->next()->twin();
+ }
+
+ // as this may be on a needle, continue until faces on both sides differ
+ while(he_final->face() == he_final->twin()->face())
+ he_final = he_final->next();
+
+ return he_final;
+
+}
+
+/*
+ * Function to compare two arrangements; first determines lowest vertex
+ * from each arrangements, then it walks the edges and compares them
+ */
+template
+bool test_are_equal(const ARR1 &arr1, const ARR2 &arr2) {
+ typedef typename ARR1::Halfedge_handle HE1;
+ typedef typename ARR2::Halfedge_handle HE2;
+
+
+ // First make sure they have the same size
+ if (arr1.number_of_vertices() != arr2.number_of_vertices()) {
+ return false;
+ }
+ if (arr1.number_of_edges() != arr2.number_of_edges()) {
+ return false;
+ }
+ if (arr1.number_of_isolated_vertices() != arr2.number_of_isolated_vertices()) {
+ return false;
+ }
+ if (arr1.number_of_faces() != arr2.number_of_faces()) {
+ return false;
+ }
+
+ // currently checking for closed for visibility region
+ assert(arr1.number_of_faces() == 2);
+ assert(arr2.number_of_faces() == 2);
+
+ // get unique halfedge
+ HE1 he_start_1 = get_initial_halfedge(arr1);
+ HE2 he_start_2 = get_initial_halfedge(arr2);
+
+ // run on first loop and compare sources
+ assert(arr1.traits()->compare_xy_2_object()(
+ he_start_1->source()->point(),
+ he_start_2->source()->point()) == CGAL::EQUAL);
+
+ HE1 he_run_1 = he_start_1->next();
+ HE2 he_run_2 = he_start_2->next();
+
+ while(he_run_1 != he_start_1){
+
+ assert(arr1.traits()->compare_xy_2_object()(
+ he_run_1->source()->point(),
+ he_run_2->source()->point()) == CGAL::EQUAL);
+
+ he_run_1 = he_run_1->next();
+ he_run_2 = he_run_2->next();
+ }
+ assert(he_run_2 == he_start_2);
+
+ // run on second loop and compare sources.
+ he_start_1 = he_start_1->twin();
+ he_start_2 = he_start_2->twin();
+ he_run_1 = he_start_1->next();
+ he_run_2 = he_start_2->next();
+ while(he_run_1 != he_start_1){
+
+ assert(arr1.traits()->compare_xy_2_object()(
+ he_run_1->source()->point(),
+ he_run_2->source()->point()) == CGAL::EQUAL);
+
+ he_run_1 = he_run_1->next();
+ he_run_2 = he_run_2->next();
+ }
+ assert(he_run_2 == he_start_2);
+ return true;
+}
+
+
+
+template
+std::string num2string(Number_type& n) {
+ std::stringstream ss;
+ ss<
+CGAL::Object get_location(
+ const Arrangement_2 &arr,
+ const typename Arrangement_2::Geometry_traits_2::Point_2 &q) {
+
+ typedef CGAL::Arr_naive_point_location Naive_pl;
+ Naive_pl naive_pl(arr);
+
+ // Perform the point-location query.
+ CGAL::Object obj = naive_pl.locate(q);
+ return obj;
+}
+
+template
+bool is_inside_face(
+ const Arrangement_2 &arr,
+ const typename Arrangement_2::Face_const_handle face,
+ const typename Arrangement_2::Geometry_traits_2::Point_2 &q) {
+
+ CGAL::Object obj = get_location(arr, q);
+ typename Arrangement_2::Face_const_handle f;
+ if (CGAL::assign (f, obj)) {
+ // q is located inside a face:
+ if (!f->is_unbounded()) {
+ if (f == face) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+template
+bool create_arrangement_from_dat_file(std::ifstream &input,
+ _Arrangement_2 &arr) {
+ arr.clear();
+
+ typedef _Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Arrangement_2::Face_handle Face_handle;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+
+ if (input) {
+ std::string curr_line;
+ std::getline(input, curr_line);
+ std::stringstream convert(curr_line);
+ int number_of_isolated_vertices;
+ convert >> number_of_isolated_vertices;
+ Face_handle uface = arr.unbounded_face();
+ for (int i = 0 ; i < number_of_isolated_vertices ; i++) {
+ std::getline(input, curr_line);
+ std::istringstream iss(curr_line);
+ Point_2 p;
+ iss >> p;
+ arr.insert_in_face_interior(p, uface);
+ }
+ std::vector edges;
+ int number_of_edges;
+ std::getline(input, curr_line);
+ std::stringstream convert2(curr_line);
+ convert2 >> number_of_edges;
+ for (int i = 0 ; i < number_of_edges ; i++) {
+ std::getline(input, curr_line);
+ std::istringstream iss(curr_line);
+ Segment_2 seg;
+ iss >> seg;
+ edges.push_back(seg);
+ }
+ CGAL::insert(arr, edges.begin(), edges.end());
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+template
+void regularize(Arrangement_2& arr){
+ //std::cout << "\n regularize" << std::endl;
+ // remove all edges with the same face on both sides
+ typedef typename Arrangement_2::Edge_iterator EIT;
+ for(EIT eit = arr.edges_begin(); eit != arr.edges_end();){
+ if(eit->face() == eit->twin()->face()){
+ // arr.remove_edge(eit++,false,false); did not compile
+ EIT eh = eit;
+ ++eit;
+ arr.remove_edge(eh,false,false);
+ }else{
+ ++eit;
+ }
+ }
+ // remove all isolated vertices (also those left from prvious step)
+ typedef typename Arrangement_2::Vertex_iterator VIT;
+ for(VIT vit = arr.vertices_begin(); vit != arr.vertices_end();){
+ if(vit->degree()== 0){
+ VIT vh = vit;
+ vit++;
+ arr.remove_isolated_vertex(vh);
+ }else{
+ vit++;
+ }
+ }
+ //std::cout << "regularize done" << std::endl;
+}
+
+
+template
+bool run_test_case_from_file(Visibility_2& visibility, std::ifstream &input) {
+ typedef typename Visibility_2::Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
+ Halfedge_around_vertex_const_circulator;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+ typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
+ typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
+
+ Arrangement_2 arr_in;
+ Visibility_arrangement_2 arr_correct_out;
+ Visibility_arrangement_2 arr_out;
+
+ std::string curr_line;
+ while (std::getline(input, curr_line)) {
+ if (curr_line[0] != '#' && curr_line[0] != '/')
+ break;
+ }
+ std::stringstream ss(curr_line);
+ Point_2 query_pt;
+ ss >> query_pt;
+
+ std::getline(input, curr_line);
+ std::istringstream iss(curr_line);
+ Point_2 reference_pt;
+ iss >> reference_pt;
+
+ std::getline(input, curr_line);
+ if (!create_arrangement_from_dat_file(input, arr_in)) {
+ return false;
+ }
+ visibility.attach(arr_in);
+ std::getline(input, curr_line);
+ if (!create_arrangement_from_dat_file
+ (input, arr_correct_out)) {
+ return false;
+ }
+
+ if(Visibility_2::Regularization_category::value){
+ regularize(arr_correct_out);
+ }
+
+
+ CGAL::Object obj = CGAL::get_location(arr_in, query_pt);
+ Face_const_handle f;
+ Halfedge_const_handle e;
+ Vertex_const_handle v;
+
+ if (CGAL::assign (f, obj)) {
+ if (!f->is_unbounded()) {
+ visibility.compute_visibility(query_pt, f, arr_out);
+ }
+ }
+ else if (CGAL::assign(e, obj)) {
+ if (e->source()->point() == reference_pt) {
+ visibility.compute_visibility(query_pt, e, arr_out);
+ }
+ else {
+ visibility.compute_visibility(query_pt, e->twin(), arr_out);
+ }
+ }
+ else if (CGAL::assign(v, obj)) {
+ // Check which halfedge we want in the query
+ Halfedge_around_vertex_const_circulator he_circ = v->incident_halfedges();
+ Halfedge_around_vertex_const_circulator he_curr = he_circ;
+ do {
+ if (he_curr->source()->point() == reference_pt) {
+ visibility.compute_visibility(query_pt, he_curr, arr_out);
+ }
+ } while (++he_curr != he_circ);
+ }
+
+
+ if (!test_are_equal(arr_out, arr_correct_out)) {
+ std::cout<<"the result is:\n";
+ CGAL::Visibility_2::print_arrangement(arr_out);
+ std::cout<<"however, the expected answer is:\n";
+ CGAL::Visibility_2::print_arrangement(arr_correct_out);
+ return false;
+ }
+ visibility.detach();
+ return true;
+}
+
+template
+void test_interface() {
+ typedef typename Visibility_2::Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+ typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+
+ Point_2 query(0.1, 0.1);
+
+ std::vector vertices;
+ vertices.push_back(Point_2(0, 0));
+ vertices.push_back(Point_2(1, 0));
+ vertices.push_back(Point_2(1, 1));
+ vertices.push_back(Point_2(0, 1));
+
+
+ Arrangement_2 arr_out;
+ Arrangement_2 square;
+
+ for(unsigned int i = 0; i < vertices.size(); ++i) {
+ CGAL::insert(square, Segment_2(vertices[i],
+ vertices[(i+1) % vertices.size()]));
+ }
+
+ Face_const_handle location;
+ CGAL::assign(location, get_location(square, query));
+
+
+
+ const Arrangement_2& arr = square;
+
+ // Constructor and attach method must accept a const arrangement.
+ Visibility_2 visibility(arr);
+
+ visibility.detach();
+ visibility.attach(arr);
+
+
+ const Visibility_2& vis = visibility;
+
+ // compute_visibility must be const
+ vis.compute_visibility(query, location, arr_out);
+
+ Halfedge_const_handle he = arr.edges_begin();
+
+ if(he->face()->is_unbounded())
+ he = he->twin();
+
+ vis.compute_visibility(he->target()->point(), he, arr_out);
+
+ // must have const arrangement_2();
+ const Arrangement_2& a = vis.arrangement_2();
+
+ visibility.attach(a);
+
+ // must have const is_attached();
+ vis.is_attached();
+
+
+
+
+}
+
+template
+void run_tests_with_changes_to_arr() {
+
+ std::cout << " Testing changes to attached arrangement:";
+
+ typedef typename Visibility_2::Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+
+ bool all_passed = true;
+
+
+ Point_2 query(0.1, 0.1);
+
+ std::vector vertices;
+ vertices.push_back(Point_2(0, 0));
+ vertices.push_back(Point_2(1, 0));
+ vertices.push_back(Point_2(1, 1));
+ vertices.push_back(Point_2(0, 1));
+
+
+ Arrangement_2 square;
+ for(unsigned int i = 0; i < vertices.size(); ++i) {
+ CGAL::insert(square, Segment_2(vertices[i],
+ vertices[(i+1) % vertices.size()]));
+ }
+
+ Arrangement_2 lower_tri;
+ CGAL::insert(lower_tri, Segment_2(vertices[0], vertices[1]));
+ CGAL::insert(lower_tri, Segment_2(vertices[1], vertices[3]));
+ CGAL::insert(lower_tri, Segment_2(vertices[3], vertices[0]));
+
+ Visibility_2 visibility;
+ Arrangement_2 arr;
+ Arrangement_2 arr_out;
+
+ // Attach empty arr and fill it afterwards
+ visibility.attach(arr);
+
+
+ for(unsigned int i = 0; i < vertices.size(); ++i) {
+ CGAL::insert(arr, Segment_2(vertices[i],
+ vertices[(i+1) % vertices.size()]));
+ }
+
+ Face_const_handle location;
+ CGAL::assign(location, get_location(arr, query));
+
+ visibility.compute_visibility(query, location, arr_out);
+
+ all_passed &= test_are_equal(arr_out, square);
+
+
+ // Change attached arrangement and query again
+
+ //arr.clear();
+
+ //CGAL::insert(arr, Segment_2(vertices[0], vertices[1]));
+ CGAL::insert(arr, Segment_2(vertices[1], vertices[3]));
+ //CGAL::insert(arr, Segment_2(vertices[3], vertices[0]));
+
+ CGAL::assign(location, get_location(arr, query));
+
+ visibility.compute_visibility(query, location, arr_out);
+
+ all_passed &= test_are_equal(arr_out, lower_tri);
+
+
+ // Detach and attach again
+
+ visibility.detach();
+ visibility.attach(arr);
+
+ CGAL::assign(location, get_location(arr, query));
+
+ visibility.compute_visibility(query, location, arr_out);
+
+ all_passed &= test_are_equal(arr_out, lower_tri);
+
+
+ // Attach another arrangement without detaching the old one first.
+
+ visibility.attach(square);
+
+ CGAL::assign(location, get_location(square, query));
+
+ visibility.compute_visibility(query, location, arr_out);
+
+ all_passed &= test_are_equal(arr_out, square);
+
+
+ if (!all_passed) {
+ std::cout << "\tFailed: Modifying attached arrangment causes wrong output.\n";
+ assert(false);
+ } else {
+ std::cout << "\tPassed.\n" ;
+ }
+}
+
+
+template
+void run_tests(int case_number_simple, int case_number_non_simple) {
+
+ // Make sure the code only compiles with a conforming interface
+ test_interface();
+
+
+ Visibility_2 visibility;
+ bool one_failed = false;
+ if (Visibility_2::Supports_simple_polygon_category::value
+ && case_number_simple >= 1) {
+ int cnt = 0;
+ int cnt_passed = 0;
+ std::cout << " Running simple polygon test cases...\n";
+ for (int i = 1 ; i <= case_number_simple ; i++) {
+ std::string input_arr_file("data/test_simple_polygon_");
+ input_arr_file += num2string(i);
+ input_arr_file += ".dat";
+ std::cout << " Running test "
+ << GREEN << input_arr_file << RESET
+ << " - ";
+ std::ifstream input(input_arr_file.c_str());
+ if (run_test_case_from_file(visibility, input)) {
+ cnt_passed++;
+ std::cout << GREEN << "Done!" << RESET << std::endl;
+ }
+ else {
+ one_failed = true;
+ std::cout << RED << "Failed!" << RESET << std::endl;
+ }
+ cnt++;
+ }
+ std::cout << " Visibility_2 object passed " << cnt_passed
+ << "/" << cnt << " tests"
+ << " (";
+ double result = (double)cnt_passed/cnt*100;
+ if (result > 99.9) {
+ std::cout << GREEN << result << "%" << RESET;
+ }
+ else {
+ std::cout << RED << result << "%" << RESET;
+ }
+ std::cout << ")" << std::endl;
+ }
+ if (Visibility_2::Supports_general_polygon_category::value
+ && case_number_non_simple >= 1) {
+
+ int cnt = 0;
+ int cnt_passed = 0;
+ std::cout << " Running non-simple polygon test cases...\n";
+ for (int i = 1 ; i <= case_number_non_simple ; i++) {
+ std::string input_arr_file("data/test_non_simple_polygon_");
+ input_arr_file += num2string(i);
+ input_arr_file += ".dat";
+ std::cout << " Running test "
+ << GREEN << input_arr_file << RESET
+ << " - ";
+ std::ifstream input(input_arr_file.c_str());
+ if (run_test_case_from_file(visibility, input)) {
+ cnt_passed++;
+ std::cout << GREEN << "Done!" << RESET << std::endl;
+ }
+ else {
+ one_failed = true;
+ std::cout << RED << "Failed!" << RESET << std::endl;
+ }
+ cnt++;
+ }
+ std::cout << " Visibility_2 object passed " << cnt_passed
+ << "/" << cnt << " tests"
+ << " (";
+ double result = (double)cnt_passed/cnt*100;
+ if (result > 99.9) {
+ std::cout << GREEN << result << "%" << RESET;
+ }
+ else {
+ std::cout << RED << result << "%" << RESET;
+ }
+ std::cout << ")" << std::endl;
+ }
+ if (one_failed) {
+ assert(false);
+ }
+
+ run_tests_with_changes_to_arr();
+
+}
+
+
+template
+void create_arrangement_from_file(_Arrangement_2 &arr, std::ifstream& input) {
+ typedef _Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+
+ if (input) {
+ std::string line;
+ while (std::getline(input, line)) {
+ if (line[0] != '#' && line[0] != '/')
+ break;
+ }
+ std::vector points;
+ std::vector segments;
+ std::stringstream convert(line);
+ int number_of_points;
+ convert >> number_of_points;
+
+ for (int i = 0; i != number_of_points; i++) {
+ std::getline(input, line);
+ std::istringstream iss(line);
+ Point_2 p;
+ iss >> p;
+ points.push_back(p);
+ }
+ int number_of_edges;
+ input >> number_of_edges;
+ for (int i = 0; i != number_of_edges; i++) {
+ unsigned i1,i2;
+ input >> i1 >> i2;
+ segments.push_back(Segment_2(points[i1], points[i2]));
+ }
+ CGAL::insert(arr, segments.begin(), segments.end());
+ }
+ else {
+ std::cout<<"Can't open the file. Check the file name.";
+ }
+}
+
+
+template
+void create_arrangement_from_env_file(_Arrangement_2 &arr, std::ifstream& input) {
+ typedef _Arrangement_2 Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+
+ if (input) {
+ std::string line;
+ while (std::getline(input, line)) {
+ if (line[0] != '#' && line[0] != '/')
+ break;
+ }
+ std::stringstream convert(line);
+ int number_of_polygons;
+ convert >> number_of_polygons;
+ for (int i = 0 ; i < number_of_polygons ; i++) {
+ std::vector points;
+ std::vector segments;
+
+ std::getline(input, line);
+ std::stringstream convert(line);
+ typename std::vector::size_type number_of_vertices;
+ convert >> number_of_vertices;
+ for (typename std::vector::size_type j = 0;
+ j < number_of_vertices; j++) {
+ std::getline(input, line);
+ std::istringstream iss(line);
+ Point_2 p;
+ iss >> p;
+ points.push_back(p);
+ }
+ for (typename std::vector::size_type j = 0;
+ j < number_of_vertices-1 ; j++)
+ {
+ segments.push_back(Segment_2(points[j], points[j+1]));
+ }
+ segments.push_back(Segment_2(points.front(), points.back()));
+ // std::cout << "before insertion\n";
+ CGAL::insert(arr, segments.begin(), segments.end());
+ // std::cout << "after\n";
+ }
+ }
+ else {
+ std::cout<<"Can't open the file. Check the file name.";
+ }
+}
+
+template
+bool compare_arr_by_edges(const Arrangement_2& arr1, const Arrangement_2& arr2){
+ std::set s1;
+ typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
+ for (Edge_const_iterator eit = arr1.edges_begin();
+ eit != arr1.edges_end(); ++eit) {
+ s1.insert(edge2string(eit->target()->point(), eit->source()->point()));
+ }
+ std::set s2;
+ for (Edge_const_iterator eit = arr2.edges_begin();
+ eit != arr2.edges_end(); ++eit) {
+ s2.insert(edge2string(eit->target()->point(), eit->source()->point()));
+ }
+ return s1==s2;
+}
+
+template
+bool is_ahead(Point_2& p1, Point_2& p2) {
+ if (p1.x() > p2.x()) {
+ return true;
+ }
+ if (p1.x() == p2.x() && p1.y() > p2.y()) {
+ return true;
+ }
+ return false;
+}
+
+
+template
+std::string edge2string(const Point_2& p1, const Point_2& p2) {
+ Point_2 q1, q2;
+ if (is_ahead(p1, p2)) {
+ q1 = p1;
+ q2 = p2;
+ }
+ else {
+ q1 = p2;
+ q2 = p1;
+ }
+ return num2string(q1.x()) + num2string(q1.y())
+ + num2string(q2.x()) + num2string(q2.y());
+}
+
+template
+Point_2 random_linear_interpolation(const Point_2 &p, const Point_2 &q) {
+
+// srand(time(NULL));
+ Number_type min_x, max_x;
+ Number_type y0, y1, x0, x1;
+
+ if (p.x() < q.x()) {
+ min_x = p.x();
+ max_x = q.x();
+ x0 = p.x();
+ x1 = q.x();
+ y0 = p.y();
+ y1 = q.y();
+ }
+ else {
+ min_x = q.x();
+ max_x = p.x();
+ x0 = q.x();
+ x1 = p.x();
+ y0 = q.y();
+ y1 = p.y();
+ }
+
+ Number_type x_normalized = rand()/static_cast(RAND_MAX);
+ Number_type x = min_x + static_cast(x_normalized*(max_x - min_x));
+ if (x == max_x && x == min_x) {
+ Number_type min_y, max_y;
+ if (p.y() < q.y()) {
+ min_y = p.y();
+ max_y = q.y();
+ }
+ else {
+ min_y = q.y();
+ max_y = p.y();
+ }
+ Number_type y_normalized = rand()/static_cast(RAND_MAX);
+ Number_type y = min_y + static_cast(y_normalized*(max_y - min_y));
+ return Point_2(x, y);
+ }
+ else {
+ Number_type y = y0 + (y1 - y0)*(x - x0)/(x1 - x0);
+ return Point_2(x, y);
+ }
+}
+
+//make sure q is in fh or on the bound.
+template
+bool is_star_shape(
+ const typename Arrangement_2::Point_2& q,
+ const Arrangement_2& arr) {
+
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+
+ // this test is written for an arr that contains on star shaped polygon
+ if (arr.number_of_faces()!=2){
+ return false;
+ }
+
+ // get the bounded face
+ Face_const_handle fh;
+ if(arr.faces_begin()->is_unbounded()){
+ fh = arr.faces_begin();
+ }else{
+ fh = ++(arr.faces_begin());
+ }
+ assert(fh->is_unbounded());
+
+ if (fh->has_outer_ccb()) {
+ typename Arrangement_2::Ccb_halfedge_const_circulator curr, circ;
+ curr = circ = fh->outer_ccb();
+ do {
+ if (CGAL::right_turn(q, curr->source()->point(), curr->target()->point())) {
+ return false;
+ }
+// Point_2 p = curr->target()->point();
+// typename Arrangement_2::Ccb_halfedge_const_circulator curr1, circ1;
+// curr1 = circ1 = fh->outer_ccb();
+// do {
+// Segment_2 intersect_s;
+// Point_2 intersect_p;
+// Point_2 source = curr1->source()->point();
+// Point_2 target = curr1->target()->point();
+// int i = intersect_seg(Segment_2(p, q), Segment_2(source, target), intersect_s, intersect_p);
+// if (i == 1 && intersect_p != source && intersect_p != target && intersect_p != q)
+// return false;
+// } while (++curr1 != circ1);
+ } while (++curr != circ);
+ }
+ return true;
+}
+
+template
+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
+typename Arrangement_2::Face_const_handle construct_biggest_arr_with_no_holes(
+ Arrangement_2 &arr_in,
+ Arrangement_2 &arr_out) {
+
+ typedef typename Arrangement_2::Face_const_iterator Face_const_iterator;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+ typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
+ typedef typename Arrangement_2::Ccb_halfedge_const_circulator
+ Ccb_halfedge_const_circulator;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Segment_2 Segment_2;
+
+ int curr_max(0);
+ Ccb_halfedge_const_circulator curr_max_circ;
+ Ccb_halfedge_const_circulator circ;
+ Ccb_halfedge_const_circulator curr;
+ Face_const_iterator fit;
+
+ int cnt(0);
+ for (fit = arr_in.faces_begin() ; fit != arr_in.faces_end() ; fit++) {
+ if (fit->has_outer_ccb()) {
+ Ccb_halfedge_const_circulator circ = fit->outer_ccb();
+ int edge_cnt = count_edges_in_face(fit);
+ if (edge_cnt > curr_max) {
+ curr_max = edge_cnt;
+ curr_max_circ = circ;
+ }
+ }
+ cnt++;
+ }
+
+ std::vector segments;
+ curr = curr_max_circ;
+ Halfedge_const_handle he;
+ do {
+ he = curr;
+ segments.push_back(Segment_2(he->source()->point(), he->target()->point()));
+ } while (++curr != curr_max_circ);
+
+ arr_out.clear();
+// std::cout << "before insertion\n";
+ CGAL::insert_non_intersecting_curves(arr_out, segments.begin(), segments.end());
+// std::cout << "after\n";
+
+ Face_const_handle fch;
+ curr_max = 0;
+ for (fit = arr_out.faces_begin() ; fit != arr_out.faces_end() ; fit++) {
+ if (fit->has_outer_ccb()) {
+ int edge_cnt = count_edges_in_face(fit);
+ if (edge_cnt > curr_max) {
+ curr_max = edge_cnt;
+ fch = fit;
+ }
+ }
+ }
+
+ return fch;
+}
+
+template
+void simple_benchmark_one_unit(
+ typename Visibility_2_fst::Arrangement_2 &arr,
+ const Query_choice &choice,
+ typename Visibility_2_fst::Arrangement_2::Face_const_handle &fit,
+ Visibility_2_fst& visibility_fst,
+ Visibility_2_snd& visibility_snd,
+ double& qtime1,
+ double& qtime2,
+ int& query_cnt) {
+
+ typedef typename Visibility_2_fst::Arrangement_2 Arrangement_2;
+ typedef typename Visibility_2_fst::Arrangement_2 Visibility_arrangement_2;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+ typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Arrangement_2::Ccb_halfedge_const_circulator
+ Ccb_halfedge_const_circulator;
+
+ typedef typename Visibility_arrangement_2::Face_handle Face_handle;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ typedef typename Geometry_traits_2::FT Number_type;
+ typedef Timer Benchmark_timer;
+
+ Benchmark_timer timer;
+
+ Ccb_halfedge_const_circulator circ = fit->outer_ccb();
+ Ccb_halfedge_const_circulator curr = circ;
+
+ do {
+ Halfedge_const_handle he = curr;
+ Point_2 curr_query_pt;
+ bool selected_query_pt = true;
+ switch (choice) {
+ case VERTEX:
+ curr_query_pt = he->target()->point();
+ break;
+ case EDGE:
+ curr_query_pt = random_linear_interpolation
+ (he->source()->point(), he->target()->point());
+ break;
+ case FACE:
+ Ccb_halfedge_const_circulator curr_next = curr;
+ curr_next++;
+ Halfedge_const_handle he_next = curr_next;
+ Point_2 p1 = he->source()->point();
+ Point_2 p2 = he->target()->point();
+ Point_2 p3 = he_next->target()->point();
+ Point_2 avg((p1.x() + p2.x() + p3.x())/3, (p1.y() + p2.y() + p3.y())/3);
+ if (is_inside_face(arr, fit, avg)) {
+ curr_query_pt = avg;
+ }
+ else {
+ selected_query_pt = false;
+ }
+ break;
+ }
+ if (!selected_query_pt) {
+ curr++;
+ if (curr == circ) {
+ break;
+ }
+ continue;
+ }
+
+ Visibility_arrangement_2 out_arr_fst, out_arr_snd;
+ timer.reset();
+ timer.start();
+ Face_handle f_fst;
+ if (choice == CGAL::FACE) {
+ f_fst = visibility_fst.compute_visibility(curr_query_pt, fit, out_arr_fst);
+ query_cnt++;
+ }
+ else {
+ f_fst = visibility_fst.compute_visibility(curr_query_pt, he, out_arr_fst);
+ query_cnt++;
+ }
+ timer.stop();
+ qtime1 += timer.time();
+
+ timer.reset();
+ if ( !is_star_shape(curr_query_pt, out_arr_fst) ) {
+ std::cout << RED << " Warning: the first output is not star-shape." << RESET << std::endl;
+ }
+ timer.start();
+ Face_handle f_snd;
+ if (choice == CGAL::FACE) {
+ f_snd = visibility_snd.compute_visibility(curr_query_pt, fit, out_arr_snd);
+ }
+ else {
+ f_snd = visibility_snd.compute_visibility(curr_query_pt, he, out_arr_snd);
+ }
+ timer.stop();
+ if ( !is_star_shape(curr_query_pt, out_arr_snd) ) {
+ std::cout << RED << " Warning: the second output is not star-shape." << RESET << std::endl;
+ }
+ qtime2 += timer.time();
+
+ if (! CGAL::test_are_equal (out_arr_fst, out_arr_snd)) {
+ if (choice == CGAL::FACE) {
+ std::cout << "query in Face:\n";
+ CGAL::Visibility_2::print_simple_face(fit);
+ }
+ std::cout << "the query point is " << curr_query_pt << std::endl;
+ std::cout << RED << "two outputs are different:\n"
+ << "first output is:\n" << RESET;
+ CGAL::Visibility_2::print_arrangement(out_arr_fst);
+ std::cout << RED << "second output is:\n"<< RESET;
+ CGAL::Visibility_2::print_arrangement(out_arr_snd);
+ assert(false);
+ }
+ } while (++curr != circ);
+}
+
+template
+void simple_benchmark(Visibility_2_fst &visibility_fst,
+ Visibility_2_snd &visibility_snd,
+ const Query_choice &choice,
+ std::ifstream &input) {
+
+ typedef typename Visibility_2_fst::Arrangement_2 Arrangement_2;
+
+ typedef typename Arrangement_2::Face_const_iterator Face_const_iterator;
+ typedef typename Arrangement_2::Face_const_handle Face_const_handle;
+
+ assert(Visibility_2_fst::Regularization_category::value
+ == Visibility_2_snd::Regularization_category::value);
+
+ Arrangement_2 arr;
+ create_arrangement_from_env_file(arr, input);
+
+ int query_cnt(0);
+ double qtime1(0), qtime2(0), ptime1(0), ptime2(0);
+ if (Visibility_2_fst::Supports_general_polygon_category::value
+ && Visibility_2_snd::Supports_general_polygon_category::value) {
+
+ Face_const_iterator fit;
+ Timer timer;
+
+ timer.start();
+ visibility_fst.attach(arr);
+ timer.stop();
+ ptime1 = timer.time();
+
+ timer.reset();
+ timer.start();
+ visibility_snd.attach(arr);
+ timer.stop();
+ ptime2 = timer.time();
+
+ for (fit = arr.faces_begin() ; fit != arr.faces_end() ; fit++) {
+ if (!fit->is_unbounded()) {
+
+ simple_benchmark_one_unit(arr,
+ choice,
+ fit,
+ visibility_fst,
+ visibility_snd,
+ qtime1,
+ qtime2,
+ query_cnt);
+ }
+ }
+ }
+ else {
+ Arrangement_2 arr_trimmed;
+ Face_const_handle fch = construct_biggest_arr_with_no_holes
+