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;
}
Ejemplo n.º 2
0
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;
}