cgal/Packages/Arrangement/demo/Leda_window/Arrangement_2/Polygon_intersection.C

170 lines
5.1 KiB
C

#ifndef CGAL_USE_LEDA
// this demo uses LEDA
#else
#include "Polygon_intersection.h"
/////////////////////////////////////////////////////////////////////
// Intersecting Polygons
////////////////////////////////////////////////////////////////////
// we assume the polygons were inserted in CCW order!!
// The face_diff function defines if to increment or decrement
// the number of polygons when moving over an edge from one face to the other.
// Method: if the direction of circ is identical to the curve on it
// then we are inside a polygon (the polygons were inserted ccw) and therefore
// we need to decrement, otherwise we are outside and need to increment
// The present example can be altered or generalized for other boolean
// operations.
// Commented out the regular face_diff that does not deal with overlaps
// as an educative example.
/*
int face_diff( Ccb_halfedge_circulator circ) {
Traits t;
if (circ->source()->point() == t.curve_source(circ->edge_node()->curve()) )
return -1; //we're inside, going outside
else
return 1;
}
*/
//generalized face_diff function, to acount for overlaps.
int face_diff (Ccb_halfedge_circulator circ) {
Traits t;
int diff = 0;
Arr_2::Overlap_circulator oc = circ->overlap_edges();
do {
if (circ->source()->point() == t.curve_source(oc->x_curve()) )
diff--; //we're inside, going outside
else
diff++;
} while (++oc != circ->overlap_edges());
return diff;
}
// covering_DFS will compute for each face in how many polygons it is.
// It is a recursive DFS function and will be called with the unbounded
// face after its counter has been initialized to 0.
void covering_DFS(Face_handle f) {
Ccb_halfedge_circulator start,circ;
// Do a recursive step for all neighbours, if any exists.
if (f->does_outer_ccb_exist()) {
start = circ = f->outer_ccb();
do {
if (circ->twin()->face()->counter < 0) {
int diff = face_diff(circ);
circ->twin()->face()->counter = (f->counter + diff);
covering_DFS(circ->twin()->face());
}
} while (++circ != start);
}
// Do a recursive step for all holes, if any exists.
Arr_2::Holes_iterator hit = f->holes_begin();
for (; Arr_2::Holes_iterator(hit)!=Arr_2::Holes_iterator(f->holes_end());
++hit)
{
start = circ = (*hit);
do {
if (circ->twin()->face()->counter < 0) {
int diff = face_diff(circ);
circ->twin()->face()->counter = (f->counter + diff);
covering_DFS(circ->twin()->face());
}
} while (++circ != start);
}
}
// Construct the arrangement that will use for calculating the intersection.
void insert_polygons(Arr_2 &arr, Polygon_list &in_poly_list)
{
Polygon::Edge_const_iterator it;
Arr_2::Curve_iterator ci;
Polygon_list::iterator plit;
// for each polygon in list
for (plit = in_poly_list.begin(); plit != in_poly_list.end(); plit++) {
// Make sure polygons are oriented counterclockwise
// to satisfy assumption in DFS function
if ( ! plit->is_counterclockwise_oriented())
plit->reverse_orientation();
// insert polygon to arrangement
for (it = plit->edges_begin(); it != plit->edges_end(); it++)
{
ci = arr.insert(*it);
}
}
}
// Convert faces of the arrangement that are in the intersection
// to polygons.
void polygons_from_faces(Arr_2& arr,
std::list<Face_iterator>& face_it_list,
Polygon_list& poly_list)
{
std::list<Face_iterator>::iterator lit;
//Arr_2::Ccb_halfedge_circulator cc;
Polygon poly;
for (lit = face_it_list.begin(); lit != face_it_list.end(); lit++) {
poly.erase(poly.vertices_begin(), poly.vertices_end());
Arr_2::Ccb_halfedge_circulator cc=(*lit)->outer_ccb();
do {
poly.push_back(cc->curve().source());
} while (++cc != (*lit)->outer_ccb());
poly_list.push_back(poly);
}
}
// performs the extraction of data out of the processed arrangement
// if covering = 0, will perform union
// otherwise, if there are n polygons in the arrangement and covering == n
// then will perform intersection
void get_faces_with_covering(Arr_2& arr,
std::list<Face_iterator>& unions,
int covering)
{
Face_handle uf = arr.unbounded_face();
uf->counter = 0;
covering_DFS(uf);
//"collecting" the union boundary faces.
for(Face_iterator fit = arr.faces_begin(); fit!=arr.faces_end(); ++fit) {
// if the face is covered by 'covering'
if (fit->counter == covering) {
unions.push_back(fit);
}
}
}
// The interface for an intersection function
bool intersect_polygons(Polygon_list &in_poly_list,
Polygon_list &out_poly_list)
{
Arr_2 arr(new Arr_naive_pl());
std::list<Face_iterator> face_it_list;
insert_polygons(arr, in_poly_list);
// faces with a covering two are faces that are in the intersection
// of the two polygons.
get_faces_with_covering(arr, face_it_list, in_poly_list.size());
polygons_from_faces(arr, face_it_list, out_poly_list);
if (out_poly_list.empty()) return 0; else return 1;
}
#endif