mirror of https://github.com/CGAL/cgal
General_polygon_set_on_surface_2 - first verstion
This commit is contained in:
parent
c50131c8c9
commit
097c3793fd
|
|
@ -1173,6 +1173,7 @@ Boolean_set_operations_2/examples/Boolean_set_operations_2/char_g.dat -text
|
||||||
Boolean_set_operations_2/examples/Boolean_set_operations_2/char_m.dat -text
|
Boolean_set_operations_2/examples/Boolean_set_operations_2/char_m.dat -text
|
||||||
Boolean_set_operations_2/examples/Boolean_set_operations_2/pgn_holes.dat -text
|
Boolean_set_operations_2/examples/Boolean_set_operations_2/pgn_holes.dat -text
|
||||||
Boolean_set_operations_2/examples/Boolean_set_operations_2/test.dxf -text svneol=unset#application/octet-stream
|
Boolean_set_operations_2/examples/Boolean_set_operations_2/test.dxf -text svneol=unset#application/octet-stream
|
||||||
|
Boolean_set_operations_2/include/CGAL/General_polygon_set_on_surface_2.h -text
|
||||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes1.dat -text
|
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes1.dat -text
|
||||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes2.dat -text
|
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes2.dat -text
|
||||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes3.dat -text
|
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes3.dat -text
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ CGAL_BEGIN_NAMESPACE
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
typedef typename Arrangement::Traits_2 Traits;
|
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||||
typedef Ccb_curve_iterator<Arrangement> Self;
|
typedef Ccb_curve_iterator<Arrangement> Self;
|
||||||
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
||||||
Ccb_halfedge_const_circulator;
|
Ccb_halfedge_const_circulator;
|
||||||
|
|
|
||||||
|
|
@ -100,12 +100,12 @@ public:
|
||||||
|
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Gps_agg_meta_traits :
|
class Gps_agg_meta_traits :
|
||||||
public Gps_traits_decorator<typename Arrangement_::Traits_2,
|
public Gps_traits_decorator<typename Arrangement_::Geometry_traits_2,
|
||||||
Gps_agg_curve_data<Arrangement_>,
|
Gps_agg_curve_data<Arrangement_>,
|
||||||
Point_with_vertex<Arrangement_> >
|
Point_with_vertex<Arrangement_> >
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
typedef typename Arrangement::Traits_2 Traits;
|
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||||
|
|
||||||
typedef typename Traits::X_monotone_curve_2 Base_X_monotone_curve_2;
|
typedef typename Traits::X_monotone_curve_2 Base_X_monotone_curve_2;
|
||||||
typedef typename Traits::Point_2 Base_Point_2;
|
typedef typename Traits::Point_2 Base_Point_2;
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,22 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_AGG_OP_H
|
#ifndef CGAL_GPS_AGG_OP_H
|
||||||
#define CGAL_GPS_AGG_OP_H
|
#define CGAL_GPS_AGG_OP_H
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file Gps_agg_op.h
|
||||||
|
\brief The class Gps_agg_op is responsible for aggregated Boolean set
|
||||||
|
operations depending on a visitor template parameter.
|
||||||
|
It uses the sweep-line algorithm from the arrangement packages
|
||||||
|
to overlay all the polygon sets, and then it uses a BFS that
|
||||||
|
determines which of the faces is contained in the result using
|
||||||
|
the visitor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_sweep.h>
|
||||||
#include <CGAL/Sweep_line_2/Arr_construction_subcurve.h>
|
#include <CGAL/Sweep_line_2/Arr_construction_subcurve.h>
|
||||||
|
|
@ -38,7 +50,7 @@ template <class Arrangement_, class Bfs_visitor_>
|
||||||
class Gps_agg_op
|
class Gps_agg_op
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement_2;
|
typedef Arrangement_ Arrangement_2;
|
||||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
typedef typename Arrangement_2::Geometry_traits_2 Traits_2;
|
||||||
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;
|
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;
|
||||||
typedef Gps_agg_meta_traits<Arrangement_2> Meta_traits;
|
typedef Gps_agg_meta_traits<Arrangement_2> Meta_traits;
|
||||||
typedef typename Meta_traits::Curve_data Curve_data;
|
typedef typename Meta_traits::Curve_data Curve_data;
|
||||||
|
|
@ -120,8 +132,10 @@ public:
|
||||||
|
|
||||||
for (i = lower; i <= upper; i += jump, ++n_pgn)
|
for (i = lower; i <= upper; i += jump, ++n_pgn)
|
||||||
{
|
{
|
||||||
|
// The BFS scan (after the loop) starts in the reference face,
|
||||||
|
// so we count the number of polygons that contain the reference face.
|
||||||
Arrangement_2* arr = (arr_vec[i]).first;
|
Arrangement_2* arr = (arr_vec[i]).first;
|
||||||
if (arr->unbounded_face()->contained())
|
if (arr->reference_face()->contained())
|
||||||
++n_inf_pgn;
|
++n_inf_pgn;
|
||||||
|
|
||||||
Edge_iterator itr = arr->edges_begin();
|
Edge_iterator itr = arr->edges_begin();
|
||||||
|
|
@ -144,9 +158,9 @@ public:
|
||||||
lower, upper, jump,
|
lower, upper, jump,
|
||||||
arr_vec);
|
arr_vec);
|
||||||
|
|
||||||
m_faces_hash[m_arr->unbounded_face()] = n_inf_pgn;
|
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||||
visitor.visit_ubf(m_arr->unbounded_face(), n_inf_pgn);
|
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||||
Bfs_scanner scanner(visitor);
|
Bfs_scanner scanner(visitor);
|
||||||
scanner.scan(*m_arr);
|
scanner.scan(*m_arr);
|
||||||
visitor.after_scan(*m_arr);
|
visitor.after_scan(*m_arr);
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ private:
|
||||||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ? SMALLER : LARGER;
|
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ? SMALLER : LARGER;
|
||||||
|
|
||||||
const Comparison_result cv_dir =
|
const Comparison_result cv_dir =
|
||||||
this->m_arr_access.arrangement().traits()->
|
this->m_arr_access.arrangement().geometry_traits()->
|
||||||
compare_endpoints_xy_2_object()(cv);
|
compare_endpoints_xy_2_object()(cv);
|
||||||
|
|
||||||
if (he_dir == cv_dir)
|
if (he_dir == cv_dir)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BPS_BASE_VISITOR_H
|
#ifndef CGAL_GPS_BPS_BASE_VISITOR_H
|
||||||
#define CGAL_GPS_BPS_BASE_VISITOR_H
|
#define CGAL_GPS_BPS_BASE_VISITOR_H
|
||||||
|
|
@ -24,7 +25,14 @@
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <class Arrangement_>
|
//! Gps_bfs_base_visitor
|
||||||
|
/*! This is a base class for all visitors that are responsible for merging
|
||||||
|
polygon sets.
|
||||||
|
We use DerivedVisitor for static polymorphism for using contained_criteria
|
||||||
|
which determines if we should mark the face as contained given the inside
|
||||||
|
count of the face.
|
||||||
|
*/
|
||||||
|
template <class Arrangement_, class DerivedVisitor>
|
||||||
class Gps_bfs_base_visitor
|
class Gps_bfs_base_visitor
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
|
|
@ -50,23 +58,38 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
void flip_face(Face_iterator f1, Face_iterator f2, Halfedge_iterator he)
|
//! discovered_face
|
||||||
|
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||||
|
during a BFS scan. In the BFS traversal we are going from old_face to
|
||||||
|
new_face throught the half-edge he.
|
||||||
|
\param old_face The face that was already revealed
|
||||||
|
\param new_face The face that we have just now revealed
|
||||||
|
\param he The half-edge that is used to traverse between them.
|
||||||
|
*/
|
||||||
|
void discovered_face(Face_iterator old_face,
|
||||||
|
Face_iterator new_face,
|
||||||
|
Halfedge_iterator he)
|
||||||
{
|
{
|
||||||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
unsigned int ic = compute_ic(old_face, new_face, he);
|
||||||
m_edges_hash->is_defined(he->twin()) &&
|
|
||||||
m_faces_hash->is_defined(f1) &&
|
|
||||||
!m_faces_hash->is_defined(f2));
|
|
||||||
|
|
||||||
// IC of f2 (inside counter)
|
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ic))
|
||||||
unsigned int ic_f2 =
|
new_face->set_contained(true);
|
||||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
}
|
||||||
(*m_faces_hash)[f2] = ic_f2;
|
|
||||||
|
// mark the unbounded_face (true iff contained)
|
||||||
|
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
||||||
|
{
|
||||||
|
CGAL_assertion(ubf->number_of_outer_ccbs() == 0);
|
||||||
|
if(static_cast<DerivedVisitor*>(this)->contained_criteria(ubf_ic))
|
||||||
|
ubf->set_contained(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// compute the inside count of a face
|
// compute the inside count of a face
|
||||||
unsigned int compute_ic(Face_iterator f1, Face_iterator f2, Halfedge_iterator he)
|
unsigned int compute_ic(Face_iterator f1,
|
||||||
|
Face_iterator f2,
|
||||||
|
Halfedge_iterator he)
|
||||||
{
|
{
|
||||||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
||||||
m_edges_hash->is_defined(he->twin()) &&
|
m_edges_hash->is_defined(he->twin()) &&
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||||
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||||
|
|
||||||
|
|
@ -25,12 +28,14 @@
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Gps_bfs_intersection_visitor : public Gps_bfs_base_visitor<Arrangement_>
|
class Gps_bfs_intersection_visitor :
|
||||||
|
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_> >
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||||
typedef Gps_bfs_base_visitor<Arrangement> Base;
|
typedef Gps_bfs_intersection_visitor<Arrangement> Self;
|
||||||
|
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||||
typedef typename Base::Edges_hash Edges_hash;
|
typedef typename Base::Edges_hash Edges_hash;
|
||||||
typedef typename Base::Faces_hash Faces_hash;
|
typedef typename Base::Faces_hash Faces_hash;
|
||||||
|
|
||||||
|
|
@ -44,33 +49,23 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
void flip_face(Face_iterator f1, Face_iterator f2, Halfedge_iterator he)
|
//! contained_criteria
|
||||||
|
/*! contained_criteria is used to the determine if the face which has
|
||||||
|
inside count should be marked as contained.
|
||||||
|
\param ic the inner count of the talked-about face.
|
||||||
|
\return true if the face of ic, otherwise false.
|
||||||
|
*/
|
||||||
|
bool contained_criteria(unsigned int ic)
|
||||||
{
|
{
|
||||||
unsigned int ic_f2;
|
// intersection means that all polygons contain the face.
|
||||||
ic_f2 = this->compute_ic(f1, f2, he);
|
CGAL_assertion(ic <= this->m_num_of_polygons);
|
||||||
(*(this->m_faces_hash))[f2] = ic_f2;
|
return (ic == this->m_num_of_polygons);
|
||||||
|
|
||||||
CGAL_assertion(ic_f2 <= this->m_num_of_polygons);
|
|
||||||
|
|
||||||
// only faces that have inside counter equal to the number of polygons
|
|
||||||
// which are intersectd, will be marked true (containted)
|
|
||||||
if(ic_f2 == this->m_num_of_polygons)
|
|
||||||
f2->set_contained(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark the unbounded_face (true iff contained)
|
|
||||||
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
|
||||||
{
|
|
||||||
CGAL_assertion(ubf->is_unbounded());
|
|
||||||
if(ubf_ic == this->m_num_of_polygons)
|
|
||||||
ubf->set_contained(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void after_scan(Arrangement&)
|
void after_scan(Arrangement&)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CGAL_END_NAMESPACE
|
CGAL_END_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BFS_JOIN_VISITOR_H
|
#ifndef CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||||
#define CGAL_GPS_BFS_JOIN_VISITOR_H
|
#define CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||||
|
|
@ -25,12 +26,14 @@
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Gps_bfs_join_visitor : public Gps_bfs_base_visitor<Arrangement_>
|
class Gps_bfs_join_visitor :
|
||||||
|
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_join_visitor<Arrangement_> >
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||||
typedef Gps_bfs_base_visitor<Arrangement> Base;
|
typedef Gps_bfs_join_visitor<Arrangement> Self;
|
||||||
|
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||||
typedef typename Base::Edges_hash Edges_hash;
|
typedef typename Base::Edges_hash Edges_hash;
|
||||||
typedef typename Base::Faces_hash Faces_hash;
|
typedef typename Base::Faces_hash Faces_hash;
|
||||||
|
|
||||||
|
|
@ -40,23 +43,16 @@ public:
|
||||||
Base(edges_hash, faces_hash, n_pgn)
|
Base(edges_hash, faces_hash, n_pgn)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
//! contained_criteria
|
||||||
void flip_face(Face_iterator f1, Face_iterator f2, Halfedge_iterator he)
|
/*! contained_criteria is used to the determine if the face which has
|
||||||
|
inside count should be marked as contained.
|
||||||
|
\param ic the inner count of the talked-about face.
|
||||||
|
\return true if the face of ic, otherwise false.
|
||||||
|
*/
|
||||||
|
bool contained_criteria(unsigned int ic)
|
||||||
{
|
{
|
||||||
unsigned int ic_f2;
|
// at least one polygon contains the face.
|
||||||
ic_f2 = this->compute_ic(f1, f2, he);
|
return (ic > 0);
|
||||||
(*(this->m_faces_hash))[f2] = ic_f2;
|
|
||||||
|
|
||||||
if(ic_f2 > 0)
|
|
||||||
f2->set_contained(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark the unbounded_face
|
|
||||||
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
|
||||||
{
|
|
||||||
CGAL_assertion(ubf->is_unbounded());
|
|
||||||
if(ubf_ic > 0)
|
|
||||||
ubf->set_contained(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void after_scan(Arrangement&)
|
void after_scan(Arrangement&)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BFS_SCANNER_H
|
#ifndef CGAL_GPS_BFS_SCANNER_H
|
||||||
#define CGAL_GPS_BFS_SCANNER_H
|
#define CGAL_GPS_BFS_SCANNER_H
|
||||||
|
|
@ -30,7 +31,7 @@ class Gps_bfs_scanner
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
|
|
||||||
typedef typename Arrangement::Inner_ccb_iterator Hole_iterator;
|
typedef typename Arrangement::Inner_ccb_iterator Inner_ccb_iterator;
|
||||||
typedef typename Arrangement::Ccb_halfedge_circulator
|
typedef typename Arrangement::Ccb_halfedge_circulator
|
||||||
Ccb_halfedge_circulator;
|
Ccb_halfedge_circulator;
|
||||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||||
|
|
@ -40,7 +41,7 @@ class Gps_bfs_scanner
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Visitor* m_visitor;
|
Visitor* m_visitor;
|
||||||
std::queue<Hole_iterator> m_holes;
|
std::queue<Inner_ccb_iterator> m_holes;
|
||||||
std::stack<Ccb_halfedge_circulator> m_ccb_stcak;
|
std::stack<Ccb_halfedge_circulator> m_ccb_stcak;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -50,17 +51,25 @@ public:
|
||||||
|
|
||||||
void scan(Arrangement& arr)
|
void scan(Arrangement& arr)
|
||||||
{
|
{
|
||||||
Face_iterator ubf = arr.unbounded_face();
|
Face_iterator ubf;
|
||||||
|
for (ubf = arr.faces_begin(); ubf != arr.faces_end(); ++ubf)
|
||||||
|
{
|
||||||
|
if (ubf->number_of_outer_ccbs() != 0)
|
||||||
|
continue;
|
||||||
|
if (ubf->visited() == true)
|
||||||
|
continue;
|
||||||
|
|
||||||
ubf->set_visited(true);
|
ubf->set_visited(true);
|
||||||
push_to_queue_holes_of_face(ubf);
|
push_to_queue_holes_of_face(ubf);
|
||||||
|
|
||||||
while(!m_holes.empty())
|
while(!m_holes.empty())
|
||||||
{
|
{
|
||||||
Hole_iterator hole = m_holes.front();
|
Inner_ccb_iterator hole = m_holes.front();
|
||||||
m_holes.pop();
|
m_holes.pop();
|
||||||
scan(*hole);
|
scan(*hole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void scan(Ccb_halfedge_circulator ccb)
|
void scan(Ccb_halfedge_circulator ccb)
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +95,7 @@ public:
|
||||||
{
|
{
|
||||||
push_to_queue_holes_of_face(he->twin()->face());
|
push_to_queue_holes_of_face(he->twin()->face());
|
||||||
new_f->set_visited(true);
|
new_f->set_visited(true);
|
||||||
m_visitor->flip_face(he->face(), new_f, he);
|
m_visitor->discovered_face(he->face(), new_f, he);
|
||||||
|
|
||||||
//scan(he->twin());
|
//scan(he->twin());
|
||||||
m_ccb_stcak.push(he->twin());
|
m_ccb_stcak.push(he->twin());
|
||||||
|
|
@ -99,7 +108,8 @@ public:
|
||||||
|
|
||||||
void push_to_queue_holes_of_face(Face_iterator f)
|
void push_to_queue_holes_of_face(Face_iterator f)
|
||||||
{
|
{
|
||||||
for(Hole_iterator hit = f->holes_begin(); hit!= f->holes_end(); ++hit)
|
for(Inner_ccb_iterator hit = f->inner_ccbs_begin();
|
||||||
|
hit!= f->inner_ccbs_end(); ++hit)
|
||||||
{
|
{
|
||||||
m_holes.push(hit);
|
m_holes.push(hit);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BFS_XOR_VISITOR_H
|
#ifndef CGAL_GPS_BFS_XOR_VISITOR_H
|
||||||
#define CGAL_GPS_BFS_XOR_VISITOR_H
|
#define CGAL_GPS_BFS_XOR_VISITOR_H
|
||||||
|
|
@ -25,43 +26,45 @@
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Gps_bfs_xor_visitor : public Gps_bfs_base_visitor<Arrangement_>
|
class Gps_bfs_xor_visitor :
|
||||||
|
public Gps_bfs_base_visitor<Arrangement_, Gps_bfs_xor_visitor<Arrangement_> >
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement;
|
typedef Arrangement_ Arrangement;
|
||||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||||
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
typedef typename Arrangement::Halfedge_iterator Halfedge_iterator;
|
||||||
typedef Gps_bfs_base_visitor<Arrangement> Base;
|
typedef Gps_bfs_xor_visitor<Arrangement> Self;
|
||||||
|
typedef Gps_bfs_base_visitor<Arrangement, Self> Base;
|
||||||
typedef typename Base::Edges_hash Edges_hash;
|
typedef typename Base::Edges_hash Edges_hash;
|
||||||
typedef typename Base::Faces_hash Faces_hash;
|
typedef typename Base::Faces_hash Faces_hash;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Gps_bfs_xor_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash, unsigned int n_pgn):
|
Gps_bfs_xor_visitor(Edges_hash* edges_hash, Faces_hash* faces_hash,
|
||||||
|
unsigned int n_pgn) :
|
||||||
Base(edges_hash, faces_hash, n_pgn)
|
Base(edges_hash, faces_hash, n_pgn)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
//! contained_criteria
|
||||||
void flip_face(Face_iterator f1, Face_iterator f2, Halfedge_iterator he)
|
/*! contained_criteria is used to the determine if the face which has
|
||||||
|
inside count should be marked as contained.
|
||||||
|
\param ic the inner count of the talked-about face.
|
||||||
|
\return true if the face of ic, otherwise false.
|
||||||
|
*/
|
||||||
|
bool contained_criteria(unsigned int ic)
|
||||||
{
|
{
|
||||||
unsigned int ic_f2;
|
// xor means odd number of polygons.
|
||||||
ic_f2 = this->compute_ic(f1, f2, he);
|
return (ic % 2) == 1;
|
||||||
(*(this->m_faces_hash))[f2] = ic_f2;
|
|
||||||
|
|
||||||
if(ic_f2%2)
|
|
||||||
f2->set_contained(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark the unbounded_face (true iff contained)
|
//! after_scan post-processing after bfs scan.
|
||||||
void visit_ubf(Face_iterator ubf, unsigned int ubf_ic)
|
/*! The function fixes some of the curves, to be in the same direction as the
|
||||||
{
|
half-edges.
|
||||||
CGAL_assertion(ubf->is_unbounded());
|
|
||||||
if(ubf_ic%2)
|
|
||||||
ubf->set_contained(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
\param arr The given arrangment.
|
||||||
|
*/
|
||||||
void after_scan(Arrangement& arr)
|
void after_scan(Arrangement& arr)
|
||||||
{
|
{
|
||||||
typedef typename Arrangement::Traits_2 Traits;
|
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||||
typedef typename Traits::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
typedef typename Traits::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
||||||
typedef typename Traits::Construct_opposite_2 Construct_opposite_2;
|
typedef typename Traits::Construct_opposite_2 Construct_opposite_2;
|
||||||
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
|
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
|
||||||
|
|
@ -79,7 +82,8 @@ public:
|
||||||
Halfedge_iterator he = eit;
|
Halfedge_iterator he = eit;
|
||||||
const X_monotone_curve_2& cv = he->curve();
|
const X_monotone_curve_2& cv = he->curve();
|
||||||
const bool is_cont = he->face()->contained();
|
const bool is_cont = he->face()->contained();
|
||||||
const Comparison_result he_res = ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
const Comparison_result he_res =
|
||||||
|
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
|
||||||
SMALLER : LARGER;
|
SMALLER : LARGER;
|
||||||
const bool has_same_dir = (cmp_endpoints(cv) == he_res);
|
const bool has_same_dir = (cmp_endpoints(cv) == he_res);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,30 @@
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_join_visitor.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_bfs_join_visitor.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <class Arrangement_>
|
/*!
|
||||||
class Join_merge
|
\file Gps_merge.h
|
||||||
|
\brief This file contains classes that are responsible for merging
|
||||||
|
two sets of polygons in the divide-and-conquer algorithm.
|
||||||
|
The file contains 3 mergers: Join_merge, Intersection_merge and
|
||||||
|
Xor_merge. Join_merge is used when we want to merge the two sets,
|
||||||
|
Intersection_merge is used for intersection, and Xor_merge is used
|
||||||
|
for symmetric difference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! Base_merge
|
||||||
|
/*! Base_merge is the base class for all merger classes.
|
||||||
|
All merges used BFS algorithm with a different visitor when discovering
|
||||||
|
a new face.
|
||||||
|
*/
|
||||||
|
template <class Arrangement_, class Visitor_>
|
||||||
|
class Base_merge
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement_2;
|
typedef Arrangement_ Arrangement_2;
|
||||||
|
typedef Visitor_ Visitor;
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
typedef std::pair<Arrangement_2 *,
|
typedef std::pair<Arrangement_2 *,
|
||||||
std::vector<Vertex_handle> *> Arr_entry;
|
std::vector<Vertex_handle> *> Arr_entry;
|
||||||
|
|
@ -46,12 +61,12 @@ public:
|
||||||
if(i==j)
|
if(i==j)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
typename Arrangement_2::Traits_2* tr = arr_vec[i].first->traits();
|
typename Arrangement_2::Geometry_traits_2* tr =
|
||||||
|
arr_vec[i].first->geometry_traits();
|
||||||
Arrangement_2 *res = new Arrangement_2(tr);
|
Arrangement_2 *res = new Arrangement_2(tr);
|
||||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
||||||
|
|
||||||
Gps_agg_op<Arrangement_2, Gps_bfs_join_visitor<Arrangement_2> >
|
Gps_agg_op<Arrangement_2, Visitor> agg_op(*res, *verts, *tr);
|
||||||
agg_op(*res, *verts, *tr);
|
|
||||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||||
|
|
||||||
for(unsigned int count=i; count<=j; count+=jump)
|
for(unsigned int count=i; count<=j; count+=jump)
|
||||||
|
|
@ -66,82 +81,33 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Join_merge
|
||||||
|
/*! Join_merge is used to join two sets of polygons together in the D&C
|
||||||
|
algorithm. It is a base merge with a visitor that joins faces.
|
||||||
|
*/
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Intersection_merge
|
class Join_merge : public Base_merge<Arrangement_,
|
||||||
{
|
Gps_bfs_join_visitor<Arrangement_> >
|
||||||
typedef Arrangement_ Arrangement_2;
|
{};
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
|
||||||
typedef std::pair<Arrangement_2 *,
|
|
||||||
std::vector<Vertex_handle> *> Arr_entry;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void operator()(unsigned int i,
|
|
||||||
unsigned int j,
|
|
||||||
unsigned int jump,
|
|
||||||
std::vector<Arr_entry>& arr_vec)
|
|
||||||
{
|
|
||||||
if(i==j)
|
|
||||||
return;
|
|
||||||
|
|
||||||
typename Arrangement_2::Traits_2* tr = arr_vec[i].first->traits();
|
|
||||||
Arrangement_2 *res = new Arrangement_2 (tr);
|
|
||||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
|
||||||
|
|
||||||
Gps_agg_op<Arrangement_2, Gps_bfs_intersection_visitor<Arrangement_2> >
|
|
||||||
agg_op(*res, *verts, *tr);
|
|
||||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
|
||||||
|
|
||||||
for(unsigned int count=i; count<=j; count+=jump)
|
|
||||||
{
|
|
||||||
delete (arr_vec[count].first);
|
|
||||||
delete (arr_vec[count].second);
|
|
||||||
}
|
|
||||||
|
|
||||||
arr_vec[i].first = res;
|
|
||||||
arr_vec[i].second = verts;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
//! Intersection_merge
|
||||||
|
/*! Intersection_merge is used to merge two sets of polygons creating their
|
||||||
|
intersection.
|
||||||
|
*/
|
||||||
template <class Arrangement_>
|
template <class Arrangement_>
|
||||||
class Xor_merge
|
class Intersection_merge : public Base_merge<Arrangement_,
|
||||||
|
Gps_bfs_intersection_visitor<Arrangement_> >
|
||||||
|
{};
|
||||||
|
|
||||||
|
//! Xor_merge
|
||||||
|
/*! Xor_merge is used to merge two sets of polygons creating their
|
||||||
|
symmetric difference.
|
||||||
|
*/
|
||||||
|
template <class Arrangement_>
|
||||||
|
class Xor_merge : public Base_merge<Arrangement_,
|
||||||
|
Gps_bfs_xor_visitor<Arrangement_> >
|
||||||
{
|
{
|
||||||
typedef Arrangement_ Arrangement_2;
|
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
|
||||||
typedef std::pair<Arrangement_2 *,
|
|
||||||
std::vector<Vertex_handle> *> Arr_entry;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Temporarily defined to see if this avoids a warning on SunPro CC
|
|
||||||
Xor_merge()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void operator()(unsigned int i,
|
|
||||||
unsigned int j,
|
|
||||||
unsigned int jump,
|
|
||||||
std::vector<Arr_entry>& arr_vec)
|
|
||||||
{
|
|
||||||
if(i==j)
|
|
||||||
return;
|
|
||||||
|
|
||||||
typename Arrangement_2::Traits_2* tr = arr_vec[i].first->traits();
|
|
||||||
Arrangement_2 *res = new Arrangement_2(tr);
|
|
||||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
|
||||||
|
|
||||||
Gps_agg_op<Arrangement_2, Gps_bfs_xor_visitor<Arrangement_2> >
|
|
||||||
agg_op(*res, *verts, *tr);
|
|
||||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
|
||||||
|
|
||||||
for(unsigned int count=i; count<=j; count+=jump)
|
|
||||||
{
|
|
||||||
delete (arr_vec[count].first);
|
|
||||||
delete (arr_vec[count].second);
|
|
||||||
}
|
|
||||||
|
|
||||||
arr_vec[i].first = res;
|
|
||||||
arr_vec[i].second = verts;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CGAL_END_NAMESPACE
|
CGAL_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,26 @@
|
||||||
#include <CGAL/Arr_naive_point_location.h>
|
#include <CGAL/Arr_naive_point_location.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
#include <CGAL/Arr_default_overlay_traits.h>
|
#include <CGAL/Arr_default_overlay_traits.h>
|
||||||
|
|
||||||
|
#define CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF \
|
||||||
|
typedef Gps_traits_adaptor<Traits_2> Traits_adapter_2; \
|
||||||
|
typedef typename Traits_2::Curve_const_iterator \
|
||||||
|
Curve_const_iterator; \
|
||||||
|
typedef std::pair<Curve_const_iterator,Curve_const_iterator> \
|
||||||
|
Cci_pair; \
|
||||||
|
typedef typename Traits_2::Construct_curves_2 \
|
||||||
|
Construct_curves_2; \
|
||||||
|
typedef typename Traits_adapter_2::Construct_vertex_2 \
|
||||||
|
Construct_vertex_2;
|
||||||
|
|
||||||
|
|
||||||
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*Arrangement is templated with extended face dcel*/
|
/*Arrangement is templated with extended face dcel*/
|
||||||
template<typename Arrangement_2>
|
template<typename Arrangement_2>
|
||||||
class ValidationOverlayTraits : public CGAL::Arr_default_overlay_traits<Arrangement_2>
|
class ValidationOverlayTraits :
|
||||||
|
public CGAL::Arr_default_overlay_traits<Arrangement_2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef CGAL::Arr_default_overlay_traits<Arrangement_2> Base;
|
typedef CGAL::Arr_default_overlay_traits<Arrangement_2> Base;
|
||||||
|
|
@ -49,7 +63,7 @@ public:
|
||||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
||||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
typedef typename Arrangement_2::Hole_const_iterator Hole_const_iterator;
|
typedef typename Arrangement_2::Inner_ccb_const_iterator Inner_ccb_const_iterator;
|
||||||
|
|
||||||
/*red faces source is the arrangement of holes. The blue faces (face) are caused by the PWH's outer boundary*/
|
/*red faces source is the arrangement of holes. The blue faces (face) are caused by the PWH's outer boundary*/
|
||||||
virtual void create_face(Face_handle_A red_face, Face_handle_B blue_face, Face_handle_R r_face) {
|
virtual void create_face(Face_handle_A red_face, Face_handle_B blue_face, Face_handle_R r_face) {
|
||||||
|
|
@ -71,17 +85,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
/*! \class
|
||||||
|
|
||||||
#define CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF \
|
|
||||||
typedef Gps_traits_adaptor<Traits_2> Traits_adapter_2;\
|
|
||||||
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;\
|
|
||||||
typedef std::pair<Curve_const_iterator,Curve_const_iterator> Cci_pair;\
|
|
||||||
typedef typename Traits_2::Construct_curves_2 Construct_curves_2;\
|
|
||||||
typedef typename Traits_adapter_2::Construct_vertex_2 Construct_vertex_2;
|
|
||||||
|
|
||||||
|
|
||||||
/*! \class
|
|
||||||
* A visitor used for checking whether the edges of a polygon are
|
* A visitor used for checking whether the edges of a polygon are
|
||||||
* non-intersecting.
|
* non-intersecting.
|
||||||
*/
|
*/
|
||||||
|
|
@ -158,9 +162,9 @@ protected:
|
||||||
|
|
||||||
//Traits_2 templates the General_polygon_set_2 Traits.
|
//Traits_2 templates the General_polygon_set_2 Traits.
|
||||||
//These include types for polygon and PWH.
|
//These include types for polygon and PWH.
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_closed_polygon(const typename Traits_2::Polygon_2& pgn, Traits_2 traits)
|
bool is_closed_polygon(const typename Traits_2::Polygon_2& pgn, Traits_2 traits)
|
||||||
{
|
{
|
||||||
|
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||||
|
|
@ -207,10 +211,10 @@ protected:
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_simple_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
bool is_simple_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||||
{// Previously known as is_strictly_simple
|
{// Previously known as is_strictly_simple
|
||||||
|
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
// Sweep the boundary curves and look for intersections.
|
// Sweep the boundary curves and look for intersections.
|
||||||
|
|
@ -223,12 +227,12 @@ protected:
|
||||||
|
|
||||||
visitor.sweep(itr_pair.first, itr_pair.second);
|
visitor.sweep(itr_pair.first, itr_pair.second);
|
||||||
return (visitor.is_valid());
|
return (visitor.is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool has_valid_orientation_polygon (const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
bool has_valid_orientation_polygon (const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||||
{
|
{
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
|
|
||||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||||
|
|
@ -240,15 +244,15 @@ protected:
|
||||||
|
|
||||||
return (traits_adapter.orientation_2_object()(itr_pair.first,
|
return (traits_adapter.orientation_2_object()(itr_pair.first,
|
||||||
itr_pair.second) == COUNTERCLOCKWISE);
|
itr_pair.second) == COUNTERCLOCKWISE);
|
||||||
}
|
}
|
||||||
/* A valid polygon is :
|
/* A valid polygon is :
|
||||||
* 1 - Closed or empty polygon
|
* 1 - Closed or empty polygon
|
||||||
* 2 - Simple (previously known as strictly simple)
|
* 2 - Simple (previously known as strictly simple)
|
||||||
* 3 - Counterclockwise oriented
|
* 3 - Counterclockwise oriented
|
||||||
*/
|
*/
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_valid_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
bool is_valid_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||||
{
|
{
|
||||||
bool closed = is_closed_polygon(pgn,traits);
|
bool closed = is_closed_polygon(pgn,traits);
|
||||||
CGAL_warning_msg (closed,
|
CGAL_warning_msg (closed,
|
||||||
"The polygon's boundary is not closed.");
|
"The polygon's boundary is not closed.");
|
||||||
|
|
@ -268,12 +272,12 @@ protected:
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_closed_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
bool is_closed_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||||
{
|
{
|
||||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||||
if(! is_closed_polygon (pgn.outer_boundary(),traits))
|
if(! is_closed_polygon (pgn.outer_boundary(),traits))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
@ -286,11 +290,11 @@ protected:
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//templated point location version
|
||||||
template<typename Traits_2>
|
template<typename Traits_2, class PointLocation>
|
||||||
bool is_crossover_outer_boundary(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits ) {
|
bool is_crossover_outer_boundary(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits, PointLocation& pl ) {
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
typedef typename Traits_2::Point_2 Point_2;
|
typedef typename Traits_2::Point_2 Point_2;
|
||||||
typedef typename Traits_2::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
typedef typename Traits_2::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
||||||
|
|
@ -304,7 +308,6 @@ protected:
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;
|
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;
|
||||||
typedef CGAL::Arr_naive_point_location<Arrangement_2> Naive_pl;
|
|
||||||
|
|
||||||
typename std::list<Halfedge_handle> he_path;
|
typename std::list<Halfedge_handle> he_path;
|
||||||
typename std::list<Halfedge_handle>::iterator he_itr;
|
typename std::list<Halfedge_handle>::iterator he_itr;
|
||||||
|
|
@ -331,7 +334,8 @@ protected:
|
||||||
|
|
||||||
Polygon_set_2 gps(traits);
|
Polygon_set_2 gps(traits);
|
||||||
Arrangement_2 arr = gps.arrangement();
|
Arrangement_2 arr = gps.arrangement();
|
||||||
Naive_pl pl (arr);
|
pl.attach(arr);
|
||||||
|
|
||||||
//insert first edge lexicographically to arrangement
|
//insert first edge lexicographically to arrangement
|
||||||
// compute the joint vertex and insert to the path list a halfedge whose target is the joint vertex
|
// compute the joint vertex and insert to the path list a halfedge whose target is the joint vertex
|
||||||
last_he = CGAL::insert_non_intersecting_curve(arr, *curr);
|
last_he = CGAL::insert_non_intersecting_curve(arr, *curr);
|
||||||
|
|
@ -375,129 +379,42 @@ protected:
|
||||||
curr = next;
|
curr = next;
|
||||||
++next;
|
++next;
|
||||||
} //end of while
|
} //end of while
|
||||||
/*We created a path of halfedges that circulates the polygon counterclockwise (curves . The
|
|
||||||
polygon should ly on the left of each of these half edges. If the boundary is invalid, the unbounded face should
|
// We created a path of halfedges that circulates the polygon counterclockwise
|
||||||
be on the left of one of more than one of the halfedges*/
|
// The polygon should lay on the left of each of these half edges.
|
||||||
typename Arrangement_2::Face_const_handle cfh;
|
// If the boundary is invalid, the unbounded face should
|
||||||
typename Arrangement_2::Face_handle fh;
|
// be on the left of one of more than one of the halfedges.
|
||||||
cfh = arr.unbounded_face();
|
// The unbounded face is always to the right of the halfedges. We check if
|
||||||
fh = arr.non_const_handle(cfh);
|
// all faces that lay on the right of the halfedges are equal (to the
|
||||||
for (he_itr = he_path.begin();he_itr != he_path.end();he_itr++) {
|
// "unbounded" face).
|
||||||
Halfedge_handle cur = *he_itr;
|
typename Arrangement_2::Face_handle fh = (*he_path.begin())->twin()->face();
|
||||||
if (cur->face() == fh)
|
for (he_itr = he_path.begin(); he_itr != he_path.end(); he_itr++) {
|
||||||
|
|
||||||
|
if ((*he_itr)->twin()->face() != fh)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Traits_2>
|
||||||
|
bool is_crossover_outer_boundary(
|
||||||
|
const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits ) {
|
||||||
|
|
||||||
|
typedef CGAL::Gps_default_dcel<Traits_2> Dcel;
|
||||||
//templated point location version
|
typedef CGAL::General_polygon_set_2<Traits_2, Dcel> Polygon_set_2;
|
||||||
template<typename Traits_2, class PointLocation>
|
|
||||||
bool is_crossover_outer_boundary(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits, const PointLocation& pl ) {
|
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
|
||||||
typedef typename Traits_2::Point_2 Point_2;
|
|
||||||
typedef typename Traits_2::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
|
||||||
typedef typename Traits_2::Construct_min_vertex_2 Construct_min_vertex_2;
|
|
||||||
typedef typename Traits_2::Construct_max_vertex_2 Construct_max_vertex_2;
|
|
||||||
typedef CGAL::Gps_default_dcel<Traits_2> dcel;
|
|
||||||
typedef CGAL::General_polygon_set_2<Traits_2, dcel> Polygon_set_2;
|
|
||||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
|
||||||
typedef typename Polygon_set_2::Arrangement_2 Arrangement_2;
|
typedef typename Polygon_set_2::Arrangement_2 Arrangement_2;
|
||||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
|
||||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
|
||||||
typedef typename Traits_2::Curve_const_iterator Curve_const_iterator;
|
|
||||||
typedef CGAL::Arr_naive_point_location<Arrangement_2> Naive_pl;
|
typedef CGAL::Arr_naive_point_location<Arrangement_2> Naive_pl;
|
||||||
|
|
||||||
typename std::list<Halfedge_handle> he_path;
|
Naive_pl pl;
|
||||||
typename std::list<Halfedge_handle>::iterator he_itr;
|
return is_crossover_outer_boundary(pgn, traits, pl);
|
||||||
//functors used throughout the function
|
}
|
||||||
Construct_min_vertex_2 min_functor = traits.construct_min_vertex_2_object();
|
|
||||||
Construct_max_vertex_2 max_functor = traits.construct_max_vertex_2_object();
|
|
||||||
Compare_endpoints_xy_2 cmp_endpoints = traits.compare_endpoints_xy_2_object();
|
|
||||||
|
|
||||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn.outer_boundary());
|
|
||||||
Curve_const_iterator begin = itr_pair.first;
|
|
||||||
Curve_const_iterator end = itr_pair.second;
|
|
||||||
if (begin == end)
|
|
||||||
return (true); // An empty polygon is valid.
|
|
||||||
//handles to consecutive curves
|
|
||||||
Curve_const_iterator curr, next;
|
|
||||||
curr = next = begin;
|
|
||||||
//handles to vertices for insert. one maintains the current curve (already inserted) and next curve's joint vertex.
|
|
||||||
//the other maintains the next curve's second vertex if it already exists in the arrangement.
|
|
||||||
Vertex_handle joint_ver, second_ver;
|
|
||||||
//closed check guarantees polygon has more than 1 curve
|
|
||||||
++next;
|
|
||||||
//halfedge handle whose target is always the joint vertex between next and curr.
|
|
||||||
Halfedge_handle last_he;
|
|
||||||
|
|
||||||
Polygon_set_2 gps(traits);
|
|
||||||
Arrangement_2 arr = gps.arrangement();
|
|
||||||
//insert first edge lexicographically to arrangement
|
|
||||||
// compute the joint vertex and insert to the path list a halfedge whose target is the joint vertex
|
|
||||||
last_he = CGAL::insert_non_intersecting_curve(arr, *curr);
|
|
||||||
if (cmp_endpoints(*curr) == SMALLER) { //polygon's boundary first curve is in lexicographic direction
|
|
||||||
joint_ver = last_he->target();
|
|
||||||
he_path.push_back(last_he);
|
|
||||||
} else { //polygon's boundary first curve not lexicographic
|
|
||||||
joint_ver = last_he->source();
|
|
||||||
he_path.push_back(last_he->twin());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*insert the rest of the curves to the arrangement efficiently the previous closed polygon check guarantees
|
|
||||||
equal_func (construct_vertex_func (*curr, 1), construct_vertex_func (*next, 0))) */
|
|
||||||
while (next != end) {
|
|
||||||
CGAL::Object obj;
|
|
||||||
Vertex_const_handle cver;
|
|
||||||
Point_2 second_point;
|
|
||||||
if(cmp_endpoints(*next) == SMALLER) {
|
|
||||||
//next curve's minimum is the joint vertex. Look if it's max exists in the arrangement and insert lexicographically
|
|
||||||
second_point = max_functor(*next);
|
|
||||||
obj = pl.locate(second_point);
|
|
||||||
if (CGAL::assign (cver, obj)) {
|
|
||||||
//insert where both vertices exist
|
|
||||||
second_ver = arr.non_const_handle(cver);
|
|
||||||
last_he = arr.insert_at_vertices( *next, joint_ver, second_ver);
|
|
||||||
} else //insert from left vertex
|
|
||||||
last_he = arr.insert_from_left_vertex ( *next,joint_ver) ;
|
|
||||||
} else { //next curve's maximum vertex is the joint vertex. try to locate the min vertex, and insert from right or from both vertices
|
|
||||||
second_point = min_functor(*next);
|
|
||||||
obj = pl.locate(second_point);
|
|
||||||
if (CGAL::assign (cver, obj)) {
|
|
||||||
//insert where both vertices exist
|
|
||||||
second_ver = arr.non_const_handle(cver);
|
|
||||||
last_he = arr.insert_at_vertices( *next, joint_ver, second_ver);
|
|
||||||
} else //insert from right vertex
|
|
||||||
last_he = arr.insert_from_right_vertex ( *next,joint_ver) ;
|
|
||||||
}
|
|
||||||
// Move to the next pair of edges.
|
|
||||||
he_path.push_back(last_he);
|
|
||||||
joint_ver=last_he->target();
|
|
||||||
curr = next;
|
|
||||||
++next;
|
|
||||||
} //end of while
|
|
||||||
/*We created a path of halfedges that circulates the polygon counterclockwise (curves . The
|
|
||||||
polygon should ly on the left of each of these half edges. If the boundary is invalid, the unbounded face should
|
|
||||||
be on the left of one of more than one of the halfedges*/
|
|
||||||
typename Arrangement_2::Face_const_handle cfh;
|
|
||||||
typename Arrangement_2::Face_handle fh;
|
|
||||||
cfh = arr.unbounded_face();
|
|
||||||
fh = arr.non_const_handle(cfh);
|
|
||||||
for (he_itr = he_path.begin();he_itr != he_path.end();he_itr++) {
|
|
||||||
Halfedge_handle cur = *he_itr;
|
|
||||||
if (cur->face() == fh)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Traits_2>
|
|
||||||
bool is_relatively_simple_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
template <typename Traits_2>
|
||||||
{// previously known as Simple
|
bool is_relatively_simple_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||||
|
{// previously known as Simple
|
||||||
|
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||||
|
|
@ -528,13 +445,13 @@ protected:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool has_valid_orientation_polygon_with_holes (const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
bool has_valid_orientation_polygon_with_holes (const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||||
{
|
{
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||||
|
|
@ -571,7 +488,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -579,21 +496,21 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
/*Verify holes do not intersect between themselves as well with the outer boundary
|
/*Verify holes do not intersect between themselves as well with the outer boundary
|
||||||
(except intersection on a vertex which is allowed).
|
(except intersection on a vertex which is allowed).
|
||||||
|
|
||||||
This efficient implementation utilizes the general poygon set for aggregated join
|
This efficient implementation utilizes the general poygon set for aggregated join
|
||||||
operations for N holes which should result in a GPS that contains N independent PWH.
|
operations for N holes which should result in a GPS that contains N independent PWH.
|
||||||
Executing a difference(gps, outer boundary) should result in an empty set if
|
Executing a difference(gps, outer boundary) should result in an empty set if
|
||||||
no holes intersect the boundary.
|
no holes intersect the boundary.
|
||||||
|
|
||||||
An iterative use of the difference free function while iterating over the holes
|
An iterative use of the difference free function while iterating over the holes
|
||||||
may have an advantage in case there are numerous holes that intersect the boundary
|
may have an advantage in case there are numerous holes that intersect the boundary
|
||||||
and the iterative loop will be stopped after a small number of iterations.
|
and the iterative loop will be stopped after a small number of iterations.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
template <class Traits_2>
|
template <class Traits_2>
|
||||||
bool are_holes_and_boundary_pairwise_disjoint(const typename Traits_2::Polygon_with_holes_2& pwh, Traits_2 traits)
|
bool are_holes_and_boundary_pairwise_disjoint(const typename Traits_2::Polygon_with_holes_2& pwh, Traits_2 traits)
|
||||||
{
|
{
|
||||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||||
|
|
||||||
typedef CGAL::Gps_default_dcel<Traits_2> dcel;
|
typedef CGAL::Gps_default_dcel<Traits_2> dcel;
|
||||||
|
|
@ -673,6 +590,7 @@ and the iterative loop will be stopped after a small number of iterations.
|
||||||
*/
|
*/
|
||||||
//check for intersection of holes with the outer boundary
|
//check for intersection of holes with the outer boundary
|
||||||
Hole_const_iterator fit;
|
Hole_const_iterator fit;
|
||||||
|
|
||||||
/*outer boundary can be relatively simple. Execution of
|
/*outer boundary can be relatively simple. Execution of
|
||||||
do_intersect(hole, boundary) or difference(hole,boundary) relies on
|
do_intersect(hole, boundary) or difference(hole,boundary) relies on
|
||||||
implementation of General polygon set which has a precondition that requires
|
implementation of General polygon set which has a precondition that requires
|
||||||
|
|
@ -682,9 +600,12 @@ and the iterative loop will be stopped after a small number of iterations.
|
||||||
outer boundary is valid PWH with no holes. We can't assume it is a valid
|
outer boundary is valid PWH with no holes. We can't assume it is a valid
|
||||||
(simple) polygon. */
|
(simple) polygon. */
|
||||||
Polygon_with_holes_2 boundary(pwh.outer_boundary(), fit, fit);
|
Polygon_with_holes_2 boundary(pwh.outer_boundary(), fit, fit);
|
||||||
//unbounded outer boundaries contain all the holes and are OK
|
|
||||||
|
// Unbounded outer boundaries contain all the holes and the holes were checked
|
||||||
|
// and are OK.
|
||||||
if (boundary.is_unbounded())
|
if (boundary.is_unbounded())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*do_intersect predicate will not suffice as hole can be completely outside
|
/*do_intersect predicate will not suffice as hole can be completely outside
|
||||||
the outer boundary in an (extremely strange) case
|
the outer boundary in an (extremely strange) case
|
||||||
The gps now contains all the holes. the difference between the boundary and a union of all
|
The gps now contains all the holes. the difference between the boundary and a union of all
|
||||||
|
|
@ -709,18 +630,18 @@ and the iterative loop will be stopped after a small number of iterations.
|
||||||
return (false);
|
return (false);
|
||||||
*/
|
*/
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*A valid polygon with holes is :
|
/*A valid polygon with holes is :
|
||||||
* 1 - Has empty or closed boundary and all the holes are closed
|
* 1 - Has empty or closed boundary and all the holes are closed
|
||||||
* 2 - The PWH is relatively simple polygon (holes are simple...)
|
* 2 - The PWH is relatively simple polygon (holes are simple...)
|
||||||
* 3 - Has it's boundary oriented counterclockwise and the holes oriented clockwise
|
* 3 - Has it's boundary oriented counterclockwise and the holes oriented clockwise
|
||||||
* 4 - All the segments (boundry and holes) do not cross or intersect in their relative interior
|
* 4 - All the segments (boundry and holes) do not cross or intersect in their relative interior
|
||||||
* 5 - The holes are on the interior of the boundary polygon if the boundary is not empty
|
* 5 - The holes are on the interior of the boundary polygon if the boundary is not empty
|
||||||
*/
|
*/
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_valid_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
bool is_valid_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||||
{
|
{
|
||||||
bool closed = is_closed_polygon_with_holes(pgn,traits);
|
bool closed = is_closed_polygon_with_holes(pgn,traits);
|
||||||
CGAL_warning_msg (closed,
|
CGAL_warning_msg (closed,
|
||||||
"The polygon's boundary or one of it's holes is not closed.");
|
"The polygon's boundary or one of it's holes is not closed.");
|
||||||
|
|
@ -752,21 +673,21 @@ and the iterative loop will be stopped after a small number of iterations.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_with_holes_2& pgn,
|
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_with_holes_2& pgn,
|
||||||
Traits_2 traits)
|
Traits_2 traits)
|
||||||
{
|
{
|
||||||
return is_valid_polygon_with_holes(pgn, traits);
|
return is_valid_polygon_with_holes(pgn, traits);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Traits_2>
|
template <typename Traits_2>
|
||||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_2& pgn,
|
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_2& pgn,
|
||||||
Traits_2 traits)
|
Traits_2 traits)
|
||||||
{
|
{
|
||||||
return is_valid_polygon(pgn, traits);
|
return is_valid_polygon(pgn, traits);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGAL_END_NAMESPACE
|
CGAL_END_NAMESPACE
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Efi Fogel <efif@post.tau.ac.il>
|
// Efi Fogel <efif@post.tau.ac.il>
|
||||||
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_UTILS_H
|
#ifndef CGAL_GPS_UTILS_H
|
||||||
#define CGAL_GPS_UTILS_H
|
#define CGAL_GPS_UTILS_H
|
||||||
|
|
@ -30,32 +31,47 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
construct_polygon(Ccb_halfedge_const_circulator ccb, Polygon_2 & pgn,
|
construct_polygon(Ccb_halfedge_const_circulator ccb, Polygon_2 & pgn,
|
||||||
Traits_ * tr)
|
Traits_ * tr)
|
||||||
{
|
{
|
||||||
typedef CGAL::Ccb_curve_iterator<Arrangement_2> Ccb_curve_iterator;
|
typedef CGAL::Ccb_curve_iterator<Arrangement_on_surface_2>
|
||||||
|
Ccb_curve_iterator;
|
||||||
Ccb_curve_iterator begin(ccb, false);
|
Ccb_curve_iterator begin(ccb, false);
|
||||||
Ccb_curve_iterator end(ccb, true);
|
Ccb_curve_iterator end(ccb, true);
|
||||||
|
|
||||||
tr->construct_polygon_2_object()(begin, end, pgn);
|
tr->construct_polygon_2_object()(begin, end, pgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The comments below was written after trying to understand what the visitors
|
||||||
|
// do. There was no comment by the author of this class.
|
||||||
|
// This class is used afterwards to extract polygons from the representing
|
||||||
|
// arrangement.
|
||||||
|
// This scanner is not the same as the Gps_bfs_scanner. In this file, the
|
||||||
|
// Gps_bfs_scanner is used with Init_faces_visitor to init the faces of the
|
||||||
|
// representing arrangement.
|
||||||
|
// It seems that Gps_bfs_scanner is used for a regular bfs scan on the faces
|
||||||
|
// of the arrangements, with comparison to Arr_bfs_scanner that cares about
|
||||||
|
// inner ccbs and outer ccbs (it treats them differently).
|
||||||
|
// If this is the case, we should unite Gps_bfs_scanner with the regular
|
||||||
|
// adaptation of arrangement to boost graph.
|
||||||
template <class Arrangement, class OutputIterator>
|
template <class Arrangement, class OutputIterator>
|
||||||
class Arr_bfs_scanner
|
class Arr_bfs_scanner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Arrangement::Traits_2 Gps_traits;
|
typedef typename Arrangement::Geometry_traits_2 Gps_traits;
|
||||||
typedef typename Arrangement::Dcel Gps_dcel;
|
typedef typename Arrangement::Topology_traits Gps_top_traits;
|
||||||
typedef typename Gps_traits::Polygon_2 Polygon_2;
|
typedef typename Gps_traits::Polygon_2 Polygon_2;
|
||||||
typedef typename Gps_traits::Polygon_with_holes_2 Polygon_with_holes_2;
|
typedef typename Gps_traits::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||||
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
||||||
Ccb_halfedge_const_circulator;
|
Ccb_halfedge_const_circulator;
|
||||||
typedef typename Arrangement::Face_const_iterator Face_const_iterator;
|
typedef typename Arrangement::Face_const_iterator Face_const_iterator;
|
||||||
typedef typename Arrangement::Halfedge_const_iterator Halfedge_const_iterator;
|
typedef typename Arrangement::Halfedge_const_iterator Halfedge_const_iterator;
|
||||||
typedef typename Arrangement::Inner_ccb_const_iterator Hole_const_iterator;
|
typedef typename Arrangement::Outer_ccb_const_iterator
|
||||||
|
Outer_ccb_const_iterator;
|
||||||
|
typedef typename Arrangement::Inner_ccb_const_iterator
|
||||||
|
Inner_ccb_const_iterator;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -74,15 +90,20 @@ public:
|
||||||
|
|
||||||
void scan(Arrangement& arr)
|
void scan(Arrangement& arr)
|
||||||
{
|
{
|
||||||
Face_const_iterator ubf = arr.unbounded_face();
|
Face_const_iterator ubf;
|
||||||
Hole_const_iterator holes_it;
|
for (ubf = arr.faces_begin(); ubf != arr.faces_end(); ++ubf)
|
||||||
Face_const_iterator fit;
|
{
|
||||||
|
if (ubf->number_of_outer_ccbs() != 0)
|
||||||
|
continue;
|
||||||
|
if (ubf->visited())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Inner_ccb_const_iterator holes_it;
|
||||||
if (!ubf->contained())
|
if (!ubf->contained())
|
||||||
{
|
{
|
||||||
ubf->set_visited(true);
|
ubf->set_visited(true);
|
||||||
for (holes_it = ubf->holes_begin();
|
for (holes_it = ubf->inner_ccbs_begin();
|
||||||
holes_it != ubf->holes_end(); ++holes_it)
|
holes_it != ubf->inner_ccbs_end(); ++holes_it)
|
||||||
{
|
{
|
||||||
scan_ccb (*holes_it);
|
scan_ccb (*holes_it);
|
||||||
}
|
}
|
||||||
|
|
@ -99,15 +120,17 @@ public:
|
||||||
Face_const_iterator top_f = m_holes_q.front();
|
Face_const_iterator top_f = m_holes_q.front();
|
||||||
m_holes_q.pop();
|
m_holes_q.pop();
|
||||||
top_f->set_visited(true);
|
top_f->set_visited(true);
|
||||||
for (holes_it = top_f->holes_begin();
|
for (holes_it = top_f->inner_ccbs_begin();
|
||||||
holes_it != top_f->holes_end(); ++holes_it)
|
holes_it != top_f->inner_ccbs_end(); ++holes_it)
|
||||||
{
|
{
|
||||||
scan_ccb(*holes_it);
|
scan_ccb(*holes_it);
|
||||||
}
|
}
|
||||||
|
|
||||||
//scan_uncontained_face(top_f->outer_ccb());
|
//scan_uncontained_face(top_f->outer_ccb());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Face_const_iterator fit;
|
||||||
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
|
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
|
||||||
{
|
{
|
||||||
fit->set_visited(false);
|
fit->set_visited(false);
|
||||||
|
|
@ -123,7 +146,7 @@ public:
|
||||||
{
|
{
|
||||||
|
|
||||||
Polygon_2 pgn_boundary;
|
Polygon_2 pgn_boundary;
|
||||||
General_polygon_set_2<Gps_traits, Gps_dcel>::
|
General_polygon_set_on_surface_2<Gps_traits, Gps_top_traits>::
|
||||||
construct_polygon(ccb, pgn_boundary, m_traits);
|
construct_polygon(ccb, pgn_boundary, m_traits);
|
||||||
|
|
||||||
Ccb_halfedge_const_circulator ccb_end = ccb;
|
Ccb_halfedge_const_circulator ccb_end = ccb;
|
||||||
|
|
@ -135,7 +158,8 @@ public:
|
||||||
++ccb;
|
++ccb;
|
||||||
}
|
}
|
||||||
while(ccb != ccb_end);
|
while(ccb != ccb_end);
|
||||||
Polygon_with_holes_2 pgn = m_traits->construct_polygon_with_holes_2_object()(pgn_boundary,
|
Polygon_with_holes_2 pgn =
|
||||||
|
m_traits->construct_polygon_with_holes_2_object()(pgn_boundary,
|
||||||
m_pgn_holes.begin(),
|
m_pgn_holes.begin(),
|
||||||
m_pgn_holes.end());
|
m_pgn_holes.end());
|
||||||
/*Polygon_with_holes_2 pgn(pgn_boundary,
|
/*Polygon_with_holes_2 pgn(pgn_boundary,
|
||||||
|
|
@ -148,11 +172,12 @@ public:
|
||||||
|
|
||||||
void scan_contained_ubf(Face_const_iterator ubf)
|
void scan_contained_ubf(Face_const_iterator ubf)
|
||||||
{
|
{
|
||||||
CGAL_assertion(ubf->is_unbounded() && ubf->contained());
|
CGAL_assertion(ubf->number_of_outer_ccbs() == 0 && ubf->contained());
|
||||||
// ubf is contained -> unbounded polygon !!
|
// ubf is contained -> unbounded polygon !!
|
||||||
all_incident_faces(ubf);
|
all_incident_faces(ubf);
|
||||||
Polygon_2 boundary;
|
Polygon_2 boundary;
|
||||||
Polygon_with_holes_2 pgn = m_traits->construct_polygon_with_holes_2_object()(boundary,
|
Polygon_with_holes_2 pgn =
|
||||||
|
m_traits->construct_polygon_with_holes_2_object()(boundary,
|
||||||
m_pgn_holes.begin(),
|
m_pgn_holes.begin(),
|
||||||
m_pgn_holes.end());
|
m_pgn_holes.end());
|
||||||
/*Polygon_with_holes_2 pgn(boundary,
|
/*Polygon_with_holes_2 pgn(boundary,
|
||||||
|
|
@ -168,18 +193,26 @@ public:
|
||||||
{
|
{
|
||||||
CGAL_assertion(!f->visited());
|
CGAL_assertion(!f->visited());
|
||||||
f->set_visited(true);
|
f->set_visited(true);
|
||||||
if (!f->is_unbounded())
|
if (f->number_of_outer_ccbs() != 0)
|
||||||
{
|
{
|
||||||
if (!f->contained())
|
if (!f->contained())
|
||||||
|
{
|
||||||
|
for (Outer_ccb_const_iterator oci = f->outer_ccbs_begin();
|
||||||
|
oci != f->outer_ccbs_end(); ++oci)
|
||||||
{
|
{
|
||||||
m_pgn_holes.push_back(Polygon_2());
|
m_pgn_holes.push_back(Polygon_2());
|
||||||
General_polygon_set_2<Gps_traits, Gps_dcel>::
|
General_polygon_set_on_surface_2<Gps_traits, Gps_top_traits>::
|
||||||
construct_polygon(f->outer_ccb(), m_pgn_holes.back(), m_traits);
|
construct_polygon(*oci, m_pgn_holes.back(), m_traits);
|
||||||
|
}
|
||||||
|
|
||||||
m_holes_q.push(f);
|
m_holes_q.push(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Ccb_halfedge_const_circulator ccb_end = f->outer_ccb();
|
for (Outer_ccb_const_iterator oci = f->outer_ccbs_begin();
|
||||||
|
oci != f->outer_ccbs_end(); ++oci)
|
||||||
|
{
|
||||||
|
Ccb_halfedge_const_circulator ccb_end = *oci;
|
||||||
Ccb_halfedge_const_circulator ccb_circ = ccb_end;
|
Ccb_halfedge_const_circulator ccb_circ = ccb_end;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -194,11 +227,12 @@ public:
|
||||||
}
|
}
|
||||||
while(ccb_circ != ccb_end);
|
while(ccb_circ != ccb_end);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (f->contained())
|
if (f->contained())
|
||||||
{
|
{
|
||||||
Hole_const_iterator hit;
|
Inner_ccb_const_iterator hit;
|
||||||
for(hit = f->holes_begin(); hit != f->holes_end(); ++hit)
|
for(hit = f->inner_ccbs_begin(); hit != f->inner_ccbs_end(); ++hit)
|
||||||
{
|
{
|
||||||
Ccb_halfedge_const_circulator ccb_of_hole = *hit;
|
Ccb_halfedge_const_circulator ccb_of_hole = *hit;
|
||||||
Halfedge_const_iterator he = ccb_of_hole;
|
Halfedge_const_iterator he = ccb_of_hole;
|
||||||
|
|
@ -207,11 +241,10 @@ public:
|
||||||
CGAL_assertion(!he->twin()->face()->contained());
|
CGAL_assertion(!he->twin()->face()->contained());
|
||||||
|
|
||||||
m_pgn_holes.push_back(Polygon_2());
|
m_pgn_holes.push_back(Polygon_2());
|
||||||
General_polygon_set_2<Gps_traits, Gps_dcel>::
|
General_polygon_set_on_surface_2<Gps_traits, Gps_top_traits>::
|
||||||
construct_polygon(he->twin()->face()->outer_ccb(),
|
construct_polygon(he->twin()->face()->outer_ccb(),
|
||||||
m_pgn_holes.back(), m_traits);
|
m_pgn_holes.back(), m_traits);
|
||||||
m_holes_q.push(he->twin()->face());
|
m_holes_q.push(he->twin()->face());
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -259,17 +292,34 @@ class Init_faces_visitor
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void flip_face(Face_iterator f1, Face_iterator f2, Halfedge_iterator /*he*/)
|
//! discovered_face
|
||||||
|
/*! discovered_face is called by Gps_bfs_scanner when it reveals a new face
|
||||||
|
during a BFS scan. It is important to say that I have a strong suspition
|
||||||
|
that this place is the reason why discovered_face was once called
|
||||||
|
"flip_face" (WTF?)
|
||||||
|
\param old_f The face that was already revealed
|
||||||
|
\param new_f The face that we have just now revealed
|
||||||
|
*/
|
||||||
|
void discovered_face(Face_iterator old_f,
|
||||||
|
Face_iterator new_f,
|
||||||
|
Halfedge_iterator /*he*/)
|
||||||
{
|
{
|
||||||
f2->set_contained(!f1->contained());
|
new_f->set_contained(!old_f->contained());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
//! _insert
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
/*! The function inserts a polygon into an arrangement, assuming that the
|
||||||
_insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
polygon is contained in one face of the arrangement.
|
||||||
|
\param pgn The polygon to be inserted to the arrangement. pgn must be
|
||||||
|
completely disjoint from the arrangement
|
||||||
|
\param arr The arrangement to insert the polygon to.
|
||||||
|
*/
|
||||||
|
template <class Traits_, class TopTraits_>
|
||||||
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
|
_insert(const Polygon_2& pgn, Arrangement_on_surface_2 & arr)
|
||||||
{
|
{
|
||||||
typedef Arr_accessor<Arrangement_2> Arr_accessor;
|
typedef Arr_accessor<Arrangement_on_surface_2> Arr_accessor;
|
||||||
|
|
||||||
Arr_accessor accessor(arr);
|
Arr_accessor accessor(arr);
|
||||||
Compare_endpoints_xy_2 cmp_ends = m_traits->compare_endpoints_xy_2_object();
|
Compare_endpoints_xy_2 cmp_ends = m_traits->compare_endpoints_xy_2_object();
|
||||||
|
|
@ -283,23 +333,29 @@ _insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
||||||
Curve_const_iterator curr = itr_pair.first;
|
Curve_const_iterator curr = itr_pair.first;
|
||||||
Curve_const_iterator end = itr_pair.second;
|
Curve_const_iterator end = itr_pair.second;
|
||||||
|
|
||||||
Face_iterator f;
|
const Arr_parameter_space ps_x =
|
||||||
if (arr.is_empty())
|
m_traits_adaptor.parameter_space_in_x_2_object()(*curr, ARR_MIN_END);
|
||||||
|
const Arr_parameter_space ps_y =
|
||||||
|
m_traits_adaptor.parameter_space_in_y_2_object()(*curr, ARR_MIN_END);
|
||||||
|
|
||||||
|
Object obj_f;
|
||||||
|
if ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR))
|
||||||
{
|
{
|
||||||
f = arr.unbounded_face();
|
Point_location pl(arr);
|
||||||
|
obj_f = pl.locate(m_traits->construct_min_vertex_2_object()(*curr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Walk_pl pl(arr);
|
obj_f = accessor.locate_curve_end(*curr, ARR_MIN_END, ps_x, ps_y);
|
||||||
|
|
||||||
Object obj = pl.locate(m_traits->construct_min_vertex_2_object()(*curr));
|
|
||||||
|
|
||||||
Face_const_iterator const_f;
|
|
||||||
// pgn must be completely disjoint from the arrangement
|
|
||||||
CGAL_assertion(CGAL::assign(const_f, obj) && !const_f->contained());
|
|
||||||
CGAL::assign(const_f, obj);
|
|
||||||
f = arr.non_const_handle(const_f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Face_const_handle const_f;
|
||||||
|
// face should not be contained as the pgn is completly disjoint of the
|
||||||
|
// arrangement.
|
||||||
|
CGAL_assertion(CGAL::assign(const_f, obj_f) && !const_f->contained());
|
||||||
|
CGAL::assign(const_f, obj_f);
|
||||||
|
Face_iterator f = arr.non_const_handle(const_f);
|
||||||
|
|
||||||
Halfedge_handle first_he =
|
Halfedge_handle first_he =
|
||||||
arr.insert_in_face_interior(*curr, f);
|
arr.insert_in_face_interior(*curr, f);
|
||||||
//first_he is directed from left to right (see insert_in_face_interior)
|
//first_he is directed from left to right (see insert_in_face_interior)
|
||||||
|
|
@ -332,8 +388,7 @@ _insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
||||||
cmp_ends(*temp),
|
cmp_ends(*temp),
|
||||||
new_face_created);
|
new_face_created);
|
||||||
CGAL_assertion(new_face_created);
|
CGAL_assertion(new_face_created);
|
||||||
CGAL_assertion((he->face() != he->twin()->face()) &&
|
CGAL_assertion((he->face() != he->twin()->face()));
|
||||||
(he->face() != arr.unbounded_face()));
|
|
||||||
|
|
||||||
he->face()->set_contained(true);
|
he->face()->set_contained(true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -365,36 +420,36 @@ _insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
||||||
cmp_ends(last_cv),
|
cmp_ends(last_cv),
|
||||||
new_face_created);
|
new_face_created);
|
||||||
CGAL_assertion(new_face_created);
|
CGAL_assertion(new_face_created);
|
||||||
CGAL_assertion((last_he->face() != last_he->twin()->face()) &&
|
CGAL_assertion((last_he->face() != last_he->twin()->face()));
|
||||||
(last_he->face() != arr.unbounded_face()));
|
|
||||||
|
|
||||||
last_he->face()->set_contained(true);
|
last_he->face()->set_contained(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template<class PolygonIter >
|
template<class PolygonIter >
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
insert(PolygonIter p_begin, PolygonIter p_end)
|
insert(PolygonIter p_begin, PolygonIter p_end)
|
||||||
{
|
{
|
||||||
typename std::iterator_traits<PolygonIter>::value_type pgn;
|
typename std::iterator_traits<PolygonIter>::value_type pgn;
|
||||||
//check validity of all polygons
|
//check validity of all polygons
|
||||||
for( ; p_begin != p_end; ++p_begin)
|
for( ; p_begin != p_end; ++p_begin)
|
||||||
{
|
{
|
||||||
CGAL_precondition(is_valid_unkown_polygon(*p_begin, *m_traits));
|
CGAL_precondition(is_valid_unknown_polygon(*p_begin, *m_traits));
|
||||||
}
|
}
|
||||||
|
|
||||||
_insert(p_begin, p_end, pgn);
|
_insert(p_begin, p_end, pgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template<class PolygonIter, class PolygonWithHolesIter>
|
template<class PolygonIter, class PolygonWithHolesIter>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
insert(PolygonIter p_begin, PolygonIter p_end,
|
insert(PolygonIter p_begin, PolygonIter p_end,
|
||||||
PolygonWithHolesIter pwh_begin, PolygonWithHolesIter pwh_end)
|
PolygonWithHolesIter pwh_begin, PolygonWithHolesIter pwh_end)
|
||||||
{
|
{
|
||||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||||
|
|
||||||
XCurveList xcurve_list;
|
XCurveList xcurve_list;
|
||||||
|
|
||||||
|
|
@ -415,7 +470,14 @@ insert(PolygonIter p_begin, PolygonIter p_end,
|
||||||
insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
|
insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
|
||||||
|
|
||||||
if (is_unbounded)
|
if (is_unbounded)
|
||||||
m_arr->unbounded_face()->set_contained(true);
|
{
|
||||||
|
for (Face_iterator fit = m_arr->faces_begin();
|
||||||
|
fit != m_arr->faces_end(); ++fit)
|
||||||
|
{
|
||||||
|
if (fit->number_of_outer_ccbs() == 0)
|
||||||
|
fit->set_contained(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
My_visitor v;
|
My_visitor v;
|
||||||
Arr_bfs_scanner scanner(v);
|
Arr_bfs_scanner scanner(v);
|
||||||
|
|
@ -424,9 +486,9 @@ insert(PolygonIter p_begin, PolygonIter p_end,
|
||||||
}
|
}
|
||||||
|
|
||||||
//insert a range of simple polygons to the arrangement
|
//insert a range of simple polygons to the arrangement
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template<class PolygonIter>
|
template<class PolygonIter>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
_insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2 & /*pgn*/)
|
_insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2 & /*pgn*/)
|
||||||
{
|
{
|
||||||
for(PolygonIter pitr = p_begin; pitr != p_end; ++pitr)
|
for(PolygonIter pitr = p_begin; pitr != p_end; ++pitr)
|
||||||
|
|
@ -435,14 +497,14 @@ _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2 & /*pgn*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template<class PolygonIter>
|
template<class PolygonIter>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
_insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
|
_insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
|
||||||
{
|
{
|
||||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||||
|
|
||||||
XCurveList xcurve_list;
|
XCurveList xcurve_list;
|
||||||
bool is_unbounded = false;
|
bool is_unbounded = false;
|
||||||
|
|
@ -456,7 +518,14 @@ _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
|
||||||
insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
|
insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
|
||||||
|
|
||||||
if (is_unbounded)
|
if (is_unbounded)
|
||||||
m_arr->unbounded_face()->set_contained(true);
|
{
|
||||||
|
for (Face_iterator fit = m_arr->faces_begin();
|
||||||
|
fit != m_arr->faces_end(); ++fit)
|
||||||
|
{
|
||||||
|
if (fit->number_of_outer_ccbs() == 0)
|
||||||
|
fit->set_contained(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
My_visitor v;
|
My_visitor v;
|
||||||
Arr_bfs_scanner scanner(v);
|
Arr_bfs_scanner scanner(v);
|
||||||
|
|
@ -464,18 +533,17 @@ _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
|
||||||
_reset_faces(m_arr);
|
_reset_faces(m_arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//insert non-sipmle poloygons with holes (non incident edges may have
|
||||||
//insert non-sipmle poloygons with holes (non incident edges may have
|
|
||||||
// common vertex, but they dont intersect at their interior
|
// common vertex, but they dont intersect at their interior
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
_insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
_insert(const Polygon_with_holes_2 & pgn, Arrangement_on_surface_2 & arr)
|
||||||
{
|
{
|
||||||
//not needed gps.insert(PWH) has the precondition
|
//not needed gps.insert(PWH) has the precondition
|
||||||
// CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
// CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||||
|
|
||||||
XCurveList xcurve_list;
|
XCurveList xcurve_list;
|
||||||
_construct_curves(pgn, std::back_inserter(xcurve_list));
|
_construct_curves(pgn, std::back_inserter(xcurve_list));
|
||||||
|
|
@ -483,7 +551,14 @@ _insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
||||||
|
|
||||||
//if (pgn.is_unbounded())
|
//if (pgn.is_unbounded())
|
||||||
if (m_traits->construct_is_unbounded_object()(pgn))
|
if (m_traits->construct_is_unbounded_object()(pgn))
|
||||||
arr.unbounded_face()->set_contained(true);
|
{
|
||||||
|
for (Face_iterator fit = arr.faces_begin();
|
||||||
|
fit != arr.faces_end(); ++fit)
|
||||||
|
{
|
||||||
|
if (fit->number_of_outer_ccbs() == 0)
|
||||||
|
fit->set_contained(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
My_visitor v;
|
My_visitor v;
|
||||||
Arr_bfs_scanner scanner(v);
|
Arr_bfs_scanner scanner(v);
|
||||||
|
|
@ -491,10 +566,10 @@ _insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
||||||
_reset_faces(&arr);
|
_reset_faces(&arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template <class OutputIterator>
|
template <class OutputIterator>
|
||||||
void
|
void
|
||||||
General_polygon_set_2<Traits_, Dcel_>::
|
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
_construct_curves(const Polygon_2 & pgn, OutputIterator oi)
|
_construct_curves(const Polygon_2 & pgn, OutputIterator oi)
|
||||||
{
|
{
|
||||||
std::pair<Curve_const_iterator,
|
std::pair<Curve_const_iterator,
|
||||||
|
|
@ -503,9 +578,9 @@ _construct_curves(const Polygon_2 & pgn, OutputIterator oi)
|
||||||
std::copy (itr_pair.first, itr_pair.second, oi);
|
std::copy (itr_pair.first, itr_pair.second, oi);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template <class OutputIterator>
|
template <class OutputIterator>
|
||||||
void General_polygon_set_2<Traits_, Dcel_>::
|
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
_construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
|
_construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
|
||||||
{
|
{
|
||||||
//if (!pgn.is_unbounded())
|
//if (!pgn.is_unbounded())
|
||||||
|
|
@ -517,7 +592,8 @@ _construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
|
||||||
m_traits->construct_curves_2_object()(pgn_boundary);
|
m_traits->construct_curves_2_object()(pgn_boundary);
|
||||||
std::copy (itr_pair.first, itr_pair.second, oi);
|
std::copy (itr_pair.first, itr_pair.second, oi);
|
||||||
}
|
}
|
||||||
std::pair<GP_Holes_const_iterator, GP_Holes_const_iterator> hpair = m_traits->construct_holes_object()(pgn);
|
std::pair<GP_Holes_const_iterator, GP_Holes_const_iterator> hpair =
|
||||||
|
m_traits->construct_holes_object()(pgn);
|
||||||
GP_Holes_const_iterator hit;
|
GP_Holes_const_iterator hit;
|
||||||
for (hit = hpair.first; hit != hpair.second; ++hit)
|
for (hit = hpair.first; hit != hpair.second; ++hit)
|
||||||
{
|
{
|
||||||
|
|
@ -529,26 +605,26 @@ _construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
template <class OutputIterator>
|
template <class OutputIterator>
|
||||||
OutputIterator
|
OutputIterator
|
||||||
General_polygon_set_2<Traits_, Dcel_>::
|
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
polygons_with_holes(OutputIterator out) const
|
polygons_with_holes(OutputIterator out) const
|
||||||
{
|
{
|
||||||
typedef Arr_bfs_scanner<Arrangement_2, OutputIterator> Arr_bfs_scanner;
|
typedef Arr_bfs_scanner<Arrangement_on_surface_2, OutputIterator> Arr_bfs_scanner;
|
||||||
Arr_bfs_scanner scanner(this->m_traits, out);
|
Arr_bfs_scanner scanner(this->m_traits, out);
|
||||||
scanner.scan(*(this->m_arr));
|
scanner.scan(*(this->m_arr));
|
||||||
return (scanner.output_iterator());
|
return (scanner.output_iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
typename General_polygon_set_2<Traits_, Dcel_>::Size
|
typename General_polygon_set_on_surface_2<Traits_, TopTraits_>::Size
|
||||||
General_polygon_set_2<Traits_, Dcel_>::
|
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
number_of_polygons_with_holes() const
|
number_of_polygons_with_holes() const
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef Arr_bfs_scanner<Arrangement_2, Counting_output_iterator>
|
typedef Arr_bfs_scanner<Arrangement_on_surface_2, Counting_output_iterator>
|
||||||
Arr_bfs_scanner;
|
Arr_bfs_scanner;
|
||||||
//counting_output_operator CTOR reqires a parameter
|
//counting_output_operator CTOR reqires a parameter
|
||||||
std::size_t *cc = new size_t();
|
std::size_t *cc = new size_t();
|
||||||
|
|
@ -557,11 +633,12 @@ number_of_polygons_with_holes() const
|
||||||
return (scanner.output_iterator().current_counter());
|
return (scanner.output_iterator().current_counter());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
|
||||||
bool General_polygon_set_2<Traits_, Dcel_>::
|
template <class Traits_, class TopTraits_>
|
||||||
|
bool General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
||||||
{
|
{
|
||||||
Walk_pl pl(*m_arr);
|
Point_location pl(*m_arr);
|
||||||
|
|
||||||
Object obj = pl.locate(q);
|
Object obj = pl.locate(q);
|
||||||
Face_const_iterator f;
|
Face_const_iterator f;
|
||||||
|
|
@ -601,7 +678,7 @@ locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Oneset_iterator<Polygon_with_holes_2> OutputItr;
|
typedef Oneset_iterator<Polygon_with_holes_2> OutputItr;
|
||||||
typedef Arr_bfs_scanner<Arrangement_2, OutputItr> Arr_bfs_scanner;
|
typedef Arr_bfs_scanner<Arrangement_on_surface_2, OutputItr> Arr_bfs_scanner;
|
||||||
|
|
||||||
OutputItr oi (pgn);
|
OutputItr oi (pgn);
|
||||||
Arr_bfs_scanner scanner(this->m_traits, oi);
|
Arr_bfs_scanner scanner(this->m_traits, oi);
|
||||||
|
|
@ -609,10 +686,17 @@ locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
||||||
|
|
||||||
Ccb_halfedge_const_circulator ccb_of_pgn = get_boundary_of_polygon(f);
|
Ccb_halfedge_const_circulator ccb_of_pgn = get_boundary_of_polygon(f);
|
||||||
this->_reset_faces();
|
this->_reset_faces();
|
||||||
if (ccb_of_pgn == Ccb_halfedge_const_circulator()) // the polygon has no boundary
|
if (ccb_of_pgn == Ccb_halfedge_const_circulator())
|
||||||
{
|
{
|
||||||
|
// the polygon has no boundary
|
||||||
|
|
||||||
// f is unbounded
|
// f is unbounded
|
||||||
scanner.scan_contained_ubf(m_arr->unbounded_face());
|
for (Face_iterator fit = m_arr->faces_begin(); fit != m_arr->faces_end();
|
||||||
|
++fit)
|
||||||
|
{
|
||||||
|
if (fit->number_of_outer_ccbs() == 0)
|
||||||
|
scanner.scan_contained_ubf(fit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -626,19 +710,27 @@ locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
typename General_polygon_set_2<Traits_, Dcel_>::Ccb_halfedge_const_circulator
|
typename General_polygon_set_on_surface_2<Traits_, TopTraits_>::Ccb_halfedge_const_circulator
|
||||||
General_polygon_set_2<Traits_, Dcel_>::
|
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
get_boundary_of_polygon(Face_const_iterator f) const
|
get_boundary_of_polygon(Face_const_iterator f) const
|
||||||
{
|
{
|
||||||
CGAL_assertion(!f->visited());
|
CGAL_assertion(!f->visited());
|
||||||
f->set_visited(true);
|
f->set_visited(true);
|
||||||
|
|
||||||
if (f->is_unbounded())
|
if (f->number_of_outer_ccbs() == 0) // (f->is_unbounded())
|
||||||
{
|
{
|
||||||
return Ccb_halfedge_const_circulator();
|
return Ccb_halfedge_const_circulator();
|
||||||
}
|
}
|
||||||
Ccb_halfedge_const_circulator ccb_end = f->outer_ccb();
|
|
||||||
|
// We assume that a polygon has only one outer_ccb. This code does not handle
|
||||||
|
// the case where there are more than 1 outer ccbs. If this is the case, we
|
||||||
|
// need to devise a method to convert the outer ccbs to inner ccbs so we
|
||||||
|
// will have only one outer ccb.
|
||||||
|
if (f->number_of_outer_ccbs() > 1)
|
||||||
|
CGAL_error_msg("Not implemented yet.");
|
||||||
|
|
||||||
|
Ccb_halfedge_const_circulator ccb_end = *f->outer_ccbs_begin();
|
||||||
Ccb_halfedge_const_circulator ccb_circ = ccb_end;
|
Ccb_halfedge_const_circulator ccb_circ = ccb_end;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -659,12 +751,13 @@ get_boundary_of_polygon(Face_const_iterator f) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Traits_, class Dcel_>
|
template <class Traits_, class TopTraits_>
|
||||||
bool General_polygon_set_2<Traits_, Dcel_>::
|
bool General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||||
is_hole_of_face(Face_const_handle f, Halfedge_const_handle he) const
|
is_hole_of_face(Face_const_handle f, Halfedge_const_handle he) const
|
||||||
{
|
{
|
||||||
Hole_const_iterator holes_it;
|
Inner_ccb_const_iterator holes_it;
|
||||||
for (holes_it = f->holes_begin(); holes_it != f->holes_end(); ++holes_it)
|
for (holes_it = f->inner_ccbs_begin();
|
||||||
|
holes_it != f->inner_ccbs_end(); ++holes_it)
|
||||||
{
|
{
|
||||||
Ccb_halfedge_const_circulator ccb = *holes_it;
|
Ccb_halfedge_const_circulator ccb = *holes_it;
|
||||||
Ccb_halfedge_const_circulator ccb_end = ccb;
|
Ccb_halfedge_const_circulator ccb_end = ccb;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -40,6 +40,7 @@ class Polygon_set_2 :
|
||||||
private:
|
private:
|
||||||
typedef General_polygon_set_2<Gps_segment_traits_2<Kernel, Containter>, Dcel_>
|
typedef General_polygon_set_2<Gps_segment_traits_2<Kernel, Containter>, Dcel_>
|
||||||
Base;
|
Base;
|
||||||
|
typedef typename Base::Base Base_of_base;
|
||||||
typedef Polygon_set_2<Kernel, Containter, Dcel_> Self;
|
typedef Polygon_set_2<Kernel, Containter, Dcel_> Self;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -237,9 +238,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
inline const Base& base(const Self& other) const
|
inline const Base_of_base& base(const Self& other) const
|
||||||
{
|
{
|
||||||
return (static_cast<const Base&>(other));
|
return (static_cast<const Base_of_base&>(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,10 @@ int main (int argc, char **argv) {
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
std::cout <<"ALL TESTS SUCCEEDED!" << std::endl;
|
std::cout <<"ALL TESTS SUCCEEDED!" << std::endl;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
std::cout <<"SOME TESTS FAILED" << std::endl;
|
std::cout <<"SOME TESTS FAILED" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue