#include #include "lwPolygon.h" #include "BitArray.h" const float epsilon = 0.001F; // error margin void lwPolygon::flip(void) { vvertices flipvertices; flipvertices.reserve(vertices.size()); vvertices::reverse_iterator i = vertices.rbegin(); vvertices::reverse_iterator end = vertices.rend(); for(; i!=end ; ++i) flipvertices.push_back(*i); vertices = flipvertices; } lwPolygon *lwPolygon::makeTriangle(long ia, long ib, long ic) { lwPolygon *triangle = new lwPolygon(*this); triangle->vertices.push_back(new lwVertex(*vertices[ia])); triangle->vertices.push_back(new lwVertex(*vertices[ib])); triangle->vertices.push_back(new lwVertex(*vertices[ic])); return triangle; } Vector3 &lwPolygon::calculateNormal() { if ( vertices.size() < 3 ) return normal; Point3 *p1 = vertices[ 0 ]->point; Point3 *p2 = vertices[ 1 ]->point; Point3 *pn = vertices[vertices.size() - 1]->point; normal = (*p2 - *p1).crossProduct(*pn - *p1); normal.normalise(); return normal; } vpolygons lwPolygon::triangulate() { vpolygons triangles; BitArray active(vertices.size(), true); // vertex part of polygon ? long vertexCount = vertices.size(); long triangleCount = 0; long start = 0; long p1 = 0; long p2 = 1; long m1 = vertexCount - 1; long m2 = vertexCount - 2; bool lastPositive = false; for (;;) { if (p2 == m2) { triangles.push_back(makeTriangle(m1, p1, p2)); break; } const Point3 vp1 = *vertices[p1]->point; const Point3 vp2 = *vertices[p2]->point; const Point3 vm1 = *vertices[m1]->point; const Point3 vm2 = *vertices[m2]->point; bool positive = false; bool negative = false; Vector3 n1 = normal.crossProduct((vm1 - vp2).normalise()); if (n1.dotProduct(vp1 - vp2) > epsilon) { positive = true; Vector3 n2 = normal.crossProduct((vp1 - vm1).normalise()); Vector3 n3 = normal.crossProduct((vp2 - vp1).normalise()); for (long a = 0; a < vertexCount; a++) { if ((a != p1) && (a != p2) && (a != m1) && active.bitSet(a)) { const Point3 v = *vertices[a]->point; if (n1.dotProduct((v - vp2).normalise()) > -epsilon && n2.dotProduct((v - vm1).normalise()) > -epsilon && n3.dotProduct((v - vp1).normalise()) > -epsilon) { positive = false; break; } } } } n1 = normal.crossProduct((vm2 - vp1).normalise()); if (n1.dotProduct(vm1 - vp1) > epsilon) { negative = true; Vector3 n2 = normal.crossProduct((vm1 - vm2).normalise()); Vector3 n3 = normal.crossProduct((vp1 - vm1).normalise()); for (long a = 0; a < vertexCount; a++) { if ((a != m1) && (a != m2) && (a != p1) && active.bitSet(a)) { const Point3 v = *vertices[a]->point; if (n1.dotProduct((v - vp1).normalise()) > -epsilon && n2.dotProduct((v - vm2).normalise()) > -epsilon && n3.dotProduct((v - vm1).normalise()) > -epsilon) { negative = false; break; } } } } if ((positive) && (negative)) { float pd = (vp2 - vm1).normalise().dotProduct((vm2 - vm1).normalise()); float md = (vm2 - vp1).normalise().dotProduct((vp2 - vp1).normalise()); if (fabs(pd - md) < epsilon) { if (lastPositive) positive = false; else negative = false; } else { if (pd < md) negative = false; else positive = false; } } if (positive) { active.clearBit(p1); triangles.push_back(makeTriangle(m1, p1, p2)); p1 = active.getNextSet(p1); p2 = active.getNextSet(p2); lastPositive = true; start = -1; } else if (negative) { active.clearBit(m1); triangles.push_back(makeTriangle(m2, m1, p1)); m1 = active.getPreviousSet(m1); m2 = active.getPreviousSet(m2); lastPositive = false; start = -1; } else { if (start == -1) start = p2; else if (p2 == start) break; m2 = m1; m1 = p1; p1 = p2; p2 = active.getNextSet(p2); } } return triangles; }