diff --git a/Documentation/biblio/cgal_manual.bib b/Documentation/biblio/cgal_manual.bib
index 2285b00840a..f9ec3628436 100644
--- a/Documentation/biblio/cgal_manual.bib
+++ b/Documentation/biblio/cgal_manual.bib
@@ -2335,6 +2335,50 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
series = {Texts and Monographs in Symbolic Computation}
}
+@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"
+}
+
% ----------------------------------------------------------------------------
% END OF BIBFILE
% ----------------------------------------------------------------------------
diff --git a/Documentation/biblio/geom.bib b/Documentation/biblio/geom.bib
index 668aea44180..a7ebeefdd3b 100644
--- a/Documentation/biblio/geom.bib
+++ b/Documentation/biblio/geom.bib
@@ -151797,4 +151797,3 @@ amplification and suppression of local contrast. Contains C code."
, publisher = "Cambridge University Press"
, year = 1999
}
-
diff --git a/Documentation/doc/Documentation/Doxyfile.in b/Documentation/doc/Documentation/Doxyfile.in
index 3b98211f403..1a6d60f2432 100644
--- a/Documentation/doc/Documentation/Doxyfile.in
+++ b/Documentation/doc/Documentation/Doxyfile.in
@@ -104,6 +104,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}/Subdivision_method_3/doc/Subdivision_method_3/fig \
diff --git a/Documentation/doc/Documentation/dependencies b/Documentation/doc/Documentation/dependencies
index 0c39215e2e6..8d6852cfc73 100644
--- a/Documentation/doc/Documentation/dependencies
+++ b/Documentation/doc/Documentation/dependencies
@@ -71,6 +71,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 5dd03dd6775..894ba6f2838 100644
--- a/Documentation/doc/Documentation/packages.txt
+++ b/Documentation/doc/Documentation/packages.txt
@@ -66,6 +66,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/Documentation/doxyassist.xml b/Documentation/doxyassist.xml
index 1d7bbb8760b..23576d72ef5 100644
--- a/Documentation/doxyassist.xml
+++ b/Documentation/doxyassist.xml
@@ -718,8 +718,24 @@ namespace for the XML file to be processed properly. -->
./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html
+
+
+
+ 2D Visibility
+ ../Visibility_2/doc/Visibility_2
+
+ ../Visibility_2/doc/Visibility_2/
+ ../Visibility_2/doc/Visibility_2/
+ ./tags/Visibility_2.tag
+ ../Visibility_2/examples
+ ../Visibility_2/doc/Visibility_2/fig
+
+ ./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html
+
+
+
2D Minkowski Sums
../Minkowski_sum_2/doc/Minkowski_sum_2
@@ -1457,6 +1473,7 @@ namespace for the XML file to be processed properly. -->
../Convex_hull_d/doc/Convex_hull_d/fig../Envelope_2/doc/Envelope_2/fig../Envelope_3/doc/Envelope_3/fig
+ ../Visibility_2/doc/Visibility_2/fig../Generator/doc/Generator/fig../Geomview/doc/Geomview/fig../GraphicsView/doc/GraphicsView/fig
@@ -1538,6 +1555,7 @@ namespace for the XML file to be processed properly. -->
./tags/Convex_hull_d.tag=../../CGAL.CGAL.dD-Convex-Hulls-and-Delaunay-Triangulations/html./tags/Envelope_2.tag=../../CGAL.CGAL.2D-Envelopes/html./tags/Envelope_3.tag=../../CGAL.CGAL.3D-Envelopes/html
+ ./tags/Visibility_2.tag=../../CGAL.CGAL.2D-Visibility/html./tags/Generator.tag=../../CGAL.CGAL.Geometric-Object-Generators/html./tags/Geomview.tag=../../CGAL.CGAL.Geomview/html./tags/GraphicsView.tag=../../CGAL.CGAL.CGAL-and-the-Qt-Graphics-View-Framework/html
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..6ef04c61d65
--- /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 RegularizationTag 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
+/// @{
+ /*!
+ Tag identifying whether the regularized visibility area is computed.
+ */
+ typedef RegularizationTag Regularization_tag;
+
+ /*!
+ Tag identifying that the class supports general polygons (i.e.\ with holes).
+ */
+ typedef ::Tag_true Supports_general_polygon_tag;
+
+ /*!
+ Tag identifying that the class supports general simple polygons.
+ */
+ typedef ::Tag_true Supports_simple_polygon_tag;
+/// @}
+
+
+
+/// \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..fbd66bc408b
--- /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.
+
+\tparam RegularizationTag 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
+/// @{
+ /*!
+ Tag identifying whether the regularized visibility area is computed.
+ */
+ typedef RegularizationTag Regularization_tag;
+
+ /*!
+ The class supports general polygons (i.e.\ with holes).
+ */
+ typedef ::Tag_true Supports_general_polygon_tag;
+
+ /*!
+ The class supports general simple polygons.
+ */
+ typedef ::Tag_true Supports_simple_polygon_tag;
+/// @}
+
+
+/// \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..cc39a6c4b5f
--- /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.
+
+\tparam RegularizationTag 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
+/// @{
+ /*!
+ Tag identifying whether the regularized visibility area is computed.
+ */
+ typedef RegularizationTag Regularization_tag;
+
+ /*!
+ The class does not support general polygons (i.e.\ with holes).
+ */
+ typedef ::Tag_false Supports_general_polygon_tag;
+
+ /*!
+ The class supports general simple polygons.
+ */
+ typedef ::Tag_true Supports_simple_polygon_tag;
+/// @}
+
+
+/// \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..0ad7c8642e4
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/CGAL/Triangular_expansion_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 polygon that may have holes.
+
+\details The algorithm obtains a constrained triangulation from 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
+the algorithm is even linear but it can also be \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.
+
+\tparam RegularizationTag 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
+/// @{
+ /*!
+ Tag identifying whether the regularized visibility area is computed.
+ */
+ typedef RegularizationTag Regularization_tag;
+
+ /*!
+ The class supports general polygons (i.e.\ with holes).
+ */
+ typedef ::Tag_true Supports_general_polygon_tag;
+
+ /*!
+ The class supports general simple polygons.
+ */
+ typedef ::Tag_true Supports_simple_polygon_tag;
+/// @}
+
+
+/// \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
+the a new restricted triangulation is computed right before a new query. It is also possible
+to force a re-computation by re-attaching the current arrangement.
+
+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..7f7db7038d3
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/Concepts/Visibility_2.h
@@ -0,0 +1,156 @@
+
+/*!
+\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 Hidden_type Arrangement_2;
+
+ /*!
+ The geometry traits class of Arrangement_2.
+ */
+ typedef Arrangement_2::Traits_2 Traits_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
+/// @{
+ /*!
+ Tag identifying whether the regularized visibility area is computed (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
+ */
+ typedef Hidden_type Regularization_tag;
+
+ /*!
+ Tag identifying whether general polygons (with holes) are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
+ */
+ typedef Hidden_type Supports_general_polygon_tag;
+
+ /*!
+ Tag identifying whether general simple polygons are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
+ */
+ typedef Hidden_type Supports_simple_polygon_tag;
+/// @}
+
+/// \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& arr() 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->arr()`
+\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->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 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..ce9f7b2f2c7
--- /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}
+\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..a58448aa65e
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..362c061beaa
--- /dev/null
+++ b/Visibility_2/doc/Visibility_2/visibility_2.txt
@@ -0,0 +1,152 @@
+namespace CGAL {
+
+/*!
+\mainpage 2D Visibility
+\anchor Chapter_2D_Visibility_Computation
+\cgalAutoToc
+
+\authors Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu
+
+\cgalFigureBegin{example_figure,visibility-teaser.png}
+\cgalFigureEnd
+
+\section visibility_2_introduction Introduction
+
+This package provides functionality to compute the visibility region within polygonal regions in two dimensions.
+Using the terminology of the package \ref PkgBooleanSetOperations2Summary, we expect the input polygon
+\f$ P \f$ to be a valid polygon or a valid polygon with holes (the definition is given below).
+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$, note that \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$
+
+
+Definition [Valid Polygon]:
+A polygon \f$ P \f$ is valid if \f$ P \f$ is closed (\f$\partial P \subset P\f$)
+and each boundary loop (only one outer boundary loop in case of no holes) is simple.
+See also \ref PkgBooleanSetOperations2Summary.
+
+
+\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 valid 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 the visibility area \f$ V_q \f$.
+Subsequently 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 actually easier (and 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 it is shown in \cgalFigureRef{definition-fig} (2). For more information about regularization, refer to Chapter
+\ref PkgBooleanSetOperations2Summary.
+
+In summary, this package provides two kinds of visibility region of point \f$ q \f$:
+- Non-regularized visibility area \f$ V_q \f$.
+- Regularized visibility area \f$ \overline{V_q} \f$.
+
+
+\section visibility_2_classes Classes and Algorithms
+
+This package is based on the \ref PkgArrangement2Summary package and exploits several of its features.
+In particular, the output is represented by an `Arrangement_2`, which enables
+the representation of needles. All provided class templates follow the `Visibility_2` concept.
+
+Answering visibility queries is, in many ways, similar to answering point-location queries. Thus, we use the same design used
+to implement point location. Each of the various visibility class templates employs a different algorithm or \em strategy
+\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.} for answering queries.
+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 (subsequently also referred to as the environment).
+Afterwards the visibility object observers changes to the attached arrangement.
+Clearly, it is possible to modify the arrangement after attaching the visibility object.
+However, this should be avoided as this also requires an update of the auxiliary
+data structures in the attached object.
+
+An actual query is then performed by giving the view point \f$ p \f$ and its containing face \f$ f \f$,
+which must represent a valid \cgalFootnote{See the package \ref PkgBooleanSetOperations2Summary for precise definition}
+polygon (\f$ f \f$ has no isolated vertices and each boundary edge of \f$ f \f$ separates it from another face).
+For this purpose every model of the Visibility_2 concept provides two overloaded member functions, called `Visibility_2::compute_visibility()`
+functions, that compute the visibility region of \f$ p \f$ in a bounded polygonal face \f$ f \f$: one is for the case where
+\f$ p \f$ is in the interior of \f$ f \f$; the other one is for the case where \f$ p \f$ is on the boundary of \f$ f \f$.
+
+
+The package provides the following models of the `Visibility_2` concept:
+
+Class | Function | Preprocessing | Query |Algorithm
+-------------------------------|-----------------------------------------------------|-------------------------------|-----------------------------------|-------------------------------
+ `Simple_polygon_visibility_2` | simple valid 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` | valid 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` | valid 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. | new
+
+
+Where \f$ n \f$ is the number of vertices of \f$ f \f$ and \f$ h \f$ is the number of holes+1.
+
+\section benchmarks Runtime in Practice
+
+\cgalFigureBegin{cathedral-fig, cathedral_2.png}
+Example environment 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 1153 vertices. The following table shows the total runtime to compute
+all visibility polygons for all vertices of the boundary 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. 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.
+\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 implentation_history Implementation History
+
+This package was first developed during Google Summer of Code 2013. Fancisc Bungju developed the Simple_polygon_visibility_2 class; Kan Huang developed the Rotational_sweep_visibility_2 class; and Michael Hemmer developed the Triangular_expansion_visibility_2 class.
+
+This first class, Simple_polygon_visibility_2, implements the algorithm presented by B. Joe and R.B. Simpson in 1987 \cite js-clvpa87. This algorithm is a linear time algorithm for simple polygons, fixing the errors in a previous algorithm presented by D.T. Lee in 1983.
+
+The second class, Rotational_sweep_visibility_2, implements the algorithm presented by T. Asano in 1985. This algorithm can be applied to polygons with holes with time complexity \f$ O(n\log n) \f$.
+
+The third class, Triangular_expansion_visibility_2, implements the algorithm presented by F. Bungju, et al.. This algorithm can be applied to polygons with holes with worst case running time \f$ O(n^2) \f$, but is extremely fast in practice.
+
+In Google Summer of Code 2014, Ning Xu became a developer for this package. He fixed bugs in the algorithm for simple polygons.
+
+*/
+
+}
+
+// `Preprocessed_rotational_sweep_visibility_2` | valid 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..38e4ae9d6da
--- /dev/null
+++ b/Visibility_2/examples/Visibility_2/general_polygon_example.cpp
@@ -0,0 +1,56 @@
+
+#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::Vertex_const_handle Vertex_const_handle;
+typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
+typedef Arrangement_2::Face_handle Face_handle;
+typedef CGAL::Triangular_expansion_visibility_2 TEV;
+int main() {
+ 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);
+ Segment_2 s[12];
+ s[0] = Segment_2(p1, p2);
+ s[1] = Segment_2(p2, p3);
+ s[2] = Segment_2(p3, p4);
+ s[3] = Segment_2(p4, p5);
+ s[4] = Segment_2(p5, p6);
+ s[5] = Segment_2(p6, p1);
+
+ s[6] = Segment_2(h1, h2);
+ s[7] = Segment_2(h2, h3);
+ s[8] = Segment_2(h3, h1);
+ s[9] = Segment_2(h4, h5);
+ s[10] = Segment_2(h5, h6);
+ s[11] = Segment_2(h6, h4);
+ Arrangement_2 env;
+ CGAL::insert_non_intersecting_curves(env, &s[0], &s[12]);
+ //find the halfedge whose target is the query point.
+ 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;
+ Arrangement_2::Ccb_halfedge_circulator curr = fh->outer_ccb();
+ std::cout << "Traverse the face of the visibility region." << std::endl;
+ std::cout << "[" << curr->curve() << "]"<< std::endl;
+ while (++curr != fh->outer_ccb())
+ std::cout << "[" << curr->curve() << "]" << 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..43adf31904e
--- /dev/null
+++ b/Visibility_2/examples/Visibility_2/simple_polygon_visibility_2.cpp
@@ -0,0 +1,65 @@
+#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::Edge_const_iterator Edge_const_iterator;
+typedef Arrangement_2::Face_handle Face_handle;
+typedef Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator;
+typedef CGAL::Simple_polygon_visibility_2
+ NSPV;
+typedef CGAL::Simple_polygon_visibility_2
+ RSPV;
+
+int main() {
+ //create environment
+ Point_2 p1(0, 4), p2(0, 0), p3(3, 2), p4(4, 0), p5(4, 4), p6(1, 2);
+ Segment_2 s[6];
+ s[0] = Segment_2(p1, p2);
+ s[1] = Segment_2(p2, p3);
+ s[2] = Segment_2(p3, p4);
+ s[3] = Segment_2(p4, p5);
+ s[4] = Segment_2(p5, p6);
+ s[5] = Segment_2(p6, p1);
+ Arrangement_2 env;
+ CGAL::insert_non_intersecting_curves(env, &s[0], &s[6]);
+ //locate the query point in the arrangement
+ Point_2 query_point(0.5, 2);
+ Arrangement_2::Face_const_handle face;
+ CGAL::Arr_naive_point_location pl(env);
+ CGAL::Object obj = pl.locate(query_point);
+ CGAL::assign(face, obj);
+ //visibility query
+ Arrangement_2 non_regular_output;
+ NSPV non_regular_visibility(env);
+ Face_handle non_regular_fh = non_regular_visibility.compute_visibility(query_point, 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->curve() << "]" << std::endl;
+ Arrangement_2 regular_output;
+ RSPV regular_visibility(env);
+ Face_handle regular_fh = regular_visibility.compute_visibility(query_point, face, regular_output);
+ Ccb_halfedge_circulator curr = regular_fh->outer_ccb();
+ 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->curve() << "]" << std::endl;
+
+ //For a regular face, we can also get its whole boundary by traversing its outer CCB.
+ std::cout << "Traverse the face of the regularized visibility region:" << std::endl;
+ std::cout << "[" << curr->curve() << "]"<< std::endl;
+ while (++curr != regular_fh->outer_ccb())
+ std::cout << "[" << curr->curve() << "]" << std::endl;
+ return 0;
+}
+
diff --git a/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h
new file mode 100644
index 00000000000..29384febac4
--- /dev/null
+++ b/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h
@@ -0,0 +1,1008 @@
+// 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): Ning Xu
+//
+
+#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
+#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#define MYDEBUG
+#ifdef MYDEBUG
+ #include
+ using namespace std;
+#endif
+
+namespace CGAL {
+
+template < class Arrangement_2_, class RegularizationTag = CGAL::Tag_true >
+class Rotational_sweep_visibility_2
+{
+public:
+ typedef Arrangement_2_ Arrangement_2;
+ typedef RegularizationTag Regularization_tag;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Arrangement_2::Traits_2 Traits_2;
+ typedef CGAL::Tag_true Supports_general_polygon_tag;
+ typedef CGAL::Tag_true Supports_simple_polygon_tag;
+
+ typedef typename Geometry_traits_2::FT Number_type;
+ 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::Direction_2 Direction_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::Hole_const_iterator Hole_const_iterator;
+ typedef typename Arrangement_2::Ccb_halfedge_const_circulator
+ Circulator;
+
+
+private:
+ template < class Arr_2_ED >
+ class Edge
+ {
+ public:
+ typedef Arr_2_ED Arrangement_2;
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ typedef typename Geometry_traits_2::FT Number_type;
+ typedef typename Arrangement_2::Ccb_halfedge_const_circulator
+ Circulator;
+ private:
+ Circulator circ;
+ CGAL::Orientation orient;
+ CGAL::Orientation boundary_orient;
+ enum { NOT_APPLIED, INWARD, OUTWARD, IN_EDGE, AT_SOURCE, AT_TARGET } mode;
+ int idx;
+ int prev_idx;
+ int quad;
+ private:
+ int compute_quad( const Point_2& query_pt, const Point_2& p )
+ {
+ CGAL::Comparison_result cx = CGAL::compare_x( query_pt, p );
+ CGAL::Comparison_result cy = CGAL::compare_y( query_pt, p );
+ if ( cy == CGAL::SMALLER ) {
+ if ( cx == CGAL::SMALLER )
+ return 0;
+ else
+ return 1;
+ } else if ( cy == CGAL::LARGER ) {
+ if ( cx == CGAL::LARGER )
+ return 2;
+ else
+ return 3;
+ } else {
+ if ( cx != CGAL::LARGER )
+ return 0;
+ else
+ return 2;
+ }
+ }
+ public:
+ Edge ( const Point_2& query_pt, const Circulator& he, bool on_edge, bool on_vertex )
+ : circ( he )
+ {
+ if ( on_vertex ) {
+ orient = CGAL::COLLINEAR;
+ if ( query_pt == he->source()->point() )
+ mode = AT_SOURCE;
+ else if ( query_pt == he->target()->point() )
+ mode = AT_TARGET;
+ else
+ mode = IN_EDGE;
+ } else if ( on_edge ) {
+ orient = CGAL::COLLINEAR;
+ mode = IN_EDGE;
+ } else {
+ orient = CGAL::orientation( query_pt,
+ he->source()->point(),
+ he->target()->point() );
+ if ( orient == CGAL::COLLINEAR ) {
+ if ( CGAL::collinear_are_ordered_along_line( query_pt,
+ he->source()->point(),
+ he->target()->point() ) )
+ mode = OUTWARD;
+ else
+ mode = INWARD;
+ } else {
+ mode = NOT_APPLIED;
+ }
+ }
+ quad = compute_quad( query_pt, he->source()->point() );
+ boundary_orient = CGAL::orientation( prev_source(), source(), target() );
+ }
+ void set_index ( int i, int p )
+ { idx = i; prev_idx = p; }
+
+ const Point_2& source () const
+ { return circ->source()->point(); }
+ const Point_2& target () const
+ { return circ->target()->point(); }
+ const Point_2& prev_source() const
+ { return circ->prev()->source()->point(); }
+ const Point_2& next_target() const
+ { return circ->next()->target()->point(); }
+ Circulator circulator () const
+ { return circ; }
+ CGAL::Orientation orientation () const
+ { return orient; }
+ CGAL::Orientation boundary_orientation () const
+ { return boundary_orient; }
+ bool inward () const
+ { return ( mode == INWARD ); }
+ bool outward () const
+ { return ( mode == OUTWARD ); }
+ bool in_edge () const
+ { return ( mode == IN_EDGE ); }
+ bool at_source () const
+ { return ( mode == AT_SOURCE ); }
+ bool at_target () const
+ { return ( mode == AT_TARGET ); }
+ int index () const
+ { return idx; }
+ int prev_index () const
+ { return prev_idx; }
+ int quadrant () const
+ { return quad; }
+ bool angle_less_than_pi () const
+ { return ( quadrant() < 2 ); }
+
+#ifdef MYDEBUG
+ void trace ( ostream& os )
+ {
+ os << "source=[" << source() << "],target=[" << target() << "],";
+ os << "orientation=[";
+ switch( orient ) {
+ case CGAL::LEFT_TURN:
+ os << "left";
+ break;
+ case CGAL::RIGHT_TURN:
+ os << "right";
+ break;
+ case CGAL::COLLINEAR:
+ os << "collinear";
+ break;
+ }
+ os << "],mode =[";
+ switch( mode ) {
+ case INWARD:
+ os << "inward";
+ break;
+ case OUTWARD:
+ os << "outward";
+ break;
+ case IN_EDGE:
+ os << "in_edge";
+ break;
+ case AT_SOURCE:
+ os << "at_source";
+ break;
+ case AT_TARGET:
+ os << "at_target";
+ break;
+ case NOT_APPLIED:
+ os << "not_applied";
+ break;
+ }
+ os << "]" << endl;
+ os << "\t\tquadrant=[" << quadrant() << "], idx=[" << index() << "], prev_idx=[" << prev_index() << "]" << endl;
+ }
+#endif
+ };
+
+ /*
+ class Less_Source
+ Compare the halfedges with their source point by their polar angle.
+ The class rovides a comparator:
+ Less_Source( const Edge_type& he1, const Edge_type& he2 )
+ where he1 and he2 are two half edges.
+
+ Precondition: he1 != he2
+
+ Special cases:
+ 1) If two source points have the same angle, the halfedge goes outward
+ or makes a right turn is less than the halfedge goes inward
+ or makes a left turn.
+ If two halfedges both go outward or make a right turn, the one with
+ closer source point is less.
+ If two halfedges both go inward or make a left turn, the one with
+ farther source point is less.
+ 2) If the source of an halfedge is the query point, consider the case
+ as moving the source point slightly along the line through the
+ halfedge, either toward the target or away the target, so that
+ the query point is still in the face.
+ */
+ template < class E >
+ class Less_Source
+ {
+ private:
+ typedef E Edge_type;
+ typedef typename E::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ typedef typename Geometry_traits_2::FT Number_type;
+ private:
+ // less_source_at_query_pt
+ // Precondition: he1.source() == query_pt
+ bool less_source_at_query_pt( const Edge_type& he1, const Edge_type& he2 )
+ {
+ CGAL::Orientation orient1 = he1.boundary_orientation();
+ CGAL::Orientation orient2 = CGAL::orientation( he1.source(), he1.target(), he2.source() );
+ if ( orient1 == CGAL::LEFT_TURN ) {
+ // The boundary makes a left turn at query_pt
+ // Consider the case as moving he1.source() slightly
+ // along the line through he1, away he1.target()
+ if ( orient2 == CGAL::COLLINEAR ) {
+ // he1.source(), he1.target(), he2.source() are collinear
+ if ( CGAL::collinear_are_ordered_along_line( he2.source(), he1.source(), he1.target() ) ) {
+ // he1.source() is between he1.target() and he2.source()
+ // he1 will be considered going inward
+ return false;
+ } else {
+ // he1.source(), he1.target(), he2.source() are ordered along ray
+ return !he2.angle_less_than_pi();
+ }
+ } else if ( orient2 == CGAL::LEFT_TURN ) {
+ // he1.source(), he1.target(), he2.source() make a left turn
+ if ( he2.angle_less_than_pi() ) {
+ return false;
+ } else {
+ return ( he1.target().y() < query_pt.y() ||
+ ( he1.target().y() == query_pt.y() &&
+ he1.target().x() < query_pt.x() ) );
+ }
+ } else {
+ // he1.source(), he1.target(), he2.source() make a right turn
+ if ( he2.angle_less_than_pi() ) {
+ return ( he1.target().y() < query_pt.y() ||
+ ( he1.target().y() == query_pt.y() &&
+ he1.target().x() < query_pt.x() ) );
+ } else {
+ return true;
+ }
+ }
+ } else {
+ // The boundary makes a right turn at query_pt,
+ // or does not make a turn at query_pt.
+ // Consider the case as moving he1.source() slightly
+ // along the line through he1, toward he1.target()
+ if ( orient2 == CGAL::COLLINEAR ) {
+ // he1.source(), he1.target(), he2.source() are collinear
+ if ( CGAL::collinear_are_ordered_along_line( he2.source(), he1.source(), he1.target() ) ) {
+ // he1.source() is between he1.target() and he2.source()
+ return !he2.angle_less_than_pi();
+ } else {
+ // he1.source(), he1.target(), he2.source() are ordered along ray
+ return true;
+ }
+ } else if ( orient2 == CGAL::LEFT_TURN ) {
+ // he1.source(), he1.target(), he2.source() make a left turn
+ if ( he2.angle_less_than_pi() ) {
+ return ( he1.target().y() > query_pt.y() ||
+ ( he1.target().y() == query_pt.y() &&
+ he1.target().x() > query_pt.x() ) );
+ } else {
+ return true;
+ }
+ } else {
+ // he1.source(), he1.target(), he2.source() make a right turn
+ if ( he2.angle_less_than_pi() ) {
+ return false;
+ } else {
+ return ( he1.target().y() > query_pt.y() ||
+ ( he1.target().y() == query_pt.y() &&
+ he1.target().x() > query_pt.x() ) );
+ }
+ }
+ }
+ }
+ // less
+ bool less ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ if ( he2.at_source() )
+ return !less_source_at_query_pt( he2, he1 );
+ if ( he1.at_source() )
+ return less_source_at_query_pt( he1, he2 );
+
+ if ( he1.quadrant() != he2.quadrant() )
+ return ( he1.quadrant() < he2.quadrant() );
+ // In the same quadrant
+ CGAL::Orientation orient = CGAL::orientation( query_pt, he1.source(), he2.source() );
+ if ( orient != CGAL::COLLINEAR ) {
+ // General case, in the same quadrant
+ return ( orient == CGAL::LEFT_TURN );
+ } else {
+ // query_pt, he1.source(), he2.source() are collinear on a ray
+ if ( CGAL::collinear_are_ordered_along_line( query_pt, he1.source(), he2.source() ) ) {
+ // he1.source() is closer
+ return ( he1.orientation() == CGAL::RIGHT_TURN || he1.outward() );
+ } else {
+ // he2.source() is closer
+ return !( he2.orientation() == CGAL::RIGHT_TURN || he2.outward() );
+ }
+ }
+ }
+ public:
+ // Constructor
+ Less_Source( const Point_2& q )
+ : query_pt( q )
+ {}
+ // Comparator
+ // Precondition: he1 and he2 are not the same halfedge
+ bool operator () ( const Edge_type& he1, const Edge_type& he2 )
+ { return less( he1, he2 ); }
+ private:
+ Point_2 query_pt;
+ Point_2 aux;
+ };
+
+ /*
+ class Less_Edge
+ Compare the halfedges intersecting a ray, find whose intersection point
+ is closer to the query point.
+ The class rovides a comparator:
+ Less_Edge( const Edge_type& he1, const Edge_type& he2 )
+ where he1 and he2 are two half edges.
+
+ Precondition: he1 != he2
+ */
+ template < class E >
+ class Less_Edge
+ {
+ private:
+ typedef E Edge_type;
+ typedef typename E::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ private:
+ Point_2 query_pt;
+ private:
+ // less_vertex
+ // Precondition: (1) he1 contains query_pt
+ // (2) he2 does not contain query_pt
+ bool less_vertex ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ assert( !(he2.at_source() || he2.at_target() || he2.in_edge() ) );
+ return true;
+ }
+ // less_consecutive
+ // Precondition: (1) Both he1 and he2 does not contain query_pt
+ // (2) he1 is the previous halfedge of he2
+ bool less_consecutive ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ if ( he1.outward() )
+ return true;
+ else if ( he1.inward() )
+ return false;
+ else if ( he1.orientation() == CGAL::LEFT_TURN ) {
+ return ( he2.boundary_orientation() == CGAL::RIGHT_TURN );
+ } else {
+ // he1.orientation() == CGAL::RIGHT_TURN
+ return ( he2.boundary_orientation() != CGAL::RIGHT_TURN );
+ }
+ }
+ // less_collinear
+ // Precondition: (1) Both he1 and he2 does not contain query_pt
+ // (2) he1 and he2 are not incident
+ // (3) query_pt, he1.source(), he1.target() are collinear
+ bool less_collinear ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ if ( he2.inward() || he2.outward() ) {
+ return CGAL::collinear_are_ordered_along_line( query_pt,
+ he1.source(),
+ he2.source() );
+ } else {
+ return ( CGAL::orientation( he2.source(), he2.target(), he1.source() )
+ == he2.orientation() );
+ }
+ }
+ // less_general
+ // Precondition: (1) Both he1 and he2 does not contain query_pt
+ // (2) he1 and he2 are not incident
+ // (3) he1.orientation() == CGAL::LEFT_TURN || RIGHT_TURN
+ // (4) he2.orientation() == CGAL::LEFT_TURN || RIGHT_TURN
+ bool less_general ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ CGAL::Orientation orient1 = CGAL::orientation( he1.source(),
+ he1.target(),
+ he2.source() );
+ CGAL::Orientation orient2 = CGAL::orientation( he1.source(),
+ he1.target(),
+ he2.target() );
+ if ( orient1 == orient2 ) {
+ // he2.source() and he2.target() lies on the same side of he1
+ return ( CGAL::orientation( he1.source(), he1.target(), query_pt )
+ != orient1 );
+ } else {
+ // he2.source() and he2.target() lies on the different side of he1
+ return ( CGAL::orientation( he2.source(), he2.target(), he1.source() )
+ == he2.orientation() );
+ }
+ }
+ // less
+ bool less ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ if ( he1.circulator() == he2.circulator() )
+ return false;
+ if ( he1.at_source() || he1.at_target() || he1.in_edge() )
+ return less_vertex( he1, he2 );
+ if ( he2.at_source() || he2.at_target() || he2.in_edge() )
+ return !less_vertex( he2, he1 );
+ if ( he1.index() == he2.prev_index() )
+ return less_consecutive( he1, he2 );
+ if ( he1.prev_index() == he2.index() )
+ return !less_consecutive( he2, he1 );
+ if ( he1.inward() || he1.outward() )
+ return less_collinear( he1, he2 );
+ if ( he2.inward() || he2.outward() )
+ return !less_collinear( he2, he1 );
+ return less_general( he1, he2 );
+ }
+ public:
+ Less_Edge ( const Point_2& q )
+ : query_pt( q )
+ {}
+ bool operator () ( const Edge_type& he1, const Edge_type& he2 )
+ { return less( he1, he2 ); }
+ };
+
+ template < class E, class Comp >
+ class Active_Edge
+ {
+ private:
+ typedef E Edge_type;
+ typedef Comp Sorter;
+ typedef typename E::Geometry_traits_2 Geometry_traits_2;
+ typedef typename Geometry_traits_2::Point_2 Point_2;
+ typedef typename std::set Active_edge_container;
+ typedef typename std::vector Edge_vector;
+ private:
+ Active_edge_container active_edges;
+ const Edge_vector * p_edges;
+ std::vector active;
+ public:
+ Active_Edge ( const Edge_vector * pe, const Sorter& s )
+ : p_edges( pe ), active_edges( s )
+ { active.assign( pe->size(), false ); }
+
+ void insert ( const Edge_type& he )
+ {
+ active_edges.insert( he );
+ active[he.index()] = true;
+ }
+ void erase ( const Edge_type& he )
+ {
+ active_edges.erase( he );
+ active[he.index()] = false;
+ }
+ void replace ( const Edge_type& he1, const Edge_type& he2 )
+ {
+ typename Active_edge_container::const_iterator ait;
+ ait = active_edges.find( he1 );
+ assert( ait != active_edges.end() );
+ const Edge_type& const_he = *ait;
+ Edge_type& tmp_he = const_cast(const_he);
+ tmp_he = he2;
+ active[he1.index()] = false;
+ active[he2.index()] = true;
+ }
+ bool is_active( int idx ) const
+ { return active[idx]; }
+ const Edge_type& closest () const
+ { return *(active_edges.begin()); }
+#ifdef MYDEBUG
+ void trace ( ostream& os )
+ {
+ typename Active_edge_container::const_iterator ait;
+ for( ait = active_edges.begin(); ait != active_edges.end(); ait++ ) {
+ cout << "Edge: " << ait->source() << " --> " << ait->target() << endl;
+ }
+ cout << "Active:[ ";
+ for ( int i = 0; i < active.size(); i++ ) {
+ if ( active[i] )
+ cout << i << " ";
+ }
+ cout << "]" << endl;
+ }
+#endif
+ };
+
+private:
+ typedef Edge Edge_type;
+ typedef std::vector Edge_vector;
+ typedef typename Edge_vector::const_iterator Edge_iterator;
+ typedef Less_Edge Active_edge_sorter;
+
+private:
+ // do_intersect_ray
+ // Verify whether the halfedge he will intersect the ray obtained by
+ // by slightly rotating the ray (query_pt, aux ) clockwisely
+ bool do_intersect_ray ( const Point_2& query_pt, const Point_2& aux, const Edge_type& he )
+ {
+ if ( he.orientation() != CGAL::COLLINEAR ) {
+ CGAL::Orientation orient1 = CGAL::orientation( query_pt, aux, he.source() );
+ CGAL::Orientation orient2 = CGAL::orientation( query_pt, aux, he.target() );
+ if ( orient1 == orient2 )
+ return false;
+ if ( orient1 == CGAL::COLLINEAR ) {
+ if ( CGAL::collinear_are_ordered_along_line( aux, query_pt, he.source() ) )
+ return false;
+ // Ray intersects he at he.source()
+ return ( he.orientation() == CGAL::RIGHT_TURN );
+ } else if ( orient2 == CGAL::COLLINEAR ) {
+ if ( CGAL::collinear_are_ordered_along_line( aux, query_pt, he.target() ) )
+ return false;
+ // Ray intersects he at he.target()
+ return ( he.orientation() == CGAL::LEFT_TURN );
+ } else {
+ return ( CGAL::orientation( query_pt, aux, he.target() ) == he.orientation() );
+ }
+ } else if ( he.inward() || he.outward() ) {
+ return false;
+ } else if ( he.at_source() ) {
+ CGAL::Orientation orient1 = CGAL::orientation( he.prev_source(), he.source(), he.target() );
+ if ( orient1 == CGAL::LEFT_TURN ) {
+ // The boundary makes a left turn at the query_pt
+ // Consider the case as moving he.source() slightly along the line
+ // through he, away he.target()
+ CGAL::Orientation orient2 = CGAL::orientation( he.source(), he.target(), aux );
+ if ( orient2 == CGAL::LEFT_TURN ) {
+ return false;
+ } else if ( orient2 == CGAL::RIGHT_TURN ) {
+ return true;
+ } else {
+ // he.source(), he.target(), aux ) are collinear
+ return !CGAL::collinear_are_ordered_along_line( aux, he.source(), he.target() );
+ }
+ } else {
+ // The boundary makes a right turn or does not turn at the query_pt
+ // Consider the case as moving he.source() slightly along the line
+ // through he, toward he.target()
+ return false;
+ }
+ } else if ( he.at_target() ) {
+ CGAL::Orientation orient1 = CGAL::orientation( he.source(), he.target(), he.next_target() );
+ if ( orient1 == CGAL::LEFT_TURN ) {
+ // The boundary makes a left turn at the query_pt
+ CGAL::Orientation orient2 = CGAL::orientation( he.target(), he.next_target(), aux );
+ if ( orient2 == CGAL::LEFT_TURN ) {
+ return ( CGAL::orientation( he.source(), he.target(), aux ) == CGAL::RIGHT_TURN );
+ } else if ( orient2 == CGAL::RIGHT_TURN ) {
+ return false;
+ } else {
+ return CGAL::collinear_are_ordered_along_line( aux, he.target(), he.next_target() );
+ }
+ } else if ( orient1 == CGAL::RIGHT_TURN ) {
+ // The boundary makes a right turn at the query_pt
+ CGAL::Orientation orient2 = CGAL::orientation( he.target(), he.next_target(), aux );
+ if ( orient2 == CGAL::LEFT_TURN ) {
+ return false;
+ } else if ( orient2 == CGAL::RIGHT_TURN ) {
+ return ( CGAL::orientation( he.source(), he.target(), aux ) == CGAL::RIGHT_TURN );
+ } else {
+ return !CGAL::collinear_are_ordered_along_line( aux, he.target(), he.next_target() );
+ }
+ }
+ } else {
+ // he.in_edge() == true
+ CGAL::Orientation orient1 = CGAL::orientation( query_pt, he.target(), aux );
+ if ( orient1 == CGAL::LEFT_TURN ) {
+ return false;
+ } else if ( orient1 == CGAL::RIGHT_TURN ) {
+ return true;
+ } else {
+ return !CGAL::collinear_are_ordered_along_line( aux, query_pt, he.target() );
+ }
+ }
+ }
+ Point_2 calculate_intersection( const Point_2& query_pt, const Point_2& aux, const Circulator& he )
+ {
+ Ray_2 ray ( query_pt, aux );
+ Segment_2 seg ( he->source()->point(), he->target()->point() );
+ CGAL::Object res = CGAL::intersection( ray, seg );
+ const Point_2 * ipoint = CGAL::object_cast(&res);
+ if ( ipoint ) {
+ return *ipoint;
+ } else {
+ assert( seg.has_on( query_pt ) );
+ return query_pt;
+ }
+ }
+ void compute_visibility_partition ( const Point_2& query_pt,
+ Edge_iterator first,
+ Edge_iterator last,
+ std::vector& out_points )
+ {
+ Point_2 aux;
+ Active_edge_sorter closer( query_pt );
+ Active_Edge< Edge_type, Active_edge_sorter > active( &unsorted_edges, closer );
+
+ // Initialize the edges intersecting the ray
+ aux = first->source();
+ if ( query_on_vertex && query_pt == aux ) {
+ CGAL::Orientation orient1 = CGAL::orientation( first->prev_source(), first->source(), first->target() );
+ if ( orient1 == CGAL::LEFT_TURN ) {
+ aux = Point_2( query_pt.x()+query_pt.x()-first->target().x(), query_pt.y()+query_pt.y()-first->target().y() );
+ } else {
+ aux = first->target();
+ }
+ }
+
+ for ( Edge_iterator eit = edges.begin(); eit != edges.end(); eit++ ) {
+ if ( do_intersect_ray( query_pt, aux, *eit ) ) {
+ active.insert( *eit );
+ }
+ }
+
+#ifdef MYDEBUG
+cout << "query_pt = [" << query_pt << "]" <source();
+ int idx = eit->index();
+ int prev = eit->prev_index();
+ Circulator top = active.closest().circulator();
+ assert( unsorted_edges[idx].circulator() == eit->circulator() );
+
+#ifdef MYDEBUG
+cout << "idx = " << idx << " , prev = " << prev << endl;
+cout << "Current edge: " << eit->source() << " --> " << eit->target() << " Previous edge: " << unsorted_edges[prev].source() << " --> " << unsorted_edges[prev].target() << endl;
+cout << "top: " << top->source()->point() << " --> " << top->target()->point() << endl;
+#endif
+
+ if ( active.is_active( idx ) && active.is_active( prev ) ) {
+ // Both edges incident to the current vertex are active
+#ifdef MYDEBUG
+cout << "Both Active!" << endl;
+#endif
+
+ active.erase( *eit );
+ active.erase( unsorted_edges[prev] );
+ if ( top != active.closest().circulator() ) {
+ Point_2 u;
+ u = calculate_intersection( query_pt, aux, active.closest().circulator() );
+ if ( last_pt != eit->source() )
+ out_points.push_back( eit->source() );
+ out_points.push_back( u );
+ last_pt = u;
+#ifdef MYDEBUG
+cout << "New Top! Intersection = " << u << endl;
+#endif
+ }
+ } else if ( active.is_active( idx ) ) {
+#ifdef MYDEBUG
+cout << "Current Active!" << endl;
+#endif
+ // Only one edge whose source is the current vertex is active.
+ active.replace( *eit, unsorted_edges[prev] );
+ if ( top != active.closest().circulator() ) {
+ if ( last_pt != eit->source() ) {
+ out_points.push_back( eit->source() );
+ last_pt = eit->source();
+ }
+#ifdef MYDEBUG
+cout << "New Top! Intersection = " << eit->source() << endl;
+#endif
+ }
+ } else if ( active.is_active( prev ) ) {
+#ifdef MYDEBUG
+cout << "Previous Active!" << endl;
+#endif
+ // Only one edge whose target is the current vertex is active.
+ active.replace( unsorted_edges[prev], *eit );
+ if ( top != active.closest().circulator() ) {
+ if ( last_pt != eit->source() ) {
+ out_points.push_back( eit->source() );
+ last_pt = eit->source();
+ }
+#ifdef MYDEBUG
+cout << "New Top! Intersection = " << eit->source() << endl;
+#endif
+ }
+ } else {
+ // Both edges incident to the current vertex are not active
+#ifdef MYDEBUG
+cout << "Both Inctive!" << endl;
+#endif
+ active.insert( *eit );
+ active.insert( unsorted_edges[prev] );
+ if ( top != active.closest().circulator() ) {
+ Point_2 u;
+ if ( query_on_vertex && query_pt == aux )
+ u = aux;
+ else
+ u = calculate_intersection( query_pt, aux, top );
+ if ( last_pt != u )
+ out_points.push_back( u );
+ out_points.push_back( eit->source() );
+ last_pt = eit->source();
+#ifdef MYDEBUG
+cout << "New Top! Intersection = " << u << endl;
+#endif
+ }
+ }
+#ifdef MYDEBUG
+cout << "*** After Iteration ***" << endl;
+active.trace( cout );
+cout << endl;
+#endif
+ }
+
+ if ( first_pt != last_pt ) {
+ if ( first_at_vertex ||
+ ( CGAL::orientation( out_points.front(), out_points.back(), first_pt ) != CGAL::COLLINEAR ) )
+ out_points.push_back( first_pt );
+ }
+#ifdef MYDEBUG
+cout << "Visibility segments:" << endl;
+for ( int i = 0; i < out_points.size(); i++ ) {
+ cout << out_points[i] << endl;
+}
+cout << endl;
+#endif
+ }
+
+
+ template < class VARR >
+ typename VARR::Face_handle
+ compute_visibility_impl ( const Point_2& query_pt, VARR& arr_out )
+ {
+ Point_2 aux( query_pt.x()+Number_type(1), query_pt.y() );
+ Less_Source comp ( query_pt );
+ // Sort halfedges with their source point by polar angle
+ std::sort( edges.begin(), edges.end(), comp );
+#ifdef MYDEBUG
+for ( int i = 0; i < edges.size(); i++ ) {
+ for ( int j = 0; j < edges.size(); j++ ) {
+ if ( i == j )
+ continue;
+ bool res = comp( edges[i], edges[j] );
+ if ( res != ( i < j ) ) {
+ cout << "WRONG: Edges1: " << edges[i].source() << " --> " << edges[i].target() << " ";
+ cout << "Edges2: " << edges[j].source() << " --> " << edges[j].target() << " ";
+ if ( res )
+ cout << "Result: 1<2" < vec;
+ compute_visibility_partition( query_pt, edges.begin(), edges.end(), vec );
+
+ // Construct arrangement
+ CGAL::Visibility_2::report_while_handling_needles
+ < Rotational_sweep_visibility_2 >
+ ( geom_traits, query_pt, vec, arr_out );
+
+ conditional_regularize( arr_out, Regularization_tag() );
+
+ edges.clear();
+ unsorted_edges.clear();
+
+ return arr_out.faces_begin();
+ }
+
+ /*! Regularize output if flag is set to true*/
+ template
+ void conditional_regularize(VARR& out_arr, CGAL::Tag_true) {
+ regularize_output(out_arr);
+ }
+ /*! No need to regularize output if flag is set to false*/
+ template
+ void conditional_regularize(VARR& out_arr, CGAL::Tag_false) {
+ //do nothing
+ }
+
+ /*! Regularizes the output - removes edges that have the same face on both
+ sides */
+ template
+ void regularize_output(VARR& out_arr) {
+ typename VARR::Edge_iterator e_itr;
+ for (e_itr = out_arr.edges_begin() ;
+ e_itr != out_arr.edges_end() ; e_itr++) {
+
+ typename VARR::Halfedge_handle he = e_itr;
+ typename VARR::Halfedge_handle he_twin = he->twin();
+ if (he->face() == he_twin->face()) {
+ out_arr.remove_edge(he);
+ }
+ }
+ }
+
+public:
+ // Constructor
+ 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 ()
+ { return std::string( "R_visibility_2" ); }
+ 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& arr () const
+ { return *p_arr; }
+
+ template < typename VARR >
+ typename VARR::Face_handle
+ compute_visibility ( const Point_2& query_pt,
+ const Halfedge_const_handle he,
+ VARR& arr_out )
+ {
+ Face_const_handle f = he->face();
+ assert( !f->is_unbounded() );
+
+ Halfedge_const_handle he2 = he;
+ query_on_edge = true;
+ query_on_vertex = false;
+ if ( query_pt == he2->target()->point() )
+ he2 = he2->next();
+ if ( query_pt == he2->source()->point() )
+ query_on_vertex = true;
+
+ arr_out.clear();
+ edges.clear();
+
+ Circulator circ, curr;
+ Circulator qedge( he2 );
+ Circulator qprev( he2->prev() );
+
+ int hole_base = 0, hole_edge = 0;
+
+ if ( f->has_outer_ccb() ) {
+ curr = circ = f->outer_ccb();
+ do {
+ bool on_edge = false, on_vertex = false;
+ if ( curr == qedge ) {
+ on_edge = true;
+ on_vertex = query_on_vertex;
+ } else if ( curr == qprev ) {
+ on_edge = on_vertex = query_on_vertex;
+ }
+ edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex ) );
+ hole_edge++;
+ } while ( ++curr != circ );
+ for ( int i = 0; i < hole_edge; i++ ) {
+ edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge );
+ }
+ hole_base += hole_edge;
+ }
+ for ( Hole_const_iterator hi = f->holes_begin();
+ hi != f->holes_end(); hi++ ) {
+ curr = circ = *hi;
+ hole_edge = 0;
+ do {
+ bool on_edge = false, on_vertex = false;
+ if ( curr == qedge ) {
+ on_edge = true;
+ on_vertex = query_on_vertex;
+ } else if ( curr == qprev ) {
+ on_edge = on_vertex = query_on_vertex;
+ }
+ edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex ) );
+ hole_edge++;
+ } while ( ++curr != circ );
+ for ( int i = 0; i < hole_edge; i++ ) {
+ edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge );
+ }
+ hole_base += hole_edge;
+ }
+
+ unsorted_edges.assign( edges.begin(), edges.end() );
+
+ return compute_visibility_impl( query_pt, arr_out );
+ }
+
+ template < typename VARR >
+ typename VARR::Face_handle
+ compute_visibility ( const Point_2& query_pt,
+ const Face_const_handle f,
+ VARR& arr_out )
+ {
+ assert( !f->is_unbounded() );
+
+ query_on_edge = query_on_vertex = false;
+ arr_out.clear();
+ edges.clear();
+
+ Circulator circ, curr;
+
+ int hole_base = 0, hole_edge = 0;
+
+ if ( f->has_outer_ccb() ) {
+ curr = circ = f->outer_ccb();
+ do {
+ edges.push_back( Edge_type( query_pt, curr, false, false ) );
+ hole_edge++;
+ } while ( ++curr != circ );
+ for ( int i = 0; i < hole_edge; i++ ) {
+ edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge );
+ }
+ hole_base += hole_edge;
+ }
+ for ( Hole_const_iterator hi = f->holes_begin();
+ hi != f->holes_end(); hi++ ) {
+ curr = circ = *hi;
+ hole_edge = 0;
+ do {
+ edges.push_back( Edge_type( query_pt, curr, false, false ) );
+ hole_edge++;
+ } while ( ++curr != circ );
+ for ( int i = 0; i < hole_edge; i++ ) {
+ edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge );
+ }
+ hole_base += hole_edge;
+ }
+
+ unsorted_edges.assign( edges.begin(), edges.end() );
+
+ return compute_visibility_impl( query_pt, arr_out );
+ }
+
+private:
+ const Arrangement_2 * p_arr;
+ const Geometry_traits_2 * geom_traits;
+
+ bool query_on_edge;
+ bool query_on_vertex;
+ Edge_vector edges;
+ Edge_vector unsorted_edges;
+}; // End of class Rotational_sweep_visibility_2
+
+} // End namespace CGAL
+
+#endif
diff --git a/Visibility_2/include/CGAL/Preprocessed_rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Preprocessed_rotational_sweep_visibility_2.h
new file mode 100644
index 00000000000..730375cd1e6
--- /dev/null
+++ b/Visibility_2/include/CGAL/Preprocessed_rotational_sweep_visibility_2.h
@@ -0,0 +1,106 @@
+// 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_PREPROCESSED_VISIBILITY_2_H
+#define CGAL_PREPROCESSED_VISIBILITY_2_H
+
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+template
+class Preprocessed_visibility_2 {
+
+public:
+ typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
+ // Currently only consider with same type for both
+ typedef Arrangement_2 Input_Arrangement_2;
+ typedef Arrangement_2 Output_Arrangement_2;
+
+ 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::Face_const_handle Face_const_handle;
+ typedef typename Arrangement_2::Kernel Kernel;
+ typedef typename CGAL::Arr_linear_traits_2 Linear_traits_2;
+
+ 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::FT Number_type;
+
+ typedef typename CGAL::Arrangement_2 Line_Arrangement_2;
+
+ Preprocessed_visibility_2() : p_arr(NULL) {};
+
+ /*! Constructor given an arrangement and the Regularization tag. */
+ Preprocessed_visibility_2(Input_Arrangement_2& arr/*, Regularization_tag r_t*/): p_arr(&arr) {};
+
+ bool is_attached() {
+ return (p_arr != NULL);
+ }
+
+ void attach(Input_Arrangement_2& arr) {
+ p_arr = &arr;
+ }
+
+ void detach() {
+ p_arr = NULL;
+ }
+
+ Input_Arrangement_2 arr() {
+ return *p_arr;
+ }
+
+ void compute_visibility(const Point_2& q,
+ const Face_const_handle face,
+ Output_Arrangement_2& out_arr
+ ) {
+
+ }
+
+ void compute_visibility(const Point_2& q,
+ const Halfedge_const_handle he,
+ Output_Arrangement_2& out_arr
+ ) {
+
+}
+
+private:
+ Input_Arrangement_2* arr;
+ Line_Arrangement_2 line_arr;
+ void preprocess() {
+
+ }
+
+ Line_2 dual_line(const Point_2& p) {
+ return Line_2(p.x(), -1, -p.y());
+ }
+
+};
+
+} // namespace CGAL
+
+#endif
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..fd378f8f69f
--- /dev/null
+++ b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h
@@ -0,0 +1,866 @@
+// 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
+
+
+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 RegularizationTag Regularization_tag;
+ typedef CGAL::Tag_true Supports_general_polygon_tag;
+ typedef CGAL::Tag_true Supports_simple_polygon_tag;
+
+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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+
+ };
+
+// Using hash_map or edx causes a seg fault, did not have the time to see why. Michael
+// class Hash_edge: public std::unary_function::result_type> {
+// public:
+// typename boost::hash::result_type
+// operator() (const EH e1) const {
+// return boost::hash()(&(e1->curve()));
+// }
+// };
+
+
+ const Geometry_traits_2 *geom_traits;
+ const Arrangement_2 *p_arr;
+ Point_2 q; //query point
+ Points polygon; //visibility polygon
+ std::map incident_edges; //the edges that are
+ std::map edx; //index of active edges in the heap
+ // boost::unordered_map edx; //index of active edges in the heap
+ std::set active_edges; //a set of edges that intersect the current vision ray.
+ VHs vs; //angular sorted vertices
+ EHs bad_edges; //edges that pass the query point
+ VH cone_end1; //an end of visibility cone
+ VH cone_end2; //another end of visibility cone
+ int cone_end1_idx; //index of cone_end1->point() in visibility polygon
+ int cone_end2_idx; //index of cone_end2->point() in visibility polygon
+
+ bool is_vertex_query;
+ bool is_edge_query;
+ bool is_face_query;
+ 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(){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) {
+ 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.
+ int 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;
+ }
+ int 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() + small_idx;
+ typename Points::iterator last = polygon.begin() + 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 (int 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);
+ }
+
+ conditional_regularize(arr_out, Regularization_tag());
+
+ 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) {
+ 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);
+ conditional_regularize(arr_out, Regularization_tag());
+ if (arr_out.faces_begin()->is_unbounded())
+ return ++arr_out.faces_begin();
+ else
+ return arr_out.faces_begin();
+ }
+
+bool is_attached() {
+ 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& arr() {
+ return *p_arr;
+}
+
+private:
+ //get the neighbor of v along edge e
+ VH get_neighbor(const EH e, const VH v) {
+ 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) {
+ 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(int i, int j) {
+ 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 (int 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 (int l=0; l!=right.size(); l++)
+ vs[i+l] = right[l];
+ for (int 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) {
+ 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; //all 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 (int 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 (int j=0; j!=remove_cnt; j++)
+ active_edges.erase(remove_ehs[j]);
+ for (int 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) {
+ std::cout<source()->point()<<"->"<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
+ {
+ 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){
+ 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) {
+ 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) {
+ for (int i=0; itarget();
+ 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)
+ {
+ 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 (int i=0; i!=vs.size(); i++) {
+ int 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)
+ {
+ 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 (int 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 (int i=0; i!=vs.size(); i++) {
+ int 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;
+ }
+ }
+
+ template
+ void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
+ regularize_output(arr_out);
+ }
+
+ template
+ void conditional_regularize(VARR& arr_out, CGAL::Tag_false) {
+ //do nothing
+ }
+
+ template
+ void regularize_output(VARR& arr_out) {
+ typename VARR::Edge_iterator e_itr;
+ for (e_itr = arr_out.edges_begin();
+ e_itr != arr_out.edges_end();
+ e_itr++) {
+ if (e_itr->face() == e_itr->twin()->face())
+ arr_out.remove_edge(e_itr);
+ }
+ }
+};
+} // 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..0934d03ba1c
--- /dev/null
+++ b/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h
@@ -0,0 +1,715 @@
+// 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