General_polygon_set_on_surface_2 - first verstion

This commit is contained in:
Ophir Setter 2009-02-17 16:21:43 +00:00
parent c50131c8c9
commit 097c3793fd
17 changed files with 2335 additions and 2147 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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()) &&

View File

@ -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

View File

@ -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&)

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));
}
};

View File

@ -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);
}