Chain Hull

Computational Geometry 2012. 9. 16. 19:28

참고: http://cm.bell-labs.com/who/clarkson/2dch.c에 구현된 알고리즘을 수정함:

  1. 점집합을 x-좌표의 값(같으면, y좌표의 값) 순으로 정렬한다. 시작점은 hull의 꼭짓점이 된다.
  2. x-좌표 순서대로 현재 점이 hull의 꼭짓점인가를 검사한다: hull의 꼭짓점이 되기 위해서는 직전까지 구성된 hull의 에지 왼편에 있어야 한다. 오른편에 있으면 직전까지 구성된 hull에서 현재 점이 왼편에 놓일 때까지 꼭짓점을 제거한다.
  3. 남는 점들을 1번 과정의 역순으로 정렬한다. 최대 x-좌표, 최소 y-좌표점이 다시 윗 hull의 시작점이 된다.
  4. x-좌표가 작아지는 순서대로 2번 과정을 수행한다.
static 
int ccw(const CPoint& A, const CPoint& B, const CPoint& C) {
    // cross (C-A, B-A) >= 0 이면 AB의 오른쪽에 C가 놓임;
    int cax = C.x - A.x;
    int cay = C.y - A.y;
    int bax = B.x - A.x;
    int bay = B.y - A.y;
    return (cax * bay - cay * bax) >= 0; 
}
// lower-hull은 x-증가: y-감소로 정렬;
static int cmpl(const void *a, const void *b) {
    int v = ((CPoint *)a)->x - ((CPoint *)b)->x;       
    if (v > 0) return  1; 
    if (v < 0) return -1;
    v = ((CPoint *)b)->y - ((CPoint *)a)->y;
    if (v > 0) return 1; 
    if (v < 0) return -1;
    return 0;
}
// upper-hull은 x-감소: y-증가로 정렬;
static int cmph(const void *a, const void *b) {
    return cmpl(b, a);
}
static 
int makeChain(CPoint *V, int n, int (*cmp)(const void*, const void*)) {
    qsort(V, n, sizeof(CPoint), cmp);
    // 점 i (>j))가 현재까지 생성된 hull(s까지)의 에지보다도 더 오른쪽에 있으면, 
    // 왼쪽에 위치할 때까지 기존 hull을 줄이고. (i)를 hull에 추가.
    int s = 1;
    for (int i = 2; i < n; i++) {
        int j = s;
        while(j >= 1 && ccw(V[j-1], V[j], V[i])) j--;
        // ccw의 =때문에 일직선상의 마지막점만 들어감;
        s = j + 1; // j = last index of hull;
        // (j+1)에 새 hull-point을 추가:
        CPoint t = V[i]; V[i] = V[s]; V[s] = t;
    }
    return s;
}
std::vector<CPoint> chainHull2(const std::vector<CPoint>& P) {
    if (P.size() < 3) return std::vector<CPoint> (); //null_vector;
    // copy to working array;
    std::vector<CPoint> chull(P.size()+1);
    for (int i = P.size(); i-->0;) chull[i] = P[i];
    /* make lower hull;*/
    int u = makeChain(&chull[0], P.size(), cmpl);      
    /* make upper hull;*/   
    chull.back()= chull.front();
    u += makeChain(&chull[u], P.size() - u + 1, cmph); 
    chull.resize(u);
    return chull;
}

728x90

'Computational Geometry' 카테고리의 다른 글

Catmull-Rom Spline  (0) 2020.12.07
Incremental Delaunay Triangulation  (1) 2020.12.01
Quick Hull  (2) 2012.09.16
Monotone Cubic Interpolation  (0) 2012.09.09
Brute Force Convex Hull Algorithm  (0) 2012.09.06
Posted by helloktk
,