diff options
Diffstat (limited to 'geometry.cpp')
-rw-r--r-- | geometry.cpp | 240 |
1 files changed, 17 insertions, 223 deletions
diff --git a/geometry.cpp b/geometry.cpp index e709fb8..e3adb6b 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -4,39 +4,6 @@ #include <gtk/gtk.h> -void addVertex(VERTEX_LIST *list, const Vertex *v) { - list->nVertices++; - list->vertices = (Vertex*)realloc(list->vertices, list->nVertices*sizeof(Vertex)); - list->vertices[list->nVertices-1] = *v; -} - -void insertVertex(VERTEX_LIST *list, const Vertex *v, unsigned int n) { - int i; - - if(n > list->nVertices) - n = list->nVertices; - - list->nVertices++; - list->vertices = (Vertex*)realloc(list->vertices, list->nVertices*sizeof(Vertex)); - - for(i = list->nVertices-1; i > n; i--) - list->vertices[i] = list->vertices[i-1]; - - list->vertices[n] = *v; -} - -void deleteVertex(VERTEX_LIST *list, unsigned int n) { - int i; - - list->nVertices--; - - for(i = n; i < list->nVertices; i++) - list->vertices[i] = list->vertices[i+1]; - - list->vertices = (Vertex*)realloc(list->vertices, list->nVertices*sizeof(Vertex)); -} - - int vertexOnLine(const Vertex *v, const LINE *l) { if(l->v1.getX() == l->v2.getX() && l->v1.getY() == l->v2.getY()) { if(l->v1.getX() == v->getX() && l->v1.getY() == v->getY()) return 1; @@ -70,166 +37,6 @@ int vertexInRect(const Vertex *v, const RECTANGLE *rect) { return ret; } -static int quadrant(Vertex *v) { - if(v->getX() > 0 && v->getY() >= 0) return 1; - if(v->getX() >= 0 && v->getY() < 0) return 2; - if(v->getX() < 0 && v->getY() <= 0) return 3; - if(v->getX() <= 0 && v->getY() > 0) return 4; - - return 0; -} - -gboolean vertexInPolygon(const Vertex *v, const POLYGON *p) { - int d = 0, i, li; - int q, ql, q2; - LINE d1 = {Vertex(-1, -1), Vertex(1, 1)}; - LINE d2 = {Vertex(-1, 1), Vertex(1, -1)}; - LINE l; - Vertex v2; - - - if(p->nVertices == 0) return FALSE; - - v2 = p->vertices[p->nVertices-1] - *v; - q = quadrant(&v2); - - if(q == 0) return TRUE; - - for(i = 0; i < p->nVertices; i++) { - ql = q; - - - v2 = p->vertices[i] - *v; - - if(q == 0) return TRUE; - - switch(q-ql) { - case 0: - break; - case 1: - case -3: - d++; - break; - case 3: - case -1: - d--; - break; - default: - l.v1 = p->vertices[(i>0)?i-1:p->nVertices-1] - *v; - l.v2 = v2; - - if(q == 1 || q == 3) { - if(!(lineIntersection(&l, &d2, &v2) & INTERSECTION_LINE)) return FALSE; - - q2 = quadrant(&v2); - if(q2 == 0) return TRUE; - - if((q == 1 && q2 == 2) || (q == 3 && q2 == 4)) d -= 2; - else d += 2; - } - else { - if(!(lineIntersection(&l, &d1, &v2) & INTERSECTION_LINE)) return FALSE; - - q2 = quadrant(&v2); - if(q2 == 0) return TRUE; - - if((q == 2 && q2 == 3) || (q == 4 && q2 == 1)) d -= 2; - else d += 2; - } - } - } - - return (d == 0) ? FALSE : TRUE; -} - -double polygonPerimeter(const POLYGON *p) { - int i; - double d = 0.0; - - for(i = 0; i < p->nVertices; i++) - d += p->vertices[i].distance(p->vertices[(i+1)%p->nVertices]); - - return d; -} - -double polygonArea(const POLYGON *p) { - int i; - double d = 0.0; - - for(i = 0; i < p->nVertices; i++) - d += (p->vertices[(i+1)%p->nVertices].getX()+p->vertices[i].getX())*(p->vertices[(i+1)%p->nVertices].getY()-p->vertices[i].getY()); - - return fabs(d/2); -} - -int lineIntersection(const LINE *la, const LINE *lb, Vertex *v) { - double xa1 = la->v1.getX(), ya1 = la->v1.getY(); - double xa2 = la->v2.getX(), ya2 = la->v2.getY(); - double xb1 = lb->v1.getX(), yb1 = lb->v1.getY(); - double xb2 = lb->v2.getX(), yb2 = lb->v2.getY(); - double temp; - int switched = 0; - Vertex v2; - - - if(v == NULL) v = &v2; - - if(xa1 == xa2 && ya1 == ya2) return INTERSECTION_ERROR; - if(xb1 == xb2 && yb1 == yb2) return INTERSECTION_ERROR; - - if(xa1 == xa2 || xb1 == xb2) { - temp = xa1; xa1 = ya1; ya1 = temp; - temp = xa2; xa2 = ya2; ya2 = temp; - temp = xb1; xb1 = yb1; yb1 = temp; - temp = xb2; xb2 = yb2; yb2 = temp; - - switched = 1; - } - - if(xa1 == xa2 && xb1 == xb2) - return (xa1 == xb1) ? INTERSECTION_IDENTICAL : INTERSECTION_NONE; - - if(xa1 == xa2) { - v->setX(xa1); - v->setY(yb1); - } - else if(xb1 == xb2) { - v->setX(xb1); - v->setY(ya1); - } - else { - double ma = (ya2-ya1)/(xa2-xa1); - double mb = (yb2-yb1)/(xb2-xb1); - double ba = ya1 - ma*xa1; - double bb = yb1 - mb*xb1; - - if(ma == mb) return (ba == bb) ? INTERSECTION_IDENTICAL : INTERSECTION_NONE; - - v->setX((bb-ba)/(ma-mb)); - v->setY(ma*v->getX() + ba); - } - - if(switched) { - temp = v->getX(); v->setX(v->getY()); v->setY(temp); - - //switch back everything for segment tests - temp = xa1; xa1 = ya1; ya1 = temp; - temp = xa2; xa2 = ya2; ya2 = temp; - temp = xb1; xb1 = yb1; yb1 = temp; - temp = xb2; xb2 = yb2; yb2 = temp; - } - - if(v->getX() < MIN(xa1,xa2) || v->getX() > MAX(xa1, xa2) || v->getY() < MIN(ya1,ya2) || v->getY() > MAX(ya1, ya2)) { - if(v->getX() < MIN(xb1,xb2) || v->getX() > MAX(xb1, xb2) || v->getY() < MIN(yb1,yb2) || v->getY() > MAX(yb1, yb2)) - return INTERSECTION_LINE_LINE; - else - return INTERSECTION_LINE_SEGMENT; - } - else if(v->getX() < MIN(xb1,xb2) || v->getX() > MAX(xb1, xb2) || v->getY() < MIN(yb1,yb2) || v->getY() > MAX(yb1, yb2)) - return INTERSECTION_SEGMENT_LINE; - else - return INTERSECTION_SEGMENT_SEGMENT; -} int lineRectIntersection(const LINE *l, const RECTANGLE *rect, int edge, Vertex *v) { const double minX = rect->x, maxX = rect->x+rect->width; @@ -262,21 +69,6 @@ int lineRectIntersections(const LINE *line, const RECTANGLE *rect, int edge, Ver return ret; } -gboolean linePolygonIntersection(const LINE *l, const POLYGON *p) { - int i; - LINE line; - - for(i = 0; i < p->nVertices; i++) { - line.v1 = p->vertices[i]; - line.v2 = p->vertices[(i+1)%p->nVertices]; - - if(lineIntersection(l, &line, NULL) == INTERSECTION_SEGMENT_SEGMENT) - return TRUE; - } - - return FALSE; -} - static void edgeVertex(Vertex *v, int edge, const RECTANGLE *rect) { if(edge == EDGE_NONE) @@ -306,7 +98,7 @@ static int simplifyVertex(Vertex *v, const Vertex *to, const RECTANGLE *rect) { -static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGLE *rect, int last, POLYGON *out) { +static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGLE *rect, int last, Polygon *out) { const LINE d1 = {Vertex(rect->x, rect->y), Vertex(rect->x+rect->width, rect->y+rect->height)}; const LINE d2 = {Vertex(rect->x, rect->y+rect->height), Vertex(rect->x+rect->width, rect->y)}; @@ -317,7 +109,7 @@ static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGL v = *v1; if((edge1 = simplifyVertex(&v, v2, rect)) != EDGE_NONE) - addVertex(out, &v); + out->push_back(v); v = *v2; edge2 = simplifyVertex(&v, v1, rect); @@ -325,33 +117,35 @@ static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGL if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) { if(lineIntersection(&l, &d1, &vi) == INTERSECTION_SEGMENT_LINE) { edgeVertex(&vi, 0, rect); - addVertex(out, &vi); + out->push_back(vi); } else if(lineIntersection(&l, &d2, &vi) == INTERSECTION_SEGMENT_LINE) { edgeVertex(&vi, 0, rect); - addVertex(out, &vi); + out->push_back(vi); } } if(!last) - addVertex(out, &v); + out->push_back(v); } -void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out) { +void simplifyPolygon(const Polygon *in, const RECTANGLE *rect, Polygon *out) { Vertex v; - int i; - if(in->nVertices == 0) return; - else if(in->nVertices == 1) { - addVertex(out, &in->vertices[0]); + if(in->empty()) return; + else if(in->size() == 1) { + out->push_back(in->front()); return; } - v = in->vertices[0]; - simplifyVertex(&v, &in->vertices[in->nVertices-1], rect); - addVertex(out, &v); + v = in->front(); + simplifyVertex(&v, &in->back(), rect); + out->push_back(v); - for(i = 0; i < in->nVertices; i++) { - addSimplifiedLine(&in->vertices[i], &in->vertices[(i+1)%in->nVertices], rect, (i == in->nVertices-1), out); + for(Polygon::const_iterator it = in->begin(); it != in->end(); it++) { + Polygon::const_iterator it2 = it+1; + if(it2 == in->end()) it2 = in->begin(); + + addSimplifiedLine(&*it, &*it2, rect, (it2 == in->begin()), out); } } |