/** * compute the convex hull of a collection of Points * * @param points the points as a Vector2 array. * @param pointsLength the number of vertices of the polygon. * @param retPoly pre allocated array of floats to put the vertices * @return the number of points in the polygon 0 if no intersection */ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) { xsort(points, pointsLength); int n = pointsLength; Vector2 lUpper[n]; lUpper[0] = points[0]; lUpper[1] = points[1]; int lUpperSize = 2; for (int i = 2; i < n; i++) { lUpper[lUpperSize] = points[i]; lUpperSize++; while (lUpperSize > 2 && !ccw( lUpper[lUpperSize - 3].x, lUpper[lUpperSize - 3].y, lUpper[lUpperSize - 2].x, lUpper[lUpperSize - 2].y, lUpper[lUpperSize - 1].x, lUpper[lUpperSize - 1].y)) { // Remove the middle point of the three last lUpper[lUpperSize - 2].x = lUpper[lUpperSize - 1].x; lUpper[lUpperSize - 2].y = lUpper[lUpperSize - 1].y; lUpperSize--; } } Vector2 lLower[n]; lLower[0] = points[n - 1]; lLower[1] = points[n - 2]; int lLowerSize = 2; for (int i = n - 3; i >= 0; i--) { lLower[lLowerSize] = points[i]; lLowerSize++; while (lLowerSize > 2 && !ccw( lLower[lLowerSize - 3].x, lLower[lLowerSize - 3].y, lLower[lLowerSize - 2].x, lLower[lLowerSize - 2].y, lLower[lLowerSize - 1].x, lLower[lLowerSize - 1].y)) { // Remove the middle point of the three last lLower[lLowerSize - 2] = lLower[lLowerSize - 1]; lLowerSize--; } } // output points in CW ordering const int total = lUpperSize + lLowerSize - 2; int outIndex = total - 1; for (int i = 0; i < lUpperSize; i++) { retPoly[outIndex] = lUpper[i]; outIndex--; } for (int i = 1; i < lLowerSize - 1; i++) { retPoly[outIndex] = lLower[i]; outIndex--; } // TODO: Add test harness which verify that all the points are inside the hull. return total; }
static void vsort_xsort(struct vsort_timing *vt, size_t loops) { size_t n = loops; while (n-- > 0) { memcpy(vt->copy, vt->data, vt->len); xsort(vt->copy, vt->items, vt->isize, vsort_long_cmp); } }