//Realiza el algoritmo de Graham de las 3 monedas para hallar el Convex Hull S de una lista de Puntos Q.
//Devuelve una Pila con el resultado clockwise.
void grahamScan(std::list<Point2D> & Q, std::stack<Point2D> & S){
  minimal = encontrarMinimal(Q);                            //Encuentra el minimal izquierda abajo
 // std::cout<<"Minimal: "; minimal.print();
  
  borrarMinimal(Q, minimal);                                //Borra el minimal de la cola 

  Q.sort(comparePoint2DPolar);                              //Ordena en forma polar
  std::cout<<"Lista ordenada\n"; printList(Q);
  
  eliminarColineales(Q);                                    //Hace limpieza de los puntos colineales, dejando el mas lejano
  std::cout<<"Lista ordenada\n"; printList(Q);
  
  
  //Ubica las 3 primeras monedas
  S.push(minimal);                                          //Agrega el primero que es el minimal
  
  //Agrega la segunda y tercera
  std::list<Point2D>::iterator it = Q.begin();              //Iterador para recorrer la Q
  for(unsigned int i = 0; i < 2 and it != Q.end(); i++, it++){
    S.push(*it);
  }
  
  //tamanio de Q
  unsigned int n = Q.size();

  //Loop de Graham Scan
  for(unsigned int i = 2; i < n and it != Q.end(); i++, it++){
    Point2D ntt = nextToTop(S);
    Point2D nt = top(S);
    Point2D p = *it;
    while(!leftTurn(ntt, nt, p) and (S.size() > 1)){        //Si no froman un giro a la izquierda y queda mas de un elemento en S
      // printStack(S);
      S.pop();                                              //Saco el tope de S
      ntt = nextToTop(S);                                   //Renuevo los valores y vuelvo a probar
      nt = top(S);
    }
    S.push(p);                                              //Agrego el elemento a S
  }
}
// Prints convex hull of a set of n points.
void convexHull() {
    // Find the bottommost point
    int Min = 0;
    for (int i = 1; i < N; i++) {
        // Pick the bottom-most or chose the left most point in case of tie
        if (cmpYX(points[i], points[Min]))
            Min = i;
    }
    
    // Place the bottom-most point at first position
    swap(points[0], points[Min]);
    
    // Sort N - 1 points with respect to the first point.  A point p1 comes
    // before p2 in sorted ouput if p2 has larger polar angle (in
    // counterclockwise direction) than p1
    p0 = points[0];
    qsort(&points[1], N - 1, sizeof(PointI), compare);
    
    // Create an empty stack and push first three points to it.
    stack<PointI> S;
    S.push(points[0]);
    S.push(points[1]);
    S.push(points[2]);
    
    // Process remaining n-3 points
    for (int i = 3; i < N; i++) {
        // Keep removing top while the angle formed by points next-to-top,
        // top, and points[i] makes a non-left turn
        while (getSide(nextToTop(S), points[i], S.top()) != -1)
            S.pop();
        S.push(points[i]);
    }
    
    // Now stack has the output points, print contents of stack
    while (!S.empty()) {
        PointI p = S.top();
        cout << p << endl;
        S.pop();
    }
}
예제 #3
0
///////////////////////////////////////////////////////////////////////////////
// Prints convex hull of a set of n points.
void computeConvexHull(const std::vector<Point*>& pointArray,
                       std::vector<Point*>&       curve,
                       const bool                 bVerbose)
{
    if(bVerbose)
    {
        fprintf(stdout, "computeConvexHull: nbPts: %ld\n", pointArray.size());
    }
    curve.resize(0);
    if(pointArray.size() < 3)
    {
        return;
    }

    std::vector<Point*> points;
    points.resize(pointArray.size());
    for(size_t i=0; i<points.size(); i++)
    {
        points[i] = pointArray[i];
    }
    const size_t n = points.size();
    // Find the bottommost point
    size_t min = 0;
    Coord  ymin = points[min]->y();
    Coord  xmin = points[min]->x();

    for(size_t i=1; i<n; i++)
    {
        const Coord x = points[i]->x();
        const Coord y = points[i]->y();
        // Pick the bottom-most or chose the left most point in case of tie
        if ((y<ymin) || (isEqual(y,ymin) && x<xmin))
        {
            min  = i;
            xmin = x;
            ymin = y;
        }
    }
    // Place the bottom-most point at first position
    //std::swap(points[0], points[min]);
    if(min != 0)
    {
        Point* p    = points[0];
        points[0]   = points[min];
        points[min] = p;
    }
    if(0 && bVerbose)
    {
        fprintf(stdout, "pivot point: %s, at pos:%ld\n", points[0]->toString().c_str(), min);
    }
    // Sort n-1 points with respect to the first point. A point p1 comes
    // before p2 in sorted ouput if p2 has larger polar angle (in
    // counterclockwise direction) than p1
    // qsort(&points[1], n-1, sizeof(Point), compare);
    ComparePoints<Point*> compareFunction(points[0]);

    // Note: for some unknown reason, the std::sort does not work on apple c++ compiler.
    //       the swap of pointers is not working properly!!!
    // std::sort(points.begin()+1, points.end(), compareFunction);
    // BubbleSort(points, 1, compareFunction);
    QuickSort(points, 1, points.size()-1, compareFunction);

    // print the point array
    if(0 && bVerbose)
    {
        fprintf(stdout, "** List of sorted points\n");
        for(size_t i=0; i<n; i++)
        {
            if(points[i])
            {
                fprintf(stdout, "[%03ld]: %s \n", i, points[i]->toString().c_str());
            }
            else
            {
                fprintf(stdout, "[%ld] null\n", i);
            }
        }
        fprintf(stdout, "\n\n");
    }

    // Create an empty stack and push first three points to it.
    std::stack<Point*> stack;
    
    stack.push(points[0]);
    stack.push(points[1]);
    stack.push(points[2]);
    
    // Process remaining n-3 points
    for(size_t i=3; i<n; i++)
    {
        // Keep removing top while the angle formed by points next-to-top,
        // top, and points[i] makes a non-left turn
        while(stack.size()>1 &&
              ComputePointOrientation(nextToTop(stack), stack.top(), points[i]) != PointOrientationConterClockWise)
        {
            stack.pop();
        }
        stack.push(points[i]);
    }
    // collect the curve
    curve.resize(0);
    while (!stack.empty())
    {
        curve.push_back(stack.top());
        stack.pop();
    }
}