point_cloud_t convex_hull_monotone_chain(point_cloud_t cloud) { point_cloud_t hull = init_point_cloud(cloud.size); int j = 0; for (int k = 0; k < cloud.size; k++) { while (j >= 2 && turn_direction(hull.pc[j-2], hull.pc[j-1], cloud.pc[k]) <= 0) --j; hull.pc[j++] = cloud.pc[k]; } for (int k = cloud.size-2, t = j+1; k >= 0; --k) { while (j >= t && turn_direction(hull.pc[j-2], hull.pc[j-1], cloud.pc[k]) <= 0) --j; hull.pc[j++] = cloud.pc[k]; } hull.size = j; return hull; }
int chull_2d(const double *original_points, int npoints, double *vertices, int *nvertices) { int rval = 0; int pivot_idx; double pivot[2]; int *stack = 0; int stack_length = 0; double *points = 0; stack = (int*) malloc(npoints * sizeof(int)); points = (double*) malloc(2 * npoints * sizeof(double)); abort_if(!stack, "could not allocate stack"); abort_if(!points, "could not allocate points"); memcpy(points, original_points, 2 * npoints * sizeof(double)); // find point with lowest y-coordinate pivot_idx = 0; memcpy(pivot, points, 2 * sizeof(double)); for (int i = 0; i < npoints; i++) { double *point = &points[2*i]; if(point[1] > pivot[1]) continue; if(point[1] == pivot[1] && point[0] > pivot[0]) continue; memcpy(pivot, point, 2 * sizeof(double)); pivot_idx = i; } // remove pivot swap(points[2*(npoints-1)], points[2*pivot_idx], double); swap(points[2*(npoints-1)+1], points[2*pivot_idx+1], double); npoints--; // sort points counterclockwise qsort_r(points, npoints, 2 * sizeof(double), _qsort_cmp_angle_distance, pivot); // adds pivot and first point to the stack stack[stack_length++] = npoints; stack[stack_length++] = 0; int k = 1; while(k < npoints) { double *p0 = &points[2*stack[stack_length-2]]; double *p1 = &points[2*stack[stack_length-1]]; double *p2 = &points[2*k]; double t = turn_direction(p0, p1, p2); if(DOUBLE_leq(t, 0)) stack_length--; if(DOUBLE_geq(t, 0)) { stack[stack_length++] = k; k++; } } for(int i = 0; i < stack_length; i++) { int j = stack_length - i - 1; vertices[2*j] = points[2*stack[i]]; vertices[2*j+1] = points[2*stack[i]+1]; } *nvertices = stack_length; CLEANUP: if(points) free(points); if(stack) free(stack); return rval; }