80 lines
2.1 KiB
C++
80 lines
2.1 KiB
C++
#include "geometry.h"
|
|
|
|
|
|
static void edgeVertex(Vertex *v, int edge, const Rectangle *rect) {
|
|
if(edge == EDGE_NONE)
|
|
edge = rect->edges(*v);
|
|
|
|
if(edge & EDGE_LEFT) v->setX(rect->getVertex1().getX());
|
|
else if(edge & EDGE_RIGHT) v->setX(rect->getVertex2().getX());
|
|
|
|
if(edge & EDGE_TOP) v->setY(rect->getVertex1().getY());
|
|
else if(edge & EDGE_BOTTOM) v->setY(rect->getVertex2().getY());
|
|
}
|
|
|
|
static int simplifyVertex(Vertex *v, const Vertex *to, const Rectangle *rect) {
|
|
Line l(*v, *to);
|
|
int edge, edge2;
|
|
|
|
|
|
edge = rect->edges(*v);
|
|
if(edge == EDGE_NONE) return EDGE_NONE;
|
|
|
|
edge2 = rect->intersects(l, v, edge);
|
|
if(edge2 != EDGE_NONE) return edge2;
|
|
|
|
edgeVertex(v, edge, rect);
|
|
return edge;
|
|
}
|
|
|
|
static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const Rectangle *rect, int last, Polygon *out) {
|
|
const Line d1(rect->getVertex1(), rect->getVertex2());
|
|
const Line d2(rect->getVertex1().getX(), rect->getVertex2().getY(), rect->getVertex2().getX(), rect->getVertex1().getY());
|
|
|
|
Line l(*v1, *v2);
|
|
Vertex v, vi;
|
|
int edge1, edge2;
|
|
|
|
|
|
v = *v1;
|
|
if((edge1 = simplifyVertex(&v, v2, rect)) != EDGE_NONE)
|
|
out->push_back(v);
|
|
|
|
v = *v2;
|
|
edge2 = simplifyVertex(&v, v1, rect);
|
|
|
|
if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) {
|
|
if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) {
|
|
edgeVertex(&vi, 0, rect);
|
|
out->push_back(vi);
|
|
}
|
|
else if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) {
|
|
edgeVertex(&vi, 0, rect);
|
|
out->push_back(vi);
|
|
}
|
|
}
|
|
|
|
if(!last)
|
|
out->push_back(v);
|
|
}
|
|
|
|
void simplifyPolygon(const Polygon *in, const Rectangle *rect, Polygon *out) {
|
|
Vertex v;
|
|
|
|
if(in->empty()) return;
|
|
else if(in->size() == 1) {
|
|
out->push_back(in->front());
|
|
return;
|
|
}
|
|
|
|
v = in->front();
|
|
simplifyVertex(&v, &in->back(), rect);
|
|
out->push_back(v);
|
|
|
|
for(Polygon::const_iterator v2 = in->begin(); v2 != in->end(); v2++) {
|
|
Polygon::const_iterator v3 = v2+1;
|
|
if(v3 == in->end()) v3 = in->begin();
|
|
|
|
addSimplifiedLine(&*v2, &*v3, rect, (v3 == in->begin()), out);
|
|
}
|
|
}
|