zoomedit: simplifyPolygon neu geschrieben
This commit is contained in:
parent
d21f73c498
commit
61145c32c9
1 changed files with 71 additions and 58 deletions
129
geometry.c
129
geometry.c
|
@ -288,68 +288,81 @@ gboolean linePolygonIntersection(const LINE *l, const POLYGON *p) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void edgeVertex(VERTEX *v, int edge, const RECTANGLE *rect) {
|
||||||
|
if(edge == EDGE_NONE)
|
||||||
|
edge = vertexInRect(v, rect);
|
||||||
|
|
||||||
|
if(edge & EDGE_LEFT) v->x = rect->x;
|
||||||
|
else if(edge & EDGE_RIGHT) v->x = rect->x+rect->width;
|
||||||
|
|
||||||
|
if(edge & EDGE_TOP) v->y = rect->y;
|
||||||
|
else if(edge & EDGE_BOTTOM) v->y = rect->y+rect->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int simplifyVertex(VERTEX *v, const VERTEX *to, const RECTANGLE *rect) {
|
||||||
|
LINE l = {*v, *to};
|
||||||
|
int edge, edge2;
|
||||||
|
|
||||||
|
|
||||||
|
edge = vertexInRect(v, rect);
|
||||||
|
if(edge == EDGE_NONE) return EDGE_NONE;
|
||||||
|
|
||||||
|
edge2 = lineRectIntersection(&l, rect, edge, v);
|
||||||
|
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->x, rect->y}, {rect->x+rect->width, rect->y+rect->height}};
|
||||||
|
const LINE d2 = {{rect->x, rect->y+rect->height}, {rect->x+rect->width, rect->y}};
|
||||||
|
|
||||||
|
LINE l = {*v1, *v2};
|
||||||
|
VERTEX v, vi;
|
||||||
|
int edge1, edge2;
|
||||||
|
|
||||||
|
|
||||||
|
v = *v1;
|
||||||
|
if((edge1 = simplifyVertex(&v, v2, rect)) != EDGE_NONE)
|
||||||
|
addVertex(out, &v);
|
||||||
|
|
||||||
|
v = *v2;
|
||||||
|
edge2 = simplifyVertex(&v, v1, rect);
|
||||||
|
|
||||||
|
if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) {
|
||||||
|
if(lineIntersection(&l, &d1, &vi) == INTERSECTION_SEGMENT_LINE) {
|
||||||
|
edgeVertex(&vi, 0, rect);
|
||||||
|
addVertex(out, &vi);
|
||||||
|
}
|
||||||
|
else if(lineIntersection(&l, &d2, &vi) == INTERSECTION_SEGMENT_LINE) {
|
||||||
|
edgeVertex(&vi, 0, rect);
|
||||||
|
addVertex(out, &vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!last)
|
||||||
|
addVertex(out, &v);
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out) {
|
void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out) {
|
||||||
int i, j;
|
VERTEX v;
|
||||||
int a;
|
int i;
|
||||||
int lastVertex, thisVertex;
|
|
||||||
VERTEX v, v2;
|
|
||||||
VERTEX_LIST vl = {0, NULL};
|
|
||||||
LINE line;
|
|
||||||
LINE d1 = {{rect->x, rect->y}, {rect->x+rect->width, rect->y+rect->height}};
|
|
||||||
LINE d2 = {{rect->x, rect->y+rect->height}, {rect->x+rect->width, rect->y}};
|
|
||||||
|
|
||||||
|
if(in->nVertices == 0) return;
|
||||||
|
else if(in->nVertices == 1) {
|
||||||
|
addVertex(out, &in->vertices[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
thisVertex = vertexInRect(&in->vertices[0], rect);
|
v = in->vertices[0];
|
||||||
|
simplifyVertex(&v, &in->vertices[in->nVertices-1], rect);
|
||||||
|
addVertex(out, &v);
|
||||||
|
|
||||||
for(i = 0; i < in->nVertices; i++) {
|
for(i = 0; i < in->nVertices; i++) {
|
||||||
line.v1 = in->vertices[i];
|
addSimplifiedLine(&in->vertices[i], &in->vertices[(i+1)%in->nVertices], rect, (i == in->nVertices-1), out);
|
||||||
line.v2 = in->vertices[(i+1)%in->nVertices];
|
|
||||||
|
|
||||||
lastVertex = thisVertex;
|
|
||||||
thisVertex = vertexInRect(&line.v2, rect);
|
|
||||||
|
|
||||||
if(thisVertex == EDGE_NONE) {
|
|
||||||
if(lastVertex != EDGE_NONE && lineRectIntersection(&line, rect, lastVertex, &v))
|
|
||||||
addVertex(&vl, &v);
|
|
||||||
|
|
||||||
addVertex(&vl, &line.v2);
|
|
||||||
}
|
|
||||||
else if(lastVertex == EDGE_NONE) {
|
|
||||||
if(lineRectIntersection(&line, rect, thisVertex, &v))
|
|
||||||
addVertex(&vl, &v);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
a = lineRectIntersections(&line, rect, lastVertex, &v, &v2);
|
|
||||||
|
|
||||||
if((a & lastVertex) && (a & thisVertex)) {
|
|
||||||
addVertex(&vl, &v);
|
|
||||||
addVertex(&vl, &v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lineIntersection(&line, &d1, &v) == INTERSECTION_SEGMENT_LINE) {
|
|
||||||
if(v.x <= rect->x) addVertex(&vl, &d1.v1);
|
|
||||||
else addVertex(&vl, &d1.v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lineIntersection(&line, &d2, &v) == INTERSECTION_SEGMENT_LINE) {
|
|
||||||
if(v.x <= rect->x) addVertex(&vl, &d2.v1);
|
|
||||||
else addVertex(&vl, &d2.v2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while(vl.nVertices > 0) {
|
|
||||||
a = 0;
|
|
||||||
|
|
||||||
for(j = 0; j < vl.nVertices; j++) {
|
|
||||||
if(vertexDistanceSquare(&line.v1, &vl.vertices[j]) < vertexDistanceSquare(&line.v1, &vl.vertices[a]))
|
|
||||||
a = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(out->nVertices == 0 || out->vertices[out->nVertices-1].x != vl.vertices[a].x ||
|
|
||||||
out->vertices[out->nVertices-1].y != vl.vertices[a].y)
|
|
||||||
addVertex(out, &vl.vertices[a]);
|
|
||||||
|
|
||||||
deleteVertex(&vl, a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue