// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets. // My implementation performs an in place reduction using the result array as scratch space. int cpConvexHull(int count, cpVect *verts, cpVect *result, int *first, cpFloat tol) { if(result){ // Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer. memcpy(result, verts, count*sizeof(cpVect)); } else { // If a result array was not specified, reduce the input instead. result = verts; } // Degenerate case, all poins are the same. int start, end; cpLoopIndexes(verts, count, &start, &end); if(start == end){ if(first) (*first) = 0; return 1; } SWAP(result[0], result[start]); SWAP(result[1], result[end == 0 ? start : end]); cpVect a = result[0]; cpVect b = result[1]; if(first) (*first) = start; int resultCount = QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1; cpAssertSoft(cpPolyValidate(result, resultCount), "Internal error: cpConvexHull() and cpPolyValidate() did not agree." "Please report this error with as much info as you can."); return resultCount; }
// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets. // My implementation performs an in place reduction using the result array as scratch space. int cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol) { if(verts != result){ // Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer. memcpy(result, verts, count*sizeof(cpVect)); } // Degenerate case, all points are the same. int start, end; cpLoopIndexes(verts, count, &start, &end); if(start == end){ if(first) (*first) = 0; return 1; } SWAP(result[0], result[start]); SWAP(result[1], result[end == 0 ? start : end]); cpVect a = result[0]; cpVect b = result[1]; if(first) (*first) = start; return QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1; }
static int QHullReduce(cpFloat tol, cpVect *verts, int count, cpVect a, cpVect pivot, cpVect b, cpVect *result) { if(count < 0){ return 0; } else if(count == 0) { result[0] = pivot; return 1; } else { int left_count = QHullPartition(verts, count, a, pivot, tol); int index = QHullReduce(tol, verts + 1, left_count - 1, a, verts[0], pivot, result); result[index++] = pivot; int right_count = QHullPartition(verts + left_count, count - left_count, pivot, b, tol); return index + QHullReduce(tol, verts + left_count + 1, right_count - 1, pivot, verts[left_count], b, result + index); } }