Computational geometry (1) convex hull

Computational geometry (1) convex hull

Solving the area of ​​a triangle : Helen-Qin Jiushao formula

Judging that a certain point is on the left side of a certain straight line : use the Helen formula above

bool ToLeft(Point p, Point q, Point s)
{
    return Area2(p, q, s) > 0;
}

int Area2(Point p, Point q, Point s)
{
    return 
        p.x * q.y - p.y * q.x 
       +q.x * s.y - q.y * s.x
       +s.x * p.y - s.y *p.x;
}

Judge whether a point is inside the triangle : then the three points are connected in a counterclockwise direction to form a directed edge. If the point is on the left side of the three straight lines, then it is true. (The complexity is O(n^4))

bool InTriangle(Point p, Point q, Point r, Point s)
{
    bool pqLeft = ToLeft(p, q, s);
    bool qrLeft = ToLeft(q, r, s);
    bool rpLeft = ToLeft(r, p, s);
    return (pdLeft == qrLeft) && (qrLeft == rqLeft);
}

Find all poles

1. Draw a straight line along this point, and a straight line must be found, so that all other points are on one side of the line to determine whether it is a pole (complexity is O(n^3))

void markEE(Point S[], int n) //n>2
{
    for(int k = 0; k <n; k ++)
        S[k].extreme = False; //先假设所有的点都不是极点
    for(int p = 0; p < n; p ++)
        for(int q = p + 1; q < n; q ++)
            checkEdge(S, n, p, q);
}

void checkEdge(Point S[], int n, int p, int q)
{
    bool LEmpty = True, REmpty = True;
    for(int k = 0; k < n && (LEmpty || REmpty); k ++)
    {
        if(k != p && k != q)
        {
            ToLeft(S[p], S[q], S[k]) ? LEmpty = False : REmpty = False;
        }
    }
    if(LEmpty || REmpty)
        S[p].extreme = S[q].extreme = True;
}

2. Jarvis algorithm: Here, counterclockwise is defined as the positive direction. The predecessor of a point is the next point in the counterclockwise direction, and the successor is the next point in the clockwise direction. The Javis March algorithm is output sensitive, and its complexity will change with the scale of the convex hull.

void Jarvis(Point S[], int n)
{
    for(int k = 0; k < n; k ++)
        S[k].extreme = false;  //假设所有的点都不是极点
    int ltl = LTL(S, n); int k = ltl;  //先利用LTL算法找到第一个极点,k是起点
    do
    {
        P[k].extreme = true; int s = -1;  //s是要找的下一个极点,用t去循环找
        for(int t = 0; t < n; t ++)
        {
            if(t != k && t != s && (s == -1 || !ToLeft(P[k], P[s], P[t])) 
                s = t; //如果t在pq的右边,更新s
        }
        P[k].succ = s; k = s; //新的极边pq确定
    }while(ltl != k); //如果循环回到了原点,结束
}

int LTL(Point S[], int n)
{
    int ltl = 0;
    for(int k = 1; k < n; k ++)
    {
        if(P[k].y < P[ltl].y || (P[k].y == P[ltl].y && P[k].x < P[ltl].x)
            ltl = k;
    }
    return ltl;
}

Judge whether a certain point is inside the polygon : make a ray for any point v of the x point and the original convex hull, then v has a predecessor and successor, if the predecessor and successor are both on the right or left of the ray, then it is a tangent . If no such tangent is found, then the point is inside the convex hull.

3. Graham Scan algorithm: First, there is a polar edge (LTL), and then the remaining points are sorted from small to large according to the polar angle. There are S stack and T stack. Initially point 1 and point 2 are in the S stack, and the other points are from the top of the T stack to the bottom of the stack. Core code: If the point on the top of the T stack is to the left of the two points on the top and the second on the top of the S stack, then push the point on the top of the T stack into the S stack, otherwise pop out the point on the top of the S stack. All elements in the S stack at the end of the program are all poles.

while(!T.empty())
{
    toLeft(S[1],S[0],T[0]) ? S.push(T.pop()) : S.pop();
}

4. Divided-And-Conquer (Divided-And-Conquer): appropriately group several points, construct sub-convex hulls separately, and then merge them into a convex hull

For the above picture, it is a better situation, because the poles of the two sub-convex hulls are ordered separately from the core, then only two ways are needed to turn these points into overall order, and then Graham Scan is performed.

We just find two cut points, then the ts segment is useless. Then, after discarding ts, perform 2-way merge on the point of the st segment and another sub-convex hull, and then perform Graham Scan.

First, when the two sub-convex hulls are constructed, they can be separated by a vertical line. We only need to find two tangents to merge the two sub-convex hulls. Our actual operation is to first find the rightmost point of the left sub-convex hull, and then find the leftmost point of the right sub-convex hull. The search method here only needs to record their leftmost and rightmost points when constructing the sub-convex hull step by step, then it only takes O(1) time to find it when needed, otherwise it needs to be used O(n) time to find these two points.

Guess you like

Origin blog.csdn.net/a40850273/article/details/90543433