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/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/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_holes2.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes3.dat -text
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ CGAL_BEGIN_NAMESPACE
|
|||
public:
|
||||
|
||||
typedef Arrangement_ Arrangement;
|
||||
typedef typename Arrangement::Traits_2 Traits;
|
||||
typedef typename Arrangement::Geometry_traits_2 Traits;
|
||||
typedef Ccb_curve_iterator<Arrangement> Self;
|
||||
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
|
|
|
|||
|
|
@ -100,12 +100,12 @@ public:
|
|||
|
||||
template <class Arrangement_>
|
||||
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_>,
|
||||
Point_with_vertex<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::Point_2 Base_Point_2;
|
||||
|
|
|
|||
|
|
@ -16,10 +16,22 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef 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_op_sweep.h>
|
||||
#include <CGAL/Sweep_line_2/Arr_construction_subcurve.h>
|
||||
|
|
@ -38,7 +50,7 @@ template <class Arrangement_, class Bfs_visitor_>
|
|||
class Gps_agg_op
|
||||
{
|
||||
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 Gps_agg_meta_traits<Arrangement_2> Meta_traits;
|
||||
typedef typename Meta_traits::Curve_data Curve_data;
|
||||
|
|
@ -120,8 +132,10 @@ public:
|
|||
|
||||
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;
|
||||
if (arr->unbounded_face()->contained())
|
||||
if (arr->reference_face()->contained())
|
||||
++n_inf_pgn;
|
||||
|
||||
Edge_iterator itr = arr->edges_begin();
|
||||
|
|
@ -144,9 +158,9 @@ public:
|
|||
lower, upper, jump,
|
||||
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);
|
||||
visitor.visit_ubf(m_arr->unbounded_face(), n_inf_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ private:
|
|||
((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ? SMALLER : LARGER;
|
||||
|
||||
const Comparison_result cv_dir =
|
||||
this->m_arr_access.arrangement().traits()->
|
||||
this->m_arr_access.arrangement().geometry_traits()->
|
||||
compare_endpoints_xy_2_object()(cv);
|
||||
|
||||
if (he_dir == cv_dir)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
#define CGAL_GPS_BPS_BASE_VISITOR_H
|
||||
|
|
@ -24,7 +25,14 @@
|
|||
|
||||
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
|
||||
{
|
||||
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) &&
|
||||
m_edges_hash->is_defined(he->twin()) &&
|
||||
m_faces_hash->is_defined(f1) &&
|
||||
!m_faces_hash->is_defined(f2));
|
||||
unsigned int ic = compute_ic(old_face, new_face, he);
|
||||
|
||||
// IC of f2 (inside counter)
|
||||
unsigned int ic_f2 =
|
||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
||||
(*m_faces_hash)[f2] = ic_f2;
|
||||
if (static_cast<DerivedVisitor*>(this)->contained_criteria(ic))
|
||||
new_face->set_contained(true);
|
||||
}
|
||||
|
||||
// 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:
|
||||
|
||||
// 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) &&
|
||||
m_edges_hash->is_defined(he->twin()) &&
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
//
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
|
||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
|
||||
|
|
@ -25,12 +28,14 @@
|
|||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
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 typename Arrangement::Face_iterator Face_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::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;
|
||||
ic_f2 = this->compute_ic(f1, f2, he);
|
||||
(*(this->m_faces_hash))[f2] = ic_f2;
|
||||
|
||||
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);
|
||||
// intersection means that all polygons contain the face.
|
||||
CGAL_assertion(ic <= this->m_num_of_polygons);
|
||||
return (ic == this->m_num_of_polygons);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
{}
|
||||
|
||||
|
||||
};
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
#define CGAL_GPS_BFS_JOIN_VISITOR_H
|
||||
|
|
@ -25,12 +26,14 @@
|
|||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
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 typename Arrangement::Face_iterator Face_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::Faces_hash Faces_hash;
|
||||
|
||||
|
|
@ -40,23 +43,16 @@ public:
|
|||
Base(edges_hash, faces_hash, n_pgn)
|
||||
{}
|
||||
|
||||
|
||||
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;
|
||||
ic_f2 = this->compute_ic(f1, f2, he);
|
||||
(*(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);
|
||||
// at least one polygon contains the face.
|
||||
return (ic > 0);
|
||||
}
|
||||
|
||||
void after_scan(Arrangement&)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_SCANNER_H
|
||||
#define CGAL_GPS_BFS_SCANNER_H
|
||||
|
|
@ -30,7 +31,7 @@ class Gps_bfs_scanner
|
|||
{
|
||||
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
|
||||
Ccb_halfedge_circulator;
|
||||
typedef typename Arrangement::Face_iterator Face_iterator;
|
||||
|
|
@ -40,7 +41,7 @@ class Gps_bfs_scanner
|
|||
|
||||
protected:
|
||||
Visitor* m_visitor;
|
||||
std::queue<Hole_iterator> m_holes;
|
||||
std::queue<Inner_ccb_iterator> m_holes;
|
||||
std::stack<Ccb_halfedge_circulator> m_ccb_stcak;
|
||||
|
||||
public:
|
||||
|
|
@ -50,17 +51,25 @@ public:
|
|||
|
||||
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);
|
||||
push_to_queue_holes_of_face(ubf);
|
||||
|
||||
while(!m_holes.empty())
|
||||
{
|
||||
Hole_iterator hole = m_holes.front();
|
||||
Inner_ccb_iterator hole = m_holes.front();
|
||||
m_holes.pop();
|
||||
scan(*hole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scan(Ccb_halfedge_circulator ccb)
|
||||
{
|
||||
|
|
@ -86,7 +95,7 @@ public:
|
|||
{
|
||||
push_to_queue_holes_of_face(he->twin()->face());
|
||||
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());
|
||||
m_ccb_stcak.push(he->twin());
|
||||
|
|
@ -99,7 +108,8 @@ public:
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
#define CGAL_GPS_BFS_XOR_VISITOR_H
|
||||
|
|
@ -25,43 +26,45 @@
|
|||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
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 typename Arrangement::Face_iterator Face_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::Faces_hash Faces_hash;
|
||||
|
||||
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)
|
||||
{}
|
||||
|
||||
|
||||
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;
|
||||
ic_f2 = this->compute_ic(f1, f2, he);
|
||||
(*(this->m_faces_hash))[f2] = ic_f2;
|
||||
|
||||
if(ic_f2%2)
|
||||
f2->set_contained(true);
|
||||
// xor means odd number of polygons.
|
||||
return (ic % 2) == 1;
|
||||
}
|
||||
|
||||
// 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%2)
|
||||
ubf->set_contained(true);
|
||||
}
|
||||
//! after_scan post-processing after bfs scan.
|
||||
/*! The function fixes some of the curves, to be in the same direction as the
|
||||
half-edges.
|
||||
|
||||
\param arr The given arrangment.
|
||||
*/
|
||||
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::Construct_opposite_2 Construct_opposite_2;
|
||||
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
|
||||
|
|
@ -79,7 +82,8 @@ public:
|
|||
Halfedge_iterator he = eit;
|
||||
const X_monotone_curve_2& cv = he->curve();
|
||||
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;
|
||||
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_xor_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>
|
||||
|
||||
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 Visitor_ Visitor;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Arrangement_2 *,
|
||||
std::vector<Vertex_handle> *> Arr_entry;
|
||||
|
|
@ -46,12 +61,12 @@ public:
|
|||
if(i==j)
|
||||
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);
|
||||
std::vector<Vertex_handle> *verts = new std::vector<Vertex_handle>;
|
||||
|
||||
Gps_agg_op<Arrangement_2, Gps_bfs_join_visitor<Arrangement_2> >
|
||||
agg_op(*res, *verts, *tr);
|
||||
Gps_agg_op<Arrangement_2, Visitor> agg_op(*res, *verts, *tr);
|
||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
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_>
|
||||
class Intersection_merge
|
||||
{
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Arrangement_2 *,
|
||||
std::vector<Vertex_handle> *> Arr_entry;
|
||||
class Join_merge : public Base_merge<Arrangement_,
|
||||
Gps_bfs_join_visitor<Arrangement_> >
|
||||
{};
|
||||
|
||||
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_>
|
||||
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
|
||||
|
|
|
|||
|
|
@ -33,12 +33,26 @@
|
|||
#include <CGAL/Arr_naive_point_location.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#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*/
|
||||
template<typename Arrangement_2>
|
||||
class ValidationOverlayTraits : public CGAL::Arr_default_overlay_traits<Arrangement_2>
|
||||
template<typename Arrangement_2>
|
||||
class ValidationOverlayTraits :
|
||||
public CGAL::Arr_default_overlay_traits<Arrangement_2>
|
||||
{
|
||||
public:
|
||||
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::Halfedge_const_handle Halfedge_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*/
|
||||
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
|
||||
|
||||
#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
|
||||
/*! \class
|
||||
* A visitor used for checking whether the edges of a polygon are
|
||||
* non-intersecting.
|
||||
*/
|
||||
|
|
@ -158,9 +162,9 @@ protected:
|
|||
|
||||
//Traits_2 templates the General_polygon_set_2 Traits.
|
||||
//These include types for polygon and PWH.
|
||||
template <typename Traits_2>
|
||||
bool is_closed_polygon(const typename Traits_2::Polygon_2& pgn, Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
bool is_closed_polygon(const typename Traits_2::Polygon_2& pgn, Traits_2 traits)
|
||||
{
|
||||
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||
|
|
@ -207,10 +211,10 @@ protected:
|
|||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
template <typename Traits_2>
|
||||
bool is_simple_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{// Previously known as is_strictly_simple
|
||||
}
|
||||
template <typename Traits_2>
|
||||
bool is_simple_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{// Previously known as is_strictly_simple
|
||||
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
// Sweep the boundary curves and look for intersections.
|
||||
|
|
@ -223,12 +227,12 @@ protected:
|
|||
|
||||
visitor.sweep(itr_pair.first, itr_pair.second);
|
||||
return (visitor.is_valid());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Traits_2>
|
||||
bool has_valid_orientation_polygon (const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
bool has_valid_orientation_polygon (const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
|
||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||
|
|
@ -240,15 +244,15 @@ protected:
|
|||
|
||||
return (traits_adapter.orientation_2_object()(itr_pair.first,
|
||||
itr_pair.second) == COUNTERCLOCKWISE);
|
||||
}
|
||||
/* A valid polygon is :
|
||||
}
|
||||
/* A valid polygon is :
|
||||
* 1 - Closed or empty polygon
|
||||
* 2 - Simple (previously known as strictly simple)
|
||||
* 3 - Counterclockwise oriented
|
||||
*/
|
||||
template <typename Traits_2>
|
||||
bool is_valid_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
bool is_valid_polygon(const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{
|
||||
bool closed = is_closed_polygon(pgn,traits);
|
||||
CGAL_warning_msg (closed,
|
||||
"The polygon's boundary is not closed.");
|
||||
|
|
@ -268,12 +272,12 @@ protected:
|
|||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Traits_2>
|
||||
bool is_closed_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
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;
|
||||
if(! is_closed_polygon (pgn.outer_boundary(),traits))
|
||||
return (false);
|
||||
|
|
@ -286,11 +290,11 @@ protected:
|
|||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Traits_2>
|
||||
bool is_crossover_outer_boundary(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits ) {
|
||||
//templated point location version
|
||||
template<typename Traits_2, class PointLocation>
|
||||
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
|
||||
typedef typename Traits_2::Point_2 Point_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_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;
|
||||
|
||||
typename std::list<Halfedge_handle> he_path;
|
||||
typename std::list<Halfedge_handle>::iterator he_itr;
|
||||
|
|
@ -331,7 +334,8 @@ protected:
|
|||
|
||||
Polygon_set_2 gps(traits);
|
||||
Arrangement_2 arr = gps.arrangement();
|
||||
Naive_pl pl (arr);
|
||||
pl.attach(arr);
|
||||
|
||||
//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);
|
||||
|
|
@ -375,129 +379,42 @@ protected:
|
|||
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)
|
||||
|
||||
// We created a path of halfedges that circulates the polygon counterclockwise
|
||||
// The polygon should lay 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.
|
||||
// The unbounded face is always to the right of the halfedges. We check if
|
||||
// all faces that lay on the right of the halfedges are equal (to the
|
||||
// "unbounded" face).
|
||||
typename Arrangement_2::Face_handle fh = (*he_path.begin())->twin()->face();
|
||||
for (he_itr = he_path.begin(); he_itr != he_path.end(); he_itr++) {
|
||||
|
||||
if ((*he_itr)->twin()->face() != fh)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Traits_2>
|
||||
bool is_crossover_outer_boundary(
|
||||
const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits ) {
|
||||
|
||||
|
||||
//templated point location version
|
||||
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 CGAL::Gps_default_dcel<Traits_2> Dcel;
|
||||
typedef CGAL::General_polygon_set_2<Traits_2, Dcel> Polygon_set_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;
|
||||
|
||||
typename std::list<Halfedge_handle> he_path;
|
||||
typename std::list<Halfedge_handle>::iterator he_itr;
|
||||
//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;
|
||||
}
|
||||
Naive_pl pl;
|
||||
return is_crossover_outer_boundary(pgn, traits, pl);
|
||||
}
|
||||
|
||||
|
||||
template <typename Traits_2>
|
||||
bool is_relatively_simple_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||
{// previously known as Simple
|
||||
|
||||
template <typename Traits_2>
|
||||
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
|
||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
|
|
@ -528,13 +445,13 @@ protected:
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Traits_2>
|
||||
bool has_valid_orientation_polygon_with_holes (const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
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
|
||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||
|
|
@ -571,7 +488,7 @@ protected:
|
|||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -579,21 +496,21 @@ protected:
|
|||
|
||||
|
||||
/*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
|
||||
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
|
||||
no holes intersect the boundary.
|
||||
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.
|
||||
Executing a difference(gps, outer boundary) should result in an empty set if
|
||||
no holes intersect the boundary.
|
||||
|
||||
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
|
||||
and the iterative loop will be stopped after a small number of iterations.
|
||||
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
|
||||
and the iterative loop will be stopped after a small number of iterations.
|
||||
|
||||
*/
|
||||
template <class Traits_2>
|
||||
bool are_holes_and_boundary_pairwise_disjoint(const typename Traits_2::Polygon_with_holes_2& pwh, Traits_2 traits)
|
||||
{
|
||||
template <class Traits_2>
|
||||
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
|
||||
|
||||
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
|
||||
Hole_const_iterator fit;
|
||||
|
||||
/*outer boundary can be relatively simple. Execution of
|
||||
do_intersect(hole, boundary) or difference(hole,boundary) relies on
|
||||
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
|
||||
(simple) polygon. */
|
||||
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())
|
||||
return true;
|
||||
|
||||
/*do_intersect predicate will not suffice as hole can be completely outside
|
||||
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
|
||||
|
|
@ -709,18 +630,18 @@ and the iterative loop will be stopped after a small number of iterations.
|
|||
return (false);
|
||||
*/
|
||||
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
|
||||
* 2 - The PWH is relatively simple polygon (holes are simple...)
|
||||
* 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
|
||||
* 5 - The holes are on the interior of the boundary polygon if the boundary is not empty
|
||||
*/
|
||||
template <typename Traits_2>
|
||||
bool is_valid_polygon_with_holes(const typename Traits_2::Polygon_with_holes_2& pgn, Traits_2 traits)
|
||||
{
|
||||
template <typename Traits_2>
|
||||
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);
|
||||
CGAL_warning_msg (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 (true);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Traits_2>
|
||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_with_holes_2& pgn,
|
||||
template <typename Traits_2>
|
||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_with_holes_2& pgn,
|
||||
Traits_2 traits)
|
||||
{
|
||||
{
|
||||
return is_valid_polygon_with_holes(pgn, traits);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Traits_2>
|
||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_2& pgn,
|
||||
template <typename Traits_2>
|
||||
bool is_valid_unknown_polygon(const typename Traits_2::Polygon_2& pgn,
|
||||
Traits_2 traits)
|
||||
{
|
||||
{
|
||||
return is_valid_polygon(pgn, traits);
|
||||
}
|
||||
}
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_UTILS_H
|
||||
#define CGAL_GPS_UTILS_H
|
||||
|
|
@ -30,32 +31,47 @@
|
|||
|
||||
#include <queue>
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
template <class Traits_, class TopTraits_>
|
||||
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
construct_polygon(Ccb_halfedge_const_circulator ccb, Polygon_2 & pgn,
|
||||
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 end(ccb, true);
|
||||
|
||||
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>
|
||||
class Arr_bfs_scanner
|
||||
{
|
||||
public:
|
||||
typedef typename Arrangement::Traits_2 Gps_traits;
|
||||
typedef typename Arrangement::Dcel Gps_dcel;
|
||||
typedef typename Arrangement::Geometry_traits_2 Gps_traits;
|
||||
typedef typename Arrangement::Topology_traits Gps_top_traits;
|
||||
typedef typename Gps_traits::Polygon_2 Polygon_2;
|
||||
typedef typename Gps_traits::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Arrangement::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arrangement::Face_const_iterator Face_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:
|
||||
|
|
@ -74,15 +90,20 @@ public:
|
|||
|
||||
void scan(Arrangement& arr)
|
||||
{
|
||||
Face_const_iterator ubf = arr.unbounded_face();
|
||||
Hole_const_iterator holes_it;
|
||||
Face_const_iterator fit;
|
||||
Face_const_iterator ubf;
|
||||
for (ubf = arr.faces_begin(); ubf != arr.faces_end(); ++ubf)
|
||||
{
|
||||
if (ubf->number_of_outer_ccbs() != 0)
|
||||
continue;
|
||||
if (ubf->visited())
|
||||
continue;
|
||||
|
||||
Inner_ccb_const_iterator holes_it;
|
||||
if (!ubf->contained())
|
||||
{
|
||||
ubf->set_visited(true);
|
||||
for (holes_it = ubf->holes_begin();
|
||||
holes_it != ubf->holes_end(); ++holes_it)
|
||||
for (holes_it = ubf->inner_ccbs_begin();
|
||||
holes_it != ubf->inner_ccbs_end(); ++holes_it)
|
||||
{
|
||||
scan_ccb (*holes_it);
|
||||
}
|
||||
|
|
@ -99,15 +120,17 @@ public:
|
|||
Face_const_iterator top_f = m_holes_q.front();
|
||||
m_holes_q.pop();
|
||||
top_f->set_visited(true);
|
||||
for (holes_it = top_f->holes_begin();
|
||||
holes_it != top_f->holes_end(); ++holes_it)
|
||||
for (holes_it = top_f->inner_ccbs_begin();
|
||||
holes_it != top_f->inner_ccbs_end(); ++holes_it)
|
||||
{
|
||||
scan_ccb(*holes_it);
|
||||
}
|
||||
|
||||
//scan_uncontained_face(top_f->outer_ccb());
|
||||
}
|
||||
}
|
||||
|
||||
Face_const_iterator fit;
|
||||
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
|
||||
{
|
||||
fit->set_visited(false);
|
||||
|
|
@ -123,7 +146,7 @@ public:
|
|||
{
|
||||
|
||||
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);
|
||||
|
||||
Ccb_halfedge_const_circulator ccb_end = ccb;
|
||||
|
|
@ -135,7 +158,8 @@ public:
|
|||
++ccb;
|
||||
}
|
||||
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.end());
|
||||
/*Polygon_with_holes_2 pgn(pgn_boundary,
|
||||
|
|
@ -148,11 +172,12 @@ public:
|
|||
|
||||
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 !!
|
||||
all_incident_faces(ubf);
|
||||
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.end());
|
||||
/*Polygon_with_holes_2 pgn(boundary,
|
||||
|
|
@ -168,18 +193,26 @@ public:
|
|||
{
|
||||
CGAL_assertion(!f->visited());
|
||||
f->set_visited(true);
|
||||
if (!f->is_unbounded())
|
||||
if (f->number_of_outer_ccbs() != 0)
|
||||
{
|
||||
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());
|
||||
General_polygon_set_2<Gps_traits, Gps_dcel>::
|
||||
construct_polygon(f->outer_ccb(), m_pgn_holes.back(), m_traits);
|
||||
General_polygon_set_on_surface_2<Gps_traits, Gps_top_traits>::
|
||||
construct_polygon(*oci, m_pgn_holes.back(), m_traits);
|
||||
}
|
||||
|
||||
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;
|
||||
do
|
||||
{
|
||||
|
|
@ -194,11 +227,12 @@ public:
|
|||
}
|
||||
while(ccb_circ != ccb_end);
|
||||
}
|
||||
}
|
||||
|
||||
if (f->contained())
|
||||
{
|
||||
Hole_const_iterator hit;
|
||||
for(hit = f->holes_begin(); hit != f->holes_end(); ++hit)
|
||||
Inner_ccb_const_iterator hit;
|
||||
for(hit = f->inner_ccbs_begin(); hit != f->inner_ccbs_end(); ++hit)
|
||||
{
|
||||
Ccb_halfedge_const_circulator ccb_of_hole = *hit;
|
||||
Halfedge_const_iterator he = ccb_of_hole;
|
||||
|
|
@ -207,11 +241,10 @@ public:
|
|||
CGAL_assertion(!he->twin()->face()->contained());
|
||||
|
||||
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(),
|
||||
m_pgn_holes.back(), m_traits);
|
||||
m_holes_q.push(he->twin()->face());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -259,17 +292,34 @@ class Init_faces_visitor
|
|||
|
||||
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_>
|
||||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
_insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
||||
//! _insert
|
||||
/*! The function inserts a polygon into an arrangement, assuming that the
|
||||
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);
|
||||
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 end = itr_pair.second;
|
||||
|
||||
Face_iterator f;
|
||||
if (arr.is_empty())
|
||||
const Arr_parameter_space ps_x =
|
||||
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
|
||||
{
|
||||
Walk_pl pl(arr);
|
||||
|
||||
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);
|
||||
obj_f = accessor.locate_curve_end(*curr, ARR_MIN_END, ps_x, ps_y);
|
||||
}
|
||||
|
||||
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 =
|
||||
arr.insert_in_face_interior(*curr, f);
|
||||
//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),
|
||||
new_face_created);
|
||||
CGAL_assertion(new_face_created);
|
||||
CGAL_assertion((he->face() != he->twin()->face()) &&
|
||||
(he->face() != arr.unbounded_face()));
|
||||
CGAL_assertion((he->face() != he->twin()->face()));
|
||||
|
||||
he->face()->set_contained(true);
|
||||
return;
|
||||
|
|
@ -365,36 +420,36 @@ _insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
|||
cmp_ends(last_cv),
|
||||
new_face_created);
|
||||
CGAL_assertion(new_face_created);
|
||||
CGAL_assertion((last_he->face() != last_he->twin()->face()) &&
|
||||
(last_he->face() != arr.unbounded_face()));
|
||||
CGAL_assertion((last_he->face() != last_he->twin()->face()));
|
||||
|
||||
last_he->face()->set_contained(true);
|
||||
}
|
||||
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class Traits_, class TopTraits_>
|
||||
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)
|
||||
{
|
||||
typename std::iterator_traits<PolygonIter>::value_type pgn;
|
||||
//check validity of all polygons
|
||||
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);
|
||||
}
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class Traits_, class TopTraits_>
|
||||
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,
|
||||
PolygonWithHolesIter pwh_begin, PolygonWithHolesIter pwh_end)
|
||||
{
|
||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
||||
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||
|
||||
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());
|
||||
|
||||
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;
|
||||
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
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class Traits_, class TopTraits_>
|
||||
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*/)
|
||||
{
|
||||
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>
|
||||
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*/)
|
||||
{
|
||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
||||
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||
|
||||
XCurveList xcurve_list;
|
||||
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());
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
template <class Traits_, class Dcel_>
|
||||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
_insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
||||
template <class Traits_, class TopTraits_>
|
||||
void General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
_insert(const Polygon_with_holes_2 & pgn, Arrangement_on_surface_2 & arr)
|
||||
{
|
||||
//not needed gps.insert(PWH) has the precondition
|
||||
// CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
typedef std::list<X_monotone_curve_2> XCurveList;
|
||||
typedef Init_faces_visitor<Arrangement_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_2, My_visitor> Arr_bfs_scanner;
|
||||
typedef Init_faces_visitor<Arrangement_on_surface_2> My_visitor;
|
||||
typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
|
||||
|
||||
XCurveList 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 (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;
|
||||
Arr_bfs_scanner scanner(v);
|
||||
|
|
@ -491,10 +566,10 @@ _insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
|||
_reset_faces(&arr);
|
||||
}
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class Traits_, class TopTraits_>
|
||||
template <class OutputIterator>
|
||||
void
|
||||
General_polygon_set_2<Traits_, Dcel_>::
|
||||
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
_construct_curves(const Polygon_2 & pgn, OutputIterator oi)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class Traits_, class TopTraits_>
|
||||
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)
|
||||
{
|
||||
//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);
|
||||
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;
|
||||
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>
|
||||
OutputIterator
|
||||
General_polygon_set_2<Traits_, Dcel_>::
|
||||
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
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);
|
||||
scanner.scan(*(this->m_arr));
|
||||
return (scanner.output_iterator());
|
||||
}
|
||||
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
typename General_polygon_set_2<Traits_, Dcel_>::Size
|
||||
General_polygon_set_2<Traits_, Dcel_>::
|
||||
template <class Traits_, class TopTraits_>
|
||||
typename General_polygon_set_on_surface_2<Traits_, TopTraits_>::Size
|
||||
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
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;
|
||||
//counting_output_operator CTOR reqires a parameter
|
||||
std::size_t *cc = new size_t();
|
||||
|
|
@ -557,11 +633,12 @@ number_of_polygons_with_holes() const
|
|||
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
|
||||
{
|
||||
Walk_pl pl(*m_arr);
|
||||
Point_location pl(*m_arr);
|
||||
|
||||
Object obj = pl.locate(q);
|
||||
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 Arr_bfs_scanner<Arrangement_2, OutputItr> Arr_bfs_scanner;
|
||||
typedef Arr_bfs_scanner<Arrangement_on_surface_2, OutputItr> Arr_bfs_scanner;
|
||||
|
||||
OutputItr oi (pgn);
|
||||
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);
|
||||
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
|
||||
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
|
||||
{
|
||||
|
|
@ -626,19 +710,27 @@ locate(const Point_2& q, Polygon_with_holes_2& pgn) const
|
|||
return true;
|
||||
}
|
||||
|
||||
template <class Traits_, class Dcel_>
|
||||
typename General_polygon_set_2<Traits_, Dcel_>::Ccb_halfedge_const_circulator
|
||||
General_polygon_set_2<Traits_, Dcel_>::
|
||||
template <class Traits_, class TopTraits_>
|
||||
typename General_polygon_set_on_surface_2<Traits_, TopTraits_>::Ccb_halfedge_const_circulator
|
||||
General_polygon_set_on_surface_2<Traits_, TopTraits_>::
|
||||
get_boundary_of_polygon(Face_const_iterator f) const
|
||||
{
|
||||
CGAL_assertion(!f->visited());
|
||||
f->set_visited(true);
|
||||
|
||||
if (f->is_unbounded())
|
||||
if (f->number_of_outer_ccbs() == 0) // (f->is_unbounded())
|
||||
{
|
||||
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;
|
||||
do
|
||||
{
|
||||
|
|
@ -659,12 +751,13 @@ get_boundary_of_polygon(Face_const_iterator f) const
|
|||
|
||||
}
|
||||
|
||||
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_>::
|
||||
is_hole_of_face(Face_const_handle f, Halfedge_const_handle he) const
|
||||
{
|
||||
Hole_const_iterator holes_it;
|
||||
for (holes_it = f->holes_begin(); holes_it != f->holes_end(); ++holes_it)
|
||||
Inner_ccb_const_iterator 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_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:
|
||||
typedef General_polygon_set_2<Gps_segment_traits_2<Kernel, Containter>, Dcel_>
|
||||
Base;
|
||||
typedef typename Base::Base Base_of_base;
|
||||
typedef Polygon_set_2<Kernel, Containter, Dcel_> Self;
|
||||
|
||||
public:
|
||||
|
|
@ -237,9 +238,9 @@ public:
|
|||
|
||||
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)
|
||||
std::cout <<"ALL TESTS SUCCEEDED!" << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout <<"SOME TESTS FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue