mirror of https://github.com/CGAL/cgal
implemented polygon validation as global functions in Gps_polygon_validation.h instead of using afunctor from the GpsTraits2 model
This commit is contained in:
parent
2ccf2ba9cc
commit
fa507ef863
|
|
@ -1255,9 +1255,20 @@ Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes2.dat -text
|
|||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes3.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes4.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/pgn_holes5.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test1.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test2.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test3.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test4.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test5.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test6.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test7.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test8.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/val_test9.dat -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/data/validation/validation_test_output.txt -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/test_agg_op.cmd eol=lf
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/test_bop.cmd eol=lf
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/test_connect_holes.cpp -text
|
||||
Boolean_set_operations_2/test/Boolean_set_operations_2/test_polygon_validation.cpp -text
|
||||
Box_intersection_d/doc_tex/Box_intersection_d/fig/benchmark.eps -text svneol=unset#application/postscript
|
||||
Box_intersection_d/doc_tex/Box_intersection_d/fig/benchmark.gif -text svneol=unset#image/gif
|
||||
Box_intersection_d/doc_tex/Box_intersection_d/fig/benchmark.pdf -text svneol=unset#application/pdf
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
||||
// Copyright (c) 2008 Tel-Aviv University (Israel).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
|
|
@ -11,37 +11,87 @@
|
|||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Boris Kozorovitzky <boriskoz@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_GPS_POLYGON_VALIDATION_VISITOR_H
|
||||
#define CGAL_GPS_POLYGON_VALIDATION_VISITOR_H
|
||||
#ifndef CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
#define CGAL_GPS_POLYGON_VALIDATION_2_H
|
||||
|
||||
#include <CGAL/Sweep_line_2.h>
|
||||
#include <CGAL/Sweep_line_2/Sweep_line_event.h>
|
||||
#include <CGAL/Sweep_line_2/Sweep_line_subcurve.h>
|
||||
#include <CGAL/Sweep_line_empty_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_traits_adaptor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_default_dcel.h>
|
||||
#include <CGAL/General_polygon_set_2.h>
|
||||
#include <list>
|
||||
#include <iterator>
|
||||
#include <CGAL/Arr_naive_point_location.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#include <CGAL/Arr_default_overlay_traits.h>
|
||||
|
||||
/*Arrangement is templated with extended face dcel*/
|
||||
template<typename Arrangement_2>
|
||||
class ValidationOverlayTraits : public CGAL::Arr_default_overlay_traits<Arrangement_2>
|
||||
{
|
||||
public:
|
||||
typedef CGAL::Arr_default_overlay_traits<Arrangement_2> Base;
|
||||
typedef typename Base::Face_handle_A Face_handle_A;
|
||||
typedef typename Base::Face_handle_B Face_handle_B;
|
||||
typedef typename Base::Face_handle_R Face_handle_R;
|
||||
|
||||
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;
|
||||
|
||||
/*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) {
|
||||
if ((red_face->contained()==true) && (blue_face->contained()==false)) {
|
||||
hole_overlap=true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
ValidationOverlayTraits() : hole_overlap(false) {}
|
||||
bool getHoleOverlap() {
|
||||
return hole_overlap;
|
||||
}
|
||||
void setHoleOverlap(bool b) {
|
||||
hole_overlap=b; return;
|
||||
}
|
||||
private:
|
||||
bool hole_overlap;
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
* A visitor used for checking whether the edges of a polygon are
|
||||
* non-intersecting.
|
||||
*/
|
||||
template <class ArrTraits_>
|
||||
|
||||
class Gps_polygon_validation_visitor :
|
||||
public Sweep_line_empty_visitor<ArrTraits_>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef ArrTraits_ Traits_2;
|
||||
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Self;
|
||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Traits_2::Point_2 Point_2;
|
||||
|
|
@ -105,118 +155,26 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
/*! \class
|
||||
* An uxiliary functor used for checking the validity of polygons.
|
||||
*/
|
||||
template <class Traits_, class TraitsAdapter_>
|
||||
class Is_valid_2
|
||||
|
||||
//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)
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Traits_ Traits_2;
|
||||
typedef TraitsAdapter_ Traits_adapter_2;
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Traits_2::Point_2 Point_2;
|
||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
typedef typename Traits_2::Polygon_2 Polygon_2;
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Polygon_with_holes_2::Hole_const_iterator
|
||||
Hole_const_iterator;
|
||||
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;
|
||||
typedef typename Traits_adapter_2::Orientation_2 Check_orientation_2;
|
||||
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||
typedef Sweep_line_2<Traits_2, Visitor> Sweep_line ;
|
||||
|
||||
private:
|
||||
|
||||
// Data members:
|
||||
Construct_curves_2 construct_curves_func;
|
||||
Construct_vertex_2 construct_vertex_func;
|
||||
Check_orientation_2 check_orientation_func;
|
||||
|
||||
public:
|
||||
|
||||
/*! Constructor. */
|
||||
Is_valid_2 (Traits_2& traits,
|
||||
const Traits_adapter_2& tr_adapter)
|
||||
{
|
||||
construct_curves_func = traits.construct_curves_2_object();
|
||||
construct_vertex_func = tr_adapter.construct_vertex_2_object();
|
||||
check_orientation_func = tr_adapter.orientation_2_object();
|
||||
}
|
||||
|
||||
/*! Check if the given polygon is valid. */
|
||||
bool operator()(const Polygon_2& pgn)
|
||||
{
|
||||
bool is_closed = _is_closed(pgn);
|
||||
CGAL_warning_msg (is_closed,
|
||||
"The polygon's boundary is not closed.");
|
||||
if (! is_closed)
|
||||
return (false);
|
||||
|
||||
bool has_valid_orientation = _has_valid_orientation(pgn);
|
||||
CGAL_warning_msg (has_valid_orientation,
|
||||
"The polygon has a wrong orientation.");
|
||||
if (! has_valid_orientation)
|
||||
return (false);
|
||||
|
||||
bool is_strictly_simple = _is_strictly_simple(pgn);
|
||||
CGAL_warning_msg (is_strictly_simple,
|
||||
"The polygon is not strictly simple.");
|
||||
if (! is_strictly_simple)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*! Check if the given polygon with holes is valid. */
|
||||
bool operator()(const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
bool is_closed = _is_closed(pgn);
|
||||
CGAL_warning_msg (is_closed,
|
||||
"The polygon's boundary is not closed.");
|
||||
if (! is_closed)
|
||||
return (false);
|
||||
|
||||
bool has_valid_orientation = _has_valid_orientation(pgn);
|
||||
CGAL_warning_msg (has_valid_orientation,
|
||||
"The polygon has a wrong orientation.");
|
||||
if (! has_valid_orientation)
|
||||
return (false);
|
||||
|
||||
bool is_simple = _is_simple(pgn);
|
||||
CGAL_warning_msg (is_simple,
|
||||
"The polygon is not simple.");
|
||||
if (! is_simple)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool _is_closed(const Polygon_2& pgn)
|
||||
{
|
||||
Cci_pair itr_pair = construct_curves_func (pgn);
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||
Curve_const_iterator begin = itr_pair.first;
|
||||
Curve_const_iterator end = itr_pair.second;
|
||||
|
||||
if (begin == end)
|
||||
return (true); // An empty polygon is valid.
|
||||
|
||||
Traits_2 tr;
|
||||
typename Traits_2::Equal_2 equal_func = tr.equal_2_object();
|
||||
Traits_adapter_2 traits_adapter;
|
||||
typename Traits_2::Equal_2 equal_func = traits.equal_2_object();
|
||||
Curve_const_iterator curr, next;
|
||||
|
||||
Construct_vertex_2 construct_vertex_func;
|
||||
construct_vertex_func = traits_adapter.construct_vertex_2_object();
|
||||
curr = next = begin;
|
||||
++next;
|
||||
|
||||
|
|
@ -250,30 +208,16 @@ protected:
|
|||
|
||||
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
|
||||
|
||||
bool _is_closed (const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
Traits_2 traits;
|
||||
|
||||
if(! _is_closed (traits.construct_outer_boundary_object()(pgn)))
|
||||
return (false);
|
||||
|
||||
Hole_const_iterator itr;
|
||||
std::pair<Hole_const_iterator, Hole_const_iterator> pair = traits.construct_holes_object()(pgn);
|
||||
for (itr = pair.first; itr!=pair.second; ++itr)
|
||||
//for (itr = pgn.holes_begin(); itr != pgn.holes_end(); ++itr)
|
||||
{
|
||||
if(! _is_closed (*itr))
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool _is_strictly_simple (const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
// Sweep the boundary curves and look for intersections.
|
||||
Cci_pair itr_pair = construct_curves_func (pgn);
|
||||
Traits_2 traits;
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||
typedef Sweep_line_2<Traits_2, Visitor> Sweep_line;
|
||||
|
||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||
Visitor visitor;
|
||||
Sweep_line sweep_line (&traits, &visitor);
|
||||
|
||||
|
|
@ -281,53 +225,329 @@ protected:
|
|||
return (visitor.is_valid());
|
||||
}
|
||||
|
||||
bool _is_simple (const Polygon_with_holes_2& pgn)
|
||||
|
||||
template <typename Traits_2>
|
||||
bool has_valid_orientation_polygon (const typename Traits_2::Polygon_2& pgn,Traits_2 traits)
|
||||
{
|
||||
// Construct a container of all boundary curves.
|
||||
Traits_2 traits;
|
||||
Polygon_2 pgn2 = traits.construct_outer_boundary_object()(pgn);
|
||||
Cci_pair itr_pair = construct_curves_func(pgn2);
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
|
||||
std::list<X_monotone_curve_2> curves;
|
||||
std::copy (itr_pair.first, itr_pair.second,
|
||||
std::back_inserter(curves));
|
||||
|
||||
std::pair<Hole_const_iterator, Hole_const_iterator> pair = traits.construct_holes_object()(pgn);
|
||||
Hole_const_iterator hoit;
|
||||
for (hoit = pair.first; hoit!=pair.second; ++hoit)
|
||||
//for (hoit = pgn.holes_begin(); hoit != pgn.holes_end(); ++hoit)
|
||||
{
|
||||
itr_pair = construct_curves_func (*hoit);
|
||||
std::copy (itr_pair.first, itr_pair.second,
|
||||
std::back_inserter(curves));
|
||||
}
|
||||
|
||||
// Perform the sweep and check fir intersections.
|
||||
//Traits_2 traits; moved to top, needed also for boundary.
|
||||
Visitor visitor(false);
|
||||
Sweep_line sweep_line (&traits, &visitor);
|
||||
|
||||
visitor.sweep (curves.begin(), curves.end());
|
||||
return (visitor.is_valid());
|
||||
}
|
||||
|
||||
bool _has_valid_orientation (const Polygon_2& pgn)
|
||||
{
|
||||
Cci_pair itr_pair = construct_curves_func (pgn);
|
||||
Cci_pair itr_pair = traits.construct_curves_2_object()(pgn);
|
||||
Traits_adapter_2 traits_adapter;
|
||||
typedef typename Traits_adapter_2::Orientation_2 Check_orientation_2;
|
||||
|
||||
if(itr_pair.first == itr_pair.second)
|
||||
return (true); // empty polygon
|
||||
|
||||
return (check_orientation_func (itr_pair.first,
|
||||
return (traits_adapter.orientation_2_object()(itr_pair.first,
|
||||
itr_pair.second) == COUNTERCLOCKWISE);
|
||||
}
|
||||
|
||||
bool _has_valid_orientation (const Polygon_with_holes_2& pgn)
|
||||
/* 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)
|
||||
{
|
||||
bool closed = is_closed_polygon(pgn,traits);
|
||||
CGAL_warning_msg (closed,
|
||||
"The polygon's boundary is not closed.");
|
||||
if (! closed)
|
||||
return (false);
|
||||
|
||||
bool simple = is_simple_polygon(pgn,traits);
|
||||
CGAL_warning_msg (simple,
|
||||
"The polygon is not simple.");
|
||||
if (!simple)
|
||||
return (false);
|
||||
|
||||
bool valid_orientation = has_valid_orientation_polygon(pgn,traits);
|
||||
CGAL_warning_msg (valid_orientation,
|
||||
"The polygon has a wrong orientation.");
|
||||
if (! valid_orientation)
|
||||
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)
|
||||
{
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
if(! is_closed_polygon (pgn.outer_boundary(),traits))
|
||||
return (false);
|
||||
|
||||
typename Polygon_with_holes_2::Hole_const_iterator itr;
|
||||
|
||||
for (itr = pgn.holes_begin(); itr != pgn.holes_end(); ++itr)
|
||||
{
|
||||
if(! is_closed_polygon (*itr,traits))
|
||||
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 ) {
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
typedef typename Traits_2::Point_2 Point_2;
|
||||
typedef typename Traits_2::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
|
||||
typedef typename Traits_2::Construct_min_vertex_2 Construct_min_vertex_2;
|
||||
typedef typename Traits_2::Construct_max_vertex_2 Construct_max_vertex_2;
|
||||
typedef CGAL::Gps_default_dcel<Traits_2> dcel;
|
||||
typedef CGAL::General_polygon_set_2<Traits_2, dcel> Polygon_set_2;
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Polygon_set_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename 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();
|
||||
Naive_pl pl (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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//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 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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||
typedef Sweep_line_2<Traits_2, Visitor> Sweep_line;
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
|
||||
Construct_curves_2 construct_curves_func = traits.construct_curves_2_object();
|
||||
// Construct a container of all outer boundary curves.
|
||||
Cci_pair itr_pair = construct_curves_func (pgn.outer_boundary());
|
||||
std::list<X_monotone_curve_2> outer_curves;
|
||||
std::copy (itr_pair.first, itr_pair.second,
|
||||
std::back_inserter(outer_curves));
|
||||
//create visitor and sweep to verify outer boundary is relatively simple
|
||||
Visitor relative_visitor(false);
|
||||
Sweep_line sweep_line (&traits, &relative_visitor);
|
||||
relative_visitor.sweep (outer_curves.begin(), outer_curves.end());
|
||||
if (!relative_visitor.is_valid())
|
||||
return false;
|
||||
|
||||
//verify every hole is simple
|
||||
typename Polygon_with_holes_2::Hole_const_iterator hoit;
|
||||
std::list<X_monotone_curve_2> hole_curves;
|
||||
for (hoit = pgn.holes_begin(); hoit != pgn.holes_end(); ++hoit)
|
||||
{
|
||||
bool simple_hole = is_simple_polygon(*hoit,traits);
|
||||
if (!simple_hole)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
typedef Sweep_line_2<Traits_2, Visitor> Sweep_line;
|
||||
typedef typename Traits_adapter_2::Orientation_2 Check_orientation_2;
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
|
||||
Traits_adapter_2 traits_adapter;
|
||||
|
||||
Construct_curves_2 construct_curves_func = traits.construct_curves_2_object();
|
||||
Check_orientation_2 check_orientation_func = traits_adapter.orientation_2_object();;
|
||||
// Check the orientation of the outer boundary.
|
||||
Traits_2 traits;
|
||||
Polygon_2 pgn2 = traits.construct_outer_boundary_object()(pgn);
|
||||
Cci_pair itr_pair = construct_curves_func (pgn2);
|
||||
Cci_pair itr_pair = construct_curves_func (pgn.outer_boundary());
|
||||
|
||||
if ((itr_pair.first != itr_pair.second) &&
|
||||
check_orientation_func (itr_pair.first,
|
||||
|
|
@ -337,11 +557,9 @@ protected:
|
|||
}
|
||||
|
||||
// Check the orientation of each of the holes.
|
||||
// typename Polygon_with_holes_2::
|
||||
Hole_const_iterator hoit;
|
||||
std::pair<Hole_const_iterator, Hole_const_iterator> pair = traits.construct_holes_object()(pgn);
|
||||
for (hoit = pair.first; hoit!=pair.second;++hoit)
|
||||
//for (hoit = pgn.holes_begin(); hoit != pgn.holes_end(); ++hoit)
|
||||
typename Polygon_with_holes_2::Hole_const_iterator hoit;
|
||||
|
||||
for (hoit = pgn.holes_begin(); hoit != pgn.holes_end(); ++hoit)
|
||||
{
|
||||
itr_pair = construct_curves_func (*hoit);
|
||||
|
||||
|
|
@ -352,11 +570,206 @@ protected:
|
|||
return (false);
|
||||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*Verify holes do not intersect between themselves as well with the outer boundary
|
||||
(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.
|
||||
|
||||
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)
|
||||
{
|
||||
CGAL_GPS_POLYGON_VALIDATION_2_TYPEDEF
|
||||
|
||||
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::Size Size;
|
||||
typedef typename Traits_2::Polygon_2 Polygon_2;
|
||||
typedef typename Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef typename Polygon_with_holes_2::Hole_const_iterator Hole_const_iterator;
|
||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
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;
|
||||
typedef Gps_polygon_validation_visitor<Traits_2> Visitor;
|
||||
typedef Sweep_line_2<Traits_2, Visitor> Sweep_line ;
|
||||
typedef typename Polygon_set_2::Arrangement_2 Arrangement_2;
|
||||
|
||||
/* Should be perfored more efficeintly than using sweep and than difference().*/
|
||||
|
||||
/*Use sweep to find intersections on the interior of curves (not on vertices) and overlapping edges which are not allowed
|
||||
(note that 0/1 dimension intersections are not detectes by do_intersect() which only returns the 2D intersection polygon if exists)
|
||||
Note that using this sweep alone allows for a hole and an edge to share a vertex and intersect
|
||||
(like illegal input pgn_w_overlap_hole.dat in validation_example)*/
|
||||
Hole_const_iterator hoit;
|
||||
// Construct a container of all boundary curves.
|
||||
Polygon_2 pgn2 = traits.construct_outer_boundary_object()(pwh);
|
||||
Construct_curves_2 construct_curves_func;
|
||||
Cci_pair itr_pair = construct_curves_func(pgn2);
|
||||
|
||||
std::list<X_monotone_curve_2> curves;
|
||||
std::copy (itr_pair.first, itr_pair.second,
|
||||
std::back_inserter(curves));
|
||||
|
||||
std::pair<Hole_const_iterator, Hole_const_iterator> pair = traits.construct_holes_object()(pwh);
|
||||
for (hoit = pair.first; hoit!=pair.second; ++hoit)
|
||||
//for (hoit = pgn.holes_begin(); hoit != pgn.holes_end(); ++hoit)
|
||||
{
|
||||
itr_pair = construct_curves_func (*hoit);
|
||||
std::copy (itr_pair.first, itr_pair.second,
|
||||
std::back_inserter(curves));
|
||||
}
|
||||
|
||||
// Perform the sweep and check for curve intersections on the interior.
|
||||
//Traits_2 traits; moved to top, needed also for boundary.
|
||||
Visitor visitor(false);
|
||||
Sweep_line sweep_line (&traits, &visitor);
|
||||
visitor.sweep (curves.begin(), curves.end());
|
||||
if (!visitor.is_valid())
|
||||
return false;
|
||||
|
||||
Polygon_set_2 gps(traits);
|
||||
//check for 2D intersections of holes (holes must be disjoint except for vertices)
|
||||
Size num_of_holes=0;
|
||||
for (hoit = pwh.holes_begin(); hoit != pwh.holes_end(); ++hoit) {
|
||||
Polygon_2 hole(*hoit);
|
||||
hole.reverse_orientation();
|
||||
/*gps.join() and gps.insert()requires that the polyon insrted is valid, and therfore hole
|
||||
orientation must be reversed*/
|
||||
bool intersect = gps.do_intersect(hole);
|
||||
if (intersect)
|
||||
return false;
|
||||
else {
|
||||
/*to use gps.insert(hole) it is required that the set coponents and the new holes do not intersect.
|
||||
because the sweep detects shared edges and the do_intersect query detects 2D intersections we can safely use
|
||||
the insert(pwh) function whose performance is better than the join(pgn)*/
|
||||
Polygon_with_holes_2 empty_pwh(hole);
|
||||
gps.insert(empty_pwh);
|
||||
num_of_holes++;
|
||||
}
|
||||
}
|
||||
/*not good - doesn't work if intersection at vertices is legal.
|
||||
Size arr_num_of_holes = gps.number_of_polygons_with_holes();
|
||||
if (num_of_holes != arr_num_of_holes)
|
||||
return false;
|
||||
*/
|
||||
//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
|
||||
valid polygon or PWH to be inserted (not just a simple polygon).
|
||||
This helper function is utilized after checking for the PWH closure,
|
||||
relative simplicity and orientation. Therefore it is safe to assume the
|
||||
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
|
||||
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
|
||||
the holes should be the empty set. For performance reasons, we use a customized overlay traits and
|
||||
perform an arrangement overlay instead of difference */
|
||||
ValidationOverlayTraits<Arrangement_2> valOverlayTraits;
|
||||
valOverlayTraits.setHoleOverlap(false);
|
||||
Polygon_set_2 gps2(traits);
|
||||
|
||||
Arrangement_2 boundary_arr = gps2.arrangement();
|
||||
gps2._insert(boundary,boundary_arr);
|
||||
Arrangement_2 holes_arr = gps.arrangement();
|
||||
Arrangement_2 output_arr;
|
||||
overlay(holes_arr, boundary_arr, output_arr, valOverlayTraits);
|
||||
if (valOverlayTraits.getHoleOverlap())
|
||||
return false;
|
||||
|
||||
/*old code that works less efficiently than the new overly traits
|
||||
gps.validation_difference(boundary);
|
||||
//if gps is not empty at least one hole intersected the boundary
|
||||
if (!gps.is_empty())
|
||||
return (false);
|
||||
*/
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*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)
|
||||
{
|
||||
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.");
|
||||
if (! closed)
|
||||
return (false);
|
||||
|
||||
bool relatively_simple = is_relatively_simple_polygon_with_holes(pgn,traits);
|
||||
CGAL_warning_msg (relatively_simple,
|
||||
"The polygon is not relatively simple.");
|
||||
if (! relatively_simple)
|
||||
return (false);
|
||||
|
||||
bool no_cross = is_crossover_outer_boundary(pgn, traits);
|
||||
CGAL_warning_msg (no_cross,
|
||||
"The polygon has a crossover.");
|
||||
if (!no_cross)
|
||||
return (false);
|
||||
|
||||
bool valid_orientation = has_valid_orientation_polygon_with_holes(pgn,traits);
|
||||
CGAL_warning_msg (valid_orientation,
|
||||
"The polygon has a wrong orientation.");
|
||||
if (! valid_orientation)
|
||||
return (false);
|
||||
|
||||
bool holes_disjoint = are_holes_and_boundary_pairwise_disjoint(pgn,traits);
|
||||
CGAL_warning_msg (holes_disjoint,
|
||||
"Holes of the PWH intersect amongst themselves or with outer boundary");
|
||||
if (! holes_disjoint)
|
||||
return false;
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
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,
|
||||
Traits_2 traits)
|
||||
{
|
||||
return is_valid_polygon(pgn, traits);
|
||||
}
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,6 @@ template <class Traits_, class Dcel_>
|
|||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
_insert(const Polygon_2& pgn, Arrangement_2 & arr)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
typedef Arr_accessor<Arrangement_2> Arr_accessor;
|
||||
|
||||
Arr_accessor accessor(arr);
|
||||
|
|
@ -379,6 +378,11 @@ void General_polygon_set_2<Traits_, Dcel_>::
|
|||
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));
|
||||
}
|
||||
_insert(p_begin, p_end, pgn);
|
||||
}
|
||||
|
||||
|
|
@ -396,14 +400,14 @@ insert(PolygonIter p_begin, PolygonIter p_end,
|
|||
|
||||
for( ; p_begin != p_end; ++p_begin)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*p_begin));
|
||||
CGAL_precondition(is_valid_polygon(*p_begin, *m_traits));
|
||||
_construct_curves(*p_begin, std::back_inserter(xcurve_list));
|
||||
}
|
||||
|
||||
bool is_unbounded = false;
|
||||
for( ; pwh_begin != pwh_end; ++pwh_begin)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*pwh_begin));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(*pwh_begin, *m_traits));
|
||||
is_unbounded = (is_unbounded || m_traits->construct_is_unbounded_object()(*pwh_begin));
|
||||
// is_unbounded = (is_unbounded || pwh_begin->is_unbounded());
|
||||
_construct_curves(*pwh_begin, std::back_inserter(xcurve_list));
|
||||
|
|
@ -427,7 +431,6 @@ _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2 & /*pgn*/)
|
|||
{
|
||||
for(PolygonIter pitr = p_begin; pitr != p_end; ++pitr)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*pitr));
|
||||
this->_insert(*pitr, *m_arr);
|
||||
}
|
||||
}
|
||||
|
|
@ -445,7 +448,6 @@ _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
|
|||
bool is_unbounded = false;
|
||||
for( ; p_begin != p_end; ++p_begin)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*p_begin));
|
||||
// is_unbounded = (is_unbounded || p_begin->is_unbounded());
|
||||
is_unbounded = (is_unbounded || m_traits->construct_is_unbounded_object()(*p_begin));
|
||||
_construct_curves(*p_begin, std::back_inserter(xcurve_list));
|
||||
|
|
@ -469,7 +471,8 @@ template <class Traits_, class Dcel_>
|
|||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
_insert(const Polygon_with_holes_2 & pgn, Arrangement_2 & arr)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
//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;
|
||||
|
|
@ -502,8 +505,7 @@ _construct_curves(const Polygon_2 & pgn, OutputIterator oi)
|
|||
|
||||
template <class Traits_, class Dcel_>
|
||||
template <class OutputIterator>
|
||||
void
|
||||
General_polygon_set_2<Traits_, Dcel_>::
|
||||
void General_polygon_set_2<Traits_, Dcel_>::
|
||||
_construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
|
||||
{
|
||||
//if (!pgn.is_unbounded())
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ public:
|
|||
m_traits_owner(true),
|
||||
m_arr(new Arrangement_2(m_traits))
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_insert(pgn, *m_arr);
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ public:
|
|||
m_traits_owner(true),
|
||||
m_arr(new Arrangement_2(m_traits))
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn_with_holes));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn_with_holes,*m_traits));
|
||||
_insert(pgn_with_holes, *m_arr);
|
||||
}
|
||||
|
||||
|
|
@ -197,18 +197,17 @@ public:
|
|||
// insert a simple polygon
|
||||
void insert(const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_insert(pgn, *m_arr);
|
||||
}
|
||||
|
||||
// insert a polygon with holes
|
||||
void insert(const Polygon_with_holes_2& pgn_with_holes)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn_with_holes));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn_with_holes, *m_traits));
|
||||
_insert(pgn_with_holes, *m_arr);
|
||||
}
|
||||
|
||||
|
||||
// insert a range of polygons that can be either simple polygons
|
||||
// or polygons with holes
|
||||
// precondition: the polygons are disjoint and simple
|
||||
|
|
@ -228,7 +227,7 @@ public:
|
|||
// test for intersection with a simple polygon
|
||||
bool do_intersect(const Polygon_2 &pgn) const
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn,*m_traits));
|
||||
Self other(pgn);
|
||||
return (do_intersect(other));
|
||||
}
|
||||
|
|
@ -236,7 +235,7 @@ public:
|
|||
// test for intersection with a polygon with holes
|
||||
bool do_intersect(const Polygon_with_holes_2& pgn_with_holes) const
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn_with_holes));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn_with_holes, *m_traits));
|
||||
Self other(pgn_with_holes);
|
||||
return (do_intersect(other));
|
||||
}
|
||||
|
|
@ -278,14 +277,14 @@ public:
|
|||
// intersection with a simple polygon
|
||||
void intersection(const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_intersection(pgn);
|
||||
}
|
||||
|
||||
// intersection with a polygon with holes
|
||||
void intersection(const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
_intersection(pgn);
|
||||
}
|
||||
|
||||
|
|
@ -305,14 +304,14 @@ public:
|
|||
// join with a simple polygon
|
||||
void join(const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_join(pgn);
|
||||
}
|
||||
|
||||
// join with a polygon with holes
|
||||
void join(const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
_join(pgn);
|
||||
}
|
||||
|
||||
|
|
@ -328,18 +327,17 @@ public:
|
|||
_join(*(gps1.m_arr), *(gps2.m_arr), *(this->m_arr));
|
||||
}
|
||||
|
||||
|
||||
// difference with a simple polygon
|
||||
void difference (const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_difference(pgn);
|
||||
}
|
||||
|
||||
// difference with a polygon with holes
|
||||
void difference (const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
_difference(pgn);
|
||||
}
|
||||
|
||||
|
|
@ -359,14 +357,14 @@ public:
|
|||
// symmetric_difference with a simple polygon
|
||||
void symmetric_difference(const Polygon_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
_symmetric_difference(pgn);
|
||||
}
|
||||
|
||||
// symmetric_difference with a polygon with holes
|
||||
void symmetric_difference(const Polygon_with_holes_2& pgn)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
_symmetric_difference(pgn);
|
||||
}
|
||||
|
||||
|
|
@ -490,14 +488,14 @@ public:
|
|||
|
||||
Oriented_side oriented_side(const Polygon_2& pgn) const
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon(pgn, *m_traits));
|
||||
Self other(pgn);
|
||||
return (oriented_side(other));
|
||||
}
|
||||
|
||||
Oriented_side oriented_side(const Polygon_with_holes_2& pgn) const
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(pgn));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(pgn, *m_traits));
|
||||
Self other(pgn);
|
||||
return (oriented_side(other));
|
||||
}
|
||||
|
|
@ -701,7 +699,7 @@ public:
|
|||
|
||||
for (InputIterator itr = begin; itr!=end; ++itr, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr));
|
||||
CGAL_precondition(is_valid_polygon((*itr), *m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
@ -726,7 +724,7 @@ public:
|
|||
|
||||
for (InputIterator itr = begin; itr!=end; ++itr, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr));
|
||||
CGAL_precondition(is_valid_polygon_with_holes((*itr), *m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
@ -753,14 +751,14 @@ public:
|
|||
|
||||
for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr1));
|
||||
CGAL_precondition(is_valid_unknown_polygon(*itr1, *m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr1, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr2));
|
||||
CGAL_precondition(is_valid_unknown_polygon(*itr2,*m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr2, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
@ -801,7 +799,7 @@ public:
|
|||
|
||||
for (InputIterator itr = begin; itr!=end; ++itr, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr));
|
||||
CGAL_precondition(is_valid_polygon(*itr,*m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
@ -826,7 +824,7 @@ public:
|
|||
|
||||
for (InputIterator itr = begin; itr!=end; ++itr, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr));
|
||||
CGAL_precondition(is_valid_polygon_with_holes(*itr,*m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
@ -853,14 +851,14 @@ public:
|
|||
|
||||
for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr1));
|
||||
CGAL_precondition(is_valid_unknown_polygon(*itr1, *m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr1, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i)
|
||||
{
|
||||
CGAL_precondition(m_traits->is_valid_2_object()(*itr2));
|
||||
CGAL_precondition(is_valid_unknown_polygon(*itr2,*m_traits));
|
||||
arr_vec[i].first = new Arrangement_2(m_traits);
|
||||
_insert(*itr2, *(arr_vec[i].first));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,14 +126,14 @@ public:
|
|||
* An auxiliary functor used for validity checks.
|
||||
*/
|
||||
typedef Gps_traits_adaptor<Base> Traits_adaptor;
|
||||
typedef CGAL::Is_valid_2<Self, Traits_adaptor> Is_valid_2;
|
||||
|
||||
/* typedef CGAL::Is_valid_2<Self, Traits_adaptor> Is_valid_2;
|
||||
Is_valid_2 is_valid_2_object()
|
||||
{
|
||||
Traits_adaptor tr_adp;
|
||||
|
||||
return (Is_valid_2 (*this, tr_adp));
|
||||
}
|
||||
}*/
|
||||
|
||||
//Added Functionality from GeneralPolygonWithHoles Concept to the traits.
|
||||
|
||||
|
|
|
|||
|
|
@ -104,14 +104,15 @@ public:
|
|||
* An auxiliary functor used for validity checks.
|
||||
*/
|
||||
typedef Gps_traits_adaptor<Base> Traits_adaptor;
|
||||
typedef CGAL::Is_valid_2<Self, Traits_adaptor> Is_valid_2;
|
||||
|
||||
/*typedef CGAL::Is_valid_2<Self, Traits_adaptor> Is_valid_2;
|
||||
Is_valid_2 is_valid_2_object()
|
||||
{
|
||||
Traits_adaptor tr_adp;
|
||||
|
||||
return (Is_valid_2 (*this, tr_adp));
|
||||
}
|
||||
}*/
|
||||
|
||||
//Added Functionality from GeneralPolygonWithHoles Concept to the traits.
|
||||
|
||||
/*A functor for constructing the outer boundary of a polygon with holes*/
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
// $Id$
|
||||
//
|
||||
// Author(s) : Ron Wein <wein@post.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_CONNECT_HOLES_H
|
||||
#define CGAL_CONNECT_HOLES_H
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Polygon_2.h>
|
||||
#include <CGAL/Polygon_with_holes_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_polygon_validation.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
#include <CGAL/iterator.h>
|
||||
#include <vector>
|
||||
|
|
@ -48,7 +49,7 @@ bool are_polygons_valid(Vec& vec)
|
|||
unsigned int i=0;
|
||||
for(; i < vec.size(); ++i)
|
||||
{
|
||||
if(!tr.is_valid_2_object()(vec[i]))
|
||||
if(!is_valid_unknown_polygon(vec[i], tr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <CGAL/Polygon_2.h>
|
||||
#include <CGAL/Polygon_with_holes_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_polygon_validation.h>
|
||||
#include <CGAL/iterator.h>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
|
@ -42,7 +43,7 @@ bool are_polygons_valid(const std::vector<Polygon_with_holes_2>& vec)
|
|||
unsigned int i=0;
|
||||
for(; i < vec.size(); ++i)
|
||||
{
|
||||
if(!tr.is_valid_2_object()(vec[i]))
|
||||
if(!is_valid_polygon_with_holes(vec[i],tr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -61,7 +62,7 @@ std::ostream& write_result_to_file(std::ostream& out, const T_P1& p1, const T_P2
|
|||
{
|
||||
out << 1 << std::endl;
|
||||
out << res_pgn <<std::endl;
|
||||
if(!tr.is_valid_2_object()(res_pgn))
|
||||
if(!is_valid_polygon_with_holes(res_pgn,tr))
|
||||
std::cout<<"warning: invalid polygon was generated\n";
|
||||
}
|
||||
else
|
||||
|
|
@ -121,7 +122,7 @@ std::ostream& write_complement_to_file(std::ostream& out, const Polygon_2& pgn)
|
|||
out << res_pgn << std::endl;
|
||||
|
||||
Traits_2 tr;
|
||||
if(!tr.is_valid_2_object()(res_pgn))
|
||||
if(!is_valid_polygon_with_holes(res_pgn,tr))
|
||||
std::cout<<"warning: invalid polygon was generated\n";
|
||||
|
||||
return out;
|
||||
|
|
@ -188,7 +189,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
inp1 >> p1;
|
||||
out << p1;
|
||||
if(! tr.is_valid_2_object()(p1))
|
||||
if(! is_valid_polygon(p1,tr))
|
||||
{
|
||||
std::cout<<"warning: first input polygon is invalid!!!\n";
|
||||
}
|
||||
|
|
@ -197,7 +198,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
inp1 >> pwh1;
|
||||
out << pwh1;
|
||||
if(! tr.is_valid_2_object()(pwh1))
|
||||
if(! is_valid_polygon_with_holes(pwh1,tr))
|
||||
{
|
||||
std::cout<<"warning: first input polygon is invalid!!!\n";
|
||||
}
|
||||
|
|
@ -213,7 +214,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
inp2 >> p2;
|
||||
out << p2;
|
||||
if(! tr.is_valid_2_object()(p2))
|
||||
if(!is_valid_polygon(p2,tr))
|
||||
{
|
||||
std::cout<<"warning: second input polygon is invalid!!!\n";
|
||||
}
|
||||
|
|
@ -222,7 +223,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
inp2 >> pwh2;
|
||||
out << pwh2;
|
||||
if(! tr.is_valid_2_object()(pwh2))
|
||||
if(! is_valid_polygon_with_holes(pwh2,tr))
|
||||
{
|
||||
std::cout<<"warning: second input polygon is invalid!!!\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
4
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
1
|
||||
|
||||
6
|
||||
1 1
|
||||
2 2
|
||||
3 1
|
||||
4 2
|
||||
5 1
|
||||
3 1
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
6
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
6 8
|
||||
2 8
|
||||
0 8
|
||||
|
||||
1
|
||||
|
||||
5
|
||||
1 6
|
||||
2 8
|
||||
4 12
|
||||
6 8
|
||||
7 6
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
4
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
2
|
||||
|
||||
4
|
||||
2 2
|
||||
2 6
|
||||
6 6
|
||||
6 2
|
||||
|
||||
4
|
||||
5 4
|
||||
5 5
|
||||
7 5
|
||||
7 4
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
4
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
2
|
||||
|
||||
4
|
||||
1 1
|
||||
1 7
|
||||
7 7
|
||||
7 1
|
||||
4
|
||||
2 2
|
||||
2 6
|
||||
6 6
|
||||
6 2
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
4
|
||||
0 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
2
|
||||
|
||||
4
|
||||
1 2
|
||||
1 6
|
||||
2 6
|
||||
2 2
|
||||
4
|
||||
2 2
|
||||
2 6
|
||||
6 6
|
||||
6 2
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
6
|
||||
0 0
|
||||
2 0
|
||||
4 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
1
|
||||
|
||||
4
|
||||
2 0
|
||||
2 6
|
||||
4 6
|
||||
4 0
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
6
|
||||
0 2
|
||||
4 2
|
||||
6 4
|
||||
6 0
|
||||
4 2
|
||||
2 4
|
||||
|
||||
0
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
6
|
||||
0 2
|
||||
4 2
|
||||
6 0
|
||||
6 4
|
||||
4 2
|
||||
2 4
|
||||
|
||||
0
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
5
|
||||
0 0
|
||||
4 0
|
||||
8 0
|
||||
8 8
|
||||
0 8
|
||||
|
||||
2
|
||||
|
||||
4
|
||||
4 0
|
||||
2 2
|
||||
4 4
|
||||
4 2
|
||||
|
||||
3
|
||||
4 4
|
||||
2 6
|
||||
6 6
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*test file for polygon validation. Intended for testing the global functions defined at Gps_polygon_validation.h*/
|
||||
|
||||
|
||||
#ifndef CGAL_BSO_RATIONAL_NT_H
|
||||
#define CGAL_BSO_RATIONAL_NT_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
||||
#ifdef CGAL_USE_GMP
|
||||
// GMP is installed. Use the GMP rational number-type.
|
||||
#include <CGAL/Gmpq.h>
|
||||
typedef CGAL::Gmpq Number_type;
|
||||
#else
|
||||
// GMP is not installed. Use CGAL's exact rational number-type.
|
||||
#include <CGAL/MP_Float.h>
|
||||
#include <CGAL/Quotient.h>
|
||||
typedef CGAL::Quotient<CGAL::MP_Float> Number_type;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/Gps_segment_traits_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2.h>
|
||||
#include <list>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_polygon_validation.h>
|
||||
#include <CGAL/General_polygon_set_2.h>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
typedef CGAL::Cartesian<Number_type> Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Circle_2 Circle_2;
|
||||
typedef CGAL::Gps_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
|
||||
typedef Traits_2::Polygon_2 Polygon_2;
|
||||
typedef Traits_2::Polygon_with_holes_2 Polygon_with_holes_2;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Base;
|
||||
typedef CGAL::Gps_traits_adaptor<Base> Traits_adaptor;
|
||||
typedef std::list<Polygon_with_holes_2> Pwh_list_2;
|
||||
|
||||
/*test files:
|
||||
|
||||
1. val_test1.dat - invalid polygon with holes. The hole is relatively simple instead of strictly simple.
|
||||
2. val_test2.dat - invalid polygon with holes. The hole overlaps the outer boundary (the intersection results in a polygon).
|
||||
3. val_test3.dat - invalid polygon with holes. Two holes intersect (the intersection results in a polygon).
|
||||
4. val_test4.dat - invalid polygon with holes. Two holes intersect (one contains the other).
|
||||
5. val_test5.dat - invalid polygon with holes. Two holes share an edge. (non regularized intersection
|
||||
results in an edge).
|
||||
6. val_test6.dat - invalid polygon with holes. A hole and the outer boundary share an edge. (non regularized intersection
|
||||
results in an edge).
|
||||
7. val_test7.dat - invalid polygon with holes. The outer boundary is not relatively simple because a "crossover" occurs
|
||||
at an intersection
|
||||
8. val_test8.dat - valid polygon with holes. Outer boundary is relatively simple.
|
||||
9. val_test9.dat - valid polygon with holes. Outer Boundary and holes are pairwise disjoint except on vertices
|
||||
*/
|
||||
|
||||
|
||||
/*test an input file. isValid indicates the input polygon is valid. ErrorMsg is displayed if the validation result does't equal isValid */
|
||||
bool testValidationForFile(const char* infilename, std::ofstream& outfile , bool isValid) {
|
||||
std::ifstream input_file (infilename);
|
||||
|
||||
if (! input_file.is_open()) {
|
||||
std::cerr << "Failed to open the " << infilename <<std::endl;
|
||||
return (false);
|
||||
}
|
||||
// Read a polygon with holes from a file.
|
||||
Polygon_2 outerP;
|
||||
unsigned int num_holes;
|
||||
|
||||
input_file >> outerP;
|
||||
input_file >> num_holes;
|
||||
|
||||
std::vector<Polygon_2> holes (num_holes);
|
||||
unsigned int k;
|
||||
|
||||
for (k = 0; k < num_holes; k++)
|
||||
input_file >> holes[k];
|
||||
Polygon_with_holes_2 P (outerP, holes.begin(), holes.end());
|
||||
Traits_2 tr;
|
||||
bool testValid = CGAL::is_valid_polygon_with_holes(P,tr);
|
||||
bool res = true;
|
||||
if (testValid != isValid) {
|
||||
res=false;
|
||||
outfile<< "Error validating " << infilename <<std::endl;
|
||||
//outfile << "P = " ;
|
||||
//print_polygon_with_holes (P);
|
||||
outfile<<std::endl;
|
||||
}
|
||||
input_file.close();
|
||||
return res;
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
std::string testfilePrefix = "data/validation/val_test";
|
||||
std::string testfileSuffix = ".dat";
|
||||
const char* outputfilename = "data/validation/validation_test_output.txt";
|
||||
std::ofstream output_file (outputfilename);
|
||||
if (! output_file.is_open()) {
|
||||
std::cerr << "Failed to open the " << outputfilename <<std::endl;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
for (int i=1;i<10;i++) {
|
||||
std::stringstream strs;
|
||||
std::string si;
|
||||
strs << i;
|
||||
strs >> si;
|
||||
std::string filename = testfilePrefix + si + testfileSuffix;
|
||||
const char *cfilename = filename.c_str();
|
||||
bool isValidPgn=false;
|
||||
if (i>7)
|
||||
isValidPgn=true;
|
||||
bool res = testValidationForFile(cfilename, output_file, isValidPgn);
|
||||
if (!res) {
|
||||
std::cout << "test " << i << " failed" << std::endl;
|
||||
result=1;
|
||||
}
|
||||
else {
|
||||
std::cout <<"test " << i << " succeeded" << std::endl;
|
||||
}
|
||||
}
|
||||
if (result == 0)
|
||||
std::cout <<"ALL TESTS SUCCEEDED!" << std::endl;
|
||||
else
|
||||
std::cout <<"SOME TESTS FAILED" << std::endl;
|
||||
return (0);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue