bool Polygon::Contains(const float3 &worldSpacePoint, float polygonThickness) const { if (PlaneCCW().Distance(worldSpacePoint) > polygonThickness) return false; return Contains2D(MapTo2D(worldSpacePoint)); }
/** The implementation of this function is based on the paper "Kong, Everett, Toussant. The Graham Scan Triangulates Simple Polygons." See also p. 772-775 of Geometric Tools for Computer Graphics. The running time of this function is O(n^2). */ TriangleArray Polygon::Triangulate() const { assume1(IsPlanar(), this->SerializeToString()); TriangleArray t; // Handle degenerate cases. if (NumVertices() < 3) return t; if (NumVertices() == 3) { t.push_back(Triangle(Vertex(0), Vertex(1), Vertex(2))); return t; } std::vector<float2> p2d; std::vector<int> polyIndices; for(int v = 0; v < NumVertices(); ++v) { p2d.push_back(MapTo2D(v)); polyIndices.push_back(v); } // Clip ears of the polygon until it has been reduced to a triangle. int i = 0; int j = 1; int k = 2; size_t numTries = 0; // Avoid creating an infinite loop. while(p2d.size() > 3 && numTries < p2d.size()) { if (float2::OrientedCCW(p2d[i], p2d[j], p2d[k]) && IsAnEar(p2d, i, k)) { // The vertex j is an ear. Clip it off. t.push_back(Triangle(p[polyIndices[i]], p[polyIndices[j]], p[polyIndices[k]])); p2d.erase(p2d.begin() + j); polyIndices.erase(polyIndices.begin() + j); // The previous index might now have become an ear. Move back one index to see if so. if (i > 0) { i = (i + (int)p2d.size() - 1) % p2d.size(); j = (j + (int)p2d.size() - 1) % p2d.size(); k = (k + (int)p2d.size() - 1) % p2d.size(); } numTries = 0; } else { // The vertex at j is not an ear. Move to test next vertex. i = j; j = k; k = (k+1) % p2d.size(); ++numTries; } } assume3(p2d.size() == 3, (int)p2d.size(), (int)polyIndices.size(), (int)NumVertices()); if (p2d.size() > 3) // If this occurs, then the polygon is NOT counter-clockwise oriented. return t; /* { // For conveniency, create a copy that has the winding order fixed, and triangulate that instead. // (Causes a large performance hit!) Polygon p2 = *this; for(size_t i = 0; i < p2.p.size()/2; ++i) std::swap(p2.p[i], p2.p[p2.p.size()-1-i]); return p2.Triangulate(); } */ // Add the last poly. t.push_back(Triangle(p[polyIndices[0]], p[polyIndices[1]], p[polyIndices[2]])); return t; }