/*********************************************
*
* Cedric Pradalier
* DEA 2000/2001
* INRIA Rhones Alpes
* http://cedric.pradalier.free.fr/index.html
* mail : http://cedric.pradalier.free.fr/mail.html
*
* *******************************************/
#include "Polygon.h"
#include "Segment.h"
#include "math.h"
#include <iostream.h>
#define EQ(X,Y) (fabs(X-Y)<1e-3)
Polygon::~Polygon()
{
//printf("*");
gpc_free_polygon(poly);
delete poly;
}
void Polygon::Read(FILE * fp)
{
gpc_free_polygon(poly);
delete poly;
poly = new gpc_polygon;
gpc_init_polygon(poly);
gpc_read_polygon(fp,true,poly);
}
Polygon * Polygon::Union(Polygon * p)
{
Polygon * r = new Polygon();
gpc_polygon_clip(GPC_UNION,poly,p->poly,r->poly);
return r;
}
Polygon * Polygon::Intersection(Polygon * p)
{
Polygon * r = new Polygon();
gpc_polygon_clip(GPC_INT,poly,p->poly,r->poly);
return r;
}
Polygon * Polygon::Minus(Polygon * p)
{
Polygon * r = new Polygon();
gpc_polygon_clip(GPC_DIFF,poly,p->poly,r->poly);
return r;
}
Polygon * Polygon::Xor(Polygon * p)
{
Polygon * r = new Polygon();
gpc_polygon_clip(GPC_XOR,poly,p->poly,r->poly);
return r;
}
void Polygon::getConnexList(Vector * list)
{
int i;
Polygon * P;
gpc_polygon * gpc_P;
if (numPartConnex()==1)
{
list->addElement(new Polygon(this));
return;
}
for(i=0;i<poly->num_contours;i++)
{
if (!(poly->hole[i]))
{
gpc_P = new gpc_polygon;
gpc_init_polygon(gpc_P);
gpc_add_contour(gpc_P,&(poly->contour[i]),poly->hole[i]);
P = new Polygon(gpc_P);
list->addElement(Intersection(P));
delete P;
}
}
}
void Polygon::getEdges(Vector * list)
{
int i,j;
for(i=0;i<poly->num_contours;i++)
{
int n = poly->contour[i].num_vertices;
for(j=0;j<n-1;j++)
list->addElement(new Segment(
Vector2(poly->contour[i].vertex[j].x,
poly->contour[i].vertex[j].y),
Vector2(poly->contour[i].vertex[j+1].x,
poly->contour[i].vertex[j+1].y)));
list->addElement(new Segment(
Vector2(poly->contour[i].vertex[n-1].x,
poly->contour[i].vertex[n-1].y),
Vector2(poly->contour[i].vertex[0].x,
poly->contour[i].vertex[0].y)));
}
list->trimToSize();
}
bool Polygon::isAVertex(double x,double y)
{
int i,j;
for(i=0;i<poly->num_contours;i++)
for(j=0;j<poly->contour[i].num_vertices;j++)
if ((fabs(poly->contour[i].vertex[j].x - x) < 1e-6) &&
(fabs(poly->contour[i].vertex[j].y - y) < 1e-6))
// if ((poly->contour[i].vertex[j].x == x) &&
// (poly->contour[i].vertex[j].y == y))
return true;
return false;
}
void Polygon::getCenter(double * x, double * y)
{
gpc_vertex pt;
gpc_get_center(poly,&pt);
*x = pt.x;
*y = pt.y;
}
void Polygon::getBoundingCircle(double * x, double * y,double * r)
{
gpc_vertex pt;
gpc_find_bounding_circle_radius(poly,&pt,r);
*x = pt.x;
*y = pt.y;
}
double Polygon::getArea()
{
return gpc_poly_area(poly);
}
int Polygon::numPartConnex()
{
int i,n;
n = 0;
for (i=0;i<poly->num_contours;i++)
if (poly->hole[i] == 0) n+=1;
return n;
}
void Polygon::cut()
{
gpc_polygon * result = new gpc_polygon;
gpc_cut_polygon(poly,result);
gpc_free_polygon(poly);
delete poly;
poly = result;
}
// #define DEBUG
Polygon * Polygon::computeVisibility(double x,double y)
{
Vector edges,obsEdges;
double triangle[6];
double quadri[8];
Polygon *visibility = new Polygon();
Polygon *T,*tmp;
Vector2 balise(x,y);
int i,j;
double mu;
triangle[0] = x;
triangle[1] = y;
getEdges(&edges);
for (i=0;i<edges.size();i++)
{
Segment * s = (Segment*)(edges.elementAt(i));
triangle[2]= s->A.x;
triangle[3]= s->A.y;
triangle[4]= s->B.x;
triangle[5]= s->B.y;
T = new Polygon(triangle,6);
Polygon * V = Intersection(T);// workspace inter T
if (V->numPartConnex() > 1) {
delete T;delete V;continue;
}
if (!V->isAVertex(balise.x,balise.y)) {
delete T;delete V;continue;
}
Polygon * O = T->Minus(V);
O->getEdges(&obsEdges);
delete T;
if (obsEdges.size() == 0)
{
tmp = visibility;
visibility = visibility->Union(V);
delete tmp;
delete V;
continue;
}
for (j=0;j<obsEdges.size();j++)
{
Segment * o = (Segment*)(obsEdges.elementAt(j));
quadri[0]=o->A.x; quadri[1]=o->A.y;
quadri[2]=o->B.x; quadri[3]=o->B.y;
Vector2 dirA = (o->A-balise);
if (EQ(dirA.norme(),0)) continue;
double lambdaA=s->intersect(balise,dirA,&mu);
if (lambdaA < 0)
{
if (EQ(mu,1))
{
quadri[6]=s->B.x;
quadri[7]=s->B.y;
}
if EQ(mu,0)
{
quadri[6]=s->A.x;
quadri[7]=s->A.y;
}
}
else
{
quadri[6]=balise.x+lambdaA*dirA.x;
quadri[7]=balise.y+lambdaA*dirA.y;
}
Vector2 dirB = (o->B-balise);
if (EQ(dirB.norme(),0)) continue;
double lambdaB=s->intersect(balise,dirB,&mu);
if (lambdaB < 0)
{
if (EQ(mu,1))
{
quadri[4]=s->B.x;
quadri[5]=s->B.y;
}
if EQ(mu,0)
{
quadri[4]=s->A.x;
quadri[5]=s->A.y;
}
}
else
{
quadri[4]=balise.x+lambdaB*dirB.x;
quadri[5]=balise.y+lambdaB*dirB.y;
}
Polygon * suppr = new Polygon(quadri,8);
T = V->Minus(suppr);
delete suppr;
delete V;
V = T;
}
obsEdges.deleteAll();
delete O;
T = visibility->Union(V);
delete V;
delete visibility;
visibility = T;
}
edges.deleteAll();
return visibility;
}
void Polygon::collectVtkPoints(VtkPoints & points,VtkPolygons & polygons)
{
int i,j;
VtkPoint3D P;
P.z = 0;
P.c = 0;
for (i=0;i<poly->num_contours;i++)
{
VtkPolygon pol;
for (j=0;j<poly->contour[i].num_vertices;j++)
{
P.x = poly->contour[i].vertex[j].x;
P.y = poly->contour[i].vertex[j].y;
pol.push_back(points.size());
points.push_back(P);
}
polygons.push_back(pol);
}
}