Merge branch 'gsoc2013-Visibility_doc-hemmer-old' into gsoc2013-Visibility_doc-hemmer
Conflicts: Documentation/biblio/cgal_manual.bib Documentation/biblio/geom.bib Installation/changes.html
|
|
@ -2501,6 +2501,66 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
|
|||
,year = {2011}
|
||||
}
|
||||
|
||||
@article{bjrb-clvpa-87,
|
||||
author = "B. Joe and R.B. Simpson",
|
||||
title = "Corrections to Lee's visibility polygon algorithm",
|
||||
journal = "BIT",
|
||||
volume = 27,
|
||||
year = 1987,
|
||||
pages = "458--473"
|
||||
}
|
||||
|
||||
@article{ta-aeafvpprh-85
|
||||
,author = {T. Asano}
|
||||
,title = {An Efficient Algorithm for Finding the Visibility Polygon for a Polygonal Region with Holes}
|
||||
,journal = {IEICE Transactions (1976-1990)}
|
||||
,year = 1985
|
||||
,volume = E68
|
||||
,number = 9
|
||||
,pages = {557--559}
|
||||
}
|
||||
|
||||
|
||||
@article{aaghi-vpsesp-85,
|
||||
author = {Takao Asano and
|
||||
Tetsuo Asano and
|
||||
Leonidas J. Guibas and
|
||||
John Hershberger and
|
||||
Hiroshi Imai},
|
||||
title = {Visibility-Polygon Search and Euclidean Shortest Paths},
|
||||
booktitle = {FOCS},
|
||||
year = {1985},
|
||||
pages = {155-164},
|
||||
ee = {http://doi.ieeecomputersociety.org/10.1109/SFCS.1985.65},
|
||||
crossref = {DBLP:conf/focs/FOCS26},
|
||||
bibsource = {DBLP, http://dblp.uni-trier.de}
|
||||
}
|
||||
|
||||
@article{dtl-voasp-83,
|
||||
author = "D. T. Lee",
|
||||
title = "Visibility of a simple polygon",
|
||||
journal = "Computer Vision, Graphics, and Image Processing",
|
||||
volume = 22,
|
||||
year = 1983,
|
||||
pages = "207--221"
|
||||
}
|
||||
|
||||
@article{ecvp-bhhhk-14,
|
||||
author = {Francisc Bungiu and
|
||||
Michael Hemmer and
|
||||
John Hershberger and
|
||||
Kan Huang and
|
||||
Alexander Kr{\"{o}}ller},
|
||||
title = {Efficient Computation of Visibility Polygons},
|
||||
journal = {CoRR},
|
||||
year = {2014},
|
||||
volume = {abs/1403.3905},
|
||||
url = {http://arxiv.org/abs/1403.3905},
|
||||
timestamp = {Wed, 17 Sep 2014 16:30:16 +0200},
|
||||
biburl = {http://dblp.uni-trier.de/rec/bib/journals/corr/BungiuHHHK14},
|
||||
bibsource = {dblp computer science bibliography, http://dblp.org}
|
||||
}
|
||||
|
||||
% ----------------------------------------------------------------------------
|
||||
% END OF BIBFILE
|
||||
% ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -151782,6 +151782,7 @@ amplification and suppression of local contrast. Contains C code."
|
|||
, year = 1999
|
||||
}
|
||||
|
||||
|
||||
@article{hh-esplp-08
|
||||
, author = "I. Haran and D. Halperin"
|
||||
, title = "An experimental study of point location in planar arrangements in CGAL"
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ IMAGE_PATH = ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/fig \
|
|||
${CMAKE_SOURCE_DIR}/Spatial_sorting/doc/Spatial_sorting/fig \
|
||||
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/fig \
|
||||
${CMAKE_SOURCE_DIR}/Straight_skeleton_2/doc/Straight_skeleton_2/fig \
|
||||
${CMAKE_SOURCE_DIR}/Visibility_2/doc/Visibility_2/fig \
|
||||
${CMAKE_SOURCE_DIR}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
|
||||
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
|
||||
${CMAKE_SOURCE_DIR}/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/fig \
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ Spatial_searching
|
|||
Spatial_sorting
|
||||
Segment_Delaunay_graph_2
|
||||
Straight_skeleton_2
|
||||
Visibility_2
|
||||
Voronoi_diagram_2
|
||||
Surface_mesh_simplification
|
||||
Subdivision_method_3
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ h1 {
|
|||
\package_listing{Snap_rounding_2}
|
||||
\package_listing{Envelope_2}
|
||||
\package_listing{Envelope_3}
|
||||
\package_listing{Visibility_2}
|
||||
|
||||
\section PartTriangulationsAndDelaunayTriangulations Triangulations and Delaunay Triangulations
|
||||
|
||||
|
|
|
|||
|
|
@ -245,6 +245,21 @@ and <code>src/</code> directories).
|
|||
</a></p>
|
||||
</div>
|
||||
|
||||
<h2 id="release4.7">Release 4.7 </h2>
|
||||
<div>
|
||||
<p>Release date: October 2015 </p>
|
||||
|
||||
<!-- Installation (and general changes) -->
|
||||
<!-- New packages -->
|
||||
<h3>2D Visibility (new package)</h3>
|
||||
<ul>
|
||||
<li>This package provides several variants to compute the visibility
|
||||
area of a point within polygonal regions in two dimensions.
|
||||
</li>
|
||||
</ul>
|
||||
<!-- end of the div for 4.6 -->
|
||||
</div>
|
||||
|
||||
<h2 id="release4.6">Release 4.6 </h2>
|
||||
<div>
|
||||
<p>Release date: April 2015 </p>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
\ingroup PkgVisibility_2Classes
|
||||
|
||||
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
|
||||
a polygon that may have holes.
|
||||
|
||||
\details The class template comprises the implementation of the algorithm of Takao Asano and Tetsuo Asano \cite aaghi-vpsesp-85. The algorithm, as the name of the class template suggests, requires preprocessing. The preprocessing takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space, which reduces the query time to \f$O(n)\f$.
|
||||
|
||||
The main preprocessing step is the dualization of all vertices of the input arrangment into an arrangment of lines.
|
||||
Computing this arrangement takes \f$ O(n^2)\f$ time and \f$ O(n^2)\f$ space.
|
||||
Using this arrangment it is possible to retrieve the angular order of all vertices around
|
||||
a query point, which is one of the essential steps to achive linear query time. For more details we refer to \cite aaghi-vpsesp-85.
|
||||
|
||||
|
||||
|
||||
\tparam Arrangement_2 is the type of input polygonal environment and output visibility polygon.
|
||||
|
||||
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
|
||||
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||
|
||||
|
||||
\cgalModels `Visibility_2`
|
||||
|
||||
\sa `CGAL::Simple_polygon_visibility_2<Arrangement_2, RegularizationCategory>`
|
||||
\sa `CGAL::Rotational_sweep_visibility_2<Arrangement_2, RegularizationCategory>`
|
||||
\sa `CGAL::Triangular_expansion_visibility_2<Arrangement_2, RegularizationCategory>`
|
||||
|
||||
|
||||
*/
|
||||
template <typename Arrangement_2, typename RegularizationCategory = Tag_false>
|
||||
class Preprocessed_rotational_sweep_visibility_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2 Arrangement_2;
|
||||
|
||||
/*!
|
||||
The type of the output arrangement.
|
||||
*/
|
||||
typedef Arrangement_2 Visibility_arrangement_2;
|
||||
|
||||
/*!
|
||||
The 2D point type used for the queries.
|
||||
*/
|
||||
typedef Arrangement_2::Point_2 Point_2;
|
||||
|
||||
/*!
|
||||
Face_const_handle type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2::Face_const_handle Face_const_handle;
|
||||
|
||||
/*!
|
||||
Halfedge_const_handle type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Tags
|
||||
/// @{
|
||||
/*!
|
||||
identifies whether the regularized visibility area is computed.
|
||||
*/
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
|
||||
/*!
|
||||
identifies that the class supports general polygons (i.e.\ with holes).
|
||||
*/
|
||||
typedef ::Tag_true Supports_general_polygon_category;
|
||||
|
||||
/*!
|
||||
identifies that the class supports general simple polygons.
|
||||
*/
|
||||
typedef ::Tag_true Supports_simple_polygon_category;
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// \name Constructors
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Default constructor creates an empty `Preprocessed_rotational_sweep_visibility_2` object that is not
|
||||
attached to any arrangement yet.
|
||||
*/
|
||||
Preprocessed_rotational_sweep_visibility_2();
|
||||
|
||||
/*!
|
||||
Constructs a `Preprocessed_rotational_sweep_visibility_2` object that is attached to `arr`.
|
||||
*/
|
||||
Preprocessed_rotational_sweep_visibility_2(const Arrangement_2& arr);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Returns whether an arrangement is attached to the visibility object
|
||||
*/
|
||||
bool is_attached() const;
|
||||
|
||||
/*!
|
||||
Attaches the given arrangement to the visibility object and applies preprocessing.
|
||||
In case the object is already attached to another arrangement,
|
||||
the visibility object gets detached before being attached to `arr`.
|
||||
*/
|
||||
void attach(const Arrangement_2& arr);
|
||||
|
||||
/*!
|
||||
Detaches the arrangement from the visibility object it is currently attached to
|
||||
*/
|
||||
void detach();
|
||||
|
||||
/*!
|
||||
Access to the attached arrangement
|
||||
*/
|
||||
const Arrangement_2& arr() const;
|
||||
|
||||
/*!
|
||||
Computes the visibility region of `q` in the
|
||||
face `f` of the arrangement that is attached to the visibility object.
|
||||
The visibility region of `q` will be stored in `out_arr`.
|
||||
\param q is the query point
|
||||
\param f is the face of the arrangement in which the visibility region is computed
|
||||
\param out_arr is the output arrangement
|
||||
\pre `f` is a face of `arr()` and represents a valid polygon.
|
||||
\pre `q` is in the interior of the given face `f`
|
||||
\return a handle to the face in `out_arr` that represents the visibility region
|
||||
*/
|
||||
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Face_const_handle f, Visibility_arrangement_2& out_arr) const;
|
||||
|
||||
/*!
|
||||
Computes the visibility region of `q` that is on `e`. If `q` is an interior point of `e`, the computed visibility region is restricted to the halfplane indicated by `e`. If `q` is an endpoint of `e`, the visibility region is restricted by `e` and its next.
|
||||
The visibility region of `q` will be stored in `out_arr`.
|
||||
\param q is the query point
|
||||
\param e the halfedge on which `q` is located
|
||||
\param out_arr is the output arrangement
|
||||
\pre `e` is a halfedge of `arr()`
|
||||
\pre `q` is on `e`
|
||||
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
|
||||
\return a handle to the face in `out_arr` that represents the visibility region
|
||||
*/
|
||||
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Visibility_2 */
|
||||
} /* namespace CGAL */
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
\ingroup PkgVisibility_2Classes
|
||||
|
||||
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
|
||||
|
||||
|
||||
\details The algorithm does not require preprocessing. It relies on the algorithm of T. Asano \cite ta-aeafvpprh-85 based on angular plane sweep, with a time complexity of \f$O (n \log n)\f$ in the number of vertices.
|
||||
|
||||
|
||||
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
|
||||
|
||||
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
|
||||
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||
|
||||
|
||||
|
||||
\cgalModels `Visibility_2`
|
||||
|
||||
\sa `CGAL::Simple_polygon_visibility_2`
|
||||
\sa `CGAL::Triangular_expansion_visibility_2`
|
||||
|
||||
*/
|
||||
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
|
||||
class Rotational_sweep_visibility_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2 Arrangement_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Tags
|
||||
/// @{
|
||||
/*!
|
||||
\copydoc ::Visibility_2::Regularization_category
|
||||
*/
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_general_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_true Supports_general_polygon_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_simple_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_true Supports_simple_polygon_category;
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Functions
|
||||
/// @{
|
||||
|
||||
|
||||
/*!
|
||||
Attaches the given arrangement to the visibility object.
|
||||
|
||||
This operation takes \f$O(1)\f$ as the class does no pre-processing.
|
||||
|
||||
In case the object is already attached to another arrangement,
|
||||
the visibility object gets detached before being attached to `arr`.
|
||||
*/
|
||||
void attach(const Arrangement_2& arr);
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Visibility_2 */
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
\ingroup PkgVisibility_2Classes
|
||||
|
||||
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
|
||||
a simple polygon with no holes.
|
||||
|
||||
\details This class implements the algorithm of B.Joe and R.B.Simpson \cite bjrb-clvpa-87.
|
||||
The algorithm is a modification and extension of the linear time algorithm of Lee \cite dtl-voasp-83.
|
||||
It computes the visibility region from a viewpoint that is in the interior or on the boundary of the polygon.
|
||||
|
||||
While scanning the boundary the algorithm uses a stack to manipulate the vertices, and ultimately
|
||||
yields the visibility region. For each scanned edge, at most 2 points are pushed onto the stack.
|
||||
Overall, at most 2\f$ n \f$ points are pushed or popped. Thus, the time and space complexities of the
|
||||
algorithm are \f$ O(n) \f$ even in case of degeneracies such as needles, where \f$ n \f$
|
||||
is the number of the vertices of the polygon.
|
||||
|
||||
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
|
||||
|
||||
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
|
||||
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||
|
||||
|
||||
\cgalModels `Visibility_2`
|
||||
|
||||
\sa `CGAL::Rotational_sweep_visibility_2`
|
||||
\sa `CGAL::Triangular_expansion_visibility_2`
|
||||
*/
|
||||
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
|
||||
class Simple_polygon_visibility_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The arrangement type is used for input.
|
||||
*/
|
||||
typedef Arrangement_2 Arrangement_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Tags
|
||||
/// @{
|
||||
/*!
|
||||
\copydoc ::Visibility_2::Regularization_category
|
||||
*/
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_general_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_false Supports_general_polygon_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_simple_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_true Supports_simple_polygon_category;
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Attaches the given arrangement to the visibility object.
|
||||
|
||||
This operation takes \f$O(1)\f$ as the class does no pre-processing.
|
||||
|
||||
In case the object is already attached to another arrangement,
|
||||
the visibility object gets detached before being attached to `arr`.
|
||||
*/
|
||||
void attach(const Arrangement_2& arr);
|
||||
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Visibility_2 */
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
\ingroup PkgVisibility_2Classes
|
||||
|
||||
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
|
||||
|
||||
\details The algorithm obtains a constrained triangulation from the input arrangement, then computes visibility by
|
||||
expanding the triangle that contains the query point.
|
||||
Preprocessing takes \f$ O(n)\f$ time and \f$ O(n) \f$ space, where \f$ n \f$ is the number of vertices of input polygon.
|
||||
The query time is \f$ O(nh)\f$, where \f$ h \f$ is the number of holes+1 of input polygon. Thus, for simple polygons (or a polygon with a constant number of holes) the algorithm complexity is linear, but it is \f$ O(n^2)\f$ in the worst case, as the number of holes can be linear in \f$ n \f$.
|
||||
|
||||
|
||||
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||
CGAL::Arr_segment_traits_2, or of CGAL::Arr_non_caching_segment_traits_2.
|
||||
|
||||
\tparam RegularizationCategory indicates whether the output should be regularized. It can be
|
||||
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||
|
||||
\cgalModels `Visibility_2`
|
||||
|
||||
\sa `CGAL::Simple_polygon_visibility_2`
|
||||
\sa `CGAL::Rotational_sweep_visibility_2`
|
||||
|
||||
|
||||
*/
|
||||
template <typename Arrangement_2_, typename RegularizationCategory = Tag_true>
|
||||
class Triangular_expansion_visibility_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2_ Arrangement_2;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Tags
|
||||
/// @{
|
||||
/*!
|
||||
\copydoc ::Visibility_2::Regularization_category
|
||||
*/
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_general_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_true Supports_general_polygon_category;
|
||||
|
||||
/*!
|
||||
See \ref Visibility_2::Supports_simple_polygon_category.
|
||||
*/
|
||||
typedef ::Tag_true Supports_simple_polygon_category;
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Attaches the given arrangement to the visibility object and computes the restricted triangulation.
|
||||
This takes \f$ O(n) \f$ time, where \f$ n \f$ is the number of vertices.
|
||||
|
||||
From this moment on the class observes changes in the arrangement. If the arrangement changes
|
||||
a new restricted triangulation is computed. Re-attaching forces re-computation.
|
||||
|
||||
In case the object is already attached to another arrangement,
|
||||
the visibility object gets detached before being attached to `arr`.
|
||||
*/
|
||||
void attach(const Arrangement_2& arr);
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Visibility_2 */
|
||||
} /* namespace CGAL */
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgVisibility_2Concepts
|
||||
\cgalConcept
|
||||
|
||||
A model of the `Visibility_2` concept can be attached to an `Arrangement_2` instance to
|
||||
answer visibility queries within the faces of this arrangement.
|
||||
|
||||
\cgalHasModel `CGAL::Simple_polygon_visibility_2`
|
||||
\cgalHasModel `CGAL::Rotational_sweep_visibility_2`
|
||||
\cgalHasModel `CGAL::Triangular_expansion_visibility_2`
|
||||
|
||||
*/
|
||||
class Visibility_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The arrangement type of the input.
|
||||
*/
|
||||
typedef unspecified_type Arrangement_2;
|
||||
|
||||
/*!
|
||||
The 2D point type used for the queries.
|
||||
*/
|
||||
typedef Arrangement_2::Point_2 Point_2;
|
||||
|
||||
/*!
|
||||
* The face handle type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2::Face_const_handle Face_const_handle;
|
||||
|
||||
/*!
|
||||
* The halfedge handle type of the input arrangement.
|
||||
*/
|
||||
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Tags
|
||||
/// @{
|
||||
/*!
|
||||
identifies whether the regularized visibility area is computed (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||
*/
|
||||
typedef unspecified_type Regularization_category;
|
||||
|
||||
/*!
|
||||
identifies whether general polygons (with holes) are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||
A general polygon is represented by a face \f$ f \f$ with no
|
||||
isolated vertex and any edge of \f$ f \f$ separates \f$ f \f$ from another face.
|
||||
Note that this allows \f$ f \f$ to touch a vertex from several sides.
|
||||
*/
|
||||
typedef unspecified_type Supports_general_polygon_category;
|
||||
|
||||
/*!
|
||||
identifies whether simple polygons are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||
|
||||
A simple polygon is represented by a face \f$ f \f$ with no holes,
|
||||
no isolated vertex and any edge of \f$ f \f$ separates \f$ f \f$ from another face.
|
||||
Note that this allows \f$ f \f$ to touch a vertex from several sides.
|
||||
*/
|
||||
typedef unspecified_type Supports_simple_polygon_category;
|
||||
/// @}
|
||||
|
||||
/// \name Constructors
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Default constructor creates an empty `Visibility_2` object that is not
|
||||
attached to any arrangement yet.
|
||||
*/
|
||||
Visibility_2();
|
||||
|
||||
/*!
|
||||
Constructs a `Visibility_2` object that is attached to `arr`.
|
||||
*/
|
||||
Visibility_2(const Arrangement_2& arr);
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Returns whether an arrangement is attached to the visibility object
|
||||
*/
|
||||
bool is_attached() const;
|
||||
|
||||
/*!
|
||||
Attaches the given arrangement `arr` to the visibility object.
|
||||
In case the object is already attached to another arrangement,
|
||||
the visibility object gets detached before being attached to `arr`.
|
||||
*/
|
||||
void attach(const Arrangement_2& arr);
|
||||
|
||||
|
||||
/*!
|
||||
Detaches the arrangement from the visibility object it is currently attached to
|
||||
*/
|
||||
void detach();
|
||||
|
||||
/*!
|
||||
Access to the attached arrangement
|
||||
*/
|
||||
const Arrangement_2& arrangement_2() const;
|
||||
|
||||
/*!
|
||||
Computes the visibility region for the given query point `q` in the
|
||||
face \f$ f \f$ of the arrangement that is attached to the visibility object.
|
||||
The visibility region of `q` is stored in `out_arr`, that is,
|
||||
all features but the unbounded face of `out_arr` represent the visibility region.
|
||||
|
||||
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
|
||||
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
|
||||
must be mutual convertible to Visibility_2::Traits_2.
|
||||
|
||||
\param q is the query point
|
||||
\param f is the face of the arrangement in which the visibility region is computed
|
||||
\param out_arr is the output arrangement
|
||||
\pre `f` is a face of `this->arrangement_2()`
|
||||
\pre `q` is in the interior of the given face `f`
|
||||
\return the face handle to the face in `out_arr` that represents interior of the visibility region
|
||||
*/
|
||||
template <typename VisibilityArrangement_2>
|
||||
typename Visibility_arrangement_2::Face_handle
|
||||
compute_visibility(const Point_2& q, const Face_const_handle f, VisibilityArrangement_2& out_arr) const;
|
||||
|
||||
/*!
|
||||
Computes the visibility region in `e->face()` for the given query
|
||||
point `q` which must be located on `e`.
|
||||
If `q` is an interior point of `e`, the computed visibility
|
||||
region is restricted to the side indicated by the halfedge `e`.
|
||||
If `q` is an endpoint of `e`, the visibility region is restricted by `e` and `e->next()`.
|
||||
The visibility region of `q` is stored in `out_arr`, that is,
|
||||
all features but the unbounded face of `out_arr` represent the visibility region.
|
||||
|
||||
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
|
||||
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
|
||||
must be mutual convertible to Visibility_2::Traits_2.
|
||||
\param q is the query point
|
||||
\param e the halfedge on which `q` is located
|
||||
\param out_arr is the output arrangement
|
||||
\pre `e` is a halfedge of `this->arrangement_2()`
|
||||
\pre `q` is on `e`
|
||||
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
|
||||
\return a handle to the face in `out_arr` that represents the interior of the visibility region
|
||||
*/
|
||||
template <typename VisibilityArrangement_2>
|
||||
typename Visibility_arrangement_2::Face_handle
|
||||
compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Visibility_2 */
|
||||
|
||||
|
|
@ -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/
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/// \defgroup PkgVisibility_2 Visibility_2 Reference
|
||||
|
||||
/// \defgroup PkgVisibility_2Concepts Concepts
|
||||
/// \ingroup PkgVisibility_2
|
||||
|
||||
/*!
|
||||
\addtogroup PkgVisibility_2
|
||||
\cgalPkgDescriptionBegin{2D Visibility Computation,PkgVisibility_2Summary}
|
||||
\cgalPkgPicture{visibility-teaser-thumbnail.png}
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu}
|
||||
\cgalPkgDesc{This package provides several variants to compute
|
||||
the visibility area of a point within polygonal regions in two dimensions.}
|
||||
\cgalPkgManuals{Chapter_2D_Visibility_Computation,PkgVisibility_2}
|
||||
\cgalPkgSummaryEnd
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{99.99}
|
||||
\cgalPkgBib{hhb-visibility-2}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgShortInfoEnd
|
||||
\cgalPkgDescriptionEnd
|
||||
|
||||
\cgalClassifedRefPages
|
||||
|
||||
## Concepts ##
|
||||
- `Visibility_2`
|
||||
|
||||
## Classes ##
|
||||
- `CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_tag>`
|
||||
- `CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag>`
|
||||
- `CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag>`
|
||||
*/
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
Manual
|
||||
Kernel_23
|
||||
STL_Extension
|
||||
Algebraic_foundations
|
||||
Circulator
|
||||
Stream_support
|
||||
Arrangement_on_surface_2
|
||||
Boolean_set_operations_2
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/*!
|
||||
\example Visibility_2/simple_polygon_visibility_2.cpp
|
||||
\example Visibility_2/general_polygon_example.cpp
|
||||
*/
|
||||
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 297 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 464 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
|
@ -0,0 +1,162 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_2D_Visibility_Computation
|
||||
\cgalAutoToc
|
||||
|
||||
\authors Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu
|
||||
|
||||
<!-- \cgalFigureBegin{example_figure,visibility-teaser.png}\cgalFigureEnd -->
|
||||
|
||||
\section visibility_2_introduction Introduction
|
||||
|
||||
This package provides functionality to compute the visibility region within polygons in two dimensions.
|
||||
The package is based on the package \ref PkgArrangement2Summary and uses CGAL::Arrangement_2
|
||||
as the fundamental class to specify the input as well as the output.
|
||||
Hence, a polygon \f$ P \f$ is represented by a bounded arrangement face \f$ f \f$
|
||||
that does not have any isolated vertices and any edge that is adjacent to \f$ f \f$ separates \f$ f \f$ from another face.
|
||||
Note that \f$ f \f$ may contain holes.
|
||||
Similarly, a simple polygon is represented by a face without holes.
|
||||
|
||||
Given two points \f$ p \f$ and \f$ q \f$ in \f$ P \f$, they are said to be
|
||||
visible to each other iff the segment \f$ pq \subset P \f$, where \f$ P \f$ is
|
||||
considered to be closed, that is, \f$\partial P \subset P\f$.
|
||||
For a query point \f$ q \in P \f$, the set of points that are visible from
|
||||
\f$ q \f$ is defined as the visibility region of \f$ q \f$, denoted by \f$ V_q \f$
|
||||
|
||||
\subsection visibility_2_degeneracies Degeneracies and Regularization
|
||||
|
||||
\cgalFigureBegin{definition-fig, example1.png}
|
||||
Non-regularized visibility and regularized visibility.
|
||||
\cgalFigureEnd
|
||||
|
||||
|
||||
As illustrated in \cgalFigureRef{definition-fig} (1) the visibility
|
||||
region \f$ V_q \f$ of a query point \f$ q \f$ may not be a polygon.
|
||||
In the figure, all labeled points are collinear, which implies that the
|
||||
point \f$ c \f$ is visible to \f$ q \f$, that is,
|
||||
the segment \f$ bc \f$ is part of \f$ V_q \f$.
|
||||
We call such low dimensional features that are caused by degeneracies `needles`.
|
||||
However, for many applications these needles are actually irrelevant.
|
||||
Moreover, for some algorithms it is even more efficient to ignore needles
|
||||
in the first place.
|
||||
Therefore, this package offers also
|
||||
functionality to compute the regularized visibility area
|
||||
\f$ \overline{V_q} = closure(interior(V_q)) = (V_q\setminus\partial V_q) \cup \partial (V_q\setminus\partial V_q)\f$,
|
||||
as shown in \cgalFigureRef{definition-fig} (2).
|
||||
For more information about regularization, refer to Chapter \ref PkgBooleanSetOperations2Summary.
|
||||
|
||||
\section visibility_2_classes Classes and Algorithms
|
||||
|
||||
Answering visibility queries is, in many ways, similar to answering point-location queries.
|
||||
Thus, we use the same design used to implement \ref PkgArrangement2Summary point location.
|
||||
Each of the various visibility class templates employs a different
|
||||
algorithm or \em strategy for answering
|
||||
queries\cgalFootnote{The term \em strategy is borrowed from the
|
||||
design-pattern taxonomy~\cite ghjv-dpero-95.
|
||||
A \em strategy provides the means to define a family of algorithms,
|
||||
each implemented by a separate class. All classes that implement the various
|
||||
algorithms are made interchangeable, letting the algorithm in use vary according to the user choice.}.
|
||||
Similar to the point-location case, some of the strategies require preprocessing. Thus, before a visibility object is used
|
||||
to answer visibility queries, it must be attached to an arrangement object.
|
||||
Afterwards, the visibility object observes changes to the attached arrangement.
|
||||
Hence, it is possible to modify the arrangement after attaching the visibility object.
|
||||
However, this feature should be used with caution as each change to the arrangement also
|
||||
requires an update of the auxiliary data structures in the attached object.
|
||||
|
||||
An actual query is performed by giving the view point \f$ p \f$ and its containing face \f$ f \f$
|
||||
(which must represent a valid polygon) to a visibility object.
|
||||
For more details see the documentation of the overloaded member function `Visibility_2::compute_visibility()`.
|
||||
|
||||
The following models of the `Visibility_2` concept are provided:
|
||||
|
||||
<CENTER>
|
||||
Class | Function | Preprocessing | Query |Algorithm
|
||||
-------------------------------|-----------------------------------------------------|-------------------------------|-----------------------------------|-------------------------------
|
||||
`Simple_polygon_visibility_2` | simple polygons | No |\f$ O(n) \f$ time and \f$ O(n) \f$ space | B. Joe and R. B. Simpson \cite bjrb-clvpa-87
|
||||
`Rotational_sweep_visibility_2` | polygons with holes | No | \f$ O(n\log n) \f$ time and \f$ O(n) \f$ space | T. Asano \cite ta-aeafvpprh-85
|
||||
`Triangular_expansion_visibility_2` | polygons with holes | \f$ O(n) \f$ time and \f$ O(n) \f$ space | \f$ O(nh) \f$ time and \f$ O(n) \f$ space. | Bungiu et al. \cite ecvp-bhhhk-14
|
||||
</CENTER>
|
||||
|
||||
Where \f$ n \f$ denotes the number of vertices of \f$ f \f$ and \f$ h \f$ the number of holes+1.
|
||||
|
||||
\section benchmarks Running Time in Practice
|
||||
|
||||
\cgalFigureBegin{cathedral-fig, cathedral_2.png}
|
||||
Example representing a cathedral.
|
||||
\cgalFigureEnd
|
||||
|
||||
The left hand side of Figure \cgalFigureRef{cathedral-fig} depicts the outer boundary of a cathedral,
|
||||
which is a simple polygon with 565 vertices.
|
||||
The right hand side shows the cathedral also with its inner pillars, which is a polygon (with holes)
|
||||
with 1153 vertices.
|
||||
The following table shows the total running time consumption of the computation of
|
||||
all visibility polygons for all vertices of the cathedral.
|
||||
|
||||
<CENTER>
|
||||
Boundary Cathedral | total preprocessing time | total query time |
|
||||
-------------------------------|-----------------------------------------------------|-------------------------------|
|
||||
`Simple_polygon_visibility_2` | - | 0.38 |
|
||||
`Rotational_sweep_visibility_2` | - | 1.01 |
|
||||
`Triangular_expansion_visibility_2` | 0.01 | 0.06 |
|
||||
</CENTER>
|
||||
|
||||
The second table shows the same for the complete cathedral.
|
||||
The table does not report the time for `Simple_polygon_visibility_2`
|
||||
as this algorithm can only handle simple polygons.
|
||||
|
||||
<CENTER>
|
||||
Complete Cathedral | total preprocessing time | total query time |
|
||||
-------------------------------|-----------------------------------------------------|-------------------------------|
|
||||
`Rotational_sweep_visibility_2` | - | 1.91 |
|
||||
`Triangular_expansion_visibility_2` | 0.01 | 0.04 |
|
||||
</CENTER>
|
||||
|
||||
Thus, in general we recommend to use `Triangular_expansion_visibility_2` even if the polygon is simple.
|
||||
The main advantage of the algorithm is its locality.
|
||||
After the triangle that contains the query point is located in the triangulation,
|
||||
the algorithm explores neighboring triangles, but only those that are actually seen.
|
||||
In this sense the algorithm can be considered as output sensitive.
|
||||
Note that the `Triangular_expansion_visibility_2` algorithm performs better on the full
|
||||
cathedral since the additional pillars block the view early in many cases.
|
||||
However, if the simple polygon is rather convex (i.e., nearly all boundary is seen) or
|
||||
if only one (or very little) queries are required, using one of the algorithms that
|
||||
does not require preprocessing is advantageous.
|
||||
|
||||
|
||||
\section simple_polygon_visibility_example Example of Visibility in a Simple Polygon
|
||||
The following example shows how to obtain the regularized and non-regularized visibility regions.
|
||||
|
||||
\cgalFigureBegin{simple_example, simple_example.png}
|
||||
|
||||
The visibility region of \f$ q \f$ in a simple polygon: (1) non-regularized visibility; and (2) regularized visibility.
|
||||
\cgalFigureEnd
|
||||
\cgalExample{Visibility_2/simple_polygon_visibility_2.cpp}
|
||||
|
||||
\section general_polygon_example Example of Visibility in a Polygon with Holes
|
||||
The following example shows how to obtain the regularized visibility region using the model
|
||||
`Triangular_expansion_visibility_2`, see \cgalFigureRef{general_polygon}.
|
||||
The arrangement has six bounded faces and an unbounded face.
|
||||
The query point \f$ q \f$ is on a vertex.
|
||||
The red arrow denotes the halfedge \f$ \overrightarrow{pq} \f$,
|
||||
which also identifies the face in which the visibility region is computed.
|
||||
\cgalFigureBegin{general_polygon, general_polygon_example.png}
|
||||
The visibility region of \f$ q \f$ in a polygon with two holes.
|
||||
\cgalFigureEnd
|
||||
\cgalExample{Visibility_2/general_polygon_example.cpp}
|
||||
|
||||
\section implementation_history Implementation History
|
||||
|
||||
This package was first developed during Google Summer of Code 2013:
|
||||
Francisc Bungiu developed the `CGAL::Simple_polygon_visibility_2`,
|
||||
Kan Huang developed the `CGAL::Rotational_sweep_visibility_2`,
|
||||
and Michael Hemmer developed the `CGAL::Triangular_expansion_visibility_2`.
|
||||
|
||||
During Google Summer of Code 2014 Ning Xu fixed a bug in `CGAL::Simple_polygon_visibility_2` and improved the testsuite.
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// `Preprocessed_rotational_sweep_visibility_2` | polygons with holes | \f$ O(n^2) \f$ time and \f$ O(n^2) \f$ space | \f$ O(n) \f$ time and \f$ O(n) \f$ space | Takao Asano, Tetsuo Asano etc \cite aaghi-vpsesp-85
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// Define the used kernel and arrangement
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Segment_2 Segment_2;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef Arrangement_2::Face_handle Face_handle;
|
||||
|
||||
// Define the used visibility class
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2> TEV;
|
||||
|
||||
int main() {
|
||||
// Defining the input geometry
|
||||
Point_2 p1(1,2), p2(12, 3), p3(19,-2), p4(12,6), p5(14,14), p6( 9,5);
|
||||
Point_2 h1(8,3), h2(10, 3), h3( 8, 4), h4(10,6), h5(11, 6), h6(11,7);
|
||||
std::vector<Segment_2> segments;
|
||||
segments.push_back(Segment_2(p1,p2));
|
||||
segments.push_back(Segment_2(p2,p3));
|
||||
segments.push_back(Segment_2(p3,p4));
|
||||
segments.push_back(Segment_2(p4,p5));
|
||||
segments.push_back(Segment_2(p5,p6));
|
||||
segments.push_back(Segment_2(p6,p1));
|
||||
|
||||
segments.push_back(Segment_2(h1,h2));
|
||||
segments.push_back(Segment_2(h2,h3));
|
||||
segments.push_back(Segment_2(h3,h1));
|
||||
segments.push_back(Segment_2(h4,h5));
|
||||
segments.push_back(Segment_2(h5,h6));
|
||||
segments.push_back(Segment_2(h6,h4));
|
||||
|
||||
// insert geometry into the arrangement
|
||||
Arrangement_2 env;
|
||||
CGAL::insert_non_intersecting_curves(env,segments.begin(),segments.end());
|
||||
|
||||
//Find the halfedge whose target is the query point.
|
||||
//(usually you may know that already by other means)
|
||||
Point_2 query_point = p4;
|
||||
Halfedge_const_handle he = env.halfedges_begin();
|
||||
while (he->source()->point() != p3 || he->target()->point() != p4)
|
||||
he++;
|
||||
|
||||
//visibility query
|
||||
Arrangement_2 output_arr;
|
||||
TEV tev(env);
|
||||
Face_handle fh = tev.compute_visibility(query_point, he, output_arr);
|
||||
|
||||
//print out the visibility region.
|
||||
std::cout << "Regularized visibility region of q has "
|
||||
<< output_arr.number_of_edges()
|
||||
<< " edges." << std::endl;
|
||||
|
||||
std::cout << "Boundary edges of the visibility region:" << std::endl;
|
||||
Arrangement_2::Ccb_halfedge_circulator curr = fh->outer_ccb();
|
||||
std::cout << "[" << curr->source()->point() << " -> " << curr->target()->point() << "]" << std::endl;
|
||||
while (++curr != fh->outer_ccb())
|
||||
std::cout << "[" << curr->source()->point() << " -> " << curr->target()->point() << "]"<< std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arr_naive_point_location.h>
|
||||
#include <istream>
|
||||
#include <vector>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Segment_2 Segment_2;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef Arrangement_2::Face_handle Face_handle;
|
||||
typedef Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||
typedef Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator;
|
||||
|
||||
|
||||
int main() {
|
||||
//create environment
|
||||
Point_2 p1(0,4), p2(0,0), p3(3,2), p4(4,0), p5(4,4), p6(1,2);
|
||||
std::vector<Segment_2> segments;
|
||||
segments.push_back(Segment_2(p1, p2));
|
||||
segments.push_back(Segment_2(p2, p3));
|
||||
segments.push_back(Segment_2(p3, p4));
|
||||
segments.push_back(Segment_2(p4, p5));
|
||||
segments.push_back(Segment_2(p5, p6));
|
||||
segments.push_back(Segment_2(p6, p1));
|
||||
|
||||
Arrangement_2 env;
|
||||
CGAL::insert_non_intersecting_curves(env,segments.begin(),segments.end());
|
||||
|
||||
// find the face of the query point
|
||||
// (usually you may know that by other means)
|
||||
Point_2 q(0.5, 2);
|
||||
Arrangement_2::Face_const_handle * face;
|
||||
CGAL::Arr_naive_point_location<Arrangement_2> pl(env);
|
||||
CGAL::Arr_point_location_result<Arrangement_2>::Type obj = pl.locate(q);
|
||||
// The query point locates in the interior of a face
|
||||
face = boost::get<Arrangement_2::Face_const_handle> (&obj);
|
||||
|
||||
// compute non regularized visibility area
|
||||
// Define visibiliy object type that computes non-regularized visibility area
|
||||
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false> NSPV;
|
||||
Arrangement_2 non_regular_output;
|
||||
NSPV non_regular_visibility(env);
|
||||
|
||||
non_regular_visibility.compute_visibility(q, *face, non_regular_output);
|
||||
|
||||
std::cout << "Non-regularized visibility region of q has "
|
||||
<< non_regular_output.number_of_edges()
|
||||
<< " edges:" << std::endl;
|
||||
for (Edge_const_iterator eit = non_regular_output.edges_begin(); eit != non_regular_output.edges_end(); ++eit)
|
||||
std::cout << "[" << eit->source()->point() << " -> " << eit->target()->point() << "]" << std::endl;
|
||||
|
||||
|
||||
// compute non regularized visibility area
|
||||
// Define visibiliy object type that computes regularized visibility area
|
||||
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_true> RSPV;
|
||||
Arrangement_2 regular_output;
|
||||
RSPV regular_visibility(env);
|
||||
|
||||
regular_visibility.compute_visibility(q, *face, regular_output);
|
||||
|
||||
std::cout << "Regularized visibility region of q has "
|
||||
<< regular_output.number_of_edges()
|
||||
<< " edges:" << std::endl;
|
||||
for (Edge_const_iterator eit = regular_output.edges_begin(); eit != regular_output.edges_end(); ++eit)
|
||||
std::cout << "[" << eit->source()->point() << " -> " << eit->target()->point() << "]" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,934 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
||||
//
|
||||
|
||||
#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
|
||||
#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
|
||||
|
||||
#include <CGAL/Visibility_2/visibility_utils.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2_ , class RegularizationCategory = CGAL::Tag_true >
|
||||
class Rotational_sweep_visibility_2 {
|
||||
public:
|
||||
typedef Arrangement_2_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::
|
||||
Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
|
||||
typedef typename Geometry_traits_2::Kernel K;
|
||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||
typedef typename Geometry_traits_2::FT Number_type;
|
||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
typedef CGAL::Tag_true Supports_general_polygon_category;
|
||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||
|
||||
private:
|
||||
typedef std::vector<Point_2> Points;
|
||||
typedef Vertex_const_handle VH;
|
||||
typedef std::vector<VH> VHs;
|
||||
typedef Halfedge_const_handle EH;
|
||||
typedef std::vector<EH> EHs;
|
||||
|
||||
class Less_edge: public std::binary_function<EH, EH, bool> {
|
||||
const Geometry_traits_2* geom_traits;
|
||||
public:
|
||||
Less_edge() {}
|
||||
Less_edge(const Geometry_traits_2* traits):geom_traits(traits) {}
|
||||
bool operator() (const EH e1, const EH e2) const {
|
||||
if (e1 == e2)
|
||||
return false;
|
||||
else {
|
||||
return &(*e1)<&(*e2);
|
||||
}
|
||||
// if (e1->source() == e2->source())
|
||||
// return Visibility_2::compare_xy_2(geom_traits,
|
||||
// e1->target()->point(), e2->target()->point()) == SMALLER;
|
||||
// else
|
||||
// return Visibility_2::compare_xy_2(geom_traits,
|
||||
// e1->source()->point(), e2->source()->point()) == SMALLER;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class Less_vertex: public std::binary_function<VH, VH, bool> {
|
||||
const Geometry_traits_2* geom_traits;
|
||||
public:
|
||||
Less_vertex() {}
|
||||
Less_vertex(const Geometry_traits_2* traits):geom_traits(traits) {}
|
||||
bool operator() (const VH v1, const VH v2) const {
|
||||
if (v1 == v2)
|
||||
return false;
|
||||
else
|
||||
// I know this is dirty but it speeds up by 25%. Michael
|
||||
return &(*v1)<&(*v2);
|
||||
// return Visibility_2::
|
||||
// compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
|
||||
}
|
||||
};
|
||||
|
||||
class Closer_edge: public std::binary_function<EH, EH, bool> {
|
||||
const Geometry_traits_2* geom_traits;
|
||||
Point_2 q;
|
||||
public:
|
||||
Closer_edge() {}
|
||||
Closer_edge(const Geometry_traits_2* traits, const Point_2& q) :
|
||||
geom_traits(traits), q(q) {}
|
||||
|
||||
int vtype(const Point_2& c, const Point_2& p) const {
|
||||
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
|
||||
case COLLINEAR:
|
||||
if (Visibility_2::less_distance_to_point_2(geom_traits, q, c, p))
|
||||
return 0;
|
||||
else
|
||||
return 3;
|
||||
case RIGHT_TURN:
|
||||
return 1;
|
||||
case LEFT_TURN:
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool operator() (const EH& e1, const EH& e2) const {
|
||||
if (e1 == e2)
|
||||
return false;
|
||||
const Point_2& s1=e1->source()->point(),
|
||||
t1=e1->target()->point(),
|
||||
s2=e2->source()->point(),
|
||||
t2=e2->target()->point();
|
||||
if (e1->source() == e2->source()) {
|
||||
|
||||
int vt1 = vtype(s1, t1),
|
||||
vt2 = vtype(s1, t2);
|
||||
if (vt1 != vt2)
|
||||
return vt1 > vt2;
|
||||
else
|
||||
return (Visibility_2::orientation_2(geom_traits, s1, t2, t1)==
|
||||
Visibility_2::orientation_2(geom_traits, s1, t2, q));
|
||||
}
|
||||
|
||||
if (e1->target() == e2->source()) {
|
||||
// const Point_2& p1 = s1,
|
||||
// p2 = t2,
|
||||
// c = s2;
|
||||
int vt1 = vtype(t1, s1),
|
||||
vt2 = vtype(t1, t2);
|
||||
if (vt1 != vt2)
|
||||
return vt1 > vt2;
|
||||
else
|
||||
return (Visibility_2::orientation_2(geom_traits, s2, t2, s1)==
|
||||
Visibility_2::orientation_2(geom_traits, s2, t2, q));
|
||||
}
|
||||
|
||||
if (e1->source() == e2->target()) {
|
||||
// const Point_2& p1 = t1,
|
||||
// p2 = s2,
|
||||
// c = s1;
|
||||
int vt1 = vtype(s1, t1),
|
||||
vt2 = vtype(s1, s2);
|
||||
if (vt1 != vt2)
|
||||
return vt1 > vt2;
|
||||
else return (Visibility_2::orientation_2(geom_traits, s1, s2, t1)==
|
||||
Visibility_2::orientation_2(geom_traits, s1, s2, q));
|
||||
}
|
||||
|
||||
if (e1->target() == e2->target()) {
|
||||
// const Point_2& p1 = s1,
|
||||
// p2 = s2,
|
||||
// c = t1;
|
||||
int vt1 = vtype(t1, s1),
|
||||
vt2 = vtype(t1, s2);
|
||||
if (vt1 != vt2)
|
||||
return vt1 > vt2;
|
||||
else return (Visibility_2::orientation_2(geom_traits, t1, s2, s1)==
|
||||
Visibility_2::orientation_2(geom_traits, t1, s2, q));
|
||||
}
|
||||
|
||||
Orientation e1q = Visibility_2::orientation_2(geom_traits, s1, t1, q);
|
||||
switch (e1q)
|
||||
{
|
||||
case COLLINEAR:
|
||||
if (Visibility_2::collinear(geom_traits, q, s2, t2)) {
|
||||
//q is collinear with e1 and e2.
|
||||
return (Visibility_2::less_distance_to_point_2(geom_traits, q, s1, s2)
|
||||
|| Visibility_2::less_distance_to_point_2(geom_traits, q, t1, t2));
|
||||
}
|
||||
else {
|
||||
//q is collinear with e1 not with e2.
|
||||
if (Visibility_2::collinear(geom_traits, s2, t2, s1))
|
||||
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, t1));
|
||||
else
|
||||
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1));
|
||||
}
|
||||
case RIGHT_TURN:
|
||||
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
|
||||
case COLLINEAR:
|
||||
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
||||
case RIGHT_TURN:
|
||||
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
|
||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||
else
|
||||
return false;
|
||||
case LEFT_TURN:
|
||||
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
case LEFT_TURN:
|
||||
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
|
||||
case COLLINEAR:
|
||||
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
||||
case LEFT_TURN:
|
||||
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||
else
|
||||
return false;
|
||||
case RIGHT_TURN:
|
||||
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
|
||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const Arrangement_2 *p_arr;
|
||||
const Geometry_traits_2 *geom_traits;
|
||||
|
||||
|
||||
mutable Point_2 q; //query point
|
||||
mutable Points polygon; //visibility polygon
|
||||
|
||||
mutable std::map<VH, EHs, Less_vertex> incident_edges;
|
||||
|
||||
mutable std::map<EH, int, Less_edge> edx; //index of active edges in
|
||||
//the heap
|
||||
|
||||
mutable std::set<EH, Closer_edge> active_edges; //a set of edges that
|
||||
//intersect the current
|
||||
//vision ray.
|
||||
|
||||
mutable VHs vs; //angular sorted vertices
|
||||
mutable EHs bad_edges; //edges that pass the query point
|
||||
mutable VH cone_end1; //an end of visibility cone
|
||||
mutable VH cone_end2; //another end of visibility cone
|
||||
|
||||
mutable typename Points::size_type cone_end1_idx;
|
||||
//index of cone_end1->point() in
|
||||
//visibility polygon
|
||||
|
||||
mutable typename Points::size_type cone_end2_idx;
|
||||
//index of cone_end2->point() in
|
||||
//visibility polygon
|
||||
|
||||
mutable bool is_vertex_query;
|
||||
mutable bool is_edge_query;
|
||||
mutable bool is_face_query;
|
||||
mutable bool is_big_cone; //whether the angle of
|
||||
//visibility_cone is greater than pi.
|
||||
|
||||
public:
|
||||
Rotational_sweep_visibility_2(): p_arr(NULL), geom_traits(NULL) {}
|
||||
Rotational_sweep_visibility_2(const Arrangement_2& arr): p_arr(&arr) {
|
||||
geom_traits = p_arr->geometry_traits();
|
||||
}
|
||||
|
||||
const std::string name() const { return std::string("R_visibility_2"); }
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(
|
||||
const Point_2& q, const Halfedge_const_handle e, VARR& arr_out) const
|
||||
{
|
||||
arr_out.clear();
|
||||
bad_edges.clear();
|
||||
this->q = q;
|
||||
|
||||
if (Visibility_2::compare_xy_2(geom_traits, q, e->target()->point())==EQUAL)
|
||||
{
|
||||
is_vertex_query = true;
|
||||
is_edge_query = false;
|
||||
is_face_query = false;
|
||||
cone_end1 = e->source();
|
||||
cone_end2 = e->next()->target();
|
||||
is_big_cone = CGAL::right_turn(cone_end1->point(), q, cone_end2->point());
|
||||
|
||||
typename Arrangement_2::
|
||||
Halfedge_around_vertex_const_circulator first, curr;
|
||||
first = curr = e->target()->incident_halfedges();
|
||||
do {
|
||||
if (curr->face() == e->face())
|
||||
bad_edges.push_back(curr);
|
||||
else if (curr->twin()->face() == e->face())
|
||||
bad_edges.push_back(curr->twin());
|
||||
} while (++curr != first);
|
||||
}
|
||||
else {
|
||||
is_vertex_query = false;
|
||||
is_edge_query = true;
|
||||
is_face_query = false;
|
||||
cone_end1 = e->source();
|
||||
cone_end2 = e->target();
|
||||
bad_edges.push_back(e);
|
||||
is_big_cone = false;
|
||||
}
|
||||
visibility_region_impl(e->face(), q);
|
||||
|
||||
//decide which inside of the visibility butterfly is needed.
|
||||
typename Points::size_type small_idx, big_idx;
|
||||
if ( cone_end1_idx < cone_end2_idx ) {
|
||||
small_idx = cone_end1_idx;
|
||||
big_idx = cone_end2_idx;
|
||||
}
|
||||
else {
|
||||
small_idx = cone_end2_idx;
|
||||
big_idx = cone_end1_idx;
|
||||
}
|
||||
typename Points::size_type next_idx = small_idx + 1;
|
||||
bool is_between;
|
||||
//indicate whether the shape between small_idx and big_idx is the visibility
|
||||
//region required.
|
||||
if (CGAL::right_turn(cone_end1->point(), q, cone_end2->point())) {
|
||||
is_between = false;
|
||||
while (next_idx != big_idx) {
|
||||
if (CGAL::left_turn(cone_end1->point(), q, polygon[next_idx]) ||
|
||||
CGAL::left_turn(q, cone_end2->point(), polygon[next_idx]))
|
||||
{
|
||||
is_between = true;
|
||||
break;
|
||||
}
|
||||
next_idx++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
is_between = true;
|
||||
while (next_idx != big_idx) {
|
||||
if (CGAL::right_turn(cone_end1->point(), q, polygon[next_idx]) ||
|
||||
CGAL::right_turn(q, cone_end2->point(), polygon[next_idx]))
|
||||
{
|
||||
is_between = false;
|
||||
break;
|
||||
}
|
||||
next_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
typename Points::iterator first = polygon.begin();
|
||||
std::advance(first, small_idx);
|
||||
typename Points::iterator last = polygon.begin();
|
||||
std::advance(last, big_idx);
|
||||
|
||||
if (is_between) {
|
||||
Points polygon_out(first, last+1);
|
||||
if (is_vertex_query)
|
||||
polygon_out.push_back(q);
|
||||
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||
(geom_traits, q, polygon_out, arr_out);
|
||||
}
|
||||
else {
|
||||
Points polygon_out(polygon.begin(), first+1);
|
||||
if (is_vertex_query) polygon_out.push_back(q);
|
||||
for (typename Points::size_type i = big_idx; i != polygon.size(); i++) {
|
||||
polygon_out.push_back(polygon[i]);
|
||||
}
|
||||
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||
(geom_traits, q, polygon_out, arr_out);
|
||||
}
|
||||
|
||||
Visibility_2::conditional_regularize(arr_out, Regularization_category());
|
||||
|
||||
if (arr_out.faces_begin()->is_unbounded())
|
||||
return ++arr_out.faces_begin();
|
||||
else
|
||||
return arr_out.faces_begin();
|
||||
}
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(
|
||||
const Point_2& q, const Face_const_handle f, VARR& arr_out) const
|
||||
{
|
||||
arr_out.clear();
|
||||
this->q = q;
|
||||
is_vertex_query = false;
|
||||
is_edge_query = false;
|
||||
is_face_query = true;
|
||||
|
||||
visibility_region_impl(f, q);
|
||||
|
||||
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||
(geom_traits, q, polygon, arr_out);
|
||||
|
||||
Visibility_2::conditional_regularize(arr_out, Regularization_category());
|
||||
|
||||
if (arr_out.faces_begin()->is_unbounded())
|
||||
return ++arr_out.faces_begin();
|
||||
else
|
||||
return arr_out.faces_begin();
|
||||
}
|
||||
|
||||
bool is_attached() const {
|
||||
return (p_arr != NULL);
|
||||
}
|
||||
|
||||
void attach(const Arrangement_2& arr) {
|
||||
p_arr = &arr;
|
||||
geom_traits = p_arr->geometry_traits();
|
||||
}
|
||||
|
||||
void detach() {
|
||||
p_arr = NULL;
|
||||
geom_traits = NULL;
|
||||
}
|
||||
|
||||
const Arrangement_2& arrangement_2() const {
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
private:
|
||||
//get the neighbor of v along edge e
|
||||
VH get_neighbor(const EH e, const VH v) const {
|
||||
if (e->source() == v)
|
||||
return e->target();
|
||||
else
|
||||
return e->source();
|
||||
}
|
||||
|
||||
//check whether ray(q->dp) intersects segment(p1, p2)
|
||||
bool do_intersect_ray(const Point_2& q,
|
||||
const Point_2& dp,
|
||||
const Point_2& p1,
|
||||
const Point_2& p2) const
|
||||
{
|
||||
return (CGAL::orientation(q, dp, p1) != CGAL::orientation(q, dp, p2) &&
|
||||
CGAL::orientation(q, p1, dp) == CGAL::orientation(q, p1, p2));
|
||||
}
|
||||
|
||||
//arrange vertices that on a same vision ray in a 'funnel' order
|
||||
void funnel(typename VHs::size_type i, typename VHs::size_type j) const {
|
||||
VHs right, left;
|
||||
//whether the edges incident to a vertex block the left side and right side
|
||||
//of current vision ray.
|
||||
bool block_left(false), block_right(false);
|
||||
VH former = vs[i], nb;
|
||||
for (typename VHs::size_type l=i; l<j; l++) {
|
||||
bool left_v(false), right_v(false), has_predecessor(false);
|
||||
EHs& edges = incident_edges[vs[l]];
|
||||
for (typename EHs::size_type k=0; k<edges.size(); k++) {
|
||||
nb = get_neighbor(edges[k], vs[l]);
|
||||
if ( nb == former ) {
|
||||
has_predecessor = true;
|
||||
break;
|
||||
}
|
||||
if (CGAL::left_turn(q, vs[l]->point(), nb->point()))
|
||||
left_v = true;
|
||||
else
|
||||
right_v = CGAL::right_turn(q, vs[l]->point(), nb->point());
|
||||
}
|
||||
if (has_predecessor) {
|
||||
//if the current vertex connects to the vertex before by an edge,
|
||||
//the vertex before can help it to block.
|
||||
block_left = block_left || left_v;
|
||||
block_right = block_right || right_v;
|
||||
}
|
||||
else {
|
||||
block_left = left_v;
|
||||
block_right = right_v;
|
||||
}
|
||||
if (block_left && block_right) {
|
||||
//when both sides are blocked,
|
||||
//there is no need to change the vertex after.
|
||||
right.push_back(vs[l]);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (block_left)
|
||||
left.push_back(vs[l]);
|
||||
else
|
||||
right.push_back(vs[l]);
|
||||
}
|
||||
former = vs[l];
|
||||
}
|
||||
for (typename VHs::size_type l=0; l!=right.size(); l++)
|
||||
vs[i+l] = right[l];
|
||||
for (typename VHs::size_type l=0; l!=left.size(); l++)
|
||||
vs[i+l+right.size()] = left[left.size()-1-l];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void visibility_region_impl(const Face_const_handle f, const Point_2& q) const
|
||||
{
|
||||
vs.clear();
|
||||
polygon.clear();
|
||||
active_edges = std::set<EH, Closer_edge>(Closer_edge(geom_traits, q));
|
||||
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
|
||||
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
|
||||
|
||||
EHs relevant_edges; //edges that can affect the visibility of query point.
|
||||
Arrangement_2 bbox;
|
||||
if (is_face_query)
|
||||
input_face(f);
|
||||
else
|
||||
input_face(f, relevant_edges, bbox);
|
||||
//the following code is the initiation of vision ray.
|
||||
//the direction of the initial ray is between the direction from q to last
|
||||
//vertex in vs and positive x-axis. By choosing this direction, we make sure
|
||||
//that all plane is swept and there is not needle at the beginning of
|
||||
//sweeping.
|
||||
Vector_2 dir;
|
||||
if (Direction_2(-1, 0) < Direction_2(Vector_2(q, vs.back()->point())))
|
||||
dir = Vector_2(1, 0) + Vector_2(q, vs.back()->point());
|
||||
else
|
||||
dir = Vector_2(0, -1);
|
||||
Point_2 dp = q + dir;
|
||||
|
||||
//initiation of active_edges. for face queries,
|
||||
//all edges on the boundary can affect visibility.
|
||||
//for non-face queries, only relevant_edges has to be considered.
|
||||
if (is_face_query) {
|
||||
Ccb_halfedge_const_circulator curr = f->outer_ccb();
|
||||
Ccb_halfedge_const_circulator circ = curr;
|
||||
do {
|
||||
if (do_intersect_ray(
|
||||
q, dp, curr->target()->point(), curr->source()->point()))
|
||||
active_edges.insert(curr);
|
||||
|
||||
} while (++curr != circ);
|
||||
|
||||
typename Arrangement_2::Hole_const_iterator hi;
|
||||
for (hi = f->holes_begin(); hi != f->holes_end(); ++hi) {
|
||||
Ccb_halfedge_const_circulator curr = circ = *hi;
|
||||
do {
|
||||
if (do_intersect_ray(
|
||||
q, dp, curr->target()->point(), curr->source()->point()))
|
||||
active_edges.insert(curr);
|
||||
} while (++curr != circ);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (typename EHs::size_type i=0; i!=relevant_edges.size(); i++)
|
||||
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(),
|
||||
relevant_edges[i]->target()->point()))
|
||||
active_edges.insert(relevant_edges[i]);
|
||||
}
|
||||
|
||||
//angular sweep begins
|
||||
// std::cout<<active_edges.size()<<std::endl;
|
||||
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
|
||||
VH vh = vs[i];
|
||||
EH closest_e = *active_edges.begin();
|
||||
EHs& edges = incident_edges[vh];
|
||||
EHs insert_ehs, remove_ehs;
|
||||
for (typename EHs::size_type j=0; j!=edges.size(); j++) {
|
||||
EH& e = edges[j];
|
||||
if (active_edges.find(e) == active_edges.end())
|
||||
insert_ehs.push_back(e);
|
||||
else
|
||||
remove_ehs.push_back(e);
|
||||
}
|
||||
typename EHs::size_type insert_cnt = insert_ehs.size();
|
||||
typename EHs::size_type remove_cnt = remove_ehs.size();
|
||||
if (insert_cnt == 1 && remove_cnt == 1) {
|
||||
const EH& ctemp_eh = *active_edges.find(remove_ehs.front());
|
||||
EH& temp_eh = const_cast<EH&>(ctemp_eh);
|
||||
temp_eh = insert_ehs.front();
|
||||
}
|
||||
else {
|
||||
for (typename EHs::size_type j=0; j!=remove_cnt; j++)
|
||||
active_edges.erase(remove_ehs[j]);
|
||||
for (typename EHs::size_type j=0; j!=insert_cnt; j++)
|
||||
active_edges.insert(insert_ehs[j]);
|
||||
}
|
||||
|
||||
if (closest_e != *active_edges.begin()) {
|
||||
//when the closest edge changed
|
||||
if (is_face_query) {
|
||||
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||
//some edges are added and some are deleted,
|
||||
//which means the vertex swept is part of visibility polygon.
|
||||
update_visibility(vh->point());
|
||||
}
|
||||
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||
//only add some edges, means the view ray is blocked by new edges.
|
||||
//therefore first add the intersection of view ray and
|
||||
//former closet edge, then add the vertice swept.
|
||||
update_visibility(ray_seg_intersection(q,
|
||||
vh->point(),
|
||||
closest_e->target()->point(),
|
||||
closest_e->source()->point())
|
||||
);
|
||||
update_visibility(vh->point());
|
||||
}
|
||||
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||
//only delete some edges, means some block is moved and the view ray
|
||||
//can reach the segments after the block.
|
||||
update_visibility(vh->point());
|
||||
update_visibility(
|
||||
ray_seg_intersection(q,
|
||||
vh->point(),
|
||||
(*active_edges.begin())->target()->point(),
|
||||
(*active_edges.begin())->source()->point()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//extra work here for edge/vertex query is the index of cone_end1 and
|
||||
//cone_end2 will be recorded.
|
||||
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||
//some edges are added and some are deleted,
|
||||
//which means the vertice swept is part of visibility polygon.
|
||||
if (update_visibility(vh->point())) {
|
||||
if (vh == cone_end1)
|
||||
cone_end1_idx = polygon.size()-1;
|
||||
else if (vh == cone_end2)
|
||||
cone_end2_idx = polygon.size()-1;
|
||||
}
|
||||
}
|
||||
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||
//only add some edges, means the view ray is blocked by new edges.
|
||||
//therefore first add the intersection of view ray and former closet
|
||||
//edge, then add the vertice swept.
|
||||
update_visibility(ray_seg_intersection(q,
|
||||
vh->point(),
|
||||
closest_e->target()->point(),
|
||||
closest_e->source()->point())
|
||||
);
|
||||
if (update_visibility(vh->point())) {
|
||||
if (vh == cone_end1)
|
||||
cone_end1_idx = polygon.size()-1;
|
||||
else if (vh == cone_end2)
|
||||
cone_end2_idx = polygon.size()-1;
|
||||
}
|
||||
}
|
||||
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||
//only delete some edges, means some block is removed and the vision
|
||||
//ray can reach the segments after the block.
|
||||
if (update_visibility(vh->point())) {
|
||||
if (vh == cone_end1)
|
||||
cone_end1_idx = polygon.size()-1;
|
||||
else if (vh == cone_end2)
|
||||
cone_end2_idx = polygon.size()-1;
|
||||
}
|
||||
update_visibility(
|
||||
ray_seg_intersection(q,
|
||||
vh->point(),
|
||||
(*active_edges.begin())->target()->point(),
|
||||
(*active_edges.begin())->source()->point())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_edge(const EH e) const {
|
||||
std::cout << e->source()->point() <<"->"<< e->target()->point() <<std::endl;
|
||||
}
|
||||
|
||||
//compute the intersection of ray(q->dp) and segment(s, t)
|
||||
//if they are collinear then return the endpoint which is closer to q.
|
||||
|
||||
Point_2 ray_seg_intersection(
|
||||
const Point_2& q, const Point_2& dp, // the ray
|
||||
const Point_2& s, const Point_2& t) // the segment
|
||||
const
|
||||
{
|
||||
if (CGAL::collinear(q, dp, s)) {
|
||||
if (CGAL::collinear(q, dp, t)) {
|
||||
if (CGAL::compare_distance_to_point(q, s, t)==CGAL::SMALLER)
|
||||
return s;
|
||||
else
|
||||
return t;
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
Ray_2 ray(q,dp);
|
||||
Segment_2 seg(s,t);
|
||||
CGAL::Object result = CGAL::intersection(ray, seg);
|
||||
return *(CGAL::object_cast<Point_2>(&result));
|
||||
}
|
||||
|
||||
//check if p has been discovered before, if not update the visibility polygon
|
||||
bool update_visibility(const Point_2& p) const {
|
||||
if (polygon.empty()) {
|
||||
polygon.push_back(p);
|
||||
return true;
|
||||
}
|
||||
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p)
|
||||
!= EQUAL)
|
||||
{
|
||||
polygon.push_back(p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//functor to decide which vertex is swept earlier by the rotational sweeping
|
||||
//ray
|
||||
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
|
||||
const Point_2& q;
|
||||
const Geometry_traits_2* geom_traits;
|
||||
public:
|
||||
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits) :
|
||||
q(q), geom_traits(traits) {}
|
||||
|
||||
bool operator() (const VH v1, const VH v2) const {
|
||||
const Point_2& p1 = v1->point();
|
||||
const Point_2& p2 = v2->point();
|
||||
int qua1 = quadrant(q, p1);
|
||||
int qua2 = quadrant(q, p2);
|
||||
if (qua1 < qua2)
|
||||
return true;
|
||||
if (qua1 > qua2)
|
||||
return false;
|
||||
if (collinear(q, p1, p2))
|
||||
return (CGAL::compare_distance_to_point(q, p1, p2) == CGAL::SMALLER);
|
||||
else
|
||||
return CGAL::right_turn(p1, q, p2);
|
||||
}
|
||||
|
||||
//return the quadrant of p with respect to o.
|
||||
int quadrant(const Point_2& o, const Point_2& p) const {
|
||||
typename Geometry_traits_2::Compare_x_2 compare_x =
|
||||
geom_traits->compare_x_2_object();
|
||||
|
||||
typename Geometry_traits_2::Compare_y_2 compare_y =
|
||||
geom_traits->compare_y_2_object();
|
||||
|
||||
Comparison_result dx = compare_x(p, o);
|
||||
Comparison_result dy = compare_y(p, o);
|
||||
if (dx==LARGER && dy!=SMALLER)
|
||||
return 1;
|
||||
if (dx!=LARGER && dy==LARGER)
|
||||
return 2;
|
||||
if (dx==SMALLER && dy!=LARGER)
|
||||
return 3;
|
||||
if (dx!=SMALLER && dy==SMALLER)
|
||||
return 4;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//when the query point is in face, every edge is good.
|
||||
void input_neighbor_f( const Halfedge_const_handle e) const {
|
||||
VH v = e->target();
|
||||
if (!incident_edges.count(v))
|
||||
vs.push_back(v);
|
||||
incident_edges[v].push_back(e);
|
||||
incident_edges[v].push_back(e->next());
|
||||
}
|
||||
|
||||
//check if p is in the visibility cone
|
||||
bool is_in_cone(const Point_2& p) const{
|
||||
if (is_big_cone)
|
||||
return (!CGAL::right_turn(cone_end1->point(), q, p)) ||
|
||||
(!CGAL::left_turn(cone_end2->point(), q, p));
|
||||
else
|
||||
return (!CGAL::right_turn(cone_end1->point(), q, p)) &&
|
||||
(!CGAL::left_turn(cone_end2->point(), q, p));
|
||||
}
|
||||
|
||||
//for vertex and edge query: the visibility is limited in a cone.
|
||||
void input_edge(const Halfedge_const_handle e,
|
||||
EHs& good_edges) const {
|
||||
for (typename EHs::size_type i = 0; i < bad_edges.size(); i++)
|
||||
if (e == bad_edges[i])
|
||||
return;
|
||||
VH v1 = e->target();
|
||||
VH v2 = e->source();
|
||||
//an edge will affect visibility only if it has an endpoint in the
|
||||
//visibility cone or it crosses the boundary of the cone.
|
||||
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) ||
|
||||
do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point()))
|
||||
{
|
||||
good_edges.push_back(e);
|
||||
if (!incident_edges.count(v1))
|
||||
vs.push_back(v1);
|
||||
incident_edges[v1].push_back(e);
|
||||
if (!incident_edges.count(v2))
|
||||
vs.push_back(v2);
|
||||
incident_edges[v2].push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
//for face query: traverse the face to get all edges
|
||||
//and sort vertices in counter-clockwise order.
|
||||
void input_face (Face_const_handle fh) const
|
||||
{
|
||||
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||
Ccb_halfedge_const_circulator circ = curr;
|
||||
do {
|
||||
assert(curr->face() == fh);
|
||||
input_neighbor_f(curr);
|
||||
} while (++curr != circ);
|
||||
|
||||
typename Arrangement_2::Hole_const_iterator hi;
|
||||
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
|
||||
Ccb_halfedge_const_circulator curr = *hi, circ = *hi;
|
||||
do {
|
||||
assert(curr->face() == fh);
|
||||
input_neighbor_f(curr);
|
||||
} while (++curr != circ);
|
||||
}
|
||||
|
||||
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
|
||||
|
||||
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
|
||||
typename VHs::size_type j = i+1;
|
||||
while (j != vs.size()) {
|
||||
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
if (j-i>1)
|
||||
funnel(i, j);
|
||||
i = j-1;
|
||||
}
|
||||
}
|
||||
//for vertex or edge query: traverse the face to get all edges
|
||||
//and sort vertices in counter-clockwise order.
|
||||
void input_face (Face_const_handle fh,
|
||||
EHs& good_edges,
|
||||
Arrangement_2& bbox) const
|
||||
{
|
||||
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||
Ccb_halfedge_const_circulator circ = curr;
|
||||
do {
|
||||
assert(curr->face() == fh);
|
||||
input_edge(curr, good_edges);
|
||||
} while (++curr != circ);
|
||||
|
||||
typename Arrangement_2::Hole_const_iterator hi;
|
||||
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
|
||||
Ccb_halfedge_const_circulator curr = circ = *hi;
|
||||
do {
|
||||
assert(curr->face() == fh);
|
||||
input_edge(curr, good_edges);
|
||||
} while (++curr != circ);
|
||||
}
|
||||
|
||||
//create a box that cover all vertices such that during the sweeping,
|
||||
//the vision ray will always intersect at least an edge.
|
||||
//this box doesn't intersect any relevant_edge.
|
||||
Points points;
|
||||
for (typename VHs::size_type i=0; i<vs.size(); i++) {
|
||||
points.push_back(vs[i]->point());
|
||||
}
|
||||
points.push_back(q);
|
||||
//first get the bounding box of all relevant points.
|
||||
typename Geometry_traits_2::Iso_rectangle_2 bb =
|
||||
bounding_box(points.begin(), points.end());
|
||||
|
||||
Number_type xmin, xmax, ymin, ymax;
|
||||
typename Geometry_traits_2::Compute_x_2 compute_x =
|
||||
geom_traits->compute_x_2_object();
|
||||
|
||||
typename Geometry_traits_2::Compute_y_2 compute_y =
|
||||
geom_traits->compute_y_2_object();
|
||||
|
||||
//make the box a little bigger than bb so that it won't intersect any
|
||||
//relevant_edge.
|
||||
xmin = compute_x((bb.min)())-1;
|
||||
ymin = compute_y((bb.min)())-1;
|
||||
xmax = compute_x((bb.max)())+1;
|
||||
ymax = compute_y((bb.max)())+1;
|
||||
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
|
||||
Point_2(xmax, ymax), Point_2(xmin, ymax)};
|
||||
|
||||
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]),
|
||||
bbox.unbounded_face());
|
||||
|
||||
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]),
|
||||
e1->target());
|
||||
|
||||
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2],box[3]),
|
||||
e2->target());
|
||||
|
||||
bbox.insert_at_vertices(Segment_2(box[0], box[3]),
|
||||
e1->source(), e3->target());
|
||||
|
||||
circ = curr = e1->face()->outer_ccb();
|
||||
do {
|
||||
VH v = curr->target();
|
||||
vs.push_back(v);
|
||||
incident_edges[v].push_back(curr);
|
||||
incident_edges[v].push_back(curr->next());
|
||||
good_edges.push_back(curr);
|
||||
} while(++curr != circ);
|
||||
|
||||
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
|
||||
|
||||
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
|
||||
typename VHs::size_type j = i+1;
|
||||
while (j != vs.size()) {
|
||||
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
if (j-i>1)
|
||||
funnel(i, j);
|
||||
i = j-1;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // end namespace CGAL
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,685 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$`
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
// Ning Xu <longyin0904@gmail.com>
|
||||
|
||||
#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
|
||||
#define CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
|
||||
|
||||
#include <CGAL/tags.h>
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Visibility_2/visibility_utils.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Arr_walk_along_line_point_location.h>
|
||||
#include <CGAL/assertions.h>
|
||||
#include <stack>
|
||||
|
||||
// TODO:
|
||||
// * fix handle needles = O(nlogn)
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2_, class RegularizationCategory = CGAL::Tag_true>
|
||||
class Simple_polygon_visibility_2 {
|
||||
|
||||
public:
|
||||
typedef Arrangement_2_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Geometry_traits_2::Kernel K;
|
||||
|
||||
typedef typename K::Intersect_2 Intersect_2;
|
||||
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle
|
||||
Halfedge_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
|
||||
Halfedge_around_vertex_const_circulator;
|
||||
|
||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
typedef CGAL::Tag_false Supports_general_polygon_category;
|
||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||
|
||||
Simple_polygon_visibility_2() : p_arr(NULL), traits(NULL) {}
|
||||
|
||||
/*! Constructor given an arrangement and the Regularization tag. */
|
||||
Simple_polygon_visibility_2(const Arrangement_2& arr):
|
||||
p_arr(&arr) {
|
||||
traits = p_arr->geometry_traits();
|
||||
point_location.attach(arr);
|
||||
query_pt_is_vertex = false;
|
||||
query_pt_is_on_halfedge = false;
|
||||
inserted_artificial_starting_vertex = false;
|
||||
}
|
||||
|
||||
|
||||
std::string name() const { return std::string("S_visibility_2"); }
|
||||
|
||||
/*! Method to check if the visibility object is attached or not to
|
||||
an arrangement*/
|
||||
bool is_attached() const {
|
||||
return (p_arr != NULL);
|
||||
}
|
||||
|
||||
/*! Attaches the visibility object to the 'arr' arrangement */
|
||||
void attach(const Arrangement_2& arr) {
|
||||
if(p_arr != &arr){
|
||||
detach();
|
||||
p_arr = &arr;
|
||||
traits = p_arr->geometry_traits();
|
||||
point_location.attach(arr);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Detaches the visibility object from the arrangement it is
|
||||
attached to*/
|
||||
void detach() {
|
||||
point_location.detach();
|
||||
p_arr = NULL;
|
||||
traits = NULL;
|
||||
vertices.clear();
|
||||
query_pt_is_vertex = false;
|
||||
query_pt_is_on_halfedge = false;
|
||||
inserted_artificial_starting_vertex = false;
|
||||
}
|
||||
|
||||
/*! Getter method for the input arrangement*/
|
||||
const Arrangement_2& arrangement_2() const {
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
/*! Computes the visibility object from the query point 'q' in the face
|
||||
'face' and constructs the output in 'out_arr'*/
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(const Point_2& q,
|
||||
const Face_const_handle face,
|
||||
VARR& out_arr) const
|
||||
{
|
||||
|
||||
CGAL_precondition(!face->is_unbounded());
|
||||
|
||||
out_arr.clear();
|
||||
|
||||
query_pt_is_vertex = false;
|
||||
query_pt_is_on_halfedge = false;
|
||||
inserted_artificial_starting_vertex = false;
|
||||
|
||||
// Now retrieve the circulator to first visible vertex from triangulation
|
||||
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
|
||||
Ccb_halfedge_const_circulator curr = circ;
|
||||
|
||||
do {
|
||||
vertices.push_back(curr->source()->point());
|
||||
} while(++curr != circ);
|
||||
|
||||
vertices.push_back(vertices[0]);
|
||||
|
||||
visibility_region_impl(q);
|
||||
|
||||
return output(q, out_arr);
|
||||
}
|
||||
|
||||
/*! Computes the visibility region of the query point 'q' located on the
|
||||
halfedge 'he' and constructs the output in 'out_arr'*/
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(
|
||||
const Point_2& q,
|
||||
const Halfedge_const_handle he,
|
||||
VARR& out_arr ) const
|
||||
{
|
||||
|
||||
out_arr.clear();
|
||||
|
||||
query_pt_is_vertex = false;
|
||||
query_pt_is_on_halfedge = false;
|
||||
bool query_on_target = false;
|
||||
|
||||
if (q != he->source()->point()) {
|
||||
if (q != he->target()->point()) {
|
||||
vertices.push_back(he->target()->point());
|
||||
query_pt_is_on_halfedge = true;
|
||||
}
|
||||
else {
|
||||
query_pt_is_vertex = true;
|
||||
query_on_target = true;
|
||||
}
|
||||
} else {
|
||||
vertices.push_back( he->target()->point() );
|
||||
query_pt_is_vertex = true;
|
||||
}
|
||||
|
||||
Ccb_halfedge_const_circulator circ = he;
|
||||
++circ;
|
||||
Ccb_halfedge_const_circulator curr = circ;
|
||||
|
||||
do {
|
||||
const Point_2& curr_vertex = curr->target()->point();
|
||||
vertices.push_back(curr_vertex);
|
||||
} while (++curr != circ);
|
||||
|
||||
if ( query_on_target ) {
|
||||
vertices.push_back( vertices[0] );
|
||||
}
|
||||
|
||||
visibility_region_impl(q);
|
||||
|
||||
return output(q, out_arr);
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
typedef Arr_walk_along_line_point_location<Arrangement_2> Arr_point_location;
|
||||
typedef typename Arr_point_location::result_type Location_result;
|
||||
|
||||
typedef std::vector<Point_2> Vertex_container;
|
||||
typedef typename Vertex_container::size_type Size_type;
|
||||
|
||||
const Arrangement_2 *p_arr;
|
||||
const Geometry_traits_2 *traits;
|
||||
|
||||
mutable Arr_point_location point_location;
|
||||
|
||||
/*! Stack of visibile points; manipulated when going through the sequence
|
||||
of input vertices; contains the vertices of the visibility region after
|
||||
the run of the algorithm*/
|
||||
mutable std::stack<Point_2> stack;
|
||||
/*! Sequence of input vertices*/
|
||||
mutable Vertex_container vertices;
|
||||
/*! State of visibility region algorithm*/
|
||||
mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
|
||||
mutable bool query_pt_is_vertex;
|
||||
mutable bool query_pt_is_on_halfedge;
|
||||
mutable bool inserted_artificial_starting_vertex;
|
||||
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
output(const Point_2& q, VARR& out_arr) const {
|
||||
|
||||
if(inserted_artificial_starting_vertex)
|
||||
stack.pop();
|
||||
|
||||
std::vector<Point_2> points;
|
||||
while(!stack.empty()) {
|
||||
const Point_2& top = stack.top();
|
||||
if (top != q || query_pt_is_vertex) {
|
||||
points.push_back(top);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
if(inserted_artificial_starting_vertex) {
|
||||
points.back() = points[0];
|
||||
inserted_artificial_starting_vertex = false;
|
||||
}
|
||||
|
||||
|
||||
// Quick fix for now. Can be done faster
|
||||
bool is_degenerate = false;
|
||||
|
||||
for(typename std::vector<Point_2>::size_type i = 0; i < points.size()-2;i++){
|
||||
if(CGAL::orientation(points[i],points[i+1],points[i+2]) == CGAL::COLLINEAR){
|
||||
is_degenerate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(is_degenerate){
|
||||
//std::cout << is_degenerate << std::endl;
|
||||
std::vector<Segment_2> segments;
|
||||
|
||||
for(typename std::vector<Point_2>::size_type i = 0;i < points.size() - 1; ++i)
|
||||
{
|
||||
segments.push_back(Segment_2(points[i], points[i+1]));
|
||||
}
|
||||
CGAL::insert(out_arr, segments.begin(), segments.end());
|
||||
}else{
|
||||
points.pop_back();
|
||||
//std::cout << " ordanary " << std::endl;
|
||||
typename VARR::Vertex_handle v_last, v_first;
|
||||
v_last = v_first =
|
||||
out_arr.insert_in_face_interior(points[0],out_arr.unbounded_face());
|
||||
|
||||
for(unsigned int i = 0; i < points.size()-1; i++){
|
||||
if(points[i] < points[(i+1)]){
|
||||
v_last = out_arr.insert_from_left_vertex (
|
||||
Segment_2(points[i], points[i+1]), v_last
|
||||
)->target();
|
||||
} else {
|
||||
v_last = out_arr.insert_from_right_vertex(
|
||||
Segment_2(points[i], points[i+1]), v_last
|
||||
)->target();
|
||||
}
|
||||
}
|
||||
out_arr.insert_at_vertices(
|
||||
Segment_2(points.front(), points.back()),
|
||||
v_last, v_first
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
CGAL_postcondition(out_arr.number_of_isolated_vertices() == 0);
|
||||
CGAL_postcondition(stack.empty());
|
||||
|
||||
Visibility_2::conditional_regularize(out_arr, Regularization_category());
|
||||
vertices.clear();
|
||||
|
||||
if (out_arr.faces_begin()->is_unbounded()) {
|
||||
return ++out_arr.faces_begin();
|
||||
}
|
||||
else {
|
||||
return out_arr.faces_begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Finds a visible vertex from the query point 'q' in 'face'
|
||||
to start the algorithm from*/
|
||||
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face,
|
||||
const Point_2 &q) const
|
||||
{
|
||||
Location_result result = point_location.ray_shoot_up(q);
|
||||
|
||||
if(const Halfedge_const_handle* e =
|
||||
boost::get<Halfedge_const_handle>(&(result)))
|
||||
{
|
||||
CGAL_assertion((*e)->face() == face);
|
||||
Point_2 p(q.x(),
|
||||
traits->compute_y_at_x_2_object()(
|
||||
Line_2((*e)->source()->point(),
|
||||
(*e)->target()->point()) ,
|
||||
q.x()));
|
||||
|
||||
vertices.push_back(p);
|
||||
inserted_artificial_starting_vertex = true;
|
||||
|
||||
return (*e)->next()->ccb();
|
||||
}
|
||||
else if (const Vertex_const_handle* v =
|
||||
boost::get<Vertex_const_handle>(&(result)))
|
||||
{
|
||||
Halfedge_around_vertex_const_circulator cir =
|
||||
(*v)->incident_halfedges();
|
||||
|
||||
while(face != cir->face()) {
|
||||
++cir;
|
||||
}
|
||||
return cir->next()->ccb();
|
||||
}
|
||||
else
|
||||
{
|
||||
CGAL_assertion_msg(false, "Should not be reachable.");
|
||||
return Ccb_halfedge_const_circulator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Main method of the algorithm - initializes the stack and variables
|
||||
and calles the corresponding methods acc. to the algorithm's state;
|
||||
'q' - query point;
|
||||
'i' - current vertex' index
|
||||
'w' - endpoint of ray shot from query point */
|
||||
void visibility_region_impl(const Point_2& q) const {
|
||||
Size_type i = 0;
|
||||
Point_2 w;
|
||||
Orientation o = traits->orientation_2_object()(q, vertices[0], vertices[1]);
|
||||
|
||||
if ( o != RIGHT_TURN ) {
|
||||
upcase = LEFT;
|
||||
i = 1;
|
||||
w = vertices[1];
|
||||
stack.push(vertices[0]);
|
||||
stack.push(vertices[1]);
|
||||
}
|
||||
else {
|
||||
upcase = SCANA;
|
||||
i = 1;
|
||||
w = vertices[1];
|
||||
stack.push(vertices[0]);
|
||||
}
|
||||
|
||||
Ray_2 ray_origin( q, vertices[0] );
|
||||
do {
|
||||
switch(upcase) {
|
||||
case LEFT:
|
||||
left(i, w, q);
|
||||
break;
|
||||
case RIGHT:
|
||||
right(i, w, q);
|
||||
break;
|
||||
case SCANA:
|
||||
scana(i, w, q);
|
||||
break;
|
||||
case SCANB:
|
||||
scanb(i, w);
|
||||
break;
|
||||
case SCANC:
|
||||
scanc(i, w);
|
||||
break;
|
||||
case SCAND:
|
||||
scand(i, w);
|
||||
break;
|
||||
case FINISH:
|
||||
break;
|
||||
}
|
||||
if ( upcase == LEFT ) {
|
||||
Point_2 s_t = stack.top();
|
||||
stack.pop();
|
||||
if (traits->orientation_2_object()(q, vertices[0], stack.top() )
|
||||
== RIGHT_TURN
|
||||
&&
|
||||
traits->orientation_2_object()(q, vertices[0], s_t)
|
||||
== LEFT_TURN )
|
||||
{
|
||||
Segment_2 seg( stack.top(), s_t );
|
||||
if (Object_2 result = Intersect_2()(seg, ray_origin) )
|
||||
{
|
||||
const Point_2 * ipoint = object_cast<Point_2>(&result);
|
||||
assert( ipoint != NULL );
|
||||
s_t = *ipoint;
|
||||
upcase = SCANB;
|
||||
}
|
||||
}
|
||||
stack.push( s_t );
|
||||
}
|
||||
} while(upcase != FINISH);
|
||||
}
|
||||
|
||||
/*! Method that handles the left turns in the vertex algorithm */
|
||||
void left(Size_type& i, Point_2& w, const Point_2& q) const {
|
||||
if (i >= vertices.size() - 1) {
|
||||
upcase = FINISH;
|
||||
}
|
||||
else {
|
||||
Point_2 s_t = stack.top();
|
||||
stack.pop();
|
||||
Point_2 s_t_prev = stack.top();
|
||||
stack.push( s_t );
|
||||
Orientation orient1 = traits->orientation_2_object()(
|
||||
q,
|
||||
vertices[i],
|
||||
vertices[i+1] );
|
||||
|
||||
if ( orient1 != RIGHT_TURN ) {
|
||||
// Case L2
|
||||
upcase = LEFT;
|
||||
stack.push( vertices[i+1] );
|
||||
w = vertices[i+1];
|
||||
i++;
|
||||
} else {
|
||||
Orientation orient2 = traits->orientation_2_object()(
|
||||
s_t_prev,
|
||||
vertices[i],
|
||||
vertices[i+1] );
|
||||
|
||||
if ( orient2 == RIGHT_TURN ) {
|
||||
// Case L3
|
||||
upcase = SCANA;
|
||||
w = vertices[i+1];
|
||||
i++;
|
||||
} else {
|
||||
// Case L4
|
||||
upcase = RIGHT;
|
||||
w = vertices[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! Scans the stack such that all vertices that were pushed before to the
|
||||
stack and are now not visible anymore. */
|
||||
void right(Size_type& i, Point_2& w, const Point_2& q) const {
|
||||
Point_2 s_j;
|
||||
Point_2 s_j_prev;
|
||||
Point_2 u;
|
||||
int mode = 0;
|
||||
Orientation orient1, orient2;
|
||||
|
||||
s_j_prev = stack.top();
|
||||
orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i] );
|
||||
|
||||
while ( stack.size() > 1 ) {
|
||||
s_j = s_j_prev;
|
||||
orient1 = orient2;
|
||||
stack.pop();
|
||||
s_j_prev = stack.top();
|
||||
|
||||
orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i]);
|
||||
if ( orient1 != LEFT_TURN && orient2 != RIGHT_TURN ) {
|
||||
mode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
Segment_2 seg2( vertices[i-1], vertices[i] );
|
||||
Segment_2 seg( s_j_prev, s_j );
|
||||
if ( vertices[i-1] != s_j )
|
||||
{
|
||||
Object_2 result = Intersect_2()( seg, seg2 );
|
||||
if(result) {
|
||||
const Point_2 * ipoint = object_cast<Point_2>(&result);
|
||||
assert( ipoint != NULL );
|
||||
u = *ipoint;
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( mode != 0 );
|
||||
if ( mode == 1 ) {
|
||||
orient1 = traits->orientation_2_object()(q, vertices[i], vertices[i+1] );
|
||||
|
||||
orient2 = traits->orientation_2_object()(vertices[i-1],
|
||||
vertices[i],
|
||||
vertices[i+1] );
|
||||
|
||||
if ( orient1 == RIGHT_TURN ) {
|
||||
// Case R1
|
||||
// Since the next action is RIGHT, we do not compute the intersection
|
||||
// of (s_j,s_j_prev) and the ray (query_pt, vertices[i]),
|
||||
// thus, (s_j,s_j_prev) is not shortcutted, but it is harmless
|
||||
upcase = RIGHT;
|
||||
stack.push( s_j );
|
||||
w = vertices[i];
|
||||
i++;
|
||||
} else if ( orient2 == RIGHT_TURN ) {
|
||||
// Case R2
|
||||
Ray_2 ray( q, vertices[i] );
|
||||
Segment_2 seg( s_j_prev, s_j );
|
||||
|
||||
Object_2 result = Intersect_2()( seg, ray );
|
||||
const Point_2 * ipoint = object_cast<Point_2>(&result);
|
||||
|
||||
assert( ipoint != NULL );
|
||||
|
||||
u = *ipoint;
|
||||
if ( stack.top() != u ) {
|
||||
stack.push( u );
|
||||
}
|
||||
upcase = LEFT;
|
||||
stack.push( vertices[i] );
|
||||
stack.push( vertices[i+1] );
|
||||
w = vertices[i+1];
|
||||
i++;
|
||||
} else {
|
||||
// Case R3
|
||||
Ray_2 ray( q, vertices[i] );
|
||||
Segment_2 seg( s_j_prev, s_j );
|
||||
|
||||
Object_2 result = Intersect_2()( seg, ray );
|
||||
const Point_2 * ipoint = object_cast<Point_2>(&result);
|
||||
|
||||
assert( ipoint != NULL );
|
||||
|
||||
u = *ipoint;
|
||||
if ( stack.top() != u ) {
|
||||
stack.push( u );
|
||||
}
|
||||
upcase = SCANC;
|
||||
w = vertices[i];
|
||||
i++;
|
||||
}
|
||||
} else if ( mode == 2 ) {
|
||||
// Case R4
|
||||
upcase = SCAND;
|
||||
w = u;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Scans the vertices starting from index 'i' for the first visible vertex
|
||||
out of the back hidden window */
|
||||
void scana(Size_type& i, Point_2& w, const Point_2& q) const {
|
||||
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
|
||||
Point_2 u;
|
||||
Size_type k = scan_edges( i, q, stack.top(), u, true );
|
||||
|
||||
Orientation orient1 =
|
||||
traits->orientation_2_object()(q, vertices[k], vertices[k+1] );
|
||||
|
||||
if ( orient1 == RIGHT_TURN ) {
|
||||
bool fwd = traits->
|
||||
collinear_are_ordered_along_line_2_object()(q, stack.top(), u );
|
||||
|
||||
if ( !fwd ) {
|
||||
// Case A1
|
||||
upcase = RIGHT;
|
||||
i = k+1;
|
||||
w = u;
|
||||
} else {
|
||||
// Case A2
|
||||
upcase = SCAND;
|
||||
i = k+1;
|
||||
w = u;
|
||||
}
|
||||
} else {
|
||||
// Case A3
|
||||
upcase = LEFT;
|
||||
i = k+1;
|
||||
stack.push( u );
|
||||
if ( u != vertices[k+1] ) {
|
||||
stack.push( vertices[k+1] );
|
||||
}
|
||||
w = vertices[k+1];
|
||||
}
|
||||
}
|
||||
|
||||
/*! Find the first edge interecting the segment (v_0, s_t) */
|
||||
void scanb(Size_type& i, Point_2& w) const {
|
||||
if ( i == vertices.size() - 1 ) {
|
||||
upcase = FINISH;
|
||||
return;
|
||||
}
|
||||
Point_2 u;
|
||||
Size_type k = scan_edges( i, stack.top(), vertices[0], u, false );
|
||||
if ( (k+1 == vertices.size()-1) && (vertices[0] == u) ) {
|
||||
// Case B1
|
||||
upcase = FINISH;
|
||||
stack.push( vertices[0] );
|
||||
} else {
|
||||
// Case B2
|
||||
upcase = RIGHT;
|
||||
i = k+1;
|
||||
w = u;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Finds the exit from a general front hidden window by finding the first
|
||||
vertex to the right of the ray defined by the query_point and w*/
|
||||
void scanc(Size_type& i, Point_2& w) const {
|
||||
Point_2 u;
|
||||
Size_type k = scan_edges( i, stack.top(), w, u, false );
|
||||
upcase = RIGHT;
|
||||
i = k+1;
|
||||
w = u;
|
||||
}
|
||||
|
||||
/*! find the first edge intersecting the given window (s_t, w) */
|
||||
void scand(Size_type& i, Point_2& w) const {
|
||||
Point_2 u;
|
||||
Size_type k = scan_edges( i, stack.top(), w, u, false );
|
||||
upcase = LEFT;
|
||||
i = k+1;
|
||||
stack.push( u );
|
||||
if ( u != vertices[k+1] ) {
|
||||
stack.push( vertices[k+1] );
|
||||
}
|
||||
w = vertices[k+1];
|
||||
}
|
||||
|
||||
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
|
||||
or given segment. is_ray = true -> ray, false -> segment.
|
||||
The intersection point is returned by u */
|
||||
Size_type scan_edges( Size_type i,
|
||||
const Point_2& ray_begin,
|
||||
const Point_2& ray_end,
|
||||
Point_2& u,
|
||||
bool is_ray ) const
|
||||
{
|
||||
Orientation old_orient = RIGHT_TURN;
|
||||
Ray_2 ray( ray_begin, ray_end );
|
||||
Segment_2 s2( ray_begin, ray_end );
|
||||
Size_type k;
|
||||
Object_2 result;
|
||||
for ( k = i; k+1 < vertices.size(); k++ ) {
|
||||
Orientation curr_orient = traits->orientation_2_object()(
|
||||
ray_begin,
|
||||
ray_end,
|
||||
vertices[k+1] );
|
||||
if ( curr_orient != old_orient ) {
|
||||
// Orientation switch, an intersection may occur
|
||||
Segment_2 seg( vertices[k], vertices[k+1] );
|
||||
if ( is_ray ) {
|
||||
result = Intersect_2()( seg, ray );
|
||||
if(result)
|
||||
break;
|
||||
} else {
|
||||
result = Intersect_2()( seg, s2 );
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
old_orient = curr_orient;
|
||||
}
|
||||
assert( k+1<vertices.size() );
|
||||
const Point_2 * ipoint = object_cast<Point_2>( &result );
|
||||
if ( ipoint ) {
|
||||
u = *ipoint;
|
||||
} else {
|
||||
u = vertices[k+1];
|
||||
}
|
||||
return k;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
#endif
|
||||
|
|
@ -0,0 +1,710 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Michael Hemmer <michael.hemmer@cgal.org>
|
||||
//
|
||||
|
||||
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Arr_observer.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2_ , class RegularizationCategory = CGAL::Tag_true >
|
||||
class Triangular_expansion_visibility_2 {
|
||||
typedef typename Arrangement_2_::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Geometry_traits_2::Kernel K;
|
||||
|
||||
typedef Triangular_expansion_visibility_2<
|
||||
Arrangement_2_, RegularizationCategory> Self;
|
||||
|
||||
public:
|
||||
typedef Arrangement_2_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||
typedef typename Arrangement_2::Halfedge Halfedge;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_circulator
|
||||
Ccb_halfedge_circulator;
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
|
||||
typedef typename K::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||
typedef typename Geometry_traits_2::FT Number_type;
|
||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||
|
||||
typedef RegularizationCategory Regularization_category;
|
||||
|
||||
typedef CGAL::Tag_true Supports_general_polygon_category;
|
||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||
|
||||
private:
|
||||
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
||||
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
|
||||
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||
typedef CGAL::No_intersection_tag Itag;
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT;
|
||||
|
||||
typedef std::pair<Point_2,Point_2> Constraint;
|
||||
|
||||
// Functor to create edge constraints for the CDT out of Halfedges
|
||||
struct Make_constraint
|
||||
{
|
||||
typedef Constraint result_type;
|
||||
|
||||
Constraint operator()(const Halfedge& edge) const {
|
||||
return std::make_pair(edge.source()->point(),
|
||||
edge.target()->point());
|
||||
}
|
||||
};
|
||||
|
||||
// Observer to track any changes of the attached arrangement.
|
||||
class Observer : public Arr_observer<Arrangement_2>
|
||||
{
|
||||
|
||||
typedef Arr_observer<Arrangement_2> Base;
|
||||
typedef Observer Self;
|
||||
|
||||
|
||||
public:
|
||||
bool has_changed;
|
||||
|
||||
Observer() : Base(), has_changed(false)
|
||||
{}
|
||||
|
||||
Observer(const Arrangement_2& arr)
|
||||
: Base(const_cast<Arrangement_2&>(arr)), has_changed(false)
|
||||
{}
|
||||
|
||||
// Arr_observer interface
|
||||
|
||||
void after_attach() { has_changed = false; }
|
||||
|
||||
|
||||
void after_global_change() { has_changed = true; }
|
||||
void after_create_vertex(Vertex_handle) { has_changed = true; }
|
||||
void after_create_boundary_vertex(Vertex_handle) { has_changed = true; }
|
||||
void after_create_edge(Halfedge_handle) { has_changed = true; }
|
||||
void after_modify_vertex(Vertex_handle) { has_changed = true; }
|
||||
void after_modify_edge(Halfedge_handle) { has_changed = true; }
|
||||
void after_split_edge(Halfedge_handle, Halfedge_handle) {
|
||||
has_changed = true; }
|
||||
void after_split_fictitious_edge(Halfedge_handle, Halfedge_handle) {
|
||||
has_changed = true; }
|
||||
void after_split_face(Face_handle, Face_handle, bool) {
|
||||
has_changed = true; }
|
||||
void after_split_outer_ccb(Face_handle, Ccb_halfedge_circulator,
|
||||
Ccb_halfedge_circulator) {
|
||||
has_changed = true; }
|
||||
void after_split_inner_ccb(Face_handle, Ccb_halfedge_circulator,
|
||||
Ccb_halfedge_circulator) {
|
||||
has_changed = true; }
|
||||
void after_add_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||
void after_add_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||
void after_add_isolated_vertex(Vertex_handle) { has_changed = true; }
|
||||
void after_merge_edge(Halfedge_handle) { has_changed = true; }
|
||||
void after_merge_fictitious_edge(Halfedge_handle) { has_changed = true; }
|
||||
void after_merge_face(Face_handle) { has_changed = true; }
|
||||
void after_merge_outer_ccb(Face_handle, Ccb_halfedge_circulator) {
|
||||
has_changed = true; }
|
||||
void after_merge_inner_ccb(Face_handle, Ccb_halfedge_circulator) {
|
||||
has_changed = true; }
|
||||
void after_move_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||
void after_move_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||
void after_move_isolated_vertex(Vertex_handle) { has_changed = true; }
|
||||
void after_remove_vertex() { has_changed = true; }
|
||||
void after_remove_edge() { has_changed = true; }
|
||||
void after_remove_outer_ccb(Face_handle) { has_changed = true; }
|
||||
void after_remove_inner_ccb(Face_handle) { has_changed = true; }
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
const Arrangement_2* p_arr;
|
||||
|
||||
// May change during visibility computation
|
||||
mutable Observer observer;
|
||||
mutable boost::shared_ptr<CDT> p_cdt;
|
||||
mutable std::vector<Segment_2> needles;
|
||||
|
||||
// Copy constructor and assignment not supported
|
||||
Triangular_expansion_visibility_2(const Self&);
|
||||
Self& operator= (const Self& );
|
||||
|
||||
|
||||
public:
|
||||
Triangular_expansion_visibility_2() : p_arr(NULL){}
|
||||
|
||||
/*! Constructor given an arrangement. */
|
||||
Triangular_expansion_visibility_2 (const Arrangement_2& arr)
|
||||
: p_arr(&arr), observer(arr)
|
||||
{
|
||||
init_cdt();
|
||||
}
|
||||
|
||||
const std::string name() const { return std::string("T_visibility_2"); }
|
||||
|
||||
|
||||
bool is_attached() const {
|
||||
//std::cout << "is_attached" << std::endl;
|
||||
return (p_arr != NULL);
|
||||
}
|
||||
|
||||
void attach(const Arrangement_2& arr) {
|
||||
if(p_arr != &arr){
|
||||
p_arr = &arr;
|
||||
observer.detach();
|
||||
observer.attach(const_cast<Arrangement_2&>(arr));
|
||||
init_cdt();
|
||||
}
|
||||
//std::cout << "attach done" << std::endl;
|
||||
}
|
||||
|
||||
void detach() {
|
||||
//std::cout << "detach" << std::endl;
|
||||
observer.detach();
|
||||
p_arr = NULL;
|
||||
p_cdt.reset();
|
||||
}
|
||||
|
||||
const Arrangement_2& arrangement_2() const {
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(const Point_2& q,
|
||||
const Face_const_handle face,
|
||||
VARR& out_arr )
|
||||
const {
|
||||
//std::cout << "query in face interior" << std::endl;
|
||||
|
||||
if(observer.has_changed) {
|
||||
init_cdt();
|
||||
}
|
||||
|
||||
out_arr.clear();
|
||||
needles.clear();
|
||||
assert(!face->is_unbounded());
|
||||
|
||||
|
||||
std::vector<Point_2> raw_output;
|
||||
typename CDT::Face_handle fh = p_cdt->locate(q);
|
||||
|
||||
raw_output.push_back(fh->vertex(1)->point());
|
||||
if(!p_cdt->is_constrained(get_edge(fh,0))){
|
||||
//std::cout<< "edge 0 is not constrained" << std::endl;
|
||||
expand_edge(
|
||||
q,
|
||||
fh->vertex(2)->point(),
|
||||
fh->vertex(1)->point(),
|
||||
fh,0,std::back_inserter(raw_output));
|
||||
}
|
||||
|
||||
raw_output.push_back(fh->vertex(2)->point());
|
||||
if(!p_cdt->is_constrained(get_edge(fh,1))){
|
||||
//std::cout << "edge 1 is not constrained" << std::endl;
|
||||
expand_edge(
|
||||
q,
|
||||
fh->vertex(0)->point(),
|
||||
fh->vertex(2)->point(),
|
||||
fh,1,std::back_inserter(raw_output));
|
||||
}
|
||||
|
||||
raw_output.push_back(fh->vertex(0)->point());
|
||||
if(!p_cdt->is_constrained(get_edge(fh,2))){
|
||||
//std::cout << "edge 2 is not constrained" << std::endl;
|
||||
expand_edge(
|
||||
q,
|
||||
fh->vertex(1)->point(),
|
||||
fh->vertex(0)->point(),
|
||||
fh,2,std::back_inserter(raw_output));
|
||||
}
|
||||
|
||||
|
||||
return output(raw_output,out_arr);
|
||||
}
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
compute_visibility(const Point_2& q,
|
||||
const Halfedge_const_handle he,
|
||||
VARR& out_arr)
|
||||
const {
|
||||
//std::cout << "visibility_region he" << std::endl;
|
||||
|
||||
if(observer.has_changed) {
|
||||
init_cdt();
|
||||
}
|
||||
|
||||
assert(!he->face()->is_unbounded());
|
||||
out_arr.clear();
|
||||
needles.clear();
|
||||
|
||||
std::vector<Point_2> raw_output;
|
||||
typename CDT::Locate_type location;
|
||||
int index;
|
||||
typename CDT::Face_handle fh = p_cdt->locate(q,location,index);
|
||||
assert(location == CDT::EDGE || location == CDT::VERTEX);
|
||||
//the following code tries to figure out which triangle one should start in.
|
||||
|
||||
|
||||
if(location == CDT::EDGE){
|
||||
//std::cout << "query on edge" << std::endl;
|
||||
// this is the easy part, there are only two possible faces
|
||||
// index indicates the edge = vertex on the other side of the edge
|
||||
// the next vertex in cw order should be the target of given edge
|
||||
if(fh->vertex(p_cdt->cw(index))->point() != he->target()->point()){
|
||||
//std::cout << "need to swap face" << std::endl;
|
||||
// take face on the other side if this is not the case
|
||||
typename CDT::Face_handle nfh = fh->neighbor(index);
|
||||
index = nfh->index(fh);
|
||||
fh = nfh;
|
||||
}
|
||||
assert(fh->vertex(p_cdt->cw(index))->point() == he->target()->point());
|
||||
assert(!p_cdt->is_infinite(fh->vertex(index)));
|
||||
|
||||
|
||||
// output the edge the query lies on
|
||||
raw_output.push_back(he->source()->point());
|
||||
raw_output.push_back(he->target()->point());
|
||||
|
||||
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->ccw(index)))){
|
||||
expand_edge(
|
||||
q,
|
||||
fh->vertex(index)->point(), //left
|
||||
he->target()->point() , //right
|
||||
fh,
|
||||
p_cdt->ccw(index),
|
||||
std::back_inserter(raw_output));
|
||||
}
|
||||
raw_output.push_back(fh->vertex(index)->point());
|
||||
|
||||
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index)))){
|
||||
expand_edge(
|
||||
q,
|
||||
he->source()->point() , //left
|
||||
fh->vertex(index)->point(), //right
|
||||
fh,
|
||||
p_cdt->cw(index),
|
||||
std::back_inserter(raw_output));
|
||||
}
|
||||
}
|
||||
|
||||
if(location == CDT::VERTEX){
|
||||
//std::cout << "query on vertex" << std::endl;
|
||||
|
||||
//bool query_point_on_vertex_is_not_working_yet = false;
|
||||
//assert(query_point_on_vertex_is_not_working_yet);
|
||||
|
||||
assert(q == he->target()->point());
|
||||
assert(fh->vertex(index)->point() == he->target()->point());
|
||||
|
||||
// push points that are seen anyway
|
||||
// raw_output.push_back(he->source()->point()); inserted last
|
||||
raw_output.push_back(he->target()->point());
|
||||
raw_output.push_back(he->next()->target()->point());
|
||||
|
||||
// now start in the triangle that contains he->next()
|
||||
while(
|
||||
p_cdt->is_infinite(fh->vertex(p_cdt->ccw(index))) ||
|
||||
he->next()->target()->point() !=
|
||||
fh->vertex(p_cdt->ccw(index))->point()
|
||||
)
|
||||
{
|
||||
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||
int nindex = nfh->index(fh);
|
||||
index = p_cdt->ccw(nindex);
|
||||
fh = nfh;
|
||||
assert(he->target()->point() == fh->vertex(index)->point());
|
||||
}
|
||||
|
||||
|
||||
assert(he->next()->source()->point() == fh->vertex(index)->point());
|
||||
assert(he->next()->target()->point() ==
|
||||
fh->vertex(p_cdt->ccw(index))->point());
|
||||
assert(!p_cdt->is_infinite(fh));
|
||||
assert(p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index))));
|
||||
|
||||
while(he->source()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
||||
|
||||
if(!p_cdt->is_constrained(get_edge(fh,index))){
|
||||
expand_edge(
|
||||
q,
|
||||
fh->vertex(p_cdt-> cw(index))->point(), //left
|
||||
fh->vertex(p_cdt->ccw(index))->point(), //right
|
||||
fh,
|
||||
index,
|
||||
std::back_inserter(raw_output));
|
||||
}
|
||||
// push left end point of edge into output
|
||||
raw_output.push_back(fh->vertex(p_cdt-> cw(index))->point());
|
||||
|
||||
// take the next triangle around q in ccw order
|
||||
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||
int nindex = nfh->index(fh);
|
||||
index = p_cdt->ccw(nindex);
|
||||
fh = nfh;
|
||||
assert(fh->vertex(index)->point() == he->target()->point());
|
||||
}
|
||||
}
|
||||
return output(raw_output,out_arr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i) const {
|
||||
return std::make_pair(fh,i);
|
||||
}
|
||||
|
||||
Point_2 ray_seg_intersection(
|
||||
const Point_2& q, const Point_2& b, // the ray
|
||||
const Point_2& s, const Point_2& t // the segment
|
||||
) const {
|
||||
|
||||
Ray_2 ray(q,b);
|
||||
Segment_2 seg(s,t);
|
||||
assert(typename K::Do_intersect_2()(ray,seg));
|
||||
CGAL::Object obj = typename K::Intersect_2()(ray,seg);
|
||||
Point_2 result = object_cast<Point_2>(obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
void collect_needle(
|
||||
const Point_2& q,
|
||||
const typename CDT::Vertex_handle vh,
|
||||
const typename CDT::Face_handle fh,
|
||||
int index)
|
||||
const {
|
||||
|
||||
// the expanded edge should not be constrained
|
||||
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||
assert(!p_cdt->is_infinite(fh));
|
||||
// go into the new face
|
||||
const typename CDT::Face_handle nfh(fh->neighbor(index));
|
||||
assert(!p_cdt->is_infinite(nfh));
|
||||
|
||||
// get indices of neighbors
|
||||
int nindex = nfh->index(fh); // index of new vertex and old face
|
||||
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
|
||||
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
|
||||
|
||||
// get vertices seen from entering edge
|
||||
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
|
||||
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
|
||||
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
|
||||
assert(!p_cdt->is_infinite(nvh));
|
||||
assert(!p_cdt->is_infinite(lvh));
|
||||
assert(!p_cdt->is_infinite(rvh));
|
||||
|
||||
// get edges seen from entering edge
|
||||
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
|
||||
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
|
||||
|
||||
// do orientation computation once for new vertex
|
||||
typename K::Orientation_2 orientation =
|
||||
p_cdt->geom_traits().orientation_2_object();
|
||||
CGAL::Orientation orient = orientation(q,vh->point(),nvh->point());
|
||||
|
||||
|
||||
//std::cout << "\n collect_needle" <<std::endl;
|
||||
//std::cout << "q "<< q << std::endl ;
|
||||
//std::cout << "vh->point() "<< vh->point() << std::endl;
|
||||
//std::cout << "lvh->point() "<< lvh->point() << std::endl ;
|
||||
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
|
||||
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
||||
|
||||
|
||||
switch ( orient ) {
|
||||
case CGAL::COUNTERCLOCKWISE:
|
||||
// looking on to the right edge
|
||||
if(p_cdt->is_constrained(re)) {
|
||||
if(vh != rvh) {
|
||||
Point_2 p = ray_seg_intersection(q, vh->point(),
|
||||
nvh->point(), rvh->point());
|
||||
//std::cout << vh->point() <<" -1- "<< p <<std::endl;
|
||||
needles.push_back(Segment_2(vh->point(),p));
|
||||
}
|
||||
} else {
|
||||
collect_needle(q,vh,nfh,rindex);
|
||||
}
|
||||
break;
|
||||
case CGAL::CLOCKWISE:
|
||||
// looking on to the left edge
|
||||
if(p_cdt->is_constrained(le)){
|
||||
if(vh != lvh){
|
||||
Point_2 p = ray_seg_intersection(q, vh->point(),
|
||||
nvh->point(), lvh->point());
|
||||
//std::cout << vh->point() <<" -2- "<< p <<std::endl;
|
||||
needles.push_back(Segment_2(vh->point(),p));
|
||||
}
|
||||
} else {
|
||||
collect_needle(q,vh,nfh,lindex);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(orient == CGAL::COLLINEAR);
|
||||
// looking on nvh, so it must be reported
|
||||
// if it wasn't already (triangles rotate around vh)
|
||||
if(vh != nvh){
|
||||
//std::cout << vh->point() <<" -3- "<< nvh->point() <<std::endl;
|
||||
needles.push_back(Segment_2(vh->point(),nvh->point()));
|
||||
}
|
||||
// but we may also contiue looking along the vertex
|
||||
if(!p_cdt->is_constrained(re)) {
|
||||
collect_needle(q,nvh,nfh,rindex);
|
||||
}
|
||||
if(!p_cdt->is_constrained(le)) {
|
||||
collect_needle(q,nvh,nfh,lindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class OIT>
|
||||
OIT expand_edge(
|
||||
const Point_2& q,
|
||||
const Point_2& left,
|
||||
const Point_2& right,
|
||||
typename CDT::Face_handle fh,
|
||||
int index,
|
||||
OIT oit)
|
||||
const {
|
||||
|
||||
// the expanded edge should not be constrained
|
||||
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||
assert(!p_cdt->is_infinite(fh));
|
||||
|
||||
// go into the new face
|
||||
const typename CDT::Face_handle nfh(fh->neighbor(index));
|
||||
assert(!p_cdt->is_infinite(nfh));
|
||||
|
||||
// get indices of neighbors
|
||||
int nindex = nfh->index(fh); // index of new vertex and old face
|
||||
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
|
||||
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
|
||||
|
||||
// get vertices seen from entering edge
|
||||
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
|
||||
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
|
||||
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
|
||||
assert(!p_cdt->is_infinite(nvh));
|
||||
assert(!p_cdt->is_infinite(lvh));
|
||||
assert(!p_cdt->is_infinite(rvh));
|
||||
|
||||
// get edges seen from entering edge
|
||||
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
|
||||
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
|
||||
|
||||
// do orientation computation once for new vertex
|
||||
typename K::Orientation_2 orientation =
|
||||
p_cdt->geom_traits().orientation_2_object();
|
||||
CGAL::Orientation ro = orientation(q,right,nvh->point());
|
||||
CGAL::Orientation lo = orientation(q,left ,nvh->point());
|
||||
|
||||
assert(typename K::Orientation_2()(q,left ,lvh->point())
|
||||
!= CGAL::CLOCKWISE);
|
||||
assert(typename K::Orientation_2()(q,right,rvh->point())
|
||||
!= CGAL::COUNTERCLOCKWISE);
|
||||
|
||||
//std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " <<
|
||||
//(lo == CGAL::CLOCKWISE) << std::endl;
|
||||
|
||||
//right edge is seen if new vertex is counter clockwise of right boarder
|
||||
if(ro == CGAL::COUNTERCLOCKWISE){
|
||||
if(p_cdt->is_constrained(re)){
|
||||
// the edge is constrained
|
||||
// report intersection with right boarder ray
|
||||
// if it is not already the right vertex (already reported)
|
||||
if(right != rvh->point()){
|
||||
*oit++ = ray_seg_intersection(q,right,nvh->point(),rvh->point());
|
||||
}
|
||||
|
||||
// then report intersection with left boarder if it exists
|
||||
if(lo == CGAL::COUNTERCLOCKWISE){
|
||||
*oit++ = ray_seg_intersection(q,left,nvh->point(),rvh->point());
|
||||
}
|
||||
}else{
|
||||
// the edge is not a constrained
|
||||
if(lo == CGAL::COUNTERCLOCKWISE){
|
||||
// no split needed and return
|
||||
//std::cout<< "h1"<< std::endl;
|
||||
oit = expand_edge(q,left,right,nfh,rindex,oit);
|
||||
//std::cout<< "h1 done"<< std::endl;
|
||||
return oit;
|
||||
}else{
|
||||
// spliting at new vertex
|
||||
//std::cout<< "h2"<< std::endl;
|
||||
*oit++ = expand_edge(q,nvh->point(),right,nfh,rindex,oit);
|
||||
//std::cout<< "h2 done"<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "q "<< q << std::endl ;
|
||||
//std::cout << "lvh->point() "<< lvh->point() << std::endl;
|
||||
//std::cout << "left "<< left << std::endl ;
|
||||
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
|
||||
//std::cout << "right "<< right << std::endl ;
|
||||
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
||||
|
||||
|
||||
// determin whether new vertex needs to be reported
|
||||
if(ro != CGAL::CLOCKWISE && lo != CGAL::COUNTERCLOCKWISE){
|
||||
*oit++ = nvh->point();
|
||||
}
|
||||
if(!Regularization_category::value){
|
||||
assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR));
|
||||
// we have to check whether a needle starts here.
|
||||
if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re)
|
||||
&& ro == CGAL::COLLINEAR)
|
||||
collect_needle(q,nvh,nfh,rindex);
|
||||
|
||||
if(p_cdt->is_constrained(re) && !p_cdt->is_constrained(le)
|
||||
&& lo == CGAL::COLLINEAR)
|
||||
collect_needle(q,nvh,nfh,lindex);
|
||||
}
|
||||
|
||||
//left edge is seen if new vertex is clockwise of left boarder
|
||||
if(lo == CGAL::CLOCKWISE){
|
||||
if(p_cdt->is_constrained(le)){
|
||||
// the edge is constrained
|
||||
// report interesection with right boarder if exists
|
||||
if(ro == CGAL::CLOCKWISE){
|
||||
*oit++ = ray_seg_intersection(q,right,nvh->point(),lvh->point());
|
||||
}
|
||||
// then report intersection with left boarder ray
|
||||
// if it is not already the left vertex (already reported)
|
||||
if(left != lvh->point()){
|
||||
*oit++ = ray_seg_intersection(q,left,nvh->point(),lvh->point());
|
||||
}
|
||||
return oit;
|
||||
}else{
|
||||
// the edge is not a constrained
|
||||
if(ro == CGAL::CLOCKWISE){
|
||||
// no split needed and return
|
||||
//std::cout<< "h3"<< std::endl;
|
||||
oit = expand_edge(q,left,right,nfh,lindex,oit);
|
||||
//std::cout<< "h3 done"<< std::endl;
|
||||
return oit;
|
||||
}else{
|
||||
// spliting at new vertex
|
||||
//std::cout<< "h4"<< std::endl;
|
||||
oit = expand_edge(q,left,nvh->point(),nfh,lindex,oit);
|
||||
//std::cout<< "h4 done"<< std::endl;
|
||||
return oit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return oit;
|
||||
}
|
||||
|
||||
|
||||
template <typename VARR>
|
||||
typename VARR::Face_handle
|
||||
output(std::vector<Point_2>& raw_output, VARR& out_arr) const {
|
||||
|
||||
if(!needles.empty()){
|
||||
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
||||
for(unsigned int i = 0; i < raw_output.size(); i++){
|
||||
// //std::cout << raw_output[i] << " -- "
|
||||
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||
segments.push_back(Segment_2(raw_output[i],
|
||||
raw_output[(i+1) % raw_output.size()]));
|
||||
}
|
||||
|
||||
CGAL::insert_non_intersecting_curves(out_arr,
|
||||
segments.begin(),
|
||||
segments.end());
|
||||
|
||||
} else {
|
||||
typename VARR::Vertex_handle v_last, v_first;
|
||||
v_last = v_first =
|
||||
out_arr.insert_in_face_interior(raw_output[0],out_arr.unbounded_face());
|
||||
|
||||
for(unsigned int i = 0; i < raw_output.size()-1; i++){
|
||||
// std::cout << raw_output[i] << " -- "
|
||||
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||
if(raw_output[i] < raw_output[(i+1)]){
|
||||
v_last = out_arr.insert_from_left_vertex (
|
||||
Segment_2(raw_output[i], raw_output[i+1]), v_last
|
||||
)->target();
|
||||
} else {
|
||||
v_last = out_arr.insert_from_right_vertex(
|
||||
Segment_2(raw_output[i], raw_output[i+1]), v_last
|
||||
)->target();
|
||||
}
|
||||
}
|
||||
out_arr.insert_at_vertices(
|
||||
Segment_2(raw_output.front(), raw_output.back()),
|
||||
v_last, v_first
|
||||
);
|
||||
}
|
||||
|
||||
assert(out_arr.number_of_faces() == 2);
|
||||
|
||||
if(out_arr.faces_begin()->is_unbounded())
|
||||
return ++out_arr.faces_begin();
|
||||
else
|
||||
return out_arr.faces_begin();
|
||||
}
|
||||
|
||||
void init_cdt() const {
|
||||
//std::cout<< "==============" <<std::endl;
|
||||
//std::cout<< "Input Polygon:" <<std::endl;
|
||||
|
||||
typedef typename boost::transform_iterator<Make_constraint,
|
||||
Edge_const_iterator> Iter;
|
||||
|
||||
Iter begin = boost::make_transform_iterator(p_arr->edges_begin(),
|
||||
Make_constraint());
|
||||
|
||||
Iter end = boost::make_transform_iterator(p_arr->edges_end(),
|
||||
Make_constraint());
|
||||
|
||||
//std::cout << "init_cdt new CDT" << std::endl;
|
||||
p_cdt = boost::shared_ptr<CDT>(new CDT(begin, end));
|
||||
observer.has_changed = false;
|
||||
//std::cout << "init_cdt done" << std::endl;
|
||||
//std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||
|
|
@ -0,0 +1,435 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#ifndef CGAL_VISIBILITY_UTILS_H
|
||||
#define CGAL_VISIBILITY_UTILS_H
|
||||
|
||||
#include <vector>
|
||||
#include <CGAL/tags.h>
|
||||
#include <CGAL/enum.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Visibility_2 {
|
||||
|
||||
template <class Arrangement_2>
|
||||
int count_edges_in_face(typename Arrangement_2::Face_const_handle fch) {
|
||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
|
||||
Ccb_halfedge_const_circulator circ = fch->outer_ccb();
|
||||
Ccb_halfedge_const_circulator curr = circ;
|
||||
|
||||
int edge_cnt(0);
|
||||
do {
|
||||
edge_cnt++;
|
||||
} while (++curr != circ);
|
||||
return edge_cnt;
|
||||
}
|
||||
|
||||
template <class Edge_const_iterator>
|
||||
void print_edge(Edge_const_iterator eit) {
|
||||
std::cout << "[" << eit->curve() << "]" << std::endl;
|
||||
}
|
||||
template <class Face_const_handle, class Ccb_halfedge_const_circulator>
|
||||
void print_simple_face(Face_const_handle fh) {
|
||||
Ccb_halfedge_const_circulator cir = fh->outer_ccb();
|
||||
Ccb_halfedge_const_circulator curr = cir;
|
||||
do {
|
||||
std::cout << "[" << curr->curve() << "]" << std::endl;
|
||||
} while (++ curr != cir);
|
||||
}
|
||||
|
||||
template <class Arrangement_2>
|
||||
void print_arrangement(const Arrangement_2& arr) {
|
||||
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||
Edge_const_iterator eit;
|
||||
std::cout << arr.number_of_edges() << " edges:" << std::endl;
|
||||
for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
|
||||
print_edge(eit);
|
||||
}
|
||||
|
||||
template <class Arrangement_2>
|
||||
void print_arrangement_by_face(const Arrangement_2& arr) {
|
||||
typedef typename Arrangement_2::Face_const_iterator Face_const_iterator;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
Face_const_iterator f;
|
||||
for (f = arr.faces_begin() ; f != arr.faces_end() ; f++) {
|
||||
if (!f->is_unbounded()) {
|
||||
std::cout << "FACE\n";
|
||||
print_simple_face<Face_const_iterator, Ccb_halfedge_const_circulator>(f);
|
||||
std::cout << "END FACE\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2>
|
||||
Orientation orientation_2(const Geometry_traits_2 *geom_traits,
|
||||
const typename Geometry_traits_2::Point_2& p,
|
||||
const typename Geometry_traits_2::Point_2& q,
|
||||
const typename Geometry_traits_2::Point_2& r) {
|
||||
|
||||
typename Geometry_traits_2::Orientation_2 orient =
|
||||
geom_traits->orientation_2_object();
|
||||
return orient(p, q, r);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2>
|
||||
bool less_distance_to_point_2(const Geometry_traits_2 *geom_traits,
|
||||
const typename Geometry_traits_2::Point_2& p,
|
||||
const typename Geometry_traits_2::Point_2& q,
|
||||
const typename Geometry_traits_2::Point_2& r) {
|
||||
|
||||
typename Geometry_traits_2::Less_distance_to_point_2 less_dist =
|
||||
geom_traits->less_distance_to_point_2_object();
|
||||
return less_dist(p, q, r);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2>
|
||||
bool collinear(const Geometry_traits_2 *geom_traits,
|
||||
const typename Geometry_traits_2::Point_2& p,
|
||||
const typename Geometry_traits_2::Point_2& q,
|
||||
const typename Geometry_traits_2::Point_2& r) {
|
||||
|
||||
typename Geometry_traits_2::Collinear_2 collinear_fnct =
|
||||
geom_traits->collinear_2_object();
|
||||
return collinear_fnct(p, q, r);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2, class _Curve_first, class _Curve_second >
|
||||
typename Geometry_traits_2::Object_2 intersect_2(
|
||||
const Geometry_traits_2 *geom_traits,
|
||||
const _Curve_first& s1,
|
||||
const _Curve_second& s2)
|
||||
{
|
||||
|
||||
typedef typename Geometry_traits_2::Kernel Kernel;
|
||||
const Kernel *kernel = static_cast<const Kernel*> (geom_traits);
|
||||
typename Kernel::Intersect_2 intersect_fnct = kernel->intersect_2_object();
|
||||
return intersect_fnct(s1, s2);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2>
|
||||
CGAL::Comparison_result compare_xy_2(
|
||||
const Geometry_traits_2 *geom_traits,
|
||||
const typename Geometry_traits_2::Point_2 &p,
|
||||
const typename Geometry_traits_2::Point_2 &q)
|
||||
{
|
||||
|
||||
typename Geometry_traits_2::Compare_xy_2 cmp =
|
||||
geom_traits->compare_xy_2_object();
|
||||
return cmp(p, q);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2, class Type1, class Type2>
|
||||
typename Geometry_traits_2::FT compute_squared_distance_2(
|
||||
const Geometry_traits_2 *geom_traits,
|
||||
const Type1& p,
|
||||
const Type2& seg) {
|
||||
|
||||
typename Geometry_traits_2::Compute_squared_distance_2 compute_dist =
|
||||
geom_traits->compute_squared_distance_2_object();
|
||||
return compute_dist(p, seg);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2, class Type1, class Type2>
|
||||
bool do_intersect_2(const Geometry_traits_2 *geom_traits,
|
||||
const Type1& c1,
|
||||
const Type2& c2) {
|
||||
|
||||
typename Geometry_traits_2::Do_intersect_2 intersect =
|
||||
geom_traits->do_intersect_2_object();
|
||||
return intersect(c1, c2);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2>
|
||||
bool collinear_are_ordered_along_line_2(
|
||||
const Geometry_traits_2 *geom_traits,
|
||||
const typename Geometry_traits_2::Point_2 &p,
|
||||
const typename Geometry_traits_2::Point_2 &q,
|
||||
const typename Geometry_traits_2::Point_2 &r)
|
||||
{
|
||||
|
||||
typename Geometry_traits_2::Collinear_are_ordered_along_line_2 coll =
|
||||
geom_traits->collinear_are_ordered_along_line_2_object();
|
||||
return coll(p, q, r);
|
||||
}
|
||||
|
||||
template <class Geometry_traits_2, class Type1, class Type2>
|
||||
typename Geometry_traits_2::Point_2 construct_projected_point_2(
|
||||
const Geometry_traits_2 *geom_traits,
|
||||
const Type1& s,
|
||||
const Type2& p) {
|
||||
|
||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::FT Number_type;
|
||||
typename Geometry_traits_2::Construct_projected_point_2 construct_proj =
|
||||
geom_traits->construct_projected_point_2_object();
|
||||
Point_2 proj_pt = construct_proj(s.supporting_line(), p);
|
||||
if (s.has_on(proj_pt)) {
|
||||
return proj_pt;
|
||||
}
|
||||
else {
|
||||
Number_type d_to_src = compute_squared_distance_2
|
||||
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.source());
|
||||
Number_type d_to_trg = compute_squared_distance_2
|
||||
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.target());
|
||||
if (d_to_src < d_to_trg) {
|
||||
return s.source();
|
||||
}
|
||||
else {
|
||||
return s.target();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// construct an arrangement of visibility region from a vector of
|
||||
// circular ordered vertices with respect to the query point
|
||||
template <class Visibility_2, class Visibility_arrangement_2>
|
||||
void report_while_handling_needles(
|
||||
const typename Visibility_2::Arrangement_2::Geometry_traits_2 *traits,
|
||||
const typename Visibility_2::Arrangement_2::Point_2& q,
|
||||
std::vector<typename Visibility_2::Arrangement_2::Point_2>& points,
|
||||
Visibility_arrangement_2& arr_out) {
|
||||
|
||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||
|
||||
typedef typename Visibility_arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename Visibility_arrangement_2::Vertex_handle Vertex_handle;
|
||||
|
||||
|
||||
|
||||
typename std::vector<Segment_2>::size_type i = 0;
|
||||
|
||||
if (points.front() == points.back()) {
|
||||
points.pop_back();
|
||||
}
|
||||
|
||||
while (collinear(traits, q, points[i], points.back())) {
|
||||
points.push_back(points[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
points.push_back(points[i]);
|
||||
|
||||
Halfedge_handle he_handle;
|
||||
|
||||
//the handle of vertex where the next segment is inserted
|
||||
Vertex_handle v_trg;
|
||||
|
||||
//the handle of vertex inserted first
|
||||
Vertex_handle v_fst;
|
||||
|
||||
//the handle of vertex of the end of a needle
|
||||
Vertex_handle v_needle_end;
|
||||
|
||||
|
||||
v_trg = v_fst = arr_out.insert_in_face_interior(points[i],
|
||||
arr_out.unbounded_face());
|
||||
|
||||
//find a point that is right after a needle
|
||||
while (i+1 < points.size()) {
|
||||
if ( collinear(traits, points[i], points[i+1], q)) {
|
||||
Vertex_handle v_needle_begin = v_trg;
|
||||
|
||||
std::vector<Point_2> forward_needle; //vertices of the needle that are not
|
||||
//between q and v_needle_begin;
|
||||
//their direction is leaving q;
|
||||
|
||||
std::vector<Point_2> backward_needle;//vertices of the needle that are not
|
||||
//between q and v_needle_begin;
|
||||
//their direction is towards q;
|
||||
|
||||
std::vector<Point_2> part_in_q_side; //vertices of the needle that are
|
||||
//between q and v_needle_begin
|
||||
part_in_q_side.push_back(points[i]);
|
||||
forward_needle.push_back((points[i]));
|
||||
|
||||
bool same_side_of_q = (compare_xy_2(traits, points[i], q) ==
|
||||
compare_xy_2(traits, points[i], points[i+1]));
|
||||
|
||||
if (same_side_of_q)
|
||||
part_in_q_side.push_back(points[i+1]);
|
||||
else
|
||||
forward_needle.push_back(points[i+1]);
|
||||
i++;
|
||||
while (i+1 < points.size() &&
|
||||
orientation_2(traits, points[i], points[i+1], q ) ==
|
||||
CGAL::COLLINEAR)
|
||||
{
|
||||
if (same_side_of_q) {
|
||||
part_in_q_side.push_back(points[i+1]);
|
||||
}
|
||||
else {
|
||||
if (compare_xy_2(traits, part_in_q_side.front(), q) ==
|
||||
compare_xy_2(traits, part_in_q_side.front(), points[i+1]))
|
||||
{
|
||||
same_side_of_q = true;
|
||||
part_in_q_side.push_back(points[i+1]);
|
||||
}
|
||||
else {
|
||||
if (less_distance_to_point_2(traits, q, points[i], points[i+1]))
|
||||
forward_needle.push_back(points[i+1]);
|
||||
else
|
||||
backward_needle.push_back(points[i+1]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//obtain the end point of a needle
|
||||
Point_2 end_of_needle;
|
||||
if (same_side_of_q)
|
||||
end_of_needle = part_in_q_side.back();
|
||||
else {
|
||||
if (backward_needle.empty()) {
|
||||
end_of_needle = forward_needle.back();
|
||||
}
|
||||
else {
|
||||
end_of_needle = backward_needle.back();
|
||||
}
|
||||
}
|
||||
|
||||
std::reverse(backward_needle.begin(), backward_needle.end());
|
||||
std::vector<Point_2> merged_needle;
|
||||
|
||||
// merge the forward_needle and backward_needle
|
||||
unsigned int itr_fst = 0, itr_snd = 0;
|
||||
while (itr_fst < forward_needle.size() &&
|
||||
itr_snd < backward_needle.size()) {
|
||||
|
||||
if (less_distance_to_point_2(traits,
|
||||
q,
|
||||
forward_needle[itr_fst],
|
||||
backward_needle[itr_snd]))
|
||||
{
|
||||
merged_needle.push_back(forward_needle[itr_fst]);
|
||||
itr_fst++;
|
||||
}
|
||||
else {
|
||||
merged_needle.push_back(backward_needle[itr_snd]);
|
||||
itr_snd++;
|
||||
}
|
||||
}
|
||||
while (itr_fst < forward_needle.size()) {
|
||||
merged_needle.push_back(forward_needle[itr_fst]);
|
||||
itr_fst++;
|
||||
}
|
||||
while (itr_snd < backward_needle.size()) {
|
||||
merged_needle.push_back(backward_needle[itr_snd]);
|
||||
itr_snd++;
|
||||
}
|
||||
|
||||
for (unsigned int p = 0 ; p+1 < merged_needle.size() ; p++) {
|
||||
if (compare_xy_2<Geometry_traits_2>(
|
||||
traits, merged_needle[p], merged_needle[p+1]) == SMALLER)
|
||||
{
|
||||
he_handle = arr_out.insert_from_left_vertex(
|
||||
Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
|
||||
}
|
||||
else {
|
||||
he_handle = arr_out.insert_from_right_vertex(
|
||||
Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
|
||||
}
|
||||
v_trg = he_handle->target();
|
||||
if (merged_needle[p+1] == end_of_needle) {
|
||||
v_needle_end = v_trg;
|
||||
}
|
||||
}
|
||||
if (same_side_of_q) {
|
||||
//insert the part of needle between q and v_needle_begin
|
||||
v_trg = v_needle_begin;
|
||||
for (unsigned int p = 0 ; p+1 < part_in_q_side.size() ; p++) {
|
||||
if (compare_xy_2<Geometry_traits_2>(
|
||||
traits, part_in_q_side[p], part_in_q_side[p+1]) == SMALLER)
|
||||
{
|
||||
he_handle = arr_out.insert_from_left_vertex(
|
||||
Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
|
||||
}
|
||||
else {
|
||||
he_handle = arr_out.insert_from_right_vertex(
|
||||
Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
|
||||
}
|
||||
v_trg = he_handle->target();
|
||||
}
|
||||
}
|
||||
else
|
||||
v_trg = v_needle_end;
|
||||
}
|
||||
else {
|
||||
if (compare_xy_2<Geometry_traits_2>(
|
||||
traits, v_trg->point(), points[i+1]) == SMALLER)
|
||||
{
|
||||
he_handle = arr_out.insert_from_left_vertex(
|
||||
Segment_2(points[i], points[i+1]), v_trg);
|
||||
}
|
||||
else {
|
||||
he_handle = arr_out.insert_from_right_vertex(
|
||||
Segment_2(points[i], points[i+1]), v_trg);
|
||||
}
|
||||
v_trg = he_handle->target();
|
||||
i++;
|
||||
}
|
||||
if (i+2 == points.size()) {
|
||||
//close the boundary
|
||||
v_trg = he_handle->target();
|
||||
arr_out.insert_at_vertices(Segment_2(points[points.size()-2],
|
||||
points[points.size()-1]),
|
||||
v_trg, v_fst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VARR>
|
||||
void regularize_output(VARR& arr_out) {
|
||||
typename VARR::Edge_iterator it = arr_out.edges_begin();
|
||||
|
||||
while(it != arr_out.edges_end()) {
|
||||
if (it->face() == it->twin()->face()) {
|
||||
typename VARR::Halfedge_handle he = it;
|
||||
++it;
|
||||
arr_out.remove_edge(he);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VARR>
|
||||
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
|
||||
regularize_output(arr_out);
|
||||
}
|
||||
|
||||
template <typename VARR>
|
||||
void conditional_regularize(VARR&, CGAL::Tag_false) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace Visibility_2
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
Braunschweig University (Germany).
|
||||
|
|
@ -0,0 +1 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -0,0 +1 @@
|
|||
Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
4
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
4
|
||||
0 1
|
||||
1 2
|
||||
2 3
|
||||
3 0
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
4
|
||||
0 0
|
||||
4 4
|
||||
32/5 24/5
|
||||
0 8
|
||||
4
|
||||
0 1
|
||||
1 2
|
||||
2 3
|
||||
3 0
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
0.5 2
|
||||
0.5 2
|
||||
|
||||
0
|
||||
6
|
||||
0 4 0 0
|
||||
0 0 3 2
|
||||
3 2 4 0
|
||||
4 0 4 4
|
||||
4 4 1 2
|
||||
1 2 0 4
|
||||
|
||||
0
|
||||
5
|
||||
0 4 0 0
|
||||
0 0 3 2
|
||||
3 2 4 2
|
||||
3 2 1 2
|
||||
1 2 0 4
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#ifndef CGAL_TEST_MODEL_METHODS_H
|
||||
#define CGAL_TEST_MODEL_METHODS_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Visibility_2, class Visibility_arrangement_2>
|
||||
void test_model_methods_for_arr(
|
||||
typename Visibility_2::Arrangement_2 &arr) {
|
||||
|
||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
|
||||
|
||||
typedef typename Visibility_arrangement_2::Face_handle VFH;
|
||||
|
||||
|
||||
Visibility_2 visibility;
|
||||
assert(false == visibility.is_attached());
|
||||
visibility.attach(arr);
|
||||
assert(true == visibility.is_attached());
|
||||
assert(true == (CGAL::test_are_equal(arr,visibility.arrangement_2())));
|
||||
|
||||
Visibility_arrangement_2 arr_out;
|
||||
Visibility_arrangement_2 arr_out_check;
|
||||
|
||||
typename Arrangement_2::Face_const_iterator fit;
|
||||
|
||||
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) {
|
||||
if (!fit->is_unbounded()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// First consider query point in the unbounded face
|
||||
const Point_2 query_pt(1, 1);
|
||||
// Check returned face_handle
|
||||
VFH face_check = visibility.compute_visibility(query_pt, fit, arr_out);
|
||||
VFH face;
|
||||
if (arr_out.faces_begin()->is_unbounded()) {
|
||||
face = ++arr_out.faces_begin();
|
||||
}
|
||||
else {
|
||||
face = arr_out.faces_begin();
|
||||
}
|
||||
assert(face_check == face);
|
||||
|
||||
assert((true == test_are_equal<Arrangement_2, Visibility_arrangement_2>
|
||||
(arr, arr_out)));
|
||||
visibility.detach();
|
||||
assert(false == visibility.is_attached());
|
||||
visibility.attach(arr);
|
||||
|
||||
visibility.compute_visibility(query_pt, fit, arr_out_check);
|
||||
assert((true == test_are_equal<Visibility_arrangement_2, Arrangement_2>
|
||||
(arr_out_check, arr)));
|
||||
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||
(arr_out, arr_out_check)));
|
||||
arr_out.clear();
|
||||
visibility.compute_visibility(query_pt, fit, arr_out);
|
||||
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||
(arr_out, arr_out_check)));
|
||||
|
||||
// Now consider the query point on a halfedge
|
||||
const Point_2 query_pt2 = Point_2(0, 4);
|
||||
arr_out.clear();
|
||||
typename Arrangement_2::Halfedge_const_iterator hit;
|
||||
VFH face_check_he;
|
||||
for (hit = arr.halfedges_begin();
|
||||
hit != arr.halfedges_end(); ++hit) {
|
||||
|
||||
if (hit->source()->point() == Point_2(0, 8) && hit->target()->point() == Point_2(0, 0)) {
|
||||
face_check_he = visibility.compute_visibility(query_pt2, hit, arr_out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arr_out.faces_begin()->is_unbounded()) {
|
||||
face = ++arr_out.faces_begin();
|
||||
}
|
||||
else {
|
||||
face = arr_out.faces_begin();
|
||||
}
|
||||
assert(face_check_he == face);
|
||||
assert((true == test_are_equal(arr_out, arr)));
|
||||
arr_out_check.clear();
|
||||
visibility.compute_visibility(query_pt2, hit, arr_out_check);
|
||||
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||
(arr_out, arr_out_check)));
|
||||
|
||||
// Now consider the query point as the target of a halfedge
|
||||
typename Arrangement_2::Halfedge_const_iterator hit_snd;
|
||||
for (hit_snd = arr.halfedges_begin(); hit_snd != arr.halfedges_end(); ++hit_snd) {
|
||||
if(!hit_snd->face()->is_unbounded()){
|
||||
arr_out.clear();
|
||||
VFH face_check_he_snd = visibility.compute_visibility(hit_snd->target()->point(), hit_snd, arr_out);
|
||||
assert(!face_check_he_snd->is_unbounded());
|
||||
if (arr_out.faces_begin()->is_unbounded()) {
|
||||
face = ++arr_out.faces_begin();
|
||||
}
|
||||
else {
|
||||
face = arr_out.faces_begin();
|
||||
}
|
||||
assert(face_check_he_snd == face);
|
||||
if (! test_are_equal(arr_out, arr)) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Visibility_2, class Visibility_arrangement_2>
|
||||
void test_model_methods() {
|
||||
|
||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2::Segment_2 Segment_2;
|
||||
|
||||
|
||||
Point_2 p1(0, 0), p2(8, 0), p3(8, 8), p4(0, 8);
|
||||
std::vector<Segment_2> seg_sq;
|
||||
seg_sq.push_back(Segment_2(p1, p2));
|
||||
seg_sq.push_back(Segment_2(p2, p3));
|
||||
seg_sq.push_back(Segment_2(p3, p4));
|
||||
seg_sq.push_back(Segment_2(p4, p1));
|
||||
Arrangement_2 arr_square;
|
||||
CGAL::insert(arr_square, seg_sq.begin(), seg_sq.end());
|
||||
|
||||
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_square);
|
||||
|
||||
std::vector<Segment_2> seg_tri;
|
||||
seg_tri.push_back(Segment_2(p1, p2));
|
||||
seg_tri.push_back(Segment_2(p2, p4));
|
||||
seg_tri.push_back(Segment_2(p4, p1));
|
||||
Arrangement_2 arr_triangle;
|
||||
CGAL::insert(arr_triangle, seg_tri.begin(), seg_tri.end());
|
||||
|
||||
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_triangle);
|
||||
}
|
||||
|
||||
} // end CGAL namespace
|
||||
#endif
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
// Kan Huang <huangkandiy@gmail.com
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef Traits_2::Point_2 Point_2;
|
||||
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
|
||||
template <class Visibility>
|
||||
void deploy_pure_benchmark(const CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||
Visibility v;
|
||||
CGAL::pure_benchmark<Visibility>
|
||||
(v, qchoice, input);
|
||||
}
|
||||
|
||||
|
||||
template <class Regularization_category>
|
||||
void benchmark_one_class(std::string name, const CGAL::Query_choice& qchoice, std::string input_arr_file) {
|
||||
std::ifstream input(input_arr_file.c_str());
|
||||
if (name == "S")
|
||||
deploy_pure_benchmark<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
|
||||
if (name == "T")
|
||||
deploy_pure_benchmark<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
|
||||
if (name == "R")
|
||||
deploy_pure_benchmark<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category> > (qchoice, input);
|
||||
}
|
||||
|
||||
void print_usage() {
|
||||
std::cout << "Usage: ./pure_benchmark [filename] [Class type] [Query type] [Regularize]\n";
|
||||
std::cout << "where [Class type] could be S(simple), R(rotational sweep), and T(triangular), indicating which class you want to test.\n";
|
||||
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
|
||||
std::cout << "[Regularize] can be: {true, false}.\n";
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
CGAL::Query_choice qchoice = CGAL::FACE;
|
||||
std::string regularization_tag("true");
|
||||
if (argc > 1) {
|
||||
std::string input_arr_file(argv[1]);
|
||||
|
||||
if (argc == 2) {
|
||||
std::cout << "NAME TAG PreProTime NQueries TimeQueries TotalTime QAVE TAVE" << std::endl;
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::FACE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::FACE, input_arr_file);
|
||||
std::cout << std::endl;
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::FACE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::FACE, input_arr_file);
|
||||
std::cout << std::endl;
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::FACE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::FACE, input_arr_file);
|
||||
std::cout << std::endl;
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_true>(std::string("PR"), CGAL::FACE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::VERTEX, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::EDGE, input_arr_file);
|
||||
benchmark_one_class<CGAL::Tag_false>(std::string("PR"), CGAL::FACE, input_arr_file);
|
||||
} else if (argc == 5) {
|
||||
qchoice = CGAL::FACE;
|
||||
std::string query_type(argv[3]);
|
||||
if (query_type == "vertex")
|
||||
qchoice = CGAL::VERTEX;
|
||||
else if (query_type == "edge")
|
||||
qchoice = CGAL::EDGE;
|
||||
else if (query_type == "face")
|
||||
qchoice = CGAL::FACE;
|
||||
else {
|
||||
std::cout<<"query type is not matched.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
regularization_tag = argv[4];
|
||||
std::string classname(argv[2]);
|
||||
if (regularization_tag == "true") {
|
||||
benchmark_one_class<CGAL::Tag_true>(classname, qchoice, input_arr_file);
|
||||
}
|
||||
else {
|
||||
benchmark_one_class<CGAL::Tag_false>(classname, qchoice, input_arr_file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
print_usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_usage();
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
// Kan Huang <huangkandiy@gmail.com>
|
||||
// Ning Xu <longyin0904@gmail.com>
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef Traits_2::Point_2 Point_2;
|
||||
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
|
||||
template <class Visibility_fst, class Visibility_snd>
|
||||
void deploy_benchmark(CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||
Visibility_fst v1;
|
||||
Visibility_snd v2;
|
||||
CGAL::simple_benchmark<Visibility_fst, Visibility_snd>
|
||||
(v1, v2, qchoice, input);
|
||||
}
|
||||
|
||||
template <class Visibility_fst, class Regularization_category>
|
||||
void define_snd_class(std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input){
|
||||
if (name2 == "S")
|
||||
deploy_benchmark<Visibility_fst, CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category> >
|
||||
(qchoice, input);
|
||||
if (name2 == "T")
|
||||
deploy_benchmark<Visibility_fst, CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category> >
|
||||
(qchoice, input);
|
||||
if (name2 == "R")
|
||||
deploy_benchmark<Visibility_fst, CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category> >
|
||||
(qchoice, input);
|
||||
}
|
||||
|
||||
template <class Regularization_category>
|
||||
void benchmark_two_classes(std::string name1, std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||
if (name1 == "S")
|
||||
define_snd_class<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
|
||||
if (name1 == "T")
|
||||
define_snd_class<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
|
||||
if (name1 == "R")
|
||||
define_snd_class<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_category>, Regularization_category> (name2, qchoice, input);
|
||||
}
|
||||
|
||||
void print_usage() {
|
||||
std::cout << "Usage: ./simple_benchmark [filename] [Class type 1] [Class type 2] [Query type] [Regularize]\n";
|
||||
std::cout << "where [Class type] could be S(simple), R(rotational sweep) and T(triangular), indicating which classes you want to test.\n";
|
||||
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
|
||||
std::cout << "[Regularize] can be: {true, false}.\n";
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
CGAL::Query_choice qchoice = CGAL::FACE;
|
||||
std::string regularization_tag("true");
|
||||
if (argc > 1) {
|
||||
std::string input_arr_file(argv[1]);
|
||||
std::ifstream input(input_arr_file.c_str());
|
||||
if (argc == 6) {
|
||||
qchoice = CGAL::FACE;
|
||||
std::string query_type(argv[4]);
|
||||
if (query_type == "vertex")
|
||||
qchoice = CGAL::VERTEX;
|
||||
else if (query_type == "edge")
|
||||
qchoice = CGAL::EDGE;
|
||||
else if (query_type == "face")
|
||||
qchoice = CGAL::FACE;
|
||||
else {
|
||||
std::cout<<"query type is not matched.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
regularization_tag = argv[5];
|
||||
std::string class1(argv[2]), class2(argv[3]);
|
||||
if (regularization_tag == "true") {
|
||||
benchmark_two_classes<CGAL::Tag_true>(class1, class2, qchoice, input);
|
||||
}
|
||||
else {
|
||||
benchmark_two_classes<CGAL::Tag_false>(class1, class2, qchoice, input);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
print_usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
print_usage();
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Kan Huang <huangkandiy@gmail.com>
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||
#include <CGAL/Arr_extended_dcel.h>
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main() {
|
||||
{
|
||||
typedef CGAL::Cartesian<CGAL::Exact_rational> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||
RSV;
|
||||
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
|
||||
}
|
||||
{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||
RSV;
|
||||
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
|
||||
}
|
||||
}{
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||
RSV;
|
||||
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
|
||||
}
|
||||
{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||
RSV;
|
||||
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<RSV,Arrangement_2>(22, 2);
|
||||
}
|
||||
}
|
||||
{
|
||||
// test Visibility_arrangement_type with extended DCEL
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||
{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}{
|
||||
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||
#include <CGAL/Arr_extended_dcel.h>
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main() {
|
||||
{
|
||||
typedef CGAL::Exact_rational Number_type;
|
||||
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef CGAL::Simple_polygon_visibility_2<
|
||||
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
|
||||
std::cout << "Running model tests - ";
|
||||
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
|
||||
std::cout << GREEN << "Done!" << RESET << std::endl;
|
||||
std::cout << "Running test suite with " << GREEN
|
||||
<< "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(22, 0);
|
||||
}
|
||||
{
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef CGAL::Simple_polygon_visibility_2<
|
||||
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
|
||||
std::cout << "Running model tests - ";
|
||||
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
|
||||
std::cout << GREEN << "Done!" << RESET << std::endl;
|
||||
std::cout << "Running test suite with " << GREEN
|
||||
<< "EPECK" << RESET << " Kernel..." << std::endl;
|
||||
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(22, 0);
|
||||
}
|
||||
{
|
||||
// test Visibility_arrangement_type with extended DCEL
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||
{
|
||||
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}{
|
||||
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
||||
// Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
{
|
||||
typedef CGAL::Exact_rational Number_type;
|
||||
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef CGAL::Simple_polygon_visibility_2<
|
||||
Arrangement_2, CGAL::Tag_false> Simple_polygon_visibility_2;
|
||||
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||
Triangular_expansion_visibility_2;
|
||||
|
||||
if (argc == 2) {
|
||||
Simple_polygon_visibility_2 simple_visibility;
|
||||
const CGAL::Query_choice qchoice = CGAL::FACE;
|
||||
std::string input_arr_file(argv[1]);
|
||||
std::ifstream input(input_arr_file.c_str());
|
||||
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||
(simple_visibility, qchoice, input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
const CGAL::Query_choice qchoice = CGAL::FACE;
|
||||
std::string input_arr_file(argv[1]);
|
||||
std::ifstream input(input_arr_file.c_str());
|
||||
std::string class_name(argv[2]);
|
||||
if ( class_name == "simple") {
|
||||
Simple_polygon_visibility_2 simple_visibility;
|
||||
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||
(simple_visibility, qchoice, input);
|
||||
return 0;
|
||||
}
|
||||
if (class_name == "triangular") {
|
||||
Triangular_expansion_visibility_2 triangular_visibility;
|
||||
CGAL::test_star_shape<Triangular_expansion_visibility_2>
|
||||
(triangular_visibility, qchoice, input);
|
||||
return 0;
|
||||
}
|
||||
std::cout<<"no type is matched.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 4) {
|
||||
std::string input_arr_file(argv[1]);
|
||||
std::ifstream input(input_arr_file.c_str());
|
||||
CGAL::Query_choice qchoice;
|
||||
std::string query_type(argv[3]);
|
||||
if (query_type == "vertex")
|
||||
qchoice = CGAL::VERTEX;
|
||||
else {
|
||||
if (query_type == "edge")
|
||||
qchoice = CGAL::EDGE;
|
||||
else {
|
||||
if (query_type == "face")
|
||||
qchoice = CGAL::FACE;
|
||||
else {
|
||||
std::cout<<"query type is not matched.\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string class_name(argv[2]);
|
||||
if (class_name == "simple") {
|
||||
Simple_polygon_visibility_2 simple_visibility;
|
||||
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||
(simple_visibility, qchoice, input);
|
||||
return 0;
|
||||
}
|
||||
if (class_name == "triangular") {
|
||||
Triangular_expansion_visibility_2 triangular_visibility;
|
||||
CGAL::test_star_shape<Triangular_expansion_visibility_2>
|
||||
(triangular_visibility, qchoice, input);
|
||||
return 0;
|
||||
}
|
||||
std::cout<<"no type is matched.\n";
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Usage: ./test_star_shape [filename] [Class type] [Query type]\n";
|
||||
std::cout << "where [Class type] could be simple, naive and triangular, indicating which class you want to test.\n";
|
||||
std::cout << "[Query type] could be vertex, edge, face.\n";
|
||||
std::cout << "The default value of [Query type] is face. The default value of [Class type] is simple.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/Arr_extended_dcel.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main() {
|
||||
{
|
||||
typedef CGAL::Exact_rational Number_type;
|
||||
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<
|
||||
Arrangement_2 , CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
|
||||
}
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<
|
||||
Arrangement_2 , CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
|
||||
}
|
||||
}
|
||||
{
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<
|
||||
Arrangement_2 , CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
|
||||
}{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<
|
||||
Arrangement_2 , CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||
CGAL::run_tests<Visibility_2,Arrangement_2>(22, 2);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// test Visibility_arrangement_type with extended DCEL
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||
CGAL::run_tests<Visibility_2,EARR>(22, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||