Merge branch 'gsoc2013-Visibility_doc-hemmer-old' into gsoc2013-Visibility_doc-hemmer
Conflicts: Documentation/biblio/how_to_cite.html Documentation/biblio/how_to_cite_cgal.txt
|
|
@ -2335,6 +2335,50 @@ ADDRESS = "Saarbr{\"u}cken, Germany"
|
||||||
series = {Texts and Monographs in Symbolic Computation}
|
series = {Texts and Monographs in Symbolic Computation}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@article{bjrb-clvpa-87,
|
||||||
|
author = "B. Joe and R.B. Simpson",
|
||||||
|
title = "Corrections to Lee's visibility polygon algorithm",
|
||||||
|
journal = "BIT",
|
||||||
|
volume = 27,
|
||||||
|
year = 1987,
|
||||||
|
pages = "458--473"
|
||||||
|
}
|
||||||
|
|
||||||
|
@article{ta-aeafvpprh-85
|
||||||
|
,author = {T. Asano}
|
||||||
|
,title = {An Efficient Algorithm for Finding the Visibility Polygon for a Polygonal Region with Holes}
|
||||||
|
,journal = {IEICE Transactions (1976-1990)}
|
||||||
|
,year = 1985
|
||||||
|
,volume = E68
|
||||||
|
,number = 9
|
||||||
|
,pages = {557--559}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@article{aaghi-vpsesp-85,
|
||||||
|
author = {Takao Asano and
|
||||||
|
Tetsuo Asano and
|
||||||
|
Leonidas J. Guibas and
|
||||||
|
John Hershberger and
|
||||||
|
Hiroshi Imai},
|
||||||
|
title = {Visibility-Polygon Search and Euclidean Shortest Paths},
|
||||||
|
booktitle = {FOCS},
|
||||||
|
year = {1985},
|
||||||
|
pages = {155-164},
|
||||||
|
ee = {http://doi.ieeecomputersociety.org/10.1109/SFCS.1985.65},
|
||||||
|
crossref = {DBLP:conf/focs/FOCS26},
|
||||||
|
bibsource = {DBLP, http://dblp.uni-trier.de}
|
||||||
|
}
|
||||||
|
|
||||||
|
@article{dtl-voasp-83,
|
||||||
|
author = "D. T. Lee",
|
||||||
|
title = "Visibility of a simple polygon",
|
||||||
|
journal = "Computer Vision, Graphics, and Image Processing",
|
||||||
|
volume = 22,
|
||||||
|
year = 1983,
|
||||||
|
pages = "207--221"
|
||||||
|
}
|
||||||
|
|
||||||
% ----------------------------------------------------------------------------
|
% ----------------------------------------------------------------------------
|
||||||
% END OF BIBFILE
|
% END OF BIBFILE
|
||||||
% ----------------------------------------------------------------------------
|
% ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -151797,4 +151797,3 @@ amplification and suppression of local contrast. Contains C code."
|
||||||
, publisher = "Cambridge University Press"
|
, publisher = "Cambridge University Press"
|
||||||
, year = 1999
|
, year = 1999
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ IMAGE_PATH = ${CMAKE_SOURCE_DIR}/Documentation/doc/Documentation/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Spatial_sorting/doc/Spatial_sorting/fig \
|
${CMAKE_SOURCE_DIR}/Spatial_sorting/doc/Spatial_sorting/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/fig \
|
${CMAKE_SOURCE_DIR}/Segment_Delaunay_graph_2/doc/Segment_Delaunay_graph_2/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Straight_skeleton_2/doc/Straight_skeleton_2/fig \
|
${CMAKE_SOURCE_DIR}/Straight_skeleton_2/doc/Straight_skeleton_2/fig \
|
||||||
|
${CMAKE_SOURCE_DIR}/Visibility_2/doc/Visibility_2/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
|
${CMAKE_SOURCE_DIR}/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
|
${CMAKE_SOURCE_DIR}/Surface_mesh_simplification/doc/Surface_mesh_simplification/fig \
|
||||||
${CMAKE_SOURCE_DIR}/Subdivision_method_3/doc/Subdivision_method_3/fig \
|
${CMAKE_SOURCE_DIR}/Subdivision_method_3/doc/Subdivision_method_3/fig \
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ Spatial_searching
|
||||||
Spatial_sorting
|
Spatial_sorting
|
||||||
Segment_Delaunay_graph_2
|
Segment_Delaunay_graph_2
|
||||||
Straight_skeleton_2
|
Straight_skeleton_2
|
||||||
|
Visibility_2
|
||||||
Voronoi_diagram_2
|
Voronoi_diagram_2
|
||||||
Surface_mesh_simplification
|
Surface_mesh_simplification
|
||||||
Subdivision_method_3
|
Subdivision_method_3
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ h1 {
|
||||||
\package_listing{Snap_rounding_2}
|
\package_listing{Snap_rounding_2}
|
||||||
\package_listing{Envelope_2}
|
\package_listing{Envelope_2}
|
||||||
\package_listing{Envelope_3}
|
\package_listing{Envelope_3}
|
||||||
|
\package_listing{Visibility_2}
|
||||||
|
|
||||||
\section PartTriangulationsAndDelaunayTriangulations Triangulations and Delaunay Triangulations
|
\section PartTriangulationsAndDelaunayTriangulations Triangulations and Delaunay Triangulations
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -718,8 +718,24 @@ namespace for the XML file to be processed properly. -->
|
||||||
<item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item>
|
<item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item>
|
||||||
</list>
|
</list>
|
||||||
</doxygen>
|
</doxygen>
|
||||||
|
</project>
|
||||||
|
|
||||||
|
<project>
|
||||||
|
<name>2D Visibility</name>
|
||||||
|
<input>../Visibility_2/doc/Visibility_2</input>
|
||||||
|
<doxygen>
|
||||||
|
<string name="STRIP_FROM_INC_PATH">../Visibility_2/doc/Visibility_2/</string>
|
||||||
|
<string name="STRIP_FROM_PATH">../Visibility_2/doc/Visibility_2/</string>
|
||||||
|
<string name="GENERATE_TAGFILE">./tags/Visibility_2.tag</string>
|
||||||
|
<string name="EXAMPLE_PATH">../Visibility_2/examples</string>
|
||||||
|
<string name="IMAGE_PATH">../Visibility_2/doc/Visibility_2/fig</string>
|
||||||
|
<list name="TAGFILES" append="true">
|
||||||
|
<item>./tags/Arrangement_on_surface_2.tag=../../CGAL.CGAL.2D-Arrangements/html</item>
|
||||||
|
</list>
|
||||||
|
</doxygen>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
||||||
<project>
|
<project>
|
||||||
<name>2D Minkowski Sums</name>
|
<name>2D Minkowski Sums</name>
|
||||||
<input>../Minkowski_sum_2/doc/Minkowski_sum_2</input>
|
<input>../Minkowski_sum_2/doc/Minkowski_sum_2</input>
|
||||||
|
|
@ -1457,6 +1473,7 @@ namespace for the XML file to be processed properly. -->
|
||||||
<item>../Convex_hull_d/doc/Convex_hull_d/fig</item>
|
<item>../Convex_hull_d/doc/Convex_hull_d/fig</item>
|
||||||
<item>../Envelope_2/doc/Envelope_2/fig</item>
|
<item>../Envelope_2/doc/Envelope_2/fig</item>
|
||||||
<item>../Envelope_3/doc/Envelope_3/fig</item>
|
<item>../Envelope_3/doc/Envelope_3/fig</item>
|
||||||
|
<item>../Visibility_2/doc/Visibility_2/fig</item>
|
||||||
<item>../Generator/doc/Generator/fig</item>
|
<item>../Generator/doc/Generator/fig</item>
|
||||||
<item>../Geomview/doc/Geomview/fig</item>
|
<item>../Geomview/doc/Geomview/fig</item>
|
||||||
<item>../GraphicsView/doc/GraphicsView/fig</item>
|
<item>../GraphicsView/doc/GraphicsView/fig</item>
|
||||||
|
|
@ -1538,6 +1555,7 @@ namespace for the XML file to be processed properly. -->
|
||||||
<item>./tags/Convex_hull_d.tag=../../CGAL.CGAL.dD-Convex-Hulls-and-Delaunay-Triangulations/html</item>
|
<item>./tags/Convex_hull_d.tag=../../CGAL.CGAL.dD-Convex-Hulls-and-Delaunay-Triangulations/html</item>
|
||||||
<item>./tags/Envelope_2.tag=../../CGAL.CGAL.2D-Envelopes/html</item>
|
<item>./tags/Envelope_2.tag=../../CGAL.CGAL.2D-Envelopes/html</item>
|
||||||
<item>./tags/Envelope_3.tag=../../CGAL.CGAL.3D-Envelopes/html</item>
|
<item>./tags/Envelope_3.tag=../../CGAL.CGAL.3D-Envelopes/html</item>
|
||||||
|
<item>./tags/Visibility_2.tag=../../CGAL.CGAL.2D-Visibility/html</item>
|
||||||
<item>./tags/Generator.tag=../../CGAL.CGAL.Geometric-Object-Generators/html</item>
|
<item>./tags/Generator.tag=../../CGAL.CGAL.Geometric-Object-Generators/html</item>
|
||||||
<item>./tags/Geomview.tag=../../CGAL.CGAL.Geomview/html</item>
|
<item>./tags/Geomview.tag=../../CGAL.CGAL.Geomview/html</item>
|
||||||
<item>./tags/GraphicsView.tag=../../CGAL.CGAL.CGAL-and-the-Qt-Graphics-View-Framework/html</item>
|
<item>./tags/GraphicsView.tag=../../CGAL.CGAL.CGAL-and-the-Qt-Graphics-View-Framework/html</item>
|
||||||
|
|
|
||||||
|
|
@ -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 RegularizationTag indicates whether the output should be regularized. It can be
|
||||||
|
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||||
|
|
||||||
|
|
||||||
|
\cgalModels `Visibility_2`
|
||||||
|
|
||||||
|
\sa `CGAL::Simple_polygon_visibility_2<Arrangement_2, RegularizationTag>`
|
||||||
|
\sa `CGAL::Rotational_sweep_visibility_2<Arrangement_2, RegularizationTag>`
|
||||||
|
\sa `CGAL::Triangular_expansion_visibility_2<Arrangement_2, RegularizationTag>`
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <typename Arrangement_2, typename RegularizationTag = Tag_false>
|
||||||
|
class Preprocessed_rotational_sweep_visibility_2 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Types
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2 Arrangement_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The type of the output arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2 Visibility_arrangement_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The 2D point type used for the queries.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Point_2 Point_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Face_const_handle type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Halfedge_const_handle type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Tags
|
||||||
|
/// @{
|
||||||
|
/*!
|
||||||
|
Tag identifying whether the regularized visibility area is computed.
|
||||||
|
*/
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tag identifying that the class supports general polygons (i.e.\ with holes).
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_general_polygon_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tag identifying that the class supports general simple polygons.
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_simple_polygon_tag;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Constructors
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Default constructor creates an empty `Preprocessed_rotational_sweep_visibility_2` object that is not
|
||||||
|
attached to any arrangement yet.
|
||||||
|
*/
|
||||||
|
Preprocessed_rotational_sweep_visibility_2();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a `Preprocessed_rotational_sweep_visibility_2` object that is attached to `arr`.
|
||||||
|
*/
|
||||||
|
Preprocessed_rotational_sweep_visibility_2(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns whether an arrangement is attached to the visibility object
|
||||||
|
*/
|
||||||
|
bool is_attached() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attaches the given arrangement to the visibility object and applies preprocessing.
|
||||||
|
In case the object is already attached to another arrangement,
|
||||||
|
the visibility object gets detached before being attached to `arr`.
|
||||||
|
*/
|
||||||
|
void attach(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Detaches the arrangement from the visibility object it is currently attached to
|
||||||
|
*/
|
||||||
|
void detach();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Access to the attached arrangement
|
||||||
|
*/
|
||||||
|
const Arrangement_2& arr() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Computes the visibility region of `q` in the
|
||||||
|
face `f` of the arrangement that is attached to the visibility object.
|
||||||
|
The visibility region of `q` will be stored in `out_arr`.
|
||||||
|
\param q is the query point
|
||||||
|
\param f is the face of the arrangement in which the visibility region is computed
|
||||||
|
\param out_arr is the output arrangement
|
||||||
|
\pre `f` is a face of `arr()` and represents a valid polygon.
|
||||||
|
\pre `q` is in the interior of the given face `f`
|
||||||
|
\return a handle to the face in `out_arr` that represents the visibility region
|
||||||
|
*/
|
||||||
|
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Face_const_handle f, Visibility_arrangement_2& out_arr) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Computes the visibility region of `q` that is on `e`. If `q` is an interior point of `e`, the computed visibility region is restricted to the halfplane indicated by `e`. If `q` is an endpoint of `e`, the visibility region is restricted by `e` and its next.
|
||||||
|
The visibility region of `q` will be stored in `out_arr`.
|
||||||
|
\param q is the query point
|
||||||
|
\param e the halfedge on which `q` is located
|
||||||
|
\param out_arr is the output arrangement
|
||||||
|
\pre `e` is a halfedge of `arr()`
|
||||||
|
\pre `q` is on `e`
|
||||||
|
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
|
||||||
|
\return a handle to the face in `out_arr` that represents the visibility region
|
||||||
|
*/
|
||||||
|
typename Visibility_arrangement_2::Face_handle compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Visibility_2 */
|
||||||
|
} /* namespace CGAL */
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
namespace CGAL {
|
||||||
|
/*!
|
||||||
|
\ingroup PkgVisibility_2Classes
|
||||||
|
|
||||||
|
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
|
||||||
|
|
||||||
|
|
||||||
|
\details The algorithm does not require preprocessing. It relies on the algorithm of T. Asano \cite ta-aeafvpprh-85 based on angular plane sweep, with a time complexity of \f$O (n \log n)\f$ in the number of vertices.
|
||||||
|
|
||||||
|
|
||||||
|
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||||
|
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||||
|
CGAL::Arr_segment_traits_2.
|
||||||
|
|
||||||
|
\tparam RegularizationTag indicates whether the output should be regularized. It can be
|
||||||
|
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\cgalModels `Visibility_2`
|
||||||
|
|
||||||
|
\sa `CGAL::Simple_polygon_visibility_2`
|
||||||
|
\sa `CGAL::Triangular_expansion_visibility_2`
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <typename Arrangement_2_, typename RegularizationTag = Tag_true>
|
||||||
|
class Rotational_sweep_visibility_2 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Types
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2 Arrangement_2;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Tags
|
||||||
|
/// @{
|
||||||
|
/*!
|
||||||
|
Tag identifying whether the regularized visibility area is computed.
|
||||||
|
*/
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class supports general polygons (i.e.\ with holes).
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_general_polygon_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class supports general simple polygons.
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_simple_polygon_tag;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attaches the given arrangement to the visibility object.
|
||||||
|
|
||||||
|
This operation takes \f$O(1)\f$ as the class does no pre-processing.
|
||||||
|
|
||||||
|
In case the object is already attached to another arrangement,
|
||||||
|
the visibility object gets detached before being attached to `arr`.
|
||||||
|
*/
|
||||||
|
void attach(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Visibility_2 */
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
namespace CGAL {
|
||||||
|
/*!
|
||||||
|
\ingroup PkgVisibility_2Classes
|
||||||
|
|
||||||
|
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within
|
||||||
|
a simple polygon with no holes.
|
||||||
|
|
||||||
|
\details This class implements the algorithm of B.Joe and R.B.Simpson \cite bjrb-clvpa-87.
|
||||||
|
The algorithm is a modification and extension of the linear time algorithm of Lee \cite dtl-voasp-83.
|
||||||
|
It computes the visibility region from a viewpoint that is in the interior or on the boundary of the polygon.
|
||||||
|
|
||||||
|
While scanning the boundary the algorithm uses a stack to manipulate the vertices, and ultimately
|
||||||
|
yields the visibility region. For each scanned edge, at most 2 points are pushed onto the stack.
|
||||||
|
Overall, at most 2\f$ n \f$ points are pushed or popped. Thus, the time and space complexities of the
|
||||||
|
algorithm are \f$ O(n) \f$ even in case of degeneracies such as needles, where \f$ n \f$
|
||||||
|
is the number of the vertices of the polygon.
|
||||||
|
|
||||||
|
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||||
|
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||||
|
CGAL::Arr_segment_traits_2.
|
||||||
|
|
||||||
|
\tparam RegularizationTag indicates whether the output should be regularized. It can be
|
||||||
|
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||||
|
|
||||||
|
|
||||||
|
\cgalModels `Visibility_2`
|
||||||
|
|
||||||
|
\sa `CGAL::Rotational_sweep_visibility_2`
|
||||||
|
\sa `CGAL::Triangular_expansion_visibility_2`
|
||||||
|
*/
|
||||||
|
template <typename Arrangement_2_, typename RegularizationTag = Tag_true>
|
||||||
|
class Simple_polygon_visibility_2 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Types
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The arrangement type is used for input.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2 Arrangement_2;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Tags
|
||||||
|
/// @{
|
||||||
|
/*!
|
||||||
|
Tag identifying whether the regularized visibility area is computed.
|
||||||
|
*/
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class does not support general polygons (i.e.\ with holes).
|
||||||
|
*/
|
||||||
|
typedef ::Tag_false Supports_general_polygon_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class supports general simple polygons.
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_simple_polygon_tag;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attaches the given arrangement to the visibility object.
|
||||||
|
|
||||||
|
This operation takes \f$O(1)\f$ as the class does no pre-processing.
|
||||||
|
|
||||||
|
In case the object is already attached to another arrangement,
|
||||||
|
the visibility object gets detached before being attached to `arr`.
|
||||||
|
*/
|
||||||
|
void attach(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Visibility_2 */
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
namespace CGAL {
|
||||||
|
/*!
|
||||||
|
\ingroup PkgVisibility_2Classes
|
||||||
|
|
||||||
|
\brief This class is a model of the concept `Visibility_2` can answer visibility queries within a polygon that may have holes.
|
||||||
|
|
||||||
|
\details The algorithm obtains a constrained triangulation from input arrangement, then computes visibility by
|
||||||
|
expanding the triangle that contains the query point.
|
||||||
|
Preprocessing takes \f$ O(n)\f$ time and \f$ O(n) \f$ space, where \f$ n \f$ is the number of vertices of input polygon.
|
||||||
|
The query time is \f$ O(nh)\f$, where \f$ h \f$ is the number of holes+1 of input polygon. Thus, for simple polygons
|
||||||
|
the algorithm is even linear but it can also be \f$ O(n^2)\f$ in the worst case as the number of holes can be linear in \f$ n \f$.
|
||||||
|
|
||||||
|
|
||||||
|
\tparam Arrangement_2_ is the type used to represent the input environment.
|
||||||
|
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2 must be an instance of
|
||||||
|
CGAL::Arr_segment_traits_2.
|
||||||
|
|
||||||
|
\tparam RegularizationTag indicates whether the output should be regularized. It can be
|
||||||
|
specified by one of the following: ::Tag_true or ::Tag_false, where ::Tag_false is the default value.
|
||||||
|
|
||||||
|
\cgalModels `Visibility_2`
|
||||||
|
|
||||||
|
\sa `CGAL::Simple_polygon_visibility_2`
|
||||||
|
\sa `CGAL::Rotational_sweep_visibility_2`
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <typename Arrangement_2_, typename RegularizationTag = Tag_true>
|
||||||
|
class Triangular_expansion_visibility_2 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Types
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Tags
|
||||||
|
/// @{
|
||||||
|
/*!
|
||||||
|
Tag identifying whether the regularized visibility area is computed.
|
||||||
|
*/
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class supports general polygons (i.e.\ with holes).
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_general_polygon_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The class supports general simple polygons.
|
||||||
|
*/
|
||||||
|
typedef ::Tag_true Supports_simple_polygon_tag;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attaches the given arrangement to the visibility object and computes the restricted triangulation.
|
||||||
|
This takes \f$ O(n) \f$ time, where \f$ n \f$ is the number of vertices.
|
||||||
|
|
||||||
|
From this moment on the class observes changes in the arrangement. If the arrangement changes
|
||||||
|
the a new restricted triangulation is computed right before a new query. It is also possible
|
||||||
|
to force a re-computation by re-attaching the current arrangement.
|
||||||
|
|
||||||
|
In case the object is already attached to another arrangement,
|
||||||
|
the visibility object gets detached before being attached to `arr`.
|
||||||
|
*/
|
||||||
|
void attach(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Visibility_2 */
|
||||||
|
} /* namespace CGAL */
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgVisibility_2Concepts
|
||||||
|
\cgalConcept
|
||||||
|
|
||||||
|
A model of the `Visibility_2` concept can be attached to an `Arrangement_2` instance to
|
||||||
|
answer visibility queries within the faces of this arrangement.
|
||||||
|
|
||||||
|
\cgalHasModel `CGAL::Simple_polygon_visibility_2`
|
||||||
|
\cgalHasModel `CGAL::Rotational_sweep_visibility_2`
|
||||||
|
\cgalHasModel `CGAL::Triangular_expansion_visibility_2`
|
||||||
|
|
||||||
|
*/
|
||||||
|
class Visibility_2 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Types
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The arrangement type of the input.
|
||||||
|
*/
|
||||||
|
typedef Hidden_type Arrangement_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The geometry traits class of Arrangement_2.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Traits_2 Traits_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The 2D point type used for the queries.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Point_2 Point_2;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The face handle type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The halfedge handle type of the input arrangement.
|
||||||
|
*/
|
||||||
|
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Tags
|
||||||
|
/// @{
|
||||||
|
/*!
|
||||||
|
Tag identifying whether the regularized visibility area is computed (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||||
|
*/
|
||||||
|
typedef Hidden_type Regularization_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tag identifying whether general polygons (with holes) are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||||
|
*/
|
||||||
|
typedef Hidden_type Supports_general_polygon_tag;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tag identifying whether general simple polygons are supported (either \ref CGAL::Tag_true or \ref CGAL::Tag_false).
|
||||||
|
*/
|
||||||
|
typedef Hidden_type Supports_simple_polygon_tag;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Constructors
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Default constructor creates an empty `Visibility_2` object that is not
|
||||||
|
attached to any arrangement yet.
|
||||||
|
*/
|
||||||
|
Visibility_2();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a `Visibility_2` object that is attached to `arr`.
|
||||||
|
*/
|
||||||
|
Visibility_2(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
/// \name Functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns whether an arrangement is attached to the visibility object
|
||||||
|
*/
|
||||||
|
bool is_attached() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attaches the given arrangement `arr` to the visibility object.
|
||||||
|
In case the object is already attached to another arrangement,
|
||||||
|
the visibility object gets detached before being attached to `arr`.
|
||||||
|
*/
|
||||||
|
void attach(const Arrangement_2& arr);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Detaches the arrangement from the visibility object it is currently attached to
|
||||||
|
*/
|
||||||
|
void detach();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Access to the attached arrangement
|
||||||
|
*/
|
||||||
|
const Arrangement_2& arr() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Computes the visibility region for the given query point `q` in the
|
||||||
|
face \f$ f \f$ of the arrangement that is attached to the visibility object.
|
||||||
|
The visibility region of `q` is stored in `out_arr`, that is,
|
||||||
|
all features but the unbounded face of `out_arr` represent the visibility region.
|
||||||
|
|
||||||
|
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
|
||||||
|
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
|
||||||
|
must be mutual convertible to Visibility_2::Traits_2.
|
||||||
|
|
||||||
|
\param q is the query point
|
||||||
|
\param f is the face of the arrangement in which the visibility region is computed
|
||||||
|
\param out_arr is the output arrangement
|
||||||
|
\pre `f` is a face of `this->arr()`
|
||||||
|
\pre `q` is in the interior of the given face `f`
|
||||||
|
\return the face handle to the face in `out_arr` that represents interior of the visibility region
|
||||||
|
*/
|
||||||
|
template <typename VisibilityArrangement_2>
|
||||||
|
typename Visibility_arrangement_2::Face_handle
|
||||||
|
compute_visibility(const Point_2& q, const Face_const_handle f, VisibilityArrangement_2& out_arr) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Computes the visibility region in `e->face()` for the given query
|
||||||
|
point `q` which must be located on `e`.
|
||||||
|
If `q` is an interior point of `e`, the computed visibility
|
||||||
|
region is restricted to the side indicated by the halfedge `e`.
|
||||||
|
If `q` is an endpoint of `e`, the visibility region is restricted by `e` and `e->next()`.
|
||||||
|
The visibility region of `q` is stored in `out_arr`, that is,
|
||||||
|
all features but the unbounded face of `out_arr` represent the visibility region.
|
||||||
|
|
||||||
|
\tparam VisibilityArrangement_2 is the type of the output arrangement representing the visibility polygon.
|
||||||
|
It must be an instance of CGAL::Arrangement_2, where its CGAL::Arrangement_2::Traits_2
|
||||||
|
must be mutual convertible to Visibility_2::Traits_2.
|
||||||
|
\param q is the query point
|
||||||
|
\param e the halfedge on which `q` is located
|
||||||
|
\param out_arr is the output arrangement
|
||||||
|
\pre `e` is a halfedge of `this->arr()`
|
||||||
|
\pre `q` is on `e`
|
||||||
|
\pre `q` equals to `e->target()->point()` if `q` is an endpoint of `e`
|
||||||
|
\return a handle to the face in `out_arr` that represents the interior of the visibility region
|
||||||
|
*/
|
||||||
|
template <typename VisibilityArrangement_2>
|
||||||
|
typename Visibility_arrangement_2::Face_handle
|
||||||
|
compute_visibility(const Point_2& q, const Halfedge_const_handle e, Visibility_arrangement_2& out_arr) const;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Visibility_2 */
|
||||||
|
|
||||||
|
|
@ -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}
|
||||||
|
\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: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
|
@ -0,0 +1,152 @@
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\mainpage 2D Visibility
|
||||||
|
\anchor Chapter_2D_Visibility_Computation
|
||||||
|
\cgalAutoToc
|
||||||
|
|
||||||
|
\authors Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu
|
||||||
|
|
||||||
|
\cgalFigureBegin{example_figure,visibility-teaser.png}
|
||||||
|
\cgalFigureEnd
|
||||||
|
|
||||||
|
\section visibility_2_introduction Introduction
|
||||||
|
|
||||||
|
This package provides functionality to compute the visibility region within polygonal regions in two dimensions.
|
||||||
|
Using the terminology of the package \ref PkgBooleanSetOperations2Summary, we expect the input polygon
|
||||||
|
\f$ P \f$ to be a valid polygon or a valid polygon with holes (the definition is given below).
|
||||||
|
Given two points \f$ p \f$ and \f$ q \f$ in \f$ P \f$, they are said to be
|
||||||
|
visible to each other iff the segment \f$ pq \subset P \f$, note that \f$\partial P \subset P\f$.
|
||||||
|
For a query point \f$ q \in P \f$, the set of points that are visible from \f$ q \f$ is defined as the visibility
|
||||||
|
region of \f$ q \f$, denoted by \f$ V_q \f$
|
||||||
|
|
||||||
|
|
||||||
|
Definition [Valid Polygon]:
|
||||||
|
A polygon \f$ P \f$ is valid if \f$ P \f$ is closed (\f$\partial P \subset P\f$)
|
||||||
|
and each boundary loop (only one outer boundary loop in case of no holes) is simple.
|
||||||
|
See also \ref PkgBooleanSetOperations2Summary.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection visibility_2_degeneracies Degeneracies and Regularization
|
||||||
|
|
||||||
|
\cgalFigureBegin{definition-fig, example1.png}
|
||||||
|
Non-regularized visibility and regularized visibility.
|
||||||
|
\cgalFigureEnd
|
||||||
|
|
||||||
|
|
||||||
|
As illustrated in \cgalFigureRef{definition-fig} (1) the visibility region \f$ V_q \f$ of a query point \f$ q \f$ may not be
|
||||||
|
a valid polygon. In the figure, all labeled points are collinear, which implies that the point \f$ c \f$ is visible to \f$ q \f$, that is,
|
||||||
|
the segment \f$ bc \f$ is part of the visibility area \f$ V_q \f$.
|
||||||
|
Subsequently we call such low dimensional features that are caused by degeneracies `needles`.
|
||||||
|
However, for many applications these needles are actually irrelevant.
|
||||||
|
Moreover, for some algorithms it is actually easier (and more efficient) to ignore needles
|
||||||
|
in the first place.
|
||||||
|
Therefore, this package offers also
|
||||||
|
functionality to compute the regularized visibility area
|
||||||
|
\f$ \overline{V_q} = closure(interior(V_q)) = (V_q\setminus\partial V_q) \cup \partial (V_q\setminus\partial V_q)\f$,
|
||||||
|
as it is shown in \cgalFigureRef{definition-fig} (2). For more information about regularization, refer to Chapter
|
||||||
|
\ref PkgBooleanSetOperations2Summary.
|
||||||
|
|
||||||
|
In summary, this package provides two kinds of visibility region of point \f$ q \f$:
|
||||||
|
- Non-regularized visibility area \f$ V_q \f$.
|
||||||
|
- Regularized visibility area \f$ \overline{V_q} \f$.
|
||||||
|
|
||||||
|
|
||||||
|
\section visibility_2_classes Classes and Algorithms
|
||||||
|
|
||||||
|
This package is based on the \ref PkgArrangement2Summary package and exploits several of its features.
|
||||||
|
In particular, the output is represented by an `Arrangement_2`, which enables
|
||||||
|
the representation of needles. All provided class templates follow the `Visibility_2` concept.
|
||||||
|
|
||||||
|
Answering visibility queries is, in many ways, similar to answering point-location queries. Thus, we use the same design used
|
||||||
|
to implement point location. Each of the various visibility class templates employs a different algorithm or \em strategy
|
||||||
|
\cgalFootnote{The term \em strategy is borrowed from the design-pattern taxonomy~\cite ghjv-dpero-95. A \em strategy provides
|
||||||
|
the means to define a family of algorithms, each implemented by a separate class. All classes that implement the various
|
||||||
|
algorithms are made interchangeable, letting the algorithm in use vary according to the user choice.} for answering queries.
|
||||||
|
Similar to the point-location case, some of the strategies require preprocessing. Thus, before a visibility object is used
|
||||||
|
to answer visibility queries, it must be attached to an arrangement object (subsequently also referred to as the environment).
|
||||||
|
Afterwards the visibility object observers changes to the attached arrangement.
|
||||||
|
Clearly, it is possible to modify the arrangement after attaching the visibility object.
|
||||||
|
However, this should be avoided as this also requires an update of the auxiliary
|
||||||
|
data structures in the attached object.
|
||||||
|
|
||||||
|
An actual query is then performed by giving the view point \f$ p \f$ and its containing face \f$ f \f$,
|
||||||
|
which must represent a valid \cgalFootnote{See the package \ref PkgBooleanSetOperations2Summary for precise definition}
|
||||||
|
polygon (\f$ f \f$ has no isolated vertices and each boundary edge of \f$ f \f$ separates it from another face).
|
||||||
|
For this purpose every model of the Visibility_2 concept provides two overloaded member functions, called `Visibility_2::compute_visibility()`
|
||||||
|
functions, that compute the visibility region of \f$ p \f$ in a bounded polygonal face \f$ f \f$: one is for the case where
|
||||||
|
\f$ p \f$ is in the interior of \f$ f \f$; the other one is for the case where \f$ p \f$ is on the boundary of \f$ f \f$.
|
||||||
|
|
||||||
|
|
||||||
|
The package provides the following models of the `Visibility_2` concept:
|
||||||
|
|
||||||
|
Class | Function | Preprocessing | Query |Algorithm
|
||||||
|
-------------------------------|-----------------------------------------------------|-------------------------------|-----------------------------------|-------------------------------
|
||||||
|
`Simple_polygon_visibility_2` | simple valid polygons | No |\f$ O(n) \f$ time and \f$ O(n) \f$ space | B.Joe and R.B.Simpson \cite bjrb-clvpa-87
|
||||||
|
`Rotational_sweep_visibility_2` | valid polygons with holes | No | \f$ O(n\log n) \f$ time and \f$ O(n) \f$ space | T.Asano \cite ta-aeafvpprh-85
|
||||||
|
`Triangular_expansion_visibility_2` | valid polygons with holes | \f$ O(n) \f$ time and \f$ O(n) \f$ space | \f$ O(nh) \f$ time and \f$ O(n) \f$ space. | new
|
||||||
|
|
||||||
|
|
||||||
|
Where \f$ n \f$ is the number of vertices of \f$ f \f$ and \f$ h \f$ is the number of holes+1.
|
||||||
|
|
||||||
|
\section benchmarks Runtime in Practice
|
||||||
|
|
||||||
|
\cgalFigureBegin{cathedral-fig, cathedral_2.png}
|
||||||
|
Example environment representing a cathedral.
|
||||||
|
\cgalFigureEnd
|
||||||
|
|
||||||
|
The left hand side of Figure \cgalFigureRef{cathedral-fig} depicts the outer boundary of a cathedral,
|
||||||
|
which is a simple polygon with 565 vertices. The right hand side shows the cathedral also with its inner
|
||||||
|
pillars, which is a polygon with 1153 vertices. The following table shows the total runtime to compute
|
||||||
|
all visibility polygons for all vertices of the boundary of the cathedral.
|
||||||
|
|
||||||
|
|
||||||
|
Boundary Cathedral | total preprocessing time | total query time |
|
||||||
|
-------------------------------|-----------------------------------------------------|-------------------------------|
|
||||||
|
`Simple_polygon_visibility_2` | - | 0.38 |
|
||||||
|
`Rotational_sweep_visibility_2` | - | 1.01 |
|
||||||
|
`Triangular_expansion_visibility_2` | 0.01 | 0.06 |
|
||||||
|
|
||||||
|
The second table shows the same for the complete cathedral. The table does not report the time for `Simple_polygon_visibility_2`
|
||||||
|
as this algorithm can only handle simple polygons.
|
||||||
|
|
||||||
|
Complete Cathedral | total preprocessing time | total query time |
|
||||||
|
-------------------------------|-----------------------------------------------------|-------------------------------|
|
||||||
|
`Rotational_sweep_visibility_2` | - | 1.91 |
|
||||||
|
`Triangular_expansion_visibility_2` | 0.01 | 0.04 |
|
||||||
|
|
||||||
|
Thus, in general we recommend to use `Triangular_expansion_visibility_2` even if the polygon is simple. The main advantage
|
||||||
|
of the algorithm is its locality. After the triangle that contains the query point is located in the triangulation,
|
||||||
|
the algorithm explores neighboring triangles, but only those that are actually seen. In this sense the algorithm can be
|
||||||
|
considered as output sensitive. However, if the simple polygon is rather convex (i.e., nearly all boundary is seen) or
|
||||||
|
if only one (or very little) queries are required, using one of the algorithms that does not require preprocessing is advantageous.
|
||||||
|
|
||||||
|
|
||||||
|
\section simple_polygon_visibility_example Example of Visibility in a Simple Polygon
|
||||||
|
The following example shows how to obtain the regularized and non-regularized visibility regions.
|
||||||
|
\cgalExample{Visibility_2/simple_polygon_visibility_2.cpp}
|
||||||
|
|
||||||
|
\section general_polygon_example Example of Visibility in a Polygon with Holes
|
||||||
|
The following example shows how to obtain the regularized visibility region using the model `Triangular_expansion_visibility_2`. See \cgalFigureRef{general_polygon}. The arrangement has six bounded faces and an unbounded face. The query point \f$ q \f$ is on a vertex. The red arrow denotes the halfedge \f$ \overrightarrow{pq} \f$, which also identifies the face in which the visibility region is computed.
|
||||||
|
\cgalFigureBegin{general_polygon, general_polygon_example.png}
|
||||||
|
The visibility region of \f$ q \f$ in a polygon with two holes.
|
||||||
|
\cgalFigureEnd
|
||||||
|
\cgalExample{Visibility_2/general_polygon_example.cpp}
|
||||||
|
|
||||||
|
\section implentation_history Implementation History
|
||||||
|
|
||||||
|
This package was first developed during Google Summer of Code 2013. Fancisc Bungju developed the Simple_polygon_visibility_2 class; Kan Huang developed the Rotational_sweep_visibility_2 class; and Michael Hemmer developed the Triangular_expansion_visibility_2 class.
|
||||||
|
|
||||||
|
This first class, Simple_polygon_visibility_2, implements the algorithm presented by B. Joe and R.B. Simpson in 1987 \cite js-clvpa87. This algorithm is a linear time algorithm for simple polygons, fixing the errors in a previous algorithm presented by D.T. Lee in 1983.
|
||||||
|
|
||||||
|
The second class, Rotational_sweep_visibility_2, implements the algorithm presented by T. Asano in 1985. This algorithm can be applied to polygons with holes with time complexity \f$ O(n\log n) \f$.
|
||||||
|
|
||||||
|
The third class, Triangular_expansion_visibility_2, implements the algorithm presented by F. Bungju, et al.. This algorithm can be applied to polygons with holes with worst case running time \f$ O(n^2) \f$, but is extremely fast in practice.
|
||||||
|
|
||||||
|
In Google Summer of Code 2014, Ning Xu became a developer for this package. He fixed bugs in the algorithm for simple polygons.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Preprocessed_rotational_sweep_visibility_2` | valid polygons with holes | \f$ O(n^2) \f$ time and \f$ O(n^2) \f$ space | \f$ O(n) \f$ time and \f$ O(n) \f$ space | Takao Asano, Tetsuo Asano etc \cite aaghi-vpsesp-85
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef Kernel::Point_2 Point_2;
|
||||||
|
typedef Kernel::Segment_2 Segment_2;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
|
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef Arrangement_2::Face_handle Face_handle;
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2> TEV;
|
||||||
|
int main() {
|
||||||
|
Point_2 p1(1, 2), p2(12, 3), p3(19, -2), p4(12, 6), p5(14, 14), p6(9, 5);
|
||||||
|
Point_2 h1(8,3), h2(10, 3), h3(8, 4), h4(10, 6), h5(11, 6), h6(11, 7);
|
||||||
|
Segment_2 s[12];
|
||||||
|
s[0] = Segment_2(p1, p2);
|
||||||
|
s[1] = Segment_2(p2, p3);
|
||||||
|
s[2] = Segment_2(p3, p4);
|
||||||
|
s[3] = Segment_2(p4, p5);
|
||||||
|
s[4] = Segment_2(p5, p6);
|
||||||
|
s[5] = Segment_2(p6, p1);
|
||||||
|
|
||||||
|
s[6] = Segment_2(h1, h2);
|
||||||
|
s[7] = Segment_2(h2, h3);
|
||||||
|
s[8] = Segment_2(h3, h1);
|
||||||
|
s[9] = Segment_2(h4, h5);
|
||||||
|
s[10] = Segment_2(h5, h6);
|
||||||
|
s[11] = Segment_2(h6, h4);
|
||||||
|
Arrangement_2 env;
|
||||||
|
CGAL::insert_non_intersecting_curves(env, &s[0], &s[12]);
|
||||||
|
//find the halfedge whose target is the query point.
|
||||||
|
Point_2 query_point = p4;
|
||||||
|
Halfedge_const_handle he = env.halfedges_begin();
|
||||||
|
while (he->source()->point() != p3 || he->target()->point() != p4)
|
||||||
|
he++;
|
||||||
|
//visibility query
|
||||||
|
Arrangement_2 output_arr;
|
||||||
|
TEV tev(env);
|
||||||
|
Face_handle fh = tev.compute_visibility(query_point, he, output_arr);
|
||||||
|
//print out the visibility region.
|
||||||
|
std::cout << "Regularized visibility region of q has "
|
||||||
|
<< output_arr.number_of_edges()
|
||||||
|
<< " edges." << std::endl;
|
||||||
|
Arrangement_2::Ccb_halfedge_circulator curr = fh->outer_ccb();
|
||||||
|
std::cout << "Traverse the face of the visibility region." << std::endl;
|
||||||
|
std::cout << "[" << curr->curve() << "]"<< std::endl;
|
||||||
|
while (++curr != fh->outer_ccb())
|
||||||
|
std::cout << "[" << curr->curve() << "]" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||||
|
#include <CGAL/Arr_naive_point_location.h>
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef Kernel::Point_2 Point_2;
|
||||||
|
typedef Kernel::Segment_2 Segment_2;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||||
|
typedef Arrangement_2::Face_handle Face_handle;
|
||||||
|
typedef Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator;
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
NSPV;
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||||
|
RSPV;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
//create environment
|
||||||
|
Point_2 p1(0, 4), p2(0, 0), p3(3, 2), p4(4, 0), p5(4, 4), p6(1, 2);
|
||||||
|
Segment_2 s[6];
|
||||||
|
s[0] = Segment_2(p1, p2);
|
||||||
|
s[1] = Segment_2(p2, p3);
|
||||||
|
s[2] = Segment_2(p3, p4);
|
||||||
|
s[3] = Segment_2(p4, p5);
|
||||||
|
s[4] = Segment_2(p5, p6);
|
||||||
|
s[5] = Segment_2(p6, p1);
|
||||||
|
Arrangement_2 env;
|
||||||
|
CGAL::insert_non_intersecting_curves(env, &s[0], &s[6]);
|
||||||
|
//locate the query point in the arrangement
|
||||||
|
Point_2 query_point(0.5, 2);
|
||||||
|
Arrangement_2::Face_const_handle face;
|
||||||
|
CGAL::Arr_naive_point_location<Arrangement_2> pl(env);
|
||||||
|
CGAL::Object obj = pl.locate(query_point);
|
||||||
|
CGAL::assign(face, obj);
|
||||||
|
//visibility query
|
||||||
|
Arrangement_2 non_regular_output;
|
||||||
|
NSPV non_regular_visibility(env);
|
||||||
|
Face_handle non_regular_fh = non_regular_visibility.compute_visibility(query_point, face, non_regular_output);
|
||||||
|
std::cout << "Non-regularized visibility region of q has "
|
||||||
|
<< non_regular_output.number_of_edges()
|
||||||
|
<< " edges:" << std::endl;
|
||||||
|
for (Edge_const_iterator eit = non_regular_output.edges_begin(); eit != non_regular_output.edges_end(); ++eit)
|
||||||
|
std::cout << "[" << eit->curve() << "]" << std::endl;
|
||||||
|
Arrangement_2 regular_output;
|
||||||
|
RSPV regular_visibility(env);
|
||||||
|
Face_handle regular_fh = regular_visibility.compute_visibility(query_point, face, regular_output);
|
||||||
|
Ccb_halfedge_circulator curr = regular_fh->outer_ccb();
|
||||||
|
std::cout << "Regularized visibility region of q has "
|
||||||
|
<< regular_output.number_of_edges()
|
||||||
|
<< " edges:" << std::endl;
|
||||||
|
for (Edge_const_iterator eit = regular_output.edges_begin(); eit != regular_output.edges_end(); ++eit)
|
||||||
|
std::cout << "[" << eit->curve() << "]" << std::endl;
|
||||||
|
|
||||||
|
//For a regular face, we can also get its whole boundary by traversing its outer CCB.
|
||||||
|
std::cout << "Traverse the face of the regularized visibility region:" << std::endl;
|
||||||
|
std::cout << "[" << curr->curve() << "]"<< std::endl;
|
||||||
|
while (++curr != regular_fh->outer_ccb())
|
||||||
|
std::cout << "[" << curr->curve() << "]" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CGAL_PREPROCESSED_VISIBILITY_2_H
|
||||||
|
#define CGAL_PREPROCESSED_VISIBILITY_2_H
|
||||||
|
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Arr_linear_traits_2.h>
|
||||||
|
#include <stack>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
template<class Arrangement_2>
|
||||||
|
class Preprocessed_visibility_2 {
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
// Currently only consider with same type for both
|
||||||
|
typedef Arrangement_2 Input_Arrangement_2;
|
||||||
|
typedef Arrangement_2 Output_Arrangement_2;
|
||||||
|
|
||||||
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Arrangement_2::Kernel Kernel;
|
||||||
|
typedef typename CGAL::Arr_linear_traits_2<Kernel> Linear_traits_2;
|
||||||
|
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||||
|
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
|
||||||
|
typedef typename CGAL::Arrangement_2<Linear_traits_2> Line_Arrangement_2;
|
||||||
|
|
||||||
|
Preprocessed_visibility_2() : p_arr(NULL) {};
|
||||||
|
|
||||||
|
/*! Constructor given an arrangement and the Regularization tag. */
|
||||||
|
Preprocessed_visibility_2(Input_Arrangement_2& arr/*, Regularization_tag r_t*/): p_arr(&arr) {};
|
||||||
|
|
||||||
|
bool is_attached() {
|
||||||
|
return (p_arr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(Input_Arrangement_2& arr) {
|
||||||
|
p_arr = &arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void detach() {
|
||||||
|
p_arr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input_Arrangement_2 arr() {
|
||||||
|
return *p_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_visibility(const Point_2& q,
|
||||||
|
const Face_const_handle face,
|
||||||
|
Output_Arrangement_2& out_arr
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_visibility(const Point_2& q,
|
||||||
|
const Halfedge_const_handle he,
|
||||||
|
Output_Arrangement_2& out_arr
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Input_Arrangement_2* arr;
|
||||||
|
Line_Arrangement_2 line_arr;
|
||||||
|
void preprocess() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Line_2 dual_line(const Point_2& p) {
|
||||||
|
return Line_2(p.x(), -1, -p.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CGAL
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,866 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
|
||||||
|
#define CGAL_ROTATIONAL_SWEEP_VISIBILITY_2_H
|
||||||
|
|
||||||
|
#include <CGAL/Visibility_2/visibility_utils.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/bounding_box.h>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
template<class Arrangement_2_ , class RegularizationTag = CGAL::Tag_true >
|
||||||
|
class Rotational_sweep_visibility_2 {
|
||||||
|
public:
|
||||||
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
|
Ccb_halfedge_const_circulator;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
|
|
||||||
|
typedef typename Geometry_traits_2::Kernel K;
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||||
|
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||||
|
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
typedef CGAL::Tag_true Supports_general_polygon_tag;
|
||||||
|
typedef CGAL::Tag_true Supports_simple_polygon_tag;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<Point_2> Points;
|
||||||
|
typedef Vertex_const_handle VH;
|
||||||
|
typedef std::vector<VH> VHs;
|
||||||
|
typedef Halfedge_const_handle EH;
|
||||||
|
typedef std::vector<EH> EHs;
|
||||||
|
|
||||||
|
class Less_edge: public std::binary_function<EH, EH, bool> {
|
||||||
|
const Geometry_traits_2* geom_traits;
|
||||||
|
public:
|
||||||
|
Less_edge() {}
|
||||||
|
Less_edge(const Geometry_traits_2* traits):geom_traits(traits) {}
|
||||||
|
bool operator() (const EH e1, const EH e2) const {
|
||||||
|
if (e1 == e2)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
return &(*e1)<&(*e2);
|
||||||
|
// if (e1->source() == e2->source())
|
||||||
|
// return Visibility_2::compare_xy_2(geom_traits, e1->target()->point(), e2->target()->point()) == SMALLER;
|
||||||
|
// else
|
||||||
|
// return Visibility_2::compare_xy_2(geom_traits, e1->source()->point(), e2->source()->point()) == SMALLER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Less_vertex: public std::binary_function<VH, VH, bool> {
|
||||||
|
const Geometry_traits_2* geom_traits;
|
||||||
|
public:
|
||||||
|
Less_vertex() {}
|
||||||
|
Less_vertex(const Geometry_traits_2* traits):geom_traits(traits) {}
|
||||||
|
bool operator() (const VH v1, const VH v2) const {
|
||||||
|
if (v1 == v2)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
// I know this is dirty but it speeds up by 25%. Michael
|
||||||
|
return &(*v1)<&(*v2);
|
||||||
|
// return Visibility_2::compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Closer_edge: public std::binary_function<EH, EH, bool> {
|
||||||
|
const Geometry_traits_2* geom_traits;
|
||||||
|
Point_2 q;
|
||||||
|
public:
|
||||||
|
Closer_edge() {}
|
||||||
|
Closer_edge(const Geometry_traits_2* traits, const Point_2& q):geom_traits(traits), q(q) {}
|
||||||
|
|
||||||
|
int vtype(const Point_2& c, const Point_2& p) const {
|
||||||
|
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
|
||||||
|
case COLLINEAR:
|
||||||
|
if (Visibility_2::less_distance_to_point_2(geom_traits, q, c, p))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 3;
|
||||||
|
case RIGHT_TURN:
|
||||||
|
return 1;
|
||||||
|
case LEFT_TURN:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool operator() (const EH& e1, const EH& e2) const {
|
||||||
|
if (e1 == e2)
|
||||||
|
return false;
|
||||||
|
const Point_2& s1=e1->source()->point(),
|
||||||
|
t1=e1->target()->point(),
|
||||||
|
s2=e2->source()->point(),
|
||||||
|
t2=e2->target()->point();
|
||||||
|
if (e1->source() == e2->source()) {
|
||||||
|
|
||||||
|
int vt1 = vtype(s1, t1),
|
||||||
|
vt2 = vtype(s1, t2);
|
||||||
|
if (vt1 != vt2)
|
||||||
|
return vt1 > vt2;
|
||||||
|
else
|
||||||
|
return (Visibility_2::orientation_2(geom_traits, s1, t2, t1)==
|
||||||
|
Visibility_2::orientation_2(geom_traits, s1, t2, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e1->target() == e2->source()) {
|
||||||
|
// const Point_2& p1 = s1,
|
||||||
|
// p2 = t2,
|
||||||
|
// c = s2;
|
||||||
|
int vt1 = vtype(t1, s1),
|
||||||
|
vt2 = vtype(t1, t2);
|
||||||
|
if (vt1 != vt2)
|
||||||
|
return vt1 > vt2;
|
||||||
|
else
|
||||||
|
return (Visibility_2::orientation_2(geom_traits, s2, t2, s1)==
|
||||||
|
Visibility_2::orientation_2(geom_traits, s2, t2, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e1->source() == e2->target()) {
|
||||||
|
// const Point_2& p1 = t1,
|
||||||
|
// p2 = s2,
|
||||||
|
// c = s1;
|
||||||
|
int vt1 = vtype(s1, t1),
|
||||||
|
vt2 = vtype(s1, s2);
|
||||||
|
if (vt1 != vt2)
|
||||||
|
return vt1 > vt2;
|
||||||
|
else return (Visibility_2::orientation_2(geom_traits, s1, s2, t1)==
|
||||||
|
Visibility_2::orientation_2(geom_traits, s1, s2, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e1->target() == e2->target()) {
|
||||||
|
// const Point_2& p1 = s1,
|
||||||
|
// p2 = s2,
|
||||||
|
// c = t1;
|
||||||
|
int vt1 = vtype(t1, s1),
|
||||||
|
vt2 = vtype(t1, s2);
|
||||||
|
if (vt1 != vt2)
|
||||||
|
return vt1 > vt2;
|
||||||
|
else return (Visibility_2::orientation_2(geom_traits, t1, s2, s1)==
|
||||||
|
Visibility_2::orientation_2(geom_traits, t1, s2, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
Orientation e1q = Visibility_2::orientation_2(geom_traits, s1, t1, q);
|
||||||
|
switch (e1q)
|
||||||
|
{
|
||||||
|
case COLLINEAR:
|
||||||
|
if (Visibility_2::collinear(geom_traits, q, s2, t2)) {
|
||||||
|
//q is collinear with e1 and e2.
|
||||||
|
return (Visibility_2::less_distance_to_point_2(geom_traits, q, s1, s2)
|
||||||
|
|| Visibility_2::less_distance_to_point_2(geom_traits, q, t1, t2));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//q is collinear with e1 not with e2.
|
||||||
|
if (Visibility_2::collinear(geom_traits, s2, t2, s1))
|
||||||
|
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, t1));
|
||||||
|
else
|
||||||
|
return (Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1));
|
||||||
|
}
|
||||||
|
case RIGHT_TURN:
|
||||||
|
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
|
||||||
|
case COLLINEAR:
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
||||||
|
case RIGHT_TURN:
|
||||||
|
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
case LEFT_TURN:
|
||||||
|
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case LEFT_TURN:
|
||||||
|
switch (Visibility_2::orientation_2(geom_traits, s1, t1, s2)) {
|
||||||
|
case COLLINEAR:
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
||||||
|
case LEFT_TURN:
|
||||||
|
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
case RIGHT_TURN:
|
||||||
|
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == LEFT_TURN)
|
||||||
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Using hash_map or edx causes a seg fault, did not have the time to see why. Michael
|
||||||
|
// class Hash_edge: public std::unary_function<VH,typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type> {
|
||||||
|
// public:
|
||||||
|
// typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type
|
||||||
|
// operator() (const EH e1) const {
|
||||||
|
// return boost::hash<const typename Arrangement_2::X_monotone_curve_2*>()(&(e1->curve()));
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
const Geometry_traits_2 *geom_traits;
|
||||||
|
const Arrangement_2 *p_arr;
|
||||||
|
Point_2 q; //query point
|
||||||
|
Points polygon; //visibility polygon
|
||||||
|
std::map<VH, EHs, Less_vertex> incident_edges; //the edges that are
|
||||||
|
std::map<EH, int, Less_edge> edx; //index of active edges in the heap
|
||||||
|
// boost::unordered_map<EH,int,Hash_edge> edx; //index of active edges in the heap
|
||||||
|
std::set<EH, Closer_edge> active_edges; //a set of edges that intersect the current vision ray.
|
||||||
|
VHs vs; //angular sorted vertices
|
||||||
|
EHs bad_edges; //edges that pass the query point
|
||||||
|
VH cone_end1; //an end of visibility cone
|
||||||
|
VH cone_end2; //another end of visibility cone
|
||||||
|
int cone_end1_idx; //index of cone_end1->point() in visibility polygon
|
||||||
|
int cone_end2_idx; //index of cone_end2->point() in visibility polygon
|
||||||
|
|
||||||
|
bool is_vertex_query;
|
||||||
|
bool is_edge_query;
|
||||||
|
bool is_face_query;
|
||||||
|
bool is_big_cone; //whether the angle of visibility_cone is greater than pi.
|
||||||
|
|
||||||
|
public:
|
||||||
|
Rotational_sweep_visibility_2(): p_arr(NULL), geom_traits(NULL) {}
|
||||||
|
Rotational_sweep_visibility_2(const Arrangement_2& arr): p_arr(&arr) {
|
||||||
|
geom_traits = p_arr->geometry_traits();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string name(){return std::string("R_visibility_2");}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q, const Halfedge_const_handle e, VARR& arr_out) {
|
||||||
|
arr_out.clear();
|
||||||
|
bad_edges.clear();
|
||||||
|
this->q = q;
|
||||||
|
|
||||||
|
if (Visibility_2::compare_xy_2(geom_traits, q, e->target()->point())==EQUAL) {
|
||||||
|
is_vertex_query = true;
|
||||||
|
is_edge_query = false;
|
||||||
|
is_face_query = false;
|
||||||
|
cone_end1 = e->source();
|
||||||
|
cone_end2 = e->next()->target();
|
||||||
|
is_big_cone = CGAL::right_turn(cone_end1->point(), q, cone_end2->point());
|
||||||
|
|
||||||
|
typename Arrangement_2::Halfedge_around_vertex_const_circulator first, curr;
|
||||||
|
first = curr = e->target()->incident_halfedges();
|
||||||
|
do {
|
||||||
|
if (curr->face() == e->face())
|
||||||
|
bad_edges.push_back(curr);
|
||||||
|
else if (curr->twin()->face() == e->face())
|
||||||
|
bad_edges.push_back(curr->twin());
|
||||||
|
} while (++curr != first);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_vertex_query = false;
|
||||||
|
is_edge_query = true;
|
||||||
|
is_face_query = false;
|
||||||
|
cone_end1 = e->source();
|
||||||
|
cone_end2 = e->target();
|
||||||
|
bad_edges.push_back(e);
|
||||||
|
is_big_cone = false;
|
||||||
|
}
|
||||||
|
visibility_region_impl(e->face(), q);
|
||||||
|
|
||||||
|
//decide which inside of the visibility butterfly is needed.
|
||||||
|
int small_idx, big_idx;
|
||||||
|
if ( cone_end1_idx < cone_end2_idx ) {
|
||||||
|
small_idx = cone_end1_idx;
|
||||||
|
big_idx = cone_end2_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
small_idx = cone_end2_idx;
|
||||||
|
big_idx = cone_end1_idx;
|
||||||
|
}
|
||||||
|
int next_idx = small_idx + 1;
|
||||||
|
bool is_between;
|
||||||
|
//indicate whether the shape between small_idx and big_idx is the visibility region required.
|
||||||
|
if (CGAL::right_turn(cone_end1->point(), q, cone_end2->point())) {
|
||||||
|
is_between = false;
|
||||||
|
while (next_idx != big_idx) {
|
||||||
|
if (CGAL::left_turn(cone_end1->point(), q, polygon[next_idx]) || CGAL::left_turn(q, cone_end2->point(), polygon[next_idx])) {
|
||||||
|
is_between = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_between = true;
|
||||||
|
while (next_idx != big_idx) {
|
||||||
|
if (CGAL::right_turn(cone_end1->point(), q, polygon[next_idx]) || CGAL::right_turn(q, cone_end2->point(), polygon[next_idx])) {
|
||||||
|
is_between = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typename Points::iterator first = polygon.begin() + small_idx;
|
||||||
|
typename Points::iterator last = polygon.begin() + big_idx;
|
||||||
|
if (is_between) {
|
||||||
|
Points polygon_out(first, last+1);
|
||||||
|
if (is_vertex_query)
|
||||||
|
polygon_out.push_back(q);
|
||||||
|
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||||
|
(geom_traits, q, polygon_out, arr_out);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Points polygon_out(polygon.begin(), first+1);
|
||||||
|
if (is_vertex_query) polygon_out.push_back(q);
|
||||||
|
for (int i = big_idx; i != polygon.size(); i++) {
|
||||||
|
polygon_out.push_back(polygon[i]);
|
||||||
|
}
|
||||||
|
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||||
|
(geom_traits, q, polygon_out, arr_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_regularize(arr_out, Regularization_tag());
|
||||||
|
|
||||||
|
if (arr_out.faces_begin()->is_unbounded())
|
||||||
|
return ++arr_out.faces_begin();
|
||||||
|
else
|
||||||
|
return arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q, const Face_const_handle f, VARR& arr_out) {
|
||||||
|
arr_out.clear();
|
||||||
|
this->q = q;
|
||||||
|
is_vertex_query = false;
|
||||||
|
is_edge_query = false;
|
||||||
|
is_face_query = true;
|
||||||
|
|
||||||
|
visibility_region_impl(f, q);
|
||||||
|
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>(geom_traits, q, polygon, arr_out);
|
||||||
|
conditional_regularize(arr_out, Regularization_tag());
|
||||||
|
if (arr_out.faces_begin()->is_unbounded())
|
||||||
|
return ++arr_out.faces_begin();
|
||||||
|
else
|
||||||
|
return arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_attached() {
|
||||||
|
return (p_arr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(const Arrangement_2& arr) {
|
||||||
|
p_arr = &arr;
|
||||||
|
geom_traits = p_arr->geometry_traits();
|
||||||
|
}
|
||||||
|
|
||||||
|
void detach() {
|
||||||
|
p_arr = NULL;
|
||||||
|
geom_traits = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Arrangement_2& arr() {
|
||||||
|
return *p_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//get the neighbor of v along edge e
|
||||||
|
VH get_neighbor(const EH e, const VH v) {
|
||||||
|
if (e->source() == v)
|
||||||
|
return e->target();
|
||||||
|
else
|
||||||
|
return e->source();
|
||||||
|
}
|
||||||
|
//check whether ray(q->dp) intersects segment(p1, p2)
|
||||||
|
bool do_intersect_ray(const Point_2& q,
|
||||||
|
const Point_2& dp,
|
||||||
|
const Point_2& p1,
|
||||||
|
const Point_2& p2) {
|
||||||
|
return (CGAL::orientation(q, dp, p1) != CGAL::orientation(q, dp, p2) && CGAL::orientation(q, p1, dp) == CGAL::orientation(q, p1, p2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//arrange vertices that on a same vision ray in a 'funnel' order
|
||||||
|
void funnel(int i, int j) {
|
||||||
|
VHs right, left;
|
||||||
|
//whether the edges incident to a vertex block the left side and right side of current vision ray.
|
||||||
|
bool block_left(false), block_right(false);
|
||||||
|
VH former = vs[i], nb;
|
||||||
|
for (int l=i; l<j; l++) {
|
||||||
|
bool left_v(false), right_v(false), has_predecessor(false);
|
||||||
|
EHs& edges = incident_edges[vs[l]];
|
||||||
|
for (int k=0; k<edges.size(); k++) {
|
||||||
|
nb = get_neighbor(edges[k], vs[l]);
|
||||||
|
if ( nb == former ) {
|
||||||
|
has_predecessor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (CGAL::left_turn(q, vs[l]->point(), nb->point()))
|
||||||
|
left_v = true;
|
||||||
|
else
|
||||||
|
right_v = CGAL::right_turn(q, vs[l]->point(), nb->point());
|
||||||
|
}
|
||||||
|
if (has_predecessor) {
|
||||||
|
//if the current vertex connects to the vertex before by an edge,
|
||||||
|
//the vertex before can help it to block.
|
||||||
|
block_left = block_left || left_v;
|
||||||
|
block_right = block_right || right_v;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
block_left = left_v;
|
||||||
|
block_right = right_v;
|
||||||
|
}
|
||||||
|
if (block_left && block_right) {
|
||||||
|
//when both sides are blocked, there is no need to change the vertex after.
|
||||||
|
right.push_back(vs[l]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (block_left)
|
||||||
|
left.push_back(vs[l]);
|
||||||
|
else
|
||||||
|
right.push_back(vs[l]);
|
||||||
|
}
|
||||||
|
former = vs[l];
|
||||||
|
}
|
||||||
|
for (int l=0; l!=right.size(); l++)
|
||||||
|
vs[i+l] = right[l];
|
||||||
|
for (int l=0; l!=left.size(); l++)
|
||||||
|
vs[i+l+right.size()] = left[left.size()-1-l];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void visibility_region_impl(const Face_const_handle f, const Point_2& q) {
|
||||||
|
vs.clear();
|
||||||
|
polygon.clear();
|
||||||
|
active_edges = std::set<EH, Closer_edge>(Closer_edge(geom_traits, q));
|
||||||
|
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
|
||||||
|
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
|
||||||
|
|
||||||
|
EHs relevant_edges; //all edges that can affect the visibility of query point.
|
||||||
|
Arrangement_2 bbox;
|
||||||
|
if (is_face_query)
|
||||||
|
input_face(f);
|
||||||
|
else
|
||||||
|
input_face(f, relevant_edges, bbox);
|
||||||
|
//the following code is the initiation of vision ray. the direction of the initial ray is between the direction
|
||||||
|
//from q to last vertex in vs and positive x-axis. By choosing this direction, we make
|
||||||
|
//sure that all plane is swept and there is not needle at the beginning of sweeping.
|
||||||
|
Vector_2 dir;
|
||||||
|
if (Direction_2(-1, 0) < Direction_2(Vector_2(q, vs.back()->point())))
|
||||||
|
dir = Vector_2(1, 0) + Vector_2(q, vs.back()->point());
|
||||||
|
else
|
||||||
|
dir = Vector_2(0, -1);
|
||||||
|
Point_2 dp = q + dir;
|
||||||
|
|
||||||
|
//initiation of active_edges. for face queries, all edges on the boundary can affect visibility.
|
||||||
|
//for non-face queries, only relevant_edges has to be considered.
|
||||||
|
if (is_face_query) {
|
||||||
|
Ccb_halfedge_const_circulator curr = f->outer_ccb();
|
||||||
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
|
do {
|
||||||
|
if (do_intersect_ray(q, dp, curr->target()->point(), curr->source()->point())) {
|
||||||
|
active_edges.insert(curr);
|
||||||
|
}
|
||||||
|
} while (++curr != circ);
|
||||||
|
|
||||||
|
typename Arrangement_2::Hole_const_iterator hi;
|
||||||
|
for (hi = f->holes_begin(); hi != f->holes_end(); ++hi) {
|
||||||
|
Ccb_halfedge_const_circulator curr = circ = *hi;
|
||||||
|
do {
|
||||||
|
if (do_intersect_ray(q, dp, curr->target()->point(), curr->source()->point()))
|
||||||
|
active_edges.insert(curr);
|
||||||
|
} while (++curr != circ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i=0; i!=relevant_edges.size(); i++)
|
||||||
|
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(), relevant_edges[i]->target()->point()))
|
||||||
|
active_edges.insert(relevant_edges[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//angular sweep begins
|
||||||
|
// std::cout<<active_edges.size()<<std::endl;
|
||||||
|
for (int i=0; i!=vs.size(); i++) {
|
||||||
|
VH vh = vs[i];
|
||||||
|
EH closest_e = *active_edges.begin();
|
||||||
|
EHs& edges = incident_edges[vh];
|
||||||
|
EHs insert_ehs, remove_ehs;
|
||||||
|
for (int j=0; j!=edges.size(); j++) {
|
||||||
|
EH& e = edges[j];
|
||||||
|
if (active_edges.find(e) == active_edges.end())
|
||||||
|
insert_ehs.push_back(e);
|
||||||
|
else
|
||||||
|
remove_ehs.push_back(e);
|
||||||
|
}
|
||||||
|
int insert_cnt = insert_ehs.size();
|
||||||
|
int remove_cnt = remove_ehs.size();
|
||||||
|
if (insert_cnt == 1 && remove_cnt == 1) {
|
||||||
|
const EH& ctemp_eh = *active_edges.find(remove_ehs.front());
|
||||||
|
EH& temp_eh = const_cast<EH&>(ctemp_eh);
|
||||||
|
temp_eh = insert_ehs.front();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int j=0; j!=remove_cnt; j++)
|
||||||
|
active_edges.erase(remove_ehs[j]);
|
||||||
|
for (int j=0; j!=insert_cnt; j++)
|
||||||
|
active_edges.insert(insert_ehs[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest_e != *active_edges.begin()) {
|
||||||
|
//when the closest edge changed
|
||||||
|
if (is_face_query) {
|
||||||
|
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||||
|
//some edges are added and some are deleted, which means the vertex swept is part of visibility polygon.
|
||||||
|
update_visibility(vh->point());
|
||||||
|
}
|
||||||
|
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||||
|
//only add some edges, means the view ray is blocked by new edges.
|
||||||
|
//therefore first add the intersection of view ray and former closet edge, then add the vertice swept.
|
||||||
|
update_visibility(ray_seg_intersection(q,
|
||||||
|
vh->point(),
|
||||||
|
closest_e->target()->point(),
|
||||||
|
closest_e->source()->point()));
|
||||||
|
update_visibility(vh->point());
|
||||||
|
}
|
||||||
|
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||||
|
//only delete some edges, means some block is moved and the view ray can reach the segments after the block.
|
||||||
|
update_visibility(vh->point());
|
||||||
|
update_visibility(ray_seg_intersection(q,
|
||||||
|
vh->point(),
|
||||||
|
(*active_edges.begin())->target()->point(),
|
||||||
|
(*active_edges.begin())->source()->point()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//extra work here for edge/vertex query is the index of cone_end1 and cone_end2 will be recorded.
|
||||||
|
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||||
|
//some edges are added and some are deleted, which means the vertice swept is part of visibility polygon.
|
||||||
|
if (update_visibility(vh->point())) {
|
||||||
|
if (vh == cone_end1)
|
||||||
|
cone_end1_idx = polygon.size()-1;
|
||||||
|
else if (vh == cone_end2)
|
||||||
|
cone_end2_idx = polygon.size()-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||||
|
//only add some edges, means the view ray is blocked by new edges.
|
||||||
|
//therefore first add the intersection of view ray and former closet edge, then add the vertice swept.
|
||||||
|
update_visibility(ray_seg_intersection(q,
|
||||||
|
vh->point(),
|
||||||
|
closest_e->target()->point(),
|
||||||
|
closest_e->source()->point()));
|
||||||
|
if (update_visibility(vh->point())) {
|
||||||
|
if (vh == cone_end1)
|
||||||
|
cone_end1_idx = polygon.size()-1;
|
||||||
|
else if (vh == cone_end2)
|
||||||
|
cone_end2_idx = polygon.size()-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||||
|
//only delete some edges, means some block is removed and the vision ray can reach the segments after the block.
|
||||||
|
if (update_visibility(vh->point())) {
|
||||||
|
if (vh == cone_end1)
|
||||||
|
cone_end1_idx = polygon.size()-1;
|
||||||
|
else if (vh == cone_end2)
|
||||||
|
cone_end2_idx = polygon.size()-1;
|
||||||
|
}
|
||||||
|
update_visibility(ray_seg_intersection(q,
|
||||||
|
vh->point(),
|
||||||
|
(*active_edges.begin())->target()->point(),
|
||||||
|
(*active_edges.begin())->source()->point()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_edge(const EH e) {
|
||||||
|
std::cout<<e->source()->point()<<"->"<<e->target()->point()<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compute the intersection of ray(q->dp) and segment(s, t)
|
||||||
|
//if they are collinear then return the endpoint which is closer to q.
|
||||||
|
|
||||||
|
Point_2 ray_seg_intersection(
|
||||||
|
const Point_2& q, const Point_2& dp, // the ray
|
||||||
|
const Point_2& s, const Point_2& t) // the segment
|
||||||
|
{
|
||||||
|
if (CGAL::collinear(q, dp, s)) {
|
||||||
|
if (CGAL::collinear(q, dp, t)) {
|
||||||
|
if (CGAL::compare_distance_to_point(q, s, t)==CGAL::SMALLER)
|
||||||
|
return s;
|
||||||
|
else
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
Ray_2 ray(q,dp);
|
||||||
|
Segment_2 seg(s,t);
|
||||||
|
CGAL::Object result = CGAL::intersection(ray, seg);
|
||||||
|
return *(CGAL::object_cast<Point_2>(&result));
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if p has been discovered before, if not update the visibility polygon
|
||||||
|
bool update_visibility(const Point_2& p){
|
||||||
|
if (polygon.empty()) {
|
||||||
|
polygon.push_back(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p) != EQUAL) {
|
||||||
|
polygon.push_back(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//functor to decide which vertex is swept earlier by the rotational sweeping ray
|
||||||
|
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
|
||||||
|
const Point_2& q;
|
||||||
|
const Geometry_traits_2* geom_traits;
|
||||||
|
public:
|
||||||
|
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits):q(q), geom_traits(traits) {}
|
||||||
|
bool operator() (const VH v1, const VH v2) const {
|
||||||
|
const Point_2& p1 = v1->point();
|
||||||
|
const Point_2& p2 = v2->point();
|
||||||
|
int qua1 = quadrant(q, p1);
|
||||||
|
int qua2 = quadrant(q, p2);
|
||||||
|
if (qua1 < qua2)
|
||||||
|
return true;
|
||||||
|
if (qua1 > qua2)
|
||||||
|
return false;
|
||||||
|
if (collinear(q, p1, p2))
|
||||||
|
return (CGAL::compare_distance_to_point(q, p1, p2) == CGAL::SMALLER);
|
||||||
|
else
|
||||||
|
return CGAL::right_turn(p1, q, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return the quadrant of p with respect to o.
|
||||||
|
int quadrant(const Point_2& o, const Point_2& p) const {
|
||||||
|
typename Geometry_traits_2::Compare_x_2 compare_x = geom_traits->compare_x_2_object();
|
||||||
|
typename Geometry_traits_2::Compare_y_2 compare_y = geom_traits->compare_y_2_object();
|
||||||
|
|
||||||
|
Comparison_result dx = compare_x(p, o);
|
||||||
|
Comparison_result dy = compare_y(p, o);
|
||||||
|
if (dx==LARGER && dy!=SMALLER)
|
||||||
|
return 1;
|
||||||
|
if (dx!=LARGER && dy==LARGER)
|
||||||
|
return 2;
|
||||||
|
if (dx==SMALLER && dy!=LARGER)
|
||||||
|
return 3;
|
||||||
|
if (dx!=SMALLER && dy==SMALLER)
|
||||||
|
return 4;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//when the query point is in face, every edge is good.
|
||||||
|
void input_neighbor_f( const Halfedge_const_handle e) {
|
||||||
|
VH v = e->target();
|
||||||
|
if (!incident_edges.count(v))
|
||||||
|
vs.push_back(v);
|
||||||
|
incident_edges[v].push_back(e);
|
||||||
|
incident_edges[v].push_back(e->next());
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if p is in the visibility cone
|
||||||
|
bool is_in_cone(const Point_2& p) const{
|
||||||
|
if (is_big_cone)
|
||||||
|
return (!CGAL::right_turn(cone_end1->point(), q, p)) || (!CGAL::left_turn(cone_end2->point(), q, p));
|
||||||
|
else
|
||||||
|
return (!CGAL::right_turn(cone_end1->point(), q, p)) && (!CGAL::left_turn(cone_end2->point(), q, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
//for vertex and edge query: the visibility is limited in a cone.
|
||||||
|
void input_edge(const Halfedge_const_handle e,
|
||||||
|
EHs& good_edges) {
|
||||||
|
for (int i=0; i<bad_edges.size(); i++)
|
||||||
|
if (e == bad_edges[i])
|
||||||
|
return;
|
||||||
|
VH v1 = e->target();
|
||||||
|
VH v2 = e->source();
|
||||||
|
//an edge will affect visibility only if it has an endpoint in the visibility cone or it crosses the boundary of the cone.
|
||||||
|
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) || do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point())) {
|
||||||
|
good_edges.push_back(e);
|
||||||
|
if (!incident_edges.count(v1))
|
||||||
|
vs.push_back(v1);
|
||||||
|
incident_edges[v1].push_back(e);
|
||||||
|
if (!incident_edges.count(v2))
|
||||||
|
vs.push_back(v2);
|
||||||
|
incident_edges[v2].push_back(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//for face query: traverse the face to get all edges
|
||||||
|
//and sort vertices in counter-clockwise order.
|
||||||
|
void input_face (Face_const_handle fh)
|
||||||
|
{
|
||||||
|
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||||
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
|
do {
|
||||||
|
assert(curr->face() == fh);
|
||||||
|
input_neighbor_f(curr);
|
||||||
|
} while (++curr != circ);
|
||||||
|
|
||||||
|
typename Arrangement_2::Hole_const_iterator hi;
|
||||||
|
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
|
||||||
|
Ccb_halfedge_const_circulator curr = *hi, circ = *hi;
|
||||||
|
do {
|
||||||
|
assert(curr->face() == fh);
|
||||||
|
input_neighbor_f(curr);
|
||||||
|
} while (++curr != circ);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
|
||||||
|
|
||||||
|
for (int i=0; i!=vs.size(); i++) {
|
||||||
|
int j = i+1;
|
||||||
|
while (j != vs.size()) {
|
||||||
|
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
|
||||||
|
break;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (j-i>1)
|
||||||
|
funnel(i, j);
|
||||||
|
i = j-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//for vertex or edge query: traverse the face to get all edges
|
||||||
|
//and sort vertices in counter-clockwise order.
|
||||||
|
void input_face (Face_const_handle fh,
|
||||||
|
EHs& good_edges,
|
||||||
|
Arrangement_2& bbox)
|
||||||
|
{
|
||||||
|
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||||
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
|
do {
|
||||||
|
assert(curr->face() == fh);
|
||||||
|
input_edge(curr, good_edges);
|
||||||
|
} while (++curr != circ);
|
||||||
|
|
||||||
|
typename Arrangement_2::Hole_const_iterator hi;
|
||||||
|
for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) {
|
||||||
|
Ccb_halfedge_const_circulator curr = circ = *hi;
|
||||||
|
do {
|
||||||
|
assert(curr->face() == fh);
|
||||||
|
input_edge(curr, good_edges);
|
||||||
|
} while (++curr != circ);
|
||||||
|
}
|
||||||
|
|
||||||
|
//create a box that cover all vertices such that during the sweeping, the vision ray will always intersect at least an edge.
|
||||||
|
//this box doesn't intersect any relevant_edge.
|
||||||
|
Points points;
|
||||||
|
for (int i=0; i<vs.size(); i++) {
|
||||||
|
points.push_back(vs[i]->point());
|
||||||
|
}
|
||||||
|
points.push_back(q);
|
||||||
|
//first get the bounding box of all relevant points.
|
||||||
|
typename Geometry_traits_2::Iso_rectangle_2 bb = bounding_box(points.begin(), points.end());
|
||||||
|
|
||||||
|
Number_type xmin, xmax, ymin, ymax;
|
||||||
|
typename Geometry_traits_2::Compute_x_2 compute_x = geom_traits->compute_x_2_object();
|
||||||
|
typename Geometry_traits_2::Compute_y_2 compute_y = geom_traits->compute_y_2_object();
|
||||||
|
|
||||||
|
//make the box a little bigger than bb so that it won't intersect any relevant_edge.
|
||||||
|
xmin = compute_x(bb.min())-1;
|
||||||
|
ymin = compute_y(bb.min())-1;
|
||||||
|
xmax = compute_x(bb.max())+1;
|
||||||
|
ymax = compute_y(bb.max())+1;
|
||||||
|
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
|
||||||
|
Point_2(xmax, ymax), Point_2(xmin, ymax)};
|
||||||
|
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]), bbox.unbounded_face());
|
||||||
|
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]), e1->target());
|
||||||
|
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2], box[3]), e2->target());
|
||||||
|
bbox.insert_at_vertices(Segment_2(box[0], box[3]), e1->source(), e3->target());
|
||||||
|
|
||||||
|
circ = curr = e1->face()->outer_ccb();
|
||||||
|
do {
|
||||||
|
VH v = curr->target();
|
||||||
|
vs.push_back(v);
|
||||||
|
incident_edges[v].push_back(curr);
|
||||||
|
incident_edges[v].push_back(curr->next());
|
||||||
|
good_edges.push_back(curr);
|
||||||
|
} while(++curr != circ);
|
||||||
|
|
||||||
|
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
|
||||||
|
|
||||||
|
for (int i=0; i!=vs.size(); i++) {
|
||||||
|
int j = i+1;
|
||||||
|
while (j != vs.size()) {
|
||||||
|
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
|
||||||
|
break;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (j-i>1)
|
||||||
|
funnel(i, j);
|
||||||
|
i = j-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
|
||||||
|
regularize_output(arr_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
void conditional_regularize(VARR& arr_out, CGAL::Tag_false) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
void regularize_output(VARR& arr_out) {
|
||||||
|
typename VARR::Edge_iterator e_itr;
|
||||||
|
for (e_itr = arr_out.edges_begin();
|
||||||
|
e_itr != arr_out.edges_end();
|
||||||
|
e_itr++) {
|
||||||
|
if (e_itr->face() == e_itr->twin()->face())
|
||||||
|
arr_out.remove_edge(e_itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end namespace CGAL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,715 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$`
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
// Ning Xu <longyin0904@gmail.com>
|
||||||
|
|
||||||
|
#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
|
||||||
|
#define CGAL_SIMPLE_POLYGON_VISIBILITY_2_H
|
||||||
|
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/tags.h>
|
||||||
|
#include <CGAL/enum.h>
|
||||||
|
#include <CGAL/Visibility_2/visibility_utils.h>
|
||||||
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
|
#include <stack>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
template<class Arrangement_2_, class RegularizationTag = CGAL::Tag_true>
|
||||||
|
class Simple_polygon_visibility_2 {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Currently only consider with same type for both
|
||||||
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Geometry_traits_2::Kernel K;
|
||||||
|
|
||||||
|
typedef typename Arrangement_2::Halfedge_const_handle
|
||||||
|
Halfedge_const_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
|
Ccb_halfedge_const_circulator;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
|
||||||
|
Halfedge_around_vertex_const_circulator;
|
||||||
|
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||||
|
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||||
|
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
typedef CGAL::Tag_false Supports_general_polygon_tag;
|
||||||
|
typedef CGAL::Tag_true Supports_simple_polygon_tag;
|
||||||
|
|
||||||
|
Simple_polygon_visibility_2() : p_arr(NULL), geom_traits(NULL) {};
|
||||||
|
|
||||||
|
/*! Constructor given an arrangement and the Regularization tag. */
|
||||||
|
Simple_polygon_visibility_2(const Arrangement_2& arr):
|
||||||
|
p_arr(&arr) {
|
||||||
|
geom_traits = p_arr->geometry_traits();
|
||||||
|
query_pt_is_vertex = false;
|
||||||
|
query_pt_is_on_halfedge = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string name(){return std::string("S_visibility_2");}
|
||||||
|
|
||||||
|
/*! Method to check if the visibility object is attached or not to
|
||||||
|
an arrangement*/
|
||||||
|
bool is_attached() {
|
||||||
|
return (p_arr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Attaches the visibility object to the 'arr' arrangement */
|
||||||
|
void attach(const Arrangement_2& arr) {
|
||||||
|
p_arr = &arr;
|
||||||
|
geom_traits = p_arr->geometry_traits();
|
||||||
|
query_pt_is_vertex = false;
|
||||||
|
query_pt_is_on_halfedge = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Detaches the visibility object from the arrangement it is
|
||||||
|
attached to*/
|
||||||
|
void detach() {
|
||||||
|
p_arr = NULL;
|
||||||
|
geom_traits = NULL;
|
||||||
|
vertices.clear();
|
||||||
|
query_pt_is_vertex = false;
|
||||||
|
query_pt_is_on_halfedge = false;
|
||||||
|
p_cdt = boost::shared_ptr<CDT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Getter method for the input arrangement*/
|
||||||
|
const Arrangement_2& arr() {
|
||||||
|
return *p_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Computes the visibility object from the query point 'q' in the face
|
||||||
|
'face' and constructs the output in 'out_arr'*/
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q,
|
||||||
|
const Face_const_handle face,
|
||||||
|
VARR& out_arr) {
|
||||||
|
|
||||||
|
assert(query_pt_is_vertex == false);
|
||||||
|
assert(query_pt_is_on_halfedge == false);
|
||||||
|
|
||||||
|
// Now retrieve the circulator to first visible vertex from triangulation
|
||||||
|
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
|
||||||
|
Ccb_halfedge_const_circulator curr = circ;
|
||||||
|
Halfedge_const_handle he;
|
||||||
|
|
||||||
|
do {
|
||||||
|
he = curr;
|
||||||
|
vertices.push_back(he->source()->point());
|
||||||
|
} while(++curr != circ);
|
||||||
|
|
||||||
|
vertices.push_back(vertices[0]);
|
||||||
|
|
||||||
|
visibility_region_impl(q);
|
||||||
|
|
||||||
|
typename std::vector<Point_2> points;
|
||||||
|
while (!s.empty()) {
|
||||||
|
Point_2 curr_point = s.top();
|
||||||
|
points.push_back(curr_point);
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::reverse(points.begin(), points.end());
|
||||||
|
|
||||||
|
CGAL::Visibility_2::report_while_handling_needles
|
||||||
|
<Simple_polygon_visibility_2>(geom_traits,
|
||||||
|
q,
|
||||||
|
points,
|
||||||
|
out_arr);
|
||||||
|
|
||||||
|
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
||||||
|
CGAL_precondition(s.size() == 0);
|
||||||
|
conditional_regularize(out_arr, Regularization_tag());
|
||||||
|
vertices.clear();
|
||||||
|
if (out_arr.faces_begin()->is_unbounded()) {
|
||||||
|
return ++out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Computes the visibility region of the query point 'q' located on the
|
||||||
|
halfedge 'he' and constructs the output in 'out_arr'*/
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(
|
||||||
|
const Point_2& q,
|
||||||
|
const Halfedge_const_handle he,
|
||||||
|
VARR& out_arr )
|
||||||
|
{
|
||||||
|
query_pt_is_vertex = false;
|
||||||
|
query_pt_is_on_halfedge = false;
|
||||||
|
bool query_on_target = false;
|
||||||
|
|
||||||
|
if (q != he->source()->point()) {
|
||||||
|
if (q != he->target()->point()) {
|
||||||
|
vertices.push_back(he->target()->point());
|
||||||
|
query_pt_is_on_halfedge = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
query_pt_is_vertex = true;
|
||||||
|
query_on_target = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vertices.push_back( he->target()->point() );
|
||||||
|
query_pt_is_vertex = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ccb_halfedge_const_circulator circ = he;
|
||||||
|
circ++;
|
||||||
|
Ccb_halfedge_const_circulator curr = circ;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Halfedge_const_handle he_handle = curr;
|
||||||
|
Point_2 curr_vertex = he_handle->target()->point();
|
||||||
|
vertices.push_back(curr_vertex);
|
||||||
|
} while (++curr != circ);
|
||||||
|
|
||||||
|
if ( query_on_target ) {
|
||||||
|
vertices.push_back( vertices[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
visibility_region_impl(q);
|
||||||
|
|
||||||
|
typename std::vector<Point_2> points;
|
||||||
|
if (!s.empty()) {
|
||||||
|
Point_2 prev_pt = s.top();
|
||||||
|
if (prev_pt != q) {
|
||||||
|
points.push_back(prev_pt);
|
||||||
|
}
|
||||||
|
else if (query_pt_is_vertex) {
|
||||||
|
points.push_back(prev_pt);
|
||||||
|
}
|
||||||
|
if (!s.empty()) {
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
while(!s.empty()) {
|
||||||
|
Point_2 curr_pt = s.top();
|
||||||
|
if (curr_pt != q) {
|
||||||
|
points.push_back(curr_pt);
|
||||||
|
}
|
||||||
|
else if (query_pt_is_vertex) {
|
||||||
|
points.push_back(curr_pt);
|
||||||
|
}
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::reverse(points.begin(), points.end());
|
||||||
|
|
||||||
|
CGAL::Visibility_2::report_while_handling_needles
|
||||||
|
<Simple_polygon_visibility_2>(geom_traits,
|
||||||
|
q,
|
||||||
|
points,
|
||||||
|
out_arr);
|
||||||
|
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
||||||
|
CGAL_precondition(s.size() == 0);
|
||||||
|
conditional_regularize(out_arr, Regularization_tag());
|
||||||
|
vertices.clear();
|
||||||
|
if (out_arr.faces_begin()->is_unbounded()) {
|
||||||
|
return ++out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
||||||
|
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
|
||||||
|
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||||
|
typedef CGAL::No_intersection_tag Itag;
|
||||||
|
typedef CGAL::Constrained_triangulation_2<K, TDS, Itag> CDT;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Arrangement_2 *p_arr;
|
||||||
|
/*! Boost pointer to the constrained Delaunay triangulation object*/
|
||||||
|
boost::shared_ptr<CDT> p_cdt;
|
||||||
|
/*! Mapping of the vertices of the input to the corresponding circulator
|
||||||
|
needed for finding the first visible vertex in case of face queries*/
|
||||||
|
std::map<Point_2, typename Arrangement_2::Ccb_halfedge_const_circulator>
|
||||||
|
point_itr_map;
|
||||||
|
const Geometry_traits_2 *geom_traits;
|
||||||
|
/*! Stack of visibile points; manipulated when going through the sequence
|
||||||
|
of input vertices; contains the vertices of the visibility region after
|
||||||
|
the run of the algorithm*/
|
||||||
|
std::stack<Point_2> s;
|
||||||
|
/*! Sequence of input vertices*/
|
||||||
|
std::vector<Point_2> vertices;
|
||||||
|
/*! State of visibility region algorithm*/
|
||||||
|
enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
|
||||||
|
bool query_pt_is_vertex;
|
||||||
|
bool query_pt_is_on_halfedge;
|
||||||
|
|
||||||
|
/*! Regularize output if flag is set to true*/
|
||||||
|
template <typename VARR>
|
||||||
|
void conditional_regularize(VARR& out_arr, CGAL::Tag_true) {
|
||||||
|
regularize_output(out_arr);
|
||||||
|
}
|
||||||
|
/*! No need to regularize output if flag is set to false*/
|
||||||
|
template <typename VARR>
|
||||||
|
void conditional_regularize(VARR& out_arr, CGAL::Tag_false) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Regularizes the output - removes edges that have the same face on both
|
||||||
|
sides */
|
||||||
|
template <typename VARR>
|
||||||
|
void regularize_output(VARR& out_arr) {
|
||||||
|
typename VARR::Edge_iterator e_itr;
|
||||||
|
for (e_itr = out_arr.edges_begin() ;
|
||||||
|
e_itr != out_arr.edges_end() ; e_itr++) {
|
||||||
|
|
||||||
|
typename VARR::Halfedge_handle he = e_itr;
|
||||||
|
typename VARR::Halfedge_handle he_twin = he->twin();
|
||||||
|
if (he->face() == he_twin->face()) {
|
||||||
|
out_arr.remove_edge(he);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Initialized the constrained Delaunay triangulation using the edges of
|
||||||
|
the outer boundary of 'face' */
|
||||||
|
void init_cdt(const Face_const_handle &face) {
|
||||||
|
|
||||||
|
std::vector<std::pair<Point_2,Point_2> > constraints;
|
||||||
|
typename Arrangement_2::Ccb_halfedge_const_circulator circ =
|
||||||
|
face->outer_ccb();
|
||||||
|
typename Arrangement_2::Ccb_halfedge_const_circulator curr = circ;
|
||||||
|
typename Arrangement_2::Halfedge_const_handle he;
|
||||||
|
|
||||||
|
do {
|
||||||
|
he = curr;
|
||||||
|
Point_2 source = he->source()->point();
|
||||||
|
Point_2 target = he->target()->point();
|
||||||
|
point_itr_map.insert(std::make_pair(source, curr));
|
||||||
|
constraints.push_back(std::make_pair(source,target));
|
||||||
|
} while(++curr != circ);
|
||||||
|
|
||||||
|
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),constraints.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Finds a visible vertex from the query point 'q' in 'face'
|
||||||
|
to start the algorithm from*/
|
||||||
|
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face, const Point_2 &q) {
|
||||||
|
init_cdt(face);
|
||||||
|
typename CDT::Face_handle fh = p_cdt->locate(q);
|
||||||
|
Point_2 start_point = fh->vertex(0)->point();
|
||||||
|
|
||||||
|
// Now retrieve the circulator to first visible vertex from triangulation
|
||||||
|
Ccb_halfedge_const_circulator circ = point_itr_map[start_point];
|
||||||
|
Halfedge_const_handle he_curr = circ;
|
||||||
|
|
||||||
|
Halfedge_around_vertex_const_circulator incident_circ = he_curr->source()->incident_halfedges();
|
||||||
|
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Ccb_halfedge_const_circulator curr_inc = incident_curr;
|
||||||
|
Halfedge_const_handle he_curr_inc = curr_inc;
|
||||||
|
|
||||||
|
if (he_curr_inc->face() == face) {
|
||||||
|
Ccb_halfedge_const_circulator incident_next = incident_curr;
|
||||||
|
incident_next++;
|
||||||
|
Halfedge_const_handle he_next_inc = incident_next;
|
||||||
|
|
||||||
|
if (CGAL::Visibility_2::orientation_2(geom_traits,
|
||||||
|
he_curr_inc->source()->point(),
|
||||||
|
he_curr_inc->target()->point(),
|
||||||
|
q) == CGAL::LEFT_TURN
|
||||||
|
|| CGAL::Visibility_2::orientation_2(geom_traits,
|
||||||
|
he_next_inc->source()->point(),
|
||||||
|
he_next_inc->target()->point(),
|
||||||
|
q) == CGAL::LEFT_TURN) {
|
||||||
|
Ccb_halfedge_const_circulator result_circ = incident_next;
|
||||||
|
Halfedge_const_handle he_print = result_circ;
|
||||||
|
return result_circ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++incident_curr != incident_circ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Main method of the algorithm - initializes the stack and variables
|
||||||
|
and calles the corresponding methods acc. to the algorithm's state;
|
||||||
|
'q' - query point;
|
||||||
|
'i' - current vertex' index
|
||||||
|
'w' - endpoint of ray shot from query point */
|
||||||
|
void visibility_region_impl(const Point_2& q) {
|
||||||
|
int i = 0;
|
||||||
|
Point_2 w;
|
||||||
|
CGAL::Orientation orient = CGAL::Visibility_2::orientation_2(geom_traits,
|
||||||
|
q,
|
||||||
|
vertices[0],
|
||||||
|
vertices[1]);
|
||||||
|
if ( orient != CGAL::RIGHT_TURN ) {
|
||||||
|
upcase = LEFT;
|
||||||
|
i = 1;
|
||||||
|
w = vertices[1];
|
||||||
|
s.push(vertices[0]);
|
||||||
|
s.push(vertices[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
upcase = SCANA;
|
||||||
|
i = 1;
|
||||||
|
w = vertices[1];
|
||||||
|
s.push(vertices[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ray_2 ray_origin( q, vertices[0] );
|
||||||
|
do {
|
||||||
|
switch(upcase) {
|
||||||
|
case LEFT:
|
||||||
|
left(i, w, q);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
right(i, w, q);
|
||||||
|
break;
|
||||||
|
case SCANA:
|
||||||
|
scana(i, w, q);
|
||||||
|
break;
|
||||||
|
case SCANB:
|
||||||
|
scanb(i, w, q);
|
||||||
|
break;
|
||||||
|
case SCANC:
|
||||||
|
scanc(i, w, q);
|
||||||
|
break;
|
||||||
|
case SCAND:
|
||||||
|
scand(i, w, q);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( upcase == LEFT ) {
|
||||||
|
Point_2 s_t = s.top();
|
||||||
|
s.pop();
|
||||||
|
if ( ( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, q, vertices[0], s.top() ) == CGAL::RIGHT_TURN ) &&
|
||||||
|
( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, q, vertices[0],s_t ) == CGAL::LEFT_TURN ) ) {
|
||||||
|
Segment_2 seg( s.top(), s_t );
|
||||||
|
if ( CGAL::Visibility_2::do_intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Ray_2>
|
||||||
|
( geom_traits, seg, ray_origin ) ) {
|
||||||
|
Object_2 result = CGAL::Visibility_2::intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Ray_2>
|
||||||
|
( geom_traits, seg, ray_origin );
|
||||||
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
|
assert( ipoint != NULL );
|
||||||
|
s_t = *ipoint;
|
||||||
|
upcase = SCANB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.push( s_t );
|
||||||
|
}
|
||||||
|
} while(upcase != FINISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Method that handles the left turns in the vertex algorithm */
|
||||||
|
void left(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
if (i >= vertices.size() - 1) {
|
||||||
|
upcase = FINISH;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Point_2 s_t = s.top();
|
||||||
|
s.pop();
|
||||||
|
Point_2 s_t_prev = s.top();
|
||||||
|
s.push( s_t );
|
||||||
|
CGAL::Orientation orient1 = CGAL::Visibility_2::orientation_2
|
||||||
|
<Geometry_traits_2>
|
||||||
|
( geom_traits,
|
||||||
|
query_pt,
|
||||||
|
vertices[i],
|
||||||
|
vertices[i+1] );
|
||||||
|
if ( orient1 != CGAL::RIGHT_TURN ) {
|
||||||
|
// Case L2
|
||||||
|
upcase = LEFT;
|
||||||
|
s.push( vertices[i+1] );
|
||||||
|
w = vertices[i+1];
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
CGAL::Orientation orient2 = CGAL::Visibility_2::orientation_2
|
||||||
|
<Geometry_traits_2>
|
||||||
|
( geom_traits,
|
||||||
|
s_t_prev,
|
||||||
|
vertices[i],
|
||||||
|
vertices[i+1] );
|
||||||
|
if ( orient2 == CGAL::RIGHT_TURN ) {
|
||||||
|
// Case L3
|
||||||
|
upcase = SCANA;
|
||||||
|
w = vertices[i+1];
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
// Case L4
|
||||||
|
upcase = RIGHT;
|
||||||
|
w = vertices[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Scans the stack such that all vertices that were pushed before to the
|
||||||
|
stack and are now not visible anymore. */
|
||||||
|
void right(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
Point_2 s_j;
|
||||||
|
Point_2 s_j_prev;
|
||||||
|
Point_2 u;
|
||||||
|
int mode = 0;
|
||||||
|
CGAL::Orientation orient1, orient2;
|
||||||
|
|
||||||
|
s_j_prev = s.top();
|
||||||
|
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, query_pt, s_j_prev, vertices[i] );
|
||||||
|
while ( s.size() > 1 ) {
|
||||||
|
s_j = s_j_prev;
|
||||||
|
orient1 = orient2;
|
||||||
|
s.pop();
|
||||||
|
s_j_prev = s.top();
|
||||||
|
|
||||||
|
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, query_pt, s_j_prev, vertices[i] );
|
||||||
|
if ( orient1 != CGAL::LEFT_TURN && orient2 != CGAL::RIGHT_TURN ) {
|
||||||
|
mode = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Segment_2 seg2( vertices[i-1], vertices[i] );
|
||||||
|
Segment_2 seg( s_j_prev, s_j );
|
||||||
|
if ( ( vertices[i-1] != s_j )
|
||||||
|
&& ( CGAL::Visibility_2::do_intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Segment_2>
|
||||||
|
(geom_traits, seg, seg2) ) ) {
|
||||||
|
Object_2 result = CGAL::Visibility_2::intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Segment_2>( geom_traits, seg, seg2 );
|
||||||
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
|
assert( ipoint != NULL );
|
||||||
|
u = *ipoint;
|
||||||
|
mode = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( mode != 0 );
|
||||||
|
if ( mode == 1 ) {
|
||||||
|
orient1 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, query_pt, vertices[i], vertices[i+1] );
|
||||||
|
orient2 = CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
|
( geom_traits, vertices[i-1], vertices[i], vertices[i+1] );
|
||||||
|
if ( orient1 == CGAL::RIGHT_TURN ) {
|
||||||
|
// Case R1
|
||||||
|
// Since the next action is RIGHT, we do not compute the intersection
|
||||||
|
// of (s_j,s_j_prev) and the ray (query_pt, vertices[i]),
|
||||||
|
// thus, (s_j,s_j_prev) is not shortcutted, but it is harmless
|
||||||
|
upcase = RIGHT;
|
||||||
|
s.push( s_j );
|
||||||
|
w = vertices[i];
|
||||||
|
i++;
|
||||||
|
} else if ( orient2 == CGAL::RIGHT_TURN ) {
|
||||||
|
// Case R2
|
||||||
|
Ray_2 ray( query_pt, vertices[i] );
|
||||||
|
Segment_2 seg( s_j_prev, s_j );
|
||||||
|
Object_2 result = CGAL::Visibility_2::intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Ray_2>
|
||||||
|
( geom_traits, seg, ray );
|
||||||
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
|
assert( ipoint != NULL );
|
||||||
|
u = *ipoint;
|
||||||
|
if ( s.top() != u ) {
|
||||||
|
s.push( u );
|
||||||
|
}
|
||||||
|
upcase = LEFT;
|
||||||
|
s.push( vertices[i] );
|
||||||
|
s.push( vertices[i+1] );
|
||||||
|
w = vertices[i+1];
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
// Case R3
|
||||||
|
Ray_2 ray( query_pt, vertices[i] );
|
||||||
|
Segment_2 seg( s_j_prev, s_j );
|
||||||
|
Object_2 result = CGAL::Visibility_2::intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Ray_2>
|
||||||
|
( geom_traits, seg, ray );
|
||||||
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
|
assert( ipoint != NULL );
|
||||||
|
u = *ipoint;
|
||||||
|
if ( s.top() != u ) {
|
||||||
|
s.push( u );
|
||||||
|
}
|
||||||
|
upcase = SCANC;
|
||||||
|
w = vertices[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else if ( mode == 2 ) {
|
||||||
|
// Case R4
|
||||||
|
upcase = SCAND;
|
||||||
|
w = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Scans the vertices starting from index 'i' for the first visible vertex
|
||||||
|
out of the back hidden window */
|
||||||
|
void scana(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
|
||||||
|
Point_2 u;
|
||||||
|
int k = scan_edges( i, query_pt, s.top(), u, true );
|
||||||
|
|
||||||
|
CGAL::Orientation orient1 = CGAL::Visibility_2::orientation_2
|
||||||
|
<Geometry_traits_2>
|
||||||
|
( geom_traits,
|
||||||
|
query_pt,
|
||||||
|
vertices[k],
|
||||||
|
vertices[k+1] );
|
||||||
|
if ( orient1 == CGAL::RIGHT_TURN ) {
|
||||||
|
bool fwd = CGAL::Visibility_2::collinear_are_ordered_along_line_2
|
||||||
|
<Geometry_traits_2>
|
||||||
|
( geom_traits, query_pt, s.top(), u );
|
||||||
|
if ( !fwd ) {
|
||||||
|
// Case A1
|
||||||
|
upcase = RIGHT;
|
||||||
|
i = k+1;
|
||||||
|
w = u;
|
||||||
|
} else {
|
||||||
|
// Case A2
|
||||||
|
upcase = SCAND;
|
||||||
|
i = k+1;
|
||||||
|
w = u;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Case A3
|
||||||
|
upcase = LEFT;
|
||||||
|
i = k+1;
|
||||||
|
s.push( u );
|
||||||
|
if ( u != vertices[k+1] ) {
|
||||||
|
s.push( vertices[k+1] );
|
||||||
|
}
|
||||||
|
w = vertices[k+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Find the first edge interecting the segment (v_0, s_t) */
|
||||||
|
void scanb(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
if ( i == vertices.size() - 1 ) {
|
||||||
|
upcase = FINISH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Point_2 u;
|
||||||
|
int k = scan_edges( i, s.top(), vertices[0], u, false );
|
||||||
|
if ( (k+1 == vertices.size()-1) && (vertices[0] == u) ) {
|
||||||
|
// Case B1
|
||||||
|
upcase = FINISH;
|
||||||
|
s.push( vertices[0] );
|
||||||
|
} else {
|
||||||
|
// Case B2
|
||||||
|
upcase = RIGHT;
|
||||||
|
i = k+1;
|
||||||
|
w = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Finds the exit from a general front hidden window by finding the first
|
||||||
|
vertex to the right of the ray defined by the query_point and w*/
|
||||||
|
void scanc(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
Point_2 u;
|
||||||
|
int k = scan_edges( i, s.top(), w, u, false );
|
||||||
|
upcase = RIGHT;
|
||||||
|
i = k+1;
|
||||||
|
w = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! find the first edge intersecting the given window (s_t, w) */
|
||||||
|
void scand(int& i, Point_2& w, const Point_2& query_pt) {
|
||||||
|
Point_2 u;
|
||||||
|
int k = scan_edges( i, s.top(), w, u, false );
|
||||||
|
upcase = LEFT;
|
||||||
|
i = k+1;
|
||||||
|
s.push( u );
|
||||||
|
if ( u != vertices[k+1] ) {
|
||||||
|
s.push( vertices[k+1] );
|
||||||
|
}
|
||||||
|
w = vertices[k+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
|
||||||
|
or given segment. is_ray = true -> ray, false -> segment.
|
||||||
|
The intersection point is returned by u */
|
||||||
|
int scan_edges( int i, const Point_2& ray_begin, const Point_2& ray_end, Point_2& u, bool is_ray ) {
|
||||||
|
CGAL::Orientation old_orient = CGAL::RIGHT_TURN;
|
||||||
|
Ray_2 ray( ray_begin, ray_end );
|
||||||
|
Segment_2 s2( ray_begin, ray_end );
|
||||||
|
int k;
|
||||||
|
Object_2 result;
|
||||||
|
for ( k = i; k+1 < vertices.size(); k++ ) {
|
||||||
|
CGAL::Orientation curr_orient = CGAL::Visibility_2::orientation_2
|
||||||
|
( geom_traits,
|
||||||
|
ray_begin,
|
||||||
|
ray_end,
|
||||||
|
vertices[k+1] );
|
||||||
|
if ( curr_orient != old_orient ) {
|
||||||
|
// Orientation switch, an intersection may occur
|
||||||
|
Segment_2 seg( vertices[k], vertices[k+1] );
|
||||||
|
if ( is_ray ) {
|
||||||
|
if (CGAL::Visibility_2::do_intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Ray_2>
|
||||||
|
(geom_traits, seg, ray) ) {
|
||||||
|
result = CGAL::Visibility_2::intersect_2
|
||||||
|
< Geometry_traits_2, Segment_2, Ray_2 >
|
||||||
|
( geom_traits, seg, ray );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (CGAL::Visibility_2::do_intersect_2
|
||||||
|
<Geometry_traits_2, Segment_2, Segment_2>
|
||||||
|
(geom_traits, seg, s2) ) {
|
||||||
|
result = CGAL::Visibility_2::intersect_2
|
||||||
|
< Geometry_traits_2, Segment_2, Segment_2 >
|
||||||
|
( geom_traits, seg, s2 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_orient = curr_orient;
|
||||||
|
}
|
||||||
|
assert( k+1<vertices.size() );
|
||||||
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>( &result );
|
||||||
|
if ( ipoint ) {
|
||||||
|
u = *ipoint;
|
||||||
|
} else {
|
||||||
|
u = vertices[k+1];
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CGAL
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,579 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
||||||
|
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
||||||
|
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
template<class Arrangement_2_ , class RegularizationTag = CGAL::Tag_true >
|
||||||
|
class Triangular_expansion_visibility_2 {
|
||||||
|
typedef typename Arrangement_2_::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Geometry_traits_2::Kernel K;
|
||||||
|
public:
|
||||||
|
// Currently only consider with same type for both
|
||||||
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||||
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
|
Ccb_halfedge_const_circulator;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
|
|
||||||
|
typedef typename K::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||||
|
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||||
|
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
typedef RegularizationTag Regularization_tag;
|
||||||
|
|
||||||
|
typedef CGAL::Tag_true Supports_general_polygon_tag;
|
||||||
|
typedef CGAL::Tag_true Supports_simple_polygon_tag;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
||||||
|
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
|
||||||
|
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||||
|
typedef CGAL::No_intersection_tag Itag;
|
||||||
|
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const std::string name(){return std::string("T_visibility_2");}
|
||||||
|
private:
|
||||||
|
const Arrangement_2* p_arr;
|
||||||
|
boost::shared_ptr<CDT> p_cdt;
|
||||||
|
std::vector<Segment_2> needles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Triangular_expansion_visibility_2() : p_arr(NULL){}
|
||||||
|
|
||||||
|
/*! Constructor given an arrangement and the Regularization tag. */
|
||||||
|
Triangular_expansion_visibility_2 (const Arrangement_2& arr)
|
||||||
|
: p_arr(&arr){
|
||||||
|
init_cdt();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_attached() {
|
||||||
|
//std::cout << "is_attached" << std::endl;
|
||||||
|
return (p_arr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach(const Arrangement_2& arr) {
|
||||||
|
// todo observe changes in arr;
|
||||||
|
if(p_arr != &arr){
|
||||||
|
p_arr = &arr;
|
||||||
|
init_cdt();
|
||||||
|
}
|
||||||
|
//std::cout << "attach done" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void detach() {
|
||||||
|
//std::cout << "detach" << std::endl;
|
||||||
|
p_arr = NULL;
|
||||||
|
p_cdt = boost::shared_ptr<CDT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Arrangement_2& arr() {
|
||||||
|
return *p_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i){
|
||||||
|
return std::make_pair(fh,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point_2 ray_seg_intersection(
|
||||||
|
const Point_2& q, const Point_2& b, // the ray
|
||||||
|
const Point_2& s, const Point_2& t) // the segment
|
||||||
|
{
|
||||||
|
Ray_2 ray(q,b);
|
||||||
|
Segment_2 seg(s,t);
|
||||||
|
assert(typename K::Do_intersect_2()(ray,seg));
|
||||||
|
CGAL::Object obj = typename K::Intersect_2()(ray,seg);
|
||||||
|
Point_2 result = object_cast<Point_2>(obj);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect_needle(
|
||||||
|
const Point_2& q,
|
||||||
|
const typename CDT::Vertex_handle vh,
|
||||||
|
const typename CDT::Face_handle fh,
|
||||||
|
int index){
|
||||||
|
|
||||||
|
|
||||||
|
// the expanded edge should not be constrained
|
||||||
|
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||||
|
assert(!p_cdt->is_infinite(fh));
|
||||||
|
// go into the new face
|
||||||
|
const typename CDT::Face_handle nfh(fh->neighbor(index));
|
||||||
|
assert(!p_cdt->is_infinite(nfh));
|
||||||
|
|
||||||
|
// get indices of neighbors
|
||||||
|
int nindex = nfh->index(fh); // index of new vertex and old face
|
||||||
|
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
|
||||||
|
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
|
||||||
|
|
||||||
|
// get vertices seen from entering edge
|
||||||
|
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
|
||||||
|
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
|
||||||
|
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
|
||||||
|
assert(!p_cdt->is_infinite(nvh));
|
||||||
|
assert(!p_cdt->is_infinite(lvh));
|
||||||
|
assert(!p_cdt->is_infinite(rvh));
|
||||||
|
|
||||||
|
// get edges seen from entering edge
|
||||||
|
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
|
||||||
|
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
|
||||||
|
|
||||||
|
// do orientation computation once for new vertex
|
||||||
|
typename K::Orientation_2 orientation =
|
||||||
|
p_cdt->geom_traits().orientation_2_object();
|
||||||
|
CGAL::Orientation orient = orientation(q,vh->point(),nvh->point());
|
||||||
|
|
||||||
|
|
||||||
|
//std::cout << "\n collect_needle" <<std::endl;
|
||||||
|
//std::cout << "q "<< q << std::endl ;
|
||||||
|
//std::cout << "vh->point() "<< vh->point() << std::endl;
|
||||||
|
//std::cout << "lvh->point() "<< lvh->point() << std::endl ;
|
||||||
|
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
|
||||||
|
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
switch ( orient ) {
|
||||||
|
case CGAL::COUNTERCLOCKWISE:
|
||||||
|
// looking on to the right edge
|
||||||
|
if(p_cdt->is_constrained(re)){
|
||||||
|
if(vh!=rvh){
|
||||||
|
Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),rvh->point());
|
||||||
|
//std::cout << vh->point() <<" -1- "<< p <<std::endl;
|
||||||
|
needles.push_back(Segment_2(vh->point(),p));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
collect_needle(q,vh,nfh,rindex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CGAL::CLOCKWISE:
|
||||||
|
// looking on to the left edge
|
||||||
|
if(p_cdt->is_constrained(le)){
|
||||||
|
if(vh!=lvh){
|
||||||
|
Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),lvh->point());
|
||||||
|
//std::cout << vh->point() <<" -2- "<< p <<std::endl;
|
||||||
|
needles.push_back(Segment_2(vh->point(),p));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
collect_needle(q,vh,nfh,lindex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(orient == CGAL::COLLINEAR);
|
||||||
|
// looking on nvh, so it must be reported
|
||||||
|
// if it wasn't already (triangles rotate around vh)
|
||||||
|
if(vh != nvh){
|
||||||
|
//std::cout << vh->point() <<" -3- "<< nvh->point() <<std::endl;
|
||||||
|
needles.push_back(Segment_2(vh->point(),nvh->point()));
|
||||||
|
}
|
||||||
|
// but we may also contiue looking along the vertex
|
||||||
|
if(!p_cdt->is_constrained(re)){
|
||||||
|
collect_needle(q,nvh,nfh,rindex);
|
||||||
|
}
|
||||||
|
if(!p_cdt->is_constrained(le)){
|
||||||
|
collect_needle(q,nvh,nfh,lindex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<class OIT>
|
||||||
|
OIT expand_edge(
|
||||||
|
const Point_2& q,
|
||||||
|
const Point_2& left,
|
||||||
|
const Point_2& right,
|
||||||
|
typename CDT::Face_handle fh,
|
||||||
|
int index,
|
||||||
|
OIT oit){
|
||||||
|
|
||||||
|
// the expanded edge should not be constrained
|
||||||
|
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||||
|
assert(!p_cdt->is_infinite(fh));
|
||||||
|
|
||||||
|
// go into the new face
|
||||||
|
const typename CDT::Face_handle nfh(fh->neighbor(index));
|
||||||
|
assert(!p_cdt->is_infinite(nfh));
|
||||||
|
|
||||||
|
// get indices of neighbors
|
||||||
|
int nindex = nfh->index(fh); // index of new vertex and old face
|
||||||
|
int rindex = p_cdt->ccw(nindex); // index of face behind right edge
|
||||||
|
int lindex = p_cdt-> cw(nindex); // index of face behind left edge
|
||||||
|
|
||||||
|
// get vertices seen from entering edge
|
||||||
|
const typename CDT::Vertex_handle nvh(nfh->vertex(nindex));
|
||||||
|
const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex)));
|
||||||
|
const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex)));
|
||||||
|
assert(!p_cdt->is_infinite(nvh));
|
||||||
|
assert(!p_cdt->is_infinite(lvh));
|
||||||
|
assert(!p_cdt->is_infinite(rvh));
|
||||||
|
|
||||||
|
// get edges seen from entering edge
|
||||||
|
typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex));
|
||||||
|
typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex));
|
||||||
|
|
||||||
|
// do orientation computation once for new vertex
|
||||||
|
typename K::Orientation_2 orientation =
|
||||||
|
p_cdt->geom_traits().orientation_2_object();
|
||||||
|
CGAL::Orientation ro = orientation(q,right,nvh->point());
|
||||||
|
CGAL::Orientation lo = orientation(q,left ,nvh->point());
|
||||||
|
|
||||||
|
assert(typename K::Orientation_2()(q,left ,lvh->point()) != CGAL::CLOCKWISE);
|
||||||
|
assert(typename K::Orientation_2()(q,right,rvh->point()) != CGAL::COUNTERCLOCKWISE);
|
||||||
|
|
||||||
|
//std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " << (lo == CGAL::CLOCKWISE) << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//right edge is seen if new vertex is counter clockwise of right boarder
|
||||||
|
if(ro == CGAL::COUNTERCLOCKWISE){
|
||||||
|
if(p_cdt->is_constrained(re)){
|
||||||
|
// the edge is constrained
|
||||||
|
// report intersection with right boarder ray
|
||||||
|
// if it is not already the right vertex (already reported)
|
||||||
|
if(right != rvh->point()){
|
||||||
|
*oit++ = ray_seg_intersection(q,right,nvh->point(),rvh->point());
|
||||||
|
}
|
||||||
|
|
||||||
|
// then report intersection with left boarder if it exists
|
||||||
|
if(lo == CGAL::COUNTERCLOCKWISE){
|
||||||
|
*oit++ = ray_seg_intersection(q,left,nvh->point(),rvh->point());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// the edge is not a constrained
|
||||||
|
if(lo == CGAL::COUNTERCLOCKWISE){
|
||||||
|
// no split needed and return
|
||||||
|
//std::cout<< "h1"<< std::endl;
|
||||||
|
oit = expand_edge(q,left,right,nfh,rindex,oit);
|
||||||
|
//std::cout<< "h1 done"<< std::endl;
|
||||||
|
return oit;
|
||||||
|
}else{
|
||||||
|
// spliting at new vertex
|
||||||
|
//std::cout<< "h2"<< std::endl;
|
||||||
|
*oit++ = expand_edge(q,nvh->point(),right,nfh,rindex,oit);
|
||||||
|
//std::cout<< "h2 done"<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//std::cout << "q "<< q << std::endl ;
|
||||||
|
//std::cout << "lvh->point() "<< lvh->point() << std::endl;
|
||||||
|
//std::cout << "left "<< left << std::endl ;
|
||||||
|
//std::cout << "nvh->point() "<< nvh->point() << std::endl ;
|
||||||
|
//std::cout << "right "<< right << std::endl ;
|
||||||
|
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
// determin whether new vertex needs to be reported
|
||||||
|
if(ro != CGAL::CLOCKWISE && lo != CGAL::COUNTERCLOCKWISE){
|
||||||
|
*oit++ = nvh->point();
|
||||||
|
}
|
||||||
|
if(!Regularization_tag::value){
|
||||||
|
assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR));
|
||||||
|
// we have to check whether a needle starts here.
|
||||||
|
if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re) && ro == CGAL::COLLINEAR)
|
||||||
|
collect_needle(q,nvh,nfh,rindex);
|
||||||
|
if(p_cdt->is_constrained(re) && !p_cdt->is_constrained(le) && lo == CGAL::COLLINEAR)
|
||||||
|
collect_needle(q,nvh,nfh,lindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//left edge is seen if new vertex is clockwise of left boarder
|
||||||
|
if(lo == CGAL::CLOCKWISE){
|
||||||
|
if(p_cdt->is_constrained(le)){
|
||||||
|
// the edge is constrained
|
||||||
|
// report interesection with right boarder if exists
|
||||||
|
if(ro == CGAL::CLOCKWISE){
|
||||||
|
*oit++ = ray_seg_intersection(q,right,nvh->point(),lvh->point());
|
||||||
|
}
|
||||||
|
// then report intersection with left boarder ray
|
||||||
|
// if it is not already the left vertex (already reported)
|
||||||
|
if(left != lvh->point()){
|
||||||
|
*oit++ = ray_seg_intersection(q,left,nvh->point(),lvh->point());
|
||||||
|
}
|
||||||
|
return oit;
|
||||||
|
}else{
|
||||||
|
// the edge is not a constrained
|
||||||
|
if(ro == CGAL::CLOCKWISE){
|
||||||
|
// no split needed and return
|
||||||
|
//std::cout<< "h3"<< std::endl;
|
||||||
|
oit = expand_edge(q,left,right,nfh,lindex,oit);
|
||||||
|
//std::cout<< "h3 done"<< std::endl;
|
||||||
|
return oit;
|
||||||
|
}else{
|
||||||
|
// spliting at new vertex
|
||||||
|
//std::cout<< "h4"<< std::endl;
|
||||||
|
oit = expand_edge(q,left,nvh->point(),nfh,lindex,oit);
|
||||||
|
//std::cout<< "h4 done"<< std::endl;
|
||||||
|
return oit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q,
|
||||||
|
const Face_const_handle face,
|
||||||
|
VARR& out_arr
|
||||||
|
){
|
||||||
|
//std::cout << "query in face interior" << std::endl;
|
||||||
|
|
||||||
|
out_arr.clear();
|
||||||
|
needles.clear();
|
||||||
|
assert(!face->is_unbounded());
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Point_2> raw_output;
|
||||||
|
typename CDT::Face_handle fh = p_cdt->locate(q);
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(1)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,0))){
|
||||||
|
//std::cout<< "edge 0 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(2)->point(),
|
||||||
|
fh->vertex(1)->point(),
|
||||||
|
fh,0,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(2)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,1))){
|
||||||
|
//std::cout << "edge 1 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(0)->point(),
|
||||||
|
fh->vertex(2)->point(),
|
||||||
|
fh,1,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(0)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,2))){
|
||||||
|
//std::cout << "edge 2 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(1)->point(),
|
||||||
|
fh->vertex(0)->point(),
|
||||||
|
fh,2,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return output(raw_output,out_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q,
|
||||||
|
const Halfedge_const_handle he,
|
||||||
|
VARR& out_arr) {
|
||||||
|
//std::cout << "visibility_region he" << std::endl;
|
||||||
|
|
||||||
|
assert(!he->face()->is_unbounded());
|
||||||
|
out_arr.clear();
|
||||||
|
needles.clear();
|
||||||
|
|
||||||
|
std::vector<Point_2> raw_output;
|
||||||
|
typename CDT::Locate_type location;
|
||||||
|
int index;
|
||||||
|
typename CDT::Face_handle fh = p_cdt->locate(q,location,index);
|
||||||
|
assert(location == CDT::EDGE || location == CDT::VERTEX);
|
||||||
|
// the following code tries to figure out which triangle one should start in.
|
||||||
|
|
||||||
|
|
||||||
|
if(location == CDT::EDGE){
|
||||||
|
//std::cout << "query on edge" << std::endl;
|
||||||
|
// this is the easy part, there are only two possible faces
|
||||||
|
// index indicates the edge = vertex on the other side of the edge
|
||||||
|
// the next vertex in cw order should be the target of given edge
|
||||||
|
if(fh->vertex(p_cdt->cw(index))->point() != he->target()->point()){
|
||||||
|
//std::cout << "need to swap face" << std::endl;
|
||||||
|
// take face on the other side if this is not the case
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(index);
|
||||||
|
index = nfh->index(fh);
|
||||||
|
fh = nfh;
|
||||||
|
}
|
||||||
|
assert(fh->vertex(p_cdt->cw(index))->point() == he->target()->point());
|
||||||
|
assert(!p_cdt->is_infinite(fh->vertex(index)));
|
||||||
|
|
||||||
|
|
||||||
|
// output the edge the query lies on
|
||||||
|
raw_output.push_back(he->source()->point());
|
||||||
|
raw_output.push_back(he->target()->point());
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->ccw(index)))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(index)->point(), //left
|
||||||
|
he->target()->point() , //right
|
||||||
|
fh,
|
||||||
|
p_cdt->ccw(index),
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
raw_output.push_back(fh->vertex(index)->point());
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index)))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
he->source()->point() , //left
|
||||||
|
fh->vertex(index)->point(), //right
|
||||||
|
fh,
|
||||||
|
p_cdt->cw(index),
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(location == CDT::VERTEX){
|
||||||
|
//std::cout << "query on vertex" << std::endl;
|
||||||
|
|
||||||
|
//bool query_point_on_vertex_is_not_working_yet = false;
|
||||||
|
//assert(query_point_on_vertex_is_not_working_yet);
|
||||||
|
|
||||||
|
assert(q == he->target()->point());
|
||||||
|
assert(fh->vertex(index)->point() == he->target()->point());
|
||||||
|
|
||||||
|
// push points that are seen anyway
|
||||||
|
// raw_output.push_back(he->source()->point()); inserted last
|
||||||
|
raw_output.push_back(he->target()->point());
|
||||||
|
raw_output.push_back(he->next()->target()->point());
|
||||||
|
|
||||||
|
// now start in the triangle that contains he->next()
|
||||||
|
while(
|
||||||
|
p_cdt->is_infinite(fh->vertex(p_cdt->ccw(index))) ||
|
||||||
|
he->next()->target()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||||
|
int nindex = nfh->index(fh);
|
||||||
|
index = p_cdt->ccw(nindex);
|
||||||
|
fh = nfh;
|
||||||
|
assert(he->target()->point() == fh->vertex(index)->point());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert(he->next()->source()->point() == fh->vertex(index)->point());
|
||||||
|
assert(he->next()->target()->point() == fh->vertex(p_cdt->ccw(index))->point());
|
||||||
|
assert(!p_cdt->is_infinite(fh));
|
||||||
|
assert(p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index))));
|
||||||
|
|
||||||
|
while(he->source()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,index))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(p_cdt-> cw(index))->point(), //left
|
||||||
|
fh->vertex(p_cdt->ccw(index))->point(), //right
|
||||||
|
fh,
|
||||||
|
index,
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
// push left end point of edge into output
|
||||||
|
raw_output.push_back(fh->vertex(p_cdt-> cw(index))->point());
|
||||||
|
|
||||||
|
// take the next triangle around q in ccw order
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||||
|
int nindex = nfh->index(fh);
|
||||||
|
index = p_cdt->ccw(nindex);
|
||||||
|
fh = nfh;
|
||||||
|
assert(fh->vertex(index)->point() == he->target()->point());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output(raw_output,out_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
output(std::vector<Point_2>& raw_output, VARR& out_arr){
|
||||||
|
|
||||||
|
if(needles.size()>0){
|
||||||
|
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
||||||
|
for(unsigned int i = 0; i <raw_output.size();i++){
|
||||||
|
// //std::cout << raw_output[i] << " -- "
|
||||||
|
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||||
|
segments.push_back(Segment_2(raw_output[i],raw_output[(i+1)%raw_output.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL::insert_non_intersecting_curves(out_arr,segments.begin(),segments.end());
|
||||||
|
//CGAL::insert(out_arr,segments.begin(),segments.end());
|
||||||
|
}else{
|
||||||
|
typename VARR::Vertex_handle v_last, v_first;
|
||||||
|
v_last = v_first =
|
||||||
|
out_arr.insert_in_face_interior(raw_output[0], out_arr.unbounded_face());
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i <raw_output.size()-1;i++){
|
||||||
|
// //std::cout << raw_output[i] << " -- "
|
||||||
|
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||||
|
if(raw_output[i]<raw_output[(i+1)]){
|
||||||
|
v_last = out_arr.insert_from_left_vertex (Segment_2(raw_output[i], raw_output[i+1]), v_last)->target();
|
||||||
|
}else{
|
||||||
|
v_last = out_arr.insert_from_right_vertex(Segment_2(raw_output[i], raw_output[i+1]), v_last)->target();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_arr.insert_at_vertices(Segment_2(raw_output.front(),raw_output.back()),v_last,v_first);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(out_arr.number_of_faces()== 2);
|
||||||
|
|
||||||
|
if(out_arr.faces_begin()->is_unbounded())
|
||||||
|
return ++out_arr.faces_begin();
|
||||||
|
else
|
||||||
|
return out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_cdt(){
|
||||||
|
//std::cout<< "==============" <<std::endl;
|
||||||
|
//std::cout<< "Input Polygon:" <<std::endl;
|
||||||
|
//todo, avoid copy by using modified iterator
|
||||||
|
std::vector<std::pair<Point_2,Point_2> > constraints;
|
||||||
|
for(typename Arrangement_2::Edge_const_iterator eit = p_arr->edges_begin();
|
||||||
|
eit != p_arr->edges_end(); eit++){
|
||||||
|
Point_2 source = eit->source()->point();
|
||||||
|
Point_2 target = eit->target()->point();
|
||||||
|
//std::cout << source << " -- " << target << std::endl;
|
||||||
|
constraints.push_back(std::make_pair(source,target));
|
||||||
|
}
|
||||||
|
//std::cout << "init_cdt new CDT" << std::endl;
|
||||||
|
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),constraints.end()));
|
||||||
|
//std::cout << "init_cdt done" << std::endl;
|
||||||
|
//std::cout << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CGAL
|
||||||
|
|
||||||
|
#endif //CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
|
||||||
|
#ifndef CGAL_VISIBILITY_UTILS_H
|
||||||
|
#define CGAL_VISIBILITY_UTILS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <CGAL/tags.h>
|
||||||
|
#include <CGAL/enum.h>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Visibility_2 {
|
||||||
|
|
||||||
|
template <class Arrangement_2>
|
||||||
|
int count_edges_in_face(typename Arrangement_2::Face_const_handle fch) {
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
|
Ccb_halfedge_const_circulator;
|
||||||
|
|
||||||
|
Ccb_halfedge_const_circulator circ = fch->outer_ccb();
|
||||||
|
Ccb_halfedge_const_circulator curr = circ;
|
||||||
|
|
||||||
|
int edge_cnt(0);
|
||||||
|
do {
|
||||||
|
edge_cnt++;
|
||||||
|
} while (++curr != circ);
|
||||||
|
return edge_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Edge_const_iterator>
|
||||||
|
void print_edge(Edge_const_iterator eit) {
|
||||||
|
std::cout << "[" << eit->curve() << "]" << std::endl;
|
||||||
|
}
|
||||||
|
template <class Face_const_handle, class Ccb_halfedge_const_circulator>
|
||||||
|
void print_simple_face(Face_const_handle fh) {
|
||||||
|
Ccb_halfedge_const_circulator cir = fh->outer_ccb();
|
||||||
|
Ccb_halfedge_const_circulator curr = cir;
|
||||||
|
do {
|
||||||
|
std::cout << "[" << curr->curve() << "]" << std::endl;
|
||||||
|
} while (++ curr != cir);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Arrangement_2>
|
||||||
|
void print_arrangement(const Arrangement_2& arr) {
|
||||||
|
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||||
|
Edge_const_iterator eit;
|
||||||
|
std::cout << arr.number_of_edges() << " edges:" << std::endl;
|
||||||
|
for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
|
||||||
|
print_edge(eit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Arrangement_2>
|
||||||
|
void print_arrangement_by_face(const Arrangement_2& arr) {
|
||||||
|
typedef typename Arrangement_2::Face_const_iterator Face_const_iterator;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
|
Ccb_halfedge_const_circulator;
|
||||||
|
Face_const_iterator fit;
|
||||||
|
for (fit = arr.faces_begin() ; fit != arr.faces_end() ; fit++) {
|
||||||
|
if (!fit->is_unbounded()) {
|
||||||
|
std::cout << "FACE\n";
|
||||||
|
print_simple_face<Face_const_iterator, Ccb_halfedge_const_circulator>(fit);
|
||||||
|
std::cout << "END FACE\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2>
|
||||||
|
Orientation orientation_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Geometry_traits_2::Point_2& p,
|
||||||
|
const typename Geometry_traits_2::Point_2& q,
|
||||||
|
const typename Geometry_traits_2::Point_2& r) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Orientation_2 orient =
|
||||||
|
geom_traits->orientation_2_object();
|
||||||
|
return orient(p, q, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2>
|
||||||
|
bool less_distance_to_point_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Geometry_traits_2::Point_2& p,
|
||||||
|
const typename Geometry_traits_2::Point_2& q,
|
||||||
|
const typename Geometry_traits_2::Point_2& r) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Less_distance_to_point_2 less_dist =
|
||||||
|
geom_traits->less_distance_to_point_2_object();
|
||||||
|
return less_dist(p, q, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2>
|
||||||
|
bool collinear(const Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Geometry_traits_2::Point_2& p,
|
||||||
|
const typename Geometry_traits_2::Point_2& q,
|
||||||
|
const typename Geometry_traits_2::Point_2& r) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Collinear_2 collinear_fnct =
|
||||||
|
geom_traits->collinear_2_object();
|
||||||
|
return collinear_fnct(p, q, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2, class _Curve_first, class _Curve_second >
|
||||||
|
typename Geometry_traits_2::Object_2 intersect_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const _Curve_first& s1,
|
||||||
|
const _Curve_second& s2) {
|
||||||
|
|
||||||
|
typedef typename Geometry_traits_2::Kernel Kernel;
|
||||||
|
const Kernel *kernel = static_cast<const Kernel*> (geom_traits);
|
||||||
|
typename Kernel::Intersect_2 intersect_fnct = kernel->intersect_2_object();
|
||||||
|
return intersect_fnct(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2>
|
||||||
|
CGAL::Comparison_result compare_xy_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Geometry_traits_2::Point_2 &p,
|
||||||
|
const typename Geometry_traits_2::Point_2 &q) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Compare_xy_2 cmp =
|
||||||
|
geom_traits->compare_xy_2_object();
|
||||||
|
return cmp(p, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2, class Type1, class Type2>
|
||||||
|
typename Geometry_traits_2::FT compute_squared_distance_2(
|
||||||
|
const Geometry_traits_2 *geom_traits,
|
||||||
|
const Type1& p,
|
||||||
|
const Type2& seg) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Compute_squared_distance_2 compute_dist =
|
||||||
|
geom_traits->compute_squared_distance_2_object();
|
||||||
|
return compute_dist(p, seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2, class Type1, class Type2>
|
||||||
|
bool do_intersect_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const Type1& c1,
|
||||||
|
const Type2& c2) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Do_intersect_2 intersect =
|
||||||
|
geom_traits->do_intersect_2_object();
|
||||||
|
return intersect(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2>
|
||||||
|
bool collinear_are_ordered_along_line_2(const Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Geometry_traits_2::Point_2 &p,
|
||||||
|
const typename Geometry_traits_2::Point_2 &q,
|
||||||
|
const typename Geometry_traits_2::Point_2 &r) {
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Collinear_are_ordered_along_line_2 coll =
|
||||||
|
geom_traits->collinear_are_ordered_along_line_2_object();
|
||||||
|
return coll(p, q, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Geometry_traits_2, class Type1, class Type2>
|
||||||
|
typename Geometry_traits_2::Point_2 construct_projected_point_2(
|
||||||
|
const Geometry_traits_2 *geom_traits,
|
||||||
|
const Type1& s,
|
||||||
|
const Type2& p) {
|
||||||
|
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
typename Geometry_traits_2::Construct_projected_point_2 construct_proj =
|
||||||
|
geom_traits->construct_projected_point_2_object();
|
||||||
|
Point_2 proj_pt = construct_proj(s.supporting_line(), p);
|
||||||
|
if (s.has_on(proj_pt)) {
|
||||||
|
return proj_pt;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Number_type d_to_src = compute_squared_distance_2
|
||||||
|
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.source());
|
||||||
|
Number_type d_to_trg = compute_squared_distance_2
|
||||||
|
<Geometry_traits_2, Point_2, Point_2>(geom_traits, proj_pt, s.target());
|
||||||
|
if (d_to_src < d_to_trg) {
|
||||||
|
return s.source();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return s.target();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//construct an arrangement of visibility region from a vector of circular ordered vertices with respect to the query point
|
||||||
|
template <class Visibility_2, class Visibility_arrangement_2>
|
||||||
|
void report_while_handling_needles(
|
||||||
|
const typename Visibility_2::Arrangement_2::Geometry_traits_2 *geom_traits,
|
||||||
|
const typename Visibility_2::Arrangement_2::Point_2& q,
|
||||||
|
std::vector<typename Visibility_2::Arrangement_2::Point_2>& points,
|
||||||
|
Visibility_arrangement_2& arr_out) {
|
||||||
|
|
||||||
|
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Point_2 Point_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||||
|
|
||||||
|
typename std::vector<Segment_2>::size_type i = 0;
|
||||||
|
|
||||||
|
if (points.front() == points.back()) {
|
||||||
|
points.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (collinear(geom_traits,
|
||||||
|
q,
|
||||||
|
points[i],
|
||||||
|
points.back())) {
|
||||||
|
|
||||||
|
points.push_back(points[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
points.push_back(points[i]);
|
||||||
|
|
||||||
|
typename Visibility_arrangement_2::Halfedge_handle he_handle;
|
||||||
|
typename Visibility_arrangement_2::Vertex_handle v_trg; //the handle of vertex where the next segment is inserted
|
||||||
|
typename Visibility_arrangement_2::Vertex_handle v_fst; //the handle of vertex inserted first
|
||||||
|
typename Visibility_arrangement_2::Vertex_handle v_needle_end; //the handle of vertex of the end of a needle
|
||||||
|
|
||||||
|
v_trg = v_fst = arr_out.insert_in_face_interior(points[i], arr_out.unbounded_face());
|
||||||
|
//find a point that is right after a needle
|
||||||
|
while (i+1 < points.size()) {
|
||||||
|
if ( collinear(geom_traits,
|
||||||
|
points[i],
|
||||||
|
points[i+1],
|
||||||
|
q)) {
|
||||||
|
typename Visibility_arrangement_2::Vertex_handle v_needle_begin = v_trg;
|
||||||
|
std::vector<Point_2> forward_needle; //vertices of the needle that are not between q and v_needle_begin; their direction is leaving q;
|
||||||
|
std::vector<Point_2> backward_needle; //vertices of the needle that are not between q and v_needle_begin; their direction is towards q;
|
||||||
|
std::vector<Point_2> part_in_q_side; //vertices of the needle that are between q and v_needle_begin
|
||||||
|
part_in_q_side.push_back(points[i]);
|
||||||
|
forward_needle.push_back((points[i]));
|
||||||
|
|
||||||
|
bool same_side_of_q = (compare_xy_2(geom_traits, points[i], q)==compare_xy_2(geom_traits, points[i], points[i+1]));
|
||||||
|
if (same_side_of_q)
|
||||||
|
part_in_q_side.push_back(points[i+1]);
|
||||||
|
else
|
||||||
|
forward_needle.push_back(points[i+1]);
|
||||||
|
i++;
|
||||||
|
while (i+1< points.size() && orientation_2(geom_traits,
|
||||||
|
points[i],
|
||||||
|
points[i+1],
|
||||||
|
q ) == CGAL::COLLINEAR) {
|
||||||
|
if (same_side_of_q) {
|
||||||
|
part_in_q_side.push_back(points[i+1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (compare_xy_2(geom_traits, part_in_q_side.front(), q)
|
||||||
|
== compare_xy_2(geom_traits, part_in_q_side.front(), points[i+1])) {
|
||||||
|
same_side_of_q = true;
|
||||||
|
part_in_q_side.push_back(points[i+1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (less_distance_to_point_2(geom_traits, q, points[i], points[i+1]))
|
||||||
|
forward_needle.push_back(points[i+1]);
|
||||||
|
else
|
||||||
|
backward_needle.push_back(points[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//obtain the end point of a needle
|
||||||
|
Point_2 end_of_needle;
|
||||||
|
if (same_side_of_q)
|
||||||
|
end_of_needle = part_in_q_side.back();
|
||||||
|
else {
|
||||||
|
if (backward_needle.empty()) {
|
||||||
|
end_of_needle = forward_needle.back();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
end_of_needle = backward_needle.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::reverse(backward_needle.begin(), backward_needle.end());
|
||||||
|
std::vector<Point_2> merged_needle;
|
||||||
|
|
||||||
|
// merge the forward_needle and backward_needle
|
||||||
|
unsigned int itr_fst = 0, itr_snd = 0;
|
||||||
|
while (itr_fst < forward_needle.size() &&
|
||||||
|
itr_snd < backward_needle.size()) {
|
||||||
|
|
||||||
|
if (less_distance_to_point_2(geom_traits,
|
||||||
|
q,
|
||||||
|
forward_needle[itr_fst],
|
||||||
|
backward_needle[itr_snd])) {
|
||||||
|
|
||||||
|
merged_needle.push_back(forward_needle[itr_fst]);
|
||||||
|
itr_fst++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
merged_needle.push_back(backward_needle[itr_snd]);
|
||||||
|
itr_snd++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (itr_fst < forward_needle.size()) {
|
||||||
|
merged_needle.push_back(forward_needle[itr_fst]);
|
||||||
|
itr_fst++;
|
||||||
|
}
|
||||||
|
while (itr_snd < backward_needle.size()) {
|
||||||
|
merged_needle.push_back(backward_needle[itr_snd]);
|
||||||
|
itr_snd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int p = 0 ; p+1 < merged_needle.size() ; p++) {
|
||||||
|
if (CGAL::Visibility_2::compare_xy_2<Geometry_traits_2>(geom_traits, merged_needle[p], merged_needle[p+1]) == CGAL::SMALLER) {
|
||||||
|
he_handle = arr_out.insert_from_left_vertex(Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
he_handle = arr_out.insert_from_right_vertex(Segment_2(merged_needle[p], merged_needle[p+1]), v_trg);
|
||||||
|
}
|
||||||
|
v_trg = he_handle->target();
|
||||||
|
if (merged_needle[p+1] == end_of_needle) {
|
||||||
|
v_needle_end = v_trg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (same_side_of_q) {
|
||||||
|
//insert the part of needle between q and v_needle_begin
|
||||||
|
v_trg = v_needle_begin;
|
||||||
|
for (unsigned int p = 0 ; p+1 < part_in_q_side.size() ; p++) {
|
||||||
|
if (CGAL::Visibility_2::compare_xy_2<Geometry_traits_2>(geom_traits, part_in_q_side[p], part_in_q_side[p+1]) == CGAL::SMALLER) {
|
||||||
|
he_handle = arr_out.insert_from_left_vertex(Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
he_handle = arr_out.insert_from_right_vertex(Segment_2(part_in_q_side[p], part_in_q_side[p+1]), v_trg);
|
||||||
|
}
|
||||||
|
v_trg = he_handle->target();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
v_trg = v_needle_end;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (CGAL::Visibility_2::compare_xy_2<Geometry_traits_2>(geom_traits, v_trg->point(), points[i+1]) == CGAL::SMALLER) {
|
||||||
|
he_handle = arr_out.insert_from_left_vertex(Segment_2(points[i], points[i+1]), v_trg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
he_handle = arr_out.insert_from_right_vertex(Segment_2(points[i], points[i+1]), v_trg);
|
||||||
|
}
|
||||||
|
v_trg = he_handle->target();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i+2 == points.size()) {
|
||||||
|
//close the boundary
|
||||||
|
v_trg = he_handle->target();
|
||||||
|
arr_out.insert_at_vertices(Segment_2(points[points.size()-2], points[points.size()-1]), v_trg, v_fst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Visibility_2
|
||||||
|
} // end namespace CGAL
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -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,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,178 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
|
||||||
|
#ifndef CGAL_TEST_MODEL_METHODS_H
|
||||||
|
#define CGAL_TEST_MODEL_METHODS_H
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
template <class Visibility_2, class Visibility_arrangement_2>
|
||||||
|
void test_model_methods_for_arr(
|
||||||
|
typename Visibility_2::Arrangement_2 &arr) {
|
||||||
|
|
||||||
|
typedef typename Visibility_2::Arrangement_2
|
||||||
|
Arrangement_2;
|
||||||
|
typedef typename Visibility_2::Traits_2 Traits_2;
|
||||||
|
typedef typename Arrangement_2::Point_2
|
||||||
|
Point_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2::Segment_2
|
||||||
|
Segment_2;
|
||||||
|
|
||||||
|
typedef typename Visibility_arrangement_2::Face_handle VFH;
|
||||||
|
|
||||||
|
|
||||||
|
Visibility_2 visibility;
|
||||||
|
assert(false == visibility.is_attached());
|
||||||
|
visibility.attach(arr);
|
||||||
|
assert(true == visibility.is_attached());
|
||||||
|
assert(true == (CGAL::test_are_equal(arr,visibility.arr())));
|
||||||
|
|
||||||
|
Visibility_arrangement_2 arr_out;
|
||||||
|
Visibility_arrangement_2 arr_out_check;
|
||||||
|
|
||||||
|
typename Arrangement_2::Face_const_iterator fit;
|
||||||
|
|
||||||
|
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) {
|
||||||
|
if (!fit->is_unbounded()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// First consider query point in the unbounded face
|
||||||
|
const Point_2 query_pt(1, 1);
|
||||||
|
// Check returned face_handle
|
||||||
|
VFH face_check = visibility.compute_visibility(query_pt, fit, arr_out);
|
||||||
|
VFH face;
|
||||||
|
if (arr_out.faces_begin()->is_unbounded()) {
|
||||||
|
face = ++arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
face = arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
assert(face_check == face);
|
||||||
|
|
||||||
|
assert((true == test_are_equal<Arrangement_2, Visibility_arrangement_2>
|
||||||
|
(arr, arr_out)));
|
||||||
|
visibility.detach();
|
||||||
|
assert(false == visibility.is_attached());
|
||||||
|
visibility.attach(arr);
|
||||||
|
|
||||||
|
visibility.compute_visibility(query_pt, fit, arr_out_check);
|
||||||
|
assert((true == test_are_equal<Visibility_arrangement_2, Arrangement_2>
|
||||||
|
(arr_out_check, arr)));
|
||||||
|
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||||
|
(arr_out, arr_out_check)));
|
||||||
|
arr_out.clear();
|
||||||
|
visibility.compute_visibility(query_pt, fit, arr_out);
|
||||||
|
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||||
|
(arr_out, arr_out_check)));
|
||||||
|
|
||||||
|
// Now consider the query point on a halfedge
|
||||||
|
const Point_2 query_pt2 = Point_2(0, 4);
|
||||||
|
arr_out.clear();
|
||||||
|
typename Arrangement_2::Halfedge_const_iterator hit;
|
||||||
|
VFH face_check_he;
|
||||||
|
for (hit = arr.halfedges_begin();
|
||||||
|
hit != arr.halfedges_end(); ++hit) {
|
||||||
|
|
||||||
|
if (hit->source()->point() == Point_2(0, 8) && hit->target()->point() == Point_2(0, 0)) {
|
||||||
|
face_check_he = visibility.compute_visibility(query_pt2, hit, arr_out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arr_out.faces_begin()->is_unbounded()) {
|
||||||
|
face = ++arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
face = arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
assert(face_check_he == face);
|
||||||
|
assert((true == test_are_equal(arr_out, arr)));
|
||||||
|
arr_out_check.clear();
|
||||||
|
visibility.compute_visibility(query_pt2, hit, arr_out_check);
|
||||||
|
assert((true == test_are_equal<Visibility_arrangement_2, Visibility_arrangement_2>
|
||||||
|
(arr_out, arr_out_check)));
|
||||||
|
|
||||||
|
// Now consider the query point as the target of a halfedge
|
||||||
|
typename Arrangement_2::Halfedge_const_iterator hit_snd;
|
||||||
|
for (hit_snd = arr.halfedges_begin(); hit_snd != arr.halfedges_end(); ++hit_snd) {
|
||||||
|
if(!hit_snd->face()->is_unbounded()){
|
||||||
|
arr_out.clear();
|
||||||
|
VFH face_check_he_snd = visibility.compute_visibility(hit_snd->target()->point(), hit_snd, arr_out);
|
||||||
|
assert(!face_check_he_snd->is_unbounded());
|
||||||
|
if (arr_out.faces_begin()->is_unbounded()) {
|
||||||
|
face = ++arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
face = arr_out.faces_begin();
|
||||||
|
}
|
||||||
|
assert(face_check_he_snd == face);
|
||||||
|
if (! test_are_equal(arr_out, arr)) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Visibility_2, class Visibility_arrangement_2>
|
||||||
|
void test_model_methods() {
|
||||||
|
|
||||||
|
// Check concept obediance
|
||||||
|
typedef typename Visibility_2::Arrangement_2
|
||||||
|
Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Point_2 Point_2;
|
||||||
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Visibility_2::Regularization_tag Regularization_tag;
|
||||||
|
typedef typename Visibility_2::Supports_general_polygon_tag
|
||||||
|
Supports_general_polygon_tag;
|
||||||
|
typedef typename Visibility_2::Supports_simple_polygon_tag
|
||||||
|
Supports_simple_polygon_tag;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2::Segment_2
|
||||||
|
Segment_2;
|
||||||
|
|
||||||
|
Point_2 p1(0, 0), p2(8, 0), p3(8, 8), p4(0, 8);
|
||||||
|
std::vector<Segment_2> seg_sq;
|
||||||
|
seg_sq.push_back(Segment_2(p1, p2));
|
||||||
|
seg_sq.push_back(Segment_2(p2, p3));
|
||||||
|
seg_sq.push_back(Segment_2(p3, p4));
|
||||||
|
seg_sq.push_back(Segment_2(p4, p1));
|
||||||
|
Arrangement_2 arr_square;
|
||||||
|
CGAL::insert(arr_square, seg_sq.begin(), seg_sq.end());
|
||||||
|
|
||||||
|
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_square);
|
||||||
|
|
||||||
|
std::vector<Segment_2> seg_tri;
|
||||||
|
seg_tri.push_back(Segment_2(p1, p2));
|
||||||
|
seg_tri.push_back(Segment_2(p2, p4));
|
||||||
|
seg_tri.push_back(Segment_2(p4, p1));
|
||||||
|
Arrangement_2 arr_triangle;
|
||||||
|
CGAL::insert(arr_triangle, seg_tri.begin(), seg_tri.end());
|
||||||
|
|
||||||
|
test_model_methods_for_arr<Visibility_2,Visibility_arrangement_2>(arr_triangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end CGAL namespace
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
// Kan Huang <huangkandiy@gmail.com
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||||
|
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||||
|
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
typedef CGAL::Gmpq Number_type;
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
|
||||||
|
template <class Visibility>
|
||||||
|
void deploy_pure_benchmark(const CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||||
|
Visibility v;
|
||||||
|
CGAL::pure_benchmark<Visibility>
|
||||||
|
(v, qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Regularization_tag>
|
||||||
|
void benchmark_one_class(std::string name, const CGAL::Query_choice& qchoice, std::string input_arr_file) {
|
||||||
|
std::ifstream input(input_arr_file.c_str());
|
||||||
|
if (name == "S")
|
||||||
|
deploy_pure_benchmark<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_tag> > (qchoice, input);
|
||||||
|
if (name == "T")
|
||||||
|
deploy_pure_benchmark<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag> > (qchoice, input);
|
||||||
|
if (name == "R")
|
||||||
|
deploy_pure_benchmark<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag> > (qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_usage() {
|
||||||
|
std::cout << "Usage: ./pure_benchmark [filename] [Class type] [Query type] [Regularize]\n";
|
||||||
|
std::cout << "where [Class type] could be S(simple), R(rotational sweep) and T(triangular), indicating which class you want to test.\n";
|
||||||
|
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
|
||||||
|
std::cout << "[Regularize] can be: {true, false}.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
CGAL::Query_choice qchoice = CGAL::FACE;
|
||||||
|
std::string regularization_tag("true");
|
||||||
|
if (argc > 1) {
|
||||||
|
std::string input_arr_file(argv[1]);
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
std::cout << "NAME TAG PreProTime NQueries TimeQueries TotalTime QAVE TAVE" << std::endl;
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("T"), CGAL::FACE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("T"), CGAL::FACE, input_arr_file);
|
||||||
|
std::cout << std::endl;
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("S"), CGAL::FACE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("S"), CGAL::FACE, input_arr_file);
|
||||||
|
std::cout << std::endl;
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(std::string("R"), CGAL::FACE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::VERTEX, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::EDGE, input_arr_file);
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(std::string("R"), CGAL::FACE, input_arr_file);
|
||||||
|
} else if (argc == 5) {
|
||||||
|
qchoice = CGAL::FACE;
|
||||||
|
std::string query_type(argv[3]);
|
||||||
|
if (query_type == "vertex")
|
||||||
|
qchoice = CGAL::VERTEX;
|
||||||
|
else if (query_type == "edge")
|
||||||
|
qchoice = CGAL::EDGE;
|
||||||
|
else if (query_type == "face")
|
||||||
|
qchoice = CGAL::FACE;
|
||||||
|
else {
|
||||||
|
std::cout<<"query type is not matched.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
regularization_tag = argv[4];
|
||||||
|
std::string classname(argv[2]);
|
||||||
|
if (regularization_tag == "true") {
|
||||||
|
benchmark_one_class<CGAL::Tag_true>(classname, qchoice, input_arr_file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
benchmark_one_class<CGAL::Tag_false>(classname, qchoice, input_arr_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_usage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_usage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -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,125 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
// Kan Huang <huangkandiy@gmail.com>
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||||
|
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||||
|
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
typedef CGAL::Gmpq Number_type;
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
|
||||||
|
template <class Visibility_fst, class Visibility_snd>
|
||||||
|
void deploy_benchmark(CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||||
|
Visibility_fst v1;
|
||||||
|
Visibility_snd v2;
|
||||||
|
CGAL::simple_benchmark<Visibility_fst, Visibility_snd>
|
||||||
|
(v1, v2, qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Visibility_fst, class Regularization_tag>
|
||||||
|
void define_snd_class(std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input){
|
||||||
|
if (name2 == "S")
|
||||||
|
deploy_benchmark<Visibility_fst, CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_tag> >
|
||||||
|
(qchoice, input);
|
||||||
|
if (name2 == "T")
|
||||||
|
deploy_benchmark<Visibility_fst, CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag> >
|
||||||
|
(qchoice, input);
|
||||||
|
if (name2 == "R")
|
||||||
|
deploy_benchmark<Visibility_fst, CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag> >
|
||||||
|
(qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Regularization_tag>
|
||||||
|
void benchmark_two_classes(std::string name1, std::string name2, CGAL::Query_choice& qchoice, std::ifstream& input) {
|
||||||
|
if (name1 == "S")
|
||||||
|
define_snd_class<CGAL::Simple_polygon_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||||
|
if (name1 == "T")
|
||||||
|
define_snd_class<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||||
|
if (name1 == "R")
|
||||||
|
define_snd_class<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_usage() {
|
||||||
|
std::cout << "Usage: ./simple_benchmark [filename] [Class type 1] [Class type 2] [Query type] [Regularize]\n";
|
||||||
|
std::cout << "where [Class type] could be S(simple), R(rotational sweep) and T(triangular), indicating which classes you want to test.\n";
|
||||||
|
std::cout << "[Query type] can be: {vertex, edge, face}.\n";
|
||||||
|
std::cout << "[Regularize] can be: {true, false}.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
CGAL::Query_choice qchoice = CGAL::FACE;
|
||||||
|
std::string regularization_tag("true");
|
||||||
|
if (argc > 1) {
|
||||||
|
std::string input_arr_file(argv[1]);
|
||||||
|
std::ifstream input(input_arr_file.c_str());
|
||||||
|
if (argc == 6) {
|
||||||
|
qchoice = CGAL::FACE;
|
||||||
|
std::string query_type(argv[4]);
|
||||||
|
if (query_type == "vertex")
|
||||||
|
qchoice = CGAL::VERTEX;
|
||||||
|
else if (query_type == "edge")
|
||||||
|
qchoice = CGAL::EDGE;
|
||||||
|
else if (query_type == "face")
|
||||||
|
qchoice = CGAL::FACE;
|
||||||
|
else {
|
||||||
|
std::cout<<"query type is not matched.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
regularization_tag = argv[5];
|
||||||
|
std::string class1(argv[2]), class2(argv[3]);
|
||||||
|
if (regularization_tag == "true") {
|
||||||
|
benchmark_two_classes<CGAL::Tag_true>(class1, class2, qchoice, input);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
benchmark_two_classes<CGAL::Tag_false>(class1, class2, qchoice, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_usage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_usage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Kan Huang <huangkandiy@gmail.com>
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
#include <CGAL/Rotational_sweep_visibility_2.h>
|
||||||
|
#include <CGAL/Arr_extended_dcel.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef CGAL::Cartesian<CGAL::Gmpq> Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
RSV;
|
||||||
|
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||||
|
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<RSV,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||||
|
RSV;
|
||||||
|
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||||
|
std::cout << "Running test suite with " << GREEN << "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<RSV,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
}{
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
RSV;
|
||||||
|
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||||
|
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<RSV,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||||
|
RSV;
|
||||||
|
CGAL::test_model_methods<RSV,Arrangement_2>();
|
||||||
|
std::cout << "Running test suite with " << GREEN << "EPECK" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<RSV,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test Visibility_arrangement_type with extended DCEL
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||||
|
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||||
|
{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}{
|
||||||
|
typedef CGAL::Rotational_sweep_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||||
|
#include <CGAL/Arr_extended_dcel.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef CGAL::Gmpq Number_type;
|
||||||
|
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
Simple_polygon_visibility_2;
|
||||||
|
std::cout << "Running model tests - ";
|
||||||
|
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
|
||||||
|
std::cout << GREEN << "Done!" << RESET << std::endl;
|
||||||
|
std::cout << "Running test suite with " << GREEN
|
||||||
|
<< "Cartesian" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(21, 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
Simple_polygon_visibility_2;
|
||||||
|
std::cout << "Running model tests - ";
|
||||||
|
CGAL::test_model_methods<Simple_polygon_visibility_2,Arrangement_2>();
|
||||||
|
std::cout << GREEN << "Done!" << RESET << std::endl;
|
||||||
|
std::cout << "Running test suite with " << GREEN
|
||||||
|
<< "EPECK" << RESET << " Kernel..." << std::endl;
|
||||||
|
CGAL::run_tests<Simple_polygon_visibility_2,Arrangement_2>(21, 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test Visibility_arrangement_type with extended DCEL
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||||
|
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||||
|
{
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}{
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
||||||
|
// Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/Simple_polygon_visibility_2.h>
|
||||||
|
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
{
|
||||||
|
typedef CGAL::Gmpq Number_type;
|
||||||
|
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef Traits_2::Point_2 Point_2;
|
||||||
|
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
Simple_polygon_visibility_2;
|
||||||
|
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||||
|
Triangular_expansion_visibility_2;
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
Simple_polygon_visibility_2 simple_visibility;
|
||||||
|
const CGAL::Query_choice qchoice = CGAL::FACE;
|
||||||
|
std::string input_arr_file(argv[1]);
|
||||||
|
std::ifstream input(input_arr_file.c_str());
|
||||||
|
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||||
|
(simple_visibility, qchoice, input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
const CGAL::Query_choice qchoice = CGAL::FACE;
|
||||||
|
std::string input_arr_file(argv[1]);
|
||||||
|
std::ifstream input(input_arr_file.c_str());
|
||||||
|
std::string class_name(argv[2]);
|
||||||
|
if ( class_name == "simple") {
|
||||||
|
Simple_polygon_visibility_2 simple_visibility;
|
||||||
|
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||||
|
(simple_visibility, qchoice, input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (class_name == "triangular") {
|
||||||
|
Triangular_expansion_visibility_2 triangular_visibility;
|
||||||
|
CGAL::test_star_shape<Triangular_expansion_visibility_2>
|
||||||
|
(triangular_visibility, qchoice, input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::cout<<"no type is matched.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 4) {
|
||||||
|
std::string input_arr_file(argv[1]);
|
||||||
|
std::ifstream input(input_arr_file.c_str());
|
||||||
|
CGAL::Query_choice qchoice;
|
||||||
|
std::string query_type(argv[3]);
|
||||||
|
if (query_type == "vertex")
|
||||||
|
qchoice = CGAL::VERTEX;
|
||||||
|
else {
|
||||||
|
if (query_type == "edge")
|
||||||
|
qchoice = CGAL::EDGE;
|
||||||
|
else {
|
||||||
|
if (query_type == "face")
|
||||||
|
qchoice = CGAL::FACE;
|
||||||
|
else {
|
||||||
|
std::cout<<"query type is not matched.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string class_name(argv[2]);
|
||||||
|
if (class_name == "simple") {
|
||||||
|
Simple_polygon_visibility_2 simple_visibility;
|
||||||
|
CGAL::test_star_shape<Simple_polygon_visibility_2>
|
||||||
|
(simple_visibility, qchoice, input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (class_name == "triangular") {
|
||||||
|
Triangular_expansion_visibility_2 triangular_visibility;
|
||||||
|
CGAL::test_star_shape<Triangular_expansion_visibility_2>
|
||||||
|
(triangular_visibility, qchoice, input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::cout<<"no type is matched.\n";
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "Usage: ./test_star_shape [filename] [Class type] [Query type]\n";
|
||||||
|
std::cout << "where [Class type] could be simple, naive and triangular, indicating which class you want to test.\n";
|
||||||
|
std::cout << "[Query type] could be vertex, edge, face.\n";
|
||||||
|
std::cout << "The default value of [Query type] is face. The default value of [Class type] is simple.\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s): Francisc Bungiu <fbungiu@gmail.com>
|
||||||
|
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Cartesian.h>
|
||||||
|
#include <CGAL/Gmpq.h>
|
||||||
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arrangement_2.h>
|
||||||
|
#include <CGAL/test_model_methods.h>
|
||||||
|
#include <CGAL/test_utils.h>
|
||||||
|
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||||
|
#include <CGAL/Arr_extended_dcel.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef CGAL::Gmpq Number_type;
|
||||||
|
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_true>
|
||||||
|
Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||||
|
CGAL::run_tests<Visibility_2,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_false>
|
||||||
|
Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||||
|
CGAL::run_tests<Visibility_2,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||||
|
{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_true>
|
||||||
|
Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||||
|
CGAL::run_tests<Visibility_2,Arrangement_2>(21, 2);
|
||||||
|
}{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_false>
|
||||||
|
Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,Arrangement_2>();
|
||||||
|
CGAL::run_tests<Visibility_2,Arrangement_2>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// test Visibility_arrangement_type with extended DCEL
|
||||||
|
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||||
|
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||||
|
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||||
|
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||||
|
{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_true> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}{
|
||||||
|
typedef CGAL::Triangular_expansion_visibility_2<ARR,CGAL::Tag_false> Visibility_2;
|
||||||
|
CGAL::test_model_methods<Visibility_2,EARR>();
|
||||||
|
CGAL::run_tests<Visibility_2,EARR>(21, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||