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

Conflicts:
	Documentation/biblio/how_to_cite.html
	Documentation/biblio/how_to_cite_cgal.txt
This commit is contained in:
Michael Hemmer 2014-07-09 12:39:23 +02:00
commit 08edac829d
95 changed files with 23872 additions and 1 deletions

View File

@ -2335,6 +2335,50 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
series = {Texts and Monographs in Symbolic Computation} 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 % END OF BIBFILE
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------

View File

@ -151797,4 +151797,3 @@ amplification and suppression of local contrast. Contains C code."
, publisher = "Cambridge University Press" , publisher = "Cambridge University Press"
, year = 1999 , year = 1999
} }

View File

@ -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}/Spatial_sorting/doc/Spatial_sorting/fig \
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/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}/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}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \ ${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
${CMAKE_SOURCE_DIR}/Subdivision_method_3/doc/Subdivision_method_3/fig \ ${CMAKE_SOURCE_DIR}/Subdivision_method_3/doc/Subdivision_method_3/fig \

View File

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

View File

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

View File

@ -718,8 +718,24 @@ namespace for the XML file to be processed properly. -->
<item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item> <item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item>
</list> </list>
</doxygen> </doxygen>
</project>
<project>
<name>2D Visibility</name>
<input>../Visibility_2/doc/Visibility_2</input>
<doxygen>
<string name="STRIP_FROM_INC_PATH">../Visibility_2/doc/Visibility_2/</string>
<string name="STRIP_FROM_PATH">../Visibility_2/doc/Visibility_2/</string>
<string name="GENERATE_TAGFILE">./tags/Visibility_2.tag</string>
<string name="EXAMPLE_PATH">../Visibility_2/examples</string>
<string name="IMAGE_PATH">../Visibility_2/doc/Visibility_2/fig</string>
<list name="TAGFILES" append="true">
<item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item>
</list>
</doxygen>
</project> </project>
<project> <project>
<name>2D Minkowski Sums</name> <name>2D Minkowski Sums</name>
<input>../Minkowski_sum_2/doc/Minkowski_sum_2</input> <input>../Minkowski_sum_2/doc/Minkowski_sum_2</input>
@ -1457,6 +1473,7 @@ namespace for the XML file to be processed properly. -->
<item>../Convex_hull_d/doc/Convex_hull_d/fig</item> <item>../Convex_hull_d/doc/Convex_hull_d/fig</item>
<item>../Envelope_2/doc/Envelope_2/fig</item> <item>../Envelope_2/doc/Envelope_2/fig</item>
<item>../Envelope_3/doc/Envelope_3/fig</item> <item>../Envelope_3/doc/Envelope_3/fig</item>
<item>../Visibility_2/doc/Visibility_2/fig</item>
<item>../Generator/doc/Generator/fig</item> <item>../Generator/doc/Generator/fig</item>
<item>../Geomview/doc/Geomview/fig</item> <item>../Geomview/doc/Geomview/fig</item>
<item>../GraphicsView/doc/GraphicsView/fig</item> <item>../GraphicsView/doc/GraphicsView/fig</item>
@ -1538,6 +1555,7 @@ namespace for the XML file to be processed properly. -->
<item>./tags/Convex_hull_d.tag=../../CGAL.CGAL.dD-Convex-Hulls-and-Delaunay-Triangulations/html</item> <item>./tags/Convex_hull_d.tag=../../CGAL.CGAL.dD-Convex-Hulls-and-Delaunay-Triangulations/html</item>
<item>./tags/Envelope_2.tag=../../CGAL.CGAL.2D-Envelopes/html</item> <item>./tags/Envelope_2.tag=../../CGAL.CGAL.2D-Envelopes/html</item>
<item>./tags/Envelope_3.tag=../../CGAL.CGAL.3D-Envelopes/html</item> <item>./tags/Envelope_3.tag=../../CGAL.CGAL.3D-Envelopes/html</item>
<item>./tags/Visibility_2.tag=../../CGAL.CGAL.2D-Visibility/html</item>
<item>./tags/Generator.tag=../../CGAL.CGAL.Geometric-Object-Generators/html</item> <item>./tags/Generator.tag=../../CGAL.CGAL.Geometric-Object-Generators/html</item>
<item>./tags/Geomview.tag=../../CGAL.CGAL.Geomview/html</item> <item>./tags/Geomview.tag=../../CGAL.CGAL.Geomview/html</item>
<item>./tags/GraphicsView.tag=../../CGAL.CGAL.CGAL-and-the-Qt-Graphics-View-Framework/html</item> <item>./tags/GraphicsView.tag=../../CGAL.CGAL.CGAL-and-the-Qt-Graphics-View-Framework/html</item>

View File

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

View File

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

View File

@ -0,0 +1,158 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
a polygon that may have holes.
\details The class template comprises the implementation of the algorithm of Takao Asano and Tetsuo Asano \cite aaghi-vpsesp-85. The algorithm, as the name of the class template suggests, requires preprocessing. The preprocessing takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space, which reduces the query time to \f$O(n)\f$.
The main preprocessing step is the dualization of all vertices of the input arrangment into an arrangment of lines.
Computing this arrangement takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space.
Using this arrangment it is possible to retrieve the angular order of all vertices around
a query point, which is one of the essential steps to achive linear query time. For more details we refer to \cite aaghi-vpsesp-85.
\tparam Arrangement_2 is the type of input polygonal environment and output visibility polygon.
\tparam 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<Arrangement_2, RegularizationTag>`
\sa `CGAL::Rotational_sweep_visibility_2<Arrangement_2, RegularizationTag>`
\sa `CGAL::Triangular_expansion_visibility_2<Arrangement_2, RegularizationTag>`
*/
template <typename Arrangement_2, typename RegularizationTag = Tag_false>
class Preprocessed_rotational_sweep_visibility_2 {
public:
/// \name Types
/// @{
/*!
The type of the input arrangement.
*/
typedef Arrangement_2 Arrangement_2;
/*!
The type of the output arrangement.
*/
typedef Arrangement_2 Visibility_arrangement_2;
/*!
The 2D point type used for the queries.
*/
typedef Arrangement_2::Point_2 Point_2;
/*!
Face_const_handle type of the input arrangement.
*/
typedef Arrangement_2::Face_const_handle Face_const_handle;
/*!
Halfedge_const_handle type of the input arrangement.
*/
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
/// @}
/// \name Tags
/// @{
/*!
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 */

View File

@ -0,0 +1,77 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
\details The algorithm does not require preprocessing. It relies on the algorithm of T. Asano \cite ta-aeafvpprh-85 based on angular plane sweep, with a time complexity of \f$O (n \log n)\f$ in the number of vertices.
\tparam Arrangement_2_ is the type used to represent the input environment.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
CGAL::Arr_segment_traits_2.
\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 <typename Arrangement_2_, typename RegularizationTag = Tag_true>
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 */
}

View File

@ -0,0 +1,82 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
a simple polygon with no holes.
\details This class implements the algorithm of B.Joe and R.B.Simpson \cite bjrb-clvpa-87.
The algorithm is a modification and extension of the linear time algorithm of Lee \cite dtl-voasp-83.
It computes the visibility region from a viewpoint that is in the interior or on the boundary of the polygon.
While scanning the boundary the algorithm uses a stack to manipulate the vertices, and ultimately
yields the visibility region. For each scanned edge, at most 2 points are pushed onto the stack.
Overall, at most 2\f$ n \f$ points are pushed or popped. Thus, the time and space complexities of the
algorithm are \f$ O(n) \f$ even in case of degeneracies such as needles, where \f$ n \f$
is the number of the vertices of the polygon.
\tparam Arrangement_2_ is the type used to represent the input environment.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
CGAL::Arr_segment_traits_2.
\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 <typename Arrangement_2_, typename RegularizationTag = Tag_true>
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 */
}

View File

@ -0,0 +1,82 @@
namespace CGAL {
/*!
\ingroup PkgVisibility_2Classes
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a 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 <typename Arrangement_2_, typename RegularizationTag = Tag_true>
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 */

View File

@ -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 VisibilityArrangement_2>
typename Visibility_arrangement_2::Face_handle
compute_visibility(const Point_2& q, const Face_const_handle f, VisibilityArrangement_2& out_arr) const;
/*!
Computes the visibility region in `e->face()` for the given query
point `q` which must be located on `e`.
If `q` is an interior point of `e`, the computed visibility
region is restricted to the side indicated by the halfedge `e`.
If `q` is an endpoint of `e`, the visibility region is restricted by `e` and `e->next()`.
The visibility region of `q` is stored in `out_arr`, that is,
all features but the unbounded face of `out_arr` represent the visibility region.
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
must be mutual convertible to Visibility_2::Traits_2.
\param q is the query point
\param e the halfedge on which `q` is located
\param out_arr is the output arrangement
\pre `e` is a halfedge of `this->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 VisibilityArrangement_2>
typename Visibility_arrangement_2::Face_handle
compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
/// @}
}; /* end Visibility_2 */

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,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

View File

@ -0,0 +1,56 @@
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <iostream>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::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<Arrangement_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;
}

View File

@ -0,0 +1,65 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Arr_naive_point_location.h>
#include <istream>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::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<Arrangement_2, CGAL::Tag_false>
NSPV;
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_true>
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<Arrangement_2> 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <huangkandiy@gmail.com>
//
#ifndef CGAL_PREPROCESSED_VISIBILITY_2_H
#define CGAL_PREPROCESSED_VISIBILITY_2_H
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_linear_traits_2.h>
#include <stack>
#include <deque>
namespace CGAL {
template<class Arrangement_2>
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<Kernel> 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<Linear_traits_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

View File

@ -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 <huangkandiy@gmail.com>
//
#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
#include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/bounding_box.h>
#include <boost/unordered_map.hpp>
namespace CGAL {
template<class Arrangement_2_ , class RegularizationTag = CGAL::Tag_true >
class Rotational_sweep_visibility_2 {
public:
typedef Arrangement_2_ Arrangement_2;
typedef typename Arrangement_2::Traits_2 Traits_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
typedef typename Geometry_traits_2::Kernel K;
typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::Ray_2 Ray_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Geometry_traits_2::Line_2 Line_2;
typedef typename Geometry_traits_2::Vector_2 Vector_2;
typedef typename Geometry_traits_2::Direction_2 Direction_2;
typedef typename Geometry_traits_2::FT Number_type;
typedef typename Geometry_traits_2::Object_2 Object_2;
typedef RegularizationTag Regularization_tag;
typedef CGAL::Tag_true Supports_general_polygon_tag;
typedef CGAL::Tag_true Supports_simple_polygon_tag;
private:
typedef std::vector<Point_2> Points;
typedef Vertex_const_handle VH;
typedef std::vector<VH> VHs;
typedef Halfedge_const_handle EH;
typedef std::vector<EH> EHs;
class Less_edge: public std::binary_function<EH, EH, bool> {
const Geometry_traits_2* geom_traits;
public:
Less_edge() {}
Less_edge(const Geometry_traits_2* traits):geom_traits(traits) {}
bool operator() (const EH e1, const EH e2) const {
if (e1 == e2)
return false;
else {
return &(*e1)<&(*e2);
// if (e1->source() == e2->source())
// return Visibility_2::compare_xy_2(geom_traits, e1->target()->point(), e2->target()->point()) == SMALLER;
// else
// return Visibility_2::compare_xy_2(geom_traits, e1->source()->point(), e2->source()->point()) == SMALLER;
}
}
};
class Less_vertex: public std::binary_function<VH, VH, bool> {
const Geometry_traits_2* geom_traits;
public:
Less_vertex() {}
Less_vertex(const Geometry_traits_2* traits):geom_traits(traits) {}
bool operator() (const VH v1, const VH v2) const {
if (v1 == v2)
return false;
else
// I know this is dirty but it speeds up by 25%. Michael
return &(*v1)<&(*v2);
// return Visibility_2::compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
}
};
class Closer_edge: public std::binary_function<EH, EH, bool> {
const Geometry_traits_2* geom_traits;
Point_2 q;
public:
Closer_edge() {}
Closer_edge(const Geometry_traits_2* traits, const Point_2& q):geom_traits(traits), q(q) {}
int vtype(const Point_2& c, const Point_2& p) const {
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
case COLLINEAR:
if (Visibility_2::less_distance_to_point_2(geom_traits, q, c, p))
return 0;
else
return 3;
case RIGHT_TURN:
return 1;
case LEFT_TURN:
return 2;
}
}
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<VH,typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type> {
// public:
// typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type
// operator() (const EH e1) const {
// return boost::hash<const typename Arrangement_2::X_monotone_curve_2*>()(&(e1->curve()));
// }
// };
const Geometry_traits_2 *geom_traits;
const Arrangement_2 *p_arr;
Point_2 q; //query point
Points polygon; //visibility polygon
std::map<VH, EHs, Less_vertex> incident_edges; //the edges that are
std::map<EH, int, Less_edge> edx; //index of active edges in the heap
// boost::unordered_map<EH,int,Hash_edge> edx; //index of active edges in the heap
std::set<EH, Closer_edge> 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>
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<Rotational_sweep_visibility_2>
(geom_traits, q, polygon_out, arr_out);
}
else {
Points polygon_out(polygon.begin(), first+1);
if (is_vertex_query) polygon_out.push_back(q);
for (int i = big_idx; i != polygon.size(); i++) {
polygon_out.push_back(polygon[i]);
}
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
(geom_traits, q, polygon_out, arr_out);
}
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>
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<Rotational_sweep_visibility_2>(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; l<j; l++) {
bool left_v(false), right_v(false), has_predecessor(false);
EHs& edges = incident_edges[vs[l]];
for (int k=0; k<edges.size(); k++) {
nb = get_neighbor(edges[k], vs[l]);
if ( nb == former ) {
has_predecessor = true;
break;
}
if (CGAL::left_turn(q, vs[l]->point(), nb->point()))
left_v = true;
else
right_v = CGAL::right_turn(q, vs[l]->point(), nb->point());
}
if (has_predecessor) {
//if the current vertex connects to the vertex before by an edge,
//the vertex before can help it to block.
block_left = block_left || left_v;
block_right = block_right || right_v;
}
else {
block_left = left_v;
block_right = right_v;
}
if (block_left && block_right) {
//when both sides are blocked, there is no need to change the vertex after.
right.push_back(vs[l]);
break;
}
else {
if (block_left)
left.push_back(vs[l]);
else
right.push_back(vs[l]);
}
former = vs[l];
}
for (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<EH, Closer_edge>(Closer_edge(geom_traits, q));
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
EHs relevant_edges; //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<<active_edges.size()<<std::endl;
for (int i=0; i!=vs.size(); i++) {
VH vh = vs[i];
EH closest_e = *active_edges.begin();
EHs& edges = incident_edges[vh];
EHs insert_ehs, remove_ehs;
for (int j=0; j!=edges.size(); j++) {
EH& e = edges[j];
if (active_edges.find(e) == active_edges.end())
insert_ehs.push_back(e);
else
remove_ehs.push_back(e);
}
int insert_cnt = insert_ehs.size();
int remove_cnt = remove_ehs.size();
if (insert_cnt == 1 && remove_cnt == 1) {
const EH& ctemp_eh = *active_edges.find(remove_ehs.front());
EH& temp_eh = const_cast<EH&>(ctemp_eh);
temp_eh = insert_ehs.front();
}
else {
for (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<<e->source()->point()<<"->"<<e->target()->point()<<std::endl;
}
//compute the intersection of ray(q->dp) and segment(s, t)
//if they are collinear then return the endpoint which is closer to q.
Point_2 ray_seg_intersection(
const Point_2& q, const Point_2& dp, // the ray
const Point_2& s, const Point_2& t) // the segment
{
if (CGAL::collinear(q, dp, s)) {
if (CGAL::collinear(q, dp, t)) {
if (CGAL::compare_distance_to_point(q, s, t)==CGAL::SMALLER)
return s;
else
return t;
}
else
return s;
}
Ray_2 ray(q,dp);
Segment_2 seg(s,t);
CGAL::Object result = CGAL::intersection(ray, seg);
return *(CGAL::object_cast<Point_2>(&result));
}
//check if p has been discovered before, if not update the visibility polygon
bool update_visibility(const Point_2& p){
if (polygon.empty()) {
polygon.push_back(p);
return true;
}
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p) != EQUAL) {
polygon.push_back(p);
return true;
}
return false;
}
//functor to decide which vertex is swept earlier by the rotational sweeping ray
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
const Point_2& q;
const Geometry_traits_2* geom_traits;
public:
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits):q(q), geom_traits(traits) {}
bool operator() (const VH v1, const VH v2) const {
const Point_2& p1 = v1->point();
const Point_2& p2 = v2->point();
int qua1 = quadrant(q, p1);
int qua2 = quadrant(q, p2);
if (qua1 < qua2)
return true;
if (qua1 > qua2)
return false;
if (collinear(q, p1, p2))
return (CGAL::compare_distance_to_point(q, p1, p2) == CGAL::SMALLER);
else
return CGAL::right_turn(p1, q, p2);
}
//return the quadrant of p with respect to o.
int quadrant(const Point_2& o, const Point_2& p) const {
typename Geometry_traits_2::Compare_x_2 compare_x = geom_traits->compare_x_2_object();
typename Geometry_traits_2::Compare_y_2 compare_y = geom_traits->compare_y_2_object();
Comparison_result dx = compare_x(p, o);
Comparison_result dy = compare_y(p, o);
if (dx==LARGER && dy!=SMALLER)
return 1;
if (dx!=LARGER && dy==LARGER)
return 2;
if (dx==SMALLER && dy!=LARGER)
return 3;
if (dx!=SMALLER && dy==SMALLER)
return 4;
return 0;
}
};
//when the query point is in face, every edge is good.
void input_neighbor_f( const Halfedge_const_handle e) {
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; i<bad_edges.size(); i++)
if (e == bad_edges[i])
return;
VH v1 = e->target();
VH v2 = e->source();
//an edge will affect visibility only if it has an endpoint in the visibility cone or it crosses the boundary of the cone.
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) || do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point())) {
good_edges.push_back(e);
if (!incident_edges.count(v1))
vs.push_back(v1);
incident_edges[v1].push_back(e);
if (!incident_edges.count(v2))
vs.push_back(v2);
incident_edges[v2].push_back(e);
}
}
//for face query: traverse the face to get all edges
//and sort vertices in counter-clockwise order.
void input_face (Face_const_handle fh)
{
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; i<vs.size(); i++) {
points.push_back(vs[i]->point());
}
points.push_back(q);
//first get the bounding box of all relevant points.
typename Geometry_traits_2::Iso_rectangle_2 bb = bounding_box(points.begin(), points.end());
Number_type xmin, xmax, ymin, ymax;
typename Geometry_traits_2::Compute_x_2 compute_x = geom_traits->compute_x_2_object();
typename Geometry_traits_2::Compute_y_2 compute_y = geom_traits->compute_y_2_object();
//make the box a little bigger than bb so that it won't intersect any relevant_edge.
xmin = compute_x(bb.min())-1;
ymin = compute_y(bb.min())-1;
xmax = compute_x(bb.max())+1;
ymax = compute_y(bb.max())+1;
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
Point_2(xmax, ymax), Point_2(xmin, ymax)};
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]), bbox.unbounded_face());
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]), e1->target());
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2], box[3]), e2->target());
bbox.insert_at_vertices(Segment_2(box[0], box[3]), e1->source(), e3->target());
circ = curr = e1->face()->outer_ccb();
do {
VH v = curr->target();
vs.push_back(v);
incident_edges[v].push_back(curr);
incident_edges[v].push_back(curr->next());
good_edges.push_back(curr);
} while(++curr != circ);
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
for (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 <typename VARR>
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
regularize_output(arr_out);
}
template <typename VARR>
void conditional_regularize(VARR& arr_out, CGAL::Tag_false) {
//do nothing
}
template <typename VARR>
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

View File

@ -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 <fbungiu@gmail.com>
// Michael Hemmer <michael.hemmer@cgal.org>
// Ning Xu <longyin0904@gmail.com>
#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
#define CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
#include <CGAL/Arrangement_2.h>
#include <CGAL/tags.h>
#include <CGAL/enum.h>
#include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <stack>
#include <map>
namespace CGAL {
template<class Arrangement_2_, class RegularizationTag = CGAL::Tag_true>
class Simple_polygon_visibility_2 {
public:
// Currently only consider with same type for both
typedef Arrangement_2_ Arrangement_2;
typedef typename Arrangement_2::Traits_2 Traits_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Geometry_traits_2::Kernel K;
typedef typename Arrangement_2::Halfedge_const_handle
Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::Ray_2 Ray_2;
typedef typename Geometry_traits_2::Segment_2 Segment_2;
typedef typename Geometry_traits_2::Line_2 Line_2;
typedef typename Geometry_traits_2::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_false Supports_general_polygon_tag;
typedef CGAL::Tag_true Supports_simple_polygon_tag;
Simple_polygon_visibility_2() : p_arr(NULL), geom_traits(NULL) {};
/*! Constructor given an arrangement and the Regularization tag. */
Simple_polygon_visibility_2(const Arrangement_2& arr):
p_arr(&arr) {
geom_traits = p_arr->geometry_traits();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
}
const std::string name(){return std::string("S_visibility_2");}
/*! Method to check if the visibility object is attached or not to
an arrangement*/
bool is_attached() {
return (p_arr != NULL);
}
/*! Attaches the visibility object to the 'arr' arrangement */
void attach(const Arrangement_2& arr) {
p_arr = &arr;
geom_traits = p_arr->geometry_traits();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
}
/*! Detaches the visibility object from the arrangement it is
attached to*/
void detach() {
p_arr = NULL;
geom_traits = NULL;
vertices.clear();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
p_cdt = boost::shared_ptr<CDT>();
}
/*! Getter method for the input arrangement*/
const Arrangement_2& arr() {
return *p_arr;
}
/*! Computes the visibility object from the query point 'q' in the face
'face' and constructs the output in 'out_arr'*/
template <typename VARR>
typename VARR::Face_handle
compute_visibility(const Point_2& q,
const Face_const_handle face,
VARR& out_arr) {
assert(query_pt_is_vertex == false);
assert(query_pt_is_on_halfedge == false);
// Now retrieve the circulator to first visible vertex from triangulation
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
Ccb_halfedge_const_circulator curr = circ;
Halfedge_const_handle he;
do {
he = curr;
vertices.push_back(he->source()->point());
} while(++curr != circ);
vertices.push_back(vertices[0]);
visibility_region_impl(q);
typename std::vector<Point_2> points;
while (!s.empty()) {
Point_2 curr_point = s.top();
points.push_back(curr_point);
s.pop();
}
std::reverse(points.begin(), points.end());
CGAL::Visibility_2::report_while_handling_needles
<Simple_polygon_visibility_2>(geom_traits,
q,
points,
out_arr);
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
CGAL_precondition(s.size() == 0);
conditional_regularize(out_arr, Regularization_tag());
vertices.clear();
if (out_arr.faces_begin()->is_unbounded()) {
return ++out_arr.faces_begin();
}
else {
return out_arr.faces_begin();
}
}
/*! Computes the visibility region of the query point 'q' located on the
halfedge 'he' and constructs the output in 'out_arr'*/
template <typename VARR>
typename VARR::Face_handle
compute_visibility(
const Point_2& q,
const Halfedge_const_handle he,
VARR& out_arr )
{
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
bool query_on_target = false;
if (q != he->source()->point()) {
if (q != he->target()->point()) {
vertices.push_back(he->target()->point());
query_pt_is_on_halfedge = true;
}
else {
query_pt_is_vertex = true;
query_on_target = true;
}
} else {
vertices.push_back( he->target()->point() );
query_pt_is_vertex = true;
}
Ccb_halfedge_const_circulator circ = he;
circ++;
Ccb_halfedge_const_circulator curr = circ;
do {
Halfedge_const_handle he_handle = curr;
Point_2 curr_vertex = he_handle->target()->point();
vertices.push_back(curr_vertex);
} while (++curr != circ);
if ( query_on_target ) {
vertices.push_back( vertices[0] );
}
visibility_region_impl(q);
typename std::vector<Point_2> points;
if (!s.empty()) {
Point_2 prev_pt = s.top();
if (prev_pt != q) {
points.push_back(prev_pt);
}
else if (query_pt_is_vertex) {
points.push_back(prev_pt);
}
if (!s.empty()) {
s.pop();
}
while(!s.empty()) {
Point_2 curr_pt = s.top();
if (curr_pt != q) {
points.push_back(curr_pt);
}
else if (query_pt_is_vertex) {
points.push_back(curr_pt);
}
s.pop();
}
}
std::reverse(points.begin(), points.end());
CGAL::Visibility_2::report_while_handling_needles
<Simple_polygon_visibility_2>(geom_traits,
q,
points,
out_arr);
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
CGAL_precondition(s.size() == 0);
conditional_regularize(out_arr, Regularization_tag());
vertices.clear();
if (out_arr.faces_begin()->is_unbounded()) {
return ++out_arr.faces_begin();
}
else {
return out_arr.faces_begin();
}
}
private:
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_triangulation_2<K, TDS, Itag> CDT;
private:
const Arrangement_2 *p_arr;
/*! Boost pointer to the constrained Delaunay triangulation object*/
boost::shared_ptr<CDT> p_cdt;
/*! Mapping of the vertices of the input to the corresponding circulator
needed for finding the first visible vertex in case of face queries*/
std::map<Point_2, typename Arrangement_2::Ccb_halfedge_const_circulator>
point_itr_map;
const Geometry_traits_2 *geom_traits;
/*! Stack of visibile points; manipulated when going through the sequence
of input vertices; contains the vertices of the visibility region after
the run of the algorithm*/
std::stack<Point_2> s;
/*! Sequence of input vertices*/
std::vector<Point_2> vertices;
/*! State of visibility region algorithm*/
enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
bool query_pt_is_vertex;
bool query_pt_is_on_halfedge;
/*! Regularize output if flag is set to true*/
template <typename VARR>
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 <typename VARR>
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 <typename VARR>
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);
}
}
}
/*! Initialized the constrained Delaunay triangulation using the edges of
the outer boundary of 'face' */
void init_cdt(const Face_const_handle &face) {
std::vector<std::pair<Point_2,Point_2> > constraints;
typename Arrangement_2::Ccb_halfedge_const_circulator circ =
face->outer_ccb();
typename Arrangement_2::Ccb_halfedge_const_circulator curr = circ;
typename Arrangement_2::Halfedge_const_handle he;
do {
he = curr;
Point_2 source = he->source()->point();
Point_2 target = he->target()->point();
point_itr_map.insert(std::make_pair(source, curr));
constraints.push_back(std::make_pair(source,target));
} while(++curr != circ);
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),constraints.end()));
}
/*! Finds a visible vertex from the query point 'q' in 'face'
to start the algorithm from*/
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face, const Point_2 &q) {
init_cdt(face);
typename CDT::Face_handle fh = p_cdt->locate(q);
Point_2 start_point = fh->vertex(0)->point();
// Now retrieve the circulator to first visible vertex from triangulation
Ccb_halfedge_const_circulator circ = point_itr_map[start_point];
Halfedge_const_handle he_curr = circ;
Halfedge_around_vertex_const_circulator incident_circ = he_curr->source()->incident_halfedges();
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
do {
Ccb_halfedge_const_circulator curr_inc = incident_curr;
Halfedge_const_handle he_curr_inc = curr_inc;
if (he_curr_inc->face() == face) {
Ccb_halfedge_const_circulator incident_next = incident_curr;
incident_next++;
Halfedge_const_handle he_next_inc = incident_next;
if (CGAL::Visibility_2::orientation_2(geom_traits,
he_curr_inc->source()->point(),
he_curr_inc->target()->point(),
q) == CGAL::LEFT_TURN
|| CGAL::Visibility_2::orientation_2(geom_traits,
he_next_inc->source()->point(),
he_next_inc->target()->point(),
q) == CGAL::LEFT_TURN) {
Ccb_halfedge_const_circulator result_circ = incident_next;
Halfedge_const_handle he_print = result_circ;
return result_circ;
}
}
} while (++incident_curr != incident_circ);
}
/*! Main method of the algorithm - initializes the stack and variables
and calles the corresponding methods acc. to the algorithm's state;
'q' - query point;
'i' - current vertex' index
'w' - endpoint of ray shot from query point */
void visibility_region_impl(const Point_2& q) {
int i = 0;
Point_2 w;
CGAL::Orientation orient = CGAL::Visibility_2::orientation_2(geom_traits,
q,
vertices[0],
vertices[1]);
if ( orient != CGAL::RIGHT_TURN ) {
upcase = LEFT;
i = 1;
w = vertices[1];
s.push(vertices[0]);
s.push(vertices[1]);
}
else {
upcase = SCANA;
i = 1;
w = vertices[1];
s.push(vertices[0]);
}
Ray_2 ray_origin( q, vertices[0] );
do {
switch(upcase) {
case LEFT:
left(i, w, q);
break;
case RIGHT:
right(i, w, q);
break;
case SCANA:
scana(i, w, q);
break;
case SCANB:
scanb(i, w, q);
break;
case SCANC:
scanc(i, w, q);
break;
case SCAND:
scand(i, w, q);
break;
}
if ( upcase == LEFT ) {
Point_2 s_t = s.top();
s.pop();
if ( ( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, q, vertices[0], s.top() ) == CGAL::RIGHT_TURN ) &&
( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, q, vertices[0],s_t ) == CGAL::LEFT_TURN ) ) {
Segment_2 seg( s.top(), s_t );
if ( CGAL::Visibility_2::do_intersect_2
<Geometry_traits_2, Segment_2, Ray_2>
( geom_traits, seg, ray_origin ) ) {
Object_2 result = CGAL::Visibility_2::intersect_2
<Geometry_traits_2, Segment_2, Ray_2>
( geom_traits, seg, ray_origin );
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
assert( ipoint != NULL );
s_t = *ipoint;
upcase = SCANB;
}
}
s.push( s_t );
}
} while(upcase != FINISH);
}
/*! Method that handles the left turns in the vertex algorithm */
void left(int& i, Point_2& w, const Point_2& query_pt) {
if (i >= vertices.size() - 1) {
upcase = FINISH;
}
else {
Point_2 s_t = s.top();
s.pop();
Point_2 s_t_prev = s.top();
s.push( s_t );
CGAL::Orientation orient1 = CGAL::Visibility_2::orientation_2
<Geometry_traits_2>
( geom_traits,
query_pt,
vertices[i],
vertices[i+1] );
if ( orient1 != CGAL::RIGHT_TURN ) {
// Case L2
upcase = LEFT;
s.push( vertices[i+1] );
w = vertices[i+1];
i++;
} else {
CGAL::Orientation orient2 = CGAL::Visibility_2::orientation_2
<Geometry_traits_2>
( geom_traits,
s_t_prev,
vertices[i],
vertices[i+1] );
if ( orient2 == CGAL::RIGHT_TURN ) {
// Case L3
upcase = SCANA;
w = vertices[i+1];
i++;
} else {
// Case L4
upcase = RIGHT;
w = vertices[i];
i++;
}
}
}
}
/*! Scans the stack such that all vertices that were pushed before to the
stack and are now not visible anymore. */
void right(int& i, Point_2& w, const Point_2& query_pt) {
Point_2 s_j;
Point_2 s_j_prev;
Point_2 u;
int mode = 0;
CGAL::Orientation orient1, orient2;
s_j_prev = s.top();
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, query_pt, s_j_prev, vertices[i] );
while ( s.size() > 1 ) {
s_j = s_j_prev;
orient1 = orient2;
s.pop();
s_j_prev = s.top();
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, query_pt, s_j_prev, vertices[i] );
if ( orient1 != CGAL::LEFT_TURN && orient2 != CGAL::RIGHT_TURN ) {
mode = 1;
break;
}
Segment_2 seg2( vertices[i-1], vertices[i] );
Segment_2 seg( s_j_prev, s_j );
if ( ( vertices[i-1] != s_j )
&& ( CGAL::Visibility_2::do_intersect_2
<Geometry_traits_2, Segment_2, Segment_2>
(geom_traits, seg, seg2) ) ) {
Object_2 result = CGAL::Visibility_2::intersect_2
<Geometry_traits_2, Segment_2, Segment_2>( geom_traits, seg, seg2 );
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
mode = 2;
break;
}
}
assert( mode != 0 );
if ( mode == 1 ) {
orient1 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, query_pt, vertices[i], vertices[i+1] );
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
( geom_traits, vertices[i-1], vertices[i], vertices[i+1] );
if ( orient1 == CGAL::RIGHT_TURN ) {
// Case R1
// Since the next action is RIGHT, we do not compute the intersection
// of (s_j,s_j_prev) and the ray (query_pt, vertices[i]),
// thus, (s_j,s_j_prev) is not shortcutted, but it is harmless
upcase = RIGHT;
s.push( s_j );
w = vertices[i];
i++;
} else if ( orient2 == CGAL::RIGHT_TURN ) {
// Case R2
Ray_2 ray( query_pt, vertices[i] );
Segment_2 seg( s_j_prev, s_j );
Object_2 result = CGAL::Visibility_2::intersect_2
<Geometry_traits_2, Segment_2, Ray_2>
( geom_traits, seg, ray );
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
if ( s.top() != u ) {
s.push( u );
}
upcase = LEFT;
s.push( vertices[i] );
s.push( vertices[i+1] );
w = vertices[i+1];
i++;
} else {
// Case R3
Ray_2 ray( query_pt, vertices[i] );
Segment_2 seg( s_j_prev, s_j );
Object_2 result = CGAL::Visibility_2::intersect_2
<Geometry_traits_2, Segment_2, Ray_2>
( geom_traits, seg, ray );
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
assert( ipoint != NULL );
u = *ipoint;
if ( s.top() != u ) {
s.push( u );
}
upcase = SCANC;
w = vertices[i];
i++;
}
} else if ( mode == 2 ) {
// Case R4
upcase = SCAND;
w = u;
}
}
/*! Scans the vertices starting from index 'i' for the first visible vertex
out of the back hidden window */
void scana(int& i, Point_2& w, const Point_2& query_pt) {
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
Point_2 u;
int k = scan_edges( i, query_pt, s.top(), u, true );
CGAL::Orientation orient1 = CGAL::Visibility_2::orientation_2
<Geometry_traits_2>
( geom_traits,
query_pt,
vertices[k],
vertices[k+1] );
if ( orient1 == CGAL::RIGHT_TURN ) {
bool fwd = CGAL::Visibility_2::collinear_are_ordered_along_line_2
<Geometry_traits_2>
( geom_traits, query_pt, s.top(), u );
if ( !fwd ) {
// Case A1
upcase = RIGHT;
i = k+1;
w = u;
} else {
// Case A2
upcase = SCAND;
i = k+1;
w = u;
}
} else {
// Case A3
upcase = LEFT;
i = k+1;
s.push( u );
if ( u != vertices[k+1] ) {
s.push( vertices[k+1] );
}
w = vertices[k+1];
}
}
/*! Find the first edge interecting the segment (v_0, s_t) */
void scanb(int& i, Point_2& w, const Point_2& query_pt) {
if ( i == vertices.size() - 1 ) {
upcase = FINISH;
return;
}
Point_2 u;
int k = scan_edges( i, s.top(), vertices[0], u, false );
if ( (k+1 == vertices.size()-1) && (vertices[0] == u) ) {
// Case B1
upcase = FINISH;
s.push( vertices[0] );
} else {
// Case B2
upcase = RIGHT;
i = k+1;
w = u;
}
}
/*! Finds the exit from a general front hidden window by finding the first
vertex to the right of the ray defined by the query_point and w*/
void scanc(int& i, Point_2& w, const Point_2& query_pt) {
Point_2 u;
int k = scan_edges( i, s.top(), w, u, false );
upcase = RIGHT;
i = k+1;
w = u;
}
/*! find the first edge intersecting the given window (s_t, w) */
void scand(int& i, Point_2& w, const Point_2& query_pt) {
Point_2 u;
int k = scan_edges( i, s.top(), w, u, false );
upcase = LEFT;
i = k+1;
s.push( u );
if ( u != vertices[k+1] ) {
s.push( vertices[k+1] );
}
w = vertices[k+1];
}
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
or given segment. is_ray = true -> ray, false -> segment.
The intersection point is returned by u */
int scan_edges( int i, const Point_2& ray_begin, const Point_2& ray_end, Point_2& u, bool is_ray ) {
CGAL::Orientation old_orient = CGAL::RIGHT_TURN;
Ray_2 ray( ray_begin, ray_end );
Segment_2 s2( ray_begin, ray_end );
int k;
Object_2 result;
for ( k = i; k+1 < vertices.size(); k++ ) {
CGAL::Orientation curr_orient = CGAL::Visibility_2::orientation_2
( geom_traits,
ray_begin,
ray_end,
vertices[k+1] );
if ( curr_orient != old_orient ) {
// Orientation switch, an intersection may occur
Segment_2 seg( vertices[k], vertices[k+1] );
if ( is_ray ) {
if (CGAL::Visibility_2::do_intersect_2
<Geometry_traits_2, Segment_2, Ray_2>
(geom_traits, seg, ray) ) {
result = CGAL::Visibility_2::intersect_2
< Geometry_traits_2, Segment_2, Ray_2 >
( geom_traits, seg, ray );
break;
}
} else {
if (CGAL::Visibility_2::do_intersect_2
<Geometry_traits_2, Segment_2, Segment_2>
(geom_traits, seg, s2) ) {
result = CGAL::Visibility_2::intersect_2
< Geometry_traits_2, Segment_2, Segment_2 >
( geom_traits, seg, s2 );
break;
}
}
}
old_orient = curr_orient;
}
assert( k+1<vertices.size() );
const Point_2 * ipoint = CGAL::object_cast<Point_2>( &result );
if ( ipoint ) {
u = *ipoint;
} else {
u = vertices[k+1];
}
return k;
}
};
} // namespace CGAL
#endif

View File

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

View File

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

View File

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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