mirror of https://github.com/CGAL/cgal
579 lines
17 KiB
C++
579 lines
17 KiB
C++
// ======================================================================
|
|
//
|
|
// Copyright (c) 1997 The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// release :
|
|
// release_date : 1999, October 01
|
|
//
|
|
// file : include/CGAL/intersecting_polygons.h
|
|
// package : bops (2.2)
|
|
// source : include/CGAL/intersecting_polygons.h
|
|
// revision : $Revision$
|
|
// revision_date : $Date$
|
|
// author(s) : Carl Van Geem <Carl.Van.Geem@risc.uni-linz.ac.at>
|
|
//
|
|
// coordinator : RISC Linz
|
|
// (Wolfgang Freiseisen <wfreisei@risc.uni-linz.ac.at>)
|
|
//
|
|
//
|
|
// ======================================================================
|
|
|
|
#ifndef CGAL_INTERSECTING_POLYGONS_H
|
|
#define CGAL_INTERSECTING_POLYGONS_H
|
|
|
|
#include <list>
|
|
#include <vector>
|
|
#ifndef CGAL_POINT_2_H
|
|
#include <CGAL/Point_2.h>
|
|
#endif
|
|
#ifndef CGAL_SEGMENT_2_H
|
|
#include <CGAL/Segment_2.h>
|
|
#endif
|
|
#ifndef CGAL_POLYGON_2_H
|
|
#include <CGAL/Polygon_2.h>
|
|
#endif
|
|
#include <iostream>
|
|
|
|
|
|
#ifndef CGAL_NSQUARE_INTERSECTING_H
|
|
#include <CGAL/nsquare_intersecting.h>
|
|
#endif
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
struct _intersecting_polygons_myhelpelement
|
|
{
|
|
int _endpointleft;
|
|
int _endpointright;
|
|
std::list<int> _cutpoints;
|
|
};
|
|
|
|
|
|
template < class R, class Container >
|
|
class _intersecting_polygons {
|
|
public:
|
|
typedef Polygon_2<Polygon_traits_2<R>, Container> Polygon;
|
|
typedef typename Polygon::Vertex_const_iterator Polygon_vertex_const_iterator;
|
|
typedef std::list<Intersectionresult<R> > Intersectionresult;
|
|
typedef typename Intersectionresult::const_iterator
|
|
Intersectionresult_iterator;
|
|
typedef Point_2<R> Point;
|
|
typedef Segment_2<R> Segment;
|
|
typedef std::vector<Point> Point_list;
|
|
typedef typename Point_list::iterator Point_list_iterator;
|
|
typedef std::list< std::pair<int,int> > Edge_list;
|
|
typedef typename Edge_list::iterator Edge_list_iterator;
|
|
|
|
private:
|
|
Polygon _polyA, _polyB;
|
|
Intersectionresult _intersection_result;
|
|
|
|
|
|
public:
|
|
_intersecting_polygons () {}
|
|
_intersecting_polygons (const Polygon& pA, const Polygon& pB) {
|
|
|
|
nsquareintersection<R, Container > nsquareintersection;
|
|
_intersection_result=nsquareintersection(pA.edges_begin(), pA.edges_end(),
|
|
pB.edges_begin(), pB.edges_end());
|
|
_polyA = pA;
|
|
_polyB = pB;
|
|
}
|
|
|
|
~_intersecting_polygons() {}
|
|
|
|
Polygon A() const { return _polyA;}
|
|
Polygon B() const { return _polyB;}
|
|
Intersectionresult intersection_result() const {
|
|
return _intersection_result;
|
|
}
|
|
|
|
|
|
int size() const { return _intersection_result.size(); }
|
|
|
|
void get_graph_information(Point_list& a_ptlst,
|
|
Edge_list& an_edlst){
|
|
get_graph_information_code(_intersection_result, _polyA, _polyB,
|
|
a_ptlst, an_edlst);
|
|
}
|
|
|
|
|
|
std::list<Point_2<R> > get_color_informationA() {
|
|
return get_color_information_code( _intersection_result, _polyA, 1);
|
|
}
|
|
|
|
|
|
std::list<Point_2<R> > get_color_informationB() {
|
|
return get_color_information_code( _intersection_result, _polyB, 2);
|
|
}
|
|
|
|
protected:
|
|
void get_graph_information_code(
|
|
const Intersectionresult& lresult,
|
|
const Polygon& polyA,
|
|
const Polygon& polyB,
|
|
Point_list& ptlst,
|
|
Edge_list& edlst)
|
|
{
|
|
/* built up the graph (step 2 in README) */
|
|
typedef _intersecting_polygons_myhelpelement myhelpelement;
|
|
std::list<myhelpelement> myhelpstructure;
|
|
myhelpelement edgetosplitel ;
|
|
|
|
Intersectionresult_iterator lrit;
|
|
Point pt;
|
|
Segment sm;
|
|
Segment edgetosplit;
|
|
Point_list_iterator ptlstit, ptlstit2;
|
|
std::pair<int,int> apair;
|
|
std::pair<int,int> newpair;
|
|
Edge_list_iterator edlstit, edlstit2, tobeerased;
|
|
int asize;
|
|
Polygon_vertex_const_iterator ait;
|
|
int minnr;
|
|
int maxnr;
|
|
int i;
|
|
int j;
|
|
int pointnr = 0;
|
|
int count = 0;
|
|
int sourceofedge = 0;
|
|
int targetofedge = 0;
|
|
int firstbpoint = 0;
|
|
int nrofvertices = 0;
|
|
bool inlist;
|
|
bool inedgelist;
|
|
bool added;
|
|
std::list<myhelpelement> edgestosplitlst;
|
|
std::list<myhelpelement>::iterator splitit;
|
|
std::list<int>::iterator intit, intit2;
|
|
/* put vertices of A in, add all segments of A (step A in README) */
|
|
asize = polyA.size();
|
|
i=0;
|
|
for (ait = polyA.vertices_begin(); ait != polyA.vertices_end(); ait++)
|
|
{
|
|
ptlst.push_back(*ait);
|
|
sourceofedge = i;
|
|
targetofedge = (i+1)%asize;
|
|
if (sourceofedge < targetofedge)
|
|
edlst.push_back( std::make_pair(sourceofedge, targetofedge));
|
|
else
|
|
edlst.push_back( std::make_pair(targetofedge, sourceofedge));
|
|
i++;
|
|
}
|
|
/* put vertices of B in, except those that are already there,
|
|
add all segments of B (step B in README) */
|
|
//bsize = polyB.size();
|
|
i=0;
|
|
for (ait = polyB.vertices_begin(); ait != polyB.vertices_end(); ait++)
|
|
{/* check whether or not polyB[i] is in the list */
|
|
ptlstit = ptlst.begin();
|
|
inlist = false;
|
|
sourceofedge = targetofedge;
|
|
for (j=0; j<asize; j++)
|
|
{
|
|
if ((*ptlstit)==(*ait))
|
|
{
|
|
inlist = true;
|
|
if (i==0)
|
|
firstbpoint = j;
|
|
targetofedge = j;
|
|
j = asize;
|
|
}
|
|
ptlstit++;
|
|
}
|
|
if (!inlist)
|
|
{
|
|
targetofedge = ptlst.size();
|
|
ptlst.push_back(*ait);
|
|
if (i==0)
|
|
firstbpoint = targetofedge;
|
|
}
|
|
if (i!=0)
|
|
{
|
|
if (sourceofedge < targetofedge)
|
|
newpair = std::make_pair(sourceofedge,targetofedge);
|
|
else
|
|
newpair = std::make_pair(targetofedge,sourceofedge);
|
|
/* pair already in the list? */
|
|
inedgelist = false;
|
|
for(edlstit2=edlst.begin(); edlstit2!=edlst.end(); edlstit2++)
|
|
inedgelist = inedgelist || ((*edlstit2) == newpair);
|
|
if (!inedgelist)
|
|
edlst.push_back(newpair);
|
|
}
|
|
i++;
|
|
}
|
|
if (targetofedge < firstbpoint)
|
|
newpair = std::make_pair(targetofedge,firstbpoint);
|
|
else
|
|
newpair = std::make_pair(firstbpoint, targetofedge);
|
|
/* pair already in the list? */
|
|
inedgelist = false;
|
|
for(edlstit2=edlst.begin(); edlstit2!=edlst.end(); edlstit2++)
|
|
inedgelist = inedgelist || ((*edlstit2) == newpair);
|
|
if (!inedgelist)
|
|
edlst.push_back(newpair);
|
|
nrofvertices = ptlst.size();
|
|
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test:*/
|
|
cout << "lresult length: " << lresult.size() << endl;
|
|
#endif /* end test */
|
|
/* put intersection points in (step C in README) */
|
|
for (lrit = lresult.begin(); lrit != lresult.end(); lrit++)
|
|
{
|
|
if(assign(pt, (*lrit).intersection_object()))
|
|
{
|
|
/* IT'S A POINT ! */
|
|
/* check whether or not pt is in the list */
|
|
inlist = false;
|
|
count = 0;
|
|
for(ptlstit=ptlst.begin(); (!inlist) && (ptlstit!=ptlst.end());
|
|
++ptlstit)
|
|
{
|
|
if ((*ptlstit)==pt)
|
|
{/* it's an old point, already in the list */
|
|
inlist = true;
|
|
pointnr = count;
|
|
}
|
|
count++;
|
|
}
|
|
if (!inlist)
|
|
{
|
|
pointnr = ptlst.size();
|
|
ptlst.push_back(pt);
|
|
}
|
|
if (!((*lrit).is_vertex_of_poly1()))
|
|
{/* do something with the one and only edge of poly1 on which
|
|
pt lies... */
|
|
if (((*lrit).segments_poly1()).size() > 1) {
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test:*/
|
|
cout << "1: geometrical error, too many segments" << endl;
|
|
#endif /* end test */
|
|
}
|
|
else {
|
|
edgetosplit = *((*lrit).segments_poly1()).begin();
|
|
ptlstit2 = ptlst.begin();
|
|
for (i=0; i<asize; i++)
|
|
{
|
|
if (edgetosplit.min() == *ptlstit2)
|
|
{
|
|
minnr = i;
|
|
}
|
|
if (edgetosplit.max() == *ptlstit2)
|
|
{
|
|
maxnr = i;
|
|
}
|
|
ptlstit2++;
|
|
}
|
|
/* add edge to the list of edges which have to be split */
|
|
added = false;
|
|
for(splitit=edgestosplitlst.begin();
|
|
( !added )&&( splitit!=edgestosplitlst.end());
|
|
splitit++ )
|
|
{
|
|
if ( ((*splitit)._endpointleft == minnr)
|
|
&&((*splitit)._endpointright == maxnr) )
|
|
{
|
|
/*1*******/
|
|
intit = (*splitit)._cutpoints.begin();
|
|
while ( (intit!= (*splitit)._cutpoints.end())
|
|
&& (compare_lexicographically_xy(
|
|
ptlst[(*intit)], ptlst[pointnr]) == SMALLER))
|
|
{
|
|
intit++;
|
|
}
|
|
(*splitit)._cutpoints.insert(intit,1,pointnr);
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << "added:" << pointnr;
|
|
cout << "to:" << minnr << "," << maxnr << endl;
|
|
#endif /* end test */
|
|
added = true;
|
|
}
|
|
}
|
|
if (!added)
|
|
{
|
|
edgetosplitel._endpointleft = minnr;
|
|
edgetosplitel._endpointright = maxnr;
|
|
edgetosplitel._cutpoints.push_back(pointnr);
|
|
edgestosplitlst.push_back(edgetosplitel);
|
|
added = true;
|
|
edgetosplitel._cutpoints.pop_back();
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << "added:" << pointnr;
|
|
cout << "to:" << minnr << "," << maxnr << endl;
|
|
#endif /* end test */
|
|
}
|
|
}
|
|
}
|
|
if (!((*lrit).is_vertex_of_poly2()))
|
|
{/* do something with the one and only edge of poly1 on which
|
|
pt lies... */
|
|
if ( ((*lrit).segments_poly2()).size() > 1) {
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test:*/
|
|
cout << "2: geometrical error, too many segments" << endl;
|
|
#endif /* end test */
|
|
}
|
|
else {
|
|
ptlstit2 = ptlst.begin();
|
|
edgetosplit = *(((*lrit).segments_poly2()).begin());
|
|
for (i=0; i< nrofvertices; i++)
|
|
{
|
|
if (edgetosplit.min() == *ptlstit2)
|
|
{
|
|
minnr = i;
|
|
}
|
|
if (edgetosplit.max() == *ptlstit2)
|
|
{
|
|
maxnr = i;
|
|
}
|
|
ptlstit2++;
|
|
}
|
|
/* add the edge to the list of edges which have to be split */
|
|
added = false;
|
|
for(splitit=edgestosplitlst.begin();
|
|
(!added) && ( splitit!=edgestosplitlst.end());
|
|
splitit++ )
|
|
{
|
|
if ( ((*splitit)._endpointleft == minnr)
|
|
&&((*splitit)._endpointright == maxnr) )
|
|
{
|
|
/*2*/
|
|
intit = (*splitit)._cutpoints.begin();
|
|
while ( (intit!= (*splitit)._cutpoints.end())
|
|
&& (compare_lexicographically_xy(
|
|
ptlst[(*intit)], ptlst[pointnr]) == SMALLER))
|
|
{
|
|
intit++;
|
|
}
|
|
(*splitit)._cutpoints.insert(intit,1,pointnr);
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << "added:" << pointnr;
|
|
cout << "to:" << minnr << "," << maxnr << endl;
|
|
#endif /* end test */
|
|
added = true;
|
|
}
|
|
}
|
|
if (!added)
|
|
{
|
|
edgetosplitel._endpointleft = minnr;
|
|
edgetosplitel._endpointright = maxnr;
|
|
edgetosplitel._cutpoints.push_back(pointnr);
|
|
edgestosplitlst.push_back(edgetosplitel);
|
|
added = true;
|
|
edgetosplitel._cutpoints.pop_back();
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << "added:" << pointnr;
|
|
cout << "to:" << minnr << "," << maxnr << endl;
|
|
#endif /* end test */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* cut some segments into pieces now: (step D in README) */
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
for(splitit=edgestosplitlst.begin();
|
|
splitit!=edgestosplitlst.end();
|
|
splitit++ )
|
|
{
|
|
cout << "edge: " << (*splitit)._endpointleft << "'"
|
|
<< (*splitit)._endpointright << endl;
|
|
cout << "its cutpoints: ";
|
|
for (intit = ((*splitit)._cutpoints).begin();
|
|
intit != ((*splitit)._cutpoints).end(); intit++)
|
|
cout << (*intit) << "," << endl;
|
|
cout << "." << endl;
|
|
}
|
|
#endif /* end test */
|
|
/* go through edgestosplitlst */
|
|
for(splitit=edgestosplitlst.begin();
|
|
splitit!=edgestosplitlst.end();
|
|
splitit++ )
|
|
{
|
|
/* for each edge (a,b,...) in that list, look for edge (a,b)
|
|
and cut it into pieces */
|
|
if ((*splitit)._endpointleft < (*splitit)._endpointright)
|
|
apair = std::make_pair((*splitit)._endpointleft,(*splitit)._endpointright);
|
|
else
|
|
apair = std::make_pair((*splitit)._endpointright,(*splitit)._endpointleft);
|
|
edlstit= edlst.begin();
|
|
while(edlstit!= edlst.end())
|
|
{
|
|
if ((*edlstit)==apair)
|
|
{
|
|
tobeerased = edlstit;
|
|
edlstit++;
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /*test */
|
|
cout << "added also:" << (*splitit)._endpointleft
|
|
<< "," << (*splitit)._endpointright << endl;
|
|
#endif /* end test */
|
|
((*splitit)._cutpoints).push_front((*splitit)._endpointleft);
|
|
((*splitit)._cutpoints).push_back((*splitit)._endpointright);
|
|
if (((*splitit)._cutpoints).size() != 0)
|
|
{
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << apair.first << "," << apair.second << "boe: "
|
|
<< ((*splitit)._cutpoints).size() << endl;
|
|
#endif /* end test */
|
|
intit = ((*splitit)._cutpoints).begin();
|
|
intit2 = --((*splitit)._cutpoints).end();
|
|
while(intit != intit2)
|
|
{
|
|
sourceofedge = *intit ;
|
|
targetofedge = *++intit ;
|
|
if (sourceofedge < targetofedge)
|
|
newpair = std::make_pair(sourceofedge,targetofedge);
|
|
else
|
|
newpair = std::make_pair(targetofedge,sourceofedge);
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test: */
|
|
cout << newpair.first << "," << newpair.second << endl;
|
|
#endif /* end test */
|
|
/* pair already in the list? */
|
|
inlist = false;
|
|
for(edlstit2=edlst.begin(); edlstit2!=edlst.end(); edlstit2++)
|
|
inlist = inlist || ((*edlstit2) == newpair);
|
|
if (!inlist)
|
|
edlst.push_back(newpair);
|
|
}
|
|
}
|
|
edlst.erase(tobeerased);
|
|
}
|
|
else
|
|
edlstit++;
|
|
}
|
|
}
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /*test */
|
|
int k=0;
|
|
for(ptlstit = ptlst.begin();ptlstit != ptlst.end(); ptlstit++)
|
|
cout << "ptlst[" << k++ << "] = " << (*ptlstit).x() << ","
|
|
<< (*ptlstit).y() << endl;
|
|
k=0;
|
|
for(edlstit = edlst.begin();edlstit != edlst.end(); edlstit++)
|
|
cout << "edlst[" << k++ << "] = " << (*edlstit).first << ","
|
|
<< (*edlstit).second << endl;
|
|
#endif /* end test */
|
|
}
|
|
|
|
|
|
|
|
|
|
std::list<Point_2<R> > get_color_information_code(
|
|
const Intersectionresult& lresult,
|
|
const Polygon& polyA,
|
|
int nr_of_poly ){
|
|
|
|
bool added;
|
|
Intersectionresult_iterator lrit;
|
|
Point pt, edgevertex1, edgevertex2;
|
|
std::list<Point> pts_on_A;
|
|
std::list<Point>::iterator end1, end2;
|
|
|
|
/* put vertices of A in */
|
|
std::copy(polyA.vertices_begin(), polyA.vertices_end(),
|
|
std::back_inserter(pts_on_A));
|
|
pts_on_A.push_back(*(polyA.vertices_begin()));
|
|
|
|
/* add intersection points */
|
|
for (lrit = lresult.begin(); lrit != lresult.end(); lrit++) {
|
|
if(assign(pt, (*lrit).intersection_object())) {
|
|
/* IT'S A POINT ! */
|
|
/* treat poly1, i.e. A */
|
|
if (( (nr_of_poly == 1) && !((*lrit).is_vertex_of_poly1() )) ||
|
|
( (nr_of_poly == 2) && !((*lrit).is_vertex_of_poly2() )) )
|
|
{
|
|
if ( (*lrit).segments_poly1().size() > 1) {
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test:*/
|
|
cout << "3: geometrical error, too many segments" << endl;
|
|
#endif /* end test */
|
|
}
|
|
else
|
|
{
|
|
if (nr_of_poly == 1)
|
|
{
|
|
edgevertex1=
|
|
(*((*lrit).segments_poly1()).begin()).source();
|
|
edgevertex2=
|
|
(*((*lrit).segments_poly1()).begin()).target();
|
|
}
|
|
else
|
|
{
|
|
edgevertex1=
|
|
(*((*lrit).segments_poly2()).begin()).source();
|
|
edgevertex2=
|
|
(*((*lrit).segments_poly2()).begin()).target();
|
|
}
|
|
/* look for vertices in the list of A and add intersection point in between */
|
|
/* if source and target are not consecutive entries in the list, then we
|
|
have to work harder: collinear_between or so */
|
|
end1 = std::find(pts_on_A.begin(),pts_on_A.end(),edgevertex1);
|
|
end2 = end1;
|
|
end2++;
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test */
|
|
cout << "end1 enzo" << endl;
|
|
std::list<Point_2<R> >::iterator pts_on_A_it;
|
|
|
|
for (pts_on_A_it =pts_on_A.begin() ;
|
|
pts_on_A_it !=pts_on_A.end();pts_on_A_it++)
|
|
cout << "(" << (*pts_on_A_it).x() << "," << (*pts_on_A_it).y() << "),";
|
|
cout << endl;
|
|
cout << "end1 =" << (*end1).x() << "," << (*end1).y() << endl;
|
|
cout << "end2 =" << (*end2).x() << "," << (*end2).y() << endl;
|
|
cout << "edgevertex1 =" << edgevertex1.x() << "," << edgevertex1.y() << endl;
|
|
cout << "edgevertex2 =" << edgevertex2.x() << "," << edgevertex2.y() << endl;
|
|
cout << "pt = " << pt.x() << "," << pt.y() << endl;
|
|
#endif /* end test */
|
|
if((*end2) == edgevertex2)
|
|
pts_on_A.insert(end2,1,pt);
|
|
else
|
|
{
|
|
added = false;
|
|
while( (!added) && ((*end1)!=edgevertex2) )
|
|
{
|
|
if (collinear_are_ordered_along_line((*end1),pt,(*end2)))
|
|
{
|
|
pts_on_A.insert(end2,1,pt);
|
|
added = true;
|
|
}
|
|
else
|
|
{
|
|
end1++;
|
|
end2++;
|
|
}
|
|
}
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test:*/
|
|
if (!added)
|
|
cout << "error: intersection point not inserted"
|
|
<< " in color list for A" << endl;
|
|
#endif /* end test */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef CGAL__INTERSECTING_POLYGONS_DEBUG_ON /* test of step PI*/
|
|
cout << "the vectors for dcel.color: " << endl;
|
|
int i=0;
|
|
for (end1 = pts_on_A.begin(); end1 != pts_on_A.end(); end1++)
|
|
cout << "A["<< i++ << "]=" << (*end1).x() << "," << (*end1).y() << endl;
|
|
#endif /* end of test*/
|
|
if(pts_on_A.size() > 0)
|
|
pts_on_A.pop_back();
|
|
return pts_on_A;
|
|
}
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#ifdef CGAL_CFG_NO_AUTOMATIC_TEMPLATE_INCLUSION
|
|
|
|
#endif
|
|
|
|
|
|
#endif // CGAL_INTERSECTING_POLYGONS_H
|